@remotion/studio 4.0.487 → 4.0.489

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.
@@ -176,6 +176,42 @@ var noop = () => {
176
176
  return;
177
177
  };
178
178
 
179
+ // src/helpers/studio-runtime-config.ts
180
+ import { DEFAULT_TIMELINE_TRACKS } from "@remotion/studio-shared";
181
+ var DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS = 300;
182
+ var defaultStudioRuntimeConfig = {
183
+ askAIEnabled: false,
184
+ bufferStateDelayInMilliseconds: null,
185
+ experimentalClientSideRenderingEnabled: false,
186
+ interactivityEnabled: true,
187
+ keyboardShortcutsEnabled: true,
188
+ maxTimelineTracks: null
189
+ };
190
+ var getStudioRuntimeConfig = () => {
191
+ if (typeof window === "undefined") {
192
+ return defaultStudioRuntimeConfig;
193
+ }
194
+ return window.remotion_studioConfig ?? defaultStudioRuntimeConfig;
195
+ };
196
+ var getStudioAskAIEnabled = () => {
197
+ return getStudioRuntimeConfig().askAIEnabled;
198
+ };
199
+ var getStudioInteractivityEnabled = () => {
200
+ return getStudioRuntimeConfig().interactivityEnabled;
201
+ };
202
+ var getStudioKeyboardShortcutsEnabled = () => {
203
+ return getStudioRuntimeConfig().keyboardShortcutsEnabled;
204
+ };
205
+ var getStudioExperimentalClientSideRenderingEnabled = () => {
206
+ return getStudioRuntimeConfig().experimentalClientSideRenderingEnabled;
207
+ };
208
+ var getStudioMaxTimelineTracks = () => {
209
+ return getStudioRuntimeConfig().maxTimelineTracks ?? DEFAULT_TIMELINE_TRACKS;
210
+ };
211
+ var getStudioBufferStateDelayInMilliseconds = () => {
212
+ return getStudioRuntimeConfig().bufferStateDelayInMilliseconds ?? DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS;
213
+ };
214
+
179
215
  // src/state/canvas-ref.ts
180
216
  import { createRef } from "react";
181
217
  var canvasRef = createRef();
@@ -995,18 +1031,18 @@ var KeybindingContextProvider = ({ children }) => {
995
1031
  };
996
1032
 
997
1033
  // src/helpers/use-keybinding.ts
998
- if (!process.env.KEYBOARD_SHORTCUTS_ENABLED) {
1034
+ if (!getStudioKeyboardShortcutsEnabled()) {
999
1035
  console.warn("Keyboard shortcuts disabled either due to: a) --disable-keyboard-shortcuts being passed b) Config.setKeyboardShortcutsEnabled(false) being set or c) a Remotion version mismatch.");
1000
1036
  }
1001
1037
  var areKeyboardShortcutsDisabled = () => {
1002
- return !process.env.KEYBOARD_SHORTCUTS_ENABLED;
1038
+ return !getStudioKeyboardShortcutsEnabled();
1003
1039
  };
1004
1040
  var useKeybinding = () => {
1005
1041
  const [paneId] = useState3(() => String(Math.random()));
1006
1042
  const context = useContext4(KeybindingContext);
1007
1043
  const { isHighestContext } = useZIndex();
1008
1044
  const registerKeybinding = useCallback4((options) => {
1009
- if (!process.env.KEYBOARD_SHORTCUTS_ENABLED) {
1045
+ if (!getStudioKeyboardShortcutsEnabled()) {
1010
1046
  return {
1011
1047
  unregister: () => {
1012
1048
  return;
@@ -2042,7 +2078,7 @@ var PreviewServerConnection = ({ children, readOnlyStudio }) => {
2042
2078
  };
2043
2079
 
2044
2080
  // src/helpers/show-browser-rendering.ts
2045
- var SHOW_BROWSER_RENDERING = Boolean(process.env.EXPERIMENTAL_CLIENT_SIDE_RENDERING_ENABLED);
2081
+ var SHOW_BROWSER_RENDERING = getStudioExperimentalClientSideRenderingEnabled();
2046
2082
 
2047
2083
  // src/helpers/timeline-node-path-key.ts
2048
2084
  import { stringifySequenceExpandedRowKey } from "@remotion/studio-shared";
@@ -3787,7 +3823,7 @@ var MenuContent = ({
3787
3823
  return containerStyles;
3788
3824
  }, [fixedHeight, isMobileLayout]);
3789
3825
  useEffect11(() => {
3790
- if (!keybindings.isHighestContext || !process.env.KEYBOARD_SHORTCUTS_ENABLED) {
3826
+ if (!keybindings.isHighestContext || !getStudioKeyboardShortcutsEnabled()) {
3791
3827
  return;
3792
3828
  }
3793
3829
  const onKeyDown = (event) => {
@@ -6142,6 +6178,9 @@ import {
6142
6178
  Internals as Internals19
6143
6179
  } from "remotion";
6144
6180
 
6181
+ // src/helpers/interactivity-enabled.ts
6182
+ var studioInteractivityEnabled = getStudioInteractivityEnabled();
6183
+
6145
6184
  // src/components/ExpandedTracksProvider.tsx
6146
6185
  import { createContext as createContext13, useCallback as useCallback24, useMemo as useMemo24, useState as useState20 } from "react";
6147
6186
 
@@ -9539,7 +9578,7 @@ var TimelineSelectionProvider = ({ children }) => {
9539
9578
  const { canvasContent } = useContext18(Internals19.CompositionManager);
9540
9579
  const timelineSelectionScope = canvasContent?.type === "composition" ? canvasContent.compositionId : null;
9541
9580
  const { expandParentTracks } = useContext18(ExpandedTracksSetterContext);
9542
- const canSelect = previewServerState.type === "connected" && !window.remotion_isReadOnlyStudio;
9581
+ const canSelect = studioInteractivityEnabled && previewServerState.type === "connected" && !window.remotion_isReadOnlyStudio;
9543
9582
  const [selectedItems, setSelectedItems] = useState21([]);
9544
9583
  const selectionAnchor = useRef16(null);
9545
9584
  const selectionScope = useRef16(null);
@@ -10141,7 +10180,7 @@ var GlobalKeybindings = ({ readOnlyStudio }) => {
10141
10180
  commandCtrlKey: true,
10142
10181
  preventDefault: true
10143
10182
  });
10144
- const cmdIKey = process.env.ASK_AI_ENABLED ? keybindings.registerKeybinding({
10183
+ const cmdIKey = getStudioAskAIEnabled() ? keybindings.registerKeybinding({
10145
10184
  event: "keydown",
10146
10185
  key: "i",
10147
10186
  callback: () => {
@@ -11766,7 +11805,7 @@ var useMenuStructure = (closeMenu, readOnlyStudio) => {
11766
11805
  label: "Tools",
11767
11806
  leaveLeftPadding: false,
11768
11807
  items: [
11769
- process.env.ASK_AI_ENABLED ? {
11808
+ getStudioAskAIEnabled() ? {
11770
11809
  id: "ask-ai",
11771
11810
  value: "ask-ai",
11772
11811
  label: "Ask AI",
@@ -13951,12 +13990,12 @@ var ErrorLoader = ({
13951
13990
  // src/components/Canvas.tsx
13952
13991
  import {
13953
13992
  ASSET_DRAG_MIME_TYPE as ASSET_DRAG_MIME_TYPE2,
13954
- COMPOSITION_DRAG_MIME_TYPE as COMPOSITION_DRAG_MIME_TYPE4,
13955
13993
  COMPONENT_DRAG_MIME_TYPE as COMPONENT_DRAG_MIME_TYPE2,
13994
+ COMPOSITION_DRAG_MIME_TYPE as COMPOSITION_DRAG_MIME_TYPE4,
13956
13995
  ELEMENT_DRAG_MIME_TYPE as ELEMENT_DRAG_MIME_TYPE3,
13957
13996
  parseAssetDragData,
13958
- parseCompositionDragData as parseCompositionDragData3,
13959
13997
  parseComponentDragData,
13998
+ parseCompositionDragData as parseCompositionDragData3,
13960
13999
  parseSfxDragData,
13961
14000
  SFX_DRAG_MIME_TYPE as SFX_DRAG_MIME_TYPE2
13962
14001
  } from "@remotion/studio-shared";
@@ -23436,7 +23475,7 @@ var SelectedOutlineOverlay = ({
23436
23475
  selectItem(item, interaction, undefined, { reveal: true });
23437
23476
  }, [selectItem]);
23438
23477
  const outlineTargets = useMemo56(() => {
23439
- if (!editorShowOutlines) {
23478
+ if (!studioInteractivityEnabled || !editorShowOutlines) {
23440
23479
  return [];
23441
23480
  }
23442
23481
  const selectedSequenceKeys = getSelectedSequenceKeys(selectedItems);
@@ -24246,6 +24285,31 @@ var ResetZoomButton = ({ onClick }) => {
24246
24285
 
24247
24286
  // src/components/Canvas.tsx
24248
24287
  import { jsx as jsx94, jsxs as jsxs43, Fragment as Fragment19 } from "react/jsx-runtime";
24288
+ var elementInstallCompositionIdStyle = {
24289
+ fontFamily: "monospace",
24290
+ fontSize: 13
24291
+ };
24292
+ var elementInstallCodeDetailsStyle = {
24293
+ marginTop: 12,
24294
+ fontSize: 13
24295
+ };
24296
+ var elementInstallCodeSummaryStyle = {
24297
+ cursor: "pointer",
24298
+ fontSize: 13,
24299
+ fontWeight: 500
24300
+ };
24301
+ var elementInstallCodeBlockStyle = {
24302
+ marginTop: 8,
24303
+ marginBottom: 0,
24304
+ maxHeight: 240,
24305
+ overflow: "auto",
24306
+ padding: 12,
24307
+ borderRadius: 6,
24308
+ backgroundColor: "rgba(255, 255, 255, 0.06)",
24309
+ fontSize: 12,
24310
+ lineHeight: 1.5,
24311
+ whiteSpace: "pre"
24312
+ };
24249
24313
  var getContainerStyle = (editorZoomGestures) => ({
24250
24314
  flex: 1,
24251
24315
  display: "flex",
@@ -24380,12 +24444,18 @@ var Canvas = ({ canvasContent, size: size2 }) => {
24380
24444
  const suppressWheelFromWebKitPinchRef = useRef32(false);
24381
24445
  const touchPinchRef = useRef32(null);
24382
24446
  const keybindings = useKeybinding();
24447
+ const confirm = useConfirmationDialog();
24383
24448
  const config = Internals40.useUnsafeVideoConfig();
24384
24449
  const areRulersVisible = useIsRulerVisible();
24385
24450
  const { editorShowGuides } = useContext38(EditorShowGuidesContext);
24386
24451
  const { compositions } = useContext38(Internals40.CompositionManager);
24387
- const { previewServerState } = useContext38(StudioServerConnectionCtx);
24452
+ const { previewServerState, subscribeToEvent } = useContext38(StudioServerConnectionCtx);
24453
+ const previewServerClientId = previewServerState.type === "connected" ? previewServerState.clientId : null;
24388
24454
  const [isAddingAsset, setIsAddingAsset] = useState42(false);
24455
+ const [installingElementName, setInstallingElementName] = useState42(null);
24456
+ const [pendingElementInstallRequests, setPendingElementInstallRequests] = useState42([]);
24457
+ const [activeElementInstallRequest, setActiveElementInstallRequest] = useState42(null);
24458
+ const lastFocusedAtRef = useRef32(typeof document === "undefined" || document.hasFocus() ? Date.now() : null);
24389
24459
  const [assetResolution, setAssetResolution] = useState42(null);
24390
24460
  const currentCompositionId = canvasContent.type === "composition" ? canvasContent.compositionId : null;
24391
24461
  const currentComposition = useMemo58(() => {
@@ -24400,7 +24470,8 @@ var Canvas = ({ canvasContent, size: size2 }) => {
24400
24470
  compositionFile,
24401
24471
  compositionId: currentCompositionId
24402
24472
  });
24403
- const canDropAssets = previewServerState.type === "connected" && !window.remotion_isReadOnlyStudio && compositionComponentInfo?.canAddSequence === true && currentCompositionId !== null && compositionFile !== null && !isAddingAsset;
24473
+ const canInstallElements = previewServerClientId !== null && !window.remotion_isReadOnlyStudio && compositionComponentInfo?.canAddSequence === true && currentCompositionId !== null && compositionFile !== null;
24474
+ const canDropAssets = canInstallElements && !isAddingAsset;
24404
24475
  const contentDimensions = useMemo58(() => {
24405
24476
  if ((canvasContent.type === "asset" || canvasContent.type === "output" || canvasContent.type === "output-blob") && assetResolution && assetResolution.type === "found") {
24406
24477
  return assetResolution.dimensions;
@@ -24756,6 +24827,146 @@ var Canvas = ({ canvasContent, size: size2 }) => {
24756
24827
  useEffect42(() => {
24757
24828
  fetchMetadata();
24758
24829
  }, [fetchMetadata]);
24830
+ const updateElementInstallTarget = useCallback51((requestId) => {
24831
+ if (previewServerClientId === null) {
24832
+ return;
24833
+ }
24834
+ callApi("/api/update-element-install-target", {
24835
+ requestId,
24836
+ clientId: previewServerClientId,
24837
+ compositionFile: canInstallElements ? compositionFile : null,
24838
+ compositionId: canInstallElements ? currentCompositionId : null,
24839
+ canInstall: canInstallElements,
24840
+ lastFocusedAt: lastFocusedAtRef.current,
24841
+ readOnly: window.remotion_isReadOnlyStudio
24842
+ }).catch(() => {
24843
+ return;
24844
+ });
24845
+ }, [
24846
+ canInstallElements,
24847
+ compositionFile,
24848
+ currentCompositionId,
24849
+ previewServerClientId
24850
+ ]);
24851
+ useEffect42(() => {
24852
+ const markFocused = () => {
24853
+ lastFocusedAtRef.current = Date.now();
24854
+ };
24855
+ window.addEventListener("focus", markFocused);
24856
+ document.addEventListener("pointerdown", markFocused, { capture: true });
24857
+ return () => {
24858
+ window.removeEventListener("focus", markFocused);
24859
+ document.removeEventListener("pointerdown", markFocused, { capture: true });
24860
+ };
24861
+ }, []);
24862
+ useEffect42(() => {
24863
+ return subscribeToEvent("request-element-install-target", (event) => {
24864
+ if (event.type !== "request-element-install-target") {
24865
+ return;
24866
+ }
24867
+ updateElementInstallTarget(event.requestId);
24868
+ });
24869
+ }, [subscribeToEvent, updateElementInstallTarget]);
24870
+ useEffect42(() => {
24871
+ if (installingElementName === null) {
24872
+ return;
24873
+ }
24874
+ const previousTitle = document.title;
24875
+ document.title = `\uD83D\uDCE6 Install ${installingElementName} - Remotion Studio`;
24876
+ return () => {
24877
+ document.title = previousTitle;
24878
+ };
24879
+ }, [installingElementName]);
24880
+ useEffect42(() => {
24881
+ if (previewServerClientId === null) {
24882
+ return;
24883
+ }
24884
+ return subscribeToEvent("element-install-request", (event) => {
24885
+ if (event.type !== "element-install-request" || event.request.clientId !== previewServerClientId) {
24886
+ return;
24887
+ }
24888
+ setPendingElementInstallRequests((requests) => [
24889
+ ...requests,
24890
+ event.request
24891
+ ]);
24892
+ });
24893
+ }, [previewServerClientId, subscribeToEvent]);
24894
+ useEffect42(() => {
24895
+ if (activeElementInstallRequest !== null || pendingElementInstallRequests.length === 0) {
24896
+ return;
24897
+ }
24898
+ const [nextRequest, ...remainingRequests] = pendingElementInstallRequests;
24899
+ if (!nextRequest) {
24900
+ throw new Error("Expected pending Element install request");
24901
+ }
24902
+ setActiveElementInstallRequest(nextRequest);
24903
+ setPendingElementInstallRequests(remainingRequests);
24904
+ }, [activeElementInstallRequest, pendingElementInstallRequests]);
24905
+ useEffect42(() => {
24906
+ if (activeElementInstallRequest === null) {
24907
+ return;
24908
+ }
24909
+ let canceled = false;
24910
+ const handleInstallRequest = async () => {
24911
+ setInstallingElementName(activeElementInstallRequest.element.displayName);
24912
+ const accepted = await confirm({
24913
+ title: "Install Element",
24914
+ message: /* @__PURE__ */ jsxs43(Fragment19, {
24915
+ children: [
24916
+ "Install “",
24917
+ activeElementInstallRequest.element.displayName,
24918
+ "” into",
24919
+ " ",
24920
+ /* @__PURE__ */ jsx94("code", {
24921
+ style: elementInstallCompositionIdStyle,
24922
+ children: activeElementInstallRequest.compositionId
24923
+ }),
24924
+ " ",
24925
+ "composition? This will create an Element source file and update the composition source.",
24926
+ /* @__PURE__ */ jsxs43("details", {
24927
+ style: elementInstallCodeDetailsStyle,
24928
+ children: [
24929
+ /* @__PURE__ */ jsx94("summary", {
24930
+ style: elementInstallCodeSummaryStyle,
24931
+ children: "Preview Element source"
24932
+ }),
24933
+ /* @__PURE__ */ jsx94("pre", {
24934
+ style: elementInstallCodeBlockStyle,
24935
+ children: /* @__PURE__ */ jsx94("code", {
24936
+ children: activeElementInstallRequest.element.sourceCode
24937
+ })
24938
+ })
24939
+ ]
24940
+ })
24941
+ ]
24942
+ }),
24943
+ confirmLabel: "Install",
24944
+ cancelLabel: "Cancel"
24945
+ });
24946
+ if (accepted && !canceled) {
24947
+ await insertElement({
24948
+ element: activeElementInstallRequest.element,
24949
+ compositionFile: activeElementInstallRequest.compositionFile,
24950
+ compositionId: activeElementInstallRequest.compositionId,
24951
+ dropPosition: null
24952
+ });
24953
+ }
24954
+ };
24955
+ handleInstallRequest().finally(() => {
24956
+ if (canceled) {
24957
+ return;
24958
+ }
24959
+ setInstallingElementName(null);
24960
+ setActiveElementInstallRequest(null);
24961
+ }).catch((err) => {
24962
+ setTimeout(() => {
24963
+ throw err;
24964
+ }, 0);
24965
+ });
24966
+ return () => {
24967
+ canceled = true;
24968
+ };
24969
+ }, [activeElementInstallRequest, confirm]);
24759
24970
  const onDragOver = useCallback51((event) => {
24760
24971
  if (!canDropAssets || !isFileDragEvent(event) && !isAssetDragEvent(event) && !isCompositionDragEvent(event) && !isComponentDragEvent(event) && !isElementDragEvent(event) && !isSfxDragEvent(event) && !isRemoteAssetDragEvent(event) || !isDragEventInsideCanvas(event)) {
24761
24972
  return;
@@ -26960,6 +27171,9 @@ var VisualControlsProvider = ({ children }) => {
26960
27171
  if (!env.isStudio) {
26961
27172
  return value;
26962
27173
  }
27174
+ if (!studioInteractivityEnabled) {
27175
+ return value;
27176
+ }
26963
27177
  if (!z) {
26964
27178
  return value;
26965
27179
  }
@@ -33350,7 +33564,7 @@ var DefaultInspector = ({ composition, currentDefaultProps, readOnlyStudio, setD
33350
33564
  const { handles: visualControlHandles } = useContext56(VisualControlsContext);
33351
33565
  const [defaultPropsMode, setDefaultPropsMode] = useState68("schema");
33352
33566
  const compositionId = composition?.id ?? null;
33353
- const hasVisualControls = Object.keys(visualControlHandles).length > 0;
33567
+ const hasVisualControls = studioInteractivityEnabled && Object.keys(visualControlHandles).length > 0;
33354
33568
  useEffect60(() => {
33355
33569
  setDefaultPropsMode("schema");
33356
33570
  }, [compositionId]);
@@ -47590,9 +47804,8 @@ import React207, { useCallback as useCallback166, useContext as useContext120, u
47590
47804
  import { Internals as Internals98 } from "remotion";
47591
47805
 
47592
47806
  // src/components/Timeline/MaxTimelineTracks.tsx
47593
- import { DEFAULT_TIMELINE_TRACKS } from "@remotion/studio-shared";
47594
47807
  import { jsxs as jsxs128 } from "react/jsx-runtime";
47595
- var MAX_TIMELINE_TRACKS = typeof process.env.MAX_TIMELINE_TRACKS === "undefined" || process.env.MAX_TIMELINE_TRACKS === null ? DEFAULT_TIMELINE_TRACKS : Number(process.env.MAX_TIMELINE_TRACKS);
47808
+ var MAX_TIMELINE_TRACKS = getStudioMaxTimelineTracks();
47596
47809
  var MAX_TIMELINE_TRACKS_NOTICE_HEIGHT = 24;
47597
47810
  var container39 = {
47598
47811
  height: MAX_TIMELINE_TRACKS_NOTICE_HEIGHT,
@@ -48188,7 +48401,7 @@ var TimelineDragHandler = () => {
48188
48401
  ref: sliderAreaRef,
48189
48402
  style: containerStyle9,
48190
48403
  ...{ [TIMELINE_SCRUBBER_ATTR]: true },
48191
- children: video ? /* @__PURE__ */ jsx258(TimelineDragHandlerInnerMemo, {}) : null
48404
+ children: video && studioInteractivityEnabled ? /* @__PURE__ */ jsx258(TimelineDragHandlerInnerMemo, {}) : null
48192
48405
  });
48193
48406
  };
48194
48407
  var TimelineDragHandlerInner = () => {
@@ -49255,6 +49468,7 @@ var TimelineSequenceItem = ({
49255
49468
  const nodePath = nodePathInfo?.sequenceSubscriptionKey ?? null;
49256
49469
  const { previewServerState } = useContext111(StudioServerConnectionCtx);
49257
49470
  const previewConnected = previewServerState.type === "connected";
49471
+ const previewInteractive = previewConnected && studioInteractivityEnabled;
49258
49472
  const { getIsExpanded } = useContext111(ExpandedTracksGetterContext);
49259
49473
  const { toggleTrack } = useContext111(ExpandedTracksSetterContext);
49260
49474
  const { setPropStatuses } = useContext111(Internals91.VisualModeSettersContext);
@@ -49291,7 +49505,7 @@ var TimelineSequenceItem = ({
49291
49505
  propStatusesForOverride,
49292
49506
  saveName
49293
49507
  } = useRenameSequence({
49294
- clientId: previewServerState.type === "connected" ? previewServerState.clientId : null,
49508
+ clientId: previewInteractive && previewServerState.type === "connected" ? previewServerState.clientId : null,
49295
49509
  nodePathInfo,
49296
49510
  sequence,
49297
49511
  validatedLocation
@@ -49299,22 +49513,22 @@ var TimelineSequenceItem = ({
49299
49513
  const canDeleteFromSource = Boolean(nodePath && validatedLocation?.source);
49300
49514
  const nodePathKey = useMemo170(() => nodePath ? Internals91.makeSequencePropsSubscriptionKey(nodePath) : null, [nodePath]);
49301
49515
  const parentId = sequence.parent ?? null;
49302
- const canReorderSequence = previewConnected && Boolean(nodePath && nodePathKey && validatedLocation?.source) && nodePathInfo?.numberOfSequencesWithThisNodePath === 1;
49303
- const canHandleSequenceDrag = previewConnected;
49516
+ const canReorderSequence = previewInteractive && Boolean(nodePath && nodePathKey && validatedLocation?.source) && nodePathInfo?.numberOfSequencesWithThisNodePath === 1;
49517
+ const canHandleSequenceDrag = previewInteractive;
49304
49518
  const confirm = useConfirmationDialog();
49305
- const deleteDisabled = useMemo170(() => !previewConnected || !sequence.controls || !canDeleteFromSource, [previewConnected, sequence.controls, canDeleteFromSource]);
49519
+ const deleteDisabled = useMemo170(() => !previewInteractive || !sequence.controls || !canDeleteFromSource, [previewInteractive, sequence.controls, canDeleteFromSource]);
49306
49520
  const duplicateDisabled = deleteDisabled;
49307
- const disableInteractivityDisabled = !previewConnected || !sequence.showInTimeline || !nodePath || !validatedLocation?.source;
49521
+ const disableInteractivityDisabled = !previewInteractive || !sequence.showInTimeline || !nodePath || !validatedLocation?.source;
49308
49522
  const onDuplicateSequenceFromSource = useCallback162(() => {
49309
- if (!validatedLocation?.source || !nodePathInfo) {
49523
+ if (duplicateDisabled || !validatedLocation?.source || !nodePathInfo) {
49310
49524
  return;
49311
49525
  }
49312
49526
  duplicateSequencesFromSource([nodePathInfo], confirm).catch(() => {
49313
49527
  return;
49314
49528
  });
49315
- }, [confirm, nodePathInfo, validatedLocation?.source]);
49529
+ }, [confirm, duplicateDisabled, nodePathInfo, validatedLocation?.source]);
49316
49530
  const onDeleteSequenceFromSource = useCallback162(async () => {
49317
- if (!validatedLocation?.source || !nodePath) {
49531
+ if (deleteDisabled || !validatedLocation?.source || !nodePath) {
49318
49532
  return;
49319
49533
  }
49320
49534
  if (nodePathInfo && nodePathInfo.numberOfSequencesWithThisNodePath > 1) {
@@ -49344,7 +49558,13 @@ var TimelineSequenceItem = ({
49344
49558
  } catch (err) {
49345
49559
  showNotification(err.message, 4000);
49346
49560
  }
49347
- }, [confirm, nodePath, validatedLocation?.source, nodePathInfo]);
49561
+ }, [
49562
+ confirm,
49563
+ deleteDisabled,
49564
+ nodePath,
49565
+ validatedLocation?.source,
49566
+ nodePathInfo
49567
+ ]);
49348
49568
  const onDisableSequenceInteractivity = useCallback162(() => {
49349
49569
  if (disableInteractivityDisabled || !nodePath || !validatedLocation?.source || previewServerState.type !== "connected") {
49350
49570
  return;
@@ -49579,8 +49799,8 @@ var TimelineSequenceItem = ({
49579
49799
  ...effectDropHighlight
49580
49800
  } : inner2;
49581
49801
  }, [effectDropHovered, inner2]);
49582
- const hasExpandableContent = Boolean(sequence.controls) || sequence.effects.length > 0;
49583
- const canToggleVisibility = previewConnected && Boolean(sequence.controls) && nodePath !== null && validatedLocation !== null && codeHiddenStatus !== undefined && codeHiddenStatus !== null && codeHiddenStatus.status === "static";
49802
+ const hasExpandableContent = studioInteractivityEnabled && (Boolean(sequence.controls) || sequence.effects.length > 0);
49803
+ const canToggleVisibility = previewInteractive && Boolean(sequence.controls) && nodePath !== null && validatedLocation !== null && codeHiddenStatus !== undefined && codeHiddenStatus !== null && codeHiddenStatus.status === "static";
49584
49804
  const onSequenceDoubleClick = useCallback162((e) => {
49585
49805
  if (isTimelineSelectionModifierEvent(e)) {
49586
49806
  e.stopPropagation();
@@ -49602,7 +49822,7 @@ var TimelineSequenceItem = ({
49602
49822
  await saveName(name);
49603
49823
  }, [saveName]);
49604
49824
  React194.useEffect(() => {
49605
- if (!canRenameSelectedSequence || !process.env.KEYBOARD_SHORTCUTS_ENABLED) {
49825
+ if (!canRenameSelectedSequence || !getStudioKeyboardShortcutsEnabled()) {
49606
49826
  setIsRenaming(false);
49607
49827
  return;
49608
49828
  }
@@ -49633,7 +49853,7 @@ var TimelineSequenceItem = ({
49633
49853
  setIsRenaming(true);
49634
49854
  }, [canRenameThisSequence]);
49635
49855
  const freezeFrameMenuItem = useSequenceFreezeFrameMenuItem({
49636
- clientId: previewServerState.type === "connected" ? previewServerState.clientId : null,
49856
+ clientId: previewInteractive && previewServerState.type === "connected" ? previewServerState.clientId : null,
49637
49857
  nodePath,
49638
49858
  propStatusesForOverride,
49639
49859
  sequence,
@@ -49642,7 +49862,7 @@ var TimelineSequenceItem = ({
49642
49862
  timelinePosition,
49643
49863
  validatedSource: validatedLocation?.source ?? null
49644
49864
  });
49645
- const canAddEffect = nodePathInfo?.supportsEffects === true && previewServerState.type === "connected" && Boolean(validatedLocation?.source);
49865
+ const canAddEffect = nodePathInfo?.supportsEffects === true && previewInteractive && Boolean(validatedLocation?.source);
49646
49866
  const onAddEffect = useCallback162(() => {
49647
49867
  if (!canAddEffect || previewServerState.type !== "connected" || !nodePath || !validatedLocation?.source) {
49648
49868
  return;
@@ -49671,7 +49891,7 @@ var TimelineSequenceItem = ({
49671
49891
  disableInteractivityDisabled,
49672
49892
  duplicateDisabled,
49673
49893
  fileLocation,
49674
- includeSourceEditItems: true,
49894
+ includeSourceEditItems: studioInteractivityEnabled,
49675
49895
  onDeleteSequenceFromSource,
49676
49896
  onDisableSequenceInteractivity,
49677
49897
  onDuplicateSequenceFromSource,
@@ -49679,7 +49899,7 @@ var TimelineSequenceItem = ({
49679
49899
  originalLocation,
49680
49900
  selectAsset,
49681
49901
  sequence,
49682
- sourceActions: [
49902
+ sourceActions: studioInteractivityEnabled ? [
49683
49903
  ...nodePathInfo?.supportsEffects ? [
49684
49904
  {
49685
49905
  type: "item",
@@ -49713,7 +49933,7 @@ var TimelineSequenceItem = ({
49713
49933
  value: "rename-sequence"
49714
49934
  },
49715
49935
  ...freezeFrameMenuItem ? [freezeFrameMenuItem] : []
49716
- ]
49936
+ ] : []
49717
49937
  });
49718
49938
  }, [
49719
49939
  assetLinkInfo,
@@ -49737,7 +49957,7 @@ var TimelineSequenceItem = ({
49737
49957
  selectAsset,
49738
49958
  sequence
49739
49959
  ]);
49740
- const canDropEffect = previewServerState.type === "connected" && nodePath !== null && validatedLocation !== null && sequence.controls?.supportsEffects === true;
49960
+ const canDropEffect = previewInteractive && nodePath !== null && validatedLocation !== null && sequence.controls?.supportsEffects === true;
49741
49961
  const sequenceReorderLineStyle = useMemo170(() => {
49742
49962
  if (!sequenceDropIndicator) {
49743
49963
  return null;
@@ -49793,7 +50013,7 @@ var TimelineSequenceItem = ({
49793
50013
  onInvoked: onToggleVisibility
49794
50014
  }) : /* @__PURE__ */ jsx266(TimelineLayerEyeSpacer, {}),
49795
50015
  arrow: hasExpandableContent && nodePathInfo !== null ? /* @__PURE__ */ jsx266(TimelineSequenceExpandArrow, {
49796
- disabled: !previewConnected,
50016
+ disabled: !previewInteractive,
49797
50017
  isExpanded,
49798
50018
  nodePathInfo,
49799
50019
  onToggleExpand,
@@ -49863,7 +50083,7 @@ var TimelineSequenceItem = ({
49863
50083
  onOpen: selectable ? onSelect : null,
49864
50084
  children: draggableTrackRow
49865
50085
  }) : draggableTrackRow,
49866
- previewConnected && isExpanded && hasExpandableContent && nodePathInfo && validatedLocation ? /* @__PURE__ */ jsx266(TimelineExpandedSection, {
50086
+ previewConnected && studioInteractivityEnabled && isExpanded && hasExpandableContent && nodePathInfo && validatedLocation ? /* @__PURE__ */ jsx266(TimelineExpandedSection, {
49867
50087
  sequence,
49868
50088
  validatedLocation,
49869
50089
  nodePathInfo,
@@ -52612,11 +52832,12 @@ var TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffset
52612
52832
  const propStatusesForOverride = useMemo176(() => {
52613
52833
  return nodePath ? Internals97.getPropStatusesCtx(propStatuses, nodePath) : undefined;
52614
52834
  }, [propStatuses, nodePath]);
52615
- const durationCanUpdate = Boolean(propStatusesForOverride?.durationInFrames?.status === "static");
52616
- const fromCanUpdate = Boolean(propStatusesForOverride?.from?.status === "static");
52617
- const trimBeforeCanUpdate = Boolean(propStatusesForOverride?.trimBefore?.status === "static");
52835
+ const durationCanUpdate = Boolean(studioInteractivityEnabled && propStatusesForOverride?.durationInFrames?.status === "static");
52836
+ const fromCanUpdate = Boolean(studioInteractivityEnabled && propStatusesForOverride?.from?.status === "static");
52837
+ const trimBeforeCanUpdate = Boolean(studioInteractivityEnabled && propStatusesForOverride?.trimBefore?.status === "static");
52618
52838
  const { previewServerState } = useContext118(StudioServerConnectionCtx);
52619
52839
  const previewConnected = previewServerState.type === "connected";
52840
+ const previewInteractive = previewConnected && studioInteractivityEnabled;
52620
52841
  const { setPropStatuses } = useContext118(Internals97.VisualModeSettersContext);
52621
52842
  const timelinePosition = Internals97.Timeline.useTimelinePosition();
52622
52843
  const selectAsset = useSelectAsset();
@@ -52636,9 +52857,9 @@ var TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffset
52636
52857
  });
52637
52858
  }, [canOpenInEditor, originalLocation]);
52638
52859
  const canDeleteFromSource = Boolean(nodePath && validatedLocation?.source);
52639
- const deleteDisabled = !previewConnected || !s.controls || !canDeleteFromSource;
52860
+ const deleteDisabled = !previewInteractive || !s.controls || !canDeleteFromSource;
52640
52861
  const duplicateDisabled = deleteDisabled;
52641
- const disableInteractivityDisabled = !previewConnected || !s.showInTimeline || !nodePath || !validatedLocation?.source;
52862
+ const disableInteractivityDisabled = !previewInteractive || !s.showInTimeline || !nodePath || !validatedLocation?.source;
52642
52863
  const mediaSrc = s.type === "audio" || s.type === "video" || s.type === "image" ? s.src : null;
52643
52864
  const assetLinkInfo = useMemo176(() => mediaSrc ? getTimelineAssetLinkInfo(mediaSrc) : null, [mediaSrc]);
52644
52865
  const onDuplicateSequenceFromSource = useCallback165(() => {
@@ -52705,7 +52926,7 @@ var TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffset
52705
52926
  validatedLocation?.source
52706
52927
  ]);
52707
52928
  const freezeFrameMenuItem = useSequenceFreezeFrameMenuItem({
52708
- clientId: previewServerState.type === "connected" ? previewServerState.clientId : null,
52929
+ clientId: previewInteractive && previewServerState.type === "connected" ? previewServerState.clientId : null,
52709
52930
  nodePath,
52710
52931
  propStatusesForOverride,
52711
52932
  sequence: s,
@@ -52725,7 +52946,7 @@ var TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffset
52725
52946
  disableInteractivityDisabled,
52726
52947
  duplicateDisabled,
52727
52948
  fileLocation,
52728
- includeSourceEditItems: true,
52949
+ includeSourceEditItems: studioInteractivityEnabled,
52729
52950
  onDeleteSequenceFromSource,
52730
52951
  onDisableSequenceInteractivity,
52731
52952
  onDuplicateSequenceFromSource,
@@ -52733,7 +52954,7 @@ var TimelineSequenceInner = ({ s, windowWidth, nodePathInfo, sequenceFrameOffset
52733
52954
  originalLocation,
52734
52955
  selectAsset,
52735
52956
  sequence: s,
52736
- sourceActions: freezeFrameMenuItem ? [freezeFrameMenuItem] : []
52957
+ sourceActions: studioInteractivityEnabled && freezeFrameMenuItem ? [freezeFrameMenuItem] : []
52737
52958
  });
52738
52959
  }, [
52739
52960
  assetLinkInfo,
@@ -52960,6 +53181,7 @@ var TimelineContextMenuArea = ({ children }) => {
52960
53181
  const [isAddingAsset, setIsAddingAsset] = useState99(false);
52961
53182
  const { previewServerState } = useContext120(StudioServerConnectionCtx);
52962
53183
  const previewConnected = previewServerState.type === "connected";
53184
+ const previewInteractive = previewConnected && studioInteractivityEnabled;
52963
53185
  const currentCompositionId = canvasContent?.type === "composition" ? canvasContent.compositionId : null;
52964
53186
  const currentComposition = useMemo179(() => {
52965
53187
  if (currentCompositionId === null) {
@@ -52973,8 +53195,8 @@ var TimelineContextMenuArea = ({ children }) => {
52973
53195
  compositionFile,
52974
53196
  compositionId: currentCompositionId
52975
53197
  });
52976
- const canInsertSolid = previewConnected && compositionComponentInfo?.canAddSequence === true && currentCompositionId !== null && compositionFile !== null && videoConfig !== null && !isAddingSolid;
52977
- const canInsertAsset = previewConnected && !window.remotion_isReadOnlyStudio && compositionComponentInfo?.canAddSequence === true && currentCompositionId !== null && compositionFile !== null && !isAddingAsset;
53198
+ const canInsertSolid = previewInteractive && compositionComponentInfo?.canAddSequence === true && currentCompositionId !== null && compositionFile !== null && videoConfig !== null && !isAddingSolid;
53199
+ const canInsertAsset = previewInteractive && !window.remotion_isReadOnlyStudio && compositionComponentInfo?.canAddSequence === true && currentCompositionId !== null && compositionFile !== null && !isAddingAsset;
52978
53200
  const insertSolid = useCallback166(async () => {
52979
53201
  if (!canInsertSolid || currentCompositionId === null || compositionFile === null || videoConfig === null) {
52980
53202
  return;
@@ -53066,6 +53288,7 @@ var TimelineInner = () => {
53066
53288
  const { overrideIdToNodePathMappings } = useContext120(Internals98.OverrideIdsToNodePathsGettersContext);
53067
53289
  const { previewServerState } = useContext120(StudioServerConnectionCtx);
53068
53290
  const previewConnected = previewServerState.type === "connected";
53291
+ const previewInteractive = previewConnected && studioInteractivityEnabled;
53069
53292
  const videoConfigIsNull = videoConfig === null;
53070
53293
  const timeline = useMemo179(() => {
53071
53294
  if (videoConfigIsNull) {
@@ -53087,7 +53310,7 @@ var TimelineInner = () => {
53087
53310
  return /* @__PURE__ */ jsxs146(TimelineContextMenuArea, {
53088
53311
  children: [
53089
53312
  sequences.map((sequence) => {
53090
- if (!shouldSubscribeToSequenceProps(sequence, previewConnected)) {
53313
+ if (!shouldSubscribeToSequenceProps(sequence, previewInteractive)) {
53091
53314
  return null;
53092
53315
  }
53093
53316
  return /* @__PURE__ */ jsx282(SubscribeToNodePaths, {
@@ -53098,15 +53321,15 @@ var TimelineInner = () => {
53098
53321
  effects: sequence.effects
53099
53322
  }, sequence.id);
53100
53323
  }),
53101
- /* @__PURE__ */ jsx282(SequencePropsObserver, {}),
53324
+ studioInteractivityEnabled ? /* @__PURE__ */ jsx282(SequencePropsObserver, {}) : null,
53102
53325
  /* @__PURE__ */ jsx282(TimelineKeyframeTracksProvider, {
53103
53326
  tracks: filtered,
53104
53327
  children: /* @__PURE__ */ jsxs146(TimelineSelectableItemsProvider, {
53105
53328
  timeline: shown,
53106
53329
  children: [
53107
- /* @__PURE__ */ jsx282(TimelineSelectAllKeybindings, {
53330
+ studioInteractivityEnabled ? /* @__PURE__ */ jsx282(TimelineSelectAllKeybindings, {
53108
53331
  timeline: shown
53109
- }),
53332
+ }) : null,
53110
53333
  /* @__PURE__ */ jsx282(TimelineHeightContainer, {
53111
53334
  shown,
53112
53335
  hasBeenCut,
@@ -53146,7 +53369,7 @@ var TimelineInner = () => {
53146
53369
  /* @__PURE__ */ jsx282(TimelineInOutPointer, {}),
53147
53370
  /* @__PURE__ */ jsx282(TimelineTimeIndicators, {}),
53148
53371
  /* @__PURE__ */ jsx282(TimelineDragHandler, {}),
53149
- /* @__PURE__ */ jsx282(TimelineInOutDragHandler, {}),
53372
+ studioInteractivityEnabled ? /* @__PURE__ */ jsx282(TimelineInOutDragHandler, {}) : null,
53150
53373
  /* @__PURE__ */ jsx282(TimelineSlider, {})
53151
53374
  ]
53152
53375
  })
@@ -56872,7 +57095,7 @@ var KeyboardShortcutsExplainer = () => {
56872
57095
  })
56873
57096
  ]
56874
57097
  }),
56875
- process.env.ASK_AI_ENABLED && /* @__PURE__ */ jsxs164(Fragment57, {
57098
+ getStudioAskAIEnabled() && /* @__PURE__ */ jsxs164(Fragment57, {
56876
57099
  children: [
56877
57100
  /* @__PURE__ */ jsx304("br", {}),
56878
57101
  /* @__PURE__ */ jsx304("div", {
@@ -65451,7 +65674,7 @@ var Modals = ({ readOnlyStudio }) => {
65451
65674
  modalContextType && modalContextType.type === "confirmation-dialog" && /* @__PURE__ */ jsx360(ConfirmationDialog, {
65452
65675
  state: modalContextType
65453
65676
  }),
65454
- process.env.ASK_AI_ENABLED && /* @__PURE__ */ jsx360(AskAiModal, {})
65677
+ getStudioAskAIEnabled() && /* @__PURE__ */ jsx360(AskAiModal, {})
65455
65678
  ]
65456
65679
  });
65457
65680
  };
@@ -65539,8 +65762,7 @@ var background = {
65539
65762
  flexDirection: "column",
65540
65763
  position: "absolute"
65541
65764
  };
65542
- var DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS = 300;
65543
- var BUFFER_STATE_DELAY_IN_MILLISECONDS = typeof process.env.BUFFER_STATE_DELAY_IN_MILLISECONDS === "undefined" || process.env.BUFFER_STATE_DELAY_IN_MILLISECONDS === null ? DEFAULT_BUFFER_STATE_DELAY_IN_MILLISECONDS : Number(process.env.BUFFER_STATE_DELAY_IN_MILLISECONDS);
65765
+ var BUFFER_STATE_DELAY_IN_MILLISECONDS = getStudioBufferStateDelayInMilliseconds();
65544
65766
  var Editor = ({ Root, readOnlyStudio }) => {
65545
65767
  const [drawElement, setDrawElement] = useState125(null);
65546
65768
  const size3 = PlayerInternals23.useElementSize(drawElement, {