@hyperframes/studio 0.7.99 → 0.7.100

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -32,7 +32,7 @@ import {
32
32
  import { useCallback as useCallback50 } from "react";
33
33
 
34
34
  // src/components/nle/PreviewPane.tsx
35
- import { useCallback as useCallback35, useRef as useRef38, useSyncExternalStore as useSyncExternalStore3 } from "react";
35
+ import { useCallback as useCallback34, useRef as useRef37, useSyncExternalStore as useSyncExternalStore3 } from "react";
36
36
 
37
37
  // src/player/components/Player.tsx
38
38
  import { forwardRef as forwardRef2, useEffect as useEffect3, useRef as useRef2, useState as useState2 } from "react";
@@ -21608,8 +21608,8 @@ import {
21608
21608
  createContext as createContext5,
21609
21609
  useContext as useContext5,
21610
21610
  useState as useState23,
21611
- useCallback as useCallback33,
21612
- useRef as useRef37,
21611
+ useCallback as useCallback32,
21612
+ useRef as useRef36,
21613
21613
  useEffect as useEffect26
21614
21614
  } from "react";
21615
21615
 
@@ -21710,94 +21710,57 @@ function useCompositionStack({
21710
21710
  };
21711
21711
  }
21712
21712
 
21713
- // src/components/nle/TimelineResizeDivider.tsx
21714
- import { useCallback as useCallback32, useRef as useRef36 } from "react";
21715
- import { jsx as jsx49, jsxs as jsxs37 } from "react/jsx-runtime";
21713
+ // src/utils/fitPanels.ts
21714
+ var MIN_PREVIEW_W = 360;
21715
+ var MIN_PREVIEW_H = 200;
21716
+ var MIN_LEFT = 200;
21717
+ var MIN_RIGHT = 280;
21718
+ var RAIL_W = 42;
21716
21719
  var MIN_TIMELINE_H = 100;
21717
- var MIN_PREVIEW_H = 120;
21718
- function TimelineResizeDivider({
21719
- timelineH,
21720
- setTimelineH,
21721
- persistTimelineH,
21722
- containerRef,
21723
- disabled
21724
- }) {
21725
- const isDragging = useRef36(false);
21726
- const timelineHRef = useRef36(timelineH);
21727
- timelineHRef.current = timelineH;
21728
- const handlePointerDown = useCallback32(
21729
- (e) => {
21730
- if (disabled) return;
21731
- e.preventDefault();
21732
- isDragging.current = true;
21733
- e.target.setPointerCapture(e.pointerId);
21734
- },
21735
- [disabled]
21736
- );
21737
- const handlePointerMove = useCallback32(
21738
- (e) => {
21739
- if (disabled) return;
21740
- if (!isDragging.current || !containerRef.current) return;
21741
- const rect = containerRef.current.getBoundingClientRect();
21742
- const mouseY = e.clientY - rect.top;
21743
- const containerH = rect.height;
21744
- const newTimelineH = Math.max(
21745
- MIN_TIMELINE_H,
21746
- Math.min(containerH - MIN_PREVIEW_H, containerH - mouseY)
21747
- );
21748
- setTimelineH(newTimelineH);
21749
- },
21750
- [disabled, containerRef, setTimelineH]
21751
- );
21752
- const handlePointerUp = useCallback32(() => {
21753
- if (isDragging.current) persistTimelineH(timelineHRef.current);
21754
- isDragging.current = false;
21755
- }, [persistTimelineH]);
21756
- const handleKeyDown = useCallback32(
21757
- (e) => {
21758
- if (disabled) return;
21759
- if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
21760
- e.preventDefault();
21761
- const containerH = containerRef.current?.getBoundingClientRect().height ?? Infinity;
21762
- const delta = e.key === "ArrowUp" ? 16 : -16;
21763
- setTimelineH((prev) => {
21764
- const next = Math.max(MIN_TIMELINE_H, Math.min(containerH - MIN_PREVIEW_H, prev + delta));
21765
- persistTimelineH(next);
21766
- return next;
21767
- });
21768
- },
21769
- [disabled, containerRef, setTimelineH, persistTimelineH]
21770
- );
21771
- return (
21772
- // Horizontal resize divider: 3px visible seam (h-[3px]), 10px pointer-capture
21773
- // zone via the absolutely-positioned inner hit area so the layout gap stays
21774
- // at 3px while draggability is preserved over the full band.
21775
- /* @__PURE__ */ jsxs37(
21776
- "div",
21777
- {
21778
- role: "separator",
21779
- "aria-orientation": "horizontal",
21780
- "aria-label": "Resize timeline (arrow keys)",
21781
- "aria-valuenow": Math.round(timelineH),
21782
- "aria-valuemin": MIN_TIMELINE_H,
21783
- "aria-valuemax": Math.round(
21784
- (containerRef.current?.getBoundingClientRect().height ?? 600) - MIN_PREVIEW_H
21785
- ),
21786
- tabIndex: 0,
21787
- className: "group relative h-[3px] flex-shrink-0 cursor-row-resize z-10 outline-none focus-visible:bg-studio-accent/20",
21788
- style: { touchAction: "none" },
21789
- onPointerDown: handlePointerDown,
21790
- onPointerMove: handlePointerMove,
21791
- onPointerUp: handlePointerUp,
21792
- onPointerCancel: handlePointerUp,
21793
- onKeyDown: handleKeyDown,
21794
- children: [
21795
- /* @__PURE__ */ jsx49("div", { className: "absolute inset-x-0 -top-[4px] h-[10px]" }),
21796
- /* @__PURE__ */ jsx49("div", { className: "h-[3px] w-full bg-transparent transition-colors group-hover:bg-white/12 group-active:bg-white/18 group-focus-visible:bg-studio-accent/60" })
21797
- ]
21798
- }
21799
- )
21800
- );
21720
+ var PANEL_SEAM_W = 6;
21721
+ var PANEL_MAX_RATIO = 0.4;
21722
+ var RAIL_LEFT_BELOW = 860;
21723
+ var RAIL_RIGHT_BELOW = 700;
21724
+ function railsEngaged(viewportWidth) {
21725
+ return viewportWidth < RAIL_LEFT_BELOW;
21726
+ }
21727
+ function clamp5(value, min, max) {
21728
+ return Math.max(min, Math.min(max, value));
21729
+ }
21730
+ function defaultPanelWidths(viewportWidth) {
21731
+ return {
21732
+ left: Math.max(MIN_LEFT, Math.min(384, Math.round(viewportWidth * 0.257))),
21733
+ right: Math.max(MIN_RIGHT, Math.min(424, Math.round(viewportWidth * 0.284)))
21734
+ };
21735
+ }
21736
+ function fitPanelWidths(viewportWidth, preferred, reopened = { left: false, right: false }) {
21737
+ const vw = Number.isFinite(viewportWidth) ? Math.max(0, viewportWidth) : 0;
21738
+ if (vw <= 0) {
21739
+ return { ...preferred, preview: 0, autoCollapseLeft: false, autoCollapseRight: false };
21740
+ }
21741
+ const autoCollapseLeft = vw < RAIL_LEFT_BELOW && !reopened.left;
21742
+ const autoCollapseRight = vw < RAIL_RIGHT_BELOW && !reopened.right;
21743
+ const cap = Math.floor(vw * PANEL_MAX_RATIO);
21744
+ const leftFloor = autoCollapseLeft ? RAIL_W : MIN_LEFT;
21745
+ const rightFloor = autoCollapseRight ? 0 : MIN_RIGHT;
21746
+ let left = autoCollapseLeft ? RAIL_W : clamp5(preferred.left, MIN_LEFT, Math.max(MIN_LEFT, cap));
21747
+ let right = autoCollapseRight ? 0 : clamp5(preferred.right, MIN_RIGHT, Math.max(MIN_RIGHT, cap));
21748
+ const budget = vw - MIN_PREVIEW_W - PANEL_SEAM_W;
21749
+ if (left + right > budget) right = Math.max(rightFloor, budget - left);
21750
+ if (left + right > budget) left = Math.max(leftFloor, budget - right);
21751
+ return {
21752
+ left,
21753
+ right,
21754
+ preview: Math.max(0, vw - left - right - PANEL_SEAM_W),
21755
+ autoCollapseLeft,
21756
+ autoCollapseRight
21757
+ };
21758
+ }
21759
+ function fitTimelineHeight(containerHeight, preferred) {
21760
+ const h = Number.isFinite(containerHeight) ? containerHeight : 0;
21761
+ const wanted = Number.isFinite(preferred) ? preferred : MIN_TIMELINE_H;
21762
+ if (h <= 0) return Math.max(MIN_TIMELINE_H, wanted);
21763
+ return clamp5(wanted, MIN_TIMELINE_H, Math.max(MIN_TIMELINE_H, h - MIN_PREVIEW_H));
21801
21764
  }
21802
21765
 
21803
21766
  // src/utils/assetPreviewStore.ts
@@ -21810,7 +21773,7 @@ var useAssetPreviewStore = create4((set) => ({
21810
21773
  }));
21811
21774
 
21812
21775
  // src/components/nle/NLEContext.tsx
21813
- import { jsx as jsx50 } from "react/jsx-runtime";
21776
+ import { jsx as jsx49 } from "react/jsx-runtime";
21814
21777
  var DEFAULT_TIMELINE_H = 360;
21815
21778
  function shouldDisableTimelineWhileCompositionLoading(compositionLoading) {
21816
21779
  return compositionLoading;
@@ -21843,13 +21806,13 @@ function NLEProvider({
21843
21806
  useAssetPreviewStore.getState().clearPreviewAsset();
21844
21807
  }, [projectId]);
21845
21808
  const [previewCompositionSize, setPreviewCompositionSize] = useState23(null);
21846
- const prevRefreshKeyRef = useRef37(refreshKey);
21809
+ const prevRefreshKeyRef = useRef36(refreshKey);
21847
21810
  useEffect26(() => {
21848
21811
  if (refreshKey === prevRefreshKeyRef.current) return;
21849
21812
  prevRefreshKeyRef.current = refreshKey;
21850
21813
  refreshPlayer();
21851
21814
  }, [refreshKey, refreshPlayer]);
21852
- const onIframeLoad = useCallback33(() => {
21815
+ const onIframeLoad = useCallback32(() => {
21853
21816
  baseOnIframeLoad();
21854
21817
  ensureMotionPathPluginLoaded(iframeRef.current);
21855
21818
  onIframeRef?.(iframeRef.current);
@@ -21867,7 +21830,7 @@ function NLEProvider({
21867
21830
  onCompositionChange
21868
21831
  });
21869
21832
  const iframeRef_ = iframeRef;
21870
- const handleDrillDown = useCallback33(
21833
+ const handleDrillDown = useCallback32(
21871
21834
  (element) => {
21872
21835
  if (!element.compositionSrc) return;
21873
21836
  usePlayerStore.getState().setSelectedElementId(null);
@@ -21894,9 +21857,9 @@ function NLEProvider({
21894
21857
  },
21895
21858
  [compIdToSrc, drillDown, iframeRef_]
21896
21859
  );
21897
- const compIdToSrcRef = useRef37(compIdToSrc);
21860
+ const compIdToSrcRef = useRef36(compIdToSrc);
21898
21861
  compIdToSrcRef.current = compIdToSrc;
21899
- const onCompIdToSrcChangeRef = useRef37(onCompIdToSrcChange);
21862
+ const onCompIdToSrcChangeRef = useRef36(onCompIdToSrcChange);
21900
21863
  onCompIdToSrcChangeRef.current = onCompIdToSrcChange;
21901
21864
  useEffect26(() => {
21902
21865
  const controller = new AbortController();
@@ -21967,19 +21930,26 @@ function NLEProvider({
21967
21930
  const stored = readStudioUiPreferences().timelineHeight;
21968
21931
  return stored !== void 0 && stored >= MIN_TIMELINE_H ? stored : DEFAULT_TIMELINE_H;
21969
21932
  });
21970
- const persistTimelineH = useCallback33((height) => {
21933
+ const persistTimelineH = useCallback32((height) => {
21971
21934
  writeStudioUiPreferences({ timelineHeight: Math.round(height) });
21972
21935
  }, []);
21973
- const containerRef = useRef37(null);
21936
+ const containerRef = useRef36(null);
21974
21937
  useEffect26(() => {
21975
- const containerH = containerRef.current?.getBoundingClientRect().height;
21976
- if (!containerH) return;
21977
- const max = containerH - MIN_PREVIEW_H;
21978
- setTimelineH((prev) => prev > max ? Math.max(MIN_TIMELINE_H, max) : prev);
21938
+ const element = containerRef.current;
21939
+ if (!element || typeof ResizeObserver === "undefined") return;
21940
+ const reconcile = () => {
21941
+ const containerH = element.getBoundingClientRect().height;
21942
+ if (!containerH) return;
21943
+ setTimelineH((prev) => fitTimelineHeight(containerH, prev));
21944
+ };
21945
+ reconcile();
21946
+ const observer = new ResizeObserver(reconcile);
21947
+ observer.observe(element);
21948
+ return () => observer.disconnect();
21979
21949
  }, []);
21980
- const hasLoadedOnceRef = useRef37(false);
21950
+ const hasLoadedOnceRef = useRef36(false);
21981
21951
  const [compositionLoading, setCompositionLoadingRaw] = useState23(true);
21982
- const setCompositionLoading = useCallback33((loading) => {
21952
+ const setCompositionLoading = useCallback32((loading) => {
21983
21953
  if (!loading) hasLoadedOnceRef.current = true;
21984
21954
  if (loading && hasLoadedOnceRef.current) return;
21985
21955
  setCompositionLoadingRaw(loading);
@@ -21989,7 +21959,7 @@ function NLEProvider({
21989
21959
  useEffect26(() => {
21990
21960
  onCompositionLoadingChange?.(compositionLoading);
21991
21961
  }, [compositionLoading, onCompositionLoadingChange]);
21992
- const onIframeRefStable = useRef37(onIframeRef);
21962
+ const onIframeRefStable = useRef36(onIframeRef);
21993
21963
  onIframeRefStable.current = onIframeRef;
21994
21964
  useEffect26(() => {
21995
21965
  onIframeRefStable.current?.(iframeRef.current);
@@ -22018,11 +21988,11 @@ function NLEProvider({
22018
21988
  previewCompositionSize,
22019
21989
  setPreviewCompositionSize
22020
21990
  };
22021
- return /* @__PURE__ */ jsx50(NLEContext.Provider, { value, children });
21991
+ return /* @__PURE__ */ jsx49(NLEContext.Provider, { value, children });
22022
21992
  }
22023
21993
 
22024
21994
  // src/components/nle/AssetPreviewOverlay.tsx
22025
- import { useEffect as useEffect27, useCallback as useCallback34 } from "react";
21995
+ import { useEffect as useEffect27, useCallback as useCallback33 } from "react";
22026
21996
 
22027
21997
  // src/utils/assetPreviewDismiss.ts
22028
21998
  var TIME_EPSILON_S = 1e-6;
@@ -22033,7 +22003,7 @@ function shouldDismissAssetPreview(openedTime, snapshot) {
22033
22003
  }
22034
22004
 
22035
22005
  // src/components/nle/AssetPreviewOverlay.tsx
22036
- import { jsx as jsx51, jsxs as jsxs38 } from "react/jsx-runtime";
22006
+ import { jsx as jsx50, jsxs as jsxs37 } from "react/jsx-runtime";
22037
22007
  function basename(path) {
22038
22008
  return path.split("/").pop() ?? path;
22039
22009
  }
@@ -22048,10 +22018,10 @@ function AssetPreviewMedia({
22048
22018
  name
22049
22019
  }) {
22050
22020
  if (kind === "image") {
22051
- return /* @__PURE__ */ jsx51("img", { src: serveUrl, alt: name, className: "max-w-full max-h-[40vh] rounded object-contain" });
22021
+ return /* @__PURE__ */ jsx50("img", { src: serveUrl, alt: name, className: "max-w-full max-h-[40vh] rounded object-contain" });
22052
22022
  }
22053
22023
  if (kind === "video") {
22054
- return /* @__PURE__ */ jsx51(
22024
+ return /* @__PURE__ */ jsx50(
22055
22025
  "video",
22056
22026
  {
22057
22027
  src: serveUrl,
@@ -22063,8 +22033,8 @@ function AssetPreviewMedia({
22063
22033
  }
22064
22034
  );
22065
22035
  }
22066
- return /* @__PURE__ */ jsxs38("div", { className: "flex flex-col items-center gap-3 px-6 py-4", children: [
22067
- /* @__PURE__ */ jsxs38(
22036
+ return /* @__PURE__ */ jsxs37("div", { className: "flex flex-col items-center gap-3 px-6 py-4", children: [
22037
+ /* @__PURE__ */ jsxs37(
22068
22038
  "svg",
22069
22039
  {
22070
22040
  width: "40",
@@ -22075,20 +22045,20 @@ function AssetPreviewMedia({
22075
22045
  strokeWidth: "1.5",
22076
22046
  className: "text-neutral-500",
22077
22047
  children: [
22078
- /* @__PURE__ */ jsx51("path", { d: "M9 18V5l12-2v13", strokeLinecap: "round", strokeLinejoin: "round" }),
22079
- /* @__PURE__ */ jsx51("circle", { cx: "6", cy: "18", r: "3" }),
22080
- /* @__PURE__ */ jsx51("circle", { cx: "18", cy: "16", r: "3" })
22048
+ /* @__PURE__ */ jsx50("path", { d: "M9 18V5l12-2v13", strokeLinecap: "round", strokeLinejoin: "round" }),
22049
+ /* @__PURE__ */ jsx50("circle", { cx: "6", cy: "18", r: "3" }),
22050
+ /* @__PURE__ */ jsx50("circle", { cx: "18", cy: "16", r: "3" })
22081
22051
  ]
22082
22052
  }
22083
22053
  ),
22084
- /* @__PURE__ */ jsx51("audio", { src: serveUrl, controls: true, className: "w-64" })
22054
+ /* @__PURE__ */ jsx50("audio", { src: serveUrl, controls: true, className: "w-64" })
22085
22055
  ] });
22086
22056
  }
22087
22057
  function AssetPreviewOverlay() {
22088
22058
  const previewAsset = useAssetPreviewStore((s) => s.previewAsset);
22089
22059
  const previewProjectId = useAssetPreviewStore((s) => s.previewProjectId);
22090
22060
  const clearPreviewAsset = useAssetPreviewStore((s) => s.clearPreviewAsset);
22091
- const handleKeyDown = useCallback34(
22061
+ const handleKeyDown = useCallback33(
22092
22062
  (e) => {
22093
22063
  if (e.key === "Escape") clearPreviewAsset();
22094
22064
  },
@@ -22114,20 +22084,20 @@ function AssetPreviewOverlay() {
22114
22084
  if (!previewAsset || !previewProjectId) return null;
22115
22085
  const serveUrl = resolveMediaPreviewUrl(previewAsset, previewProjectId);
22116
22086
  const name = basename(previewAsset);
22117
- return /* @__PURE__ */ jsx51(
22087
+ return /* @__PURE__ */ jsx50(
22118
22088
  "div",
22119
22089
  {
22120
22090
  className: "absolute inset-0 z-50 flex flex-col items-center justify-center bg-black/20",
22121
22091
  onClick: clearPreviewAsset,
22122
22092
  role: "dialog",
22123
22093
  "aria-label": `Preview: ${name}`,
22124
- children: /* @__PURE__ */ jsxs38(
22094
+ children: /* @__PURE__ */ jsxs37(
22125
22095
  "div",
22126
22096
  {
22127
22097
  className: "relative flex flex-col items-center gap-2 max-w-[58%] rounded-lg border border-neutral-800 bg-neutral-950/95 p-2 pt-8 shadow-2xl",
22128
22098
  onClick: (e) => e.stopPropagation(),
22129
22099
  children: [
22130
- /* @__PURE__ */ jsx51(
22100
+ /* @__PURE__ */ jsx50(
22131
22101
  "button",
22132
22102
  {
22133
22103
  className: "absolute top-2 right-2 w-6 h-6 rounded-full bg-neutral-800 hover:bg-neutral-700 text-neutral-300 hover:text-white flex items-center justify-center transition-colors z-10",
@@ -22136,7 +22106,7 @@ function AssetPreviewOverlay() {
22136
22106
  clearPreviewAsset();
22137
22107
  },
22138
22108
  "aria-label": "Close preview",
22139
- children: /* @__PURE__ */ jsxs38(
22109
+ children: /* @__PURE__ */ jsxs37(
22140
22110
  "svg",
22141
22111
  {
22142
22112
  width: "12",
@@ -22147,15 +22117,15 @@ function AssetPreviewOverlay() {
22147
22117
  fill: "none",
22148
22118
  strokeLinecap: "round",
22149
22119
  children: [
22150
- /* @__PURE__ */ jsx51("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
22151
- /* @__PURE__ */ jsx51("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
22120
+ /* @__PURE__ */ jsx50("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
22121
+ /* @__PURE__ */ jsx50("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
22152
22122
  ]
22153
22123
  }
22154
22124
  )
22155
22125
  }
22156
22126
  ),
22157
- /* @__PURE__ */ jsx51(AssetPreviewMedia, { kind: resolveAssetKind(previewAsset), serveUrl, name }),
22158
- /* @__PURE__ */ jsx51("span", { className: "text-[12px] text-neutral-400 truncate max-w-full px-2 text-center", children: name })
22127
+ /* @__PURE__ */ jsx50(AssetPreviewMedia, { kind: resolveAssetKind(previewAsset), serveUrl, name }),
22128
+ /* @__PURE__ */ jsx50("span", { className: "text-[12px] text-neutral-400 truncate max-w-full px-2 text-center", children: name })
22159
22129
  ]
22160
22130
  }
22161
22131
  )
@@ -22164,7 +22134,7 @@ function AssetPreviewOverlay() {
22164
22134
  }
22165
22135
 
22166
22136
  // src/components/nle/PreviewPane.tsx
22167
- import { jsx as jsx52, jsxs as jsxs39 } from "react/jsx-runtime";
22137
+ import { jsx as jsx51, jsxs as jsxs38 } from "react/jsx-runtime";
22168
22138
  function subscribeFullscreen(cb) {
22169
22139
  document.addEventListener("fullscreenchange", cb);
22170
22140
  return () => document.removeEventListener("fullscreenchange", cb);
@@ -22199,8 +22169,8 @@ function PreviewPane({
22199
22169
  previewCompositionSize,
22200
22170
  setPreviewCompositionSize
22201
22171
  } = useNLEContext();
22202
- const stageRefForDrop = useRef38(null);
22203
- const handleStageRef = useCallback35((ref) => {
22172
+ const stageRefForDrop = useRef37(null);
22173
+ const handleStageRef = useCallback34((ref) => {
22204
22174
  stageRefForDrop.current = ref.current;
22205
22175
  }, []);
22206
22176
  const {
@@ -22215,10 +22185,10 @@ function PreviewPane({
22215
22185
  stageRef: stageRefForDrop,
22216
22186
  onBlockDrop: onPreviewBlockDrop
22217
22187
  });
22218
- const containerRef = useRef38(null);
22188
+ const containerRef = useRef37(null);
22219
22189
  const fullscreenElement = useSyncExternalStore3(subscribeFullscreen, getFullscreenElement);
22220
22190
  const isFullscreen = fullscreenElement === containerRef.current && fullscreenElement != null;
22221
- const toggleFullscreen = useCallback35(() => {
22191
+ const toggleFullscreen = useCallback34(() => {
22222
22192
  if (!containerRef.current) return;
22223
22193
  if (document.fullscreenElement) {
22224
22194
  void document.exitFullscreen();
@@ -22228,14 +22198,14 @@ function PreviewPane({
22228
22198
  }, []);
22229
22199
  const currentLevel = compositionStack[compositionStack.length - 1];
22230
22200
  const directUrl = compositionStack.length > 1 ? currentLevel.previewUrl : void 0;
22231
- return /* @__PURE__ */ jsxs39(
22201
+ return /* @__PURE__ */ jsxs38(
22232
22202
  "div",
22233
22203
  {
22234
22204
  ref: containerRef,
22235
22205
  className: `flex-1 min-h-0 flex flex-col overflow-hidden bg-neutral-950 ${isFullscreen ? "" : "rounded-lg border border-neutral-800/50"}`,
22236
22206
  "data-studio-fullscreen-target": "",
22237
22207
  children: [
22238
- /* @__PURE__ */ jsxs39(
22208
+ /* @__PURE__ */ jsxs38(
22239
22209
  "div",
22240
22210
  {
22241
22211
  className: "flex-1 min-h-0 relative overflow-hidden",
@@ -22246,8 +22216,8 @@ function PreviewPane({
22246
22216
  onDragLeave: handlePreviewDragLeave,
22247
22217
  onDrop: handlePreviewDrop,
22248
22218
  children: [
22249
- /* @__PURE__ */ jsxs39("div", { className: "absolute inset-0 overflow-hidden", children: [
22250
- /* @__PURE__ */ jsx52(
22219
+ /* @__PURE__ */ jsxs38("div", { className: "absolute inset-0 overflow-hidden", children: [
22220
+ /* @__PURE__ */ jsx51(
22251
22221
  NLEPreview,
22252
22222
  {
22253
22223
  projectId,
@@ -22261,16 +22231,16 @@ function PreviewPane({
22261
22231
  onCompositionSizeChange: setPreviewCompositionSize
22262
22232
  }
22263
22233
  ),
22264
- previewDragOver && /* @__PURE__ */ jsx52("div", { className: "absolute inset-2 z-40 rounded-lg border-2 border-dashed border-studio-accent/50 bg-studio-accent/[0.04] pointer-events-none" }),
22265
- /* @__PURE__ */ jsx52(AssetPreviewOverlay, {})
22234
+ previewDragOver && /* @__PURE__ */ jsx51("div", { className: "absolute inset-2 z-40 rounded-lg border-2 border-dashed border-studio-accent/50 bg-studio-accent/[0.04] pointer-events-none" }),
22235
+ /* @__PURE__ */ jsx51(AssetPreviewOverlay, {})
22266
22236
  ] }),
22267
22237
  !isFullscreen && previewOverlay
22268
22238
  ]
22269
22239
  }
22270
22240
  ),
22271
- /* @__PURE__ */ jsxs39("div", { className: "flex-shrink-0", children: [
22272
- !isFullscreen && compositionStack.length > 1 && /* @__PURE__ */ jsx52(CompositionBreadcrumb, { stack: compositionStack, onNavigate: handleNavigateComposition }),
22273
- /* @__PURE__ */ jsx52(
22241
+ /* @__PURE__ */ jsxs38("div", { className: "flex-shrink-0", children: [
22242
+ !isFullscreen && compositionStack.length > 1 && /* @__PURE__ */ jsx51(CompositionBreadcrumb, { stack: compositionStack, onNavigate: handleNavigateComposition }),
22243
+ /* @__PURE__ */ jsx51(
22274
22244
  PlayerControls,
22275
22245
  {
22276
22246
  onTogglePlay: togglePlay,
@@ -22288,6 +22258,91 @@ function PreviewPane({
22288
22258
 
22289
22259
  // src/components/nle/TimelinePane.tsx
22290
22260
  import { useCallback as useCallback36 } from "react";
22261
+
22262
+ // src/components/nle/TimelineResizeDivider.tsx
22263
+ import { useCallback as useCallback35, useRef as useRef38 } from "react";
22264
+ import { jsx as jsx52, jsxs as jsxs39 } from "react/jsx-runtime";
22265
+ function TimelineResizeDivider({
22266
+ timelineH,
22267
+ setTimelineH,
22268
+ persistTimelineH,
22269
+ containerRef,
22270
+ disabled
22271
+ }) {
22272
+ const isDragging = useRef38(false);
22273
+ const timelineHRef = useRef38(timelineH);
22274
+ timelineHRef.current = timelineH;
22275
+ const handlePointerDown = useCallback35(
22276
+ (e) => {
22277
+ if (disabled) return;
22278
+ e.preventDefault();
22279
+ isDragging.current = true;
22280
+ e.target.setPointerCapture(e.pointerId);
22281
+ },
22282
+ [disabled]
22283
+ );
22284
+ const handlePointerMove = useCallback35(
22285
+ (e) => {
22286
+ if (disabled) return;
22287
+ if (!isDragging.current || !containerRef.current) return;
22288
+ const rect = containerRef.current.getBoundingClientRect();
22289
+ const mouseY = e.clientY - rect.top;
22290
+ setTimelineH(fitTimelineHeight(rect.height, rect.height - mouseY));
22291
+ },
22292
+ [disabled, containerRef, setTimelineH]
22293
+ );
22294
+ const handlePointerUp = useCallback35(() => {
22295
+ if (isDragging.current) persistTimelineH(timelineHRef.current);
22296
+ isDragging.current = false;
22297
+ }, [persistTimelineH]);
22298
+ const handleKeyDown = useCallback35(
22299
+ (e) => {
22300
+ if (disabled) return;
22301
+ if (e.key !== "ArrowUp" && e.key !== "ArrowDown") return;
22302
+ e.preventDefault();
22303
+ const containerH = containerRef.current?.getBoundingClientRect().height ?? 0;
22304
+ const delta = e.key === "ArrowUp" ? 16 : -16;
22305
+ setTimelineH((prev) => {
22306
+ const next = fitTimelineHeight(containerH, prev + delta);
22307
+ persistTimelineH(next);
22308
+ return next;
22309
+ });
22310
+ },
22311
+ [disabled, containerRef, setTimelineH, persistTimelineH]
22312
+ );
22313
+ return (
22314
+ // Horizontal resize divider: 3px visible seam (h-[3px]), 10px pointer-capture
22315
+ // zone via the absolutely-positioned inner hit area so the layout gap stays
22316
+ // at 3px while draggability is preserved over the full band.
22317
+ /* @__PURE__ */ jsxs39(
22318
+ "div",
22319
+ {
22320
+ role: "separator",
22321
+ "aria-orientation": "horizontal",
22322
+ "aria-label": "Resize timeline (arrow keys)",
22323
+ "aria-valuenow": Math.round(timelineH),
22324
+ "aria-valuemin": MIN_TIMELINE_H,
22325
+ "aria-valuemax": Math.round(
22326
+ (containerRef.current?.getBoundingClientRect().height ?? 600) - MIN_PREVIEW_H
22327
+ ),
22328
+ tabIndex: 0,
22329
+ className: "group relative h-[3px] flex-shrink-0 cursor-row-resize z-10 outline-none focus-visible:bg-studio-accent/20",
22330
+ style: { touchAction: "none" },
22331
+ onPointerDown: handlePointerDown,
22332
+ onPointerMove: handlePointerMove,
22333
+ onPointerUp: handlePointerUp,
22334
+ onPointerCancel: handlePointerUp,
22335
+ onKeyDown: handleKeyDown,
22336
+ children: [
22337
+ /* @__PURE__ */ jsx52("div", { className: "absolute inset-x-0 -top-[4px] h-[10px]" }),
22338
+ /* @__PURE__ */ jsx52("div", { className: "h-[3px] w-full bg-transparent transition-colors group-hover:bg-white/12 group-active:bg-white/18 group-focus-visible:bg-studio-accent/60" })
22339
+ ]
22340
+ }
22341
+ )
22342
+ );
22343
+ }
22344
+
22345
+ // src/components/nle/TimelinePane.tsx
22291
22346
  import { Fragment as Fragment15, jsx as jsx53, jsxs as jsxs40 } from "react/jsx-runtime";
22292
22347
  function forwardRebasedTimelineMoveElements(edits, coalesceKey, operation, onMoveElements, coalesceMs) {
22293
22348
  return onMoveElements(
@@ -33554,7 +33609,7 @@ var NOOP_EPSILON_PCT2 = 0.1;
33554
33609
  var EPSILON_TIME = 1e-4;
33555
33610
  var MIN_TWEEN_DURATION = 0.01;
33556
33611
  var round33 = (n) => Math.round(n * 1e3) / 1e3;
33557
- var clamp5 = (n, lo, hi) => Math.max(lo, Math.min(hi, n));
33612
+ var clamp6 = (n, lo, hi) => Math.max(lo, Math.min(hi, n));
33558
33613
  function resolveFlatTweenBoundaryRetime(opts) {
33559
33614
  const { keyframeCount, draggedTweenPct, tweenStart, tweenEnd, dropAbsTime } = opts;
33560
33615
  if (keyframeCount > 0) return null;
@@ -33585,7 +33640,7 @@ function resolveKeyframeRetime(opts) {
33585
33640
  });
33586
33641
  if (flatBoundary) return flatBoundary;
33587
33642
  if (dropAbsTime >= tweenStart - EPSILON_TIME && dropAbsTime <= tweenEnd + EPSILON_TIME) {
33588
- const toTweenPct = round33(clamp5((dropAbsTime - tweenStart) / tweenDuration * 100, 0, 100));
33643
+ const toTweenPct = round33(clamp6((dropAbsTime - tweenStart) / tweenDuration * 100, 0, 100));
33589
33644
  if (Math.abs(toTweenPct - draggedTweenPct) < NOOP_EPSILON_PCT2) return { kind: "noop" };
33590
33645
  return { kind: "move", toTweenPct };
33591
33646
  }
@@ -39622,7 +39677,7 @@ function hasCssWord(value, word) {
39622
39677
  function parsePercentToken(value, fallback) {
39623
39678
  if (!value?.endsWith("%")) return fallback;
39624
39679
  const parsed = parseCssNumber(value.slice(0, -1));
39625
- return parsed == null ? fallback : clamp6(parsed, 0, 100);
39680
+ return parsed == null ? fallback : clamp7(parsed, 0, 100);
39626
39681
  }
39627
39682
  function parseAngleToken(value) {
39628
39683
  const trimmed = value?.trim().toLowerCase();
@@ -39644,13 +39699,13 @@ function trailingPercentStart(value) {
39644
39699
  if (start === 0 || !isWhitespace(withoutUnit[start - 1])) return null;
39645
39700
  return start;
39646
39701
  }
39647
- function clamp6(value, min, max) {
39702
+ function clamp7(value, min, max) {
39648
39703
  return Math.min(max, Math.max(min, value));
39649
39704
  }
39650
39705
  var round = roundToCenti;
39651
39706
  function parsePercent(value, fallback) {
39652
39707
  const parsed = parseCssNumber(value);
39653
- return parsed == null ? fallback : clamp6(parsed, 0, 100);
39708
+ return parsed == null ? fallback : clamp7(parsed, 0, 100);
39654
39709
  }
39655
39710
  function parseColorStop(raw) {
39656
39711
  const trimmed = raw.trim();
@@ -39681,7 +39736,7 @@ function normalizeStops(stops) {
39681
39736
  }));
39682
39737
  return result.map((stop) => ({
39683
39738
  color: stop.color,
39684
- position: round(clamp6(stop.position, 0, 100))
39739
+ position: round(clamp7(stop.position, 0, 100))
39685
39740
  }));
39686
39741
  }
39687
39742
  function splitGradientArgs(value) {
@@ -39844,7 +39899,7 @@ function formatHex(channel) {
39844
39899
  return channel.toString(16).padStart(2, "0");
39845
39900
  }
39846
39901
  function interpolateGradientStopColor(model, position) {
39847
- const clampedPosition = clamp6(position, 0, 100);
39902
+ const clampedPosition = clamp7(position, 0, 100);
39848
39903
  const sortedStops = [...model.stops].sort((a, b) => a.position - b.position);
39849
39904
  const exact = sortedStops.find((stop) => Math.abs(stop.position - clampedPosition) < 1e-3);
39850
39905
  if (exact) return exact.color;
@@ -39868,7 +39923,7 @@ function interpolateGradientStopColor(model, position) {
39868
39923
  return `rgba(${red}, ${green}, ${blue}, ${alpha})`;
39869
39924
  }
39870
39925
  function insertGradientStop(model, position) {
39871
- const clampedPosition = round(clamp6(position, 0, 100));
39926
+ const clampedPosition = round(clamp7(position, 0, 100));
39872
39927
  const color = interpolateGradientStopColor(model, clampedPosition);
39873
39928
  const nextStops = [...model.stops, { color, position: clampedPosition }].sort(
39874
39929
  (a, b) => a.position - b.position
@@ -50734,7 +50789,7 @@ var FileTree = memo33(function FileTree2({
50734
50789
  });
50735
50790
 
50736
50791
  // src/App.tsx
50737
- import { useState as useState133, useCallback as useCallback152, useRef as useRef142, useMemo as useMemo66, useEffect as useEffect121, useLayoutEffect as useLayoutEffect9 } from "react";
50792
+ import { useState as useState133, useCallback as useCallback152, useRef as useRef142, useMemo as useMemo66, useEffect as useEffect122, useLayoutEffect as useLayoutEffect9 } from "react";
50738
50793
 
50739
50794
  // src/components/renders/useRenderQueue.ts
50740
50795
  import { useState as useState77, useEffect as useEffect71, useCallback as useCallback65, useRef as useRef83, useMemo as useMemo46 } from "react";
@@ -52315,33 +52370,26 @@ function usePersistentEditHistory(options) {
52315
52370
  }
52316
52371
 
52317
52372
  // src/hooks/usePanelLayout.ts
52318
- import { useState as useState82, useCallback as useCallback69, useRef as useRef90 } from "react";
52373
+ import { useState as useState82, useCallback as useCallback69, useRef as useRef90, useEffect as useEffect74 } from "react";
52374
+ var NO_OVERRIDE = { left: false, right: false };
52319
52375
  function getInitialRightInspectorPanes(tab) {
52320
52376
  if (tab === "layers") return { layers: true, design: false };
52321
52377
  return { layers: false, design: true };
52322
52378
  }
52323
- function getInitialPanelWidths() {
52324
- const viewportWidth = typeof window === "undefined" ? 1496 : window.innerWidth;
52379
+ function readViewportWidth() {
52380
+ return typeof window === "undefined" ? 1496 : window.innerWidth;
52381
+ }
52382
+ function getPreferredPanelWidths() {
52325
52383
  const preferences = readStudioUiPreferences();
52326
- const leftDefault = Math.max(240, Math.min(384, Math.round(viewportWidth * 0.257)));
52327
- const rightDefault = Math.max(320, Math.min(424, Math.round(viewportWidth * 0.284)));
52384
+ const defaults = defaultPanelWidths(readViewportWidth());
52328
52385
  return {
52329
- left: Math.max(
52330
- 160,
52331
- Math.min(Math.floor(viewportWidth * 0.5), preferences.leftWidth ?? leftDefault)
52332
- ),
52333
- right: Math.max(160, Math.min(600, preferences.rightWidth ?? rightDefault))
52386
+ left: preferences.leftWidth ?? defaults.left,
52387
+ right: preferences.rightWidth ?? defaults.right
52334
52388
  };
52335
52389
  }
52336
- function clampPanelWidth(side, width) {
52337
- const max = side === "left" ? Math.floor(window.innerWidth * 0.5) : 600;
52338
- return Math.max(160, Math.min(max, width));
52339
- }
52340
52390
  function usePanelLayout(initialState2) {
52341
- const [initialPanelWidths] = useState82(getInitialPanelWidths);
52342
- const [leftWidth, setLeftWidth] = useState82(initialPanelWidths.left);
52343
- const [rightWidth, setRightWidth] = useState82(initialPanelWidths.right);
52344
- const panelWidthsRef = useRef90(initialPanelWidths);
52391
+ const [preferredWidths, setPreferredWidths] = useState82(getPreferredPanelWidths);
52392
+ const [viewportWidth, setViewportWidth] = useState82(readViewportWidth);
52345
52393
  const [leftCollapsed, setLeftCollapsed] = useState82(
52346
52394
  () => readStudioUiPreferences().leftCollapsed ?? false
52347
52395
  );
@@ -52352,33 +52400,65 @@ function usePanelLayout(initialState2) {
52352
52400
  const [rightInspectorPanes, setRightInspectorPanes] = useState82(
52353
52401
  () => getInitialRightInspectorPanes(initialState2?.rightPanelTab)
52354
52402
  );
52403
+ const [autoCollapseOverride, setAutoCollapseOverride] = useState82(NO_OVERRIDE);
52404
+ useEffect74(() => {
52405
+ if (typeof window === "undefined") return;
52406
+ const handleResize = () => {
52407
+ const width = window.innerWidth;
52408
+ setViewportWidth(width);
52409
+ if (!railsEngaged(width)) {
52410
+ setAutoCollapseOverride((prev) => prev.left || prev.right ? NO_OVERRIDE : prev);
52411
+ }
52412
+ };
52413
+ window.addEventListener("resize", handleResize);
52414
+ return () => window.removeEventListener("resize", handleResize);
52415
+ }, []);
52416
+ const fitted = fitPanelWidths(viewportWidth, preferredWidths, autoCollapseOverride);
52417
+ const leftCollapsedByWidth = fitted.autoCollapseLeft;
52418
+ const rightCollapsedByWidth = fitted.autoCollapseRight;
52419
+ const fittedRef = useRef90(fitted);
52420
+ fittedRef.current = fitted;
52355
52421
  const panelDragRef = useRef90(null);
52356
- const updatePanelWidth = useCallback69((side, width) => {
52357
- const next = clampPanelWidth(side, width);
52358
- panelWidthsRef.current[side] = next;
52359
- if (side === "left") setLeftWidth(next);
52360
- else setRightWidth(next);
52422
+ const preferredRef = useRef90(preferredWidths);
52423
+ const setPreferred = useCallback69((side, width) => {
52424
+ const next = Math.max(0, Math.round(width));
52425
+ preferredRef.current = { ...preferredRef.current, [side]: next };
52426
+ setPreferredWidths(preferredRef.current);
52361
52427
  return next;
52362
52428
  }, []);
52429
+ const updatePanelWidth = useCallback69(
52430
+ (side, width) => {
52431
+ setPreferred(side, width);
52432
+ },
52433
+ [setPreferred]
52434
+ );
52363
52435
  const commitPanelWidth = useCallback69(
52364
52436
  (side, width) => {
52365
- const next = updatePanelWidth(side, Math.round(width));
52366
- writeStudioUiPreferences(side === "left" ? { leftWidth: next } : { rightWidth: next });
52437
+ const candidate = { ...preferredRef.current, [side]: Math.max(0, Math.round(width)) };
52438
+ const settled = fitPanelWidths(readViewportWidth(), candidate)[side];
52439
+ setPreferred(side, settled);
52440
+ writeStudioUiPreferences(side === "left" ? { leftWidth: settled } : { rightWidth: settled });
52367
52441
  },
52368
- [updatePanelWidth]
52442
+ [setPreferred]
52369
52443
  );
52370
52444
  const adjustPanelWidth = useCallback69(
52371
52445
  (side, delta) => {
52372
- commitPanelWidth(side, panelWidthsRef.current[side] + delta);
52446
+ commitPanelWidth(side, preferredRef.current[side] + delta);
52373
52447
  },
52374
52448
  [commitPanelWidth]
52375
52449
  );
52450
+ const effectiveLeftCollapsedRef = useRef90(false);
52451
+ effectiveLeftCollapsedRef.current = leftCollapsed || leftCollapsedByWidth;
52376
52452
  const toggleLeftSidebar = useCallback69(() => {
52377
- setLeftCollapsed((collapsed) => {
52378
- writeStudioUiPreferences({ leftCollapsed: !collapsed });
52379
- trackStudioEvent("panel_toggle", { panel: "left_sidebar", collapsed: !collapsed });
52380
- return !collapsed;
52381
- });
52453
+ const next = !effectiveLeftCollapsedRef.current;
52454
+ setLeftCollapsed(next);
52455
+ writeStudioUiPreferences({ leftCollapsed: next });
52456
+ trackStudioEvent("panel_toggle", { panel: "left_sidebar", collapsed: next });
52457
+ if (!next) setAutoCollapseOverride((prev) => ({ ...prev, left: true }));
52458
+ }, []);
52459
+ const setRightCollapsedWithOverride = useCallback69((collapsed) => {
52460
+ setRightCollapsed(collapsed);
52461
+ if (!collapsed) setAutoCollapseOverride((prev) => ({ ...prev, right: true }));
52382
52462
  }, []);
52383
52463
  const handlePanelResizeStart = useCallback69((side, e) => {
52384
52464
  e.preventDefault();
@@ -52386,7 +52466,7 @@ function usePanelLayout(initialState2) {
52386
52466
  panelDragRef.current = {
52387
52467
  side,
52388
52468
  startX: e.clientX,
52389
- startW: panelWidthsRef.current[side]
52469
+ startW: fittedRef.current[side]
52390
52470
  };
52391
52471
  }, []);
52392
52472
  const handlePanelResizeMove = useCallback69(
@@ -52400,7 +52480,7 @@ function usePanelLayout(initialState2) {
52400
52480
  );
52401
52481
  const handlePanelResizeEnd = useCallback69(() => {
52402
52482
  const side = panelDragRef.current?.side;
52403
- if (side) commitPanelWidth(side, panelWidthsRef.current[side]);
52483
+ if (side) commitPanelWidth(side, preferredRef.current[side]);
52404
52484
  panelDragRef.current = null;
52405
52485
  }, [commitPanelWidth]);
52406
52486
  const trackedSetRightPanelTab = useCallback69(
@@ -52426,13 +52506,22 @@ function usePanelLayout(initialState2) {
52426
52506
  setRightInspectorPanes({ design: pane === "design", layers: pane === "layers" });
52427
52507
  }, []);
52428
52508
  return {
52429
- leftWidth,
52430
- rightWidth,
52509
+ leftWidth: fitted.left,
52510
+ rightWidth: fitted.right,
52431
52511
  adjustPanelWidth,
52512
+ /**
52513
+ * User intent. Persisted to localStorage; never written by auto-collapse.
52514
+ * Deliberately read-only outside this hook: `toggleLeftSidebar` is the only
52515
+ * writer, so it cannot be flipped without also clearing the rail override
52516
+ * (which would open the sidebar and then immediately rail it again).
52517
+ */
52432
52518
  leftCollapsed,
52433
- setLeftCollapsed,
52519
+ /** User intent. Synced into the shareable URL; never written by auto-collapse. */
52434
52520
  rightCollapsed,
52435
- setRightCollapsed,
52521
+ setRightCollapsed: setRightCollapsedWithOverride,
52522
+ /** What the shell actually renders: intent OR the window forcing a rail. */
52523
+ effectiveLeftCollapsed: leftCollapsed || leftCollapsedByWidth,
52524
+ effectiveRightCollapsed: rightCollapsed || rightCollapsedByWidth,
52436
52525
  rightPanelTab,
52437
52526
  setRightPanelTab: trackedSetRightPanelTab,
52438
52527
  rightInspectorPanes,
@@ -52483,13 +52572,13 @@ function createStudioWriteToken() {
52483
52572
  }
52484
52573
 
52485
52574
  // src/hooks/useFileTree.ts
52486
- import { useState as useState83, useCallback as useCallback70, useEffect as useEffect74, useMemo as useMemo48 } from "react";
52575
+ import { useState as useState83, useCallback as useCallback70, useEffect as useEffect75, useMemo as useMemo48 } from "react";
52487
52576
  function useFileTree({ projectId, projectIdRef }) {
52488
52577
  const [projectDir, setProjectDir] = useState83(null);
52489
52578
  const [fileTree, setFileTree] = useState83([]);
52490
52579
  const [compositionPaths, setCompositionPaths] = useState83([]);
52491
52580
  const [fileTreeLoaded, setFileTreeLoaded] = useState83(false);
52492
- useEffect74(() => {
52581
+ useEffect75(() => {
52493
52582
  if (!projectId) {
52494
52583
  setFileTreeLoaded(false);
52495
52584
  return;
@@ -53476,7 +53565,7 @@ function usePreviewPersistence({
53476
53565
  }
53477
53566
 
53478
53567
  // src/hooks/usePreviewDocumentVersion.ts
53479
- import { useCallback as useCallback74, useEffect as useEffect75, useRef as useRef94, useState as useState86 } from "react";
53568
+ import { useCallback as useCallback74, useEffect as useEffect76, useRef as useRef94, useState as useState86 } from "react";
53480
53569
  function usePreviewDocumentVersion() {
53481
53570
  const [previewDocumentVersion, setPreviewDocumentVersion] = useState86(0);
53482
53571
  const refreshTimersRef = useRef94([]);
@@ -53489,7 +53578,7 @@ function usePreviewDocumentVersion() {
53489
53578
  window.setTimeout(() => setPreviewDocumentVersion((v) => v + 1), 300)
53490
53579
  );
53491
53580
  }, []);
53492
- useEffect75(
53581
+ useEffect76(
53493
53582
  () => () => {
53494
53583
  for (const id of refreshTimersRef.current) clearTimeout(id);
53495
53584
  },
@@ -55034,7 +55123,7 @@ function persistTimelineMoveEditsAtomically(edits, coalesceKey, operation, deps,
55034
55123
  import { useCallback as useCallback102 } from "react";
55035
55124
 
55036
55125
  // src/hooks/useAskAgentModal.ts
55037
- import { useState as useState87, useCallback as useCallback80, useRef as useRef97, useEffect as useEffect76 } from "react";
55126
+ import { useState as useState87, useCallback as useCallback80, useRef as useRef97, useEffect as useEffect77 } from "react";
55038
55127
  function useAskAgentModal({
55039
55128
  activeCompPath,
55040
55129
  projectDir,
@@ -55115,13 +55204,13 @@ function useAskAgentModal({
55115
55204
  showToast
55116
55205
  ]
55117
55206
  );
55118
- useEffect76(() => {
55207
+ useEffect77(() => {
55119
55208
  setAgentPromptTagSnippet(void 0);
55120
55209
  setAgentPromptSelectionContext(void 0);
55121
55210
  setAgentModalAnchorPoint(null);
55122
55211
  setCopiedAgentPrompt(false);
55123
55212
  }, [domEditSelection]);
55124
- useEffect76(
55213
+ useEffect77(
55125
55214
  () => () => {
55126
55215
  if (copiedAgentTimerRef.current) clearTimeout(copiedAgentTimerRef.current);
55127
55216
  },
@@ -55145,7 +55234,7 @@ function useAskAgentModal({
55145
55234
  }
55146
55235
 
55147
55236
  // src/hooks/useDomSelection.ts
55148
- import { useState as useState88, useCallback as useCallback81, useRef as useRef98, useEffect as useEffect78 } from "react";
55237
+ import { useState as useState88, useCallback as useCallback81, useRef as useRef98, useEffect as useEffect79 } from "react";
55149
55238
 
55150
55239
  // src/utils/domEditHelpers.ts
55151
55240
  function domEditSelectionsTargetSame(a, b) {
@@ -55178,7 +55267,7 @@ function seedDomEditGroupWithSelection(group, selection) {
55178
55267
  }
55179
55268
 
55180
55269
  // src/hooks/useStudioTestHooks.ts
55181
- import { useEffect as useEffect77 } from "react";
55270
+ import { useEffect as useEffect78 } from "react";
55182
55271
 
55183
55272
  // src/player/lib/timelinePerformanceDiagnostics.ts
55184
55273
  function readNonNegativeNumber(value) {
@@ -55261,7 +55350,7 @@ function useStudioTestHooks({
55261
55350
  buildDomSelectionFromTarget,
55262
55351
  applyDomSelection
55263
55352
  }) {
55264
- useEffect77(() => {
55353
+ useEffect78(() => {
55265
55354
  if (!STUDIO_TEST_HOOKS_ENABLED || typeof window === "undefined") return;
55266
55355
  const api = {
55267
55356
  runtimeMode: STUDIO_RUNTIME_MODE,
@@ -55562,10 +55651,10 @@ function useDomSelection({
55562
55651
  previewIframeRef
55563
55652
  ]
55564
55653
  );
55565
- useEffect78(() => {
55654
+ useEffect79(() => {
55566
55655
  updateDomEditHoverSelection(null);
55567
55656
  }, [activeCompPath, projectId, previewIframe, refreshKey, updateDomEditHoverSelection]);
55568
- useEffect78(() => {
55657
+ useEffect79(() => {
55569
55658
  const previous = compositionIdentityRef.current;
55570
55659
  if (previous.activeCompPath === activeCompPath && previous.projectId === projectId) return;
55571
55660
  compositionIdentityRef.current = { activeCompPath, projectId };
@@ -55573,7 +55662,7 @@ function useDomSelection({
55573
55662
  setActiveGroupElementState(null);
55574
55663
  applyDomSelection(null, { revealPanel: false });
55575
55664
  }, [activeCompPath, projectId, applyDomSelection]);
55576
- useEffect78(() => {
55665
+ useEffect79(() => {
55577
55666
  if (!domEditHoverSelection) return;
55578
55667
  const shouldClear = captionEditMode || domEditSelectionsTargetSame(domEditHoverSelection, domEditSelection) || domEditSelectionInGroup(domEditGroupSelections, domEditHoverSelection) || !domEditHoverSelection.element.isConnected;
55579
55668
  if (shouldClear) updateDomEditHoverSelection(null);
@@ -55584,7 +55673,7 @@ function useDomSelection({
55584
55673
  domEditGroupSelections,
55585
55674
  updateDomEditHoverSelection
55586
55675
  ]);
55587
- useEffect78(() => {
55676
+ useEffect79(() => {
55588
55677
  if (!captionEditMode) return;
55589
55678
  applyDomSelection(null, { revealPanel: false });
55590
55679
  }, [applyDomSelection, captionEditMode]);
@@ -58330,7 +58419,7 @@ function useGsapKeyframeOps({
58330
58419
  }
58331
58420
 
58332
58421
  // src/hooks/useGsapPropertyDebounce.ts
58333
- import { useCallback as useCallback92, useEffect as useEffect79, useRef as useRef103 } from "react";
58422
+ import { useCallback as useCallback92, useEffect as useEffect80, useRef as useRef103 } from "react";
58334
58423
  import { parseGsapScriptAcorn } from "@hyperframes/core/gsap-parser-acorn";
58335
58424
  var DEBOUNCE_MS = 150;
58336
58425
  function mergeTweenProperties(sdkSession, animationId, edited, kind) {
@@ -58400,7 +58489,7 @@ function useGsapPropertyDebounce(commitMutationSafely, sdk) {
58400
58489
  },
58401
58490
  [flushPendingPropertyEdit]
58402
58491
  );
58403
- useEffect79(() => {
58492
+ useEffect80(() => {
58404
58493
  return () => {
58405
58494
  if (debounceTimerRef.current) clearTimeout(debounceTimerRef.current);
58406
58495
  void flushPendingPropertyEdit();
@@ -58941,10 +59030,10 @@ function useGsapScriptCommits({ projectIdRef, activeCompPath, previewIframeRef,
58941
59030
  }
58942
59031
 
58943
59032
  // src/hooks/useDomEditWiring.ts
58944
- import { useCallback as useCallback98, useEffect as useEffect81, useRef as useRef107 } from "react";
59033
+ import { useCallback as useCallback98, useEffect as useEffect82, useRef as useRef107 } from "react";
58945
59034
 
58946
59035
  // src/hooks/useDomEditPreviewSync.ts
58947
- import { useEffect as useEffect80, useRef as useRef105 } from "react";
59036
+ import { useEffect as useEffect81, useRef as useRef105 } from "react";
58948
59037
  function useDomEditPreviewSync({
58949
59038
  previewIframe,
58950
59039
  activeCompPath,
@@ -58960,7 +59049,7 @@ function useDomEditPreviewSync({
58960
59049
  getSidebarTab,
58961
59050
  gsapCacheVersion
58962
59051
  }) {
58963
- useEffect80(() => {
59052
+ useEffect81(() => {
58964
59053
  if (!previewIframe) return;
58965
59054
  const syncSelectionFromDocument = async () => {
58966
59055
  if (captionEditMode) return;
@@ -59012,7 +59101,7 @@ function useDomEditPreviewSync({
59012
59101
  ]);
59013
59102
  const openSourceRef = useRef105(openSourceForSelection);
59014
59103
  openSourceRef.current = openSourceForSelection;
59015
- useEffect80(
59104
+ useEffect81(
59016
59105
  // fallow-ignore-next-line complexity
59017
59106
  () => {
59018
59107
  if (!domEditSelection || !openSourceRef.current || !getSidebarTab) return;
@@ -59449,7 +59538,7 @@ function useDomEditWiring({
59449
59538
  },
59450
59539
  [openSourceForSelection, selectSidebarTab]
59451
59540
  );
59452
- useEffect81(() => {
59541
+ useEffect82(() => {
59453
59542
  if (!domEditSelection?.id) return;
59454
59543
  const { selectedElementId, elements, setSelectedElementId } = usePlayerStore.getState();
59455
59544
  const matchKey = elements.find(
@@ -59459,7 +59548,7 @@ function useDomEditWiring({
59459
59548
  if (key2 && key2 !== selectedElementId) setSelectedElementId(key2);
59460
59549
  }, [domEditSelection?.id]);
59461
59550
  const prevRefreshKeyRef = useRef107(refreshKey);
59462
- useEffect81(() => {
59551
+ useEffect82(() => {
59463
59552
  if (refreshKey !== prevRefreshKeyRef.current) {
59464
59553
  prevRefreshKeyRef.current = refreshKey;
59465
59554
  bumpGsapCache();
@@ -59597,7 +59686,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59597
59686
  if (!anim || isInstantHold(anim)) {
59598
59687
  const sel = selectorFromSelection(selection) ?? writeTargetSelector(selection);
59599
59688
  if (!sel) return { status: "blocked", reason: "no-selector" };
59600
- const sizeSet = anim ?? findSizeSetAnimation(workingAnimations, sel, selection.element);
59689
+ const sizeSet = resizeGroup === "size" ? anim ?? findSizeSetAnimation(workingAnimations, sel, selection.element) : findSizeSetAnimation(workingAnimations, sel, selection.element);
59601
59690
  if (resizeGroup === "size") {
59602
59691
  const animatedTween = pickClosestToPlayhead(
59603
59692
  workingAnimations.filter((a) => !isInstantHold(a) && resolveTweenDuration(a) > 0)
@@ -59645,7 +59734,8 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59645
59734
  const liveScaleY = rawLiveScaleY > 0 ? rawLiveScaleY : 1;
59646
59735
  const newScaleX = roundTo3(size.width * liveScaleX / cssW);
59647
59736
  const newScaleY = roundTo3(size.height * liveScaleY / cssH);
59648
- nonUniformScale = Math.abs(newScaleX - newScaleY) > 0.01;
59737
+ const uniformDrift = Math.abs(newScaleX - newScaleY) * cssH;
59738
+ nonUniformScale = uniformDrift > 0.5;
59649
59739
  useScaleLonghands = nonUniformScale || tweenUsesScaleLonghands(anim);
59650
59740
  resizeProps = useScaleLonghands ? { scaleX: newScaleX, scaleY: newScaleY } : { scale: newScaleX };
59651
59741
  logResize("intercept-route", {
@@ -59671,9 +59761,9 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59671
59761
  };
59672
59762
  }
59673
59763
  const finalizeScaleResizeCommit = async () => {
59674
- if (!scaleDraftEl) return;
59764
+ if (!scaleDraftEl) return false;
59675
59765
  clearStudioBoxSize(scaleDraftEl);
59676
- if (!scaleDraftDropPoint || !selector) return;
59766
+ if (!scaleDraftDropPoint || !selector) return false;
59677
59767
  if (committedScale) {
59678
59768
  setElementGsapScale(scaleDraftEl, committedScale.x, committedScale.y);
59679
59769
  }
@@ -59687,10 +59777,10 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59687
59777
  setElementGsapPosition(scaleDraftEl, base2.x, base2.y);
59688
59778
  const post = scaleDraftEl.getBoundingClientRect();
59689
59779
  const residual = { x: scaleDraftDropPoint.x - post.x, y: scaleDraftDropPoint.y - post.y };
59690
- if (!Number.isFinite(residual.x) || !Number.isFinite(residual.y)) return;
59780
+ if (!Number.isFinite(residual.x) || !Number.isFinite(residual.y)) return false;
59691
59781
  if (Math.abs(residual.x) < 0.5 && Math.abs(residual.y) < 0.5) {
59692
59782
  logResize("scale-finalize", { skipped: "already-on-drop-point", residual, base: base2 });
59693
- return;
59783
+ return true;
59694
59784
  }
59695
59785
  const corrected = {
59696
59786
  x: Math.round(base2.x + residual.x),
@@ -59718,13 +59808,14 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59718
59808
  commitMutation,
59719
59809
  fetchAnimations: fetchFallbackAnimations
59720
59810
  });
59721
- return;
59811
+ return true;
59722
59812
  }
59723
59813
  const existingSet = findExistingPositionWrite(currentAnimations, selector, selection.element);
59724
59814
  await commitStaticGsapPosition(selection, delta, base2, selector, existingSet, {
59725
59815
  commitMutation,
59726
59816
  fetchAnimations: fetchFallbackAnimations
59727
59817
  });
59818
+ return true;
59728
59819
  };
59729
59820
  if (!usePlayerStore.getState().autoKeyframeEnabled) {
59730
59821
  if (activeKeyframePct != null) setActiveKeyframePct(null);
@@ -59737,8 +59828,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59737
59828
  { commitMutation, fetchAnimations: fetchFallbackAnimations },
59738
59829
  "Resize animation"
59739
59830
  );
59740
- await finalizeScaleResizeCommit();
59741
- return { status: "persisted" };
59831
+ return { status: "persisted", ownsDragOffset: await finalizeScaleResizeCommit() };
59742
59832
  }
59743
59833
  const ct = usePlayerStore.getState().currentTime;
59744
59834
  const ts = resolveTweenStart(anim);
@@ -59817,8 +59907,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59817
59907
  softReload: true
59818
59908
  }
59819
59909
  );
59820
- await finalizeScaleResizeCommit();
59821
- return { status: "persisted" };
59910
+ return { status: "persisted", ownsDragOffset: await finalizeScaleResizeCommit() };
59822
59911
  }
59823
59912
  const SIZE_PROPS = /* @__PURE__ */ new Set(["width", "height"]);
59824
59913
  const backfillDefaults = {};
@@ -59837,8 +59926,7 @@ async function tryGsapResizeIntercept(selection, size, animations, iframe, commi
59837
59926
  },
59838
59927
  { label: `Resize (keyframe ${pct}%)`, softReload: true }
59839
59928
  );
59840
- await finalizeScaleResizeCommit();
59841
- return { status: "persisted" };
59929
+ return { status: "persisted", ownsDragOffset: await finalizeScaleResizeCommit() };
59842
59930
  }
59843
59931
 
59844
59932
  // src/hooks/useAnimatedPropertyCommit.ts
@@ -60338,11 +60426,13 @@ function useGsapAwareEditing({
60338
60426
  makeFetchFallback(selection)
60339
60427
  );
60340
60428
  assertGsapEditPersisted(outcome);
60429
+ const ownsDragOffset = outcome.status === "persisted" && outcome.ownsDragOffset === true;
60341
60430
  logResize("intercept-handled", {
60342
60431
  scaleRoute,
60343
- willForwardOffset: !!(offset && !scaleRoute)
60432
+ ownsDragOffset,
60433
+ willForwardOffset: !!(offset && !ownsDragOffset)
60344
60434
  });
60345
- if (offset && !scaleRoute) {
60435
+ if (offset && !ownsDragOffset) {
60346
60436
  const dragOutcome = await tryGsapDragIntercept(
60347
60437
  selection,
60348
60438
  offset,
@@ -60353,7 +60443,7 @@ function useGsapAwareEditing({
60353
60443
  );
60354
60444
  assertGsapEditPersisted(dragOutcome);
60355
60445
  }
60356
- logResizeSettle(selection.element, scaleRoute ? "gsap-scale" : "gsap-size");
60446
+ logResizeSettle(selection.element, ownsDragOffset ? "gsap-scale" : "gsap-size");
60357
60447
  return;
60358
60448
  } catch (error) {
60359
60449
  trackGsapInteractionFailure(error, selection, "resize", "Resize animated layer");
@@ -60491,7 +60581,7 @@ function useGsapAwareEditing({
60491
60581
  }
60492
60582
 
60493
60583
  // src/hooks/useStudioSelectionPublisher.ts
60494
- import { useEffect as useEffect82, useRef as useRef108 } from "react";
60584
+ import { useEffect as useEffect83, useRef as useRef108 } from "react";
60495
60585
 
60496
60586
  // src/utils/studioSelectionSnapshot.ts
60497
60587
  function round34(value) {
@@ -60584,7 +60674,7 @@ function useStudioSelectionPublisher({
60584
60674
  }) {
60585
60675
  const lastSelectionRefreshKeyRef = useRef108(refreshKey);
60586
60676
  const pendingSelectionRefreshKeyRef = useRef108(null);
60587
- useEffect82(() => {
60677
+ useEffect83(() => {
60588
60678
  if (!projectId) return;
60589
60679
  const selection = domEditSelection?.element.isConnected ? buildStudioSelectionSnapshot({
60590
60680
  projectId,
@@ -60595,13 +60685,13 @@ function useStudioSelectionPublisher({
60595
60685
  void putSelection(projectId, selection, controller.signal).catch(reportSelectionPublishError);
60596
60686
  return () => controller.abort();
60597
60687
  }, [domEditSelection, projectId]);
60598
- useEffect82(() => {
60688
+ useEffect83(() => {
60599
60689
  if (!projectId) return;
60600
60690
  return () => {
60601
60691
  void putSelection(projectId, null).catch(reportSelectionPublishError);
60602
60692
  };
60603
60693
  }, [projectId]);
60604
- useEffect82(() => {
60694
+ useEffect83(() => {
60605
60695
  if (lastSelectionRefreshKeyRef.current === refreshKey) return;
60606
60696
  lastSelectionRefreshKeyRef.current = refreshKey;
60607
60697
  pendingSelectionRefreshKeyRef.current = domEditSelectionRef.current ? refreshKey : null;
@@ -60610,7 +60700,7 @@ function useStudioSelectionPublisher({
60610
60700
  void putSelection(projectId, null, controller.signal).catch(reportSelectionPublishError);
60611
60701
  return () => controller.abort();
60612
60702
  }, [domEditSelectionRef, projectId, refreshKey]);
60613
- useEffect82(() => {
60703
+ useEffect83(() => {
60614
60704
  if (pendingSelectionRefreshKeyRef.current === null) return;
60615
60705
  pendingSelectionRefreshKeyRef.current = null;
60616
60706
  const selection = domEditSelectionRef.current;
@@ -61127,23 +61217,23 @@ function useDomEditSession({
61127
61217
  }
61128
61218
 
61129
61219
  // src/hooks/useSdkSelectionSync.ts
61130
- import { useEffect as useEffect83 } from "react";
61220
+ import { useEffect as useEffect84 } from "react";
61131
61221
  function toHfIds(group, primary) {
61132
61222
  const source = group.length > 0 ? group : primary ? [primary] : [];
61133
61223
  return source.flatMap((s) => s.hfId ? [s.hfId] : []);
61134
61224
  }
61135
61225
  function useSdkSelectionSync(session, domEditSelection, domEditGroupSelections) {
61136
- useEffect83(() => {
61226
+ useEffect84(() => {
61137
61227
  if (!session) return;
61138
61228
  session.setSelection(toHfIds(domEditGroupSelections, domEditSelection));
61139
61229
  }, [session, domEditSelection, domEditGroupSelections]);
61140
61230
  }
61141
61231
 
61142
61232
  // src/hooks/useStudioSdkSessions.ts
61143
- import { useEffect as useEffect85 } from "react";
61233
+ import { useEffect as useEffect86 } from "react";
61144
61234
 
61145
61235
  // src/hooks/useSdkSession.ts
61146
- import { useState as useState89, useEffect as useEffect84, useCallback as useCallback103, useRef as useRef109 } from "react";
61236
+ import { useState as useState89, useEffect as useEffect85, useCallback as useCallback103, useRef as useRef109 } from "react";
61147
61237
  import { openComposition as openComposition3 } from "@hyperframes/sdk";
61148
61238
 
61149
61239
  // src/hooks/externalFileReloadBus.ts
@@ -61203,13 +61293,13 @@ function useSdkSession(projectId, activeCompPath) {
61203
61293
  const [reloadToken, setReloadToken] = useState89(0);
61204
61294
  const reloadTokenRef = useRef109(reloadToken);
61205
61295
  reloadTokenRef.current = reloadToken;
61206
- useEffect84(
61296
+ useEffect85(
61207
61297
  () => addExternalFileReloadListener((changedPath) => {
61208
61298
  if (changedPath === activeCompPathRef.current) setReloadToken((token) => token + 1);
61209
61299
  }),
61210
61300
  []
61211
61301
  );
61212
- useEffect84(() => {
61302
+ useEffect85(() => {
61213
61303
  const generation = ++generationRef.current;
61214
61304
  let cancelled = false;
61215
61305
  const previous = ownedSessionRef.current;
@@ -61293,7 +61383,7 @@ function useSdkSession(projectId, activeCompPath) {
61293
61383
  function useStudioSdkSessions(projectId, activeCompPath, masterCompPath) {
61294
61384
  const sdkHandle = useSdkSession(projectId, activeCompPath ?? masterCompPath);
61295
61385
  const editFlowSdkSession = activeCompPath ? sdkHandle.session : null;
61296
- useEffect85(() => {
61386
+ useEffect86(() => {
61297
61387
  usePreviewVariablesStore.getState().setValues(null);
61298
61388
  }, [projectId, activeCompPath]);
61299
61389
  return { sdkHandle, editFlowSdkSession };
@@ -61401,7 +61491,7 @@ async function deleteExternalConflictSnapshot(projectId, filePath) {
61401
61491
  }
61402
61492
 
61403
61493
  // src/hooks/useExternalFileChangeCoordinator.ts
61404
- import { useCallback as useCallback104, useEffect as useEffect86, useRef as useRef110, useState as useState90 } from "react";
61494
+ import { useCallback as useCallback104, useEffect as useEffect87, useRef as useRef110, useState as useState90 } from "react";
61405
61495
  function testHotAdapter() {
61406
61496
  const value = globalThis.__HF_STUDIO_HOT_TEST_ADAPTER__;
61407
61497
  if (!value || typeof value !== "object") return null;
@@ -61458,19 +61548,19 @@ function useExternalFileChangeCoordinator({
61458
61548
  const blockedRef = useRef110(blocked);
61459
61549
  const snapshotWriteTailRef = useRef110(Promise.resolve());
61460
61550
  blockedRef.current = blocked;
61461
- useEffect86(() => {
61551
+ useEffect87(() => {
61462
61552
  mountedRef.current = true;
61463
61553
  return () => {
61464
61554
  mountedRef.current = false;
61465
61555
  generationRef.current += 1;
61466
61556
  };
61467
61557
  }, []);
61468
- useEffect86(() => {
61558
+ useEffect87(() => {
61469
61559
  generationRef.current += 1;
61470
61560
  setBlocked(null);
61471
61561
  lastEventIdentityRef.current = null;
61472
61562
  }, [projectId, activeCompPath]);
61473
- useEffect86(() => {
61563
+ useEffect87(() => {
61474
61564
  if (!projectId || !recoveryFilePath || !loadConflictSnapshot) return;
61475
61565
  const generation = ++generationRef.current;
61476
61566
  let cancelled = false;
@@ -61621,7 +61711,7 @@ function useExternalFileChangeCoordinator({
61621
61711
  reloadAcceptedGeneration
61622
61712
  ]
61623
61713
  );
61624
- useEffect86(() => {
61714
+ useEffect87(() => {
61625
61715
  const handler = (payload) => processChange(payload);
61626
61716
  const adapter = testHotAdapter();
61627
61717
  if (adapter) {
@@ -62087,7 +62177,7 @@ function useBlockHandlers({
62087
62177
  }
62088
62178
 
62089
62179
  // src/hooks/useAppHotkeys.ts
62090
- import { useCallback as useCallback107, useEffect as useEffect87, useRef as useRef112 } from "react";
62180
+ import { useCallback as useCallback107, useEffect as useEffect88, useRef as useRef112 } from "react";
62091
62181
  function iframeContentWindow(iframe) {
62092
62182
  try {
62093
62183
  return iframe?.contentWindow ?? null;
@@ -62380,7 +62470,7 @@ function useAppHotkeys({
62380
62470
  }
62381
62471
  if (!isEditableTarget(event.target)) dispatchPlainKey(event, key2, cb);
62382
62472
  }, []);
62383
- useEffect87(() => {
62473
+ useEffect88(() => {
62384
62474
  window.addEventListener("keydown", handleAppKeyDown, true);
62385
62475
  return () => window.removeEventListener("keydown", handleAppKeyDown, true);
62386
62476
  }, [handleAppKeyDown]);
@@ -62398,7 +62488,7 @@ function useAppHotkeys({
62398
62488
  },
62399
62489
  [handleAppKeyDown]
62400
62490
  );
62401
- useEffect87(
62491
+ useEffect88(
62402
62492
  () => () => {
62403
62493
  safeRemoveListener(
62404
62494
  previewHotkeyWindowRef.current,
@@ -62439,7 +62529,7 @@ function useAppHotkeys({
62439
62529
  },
62440
62530
  [handleHistoryHotkey]
62441
62531
  );
62442
- useEffect87(
62532
+ useEffect88(
62443
62533
  () => () => {
62444
62534
  previewHistoryCleanupRef.current?.();
62445
62535
  previewHistoryCleanupRef.current = null;
@@ -62697,7 +62787,7 @@ function useClipboard({
62697
62787
  }
62698
62788
 
62699
62789
  // src/hooks/useCaptionDetection.ts
62700
- import { useEffect as useEffect88 } from "react";
62790
+ import { useEffect as useEffect89 } from "react";
62701
62791
 
62702
62792
  // src/captions/types.ts
62703
62793
  var DEFAULT_STYLE = {
@@ -62949,7 +63039,7 @@ function useCaptionDetection({
62949
63039
  captionSync,
62950
63040
  setRightCollapsed
62951
63041
  }) {
62952
- useEffect88(() => {
63042
+ useEffect89(() => {
62953
63043
  if (!projectId) return;
62954
63044
  let activating = false;
62955
63045
  const tryActivateCaptions = () => {
@@ -63029,7 +63119,7 @@ function useCaptionDetection({
63029
63119
  window.removeEventListener("message", handleMessage);
63030
63120
  };
63031
63121
  }, [activeCompPath, projectId, compIdToSrc, captionSync, previewIframeRef]);
63032
- useEffect88(() => {
63122
+ useEffect89(() => {
63033
63123
  if (captionEditMode) {
63034
63124
  setRightCollapsed(!captionHasSelection);
63035
63125
  }
@@ -63466,7 +63556,7 @@ function useRenderClipContent({
63466
63556
  }
63467
63557
 
63468
63558
  // src/hooks/useConsoleErrorCapture.ts
63469
- import { useCallback as useCallback112, useEffect as useEffect89, useRef as useRef116, useState as useState93 } from "react";
63559
+ import { useCallback as useCallback112, useEffect as useEffect90, useRef as useRef116, useState as useState93 } from "react";
63470
63560
  function useConsoleErrorCapture(previewIframe) {
63471
63561
  const [consoleErrors, setConsoleErrors] = useState93(null);
63472
63562
  const consoleErrorsRef = useRef116([]);
@@ -63474,7 +63564,7 @@ function useConsoleErrorCapture(previewIframe) {
63474
63564
  consoleErrorsRef.current = [];
63475
63565
  setConsoleErrors(null);
63476
63566
  }, []);
63477
- useEffect89(() => {
63567
+ useEffect90(() => {
63478
63568
  if (!previewIframe) return;
63479
63569
  let patchedWin = null;
63480
63570
  let origConsoleError = null;
@@ -63663,7 +63753,7 @@ function useFrameCapture({
63663
63753
  }
63664
63754
 
63665
63755
  // src/hooks/useLintModal.ts
63666
- import { useState as useState95, useCallback as useCallback114, useEffect as useEffect90, useRef as useRef118, useMemo as useMemo54 } from "react";
63756
+ import { useState as useState95, useCallback as useCallback114, useEffect as useEffect91, useRef as useRef118, useMemo as useMemo54 } from "react";
63667
63757
  function parseFinding(f) {
63668
63758
  return {
63669
63759
  severity: f.severity === "error" ? "error" : "warning",
@@ -63705,7 +63795,7 @@ function useLintModal(projectId, refreshKey) {
63705
63795
  );
63706
63796
  const handleLint = useCallback114(() => runLint(), [runLint]);
63707
63797
  const prevProjectIdRef = useRef118(projectId);
63708
- useEffect90(() => {
63798
+ useEffect91(() => {
63709
63799
  if (projectId !== prevProjectIdRef.current) {
63710
63800
  autoLintRanRef.current = false;
63711
63801
  prevProjectIdRef.current = projectId;
@@ -63714,7 +63804,7 @@ function useLintModal(projectId, refreshKey) {
63714
63804
  autoLintRanRef.current = true;
63715
63805
  void runLint({ background: true });
63716
63806
  }, [projectId, runLint]);
63717
- useEffect90(() => {
63807
+ useEffect91(() => {
63718
63808
  if (!projectId || !refreshKey) return;
63719
63809
  const timer = setTimeout(() => void runLint({ background: true }), 1e3);
63720
63810
  return () => clearTimeout(timer);
@@ -63737,7 +63827,7 @@ function useLintModal(projectId, refreshKey) {
63737
63827
  );
63738
63828
  const findingsByElement = useMemo54(() => groupFindings((f) => f.elementId), [groupFindings]);
63739
63829
  const findingsByFile = useMemo54(() => groupFindings((f) => f.file), [groupFindings]);
63740
- useEffect90(() => {
63830
+ useEffect91(() => {
63741
63831
  usePlayerStore.getState().setLintFindingsByElement(findingsByElement);
63742
63832
  }, [findingsByElement]);
63743
63833
  return {
@@ -63835,7 +63925,7 @@ function useCompositionContentLoader({
63835
63925
  }
63836
63926
 
63837
63927
  // src/hooks/useStudioUrlState.ts
63838
- import { useCallback as useCallback117, useEffect as useEffect91, useRef as useRef120, useState as useState97 } from "react";
63928
+ import { useCallback as useCallback117, useEffect as useEffect92, useRef as useRef120, useState as useState97 } from "react";
63839
63929
 
63840
63930
  // src/utils/studioUrlState.ts
63841
63931
  var VALID_TABS = ["layers", "design", "renders", "slideshow", "variables"];
@@ -64011,7 +64101,7 @@ function useStudioUrlState({
64011
64101
  },
64012
64102
  [activeCompPath, applyDomSelection, buildDomSelectionFromTarget, previewIframeRef]
64013
64103
  );
64014
- useEffect91(() => {
64104
+ useEffect92(() => {
64015
64105
  if (!projectId || hydratedSeekRef.current || compositionLoading) return;
64016
64106
  const nextTime = duration > 0 ? clampNumber(initialState2.currentTime ?? 0, 0, duration) : Math.max(0, initialState2.currentTime ?? 0);
64017
64107
  usePlayerStore.getState().requestSeek(nextTime);
@@ -64019,7 +64109,7 @@ function useStudioUrlState({
64019
64109
  hydratedSeekRef.current = true;
64020
64110
  }, [projectId, compositionLoading, duration, initialState2.currentTime]);
64021
64111
  const selectionHydrationTime = selectionHydrated ? 0 : currentTime;
64022
- useEffect91(() => {
64112
+ useEffect92(() => {
64023
64113
  if (!projectId || hydratedSelectionRef.current || compositionLoading) return;
64024
64114
  if (!hydratedSeekRef.current) return;
64025
64115
  const targetTime = initialState2.currentTime;
@@ -64046,7 +64136,7 @@ function useStudioUrlState({
64046
64136
  projectId,
64047
64137
  refreshKey
64048
64138
  ]);
64049
- useEffect91(() => {
64139
+ useEffect92(() => {
64050
64140
  if (hydratedInitialTimeRef.current) return;
64051
64141
  const targetTime = stableTimeRef.current;
64052
64142
  if (targetTime == null) {
@@ -64056,7 +64146,7 @@ function useStudioUrlState({
64056
64146
  if (Math.abs(currentTime - targetTime) > 0.05) return;
64057
64147
  hydratedInitialTimeRef.current = true;
64058
64148
  }, [currentTime]);
64059
- useEffect91(() => {
64149
+ useEffect92(() => {
64060
64150
  if (!activeCompPathHydrated) return;
64061
64151
  if (!hydratedSeekRef.current) return;
64062
64152
  if (!hydratedInitialTimeRef.current) return;
@@ -64067,12 +64157,12 @@ function useStudioUrlState({
64067
64157
  }, 200);
64068
64158
  return () => window.clearTimeout(handle);
64069
64159
  }, [activeCompPathHydrated, buildUrlState, currentTime, duration, isPlaying, projectId]);
64070
- useEffect91(() => {
64160
+ useEffect92(() => {
64071
64161
  if (!activeCompPathHydrated) return;
64072
64162
  if (!projectId) return;
64073
64163
  replaceHash(buildStudioHash(projectId, buildUrlState()));
64074
64164
  }, [activeCompPathHydrated, buildUrlState, projectId]);
64075
- useEffect91(() => {
64165
+ useEffect92(() => {
64076
64166
  if (!projectId) return;
64077
64167
  const onHashChange = () => {
64078
64168
  if (parseProjectIdFromHash(window.location.hash) !== projectId) return;
@@ -64205,9 +64295,10 @@ function PanelLayoutProvider({
64205
64295
  rightWidth,
64206
64296
  adjustPanelWidth,
64207
64297
  leftCollapsed,
64208
- setLeftCollapsed,
64209
64298
  rightCollapsed,
64210
64299
  setRightCollapsed,
64300
+ effectiveLeftCollapsed,
64301
+ effectiveRightCollapsed,
64211
64302
  rightPanelTab,
64212
64303
  setRightPanelTab,
64213
64304
  rightInspectorPanes,
@@ -64226,9 +64317,10 @@ function PanelLayoutProvider({
64226
64317
  rightWidth,
64227
64318
  adjustPanelWidth,
64228
64319
  leftCollapsed,
64229
- setLeftCollapsed,
64230
64320
  rightCollapsed,
64231
64321
  setRightCollapsed,
64322
+ effectiveLeftCollapsed,
64323
+ effectiveRightCollapsed,
64232
64324
  rightPanelTab,
64233
64325
  setRightPanelTab,
64234
64326
  rightInspectorPanes,
@@ -64244,9 +64336,10 @@ function PanelLayoutProvider({
64244
64336
  rightWidth,
64245
64337
  adjustPanelWidth,
64246
64338
  leftCollapsed,
64247
- setLeftCollapsed,
64248
64339
  rightCollapsed,
64249
64340
  setRightCollapsed,
64341
+ effectiveLeftCollapsed,
64342
+ effectiveRightCollapsed,
64250
64343
  rightPanelTab,
64251
64344
  setRightPanelTab,
64252
64345
  rightInspectorPanes,
@@ -64266,7 +64359,7 @@ import {
64266
64359
  createContext as createContext9,
64267
64360
  useCallback as useCallback119,
64268
64361
  useContext as useContext9,
64269
- useEffect as useEffect92,
64362
+ useEffect as useEffect93,
64270
64363
  useMemo as useMemo57,
64271
64364
  useRef as useRef122,
64272
64365
  useState as useState99
@@ -64304,7 +64397,7 @@ function useViewModeState() {
64304
64397
  }
64305
64398
  return true;
64306
64399
  }, []);
64307
- useEffect92(() => {
64400
+ useEffect93(() => {
64308
64401
  const onPopState = () => {
64309
64402
  const mode = readViewModeFromUrl();
64310
64403
  if (mode !== viewMode && !canSetViewMode(mode)) {
@@ -64586,6 +64679,9 @@ function ViewModeToggle() {
64586
64679
  }
64587
64680
  );
64588
64681
  }
64682
+ function shouldOpenInspector(effectiveRightCollapsed, inspectorPanelActive) {
64683
+ return effectiveRightCollapsed || !inspectorPanelActive;
64684
+ }
64589
64685
  function StudioHeader({
64590
64686
  captureFrameHref,
64591
64687
  captureFrameFilename,
@@ -64597,7 +64693,7 @@ function StudioHeader({
64597
64693
  onExport
64598
64694
  }) {
64599
64695
  const { projectId, editHistory, handleUndo, handleRedo, renderQueue } = useStudioShellContext();
64600
- const { rightCollapsed, setRightCollapsed, setRightPanelTab } = usePanelLayoutContext();
64696
+ const { effectiveRightCollapsed, setRightCollapsed, setRightPanelTab } = usePanelLayoutContext();
64601
64697
  const isRendering = renderQueue.isRendering;
64602
64698
  return /* @__PURE__ */ jsxs118("div", { className: "flex items-center justify-between h-10 px-3 bg-neutral-900 border-b border-neutral-800 flex-shrink-0", children: [
64603
64699
  /* @__PURE__ */ jsxs118("div", { className: "flex items-center gap-3", children: [
@@ -64707,7 +64803,7 @@ function StudioHeader({
64707
64803
  {
64708
64804
  type: "button",
64709
64805
  onClick: () => {
64710
- if (rightCollapsed || !inspectorPanelActive) {
64806
+ if (shouldOpenInspector(effectiveRightCollapsed, inspectorPanelActive)) {
64711
64807
  trackStudioEvent("panel_toggle", { panel: "inspector", collapsed: false });
64712
64808
  setRightPanelTab("design");
64713
64809
  setRightCollapsed(false);
@@ -64766,10 +64862,10 @@ function StudioHeader({
64766
64862
  }
64767
64863
 
64768
64864
  // src/hooks/useGestureCommit.ts
64769
- import { useState as useState101, useCallback as useCallback121, useRef as useRef125, useEffect as useEffect94 } from "react";
64865
+ import { useState as useState101, useCallback as useCallback121, useRef as useRef125, useEffect as useEffect95 } from "react";
64770
64866
 
64771
64867
  // src/hooks/useGestureRecording.ts
64772
- import { useCallback as useCallback120, useEffect as useEffect93, useRef as useRef124, useState as useState100 } from "react";
64868
+ import { useCallback as useCallback120, useEffect as useEffect94, useRef as useRef124, useState as useState100 } from "react";
64773
64869
  function readBasePosition(element, iframeEl) {
64774
64870
  let baseOpacity = 1;
64775
64871
  let baseScale = 1;
@@ -64918,7 +65014,7 @@ function useGestureRecording() {
64918
65014
  const refs = useRef124(createRecordingRefs());
64919
65015
  const samplesRef = useRef124(refs.current.samples);
64920
65016
  const trailRef = useRef124(refs.current.trail);
64921
- useEffect93(() => {
65017
+ useEffect94(() => {
64922
65018
  const r = refs.current;
64923
65019
  return () => {
64924
65020
  isRecordingRef.current = false;
@@ -65301,7 +65397,7 @@ function useGestureCommit({
65301
65397
  const recordingStartTimeRef = useRef125(0);
65302
65398
  const commitInFlightRef = useRef125(false);
65303
65399
  const capturedSelectionRef = useRef125(null);
65304
- useEffect94(() => () => clearInterval(recordingAutoStopRef.current), []);
65400
+ useEffect95(() => () => clearInterval(recordingAutoStopRef.current), []);
65305
65401
  const stopAndCommitRecording = useCallback121(async () => {
65306
65402
  clearInterval(recordingAutoStopRef.current);
65307
65403
  if (commitInFlightRef.current) {
@@ -65646,7 +65742,7 @@ import {
65646
65742
  } from "react";
65647
65743
 
65648
65744
  // src/components/sidebar/CompositionsTab.tsx
65649
- import { memo as memo37, useCallback as useCallback122, useEffect as useEffect95, useRef as useRef126, useState as useState102 } from "react";
65745
+ import { memo as memo37, useCallback as useCallback122, useEffect as useEffect96, useRef as useRef126, useState as useState102 } from "react";
65650
65746
  import { jsx as jsx144, jsxs as jsxs120 } from "react/jsx-runtime";
65651
65747
  var DEFAULT_PREVIEW_STAGE = { width: 1920, height: 1080 };
65652
65748
  var CARD_W = 80;
@@ -65764,10 +65860,10 @@ function CompCard({
65764
65860
  });
65765
65861
  const thumbnailOffsetX = (CARD_W - stageSize.width * previewScale) / 2;
65766
65862
  const thumbnailOffsetY = (CARD_H - stageSize.height * previewScale) / 2;
65767
- useEffect95(() => {
65863
+ useEffect96(() => {
65768
65864
  if (hovered) requestIframePlaybackSync(true);
65769
65865
  }, [hovered, requestIframePlaybackSync]);
65770
- useEffect95(() => {
65866
+ useEffect96(() => {
65771
65867
  return () => {
65772
65868
  if (hoverTimer.current) clearTimeout(hoverTimer.current);
65773
65869
  if (syncTimer.current) clearTimeout(syncTimer.current);
@@ -65943,7 +66039,7 @@ var CompositionsTab = memo37(function CompositionsTab2({
65943
66039
  });
65944
66040
 
65945
66041
  // src/components/sidebar/AssetsTab.tsx
65946
- import { memo as memo38, useState as useState107, useCallback as useCallback125, useRef as useRef129, useMemo as useMemo60, useEffect as useEffect100 } from "react";
66042
+ import { memo as memo38, useState as useState107, useCallback as useCallback125, useRef as useRef129, useMemo as useMemo60, useEffect as useEffect101 } from "react";
65947
66043
 
65948
66044
  // src/components/sidebar/assetHelpers.ts
65949
66045
  function getCategory(path) {
@@ -65993,7 +66089,7 @@ var CATEGORY_LABELS = {
65993
66089
  var FILTER_ORDER = ["audio", "images", "video", "fonts"];
65994
66090
 
65995
66091
  // src/components/sidebar/AudioRow.tsx
65996
- import { useState as useState103, useRef as useRef127, useEffect as useEffect96, useCallback as useCallback123 } from "react";
66092
+ import { useState as useState103, useRef as useRef127, useEffect as useEffect97, useCallback as useCallback123 } from "react";
65997
66093
 
65998
66094
  // src/components/sidebar/AssetContextMenu.tsx
65999
66095
  import { jsx as jsx145, jsxs as jsxs121 } from "react/jsx-runtime";
@@ -66168,14 +66264,14 @@ function AudioRow({
66168
66264
  clearPreviewAsset
66169
66265
  ]
66170
66266
  );
66171
- useEffect96(() => {
66267
+ useEffect97(() => {
66172
66268
  return () => {
66173
66269
  cancelAnimationFrame(animRef.current);
66174
66270
  audioRef.current?.pause();
66175
66271
  actxRef.current?.close();
66176
66272
  };
66177
66273
  }, []);
66178
- useEffect96(() => {
66274
+ useEffect97(() => {
66179
66275
  if (playing) {
66180
66276
  const barCount = 24;
66181
66277
  const loop = () => {
@@ -66313,7 +66409,7 @@ function AudioRow({
66313
66409
  }
66314
66410
 
66315
66411
  // src/components/sidebar/GlobalAssetsView.tsx
66316
- import { useEffect as useEffect97, useMemo as useMemo59, useState as useState104 } from "react";
66412
+ import { useEffect as useEffect98, useMemo as useMemo59, useState as useState104 } from "react";
66317
66413
  import { jsx as jsx147, jsxs as jsxs123 } from "react/jsx-runtime";
66318
66414
  function globalAssetRows(records, query = "") {
66319
66415
  const q = query.trim().toLowerCase();
@@ -66329,7 +66425,7 @@ function globalAssetRows(records, query = "") {
66329
66425
  }
66330
66426
  function GlobalAssetsView({ searchQuery }) {
66331
66427
  const [records, setRecords] = useState104(null);
66332
- useEffect97(() => {
66428
+ useEffect98(() => {
66333
66429
  let cancelled = false;
66334
66430
  fetch("/api/assets/global").then((r) => r.ok ? r.json() : { assets: [] }).then((d) => {
66335
66431
  if (!cancelled) setRecords(Array.isArray(d.assets) ? d.assets : []);
@@ -66372,10 +66468,10 @@ function GlobalAssetsView({ searchQuery }) {
66372
66468
  }
66373
66469
 
66374
66470
  // src/components/sidebar/AssetCard.tsx
66375
- import { useState as useState106, useEffect as useEffect99, useRef as useRef128, useCallback as useCallback124 } from "react";
66471
+ import { useState as useState106, useEffect as useEffect100, useRef as useRef128, useCallback as useCallback124 } from "react";
66376
66472
 
66377
66473
  // src/components/ui/VideoFrameThumbnail.tsx
66378
- import { useState as useState105, useEffect as useEffect98 } from "react";
66474
+ import { useState as useState105, useEffect as useEffect99 } from "react";
66379
66475
  import { jsx as jsx148 } from "react/jsx-runtime";
66380
66476
  function VideoFrameThumbnail({
66381
66477
  src,
@@ -66383,7 +66479,7 @@ function VideoFrameThumbnail({
66383
66479
  }) {
66384
66480
  const [frame, setFrame] = useState105(null);
66385
66481
  const [failed2, setFailed] = useState105(false);
66386
- useEffect98(() => {
66482
+ useEffect99(() => {
66387
66483
  setFailed(false);
66388
66484
  const video = document.createElement("video");
66389
66485
  video.crossOrigin = "anonymous";
@@ -66436,7 +66532,7 @@ function openAssetContextMenu(e, setContextMenu) {
66436
66532
  }
66437
66533
  function useProbedDuration(src, skip) {
66438
66534
  const [duration, setDuration] = useState106(void 0);
66439
- useEffect99(() => {
66535
+ useEffect100(() => {
66440
66536
  if (skip) return;
66441
66537
  let cancelled = false;
66442
66538
  let retryTimer;
@@ -66709,7 +66805,7 @@ var AssetsTab = memo38(function AssetsTab2({
66709
66805
  const [manifest, setManifest] = useState107(/* @__PURE__ */ new Map());
66710
66806
  const manifest404Ref = useRef129(/* @__PURE__ */ new Set());
66711
66807
  const assetsKey = assets.join("|");
66712
- useEffect100(() => {
66808
+ useEffect101(() => {
66713
66809
  if (manifest404Ref.current.has(projectId)) return;
66714
66810
  let cancelled = false;
66715
66811
  fetch(`/api/projects/${projectId}/preview/.media/manifest.jsonl`).then((r) => {
@@ -67028,7 +67124,7 @@ var AssetsTab = memo38(function AssetsTab2({
67028
67124
  });
67029
67125
 
67030
67126
  // src/components/sidebar/BlocksTab.tsx
67031
- import { memo as memo39, useState as useState108, useCallback as useCallback126, useRef as useRef130, useEffect as useEffect101 } from "react";
67127
+ import { memo as memo39, useState as useState108, useCallback as useCallback126, useRef as useRef130, useEffect as useEffect102 } from "react";
67032
67128
  import { createPortal as createPortal7 } from "react-dom";
67033
67129
  import { jsx as jsx151, jsxs as jsxs126 } from "react/jsx-runtime";
67034
67130
  var BlocksTab = memo39(function BlocksTab2({ onAddBlock, onPreviewBlock }) {
@@ -67257,7 +67353,7 @@ function BlockCard({
67257
67353
  setHovered(false);
67258
67354
  onPreview?.(null);
67259
67355
  }, [onPreview]);
67260
- useEffect101(() => {
67356
+ useEffect102(() => {
67261
67357
  return () => {
67262
67358
  if (hoverTimer.current) clearTimeout(hoverTimer.current);
67263
67359
  };
@@ -67419,7 +67515,7 @@ function PromptPreviewModal({
67419
67515
  const [value, setValue] = useState108(prompt);
67420
67516
  const [copied, setCopied] = useState108(false);
67421
67517
  const textareaRef = useRef130(null);
67422
- useEffect101(() => {
67518
+ useEffect102(() => {
67423
67519
  requestAnimationFrame(() => textareaRef.current?.focus());
67424
67520
  }, []);
67425
67521
  const handleCopy = useCallback126(() => {
@@ -67870,7 +67966,7 @@ function StudioLeftSidebar({
67870
67966
  onAddCompositionToTimeline
67871
67967
  }) {
67872
67968
  const {
67873
- leftCollapsed,
67969
+ effectiveLeftCollapsed,
67874
67970
  leftWidth,
67875
67971
  adjustPanelWidth,
67876
67972
  toggleLeftSidebar,
@@ -67903,7 +67999,7 @@ function StudioLeftSidebar({
67903
67999
  },
67904
68000
  [renderQueue, waitForPendingDomEditSaves]
67905
68001
  );
67906
- if (leftCollapsed) {
68002
+ if (effectiveLeftCollapsed) {
67907
68003
  return /* @__PURE__ */ jsx154("div", { className: "mr-0.5 flex w-10 flex-shrink-0 flex-col items-center rounded-lg border border-neutral-800/50 bg-neutral-950 pt-1", children: /* @__PURE__ */ jsx154(
67908
68004
  "button",
67909
68005
  {
@@ -68015,10 +68111,10 @@ function StudioLeftSidebar({
68015
68111
  }
68016
68112
 
68017
68113
  // src/components/StudioRightPanel.tsx
68018
- import { useCallback as useCallback144, useEffect as useEffect108, useRef as useRef137 } from "react";
68114
+ import { useCallback as useCallback144, useEffect as useEffect109, useRef as useRef137 } from "react";
68019
68115
 
68020
68116
  // src/components/editor/LayersPanel.tsx
68021
- import { memo as memo41, useState as useState112, useCallback as useCallback130, useEffect as useEffect102, useRef as useRef133 } from "react";
68117
+ import { memo as memo41, useState as useState112, useCallback as useCallback130, useEffect as useEffect103, useRef as useRef133 } from "react";
68022
68118
 
68023
68119
  // src/components/editor/useLayerDrag.ts
68024
68120
  import { useRef as useRef132, useState as useState111, useCallback as useCallback129 } from "react";
@@ -68321,10 +68417,10 @@ var LayersPanel = memo41(function LayersPanel2() {
68321
68417
  });
68322
68418
  setLayers(sortLayersByZIndex(items));
68323
68419
  }, [previewIframeRef, activeCompPath, isMasterView, activeGroupElement, setActiveGroupElement]);
68324
- useEffect102(() => {
68420
+ useEffect103(() => {
68325
68421
  collectLayers();
68326
68422
  }, [collectLayers, refreshKey, zEditVersion]);
68327
- useEffect102(() => {
68423
+ useEffect103(() => {
68328
68424
  const iframe = previewIframeRef.current;
68329
68425
  if (!iframe) return;
68330
68426
  const handleLoad = () => {
@@ -68334,13 +68430,13 @@ var LayersPanel = memo41(function LayersPanel2() {
68334
68430
  iframe.addEventListener("load", handleLoad);
68335
68431
  return () => iframe.removeEventListener("load", handleLoad);
68336
68432
  }, [previewIframeRef, collectLayers]);
68337
- useEffect102(() => {
68433
+ useEffect103(() => {
68338
68434
  if (!compositionLoading) {
68339
68435
  const timer = setTimeout(collectLayers, 100);
68340
68436
  return () => clearTimeout(timer);
68341
68437
  }
68342
68438
  }, [compositionLoading, collectLayers]);
68343
- useEffect102(() => {
68439
+ useEffect103(() => {
68344
68440
  const throttle = createRafThrottle(collectLayers, 100);
68345
68441
  const unsubscribe = liveTime.subscribe(throttle.invoke);
68346
68442
  return () => {
@@ -69186,7 +69282,7 @@ function ParamControl({
69186
69282
  }
69187
69283
 
69188
69284
  // src/components/renders/RenderQueue.tsx
69189
- import { memo as memo46, useState as useState116, useRef as useRef134, useEffect as useEffect103, useLayoutEffect as useLayoutEffect8, useId as useId6 } from "react";
69285
+ import { memo as memo46, useState as useState116, useRef as useRef134, useEffect as useEffect104, useLayoutEffect as useLayoutEffect8, useId as useId6 } from "react";
69190
69286
  import { createPortal as createPortal8 } from "react-dom";
69191
69287
  import { CANVAS_DIMENSIONS } from "@hyperframes/parsers";
69192
69288
 
@@ -69482,7 +69578,7 @@ function FormatInfoTooltip({ format }) {
69482
69578
  const hide = () => {
69483
69579
  timeoutRef.current = setTimeout(() => setOpen(false), 120);
69484
69580
  };
69485
- useEffect103(() => () => clearTimeout(timeoutRef.current), []);
69581
+ useEffect104(() => () => clearTimeout(timeoutRef.current), []);
69486
69582
  useLayoutEffect8(() => {
69487
69583
  if (!open) return;
69488
69584
  const el = triggerRef.current;
@@ -69496,7 +69592,7 @@ function FormatInfoTooltip({ format }) {
69496
69592
  )
69497
69593
  );
69498
69594
  }, [open]);
69499
- useEffect103(() => {
69595
+ useEffect104(() => {
69500
69596
  if (!open) return;
69501
69597
  const onKeyDown = (e) => {
69502
69598
  if (e.key === "Escape") setOpen(false);
@@ -69708,7 +69804,7 @@ var RenderQueue = memo46(function RenderQueue2({
69708
69804
  compositionDimensions
69709
69805
  }) {
69710
69806
  const listRef = useRef134(null);
69711
- useEffect103(() => {
69807
+ useEffect104(() => {
69712
69808
  if (listRef.current) {
69713
69809
  listRef.current.scrollTo({ top: listRef.current.scrollHeight, behavior: "smooth" });
69714
69810
  }
@@ -69816,7 +69912,7 @@ var RenderQueue = memo46(function RenderQueue2({
69816
69912
  });
69817
69913
 
69818
69914
  // src/components/panels/SlideshowPanel.tsx
69819
- import { useState as useState118, useEffect as useEffect104, useCallback as useCallback136, useRef as useRef135 } from "react";
69915
+ import { useState as useState118, useEffect as useEffect105, useCallback as useCallback136, useRef as useRef135 } from "react";
69820
69916
  import { parseSlideshowManifest } from "@hyperframes/core/slideshow";
69821
69917
 
69822
69918
  // src/components/panels/SlideshowSubPanels.tsx
@@ -70455,7 +70551,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
70455
70551
  const { domEditSelection } = useDomEditSelectionContext();
70456
70552
  const manifestRef = useRef135(manifest);
70457
70553
  const notesCtrlRef = useRef135(makeSlideshowNotesController());
70458
- useEffect104(() => {
70554
+ useEffect105(() => {
70459
70555
  if (!compHtml) {
70460
70556
  notesCtrlRef.current.flush();
70461
70557
  setManifest({ slides: [] });
@@ -70489,7 +70585,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
70489
70585
  },
70490
70586
  [onPersistNotes]
70491
70587
  );
70492
- useEffect104(() => {
70588
+ useEffect105(() => {
70493
70589
  const ctrl = notesCtrlRef.current;
70494
70590
  return () => {
70495
70591
  ctrl.flush();
@@ -70709,7 +70805,7 @@ function SlideshowPanel({ scenes, onPersist, onPersistNotes }) {
70709
70805
  }
70710
70806
 
70711
70807
  // src/components/panels/VariablesPanel.tsx
70712
- import { memo as memo47, useCallback as useCallback140, useEffect as useEffect106, useMemo as useMemo61, useState as useState122 } from "react";
70808
+ import { memo as memo47, useCallback as useCallback140, useEffect as useEffect107, useMemo as useMemo61, useState as useState122 } from "react";
70713
70809
 
70714
70810
  // src/hooks/useVariablesPersist.ts
70715
70811
  import { useCallback as useCallback137 } from "react";
@@ -70763,7 +70859,7 @@ function useVariablesPersist({
70763
70859
  import { useCallback as useCallback139, useState as useState121 } from "react";
70764
70860
 
70765
70861
  // src/hooks/useProjectCompositionVariables.ts
70766
- import { useCallback as useCallback138, useEffect as useEffect105, useState as useState119 } from "react";
70862
+ import { useCallback as useCallback138, useEffect as useEffect106, useState as useState119 } from "react";
70767
70863
  import { openComposition as openComposition4 } from "@hyperframes/sdk";
70768
70864
  async function readGroup(path, readProjectFile) {
70769
70865
  let content;
@@ -70787,7 +70883,7 @@ async function readGroup(path, readProjectFile) {
70787
70883
  }
70788
70884
  function useProjectCompositionVariables(fileTree, excludePath, readProjectFile, refreshKey) {
70789
70885
  const [groups, setGroups] = useState119([]);
70790
- useEffect105(() => {
70886
+ useEffect106(() => {
70791
70887
  let cancelled = false;
70792
70888
  const htmlFiles = fileTree.filter((p) => p.endsWith(".html") && p !== excludePath);
70793
70889
  void (async () => {
@@ -71397,7 +71493,7 @@ var VariablesPanel = memo47(function VariablesPanel2({
71397
71493
  const previewValues = usePreviewVariablesStore((s) => s.values);
71398
71494
  const setPreviewValues = usePreviewVariablesStore((s) => s.setValues);
71399
71495
  const [revision, setRevision] = useState122(0);
71400
- useEffect106(() => {
71496
+ useEffect107(() => {
71401
71497
  if (!sdkSession) return;
71402
71498
  return sdkSession.on("change", () => setRevision((r) => r + 1));
71403
71499
  }, [sdkSession]);
@@ -71767,7 +71863,7 @@ function useSlideshowPersist({
71767
71863
  }
71768
71864
 
71769
71865
  // src/hooks/useSlideshowTabState.ts
71770
- import { useEffect as useEffect107, useMemo as useMemo62 } from "react";
71866
+ import { useEffect as useEffect108, useMemo as useMemo62 } from "react";
71771
71867
  import { SLIDESHOW_ISLAND_TYPE as SLIDESHOW_ISLAND_TYPE2, slideshowIslandRegex as slideshowIslandRegex2 } from "@hyperframes/core/slideshow";
71772
71868
  function useSlideshowTabState(params) {
71773
71869
  const { editingFileContent, previewIframeRef, refreshKey, rightPanelTab, setRightPanelTab } = params;
@@ -71788,7 +71884,7 @@ function useSlideshowTabState(params) {
71788
71884
  return [];
71789
71885
  }
71790
71886
  }, [previewIframeRef, rightPanelTab, refreshKey]);
71791
- useEffect107(() => {
71887
+ useEffect108(() => {
71792
71888
  if (rightPanelTab === "slideshow" && !isSlideshowComposition) {
71793
71889
  setRightPanelTab("renders");
71794
71890
  }
@@ -72226,7 +72322,7 @@ function StudioRightPanel({
72226
72322
  handleInspectorSplitResizeEnd
72227
72323
  } = useInspectorSplitResize();
72228
72324
  const backgroundRemovalAbortRef = useRef137(null);
72229
- useEffect108(
72325
+ useEffect109(
72230
72326
  () => () => {
72231
72327
  backgroundRemovalAbortRef.current?.abort();
72232
72328
  },
@@ -72594,7 +72690,7 @@ function StudioRightPanel({
72594
72690
  }
72595
72691
 
72596
72692
  // src/components/TimelineToolbar.tsx
72597
- import { useEffect as useEffect110, useRef as useRef138 } from "react";
72693
+ import { useEffect as useEffect111, useRef as useRef138 } from "react";
72598
72694
  import { Image as Image2, Magnet, MagnifyingGlassMinus, MagnifyingGlassPlus } from "@phosphor-icons/react";
72599
72695
 
72600
72696
  // src/hooks/useEnableKeyframes.ts
@@ -72933,7 +73029,7 @@ function useEnableKeyframes(sessionRef) {
72933
73029
  }
72934
73030
 
72935
73031
  // src/hooks/useKeyframeKeyboard.ts
72936
- import { useEffect as useEffect109, useCallback as useCallback146 } from "react";
73032
+ import { useEffect as useEffect110, useCallback as useCallback146 } from "react";
72937
73033
  function isTextInput(el) {
72938
73034
  if (!el) return false;
72939
73035
  const tag = el.tagName;
@@ -73001,7 +73097,7 @@ function useKeyframeKeyboard({
73001
73097
  onNudgeKeyframe
73002
73098
  ]
73003
73099
  );
73004
- useEffect109(() => {
73100
+ useEffect110(() => {
73005
73101
  if (!enabled2) return;
73006
73102
  window.addEventListener("keydown", handler, { capture: true });
73007
73103
  return () => window.removeEventListener("keydown", handler, { capture: true });
@@ -73089,7 +73185,7 @@ function TimelineToolbar({ domEditSession, onSplitElement }) {
73089
73185
  enabled: Boolean(onToggleKeyframe),
73090
73186
  onAddKeyframe: onToggleKeyframe
73091
73187
  });
73092
- useEffect110(() => {
73188
+ useEffect111(() => {
73093
73189
  const onKeyDown = (e) => {
73094
73190
  if (e.key !== "n" && e.key !== "N") return;
73095
73191
  if (e.metaKey || e.ctrlKey || e.altKey) return;
@@ -73367,7 +73463,7 @@ import { useState as useState131 } from "react";
73367
73463
  import { Copy as Copy2, Check as Check2 } from "@phosphor-icons/react";
73368
73464
 
73369
73465
  // src/hooks/useStoryboard.ts
73370
- import { useCallback as useCallback147, useEffect as useEffect111, useRef as useRef139, useState as useState124 } from "react";
73466
+ import { useCallback as useCallback147, useEffect as useEffect112, useRef as useRef139, useState as useState124 } from "react";
73371
73467
  function useStoryboard(projectId) {
73372
73468
  const [data, setData] = useState124(null);
73373
73469
  const [loading, setLoading] = useState124(true);
@@ -73376,7 +73472,7 @@ function useStoryboard(projectId) {
73376
73472
  const hasDataRef = useRef139(false);
73377
73473
  const lastProjectRef = useRef139(null);
73378
73474
  const reload = useCallback147(() => setReloadKey((k) => k + 1), []);
73379
- useEffect111(() => {
73475
+ useEffect112(() => {
73380
73476
  if (!projectId) return;
73381
73477
  let cancelled = false;
73382
73478
  if (lastProjectRef.current !== projectId) {
@@ -73408,7 +73504,7 @@ function useStoryboard(projectId) {
73408
73504
  }
73409
73505
 
73410
73506
  // src/hooks/useProjectSignaturePoll.ts
73411
- import { useEffect as useEffect112, useRef as useRef140 } from "react";
73507
+ import { useEffect as useEffect113, useRef as useRef140 } from "react";
73412
73508
  var POLL_INTERVAL_MS = 2e3;
73413
73509
  async function fetchProjectSignature(projectId) {
73414
73510
  try {
@@ -73425,7 +73521,7 @@ function useProjectSignaturePoll(projectId, currentSignature, onChange) {
73425
73521
  const onChangeRef = useRef140(onChange);
73426
73522
  signatureRef.current = currentSignature;
73427
73523
  onChangeRef.current = onChange;
73428
- useEffect112(() => {
73524
+ useEffect113(() => {
73429
73525
  if (!projectId) return;
73430
73526
  let disposed = false;
73431
73527
  let inFlight = false;
@@ -73452,7 +73548,7 @@ function useProjectSignaturePoll(projectId, currentSignature, onChange) {
73452
73548
  }
73453
73549
 
73454
73550
  // src/components/storyboard/StoryboardLoaded.tsx
73455
- import { useEffect as useEffect118, useMemo as useMemo65, useState as useState130 } from "react";
73551
+ import { useEffect as useEffect119, useMemo as useMemo65, useState as useState130 } from "react";
73456
73552
 
73457
73553
  // src/components/storyboard/StoryboardDirection.tsx
73458
73554
  import { jsx as jsx172, jsxs as jsxs144 } from "react/jsx-runtime";
@@ -73475,7 +73571,7 @@ function StoryboardDirection({ globals, frameCount }) {
73475
73571
  }
73476
73572
 
73477
73573
  // src/components/storyboard/FramePoster.tsx
73478
- import { useEffect as useEffect113, useState as useState125 } from "react";
73574
+ import { useEffect as useEffect114, useState as useState125 } from "react";
73479
73575
  import { jsx as jsx173 } from "react/jsx-runtime";
73480
73576
  function FramePoster({
73481
73577
  projectId,
@@ -73486,7 +73582,7 @@ function FramePoster({
73486
73582
  posterVersion
73487
73583
  }) {
73488
73584
  const [failed2, setFailed] = useState125(false);
73489
- useEffect113(() => setFailed(false), [src, seconds, posterVersion]);
73585
+ useEffect114(() => setFailed(false), [src, seconds, posterVersion]);
73490
73586
  if (failed2) {
73491
73587
  return /* @__PURE__ */ jsx173("div", { className: "flex h-full w-full items-center justify-center text-[11px] text-neutral-600", children: "Preview unavailable" });
73492
73588
  }
@@ -73685,7 +73781,7 @@ function StoryboardScriptPanel({ script }) {
73685
73781
  }
73686
73782
 
73687
73783
  // src/components/storyboard/StoryboardSourceEditor.tsx
73688
- import { useCallback as useCallback148, useEffect as useEffect114, useMemo as useMemo63, useRef as useRef141, useState as useState126 } from "react";
73784
+ import { useCallback as useCallback148, useEffect as useEffect115, useMemo as useMemo63, useRef as useRef141, useState as useState126 } from "react";
73689
73785
  import { marked } from "marked";
73690
73786
  import DOMPurify from "dompurify";
73691
73787
  import { jsx as jsx177, jsxs as jsxs147 } from "react/jsx-runtime";
@@ -73697,7 +73793,7 @@ function useEditableFile(path, onSaved) {
73697
73793
  const [loading, setLoading] = useState126(true);
73698
73794
  const [saving, setSaving] = useState126(false);
73699
73795
  const [error, setError] = useState126(null);
73700
- useEffect114(() => {
73796
+ useEffect115(() => {
73701
73797
  if (!path) return;
73702
73798
  let cancelled = false;
73703
73799
  setLoading(true);
@@ -73735,7 +73831,7 @@ function hardenLinks(node) {
73735
73831
  function useMarkdownPreview(source) {
73736
73832
  const [debounced, setDebounced] = useState126(source);
73737
73833
  const primed = useRef141(false);
73738
- useEffect114(() => {
73834
+ useEffect115(() => {
73739
73835
  if (!primed.current && source !== "") {
73740
73836
  primed.current = true;
73741
73837
  setDebounced(source);
@@ -73767,8 +73863,8 @@ function StoryboardSourceEditor({
73767
73863
  const activePath = files.some((f) => f.path === selected) ? selected : files[0]?.path ?? "";
73768
73864
  const file = useEditableFile(activePath, onSaved);
73769
73865
  const previewHtml = useMarkdownPreview(file.content);
73770
- useEffect114(() => onDirtyChange?.(file.dirty), [onDirtyChange, file.dirty]);
73771
- useEffect114(() => {
73866
+ useEffect115(() => onDirtyChange?.(file.dirty), [onDirtyChange, file.dirty]);
73867
+ useEffect115(() => {
73772
73868
  if (!file.dirty) return;
73773
73869
  const onBeforeUnload = (event) => {
73774
73870
  event.preventDefault();
@@ -73840,11 +73936,11 @@ function StoryboardSourceEditor({
73840
73936
  }
73841
73937
 
73842
73938
  // src/components/storyboard/StoryboardFrameFocus.tsx
73843
- import { useCallback as useCallback149, useEffect as useEffect116, useState as useState128 } from "react";
73939
+ import { useCallback as useCallback149, useEffect as useEffect117, useState as useState128 } from "react";
73844
73940
  import { setFrameVoiceover } from "@hyperframes/core/storyboard";
73845
73941
 
73846
73942
  // src/components/storyboard/AgentChatMessageButton.tsx
73847
- import { useEffect as useEffect115, useState as useState127 } from "react";
73943
+ import { useEffect as useEffect116, useState as useState127 } from "react";
73848
73944
  import { jsx as jsx178 } from "react/jsx-runtime";
73849
73945
  var APPLY_STORYBOARD_FEEDBACK_MESSAGE = "Read the storyboard feedback I saved in .hyperframes/frame-comments.json and revise the frames.";
73850
73946
  function AgentChatMessageButton({
@@ -73853,7 +73949,7 @@ function AgentChatMessageButton({
73853
73949
  onCopied
73854
73950
  }) {
73855
73951
  const [copyState, setCopyState] = useState127("idle");
73856
- useEffect115(() => {
73952
+ useEffect116(() => {
73857
73953
  if (copyState !== "copied") return;
73858
73954
  const timeout = window.setTimeout(() => setCopyState("again"), 3e3);
73859
73955
  return () => window.clearTimeout(timeout);
@@ -73926,7 +74022,7 @@ function StoryboardFrameFocus({
73926
74022
  const saved = await applyEdit((src) => setFrameVoiceover(src, frame.index, draft));
73927
74023
  if (saved) setSavedVoiceover(draft);
73928
74024
  }, [applyEdit, frame.index, draft]);
73929
- useEffect116(() => {
74025
+ useEffect117(() => {
73930
74026
  if (!dirty) return;
73931
74027
  const onBeforeUnload = (e) => {
73932
74028
  e.preventDefault();
@@ -73938,14 +74034,14 @@ function StoryboardFrameFocus({
73938
74034
  () => !dirty || window.confirm("Discard unsaved voiceover changes?"),
73939
74035
  [dirty]
73940
74036
  );
73941
- useEffect116(() => registerViewModeGuard(confirmLeave), [confirmLeave, registerViewModeGuard]);
74037
+ useEffect117(() => registerViewModeGuard(confirmLeave), [confirmLeave, registerViewModeGuard]);
73942
74038
  const handleBack = () => {
73943
74039
  if (confirmLeave()) onBack();
73944
74040
  };
73945
74041
  const handleNavigate = (delta) => {
73946
74042
  if (confirmLeave()) onNavigate(delta);
73947
74043
  };
73948
- useEffect116(() => {
74044
+ useEffect117(() => {
73949
74045
  const onKey = (e) => {
73950
74046
  const el = document.activeElement;
73951
74047
  if (el instanceof HTMLTextAreaElement || el instanceof HTMLInputElement) return;
@@ -74417,7 +74513,7 @@ function progressLabel(summary) {
74417
74513
  }
74418
74514
 
74419
74515
  // src/components/storyboard/useFrameComments.ts
74420
- import { useCallback as useCallback150, useEffect as useEffect117, useMemo as useMemo64, useState as useState129 } from "react";
74516
+ import { useCallback as useCallback150, useEffect as useEffect118, useMemo as useMemo64, useState as useState129 } from "react";
74421
74517
 
74422
74518
  // src/components/storyboard/frameComments.ts
74423
74519
  var FRAME_COMMENTS_PATH = ".hyperframes/frame-comments.json";
@@ -74490,7 +74586,7 @@ function useFrameComments(frames) {
74490
74586
  } catch {
74491
74587
  }
74492
74588
  }, [readOptionalProjectFile]);
74493
- useEffect117(() => {
74589
+ useEffect118(() => {
74494
74590
  void refreshPending();
74495
74591
  const onFocus = () => void refreshPending();
74496
74592
  window.addEventListener("focus", onFocus);
@@ -74551,10 +74647,10 @@ function StoryboardLoaded({
74551
74647
  const [feedbackMessageCopied, setFeedbackMessageCopied] = useState130(false);
74552
74648
  const comments = useFrameComments(data.frames);
74553
74649
  const { refreshPending } = comments;
74554
- useEffect118(() => {
74650
+ useEffect119(() => {
74555
74651
  void refreshPending();
74556
74652
  }, [data.signature, refreshPending]);
74557
- useEffect118(() => {
74653
+ useEffect119(() => {
74558
74654
  if (comments.draftCount > 0) setFeedbackMessageCopied(false);
74559
74655
  }, [comments.draftCount]);
74560
74656
  const saveFeedbackAndCopyMessage = async () => {
@@ -74903,7 +74999,7 @@ function StudioSplash({ waiting }) {
74903
74999
  }
74904
75000
 
74905
75001
  // src/hooks/useServerConnection.ts
74906
- import { useEffect as useEffect119, useState as useState132 } from "react";
75002
+ import { useEffect as useEffect120, useState as useState132 } from "react";
74907
75003
  function useServerConnection() {
74908
75004
  const [projectId, setProjectId] = useState132(null);
74909
75005
  const [resolving, setResolving] = useState132(true);
@@ -74944,7 +75040,7 @@ function useServerConnection() {
74944
75040
  if (retryTimer !== null) clearTimeout(retryTimer);
74945
75041
  };
74946
75042
  });
74947
- useEffect119(() => {
75043
+ useEffect120(() => {
74948
75044
  const onHashChange = () => {
74949
75045
  const next = parseProjectIdFromHash(window.location.hash);
74950
75046
  if (next && next !== projectId) setProjectId(next);
@@ -74956,9 +75052,9 @@ function useServerConnection() {
74956
75052
  }
74957
75053
 
74958
75054
  // src/hooks/useStudioSessionStart.ts
74959
- import { useEffect as useEffect120 } from "react";
75055
+ import { useEffect as useEffect121 } from "react";
74960
75056
  function useStudioSessionStart(projectId, resolving, waitingForServer) {
74961
- useEffect120(() => {
75057
+ useEffect121(() => {
74962
75058
  if (resolving || waitingForServer || hasFiredSessionStart()) return;
74963
75059
  markSessionStartFired();
74964
75060
  trackStudioSessionStart({ has_project: projectId != null });
@@ -75039,7 +75135,7 @@ function StudioApp() {
75039
75135
  activeCompPath,
75040
75136
  masterCompPath
75041
75137
  );
75042
- useEffect121(() => {
75138
+ useEffect122(() => {
75043
75139
  if (activeCompPathHydrated) return;
75044
75140
  if (!fileManager.fileTreeLoaded) return;
75045
75141
  const nextCompPath = normalizeStudioCompositionPath(
@@ -75313,7 +75409,7 @@ function StudioApp() {
75313
75409
  } = useInspectorState(
75314
75410
  panelLayout.rightPanelTab,
75315
75411
  panelLayout.rightInspectorPanes,
75316
- panelLayout.rightCollapsed,
75412
+ panelLayout.effectiveRightCollapsed,
75317
75413
  isPlaying,
75318
75414
  domEditSession.domEditSelection,
75319
75415
  gestureState === "recording"
@@ -75429,7 +75525,7 @@ function StudioApp() {
75429
75525
  onAddCompositionToTimeline: handleAddCompositionAtPlayhead
75430
75526
  }
75431
75527
  ),
75432
- right: panelLayout.rightCollapsed ? null : /* @__PURE__ */ jsx184(
75528
+ right: panelLayout.effectiveRightCollapsed ? null : /* @__PURE__ */ jsx184(
75433
75529
  StudioRightPanel,
75434
75530
  {
75435
75531
  designPanelActive,