@remotion/studio 4.0.518 → 4.0.519

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (140) hide show
  1. package/dist/components/AppLaunchButton.d.ts +16 -0
  2. package/dist/components/AppLaunchButton.js +90 -0
  3. package/dist/components/AssetSelector.js +7 -6
  4. package/dist/components/AssetSelectorItem.d.ts +12 -0
  5. package/dist/components/AssetSelectorItem.js +180 -62
  6. package/dist/components/Button.js +20 -7
  7. package/dist/components/Canvas.js +109 -78
  8. package/dist/components/CanvasOrLoading.js +7 -7
  9. package/dist/components/CodingAgentButton.d.ts +7 -0
  10. package/dist/components/CodingAgentButton.js +59 -0
  11. package/dist/components/CompositionContextButton.d.ts +1 -0
  12. package/dist/components/CompositionContextButton.js +6 -3
  13. package/dist/components/CompositionSelector.js +15 -10
  14. package/dist/components/CompositionSelectorItem.js +16 -23
  15. package/dist/components/ConfigureLicenseModal.js +4 -48
  16. package/dist/components/CurrentAsset.js +1 -1
  17. package/dist/components/ElementInstallConfirmation.d.ts +20 -7
  18. package/dist/components/ElementInstallConfirmation.js +325 -32
  19. package/dist/components/FixComputedValueModal.js +5 -131
  20. package/dist/components/InitialCompositionLoader.js +3 -2
  21. package/dist/components/InspectorOpenInEditor.js +48 -33
  22. package/dist/components/InspectorPanel/CompositionInspector.js +35 -3
  23. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +22 -14
  24. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +3 -1
  25. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +1 -1
  26. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +10 -5
  27. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +1 -1
  28. package/dist/components/InspectorPanel/common.js +1 -0
  29. package/dist/components/InspectorPanel/styles.js +1 -0
  30. package/dist/components/InspectorSequenceSection.js +8 -3
  31. package/dist/components/InspectorSourceLocation.js +5 -1
  32. package/dist/components/KnownBugs.d.ts +1 -1
  33. package/dist/components/KnownBugs.js +1 -1
  34. package/dist/components/LicenseExplanation.d.ts +2 -0
  35. package/dist/components/LicenseExplanation.js +63 -0
  36. package/dist/components/MenuToolbar.js +7 -1
  37. package/dist/components/Modals.js +1 -2
  38. package/dist/components/NewComposition/InputDragger.js +29 -2
  39. package/dist/components/NewComposition/NewCompDuration.js +1 -1
  40. package/dist/components/NewComposition/NewComposition.d.ts +23 -0
  41. package/dist/components/NewComposition/NewComposition.js +217 -80
  42. package/dist/components/{UpdateModal/OpenIssueButton.js → OpenIssueButton.js} +1 -1
  43. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +2 -1
  44. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +21 -13
  45. package/dist/components/RenderQueue/actions.d.ts +1 -0
  46. package/dist/components/RenderQueue/actions.js +5 -1
  47. package/dist/components/SelectedOutlineCanvasRotation.js +27 -1
  48. package/dist/components/SelectedOutlineElement.js +2 -1
  49. package/dist/components/SelectedOutlineKeyboardControls.d.ts +2 -2
  50. package/dist/components/SelectedOutlineOverlay.d.ts +3 -1
  51. package/dist/components/SelectedOutlineOverlay.js +21 -26
  52. package/dist/components/SelectedOutlinePolygon.d.ts +1 -0
  53. package/dist/components/SelectedOutlinePolygon.js +12 -4
  54. package/dist/components/SelectedOutlineRenderer.js +88 -21
  55. package/dist/components/SettingsContext.js +2 -1
  56. package/dist/components/SettingsModal.d.ts +1 -1
  57. package/dist/components/SettingsModal.js +19 -3
  58. package/dist/components/SidebarRenderButton.d.ts +1 -0
  59. package/dist/components/SidebarRenderButton.js +14 -5
  60. package/dist/components/Timeline/SequencePropsObserver.js +29 -14
  61. package/dist/components/Timeline/TimelineKeyframeControls.js +3 -1
  62. package/dist/components/Timeline/TimelineRowChrome.js +4 -2
  63. package/dist/components/Timeline/TimelineSequence.js +40 -8
  64. package/dist/components/Timeline/TimelineSequenceItem.js +34 -1
  65. package/dist/components/Timeline/TimelineStack/get-stack.d.ts +1 -0
  66. package/dist/components/Timeline/TimelineStack/get-stack.js +35 -3
  67. package/dist/components/Timeline/duplicate-selected-timeline-item.js +23 -25
  68. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +6 -0
  69. package/dist/components/Timeline/get-sequence-context-menu-items.js +34 -1
  70. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +2 -0
  71. package/dist/components/Timeline/sequence-props-subscription-store.js +22 -1
  72. package/dist/components/Timeline/use-sequence-props-subscription.js +7 -0
  73. package/dist/components/TimelineCombobox.js +1 -0
  74. package/dist/components/UpdateCheck.d.ts +0 -8
  75. package/dist/components/UpdateCheck.js +7 -54
  76. package/dist/components/UpdateStatusContext.d.ts +18 -0
  77. package/dist/components/UpdateStatusContext.js +74 -0
  78. package/dist/components/UpdatesSettings.d.ts +2 -0
  79. package/dist/components/UpdatesSettings.js +251 -0
  80. package/dist/components/WebMcp.js +3 -3
  81. package/dist/components/get-open-in-menu-items.d.ts +4 -0
  82. package/dist/components/get-open-in-menu-items.js +28 -24
  83. package/dist/components/root-composition-menu-items.d.ts +4 -1
  84. package/dist/components/root-composition-menu-items.js +38 -1
  85. package/dist/components/selected-outline-geometry.d.ts +21 -2
  86. package/dist/components/selected-outline-geometry.js +16 -5
  87. package/dist/components/selected-outline-measurement.d.ts +40 -1
  88. package/dist/components/selected-outline-measurement.js +239 -1
  89. package/dist/components/selected-outline-order.d.ts +12 -0
  90. package/dist/components/selected-outline-order.js +251 -0
  91. package/dist/components/selected-outline-types.d.ts +15 -2
  92. package/dist/components/selected-outline-uv.js +106 -3
  93. package/dist/components/use-configure-default-apps.d.ts +1 -0
  94. package/dist/components/use-configure-default-apps.js +24 -0
  95. package/dist/error-overlay/remotion-overlay/CodeFrame.js +5 -6
  96. package/dist/error-overlay/remotion-overlay/CopyStackTrace.js +1 -1
  97. package/dist/error-overlay/remotion-overlay/ErrorDisplay.js +47 -18
  98. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +1 -1
  99. package/dist/error-overlay/remotion-overlay/ErrorTitle.js +5 -4
  100. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +48 -76
  101. package/dist/error-overlay/remotion-overlay/SearchGitHubIssues.js +1 -1
  102. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +2 -2
  103. package/dist/error-overlay/remotion-overlay/StackFrame.js +13 -8
  104. package/dist/error-overlay/remotion-overlay/Symbolicating.js +1 -1
  105. package/dist/esm/{chunk-7prjt5n5.js → chunk-1fkq5bfq.js} +15439 -11610
  106. package/dist/esm/chunk-6jf1natv.js +25 -0
  107. package/dist/esm/{chunk-4bxz1d3g.js → chunk-je0h1bgt.js} +1 -28
  108. package/dist/esm/chunk-m0jqdbkr.js +14571 -0
  109. package/dist/esm/index.mjs +0 -2
  110. package/dist/esm/internals.mjs +32140 -13755
  111. package/dist/esm/previewEntry.mjs +35408 -17021
  112. package/dist/esm/renderEntry.mjs +6 -3
  113. package/dist/helpers/can-show-updates.d.ts +5 -0
  114. package/dist/helpers/can-show-updates.js +7 -0
  115. package/dist/helpers/colors.d.ts +0 -3
  116. package/dist/helpers/colors.js +2 -5
  117. package/dist/helpers/create-folder-tree.d.ts +5 -0
  118. package/dist/helpers/create-folder-tree.js +24 -1
  119. package/dist/helpers/get-asset-metadata.js +1 -1
  120. package/dist/helpers/get-box-quads-polyfill-internals.d.ts +82 -0
  121. package/dist/helpers/get-box-quads-polyfill-internals.js +2403 -0
  122. package/dist/helpers/get-box-quads-ponyfill.d.ts +10 -0
  123. package/dist/helpers/get-box-quads-ponyfill.js +23 -0
  124. package/dist/helpers/get-git-menu-item.d.ts +5 -0
  125. package/dist/helpers/get-git-menu-item.js +15 -1
  126. package/dist/helpers/hoverable.js +10 -5
  127. package/dist/helpers/open-in-editor.js +51 -1
  128. package/dist/helpers/preview-server-events.js +3 -0
  129. package/dist/helpers/timeline-layout.d.ts +0 -1
  130. package/dist/helpers/timeline-layout.js +1 -5
  131. package/dist/helpers/url-state.d.ts +1 -0
  132. package/dist/helpers/url-state.js +12 -5
  133. package/dist/renderEntry.js +2 -0
  134. package/dist/state/folders.d.ts +3 -0
  135. package/dist/state/folders.js +40 -1
  136. package/dist/state/modals.d.ts +1 -6
  137. package/package.json +17 -14
  138. package/dist/components/UpdateModal/UpdateModal.d.ts +0 -6
  139. package/dist/components/UpdateModal/UpdateModal.js +0 -104
  140. /package/dist/components/{UpdateModal/OpenIssueButton.d.ts → OpenIssueButton.d.ts} +0 -0
@@ -33,9 +33,8 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SelectedOutlineOverlay = exports.selectedOutlineDragThresholdPx = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getSelectedCropInfo = exports.getOutlineSelectionInteraction = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineUvSnapThresholdPx = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineTransformOriginDragChanges = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineCropFollowingTransformOrigin = exports.getSelectedOutlineCropDragValues = exports.getSelectedOutlineCropDragChanges = exports.getSelectedOutlineActiveSchema = exports.getSelectedOutline3DRotationDragValues = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = void 0;
36
+ exports.SelectedOutlineOverlay = exports.selectedOutlineDragThresholdPx = exports.getTransformedSvgViewportPoints = exports.getSequencesWithSelectableOutlines = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getSelectedCropInfo = exports.getOutlineSelectionInteraction = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineUvSnapThresholdPx = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineTransformOriginDragChanges = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineCropFollowingTransformOrigin = exports.getSelectedOutlineCropDragValues = exports.getSelectedOutlineCropDragChanges = exports.getSelectedOutlineActiveSchema = exports.getSelectedOutline3DRotationDragValues = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = exports.orderOutlinesForRendering = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
- const canvas_1 = require("@remotion/canvas");
39
38
  const player_1 = require("@remotion/player");
40
39
  const react_1 = __importStar(require("react"));
41
40
  const remotion_1 = require("remotion");
@@ -51,6 +50,8 @@ const timeline_sequence_hover_1 = require("../state/timeline-sequence-hover");
51
50
  const transform_3d_mode_1 = require("../state/transform-3d-mode");
52
51
  const selected_outline_drag_1 = require("./selected-outline-drag");
53
52
  const selected_outline_measurement_1 = require("./selected-outline-measurement");
53
+ const selected_outline_order_1 = require("./selected-outline-order");
54
+ Object.defineProperty(exports, "orderOutlinesForRendering", { enumerable: true, get: function () { return selected_outline_order_1.orderOutlinesForRendering; } });
54
55
  const selected_outline_types_1 = require("./selected-outline-types");
55
56
  const SelectedOutlineKeyboardControls_1 = require("./SelectedOutlineKeyboardControls");
56
57
  const SelectedOutlineRenderer_1 = require("./SelectedOutlineRenderer");
@@ -93,6 +94,8 @@ Object.defineProperty(exports, "getSelectedOutlineRotationCornerInfo", { enumera
93
94
  Object.defineProperty(exports, "getSelectedOutlineRotationDeltaDegrees", { enumerable: true, get: function () { return selected_outline_measurement_2.getSelectedOutlineRotationDeltaDegrees; } });
94
95
  Object.defineProperty(exports, "getSelectedOutlineRotationPivot", { enumerable: true, get: function () { return selected_outline_measurement_2.getSelectedOutlineRotationPivot; } });
95
96
  Object.defineProperty(exports, "getSelectedSequenceKeys", { enumerable: true, get: function () { return selected_outline_measurement_2.getSelectedSequenceKeys; } });
97
+ Object.defineProperty(exports, "getSequencesWithSelectableOutlines", { enumerable: true, get: function () { return selected_outline_measurement_2.getSequencesWithSelectableOutlines; } });
98
+ Object.defineProperty(exports, "getTransformedSvgViewportPoints", { enumerable: true, get: function () { return selected_outline_measurement_2.getTransformedSvgViewportPoints; } });
96
99
  const selected_outline_types_2 = require("./selected-outline-types");
97
100
  Object.defineProperty(exports, "selectedOutlineDragThresholdPx", { enumerable: true, get: function () { return selected_outline_types_2.selectedOutlineDragThresholdPx; } });
98
101
  const getEffectiveCropValue = ({ activeSchema, dragOverrides, fieldKey, frame, propStatuses, runtimeValues, }) => {
@@ -260,7 +263,6 @@ const calculateOutlineTargets = ({ connectedClientId, editorShowOutlines, getDra
260
263
  key,
261
264
  containsSelection,
262
265
  crop,
263
- includeOutsideContainer: showSelectedOutline,
264
266
  keyframeDisplayOffset: nodeKeyframeDisplayOffset,
265
267
  nodePathInfo,
266
268
  ref: sequence.refForOutline,
@@ -531,30 +533,21 @@ const ActiveSelectedOutlineOverlayUnmemoized = ({ calculateOutlineTargetsForCurr
531
533
  controls.runtimeValues,
532
534
  outlineRuntimeSnapshots[index],
533
535
  ])), [outlineRuntimeControls, outlineRuntimeSnapshots]);
534
- const outlineTargets = (0, react_1.useMemo)(() => {
535
- const targets = calculateOutlineTargetsForCurrentState({
536
- mode: 'layout',
537
- runtimeValuesByStore: outlineRuntimeValuesByStore,
538
- selectableOutlines: selectableOutlinesForLayout,
539
- targetKey: null,
540
- targetTimelinePosition: timelinePosition,
541
- });
542
- return targets.map((target) => {
543
- const hovered = (0, timeline_node_path_key_1.timelineSequenceNodePathToKey)(target.nodePathInfo.sequenceSubscriptionKey) === hoveredTimelineNodePathKey;
544
- return hovered && !target.includeOutsideContainer
545
- ? { ...target, includeOutsideContainer: true }
546
- : target;
547
- });
548
- }, [
536
+ const outlineTargets = (0, react_1.useMemo)(() => calculateOutlineTargetsForCurrentState({
537
+ mode: 'layout',
538
+ runtimeValuesByStore: outlineRuntimeValuesByStore,
539
+ selectableOutlines: selectableOutlinesForLayout,
540
+ targetKey: null,
541
+ targetTimelinePosition: timelinePosition,
542
+ }), [
549
543
  calculateOutlineTargetsForCurrentState,
550
- hoveredTimelineNodePathKey,
551
544
  outlineRuntimeValuesByStore,
552
545
  selectableOutlinesForLayout,
553
546
  timelinePosition,
554
547
  ]);
555
548
  (0, react_1.useLayoutEffect)(() => {
556
549
  updateOutlinesRef.current();
557
- }, [outlineTargets, scale, translationX, translationY]);
550
+ }, [scale, translationX, translationY]);
558
551
  return (jsx_runtime_1.jsx(SelectedOutlineRenderer_1.SelectedOutlineRenderer, { compositionHeight: compositionHeight, compositionWidth: compositionWidth, dragging: draggingOutline, getLatestOutlineTargetByKey: getLatestOutlineTargetByKey, outlineTargets: outlineTargets, onDraggingChange: onDraggingChange, onContextMenuOpenChange: onContextMenuOpenChange, onSelect: onSelect, scale: scale, sequences: sequences, updateOutlinesRef: updateOutlinesRef }));
559
552
  };
560
553
  const ActiveSelectedOutlineOverlay = react_1.default.memo(ActiveSelectedOutlineOverlayUnmemoized);
@@ -589,7 +582,7 @@ const SelectedOutlineOverlayUnmemoized = ({ canvasHovered, compositionHeight, co
589
582
  !editorShowOutlines) {
590
583
  return [];
591
584
  }
592
- return (0, canvas_1.getCanvasSelectableOutlines)({
585
+ return (0, selected_outline_measurement_1.getSequencesWithSelectableOutlines)({
593
586
  sequences,
594
587
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
595
588
  compositions,
@@ -638,13 +631,11 @@ const SelectedOutlineOverlayUnmemoized = ({ canvasHovered, compositionHeight, co
638
631
  selectedTransformOriginInfo,
639
632
  sequenceKeysContainingSelection,
640
633
  ]);
641
- const calculateOutlineTargetsRef = (0, react_1.useRef)(calculateOutlineTargetsForCurrentState);
642
634
  const getSelectableOutlinesRef = (0, react_1.useRef)(getSelectableOutlines);
643
635
  const selectableOutlinesCacheRef = (0, react_1.useRef)(null);
644
636
  (0, react_1.useLayoutEffect)(() => {
645
- calculateOutlineTargetsRef.current = calculateOutlineTargetsForCurrentState;
646
637
  getSelectableOutlinesRef.current = getSelectableOutlines;
647
- }, [calculateOutlineTargetsForCurrentState, getSelectableOutlines]);
638
+ }, [getSelectableOutlines]);
648
639
  const getSelectableOutlinesAtFrame = (0, react_1.useCallback)((timelinePosition) => {
649
640
  const currentGetSelectableOutlines = getSelectableOutlinesRef.current;
650
641
  const cached = selectableOutlinesCacheRef.current;
@@ -662,7 +653,7 @@ const SelectedOutlineOverlayUnmemoized = ({ canvasHovered, compositionHeight, co
662
653
  }, []);
663
654
  const getLatestOutlineTargetByKey = (0, react_1.useCallback)((key) => {
664
655
  const timelinePosition = getCurrentFrame();
665
- const target = calculateOutlineTargetsRef.current({
656
+ const target = calculateOutlineTargetsForCurrentState({
666
657
  mode: 'controls',
667
658
  runtimeValuesByStore: new Map(),
668
659
  selectableOutlines: getSelectableOutlinesAtFrame(timelinePosition),
@@ -670,7 +661,11 @@ const SelectedOutlineOverlayUnmemoized = ({ canvasHovered, compositionHeight, co
670
661
  targetTimelinePosition: timelinePosition,
671
662
  })[0];
672
663
  return target;
673
- }, [getCurrentFrame, getSelectableOutlinesAtFrame]);
664
+ }, [
665
+ calculateOutlineTargetsForCurrentState,
666
+ getCurrentFrame,
667
+ getSelectableOutlinesAtFrame,
668
+ ]);
674
669
  const getCurrentSelectableOutlines = (0, react_1.useCallback)(() => getSelectableOutlinesAtFrame(getCurrentFrame()), [getCurrentFrame, getSelectableOutlinesAtFrame]);
675
670
  const onDraggingChange = (0, react_1.useCallback)((dragging) => {
676
671
  setDraggingOutline(dragging);
@@ -23,4 +23,5 @@ export declare const SelectedOutlinePolygon: React.NamedExoticComponent<{
23
23
  readonly onDoubleClickTarget: (target: SelectedOutlineTarget, button: number, sequenceWasDragged: boolean) => boolean;
24
24
  readonly scale: number;
25
25
  readonly showSelectedOutline: boolean;
26
+ readonly translateWithCommandKey: boolean;
26
27
  }>;
@@ -41,6 +41,7 @@ const client_id_1 = require("../helpers/client-id");
41
41
  const colors_1 = require("../helpers/colors");
42
42
  const drag_aware_double_click_1 = require("../helpers/drag-aware-double-click");
43
43
  const interactivity_enabled_1 = require("../helpers/interactivity-enabled");
44
+ const is_mac_1 = require("../helpers/is-mac");
44
45
  const pointer_session_1 = require("../helpers/pointer-session");
45
46
  const editor_guides_1 = require("../state/editor-guides");
46
47
  const editor_snapping_1 = require("../state/editor-snapping");
@@ -57,7 +58,7 @@ const imperative_state_1 = require("./Timeline/imperative-state");
57
58
  const save_sequence_prop_1 = require("./Timeline/save-sequence-prop");
58
59
  const should_clear_selection_on_pointer_down_1 = require("./Timeline/should-clear-selection-on-pointer-down");
59
60
  exports.SELECTED_OUTLINE_KEY_ATTR = 'data-remotion-studio-selected-outline-key';
60
- const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth, containsSelection, directlySelected, dragging, getAllDragOutlines, getAllDragTargets, getLayoutTarget, getTarget, hasTarget, hovered, outline, onDraggingChange, onHoverChange, onSnapPointsChange, onSelect, onDoubleClickTarget, scale, showSelectedOutline, }) => {
61
+ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth, containsSelection, directlySelected, dragging, getAllDragOutlines, getAllDragTargets, getLayoutTarget, getTarget, hasTarget, hovered, outline, onDraggingChange, onHoverChange, onSnapPointsChange, onSelect, onDoubleClickTarget, scale, showSelectedOutline, translateWithCommandKey, }) => {
61
62
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
62
63
  const dragAwareDoubleClick = (0, react_1.useMemo)(() => (0, drag_aware_double_click_1.createDragAwareDoubleClickTracker)(), []);
63
64
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
@@ -95,7 +96,12 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
95
96
  const { drag, selected } = target;
96
97
  event.preventDefault();
97
98
  event.stopPropagation();
98
- const interaction = (0, selected_outline_measurement_1.getOutlineSelectionInteraction)(event);
99
+ const temporaryTranslate = translateWithCommandKey &&
100
+ (selected || containsSelection) &&
101
+ (is_mac_1.isMac ? event.metaKey : event.ctrlKey);
102
+ const interaction = temporaryTranslate
103
+ ? { shiftKey: false, toggleKey: false }
104
+ : (0, selected_outline_measurement_1.getOutlineSelectionInteraction)(event);
99
105
  const shouldUpdateSelection = !selected || interaction.shiftKey || interaction.toggleKey;
100
106
  const ownerSvg = (_a = polygonRef.current) === null || _a === void 0 ? void 0 : _a.ownerSVGElement;
101
107
  let pointerInsideSelectedOutline = false;
@@ -159,7 +165,7 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
159
165
  let currentPointerY = startPointerY;
160
166
  let axisLocked = false;
161
167
  let dragStarted = false;
162
- let snappingDisabled = event.metaKey || event.ctrlKey;
168
+ let snappingDisabled = !temporaryTranslate && (event.metaKey || event.ctrlKey);
163
169
  let snapTargets = null;
164
170
  const updateDragOverrides = () => {
165
171
  const screenDeltaX = currentPointerX - startPointerX;
@@ -241,7 +247,8 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
241
247
  currentPointerX = moveEvent.clientX;
242
248
  currentPointerY = moveEvent.clientY;
243
249
  axisLocked = moveEvent.shiftKey;
244
- snappingDisabled = moveEvent.metaKey || moveEvent.ctrlKey;
250
+ snappingDisabled =
251
+ !temporaryTranslate && (moveEvent.metaKey || moveEvent.ctrlKey);
245
252
  updateDragOverrides();
246
253
  };
247
254
  const onKeyChange = (keyEvent) => {
@@ -336,6 +343,7 @@ const SelectedOutlinePolygonUnmemoized = ({ compositionHeight, compositionWidth,
336
343
  scale,
337
344
  setPropStatuses,
338
345
  setDragOverrides,
346
+ translateWithCommandKey,
339
347
  ]);
340
348
  const onDoubleClick = react_1.default.useCallback((event) => {
341
349
  const target = getTarget();
@@ -35,11 +35,12 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.SelectedOutlineRenderer = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
- const canvas_1 = require("@remotion/canvas");
39
38
  const react_1 = __importStar(require("react"));
40
39
  const timeline_node_path_key_1 = require("../helpers/timeline-node-path-key");
41
40
  const timeline_sequence_hover_1 = require("../state/timeline-sequence-hover");
42
41
  const ContextMenu_1 = require("./ContextMenu");
42
+ const selected_outline_measurement_1 = require("./selected-outline-measurement");
43
+ const selected_outline_order_1 = require("./selected-outline-order");
43
44
  const SelectedOutlineEditingHandles_1 = require("./SelectedOutlineEditingHandles");
44
45
  const SelectedOutlineElement_1 = require("./SelectedOutlineElement");
45
46
  const SelectedOutlinePolygon_1 = require("./SelectedOutlinePolygon");
@@ -54,9 +55,14 @@ const outlineContainer = {
54
55
  };
55
56
  const SelectedOutlineRendererUnmemoized = ({ compositionHeight, compositionWidth, dragging, getLatestOutlineTargetByKey, outlineTargets, onDraggingChange, onContextMenuOpenChange, onSelect, scale, sequences, updateOutlinesRef, }) => {
56
57
  var _a;
57
- const outlinesController = (0, canvas_1.useCanvasOutlinesController)();
58
- const renderState = (0, canvas_1.useCanvasOutlines)(outlinesController);
58
+ // Targets are derived props and can receive a new identity on every render.
59
+ // Keep only measured geometry in state to avoid layout-effect update loops.
60
+ const [outlines, setOutlines] = (0, react_1.useState)([]);
61
+ const outlinesRef = (0, react_1.useRef)(outlines);
59
62
  const overlayRef = (0, react_1.useRef)(null);
63
+ const resizeObserverRef = (0, react_1.useRef)(null);
64
+ const resizeObserverAnimationFrameRef = (0, react_1.useRef)(null);
65
+ const observedOutlineElementsRef = (0, react_1.useRef)(new Set());
60
66
  const contextMenuOpenHandlersRef = (0, react_1.useRef)(new Map());
61
67
  const registerContextMenuOpen = (0, react_1.useCallback)((key, handler) => {
62
68
  if (handler === null) {
@@ -83,9 +89,23 @@ const SelectedOutlineRendererUnmemoized = ({ compositionHeight, compositionWidth
83
89
  const hoveredSequence = (0, timeline_sequence_hover_1.useTimelineSequenceHoverState)();
84
90
  const setHoveredSequence = (0, timeline_sequence_hover_1.useSetTimelineSequenceHover)();
85
91
  const hoveredNodePathKey = (_a = hoveredSequence === null || hoveredSequence === void 0 ? void 0 : hoveredSequence.nodePathKey) !== null && _a !== void 0 ? _a : null;
92
+ const hoveredTimelineNodePathKey = (hoveredSequence === null || hoveredSequence === void 0 ? void 0 : hoveredSequence.source) === 'timeline' ? hoveredNodePathKey : null;
86
93
  const updateOutlines = (0, react_1.useCallback)(() => {
87
- outlinesController.update(overlayRef.current, outlineTargets);
88
- }, [outlineTargets, outlinesController]);
94
+ if (overlayRef.current === null || outlineTargets.length === 0) {
95
+ if (outlinesRef.current.length === 0) {
96
+ return;
97
+ }
98
+ outlinesRef.current = [];
99
+ setOutlines(outlinesRef.current);
100
+ return;
101
+ }
102
+ const nextOutlines = (0, selected_outline_measurement_1.measureOutlines)(overlayRef.current, outlineTargets, hoveredTimelineNodePathKey);
103
+ if ((0, selected_outline_measurement_1.outlinesAreEqual)(outlinesRef.current, nextOutlines)) {
104
+ return;
105
+ }
106
+ outlinesRef.current = nextOutlines;
107
+ setOutlines(nextOutlines);
108
+ }, [hoveredTimelineNodePathKey, outlineTargets]);
89
109
  (0, react_1.useLayoutEffect)(() => {
90
110
  updateOutlinesRef.current = updateOutlines;
91
111
  updateOutlines();
@@ -96,32 +116,79 @@ const SelectedOutlineRendererUnmemoized = ({ compositionHeight, compositionWidth
96
116
  };
97
117
  }, [updateOutlines, updateOutlinesRef]);
98
118
  (0, react_1.useLayoutEffect)(() => {
99
- return () => outlinesController.disconnect();
100
- }, [outlinesController]);
119
+ if (typeof ResizeObserver === 'undefined') {
120
+ return;
121
+ }
122
+ const resizeObserver = new ResizeObserver(() => {
123
+ if (resizeObserverAnimationFrameRef.current !== null) {
124
+ return;
125
+ }
126
+ resizeObserverAnimationFrameRef.current = requestAnimationFrame(() => {
127
+ resizeObserverAnimationFrameRef.current = null;
128
+ updateOutlinesRef.current();
129
+ });
130
+ });
131
+ resizeObserverRef.current = resizeObserver;
132
+ return () => {
133
+ if (resizeObserverAnimationFrameRef.current !== null) {
134
+ cancelAnimationFrame(resizeObserverAnimationFrameRef.current);
135
+ resizeObserverAnimationFrameRef.current = null;
136
+ }
137
+ resizeObserver.disconnect();
138
+ resizeObserverRef.current = null;
139
+ observedOutlineElementsRef.current = new Set();
140
+ };
141
+ }, [updateOutlinesRef]);
142
+ (0, react_1.useLayoutEffect)(() => {
143
+ const resizeObserver = resizeObserverRef.current;
144
+ if (resizeObserver === null) {
145
+ return;
146
+ }
147
+ const nextObservedElements = new Set();
148
+ if (overlayRef.current !== null) {
149
+ nextObservedElements.add(overlayRef.current);
150
+ }
151
+ for (const target of outlineTargets) {
152
+ if (target.ref.current !== null) {
153
+ nextObservedElements.add(target.ref.current);
154
+ }
155
+ }
156
+ for (const element of observedOutlineElementsRef.current) {
157
+ if (!nextObservedElements.has(element)) {
158
+ resizeObserver.unobserve(element);
159
+ }
160
+ }
161
+ for (const element of nextObservedElements) {
162
+ if (!observedOutlineElementsRef.current.has(element)) {
163
+ resizeObserver.observe(element);
164
+ }
165
+ }
166
+ observedOutlineElementsRef.current = nextObservedElements;
167
+ }, [outlineTargets]);
101
168
  const targetsByKey = (0, react_1.useMemo)(() => {
102
- return new Map(renderState.targets.map((target) => [target.key, target]));
103
- }, [renderState.targets]);
169
+ return new Map(outlineTargets.map((target) => [target.key, target]));
170
+ }, [outlineTargets]);
104
171
  (0, react_1.useEffect)(() => {
105
172
  if ((hoveredSequence === null || hoveredSequence === void 0 ? void 0 : hoveredSequence.source) === 'canvas' &&
106
- !renderState.targets.some((target) => target.key === hoveredSequence.key)) {
173
+ !outlineTargets.some((target) => target.key === hoveredSequence.key)) {
107
174
  setHoveredSequence((currentHover) => (currentHover === null || currentHover === void 0 ? void 0 : currentHover.source) === 'canvas' ? null : currentHover);
108
175
  }
109
- }, [hoveredSequence, renderState.targets, setHoveredSequence]);
176
+ }, [hoveredSequence, outlineTargets, setHoveredSequence]);
110
177
  // Reordering a captured SVG target can cancel the active pointer session.
111
178
  const outlineRenderingOrderRef = (0, react_1.useRef)([]);
112
179
  const outlinesForRendering = (0, react_1.useMemo)(() => {
113
180
  if (!dragging || outlineRenderingOrderRef.current.length === 0) {
114
- const orderedOutlines = (0, canvas_1.orderCanvasOutlinesForRendering)({
115
- outlines: renderState.outlines,
181
+ const orderedOutlines = (0, selected_outline_order_1.orderOutlinesForRendering)({
182
+ outlines,
116
183
  sequences,
117
184
  targetsByKey,
118
185
  });
119
186
  outlineRenderingOrderRef.current = orderedOutlines.map((outline) => outline.key);
120
187
  return orderedOutlines;
121
188
  }
122
- const currentOutlinesByKey = new Map(renderState.outlines.map((outline) => [outline.key, outline]));
189
+ const currentOutlinesByKey = new Map(outlines.map((outline) => [outline.key, outline]));
123
190
  const frozenKeys = new Set(outlineRenderingOrderRef.current);
124
- const newOutlines = renderState.outlines.filter((outline) => !frozenKeys.has(outline.key));
191
+ const newOutlines = outlines.filter((outline) => !frozenKeys.has(outline.key));
125
192
  outlineRenderingOrderRef.current = [
126
193
  ...outlineRenderingOrderRef.current,
127
194
  ...newOutlines.map((outline) => outline.key),
@@ -130,10 +197,10 @@ const SelectedOutlineRendererUnmemoized = ({ compositionHeight, compositionWidth
130
197
  const outline = currentOutlinesByKey.get(key);
131
198
  return outline === undefined ? [] : [outline];
132
199
  });
133
- }, [dragging, renderState.outlines, sequences, targetsByKey]);
200
+ }, [dragging, outlines, sequences, targetsByKey]);
134
201
  const outlinesByKey = (0, react_1.useMemo)(() => {
135
- return new Map(renderState.outlines.map((outline) => [outline.key, outline]));
136
- }, [renderState.outlines]);
202
+ return new Map(outlines.map((outline) => [outline.key, outline]));
203
+ }, [outlines]);
137
204
  const { outlinesForEditingHandles, outlinesForTransformOrigin, outlinesForUvHandles, } = (0, react_1.useMemo)(() => {
138
205
  const editingHandles = [];
139
206
  const transformOrigin = [];
@@ -159,12 +226,12 @@ const SelectedOutlineRendererUnmemoized = ({ compositionHeight, compositionWidth
159
226
  outlinesForUvHandles: uvHandles,
160
227
  };
161
228
  }, [hoveredNodePathKey, outlinesForRendering, targetsByKey]);
162
- const targetsRef = (0, react_1.useRef)(renderState.targets);
229
+ const targetsRef = (0, react_1.useRef)(outlineTargets);
163
230
  const outlinesByKeyRef = (0, react_1.useRef)(outlinesByKey);
164
231
  (0, react_1.useLayoutEffect)(() => {
165
- targetsRef.current = renderState.targets;
232
+ targetsRef.current = outlineTargets;
166
233
  outlinesByKeyRef.current = outlinesByKey;
167
- }, [outlinesByKey, renderState.targets]);
234
+ }, [outlineTargets, outlinesByKey]);
168
235
  const getAllDragTargets = (0, react_1.useCallback)(() => targetsRef.current.flatMap((target) => {
169
236
  var _a;
170
237
  var _b;
@@ -6,6 +6,7 @@ const react_1 = require("react");
6
6
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
7
7
  const client_id_1 = require("../helpers/client-id");
8
8
  const call_api_1 = require("./call-api");
9
+ const UpdateStatusContext_1 = require("./UpdateStatusContext");
9
10
  const SettingsContext = (0, react_1.createContext)(null);
10
11
  const SettingsProvider = ({ children }) => {
11
12
  var _a;
@@ -110,7 +111,7 @@ const SettingsProvider = ({ children }) => {
110
111
  const value = (0, react_1.useMemo)(() => {
111
112
  return { ...settings, setPublicLicenseKey };
112
113
  }, [setPublicLicenseKey, settings]);
113
- return (jsx_runtime_1.jsx(SettingsContext.Provider, { value: value, children: children }));
114
+ return (jsx_runtime_1.jsx(SettingsContext.Provider, { value: value, children: jsx_runtime_1.jsx(UpdateStatusContext_1.UpdateStatusProvider, { children: children }) }));
114
115
  };
115
116
  exports.SettingsProvider = SettingsProvider;
116
117
  const useSettings = () => {
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- type SettingsTab = 'apps' | 'rendering' | 'studio' | 'packages' | 'shortcuts' | 'skills' | 'license';
2
+ type SettingsTab = 'apps' | 'rendering' | 'studio' | 'packages' | 'shortcuts' | 'skills' | 'license' | 'updates';
3
3
  export declare const SettingsModal: React.FC<{
4
4
  readonly initialTab: SettingsTab;
5
5
  readonly initialPublicLicenseKey: string | null;
@@ -4,7 +4,10 @@ exports.SettingsModal = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
7
+ const can_show_updates_1 = require("../helpers/can-show-updates");
8
+ const client_id_1 = require("../helpers/client-id");
7
9
  const apps_1 = require("../icons/apps");
10
+ const cloud_download_1 = require("../icons/cloud-download");
8
11
  const keyboard_1 = require("../icons/keyboard");
9
12
  const license_1 = require("../icons/license");
10
13
  const package_1 = require("../icons/package");
@@ -26,6 +29,7 @@ const SettingsModalFooter_1 = require("./SettingsModalFooter");
26
29
  const SkillsSettings_1 = require("./SkillsSettings");
27
30
  const StudioSettings_1 = require("./StudioSettings");
28
31
  const vertical_1 = require("./Tabs/vertical");
32
+ const UpdatesSettings_1 = require("./UpdatesSettings");
29
33
  const hiddenPanel = {
30
34
  display: 'none',
31
35
  };
@@ -58,13 +62,20 @@ const keyboardIcon = {
58
62
  const SettingsModal = ({ initialPublicLicenseKey, initialTab }) => {
59
63
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
60
64
  const { setPublicLicenseKey } = (0, SettingsContext_1.useSettings)();
65
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
61
66
  const isBrowserStudio = (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null;
67
+ const showUpdates = (0, can_show_updates_1.canShowUpdates)({
68
+ connectionStatus: previewServerState.type,
69
+ isBrowserStudio,
70
+ readOnlyStudio: window.remotion_isReadOnlyStudio,
71
+ });
62
72
  const packageManager = window.remotion_packageManager === 'unknown'
63
73
  ? null
64
74
  : window.remotion_packageManager;
65
75
  const showPackages = (0, browser_studio_operations_1.canInstallPackages)() && (isBrowserStudio || packageManager !== null);
66
- const [tab, setTab] = (0, react_1.useState)(initialTab);
67
- const [openedTabs, setOpenedTabs] = (0, react_1.useState)([initialTab]);
76
+ const safeInitialTab = initialTab === 'updates' && !showUpdates ? 'shortcuts' : initialTab;
77
+ const [tab, setTab] = (0, react_1.useState)(safeInitialTab);
78
+ const [openedTabs, setOpenedTabs] = (0, react_1.useState)([safeInitialTab]);
68
79
  const [packagesFooterContainer, setPackagesFooterContainer] = (0, react_1.useState)(null);
69
80
  const dismiss = (0, react_1.useCallback)(() => {
70
81
  setSelectedModal(null);
@@ -78,11 +89,16 @@ const SettingsModal = ({ initialPublicLicenseKey, initialTab }) => {
78
89
  return [...currentOpenedTabs, newTab];
79
90
  });
80
91
  }, []);
92
+ (0, react_1.useLayoutEffect)(() => {
93
+ if (!showUpdates && tab === 'updates') {
94
+ selectTab('shortcuts');
95
+ }
96
+ }, [selectTab, showUpdates, tab]);
81
97
  (0, react_1.useEffect)(() => {
82
98
  setPublicLicenseKey(initialPublicLicenseKey);
83
99
  }, [initialPublicLicenseKey, setPublicLicenseKey]);
84
100
  return (jsx_runtime_1.jsx(DismissableModal_1.DismissableModal, { panelStyle: render_modals_1.outerModalStyle, children: jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
85
101
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "Settings", onClose: dismiss }), jsx_runtime_1.jsxs("div", { style: render_modals_1.horizontalLayout, children: [
86
- jsx_runtime_1.jsxs("div", { style: settingsLeftSidebar, children: [isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'rendering', onClick: () => selectTab('rendering'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(video_1.FilmIcon, { color: color, style: render_modals_1.icon }) })), children: "Defaults" })), isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'studio', onClick: () => selectTab('studio'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(remotion_triangle_1.RemotionTriangleIcon, { color: color, style: render_modals_1.icon }) })), children: "Studio" })), jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'shortcuts', onClick: () => selectTab('shortcuts'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(keyboard_1.KeyboardIcon, { color: color, style: keyboardIcon }) })), children: "Shortcuts" }), showPackages ? (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'packages', onClick: () => selectTab('packages'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(package_1.PackageIcon, { color: color, style: render_modals_1.icon }) })), children: "Packages" })) : null, isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'skills', onClick: () => selectTab('skills'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(skills_1.SkillsIcon, { color: color, style: skillsIcon }) })), children: "Skills" })), isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'apps', onClick: () => selectTab('apps'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(apps_1.AppsIcon, { color: color, style: appsIcon }) })), children: "Apps" })), isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'license', onClick: () => selectTab('license'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(license_1.LicenseIcon, { color: color, style: render_modals_1.icon }) })), children: "License" }))] }), openedTabs.includes('packages') ? (jsx_runtime_1.jsx("div", { style: tab === 'packages' ? render_modals_1.optionsPanel : hiddenPanel, children: jsx_runtime_1.jsx(InstallPackage_1.InstallPackageSettings, { footerContainer: packagesFooterContainer, packageManager: packageManager }) })) : null, openedTabs.includes('apps') ? (jsx_runtime_1.jsx("div", { style: tab === 'apps' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureDefaultEditorModal_1.DefaultEditorSettings, {}) })) : null, openedTabs.includes('license') ? (jsx_runtime_1.jsx("div", { style: tab === 'license' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureLicenseModal_1.LicenseSettings, {}) })) : null, openedTabs.includes('skills') ? (jsx_runtime_1.jsx("div", { style: tab === 'skills' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(SkillsSettings_1.SkillsSettings, {}) })) : null, openedTabs.includes('shortcuts') ? (jsx_runtime_1.jsx("div", { style: tab === 'shortcuts' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(KeyboardShortcutsSettings_1.KeyboardShortcutsSettings, {}) })) : null, openedTabs.includes('rendering') ? (jsx_runtime_1.jsx("div", { style: tab === 'rendering' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(RenderingSettings_1.RenderingSettings, {}) })) : null, openedTabs.includes('studio') ? (jsx_runtime_1.jsx("div", { style: tab === 'studio' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(StudioSettings_1.StudioSettings, {}) })) : null] }), tab === 'packages' ? (jsx_runtime_1.jsx("div", { ref: setPackagesFooterContainer })) : isBrowserStudio ? null : (jsx_runtime_1.jsx(SettingsModalFooter_1.SettingsModalFooter, { showLicenseFaq: tab === 'license' }))] }) }));
102
+ jsx_runtime_1.jsxs("div", { style: settingsLeftSidebar, children: [isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'rendering', onClick: () => selectTab('rendering'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(video_1.FilmIcon, { color: color, style: render_modals_1.icon }) })), children: "Defaults" })), isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'studio', onClick: () => selectTab('studio'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(remotion_triangle_1.RemotionTriangleIcon, { color: color, style: render_modals_1.icon }) })), children: "Studio" })), jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'shortcuts', onClick: () => selectTab('shortcuts'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(keyboard_1.KeyboardIcon, { color: color, style: keyboardIcon }) })), children: "Shortcuts" }), showPackages ? (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'packages', onClick: () => selectTab('packages'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(package_1.PackageIcon, { color: color, style: render_modals_1.icon }) })), children: "Packages" })) : null, isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'skills', onClick: () => selectTab('skills'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(skills_1.SkillsIcon, { color: color, style: skillsIcon }) })), children: "Skills" })), isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'apps', onClick: () => selectTab('apps'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(apps_1.AppsIcon, { color: color, style: appsIcon }) })), children: "Apps" })), isBrowserStudio ? null : (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'license', onClick: () => selectTab('license'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(license_1.LicenseIcon, { color: color, style: render_modals_1.icon }) })), children: "License" })), showUpdates ? (jsx_runtime_1.jsx(vertical_1.VerticalTab, { style: render_modals_1.horizontalTab, selected: tab === 'updates', onClick: () => selectTab('updates'), renderIcon: (color) => (jsx_runtime_1.jsx("div", { style: render_modals_1.iconContainer, children: jsx_runtime_1.jsx(cloud_download_1.CloudDownloadIcon, { color: color, style: render_modals_1.icon }) })), children: "Updates" })) : null] }), openedTabs.includes('packages') ? (jsx_runtime_1.jsx("div", { style: tab === 'packages' ? render_modals_1.optionsPanel : hiddenPanel, children: jsx_runtime_1.jsx(InstallPackage_1.InstallPackageSettings, { footerContainer: packagesFooterContainer, packageManager: packageManager }) })) : null, openedTabs.includes('apps') ? (jsx_runtime_1.jsx("div", { style: tab === 'apps' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureDefaultEditorModal_1.DefaultEditorSettings, {}) })) : null, openedTabs.includes('license') ? (jsx_runtime_1.jsx("div", { style: tab === 'license' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ConfigureLicenseModal_1.LicenseSettings, {}) })) : null, openedTabs.includes('skills') ? (jsx_runtime_1.jsx("div", { style: tab === 'skills' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(SkillsSettings_1.SkillsSettings, {}) })) : null, openedTabs.includes('shortcuts') ? (jsx_runtime_1.jsx("div", { style: tab === 'shortcuts' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(KeyboardShortcutsSettings_1.KeyboardShortcutsSettings, {}) })) : null, openedTabs.includes('rendering') ? (jsx_runtime_1.jsx("div", { style: tab === 'rendering' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(RenderingSettings_1.RenderingSettings, {}) })) : null, openedTabs.includes('studio') ? (jsx_runtime_1.jsx("div", { style: tab === 'studio' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(StudioSettings_1.StudioSettings, {}) })) : null, showUpdates && openedTabs.includes('updates') ? (jsx_runtime_1.jsx("div", { style: tab === 'updates' ? settingsOptionsPanel : hiddenPanel, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(UpdatesSettings_1.UpdatesSettings, {}) })) : null] }), tab === 'packages' ? (jsx_runtime_1.jsx("div", { ref: setPackagesFooterContainer })) : isBrowserStudio || tab === 'updates' ? null : (jsx_runtime_1.jsx(SettingsModalFooter_1.SettingsModalFooter, { showLicenseFaq: tab === 'license' }))] }) }));
87
103
  };
88
104
  exports.SettingsModal = SettingsModal;
@@ -3,4 +3,5 @@ import type { _InternalTypes } from 'remotion';
3
3
  export declare const SidebarRenderButton: React.FC<{
4
4
  readonly composition: _InternalTypes['AnyCompMetadata'];
5
5
  readonly visible: boolean;
6
+ readonly readOnlyStudio: boolean;
6
7
  }>;
@@ -9,7 +9,10 @@ const hoverable_1 = require("../helpers/hoverable");
9
9
  const render_1 = require("../icons/render");
10
10
  const modals_1 = require("../state/modals");
11
11
  const InlineAction_1 = require("./InlineAction");
12
- const SidebarRenderButton = ({ composition, visible }) => {
12
+ const revealStyle = {
13
+ display: 'flex',
14
+ };
15
+ const SidebarRenderButton = ({ composition, visible, readOnlyStudio }) => {
13
16
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
14
17
  const iconStyle = (0, react_1.useMemo)(() => {
15
18
  return {
@@ -79,15 +82,21 @@ const SidebarRenderButton = ({ composition, visible }) => {
79
82
  initialMediaCacheSizeInBytes: defaults.mediaCacheSizeInBytes,
80
83
  renderDefaults: defaults,
81
84
  initialDarkMode: defaults.darkMode,
82
- readOnlyStudio: false,
85
+ readOnlyStudio,
83
86
  });
84
- }, [composition.defaultProps, composition.id, props, setSelectedModal]);
87
+ }, [
88
+ composition.defaultProps,
89
+ composition.id,
90
+ props,
91
+ readOnlyStudio,
92
+ setSelectedModal,
93
+ ]);
85
94
  const renderAction = (0, react_1.useCallback)((color) => {
86
95
  return jsx_runtime_1.jsx(render_1.ThinRenderIcon, { fill: color, svgProps: iconStyle });
87
96
  }, [iconStyle]);
88
- if (!visible || connectionStatus !== 'connected') {
97
+ if (!visible || (connectionStatus !== 'connected' && !readOnlyStudio)) {
89
98
  return null;
90
99
  }
91
- return (jsx_runtime_1.jsx(InlineAction_1.InlineAction, { renderAction: renderAction, onClick: onClick, variant: null, style: hoverable_1.NO_HOVER_BACKGROUND_STYLE, className: hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME }));
100
+ return (jsx_runtime_1.jsx("div", { className: hoverable_1.HOVER_GROUP_REVEAL_CLASS_NAME, style: revealStyle, children: jsx_runtime_1.jsx(InlineAction_1.InlineAction, { renderAction: renderAction, onClick: onClick, variant: null, style: hoverable_1.NO_HOVER_BACKGROUND_STYLE, className: hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME }) }));
92
101
  };
93
102
  exports.SidebarRenderButton = SidebarRenderButton;
@@ -7,6 +7,7 @@ const fast_refresh_context_1 = require("../../fast-refresh-context");
7
7
  const client_id_1 = require("../../helpers/client-id");
8
8
  const sequence_node_path_mutations_1 = require("../../helpers/sequence-node-path-mutations");
9
9
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
10
+ const sequence_props_subscription_store_1 = require("./sequence-props-subscription-store");
10
11
  const SequencePropsObserver = () => {
11
12
  const { subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
12
13
  const { remapPropStatuses, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
@@ -37,11 +38,13 @@ const SequencePropsObserver = () => {
37
38
  }
38
39
  const statusRemappings = [];
39
40
  const overrideUpdates = [];
41
+ const overrideIdsToRefresh = new Set();
40
42
  for (const [overrideId, previousNodePath] of Object.entries(overrideIdToNodePathMappingsRef.current)) {
41
43
  let { nodePath } = previousNodePath;
42
44
  let wasRemapped = false;
43
45
  let wasDeleted = false;
44
46
  let runtimeNodePathExists = true;
47
+ let runtimeNodePathNeedsRefresh = false;
45
48
  const previousNodePathString = JSON.stringify(previousNodePath.nodePath);
46
49
  for (const mutation of mutations) {
47
50
  for (const file of mutation.files) {
@@ -49,29 +52,35 @@ const SequencePropsObserver = () => {
49
52
  continue;
50
53
  }
51
54
  // Prop statuses follow source nodes to their new paths. Override IDs,
52
- // however, follow React's runtime instances. After deleting an unkeyed
53
- // sibling, React reuses the instance already at the destination path.
54
- // Keep that mapping in place and only remove mappings for vacated paths.
55
- const runtimeNodePathIsSource = file.remappings.some((item) => JSON.stringify(item.oldNodePath) === previousNodePathString);
55
+ // however, follow React's runtime instances. Structural edits may reuse
56
+ // the instance already at a path, so only remove mappings from paths
57
+ // which are sources without also being destinations.
58
+ const runtimeNodePathIsSource = file.remappings.some((item) => item.oldNodePath !== null &&
59
+ JSON.stringify(item.oldNodePath) === previousNodePathString);
56
60
  const runtimeNodePathIsDestination = file.remappings.some((item) => item.newNodePath !== null &&
57
61
  JSON.stringify(item.newNodePath) === previousNodePathString);
58
- const runtimeNodePathWasRestored = file.restoredNodePaths.some((item) => JSON.stringify(item) === previousNodePathString);
62
+ const runtimeNodePathWasInserted = file.remappings.some((item) => item.oldNodePath === null &&
63
+ item.newNodePath !== null &&
64
+ JSON.stringify(item.newNodePath) === previousNodePathString);
65
+ const runtimeNodePathWasUpdated = file.remappings.some((item) => item.oldNodePath !== null &&
66
+ item.newNodePath !== null &&
67
+ JSON.stringify(item.oldNodePath) === previousNodePathString &&
68
+ JSON.stringify(item.newNodePath) === previousNodePathString);
59
69
  if (runtimeNodePathIsSource) {
60
- runtimeNodePathExists =
61
- runtimeNodePathIsDestination || runtimeNodePathWasRestored;
70
+ runtimeNodePathExists = runtimeNodePathIsDestination;
71
+ runtimeNodePathNeedsRefresh =
72
+ runtimeNodePathWasInserted || runtimeNodePathWasUpdated;
62
73
  }
63
- else if (runtimeNodePathIsDestination ||
64
- runtimeNodePathWasRestored) {
74
+ else if (runtimeNodePathIsDestination) {
65
75
  runtimeNodePathExists = true;
76
+ runtimeNodePathNeedsRefresh =
77
+ runtimeNodePathWasInserted || runtimeNodePathWasUpdated;
66
78
  }
67
79
  if (wasDeleted) {
68
- const wasRestored = file.restoredNodePaths.some((restoredNodePath) => JSON.stringify(restoredNodePath) === JSON.stringify(nodePath));
69
- if (wasRestored) {
70
- wasDeleted = false;
71
- }
72
80
  continue;
73
81
  }
74
- const remapping = file.remappings.find((item) => JSON.stringify(item.oldNodePath) === JSON.stringify(nodePath));
82
+ const remapping = file.remappings.find((item) => item.oldNodePath !== null &&
83
+ JSON.stringify(item.oldNodePath) === JSON.stringify(nodePath));
75
84
  if (!remapping) {
76
85
  continue;
77
86
  }
@@ -97,11 +106,17 @@ const SequencePropsObserver = () => {
97
106
  overrideId,
98
107
  nodePath: runtimeNodePathExists ? previousNodePath : null,
99
108
  });
109
+ if (runtimeNodePathExists && runtimeNodePathNeedsRefresh) {
110
+ overrideIdsToRefresh.add(overrideId);
111
+ }
100
112
  }
101
113
  remapPropStatuses(statusRemappings);
102
114
  for (const event of overrideUpdates) {
103
115
  setOverrideIdToNodePath(event.overrideId, event.nodePath);
104
116
  }
117
+ for (const overrideId of overrideIdsToRefresh) {
118
+ (0, sequence_props_subscription_store_1.refreshSequencePropsSubscription)(overrideId);
119
+ }
105
120
  for (const event of statusRemappings) {
106
121
  if (event.nodePath === null) {
107
122
  continue;
@@ -206,6 +206,7 @@ const hasTargetKeyframeAtCurrentFrame = (target) => {
206
206
  return (0, get_keyframe_navigation_1.hasKeyframeAtSourceFrame)(target.propStatus.keyframes, target.sourceFrame);
207
207
  };
208
208
  const getAddChange = (target) => {
209
+ var _a;
209
210
  if (target.propStatus.status === 'computed' ||
210
211
  !(0, studio_shared_1.isSchemaFieldKeyframable)({ schema: target.schema, key: target.fieldKey }) ||
211
212
  hasTargetKeyframeAtCurrentFrame(target)) {
@@ -213,7 +214,8 @@ const getAddChange = (target) => {
213
214
  }
214
215
  const value = getCurrentKeyframeValue({
215
216
  propStatus: target.propStatus,
216
- jsxFrame: target.sourceFrame,
217
+ jsxFrame: target.sourceFrame +
218
+ ((_a = target.propStatus.keyframeDisplayOffsetAdjustment) !== null && _a !== void 0 ? _a : 0),
217
219
  defaultValue: target.defaultValue,
218
220
  dragOverrideValue: target.dragOverrideValue,
219
221
  });