@remotion/studio 4.0.497 → 4.0.498

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 (45) hide show
  1. package/dist/components/Checkbox.js +1 -1
  2. package/dist/components/ConfigureLicenseModal.d.ts +4 -0
  3. package/dist/components/ConfigureLicenseModal.js +194 -0
  4. package/dist/components/Editor.d.ts +0 -1
  5. package/dist/components/Editor.js +2 -3
  6. package/dist/components/InspectorPanel/CompositionInspector.js +2 -1
  7. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -4
  8. package/dist/components/InspectorPanel/use-composition-actions.js +1 -1
  9. package/dist/components/LicenseKeyValidation.d.ts +17 -0
  10. package/dist/components/LicenseKeyValidation.js +113 -0
  11. package/dist/components/Modals.js +2 -1
  12. package/dist/components/RenderButton.js +0 -1
  13. package/dist/components/RenderModal/WebRenderModal.js +14 -8
  14. package/dist/components/SelectedOutlineOverlay.js +1 -1
  15. package/dist/components/Timeline/MaxTimelineTracks.d.ts +0 -1
  16. package/dist/components/Timeline/MaxTimelineTracks.js +3 -3
  17. package/dist/components/Timeline/Timeline.js +9 -8
  18. package/dist/components/Timeline/TimelineDragHandler.js +1 -1
  19. package/dist/components/Timeline/TimelineSelection.js +1 -1
  20. package/dist/components/Timeline/TimelineSequence.js +6 -6
  21. package/dist/components/Timeline/TimelineSequenceItem.js +5 -5
  22. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +8 -0
  23. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +40 -2
  24. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +17 -0
  25. package/dist/components/Timeline/call-update-keyframe-settings.js +43 -1
  26. package/dist/components/Timeline/update-selected-easing.js +26 -23
  27. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +5 -0
  28. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +16 -9
  29. package/dist/components/Timeline/use-timeline-asset-drop.js +1 -1
  30. package/dist/esm/{chunk-5wj95bdd.js → chunk-7a6q9hk2.js} +2454 -2312
  31. package/dist/esm/index.mjs +0 -19
  32. package/dist/esm/internals.mjs +2454 -2312
  33. package/dist/esm/previewEntry.mjs +2457 -2315
  34. package/dist/esm/renderEntry.mjs +1 -1
  35. package/dist/helpers/interactivity-enabled.d.ts +1 -1
  36. package/dist/helpers/interactivity-enabled.js +2 -2
  37. package/dist/helpers/retry-payload.js +0 -1
  38. package/dist/helpers/use-menu-structure.js +9 -3
  39. package/dist/state/modals.d.ts +3 -1
  40. package/dist/visual-controls/VisualControls.js +1 -1
  41. package/package.json +11 -11
  42. package/dist/components/RenderModal/WebRenderModalLicense.d.ts +0 -9
  43. package/dist/components/RenderModal/WebRenderModalLicense.js +0 -189
  44. package/dist/components/RenderModal/WebRenderModalLicenseKeyDetails.d.ts +0 -13
  45. package/dist/components/RenderModal/WebRenderModalLicenseKeyDetails.js +0 -60
@@ -43,6 +43,7 @@ const colors_1 = require("../../helpers/colors");
43
43
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
44
44
  const is_current_selected_still_1 = require("../../helpers/is-current-selected-still");
45
45
  const open_in_editor_1 = require("../../helpers/open-in-editor");
46
+ const studio_runtime_config_1 = require("../../helpers/studio-runtime-config");
46
47
  const call_api_1 = require("../call-api");
47
48
  const ContextMenu_1 = require("../ContextMenu");
48
49
  const import_assets_1 = require("../import-assets");
@@ -51,7 +52,6 @@ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
51
52
  const SplitterContainer_1 = require("../Splitter/SplitterContainer");
52
53
  const SplitterElement_1 = require("../Splitter/SplitterElement");
53
54
  const SplitterHandle_1 = require("../Splitter/SplitterHandle");
54
- const MaxTimelineTracks_1 = require("./MaxTimelineTracks");
55
55
  const SequencePropsObserver_1 = require("./SequencePropsObserver");
56
56
  const should_show_track_in_timeline_1 = require("./should-show-track-in-timeline");
57
57
  const should_subscribe_to_sequence_props_1 = require("./should-subscribe-to-sequence-props");
@@ -92,7 +92,7 @@ const TimelineContextMenuArea = ({ children }) => {
92
92
  const [isAddingAsset, setIsAddingAsset] = (0, react_1.useState)(false);
93
93
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
94
94
  const previewConnected = previewServerState.type === 'connected';
95
- const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
95
+ const previewInteractive = previewConnected && (0, interactivity_enabled_1.isStudioInteractivityEnabled)();
96
96
  const currentCompositionId = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
97
97
  const currentComposition = (0, react_1.useMemo)(() => {
98
98
  var _a;
@@ -219,7 +219,7 @@ const TimelineInner = () => {
219
219
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
220
220
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
221
221
  const previewConnected = previewServerState.type === 'connected';
222
- const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
222
+ const previewInteractive = previewConnected && (0, interactivity_enabled_1.isStudioInteractivityEnabled)();
223
223
  const videoConfigIsNull = videoConfig === null;
224
224
  const timeline = (0, react_1.useMemo)(() => {
225
225
  if (videoConfigIsNull) {
@@ -240,21 +240,22 @@ const TimelineInner = () => {
240
240
  const filtered = (0, react_1.useMemo)(() => {
241
241
  return timeline.filter((t) => (0, should_show_track_in_timeline_1.shouldShowTrackInTimeline)(t, durationInFrames));
242
242
  }, [durationInFrames, timeline]);
243
+ const maxTimelineTracks = (0, studio_runtime_config_1.getStudioMaxTimelineTracks)();
243
244
  const shown = (0, react_1.useMemo)(() => {
244
- return filtered.length > MaxTimelineTracks_1.MAX_TIMELINE_TRACKS
245
- ? filtered.slice(0, MaxTimelineTracks_1.MAX_TIMELINE_TRACKS)
245
+ return filtered.length > maxTimelineTracks
246
+ ? filtered.slice(0, maxTimelineTracks)
246
247
  : filtered;
247
- }, [filtered]);
248
+ }, [filtered, maxTimelineTracks]);
248
249
  const hasBeenCut = filtered.length > shown.length;
249
250
  return (jsx_runtime_1.jsxs(TimelineContextMenuArea, { children: [sequences.map((sequence) => {
250
251
  if (!(0, should_subscribe_to_sequence_props_1.shouldSubscribeToSequenceProps)(sequence, previewInteractive)) {
251
252
  return null;
252
253
  }
253
254
  return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, componentIdentity: sequence.controls.componentIdentity, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
254
- }), interactivity_enabled_1.studioInteractivityEnabled ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: [interactivity_enabled_1.studioInteractivityEnabled ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
255
+ }), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: [(0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
255
256
  jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [
256
257
  jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown }) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: null, children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
257
- jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), interactivity_enabled_1.studioInteractivityEnabled ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null, jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
258
+ jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null, jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
258
259
  ] }) })
259
260
  ] })
260
261
  ] })) })
@@ -89,7 +89,7 @@ const TimelineDragHandler = () => {
89
89
  if (!canvasContent || canvasContent.type !== 'composition') {
90
90
  return null;
91
91
  }
92
- return (jsx_runtime_1.jsx("div", { ref: timeline_refs_1.sliderAreaRef, style: containerStyle, [TimelineSelection_1.TIMELINE_SCRUBBER_ATTR]: true, children: video && interactivity_enabled_1.studioInteractivityEnabled ? (jsx_runtime_1.jsx(TimelineDragHandlerInnerMemo, {})) : null }));
92
+ return (jsx_runtime_1.jsx("div", { ref: timeline_refs_1.sliderAreaRef, style: containerStyle, [TimelineSelection_1.TIMELINE_SCRUBBER_ATTR]: true, children: video && (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineDragHandlerInnerMemo, {})) : null }));
93
93
  };
94
94
  exports.TimelineDragHandler = TimelineDragHandler;
95
95
  const TimelineDragHandlerInner = () => {
@@ -595,7 +595,7 @@ const TimelineSelectionProvider = ({ children }) => {
595
595
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
596
596
  const timelineSelectionScope = (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? canvasContent.compositionId : null;
597
597
  const { expandParentTracks } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
598
- const canSelect = interactivity_enabled_1.studioInteractivityEnabled &&
598
+ const canSelect = (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
599
599
  previewServerState.type === 'connected' &&
600
600
  !window.remotion_isReadOnlyStudio;
601
601
  const [selectedItems, setSelectedItems] = (0, react_1.useState)([]);
@@ -183,15 +183,15 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
183
183
  ? remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)
184
184
  : undefined;
185
185
  }, [propStatuses, nodePath]);
186
- const durationCanUpdate = Boolean(interactivity_enabled_1.studioInteractivityEnabled &&
186
+ const durationCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
187
187
  ((_a = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames) === null || _a === void 0 ? void 0 : _a.status) === 'static');
188
- const fromCanUpdate = Boolean(interactivity_enabled_1.studioInteractivityEnabled &&
188
+ const fromCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
189
189
  ((_b = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.from) === null || _b === void 0 ? void 0 : _b.status) === 'static');
190
- const trimBeforeCanUpdate = Boolean(interactivity_enabled_1.studioInteractivityEnabled &&
190
+ const trimBeforeCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
191
191
  ((_c = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.trimBefore) === null || _c === void 0 ? void 0 : _c.status) === 'static');
192
192
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
193
193
  const previewConnected = previewServerState.type === 'connected';
194
- const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
194
+ const previewInteractive = previewConnected && (0, interactivity_enabled_1.isStudioInteractivityEnabled)();
195
195
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
196
196
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
197
197
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
@@ -346,7 +346,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
346
346
  disableInteractivityDisabled,
347
347
  duplicateDisabled,
348
348
  fileLocation,
349
- includeSourceEditItems: interactivity_enabled_1.studioInteractivityEnabled,
349
+ includeSourceEditItems: (0, interactivity_enabled_1.isStudioInteractivityEnabled)(),
350
350
  onDeleteSequenceFromSource,
351
351
  onDisableSequenceInteractivity,
352
352
  onDuplicateSequenceFromSource,
@@ -354,7 +354,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
354
354
  originalLocation,
355
355
  selectAsset,
356
356
  sequence: s,
357
- sourceActions: interactivity_enabled_1.studioInteractivityEnabled && freezeFrameMenuItem
357
+ sourceActions: (0, interactivity_enabled_1.isStudioInteractivityEnabled)() && freezeFrameMenuItem
358
358
  ? [freezeFrameMenuItem]
359
359
  : [],
360
360
  });
@@ -177,7 +177,7 @@ const TimelineSequenceItem = ({ children, connectedCompositions, nestedDepth, se
177
177
  const nodePath = (_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _d !== void 0 ? _d : null;
178
178
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
179
179
  const previewConnected = previewServerState.type === 'connected';
180
- const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
180
+ const previewInteractive = previewConnected && (0, interactivity_enabled_1.isStudioInteractivityEnabled)();
181
181
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
182
182
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
183
183
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
@@ -549,7 +549,7 @@ const TimelineSequenceItem = ({ children, connectedCompositions, nestedDepth, se
549
549
  }
550
550
  : inner;
551
551
  }, [effectDropHovered, inner]);
552
- const hasExpandableContent = interactivity_enabled_1.studioInteractivityEnabled &&
552
+ const hasExpandableContent = (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
553
553
  (Boolean(sequence.controls) || sequence.effects.length > 0);
554
554
  const canToggleVisibility = previewInteractive &&
555
555
  Boolean(sequence.controls) &&
@@ -682,7 +682,7 @@ const TimelineSequenceItem = ({ children, connectedCompositions, nestedDepth, se
682
682
  disableInteractivityDisabled,
683
683
  duplicateDisabled,
684
684
  fileLocation,
685
- includeSourceEditItems: interactivity_enabled_1.studioInteractivityEnabled,
685
+ includeSourceEditItems: (0, interactivity_enabled_1.isStudioInteractivityEnabled)(),
686
686
  onDeleteSequenceFromSource,
687
687
  onDisableSequenceInteractivity,
688
688
  onDuplicateSequenceFromSource,
@@ -690,7 +690,7 @@ const TimelineSequenceItem = ({ children, connectedCompositions, nestedDepth, se
690
690
  originalLocation,
691
691
  selectAsset,
692
692
  sequence,
693
- sourceActions: interactivity_enabled_1.studioInteractivityEnabled
693
+ sourceActions: (0, interactivity_enabled_1.isStudioInteractivityEnabled)()
694
694
  ? [
695
695
  ...((nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects)
696
696
  ? [
@@ -819,7 +819,7 @@ const TimelineSequenceItem = ({ children, connectedCompositions, nestedDepth, se
819
819
  ] })) : null] }) }));
820
820
  const draggableTrackRow = canHandleSequenceDrag ? (jsx_runtime_1.jsxs("div", { draggable: canReorderSequence, onDragStart: onSequenceDragStart, onDragEnd: onSequenceDragEnd, onDragOver: onSequenceDragOver, onDragLeave: onSequenceDragLeave, onDrop: onSequenceDrop, style: sequenceReorderWrapper, children: [sequenceReorderLineStyle ? (jsx_runtime_1.jsx("div", { style: sequenceReorderLineStyle })) : null, sequenceDropRejection ? (jsx_runtime_1.jsx("div", { style: sequenceReorderRejectionStyle, children: sequenceDropRejection })) : null, trackRow] })) : (trackRow);
821
821
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selectable ? onSelect : null, children: draggableTrackRow })) : (draggableTrackRow), previewConnected &&
822
- interactivity_enabled_1.studioInteractivityEnabled &&
822
+ (0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
823
823
  isExpanded &&
824
824
  hasExpandableContent &&
825
825
  nodePathInfo &&
@@ -4,6 +4,7 @@ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-s
4
4
  import type { MoveEffectKeyframeChange, MoveSequenceKeyframeChange } from './call-move-keyframe';
5
5
  import { type SaveSequencePropChange } from './save-sequence-prop';
6
6
  import { type TimelineSelection } from './TimelineSelection';
7
+ export declare const timelineSequenceFromDragSnapThresholdPx = 10;
7
8
  export type TimelineSequenceDurationDragTarget = {
8
9
  readonly fileName: string;
9
10
  readonly initialDuration: number;
@@ -23,6 +24,7 @@ export type TimelineSequenceLeftEdgeDragTarget = {
23
24
  readonly schema: InteractivitySchema;
24
25
  };
25
26
  export type TimelineSequenceFromDragTarget = {
27
+ readonly canSnapToTimelineStart: boolean;
26
28
  readonly effectKeyframes: TimelineSequenceEffectKeyframeDragTarget[];
27
29
  readonly fileName: string;
28
30
  readonly initialFrom: number;
@@ -77,6 +79,12 @@ export declare const getTimelineSequenceFromDragValue: ({ initialFrom, deltaFram
77
79
  readonly initialFrom: number;
78
80
  readonly deltaFrames: number;
79
81
  }) => number;
82
+ export declare const getTimelineSequenceFromDragDelta: ({ deltaFrames, pxPerFrame, snappingEnabled, targets, }: {
83
+ readonly deltaFrames: number;
84
+ readonly pxPerFrame: number;
85
+ readonly snappingEnabled: boolean;
86
+ readonly targets: readonly TimelineSequenceFromDragTarget[];
87
+ }) => number;
80
88
  export declare const getTimelineSequenceFromDragChanges: ({ targets, deltaFrames, }: {
81
89
  readonly targets: readonly TimelineSequenceFromDragTarget[];
82
90
  readonly deltaFrames: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineSequenceRightEdgeDragHandle = exports.useTimelineSequenceFromDrag = exports.TimelineSequenceLeftEdgeDragHandle = exports.getTimelineSequenceFromDragTargets = exports.getTimelineSequenceLeftEdgeDragTargets = exports.getTimelineSequenceDurationDragTargets = exports.getTimelineSequenceFromDragKeyframeMoves = exports.getTimelineSequenceFromDragChanges = exports.getTimelineSequenceFromDragValue = exports.getTimelineSequenceDurationDragChanges = exports.getTimelineSequenceLeftEdgeDragChanges = exports.getTimelineSequenceLeftEdgeDragValues = exports.getTimelineSequenceLeftEdgeDragDelta = exports.getTimelineSequenceDurationDragValue = exports.isTimelineSequenceLeftEdgeDraggable = exports.isTimelineSequenceDurationDraggable = exports.isCascadingSequence = exports.isTransitionSeriesSequence = void 0;
3
+ exports.TimelineSequenceRightEdgeDragHandle = exports.useTimelineSequenceFromDrag = exports.TimelineSequenceLeftEdgeDragHandle = exports.getTimelineSequenceFromDragTargets = exports.getTimelineSequenceLeftEdgeDragTargets = exports.getTimelineSequenceDurationDragTargets = exports.getTimelineSequenceFromDragKeyframeMoves = exports.getTimelineSequenceFromDragChanges = exports.getTimelineSequenceFromDragDelta = exports.getTimelineSequenceFromDragValue = exports.getTimelineSequenceDurationDragChanges = exports.getTimelineSequenceLeftEdgeDragChanges = exports.getTimelineSequenceLeftEdgeDragValues = exports.getTimelineSequenceLeftEdgeDragDelta = exports.getTimelineSequenceDurationDragValue = exports.isTimelineSequenceLeftEdgeDraggable = exports.isTimelineSequenceDurationDraggable = exports.isCascadingSequence = exports.isTransitionSeriesSequence = exports.timelineSequenceFromDragSnapThresholdPx = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
@@ -11,10 +11,12 @@ const client_id_1 = require("../../helpers/client-id");
11
11
  const colors_1 = require("../../helpers/colors");
12
12
  const sort_by_nonce_history_1 = require("../../helpers/sort-by-nonce-history");
13
13
  const timeline_layout_1 = require("../../helpers/timeline-layout");
14
+ const editor_snapping_1 = require("../../state/editor-snapping");
14
15
  const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
15
16
  const save_sequence_prop_1 = require("./save-sequence-prop");
16
17
  const TimelineSelection_1 = require("./TimelineSelection");
17
18
  const HANDLE_WIDTH = 6;
19
+ exports.timelineSequenceFromDragSnapThresholdPx = 10;
18
20
  const baseStyle = {
19
21
  position: 'absolute',
20
22
  top: 0,
@@ -252,6 +254,33 @@ const getTimelineSequenceDurationDragChanges = ({ targets, deltaFrames, }) => {
252
254
  exports.getTimelineSequenceDurationDragChanges = getTimelineSequenceDurationDragChanges;
253
255
  const getTimelineSequenceFromDragValue = ({ initialFrom, deltaFrames, }) => initialFrom + deltaFrames;
254
256
  exports.getTimelineSequenceFromDragValue = getTimelineSequenceFromDragValue;
257
+ const getTimelineSequenceFromDragDelta = ({ deltaFrames, pxPerFrame, snappingEnabled, targets, }) => {
258
+ var _a;
259
+ if (!snappingEnabled) {
260
+ return deltaFrames;
261
+ }
262
+ let closestSnap;
263
+ for (const target of targets) {
264
+ if (!target.canSnapToTimelineStart) {
265
+ continue;
266
+ }
267
+ const nextFrom = (0, exports.getTimelineSequenceFromDragValue)({
268
+ initialFrom: target.initialFrom,
269
+ deltaFrames,
270
+ });
271
+ const distancePx = Math.abs(nextFrom * pxPerFrame);
272
+ if (distancePx > exports.timelineSequenceFromDragSnapThresholdPx ||
273
+ (closestSnap && closestSnap.distancePx <= distancePx)) {
274
+ continue;
275
+ }
276
+ closestSnap = {
277
+ deltaFrames: -target.initialFrom,
278
+ distancePx,
279
+ };
280
+ }
281
+ return (_a = closestSnap === null || closestSnap === void 0 ? void 0 : closestSnap.deltaFrames) !== null && _a !== void 0 ? _a : deltaFrames;
282
+ };
283
+ exports.getTimelineSequenceFromDragDelta = getTimelineSequenceFromDragDelta;
255
284
  const getTimelineSequenceFromDragChanges = ({ targets, deltaFrames, }) => {
256
285
  return targets.flatMap((target) => {
257
286
  const nextValue = (0, exports.getTimelineSequenceFromDragValue)({
@@ -456,6 +485,7 @@ const getTimelineSequenceFromDragTargets = ({ draggedNodePathInfo, selectedItems
456
485
  propStatuses,
457
486
  });
458
487
  targets.set(key, {
488
+ canSnapToTimelineStart: originalSequence.parent === null,
459
489
  effectKeyframes,
460
490
  fileName: nodePath.absolutePath,
461
491
  initialFrom: originalSequence.from,
@@ -672,6 +702,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
672
702
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
673
703
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
674
704
  const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
705
+ const { editorSnapping } = (0, react_1.useContext)(editor_snapping_1.EditorSnappingContext);
675
706
  const [dragging, setDragging] = (0, react_1.useState)(false);
676
707
  const dragStateRef = (0, react_1.useRef)(null);
677
708
  const latestRef = (0, react_1.useRef)({
@@ -683,6 +714,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
683
714
  clearEffectDragOverrides,
684
715
  previewServerState,
685
716
  overrideIdToNodePathMappings,
717
+ editorSnapping,
686
718
  });
687
719
  latestRef.current = {
688
720
  nodePathInfo,
@@ -693,6 +725,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
693
725
  clearEffectDragOverrides,
694
726
  previewServerState,
695
727
  overrideIdToNodePathMappings,
728
+ editorSnapping,
696
729
  };
697
730
  const finishDrag = (0, react_1.useCallback)((commit) => {
698
731
  const dragState = dragStateRef.current;
@@ -805,7 +838,12 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
805
838
  return;
806
839
  }
807
840
  const dx = e.clientX - dragState.initialClientX;
808
- const deltaFrames = Math.round(dx / dragState.pxPerFrame);
841
+ const deltaFrames = (0, exports.getTimelineSequenceFromDragDelta)({
842
+ deltaFrames: Math.round(dx / dragState.pxPerFrame),
843
+ pxPerFrame: dragState.pxPerFrame,
844
+ snappingEnabled: latestRef.current.editorSnapping,
845
+ targets: dragState.targets,
846
+ });
809
847
  dragState.latestDeltaFrames = deltaFrames;
810
848
  for (const target of dragState.targets) {
811
849
  const nextFrom = (0, exports.getTimelineSequenceFromDragValue)({
@@ -20,3 +20,20 @@ export declare const callUpdateEffectKeyframeSettings: ({ fileName, nodePath, ef
20
20
  setPropStatuses: SetPropStatuses;
21
21
  clientId: string;
22
22
  }) => Promise<void>;
23
+ type BatchSequenceKeyframeSettingsUpdate = {
24
+ fileName: string;
25
+ nodePath: SequencePropsSubscriptionKey;
26
+ fieldKey: string;
27
+ settings: KeyframeSettings;
28
+ schema: InteractivitySchema;
29
+ };
30
+ type BatchEffectKeyframeSettingsUpdate = BatchSequenceKeyframeSettingsUpdate & {
31
+ effectIndex: number;
32
+ };
33
+ export declare const callBatchUpdateKeyframeSettings: ({ sequenceKeyframes, effectKeyframes, setPropStatuses, clientId, }: {
34
+ sequenceKeyframes: BatchSequenceKeyframeSettingsUpdate[];
35
+ effectKeyframes: BatchEffectKeyframeSettingsUpdate[];
36
+ setPropStatuses: SetPropStatuses;
37
+ clientId: string;
38
+ }) => Promise<void>;
39
+ export {};
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.callUpdateEffectKeyframeSettings = exports.callUpdateSequenceKeyframeSettings = void 0;
3
+ exports.callBatchUpdateKeyframeSettings = exports.callUpdateEffectKeyframeSettings = exports.callUpdateSequenceKeyframeSettings = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
5
  const call_api_1 = require("../call-api");
6
+ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
6
7
  const apply_effect_response_to_prop_statuses_1 = require("./apply-effect-response-to-prop-statuses");
7
8
  const save_prop_queue_1 = require("./save-prop-queue");
8
9
  const callUpdateSequenceKeyframeSettings = ({ fileName, nodePath, fieldKey, settings, schema, setPropStatuses, clientId, }) => {
@@ -50,3 +51,44 @@ const callUpdateEffectKeyframeSettings = ({ fileName, nodePath, effectIndex, fie
50
51
  });
51
52
  };
52
53
  exports.callUpdateEffectKeyframeSettings = callUpdateEffectKeyframeSettings;
54
+ const callBatchUpdateKeyframeSettings = ({ sequenceKeyframes, effectKeyframes, setPropStatuses, clientId, }) => {
55
+ for (const update of sequenceKeyframes) {
56
+ setPropStatuses(update.nodePath, (prev) => (0, studio_shared_1.optimisticUpdateSequenceKeyframeSettings)({
57
+ previous: prev,
58
+ fieldKey: update.fieldKey,
59
+ settings: update.settings,
60
+ }));
61
+ }
62
+ for (const update of effectKeyframes) {
63
+ setPropStatuses(update.nodePath, (prev) => (0, studio_shared_1.optimisticUpdateEffectKeyframeSettings)({
64
+ previous: prev,
65
+ effectIndex: update.effectIndex,
66
+ fieldKey: update.fieldKey,
67
+ settings: update.settings,
68
+ }));
69
+ }
70
+ return (0, call_api_1.callApi)('/api/batch-update-keyframe-settings', {
71
+ sequenceKeyframes: sequenceKeyframes.map((update) => ({
72
+ fileName: update.fileName,
73
+ nodePath: update.nodePath,
74
+ key: update.fieldKey,
75
+ settings: update.settings,
76
+ schema: update.schema,
77
+ })),
78
+ effectKeyframes: effectKeyframes.map((update) => ({
79
+ fileName: update.fileName,
80
+ sequenceNodePath: update.nodePath,
81
+ effectIndex: update.effectIndex,
82
+ key: update.fieldKey,
83
+ settings: update.settings,
84
+ schema: update.schema,
85
+ })),
86
+ clientId,
87
+ })
88
+ .then(() => undefined)
89
+ .catch((err) => {
90
+ (0, NotificationCenter_1.showNotification)(`Could not update keyframe settings: ${err instanceof Error ? err.message : String(err)}`, 4000);
91
+ throw err;
92
+ });
93
+ };
94
+ exports.callBatchUpdateKeyframeSettings = callBatchUpdateKeyframeSettings;
@@ -132,33 +132,36 @@ const updateSelectedTimelineEasings = ({ selections, sequences, overrideIdsToNod
132
132
  if (updates.length === 0) {
133
133
  return null;
134
134
  }
135
- return Promise.all(updates.map((update) => {
136
- const settings = {
137
- type: 'easing',
138
- segmentIndex: update.segmentIndex,
139
- easing,
140
- };
141
- if (update.type === 'sequence') {
142
- return (0, call_update_keyframe_settings_1.callUpdateSequenceKeyframeSettings)({
143
- fileName: update.fileName,
144
- nodePath: update.nodePath,
145
- fieldKey: update.fieldKey,
146
- settings,
147
- schema: update.schema,
148
- setPropStatuses,
149
- clientId,
150
- });
151
- }
152
- return (0, call_update_keyframe_settings_1.callUpdateEffectKeyframeSettings)({
135
+ return (0, call_update_keyframe_settings_1.callBatchUpdateKeyframeSettings)({
136
+ sequenceKeyframes: updates
137
+ .filter((update) => update.type === 'sequence')
138
+ .map((update) => ({
139
+ fileName: update.fileName,
140
+ nodePath: update.nodePath,
141
+ fieldKey: update.fieldKey,
142
+ settings: {
143
+ type: 'easing',
144
+ segmentIndex: update.segmentIndex,
145
+ easing,
146
+ },
147
+ schema: update.schema,
148
+ })),
149
+ effectKeyframes: updates
150
+ .filter((update) => update.type === 'effect')
151
+ .map((update) => ({
153
152
  fileName: update.fileName,
154
153
  nodePath: update.nodePath,
155
154
  effectIndex: update.effectIndex,
156
155
  fieldKey: update.fieldKey,
157
- settings,
156
+ settings: {
157
+ type: 'easing',
158
+ segmentIndex: update.segmentIndex,
159
+ easing,
160
+ },
158
161
  schema: update.schema,
159
- setPropStatuses,
160
- clientId,
161
- });
162
- })).then(() => undefined);
162
+ })),
163
+ setPropStatuses,
164
+ clientId,
165
+ });
163
166
  };
164
167
  exports.updateSelectedTimelineEasings = updateSelectedTimelineEasings;
@@ -2,6 +2,11 @@ import type { CanUpdateSequencePropStatus, SequencePropsSubscriptionKey, TSequen
2
2
  import type { ComboboxValue } from '../NewComposition/ComboBox';
3
3
  import { type SetPropStatuses } from './save-sequence-prop';
4
4
  export declare const shouldShowFreezeFrameMenuItem: (sequence: TSequence) => boolean;
5
+ export declare const calculateSequenceFreezeFrame: ({ sequence, sequenceFrameOffset, timelinePosition, }: {
6
+ readonly sequence: TSequence;
7
+ readonly sequenceFrameOffset: number;
8
+ readonly timelinePosition: number;
9
+ }) => number;
5
10
  export declare const useSequenceFreezeFrameMenuItem: ({ clientId, nodePath, propStatusesForOverride, sequence, sequenceFrameOffset, setPropStatuses, timelinePosition, validatedSource, }: {
6
11
  readonly clientId: string | null;
7
12
  readonly nodePath: SequencePropsSubscriptionKey | null;
@@ -1,12 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useSequenceFreezeFrameMenuItem = exports.shouldShowFreezeFrameMenuItem = void 0;
3
+ exports.useSequenceFreezeFrameMenuItem = exports.calculateSequenceFreezeFrame = exports.shouldShowFreezeFrameMenuItem = void 0;
4
4
  const react_1 = require("react");
5
5
  const save_sequence_prop_1 = require("./save-sequence-prop");
6
6
  const shouldShowFreezeFrameMenuItem = (sequence) => {
7
7
  return sequence.type !== 'audio';
8
8
  };
9
9
  exports.shouldShowFreezeFrameMenuItem = shouldShowFreezeFrameMenuItem;
10
+ const calculateSequenceFreezeFrame = ({ sequence, sequenceFrameOffset, timelinePosition, }) => {
11
+ const rawFreezeFrame = Math.round(timelinePosition - sequence.from + sequenceFrameOffset);
12
+ const minFrame = sequenceFrameOffset;
13
+ const maxFrame = Number.isFinite(sequence.duration)
14
+ ? Math.max(minFrame, sequence.duration + sequenceFrameOffset - 1)
15
+ : Infinity;
16
+ return Math.min(Math.max(minFrame, rawFreezeFrame), maxFrame);
17
+ };
18
+ exports.calculateSequenceFreezeFrame = calculateSequenceFreezeFrame;
10
19
  const useSequenceFreezeFrameMenuItem = ({ clientId, nodePath, propStatusesForOverride, sequence, sequenceFrameOffset, setPropStatuses, timelinePosition, validatedSource, }) => {
11
20
  const freezeStatus = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.freeze;
12
21
  const isFrozen = (freezeStatus === null || freezeStatus === void 0 ? void 0 : freezeStatus.status) === 'static' &&
@@ -26,11 +35,11 @@ const useSequenceFreezeFrameMenuItem = ({ clientId, nodePath, propStatusesForOve
26
35
  clientId === null) {
27
36
  return;
28
37
  }
29
- const rawFreezeFrame = Math.round(timelinePosition - sequence.from + sequenceFrameOffset);
30
- const maxFrame = Number.isFinite(sequence.duration)
31
- ? Math.max(0, sequence.duration - 1)
32
- : rawFreezeFrame;
33
- const freezeFrame = Math.min(Math.max(0, rawFreezeFrame), maxFrame);
38
+ const freezeFrame = (0, exports.calculateSequenceFreezeFrame)({
39
+ sequence,
40
+ sequenceFrameOffset,
41
+ timelinePosition,
42
+ });
34
43
  const remove = isFrozen;
35
44
  (0, save_sequence_prop_1.saveSequenceProps)({
36
45
  addedKeyframes: null,
@@ -55,9 +64,7 @@ const useSequenceFreezeFrameMenuItem = ({ clientId, nodePath, propStatusesForOve
55
64
  clientId,
56
65
  isFrozen,
57
66
  nodePath,
58
- sequence.controls,
59
- sequence.duration,
60
- sequence.from,
67
+ sequence,
61
68
  sequenceFrameOffset,
62
69
  setPropStatuses,
63
70
  timelinePosition,
@@ -44,7 +44,7 @@ const useTimelineAssetDrop = () => {
44
44
  compositionFile,
45
45
  compositionId: currentCompositionId,
46
46
  });
47
- const previewInteractive = previewServerState.type === 'connected' && interactivity_enabled_1.studioInteractivityEnabled;
47
+ const previewInteractive = previewServerState.type === 'connected' && (0, interactivity_enabled_1.isStudioInteractivityEnabled)();
48
48
  const canInsertAsset = previewInteractive &&
49
49
  !window.remotion_isReadOnlyStudio &&
50
50
  (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === true &&