@remotion/studio 4.0.497 → 4.0.499

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 (84) hide show
  1. package/dist/components/AssetSelectorItem.js +31 -3
  2. package/dist/components/Canvas.js +162 -7
  3. package/dist/components/Checkbox.js +1 -1
  4. package/dist/components/CompositionSelector.js +13 -10
  5. package/dist/components/CompositionSelectorItem.js +21 -13
  6. package/dist/components/ConfigureLicenseModal.d.ts +4 -0
  7. package/dist/components/ConfigureLicenseModal.js +194 -0
  8. package/dist/components/Editor.d.ts +0 -1
  9. package/dist/components/Editor.js +2 -3
  10. package/dist/components/EditorContent.js +1 -1
  11. package/dist/components/EditorRuler/Ruler.js +5 -3
  12. package/dist/components/ForceSpecificCursor.js +13 -1
  13. package/dist/components/InspectorPanel/CompositionInspector.js +2 -1
  14. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -4
  15. package/dist/components/InspectorPanel/use-composition-actions.js +1 -1
  16. package/dist/components/LicenseKeyValidation.d.ts +17 -0
  17. package/dist/components/LicenseKeyValidation.js +113 -0
  18. package/dist/components/Modals.js +2 -1
  19. package/dist/components/NewComposition/InputDragger.d.ts +27 -0
  20. package/dist/components/NewComposition/InputDragger.js +151 -23
  21. package/dist/components/RenderButton.js +0 -1
  22. package/dist/components/RenderModal/WebRenderModal.js +14 -8
  23. package/dist/components/SelectedOutlineOverlay.js +1 -1
  24. package/dist/components/Splitter/SplitterContainer.d.ts +2 -0
  25. package/dist/components/Splitter/SplitterContainer.js +5 -1
  26. package/dist/components/Splitter/SplitterContext.d.ts +2 -0
  27. package/dist/components/Splitter/SplitterContext.js +2 -0
  28. package/dist/components/Splitter/SplitterElement.js +6 -1
  29. package/dist/components/Splitter/SplitterHandle.js +27 -2
  30. package/dist/components/Timeline/MaxTimelineTracks.d.ts +0 -1
  31. package/dist/components/Timeline/MaxTimelineTracks.js +3 -3
  32. package/dist/components/Timeline/Timeline.js +10 -9
  33. package/dist/components/Timeline/TimelineDragHandler.js +1 -1
  34. package/dist/components/Timeline/TimelineInOutDragHandler.js +25 -1
  35. package/dist/components/Timeline/TimelineLayerEye.js +4 -1
  36. package/dist/components/Timeline/TimelineSelection.js +1 -1
  37. package/dist/components/Timeline/TimelineSequence.js +12 -7
  38. package/dist/components/Timeline/TimelineSequenceItem.js +5 -5
  39. package/dist/components/Timeline/TimelineSequenceName.js +1 -0
  40. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +13 -1
  41. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +68 -12
  42. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +17 -0
  43. package/dist/components/Timeline/call-update-keyframe-settings.js +43 -1
  44. package/dist/components/Timeline/update-selected-easing.js +26 -23
  45. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +5 -0
  46. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +16 -9
  47. package/dist/components/Timeline/use-timeline-asset-drop.js +1 -1
  48. package/dist/components/Timeline/use-timeline-keyframe-drag.js +6 -4
  49. package/dist/components/TopPanel.js +2 -1
  50. package/dist/components/composition-drop-preview.d.ts +33 -0
  51. package/dist/components/composition-drop-preview.js +67 -0
  52. package/dist/components/drop-handler-data.d.ts +1 -1
  53. package/dist/components/drop-handler-data.js +27 -60
  54. package/dist/components/effect-drag-and-drop.d.ts +1 -1
  55. package/dist/components/effect-drag-and-drop.js +7 -55
  56. package/dist/components/element-drag-and-drop.d.ts +1 -1
  57. package/dist/components/element-drag-and-drop.js +5 -17
  58. package/dist/components/handle-drop.js +0 -1
  59. package/dist/components/import-assets.d.ts +7 -8
  60. package/dist/components/import-assets.js +2 -9
  61. package/dist/esm/{chunk-5wj95bdd.js → chunk-pk1zwsn1.js} +5972 -4763
  62. package/dist/esm/index.mjs +0 -19
  63. package/dist/esm/internals.mjs +5972 -4763
  64. package/dist/esm/previewEntry.mjs +10765 -9556
  65. package/dist/esm/renderEntry.mjs +1 -1
  66. package/dist/helpers/get-effective-translation.d.ts +13 -1
  67. package/dist/helpers/get-effective-translation.js +12 -6
  68. package/dist/helpers/interactivity-enabled.d.ts +1 -1
  69. package/dist/helpers/interactivity-enabled.js +2 -2
  70. package/dist/helpers/retry-payload.js +0 -1
  71. package/dist/helpers/ruler-canvas-size.d.ts +7 -0
  72. package/dist/helpers/ruler-canvas-size.js +14 -1
  73. package/dist/helpers/use-image-metadata.d.ts +1 -0
  74. package/dist/helpers/use-image-metadata.js +8 -5
  75. package/dist/helpers/use-media-metadata.d.ts +1 -0
  76. package/dist/helpers/use-media-metadata.js +8 -5
  77. package/dist/helpers/use-menu-structure.js +9 -3
  78. package/dist/state/modals.d.ts +3 -1
  79. package/dist/visual-controls/VisualControls.js +1 -1
  80. package/package.json +13 -12
  81. package/dist/components/RenderModal/WebRenderModalLicense.d.ts +0 -9
  82. package/dist/components/RenderModal/WebRenderModalLicense.js +0 -189
  83. package/dist/components/RenderModal/WebRenderModalLicenseKeyDetails.d.ts +0 -13
  84. package/dist/components/RenderModal/WebRenderModalLicenseKeyDetails.js +0 -60
@@ -252,17 +252,41 @@ const TimelineInOutDragHandlerInner = () => {
252
252
  videoConfig,
253
253
  width,
254
254
  ]);
255
+ const onPointerCancelInOut = (0, react_1.useCallback)(() => {
256
+ document.body.style.userSelect = '';
257
+ document.body.style.webkitUserSelect = '';
258
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
259
+ setInOutDragging({
260
+ dragging: false,
261
+ });
262
+ }, []);
255
263
  (0, react_1.useEffect)(() => {
256
264
  if (inOutDragging.dragging === false) {
257
265
  return;
258
266
  }
259
267
  window.addEventListener('pointermove', onPointerMoveInOut);
260
268
  window.addEventListener('pointerup', onPointerUpInOut);
269
+ window.addEventListener('pointercancel', onPointerCancelInOut);
270
+ window.addEventListener('blur', onPointerCancelInOut);
261
271
  return () => {
262
272
  window.removeEventListener('pointermove', onPointerMoveInOut);
263
273
  window.removeEventListener('pointerup', onPointerUpInOut);
274
+ window.removeEventListener('pointercancel', onPointerCancelInOut);
275
+ window.removeEventListener('blur', onPointerCancelInOut);
276
+ };
277
+ }, [
278
+ inOutDragging.dragging,
279
+ onPointerCancelInOut,
280
+ onPointerMoveInOut,
281
+ onPointerUpInOut,
282
+ ]);
283
+ (0, react_1.useEffect)(() => {
284
+ return () => {
285
+ document.body.style.userSelect = '';
286
+ document.body.style.webkitUserSelect = '';
287
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
264
288
  };
265
- }, [inOutDragging.dragging, onPointerMoveInOut, onPointerUpInOut]);
289
+ }, []);
266
290
  const inContextMenu = (0, react_1.useMemo)(() => {
267
291
  return [
268
292
  {
@@ -64,7 +64,10 @@ const TimelineLayerEye = ({ onInvoked, hidden, type }) => {
64
64
  onInvoked(layerPointedDown);
65
65
  }
66
66
  }, [onInvoked]);
67
- return (jsx_runtime_1.jsx("div", { style: exports.timelineLayerIconContainer, draggable: false, onDragStart: onDragStart, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, children: renderAction(colors_1.LIGHT_COLOR) }));
67
+ const onDoubleClick = (0, react_1.useCallback)((e) => {
68
+ e.stopPropagation();
69
+ }, []);
70
+ return (jsx_runtime_1.jsx("div", { style: exports.timelineLayerIconContainer, draggable: false, onDragStart: onDragStart, onDoubleClick: onDoubleClick, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, children: renderAction(colors_1.LIGHT_COLOR) }));
68
71
  };
69
72
  exports.TimelineLayerEye = TimelineLayerEye;
70
73
  const spacerStyle = {
@@ -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,20 @@ 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 durationCanResize = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
189
+ (0, TimelineSequenceRightEdgeDragHandle_1.canResizeTimelineSequenceDuration)({
190
+ sequence: s,
191
+ status: propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames,
192
+ }));
193
+ const fromCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
189
194
  ((_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 &&
195
+ const trimBeforeCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
191
196
  ((_c = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.trimBefore) === null || _c === void 0 ? void 0 : _c.status) === 'static');
192
197
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
193
198
  const previewConnected = previewServerState.type === 'connected';
194
- const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
199
+ const previewInteractive = previewConnected && (0, interactivity_enabled_1.isStudioInteractivityEnabled)();
195
200
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
196
201
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
197
202
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
@@ -346,7 +351,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
346
351
  disableInteractivityDisabled,
347
352
  duplicateDisabled,
348
353
  fileLocation,
349
- includeSourceEditItems: interactivity_enabled_1.studioInteractivityEnabled,
354
+ includeSourceEditItems: (0, interactivity_enabled_1.isStudioInteractivityEnabled)(),
350
355
  onDeleteSequenceFromSource,
351
356
  onDisableSequenceInteractivity,
352
357
  onDuplicateSequenceFromSource,
@@ -354,7 +359,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
354
359
  originalLocation,
355
360
  selectAsset,
356
361
  sequence: s,
357
- sourceActions: interactivity_enabled_1.studioInteractivityEnabled && freezeFrameMenuItem
362
+ sourceActions: (0, interactivity_enabled_1.isStudioInteractivityEnabled)() && freezeFrameMenuItem
358
363
  ? [freezeFrameMenuItem]
359
364
  : [],
360
365
  });
@@ -446,7 +451,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
446
451
  const showRightEdgeDragHandle = (0, TimelineSequenceRightEdgeDragHandle_1.isTimelineSequenceDurationDraggable)(s) &&
447
452
  nodePath !== null &&
448
453
  validatedLocation !== null &&
449
- durationCanUpdate;
454
+ durationCanResize;
450
455
  const showLeftEdgeDragHandle = (0, TimelineSequenceRightEdgeDragHandle_1.isTimelineSequenceLeftEdgeDraggable)(s) &&
451
456
  nodePath !== null &&
452
457
  validatedLocation !== null &&
@@ -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 &&
@@ -24,6 +24,7 @@ const TimelineSequenceName = ({ displayName, fallbackDisplayName, selected, cont
24
24
  alignSelf: 'stretch',
25
25
  ...(0, TimelineSelection_1.getTimelineSelectedLabelStyle)(selected, false),
26
26
  display: 'inline-flex',
27
+ flexShrink: 0,
27
28
  fontFamily: 'inherit',
28
29
  fontSize: 12,
29
30
  lineHeight: 'normal',
@@ -1,9 +1,10 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatusKeyframed, OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, TSequence, InteractivitySchema } from 'remotion';
2
+ import type { CanUpdateSequencePropStatus, CanUpdateSequencePropStatusKeyframed, OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, TSequence, InteractivitySchema } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
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;
@@ -40,6 +42,10 @@ type TimelineSequenceEffectKeyframeDragTarget = TimelineSequenceKeyframeDragTarg
40
42
  export declare const isTransitionSeriesSequence: (sequence: TSequence) => boolean;
41
43
  export declare const isCascadingSequence: (sequence: TSequence) => boolean;
42
44
  export declare const isTimelineSequenceDurationDraggable: (sequence: TSequence) => boolean;
45
+ export declare const canResizeTimelineSequenceDuration: ({ sequence, status, }: {
46
+ readonly sequence: TSequence;
47
+ readonly status: CanUpdateSequencePropStatus | undefined;
48
+ }) => boolean;
43
49
  export declare const isTimelineSequenceLeftEdgeDraggable: (sequence: TSequence) => boolean;
44
50
  export declare const getTimelineSequenceDurationDragValue: ({ initialDuration, deltaFrames, minimumDuration, }: {
45
51
  readonly initialDuration: number;
@@ -77,6 +83,12 @@ export declare const getTimelineSequenceFromDragValue: ({ initialFrom, deltaFram
77
83
  readonly initialFrom: number;
78
84
  readonly deltaFrames: number;
79
85
  }) => number;
86
+ export declare const getTimelineSequenceFromDragDelta: ({ deltaFrames, pxPerFrame, snappingEnabled, targets, }: {
87
+ readonly deltaFrames: number;
88
+ readonly pxPerFrame: number;
89
+ readonly snappingEnabled: boolean;
90
+ readonly targets: readonly TimelineSequenceFromDragTarget[];
91
+ }) => number;
80
92
  export declare const getTimelineSequenceFromDragChanges: ({ targets, deltaFrames, }: {
81
93
  readonly targets: readonly TimelineSequenceFromDragTarget[];
82
94
  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.canResizeTimelineSequenceDuration = 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,
@@ -127,6 +129,16 @@ const isTimelineSequenceDurationDraggable = (sequence) => {
127
129
  Boolean(sequence.controls));
128
130
  };
129
131
  exports.isTimelineSequenceDurationDraggable = isTimelineSequenceDurationDraggable;
132
+ const canResizeTimelineSequenceDuration = ({ sequence, status, }) => {
133
+ if ((status === null || status === void 0 ? void 0 : status.status) !== 'static') {
134
+ return false;
135
+ }
136
+ if (sequence.type === 'audio' || sequence.type === 'video') {
137
+ return status.codeValue !== undefined;
138
+ }
139
+ return true;
140
+ };
141
+ exports.canResizeTimelineSequenceDuration = canResizeTimelineSequenceDuration;
130
142
  const isTimelineSequenceLeftEdgeDraggable = (sequence) => {
131
143
  return ((!sequence.isInsideSeries || (0, exports.isCascadingSequence)(sequence)) &&
132
144
  Boolean(sequence.controls) &&
@@ -252,6 +264,33 @@ const getTimelineSequenceDurationDragChanges = ({ targets, deltaFrames, }) => {
252
264
  exports.getTimelineSequenceDurationDragChanges = getTimelineSequenceDurationDragChanges;
253
265
  const getTimelineSequenceFromDragValue = ({ initialFrom, deltaFrames, }) => initialFrom + deltaFrames;
254
266
  exports.getTimelineSequenceFromDragValue = getTimelineSequenceFromDragValue;
267
+ const getTimelineSequenceFromDragDelta = ({ deltaFrames, pxPerFrame, snappingEnabled, targets, }) => {
268
+ var _a;
269
+ if (!snappingEnabled) {
270
+ return deltaFrames;
271
+ }
272
+ let closestSnap;
273
+ for (const target of targets) {
274
+ if (!target.canSnapToTimelineStart) {
275
+ continue;
276
+ }
277
+ const nextFrom = (0, exports.getTimelineSequenceFromDragValue)({
278
+ initialFrom: target.initialFrom,
279
+ deltaFrames,
280
+ });
281
+ const distancePx = Math.abs(nextFrom * pxPerFrame);
282
+ if (distancePx > exports.timelineSequenceFromDragSnapThresholdPx ||
283
+ (closestSnap && closestSnap.distancePx <= distancePx)) {
284
+ continue;
285
+ }
286
+ closestSnap = {
287
+ deltaFrames: -target.initialFrom,
288
+ distancePx,
289
+ };
290
+ }
291
+ return (_a = closestSnap === null || closestSnap === void 0 ? void 0 : closestSnap.deltaFrames) !== null && _a !== void 0 ? _a : deltaFrames;
292
+ };
293
+ exports.getTimelineSequenceFromDragDelta = getTimelineSequenceFromDragDelta;
255
294
  const getTimelineSequenceFromDragChanges = ({ targets, deltaFrames, }) => {
256
295
  return targets.flatMap((target) => {
257
296
  const nextValue = (0, exports.getTimelineSequenceFromDragValue)({
@@ -309,6 +348,7 @@ const findSequenceTrack = ({ tracks, nodePathInfo, }) => {
309
348
  });
310
349
  };
311
350
  const getTimelineSequenceDurationDragTargets = ({ draggedNodePathInfo, selectedItems, sequences, overrideIdsToNodePaths, propStatuses, }) => {
351
+ var _a;
312
352
  const draggedSelectionKey = (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(draggedNodePathInfo);
313
353
  const selectedSequenceItems = selectedItems.filter((item) => item.type === 'sequence');
314
354
  const draggedItemIsSelected = selectedSequenceItems.some((item) => (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(item.nodePathInfo) ===
@@ -334,7 +374,11 @@ const getTimelineSequenceDurationDragTargets = ({ draggedNodePathInfo, selectedI
334
374
  return null;
335
375
  }
336
376
  const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
337
- if (!canUpdateDurationInFrames({ propStatuses, nodePath })) {
377
+ const durationStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a.durationInFrames;
378
+ if (!(0, exports.canResizeTimelineSequenceDuration)({
379
+ sequence: originalSequence,
380
+ status: durationStatus,
381
+ })) {
338
382
  return null;
339
383
  }
340
384
  const { controls } = originalSequence;
@@ -456,6 +500,7 @@ const getTimelineSequenceFromDragTargets = ({ draggedNodePathInfo, selectedItems
456
500
  propStatuses,
457
501
  });
458
502
  targets.set(key, {
503
+ canSnapToTimelineStart: originalSequence.parent === null,
459
504
  effectKeyframes,
460
505
  fileName: nodePath.absolutePath,
461
506
  initialFrom: originalSequence.from,
@@ -513,14 +558,14 @@ const TimelineSequenceLeftEdgeDragHandle = ({ nodePathInfo, windowWidth, timelin
513
558
  };
514
559
  const finishDrag = (0, react_1.useCallback)((commit) => {
515
560
  const dragState = dragStateRef.current;
561
+ if (!dragState) {
562
+ return;
563
+ }
516
564
  dragStateRef.current = null;
517
565
  document.body.style.userSelect = '';
518
566
  document.body.style.webkitUserSelect = '';
519
567
  (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
520
568
  setDragging(false);
521
- if (!dragState) {
522
- return;
523
- }
524
569
  const { setPropStatuses: latestSetPropStatuses, clearDragOverrides: latestClear, previewServerState: latestServerState, } = latestRef.current;
525
570
  const changes = (0, exports.getTimelineSequenceLeftEdgeDragChanges)({
526
571
  targets: dragState.targets,
@@ -655,6 +700,7 @@ const TimelineSequenceLeftEdgeDragHandle = ({ nodePathInfo, windowWidth, timelin
655
700
  window.removeEventListener('pointerup', onUp);
656
701
  window.removeEventListener('pointercancel', onCancel);
657
702
  window.removeEventListener('blur', onWindowBlur);
703
+ finishDrag(false);
658
704
  };
659
705
  }, [dragging, finishDrag]);
660
706
  const style = {
@@ -672,6 +718,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
672
718
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
673
719
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
674
720
  const currentSelection = (0, TimelineSelection_1.useCurrentTimelineSelectionStateAsRef)();
721
+ const { editorSnapping } = (0, react_1.useContext)(editor_snapping_1.EditorSnappingContext);
675
722
  const [dragging, setDragging] = (0, react_1.useState)(false);
676
723
  const dragStateRef = (0, react_1.useRef)(null);
677
724
  const latestRef = (0, react_1.useRef)({
@@ -683,6 +730,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
683
730
  clearEffectDragOverrides,
684
731
  previewServerState,
685
732
  overrideIdToNodePathMappings,
733
+ editorSnapping,
686
734
  });
687
735
  latestRef.current = {
688
736
  nodePathInfo,
@@ -693,16 +741,17 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
693
741
  clearEffectDragOverrides,
694
742
  previewServerState,
695
743
  overrideIdToNodePathMappings,
744
+ editorSnapping,
696
745
  };
697
746
  const finishDrag = (0, react_1.useCallback)((commit) => {
698
747
  const dragState = dragStateRef.current;
748
+ if (!dragState) {
749
+ return;
750
+ }
699
751
  dragStateRef.current = null;
700
752
  document.body.style.userSelect = '';
701
753
  document.body.style.webkitUserSelect = '';
702
754
  setDragging(false);
703
- if (!dragState) {
704
- return;
705
- }
706
755
  const { setPropStatuses: latestSetPropStatuses, clearDragOverrides: latestClear, clearEffectDragOverrides: latestClearEffect, previewServerState: latestServerState, } = latestRef.current;
707
756
  const changes = (0, exports.getTimelineSequenceFromDragChanges)({
708
757
  targets: dragState.targets,
@@ -805,7 +854,12 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
805
854
  return;
806
855
  }
807
856
  const dx = e.clientX - dragState.initialClientX;
808
- const deltaFrames = Math.round(dx / dragState.pxPerFrame);
857
+ const deltaFrames = (0, exports.getTimelineSequenceFromDragDelta)({
858
+ deltaFrames: Math.round(dx / dragState.pxPerFrame),
859
+ pxPerFrame: dragState.pxPerFrame,
860
+ snappingEnabled: latestRef.current.editorSnapping,
861
+ targets: dragState.targets,
862
+ });
809
863
  dragState.latestDeltaFrames = deltaFrames;
810
864
  for (const target of dragState.targets) {
811
865
  const nextFrom = (0, exports.getTimelineSequenceFromDragValue)({
@@ -859,6 +913,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
859
913
  window.removeEventListener('pointerup', onUp);
860
914
  window.removeEventListener('pointercancel', onCancel);
861
915
  window.removeEventListener('blur', onWindowBlur);
916
+ finishDrag(false);
862
917
  };
863
918
  }, [dragging, finishDrag]);
864
919
  return {
@@ -895,14 +950,14 @@ const TimelineSequenceRightEdgeDragHandle = ({ nodePathInfo, windowWidth, timeli
895
950
  };
896
951
  const finishDrag = (0, react_1.useCallback)((commit) => {
897
952
  const dragState = dragStateRef.current;
953
+ if (!dragState) {
954
+ return;
955
+ }
898
956
  dragStateRef.current = null;
899
957
  document.body.style.userSelect = '';
900
958
  document.body.style.webkitUserSelect = '';
901
959
  (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
902
960
  setDragging(false);
903
- if (!dragState) {
904
- return;
905
- }
906
961
  const { setPropStatuses: latestSetPropStatuses, clearDragOverrides: latestClear, previewServerState: latestServerState, } = latestRef.current;
907
962
  const changes = (0, exports.getTimelineSequenceDurationDragChanges)({
908
963
  targets: dragState.targets,
@@ -1031,6 +1086,7 @@ const TimelineSequenceRightEdgeDragHandle = ({ nodePathInfo, windowWidth, timeli
1031
1086
  window.removeEventListener('pointerup', onUp);
1032
1087
  window.removeEventListener('pointercancel', onCancel);
1033
1088
  window.removeEventListener('blur', onWindowBlur);
1089
+ finishDrag(false);
1034
1090
  };
1035
1091
  }, [dragging, finishDrag]);
1036
1092
  const style = {
@@ -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 &&