@remotion/studio 4.0.513 → 4.0.514

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 (174) hide show
  1. package/dist/Studio.js +2 -1
  2. package/dist/components/AskAiModal.js +1 -1
  3. package/dist/components/AssetSelector.js +2 -0
  4. package/dist/components/AssetSelectorItem.js +1 -2
  5. package/dist/components/AudioWaveform.d.ts +3 -0
  6. package/dist/components/AudioWaveform.js +55 -67
  7. package/dist/components/Canvas.js +40 -5
  8. package/dist/components/CanvasOrLoading.js +5 -0
  9. package/dist/components/CompositionSelector.js +2 -0
  10. package/dist/components/ConfigureDefaultEditorModal.js +17 -11
  11. package/dist/components/Editor.js +16 -1
  12. package/dist/components/ElementInstallConfirmation.d.ts +1 -0
  13. package/dist/components/ElementInstallConfirmation.js +4 -2
  14. package/dist/components/FixComputedValueModal.d.ts +9 -0
  15. package/dist/components/FixComputedValueModal.js +217 -0
  16. package/dist/components/InitialCompositionLoader.js +19 -0
  17. package/dist/components/InlineDropdown.js +4 -4
  18. package/dist/components/InspectorInfoHeader.js +3 -3
  19. package/dist/components/InspectorOpenInEditor.js +3 -1
  20. package/dist/components/InspectorPanel/CompositionInspector.js +11 -1
  21. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +2 -2
  22. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +1 -1
  23. package/dist/components/InspectorPanel/EasingInspector.js +1 -1
  24. package/dist/components/InspectorPanel/KeyframeInspector.js +2 -2
  25. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +1 -1
  26. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +35 -6
  27. package/dist/components/InspectorPanel/common.d.ts +5 -5
  28. package/dist/components/InspectorPanel/common.js +8 -8
  29. package/dist/components/InspectorPanel/styles.d.ts +1 -1
  30. package/dist/components/InspectorPanel/styles.js +4 -2
  31. package/dist/components/InspectorSourceLocation.d.ts +1 -1
  32. package/dist/components/InspectorSourceLocation.js +2 -2
  33. package/dist/components/LicenseKeyValidation.js +2 -2
  34. package/dist/components/Modals.js +2 -1
  35. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  36. package/dist/components/NewComposition/CodemodFooter.js +10 -8
  37. package/dist/components/NewComposition/DeleteComposition.js +1 -1
  38. package/dist/components/NewComposition/DeleteFolder.js +1 -1
  39. package/dist/components/NewComposition/DuplicateComposition.js +7 -2
  40. package/dist/components/NewComposition/NewComposition.js +1 -1
  41. package/dist/components/NewComposition/NewFolder.js +1 -1
  42. package/dist/components/NewComposition/RenameComposition.js +1 -1
  43. package/dist/components/NewComposition/RenameFolder.js +1 -1
  44. package/dist/components/NewComposition/duplicate-composition-api.d.ts +16 -0
  45. package/dist/components/NewComposition/duplicate-composition-api.js +16 -0
  46. package/dist/components/NoRegisterRoot.js +1 -1
  47. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +4 -3
  48. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -0
  49. package/dist/components/QuickSwitcher/fuzzy-search.js +1 -1
  50. package/dist/components/RefreshCompositionOverlay.js +1 -1
  51. package/dist/components/RenderButton.js +6 -3
  52. package/dist/components/RenderModal/WebRenderModal.js +6 -2
  53. package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +2 -0
  54. package/dist/components/RenderModal/WebRenderModalAdvanced.js +9 -2
  55. package/dist/components/RenderModal/render-modals.js +5 -1
  56. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +5 -1
  57. package/dist/components/RenderQueue/actions.js +12 -2
  58. package/dist/components/RenderQueue/client-side-render-types.d.ts +1 -0
  59. package/dist/components/RenderingSettings.d.ts +2 -0
  60. package/dist/components/RenderingSettings.js +355 -0
  61. package/dist/components/SelectedOutlineElement.js +3 -3
  62. package/dist/components/SelectedOutlinePolygon.d.ts +1 -0
  63. package/dist/components/SelectedOutlinePolygon.js +53 -9
  64. package/dist/components/SettingsContext.d.ts +4 -1
  65. package/dist/components/SettingsContext.js +9 -2
  66. package/dist/components/SettingsModal.d.ts +1 -1
  67. package/dist/components/SettingsModal.js +10 -1
  68. package/dist/components/SettingsModalFooter.js +1 -1
  69. package/dist/components/StudioSettings.d.ts +2 -0
  70. package/dist/components/StudioSettings.js +185 -0
  71. package/dist/components/Timeline/LoopedIndicator.js +1 -1
  72. package/dist/components/Timeline/LoopedTimelineIndicators.d.ts +3 -0
  73. package/dist/components/Timeline/LoopedTimelineIndicators.js +22 -14
  74. package/dist/components/Timeline/Timeline.js +11 -9
  75. package/dist/components/Timeline/TimelineAssetField.d.ts +2 -2
  76. package/dist/components/Timeline/TimelineAssetField.js +1 -1
  77. package/dist/components/Timeline/TimelineDragHandler.js +62 -76
  78. package/dist/components/Timeline/TimelineEffectItem.js +1 -1
  79. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +4 -2
  80. package/dist/components/Timeline/TimelineEffectPropItem.js +16 -11
  81. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -1
  82. package/dist/components/Timeline/TimelineExpandedRow.js +4 -4
  83. package/dist/components/Timeline/TimelineExpandedSection.js +1 -1
  84. package/dist/components/Timeline/TimelineHeightContainer.d.ts +0 -4
  85. package/dist/components/Timeline/TimelineHeightContainer.js +4 -4
  86. package/dist/components/Timeline/TimelineImageInfo.d.ts +1 -0
  87. package/dist/components/Timeline/TimelineImageInfo.js +3 -2
  88. package/dist/components/Timeline/TimelineKeyframeControls.js +6 -1
  89. package/dist/components/Timeline/TimelineList.d.ts +1 -5
  90. package/dist/components/Timeline/TimelineList.js +14 -9
  91. package/dist/components/Timeline/TimelinePinchZoom.js +5 -5
  92. package/dist/components/Timeline/TimelineRowChrome.d.ts +0 -2
  93. package/dist/components/Timeline/TimelineRowChrome.js +12 -5
  94. package/dist/components/Timeline/TimelineSchemaField.d.ts +7 -3
  95. package/dist/components/Timeline/TimelineSchemaField.js +71 -13
  96. package/dist/components/Timeline/TimelineScrollable.js +3 -1
  97. package/dist/components/Timeline/TimelineSelection.d.ts +5 -2
  98. package/dist/components/Timeline/TimelineSelection.js +90 -103
  99. package/dist/components/Timeline/TimelineSequence.js +59 -25
  100. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -1
  101. package/dist/components/Timeline/TimelineSequenceItem.js +15 -9
  102. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +2 -1
  103. package/dist/components/Timeline/TimelineSequencePropItem.js +3 -3
  104. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +33 -10
  105. package/dist/components/Timeline/TimelineSlider.js +42 -33
  106. package/dist/components/Timeline/TimelineTimeIndicators.js +90 -98
  107. package/dist/components/Timeline/TimelineTracks.d.ts +0 -2
  108. package/dist/components/Timeline/TimelineTracks.js +11 -4
  109. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  110. package/dist/components/Timeline/TimelineVideoInfo.d.ts +4 -4
  111. package/dist/components/Timeline/TimelineVideoInfo.js +151 -61
  112. package/dist/components/Timeline/TimelineViewport.d.ts +12 -0
  113. package/dist/components/Timeline/TimelineViewport.js +62 -0
  114. package/dist/components/Timeline/TimelineVirtualization.d.ts +22 -0
  115. package/dist/components/Timeline/TimelineVirtualization.js +144 -0
  116. package/dist/components/Timeline/TimelineZoomControls.js +16 -8
  117. package/dist/components/Timeline/call-add-keyframe.js +31 -3
  118. package/dist/components/Timeline/call-delete-keyframe.js +13 -3
  119. package/dist/components/Timeline/call-move-keyframe.js +11 -1
  120. package/dist/components/Timeline/call-update-keyframe-settings.js +31 -3
  121. package/dist/components/Timeline/delete-selected-timeline-item.js +2 -1
  122. package/dist/components/Timeline/get-timeline-keyframes.d.ts +1 -2
  123. package/dist/components/Timeline/get-timeline-keyframes.js +1 -8
  124. package/dist/components/Timeline/get-timeline-sequence-visible-layout.d.ts +30 -0
  125. package/dist/components/Timeline/get-timeline-sequence-visible-layout.js +61 -0
  126. package/dist/components/Timeline/split-selected-timeline-item.js +2 -2
  127. package/dist/components/Timeline/timeline-scroll-logic.d.ts +24 -0
  128. package/dist/components/Timeline/timeline-scroll-logic.js +127 -4
  129. package/dist/components/Timeline/use-timeline-height.d.ts +3 -5
  130. package/dist/components/Timeline/use-timeline-height.js +16 -18
  131. package/dist/components/UpdateCheck.d.ts +2 -10
  132. package/dist/components/UpdateCheck.js +8 -2
  133. package/dist/components/VisualControls/VisualControlHandle.js +8 -0
  134. package/dist/components/delete-jsx-node-api.d.ts +2 -0
  135. package/dist/components/delete-jsx-node-api.js +12 -0
  136. package/dist/components/element-install-api.d.ts +3 -0
  137. package/dist/components/element-install-api.js +19 -0
  138. package/dist/components/import-assets.js +20 -9
  139. package/dist/components/reorder-sequence-api.d.ts +2 -0
  140. package/dist/components/reorder-sequence-api.js +12 -0
  141. package/dist/components/split-jsx-sequence-api.d.ts +2 -0
  142. package/dist/components/split-jsx-sequence-api.js +12 -0
  143. package/dist/components/split-video-from-audio-api.d.ts +2 -0
  144. package/dist/components/split-video-from-audio-api.js +12 -0
  145. package/dist/error-overlay/remotion-overlay/Overlay.js +1 -1
  146. package/dist/esm/{chunk-tv7r0jy3.js → chunk-xn2q7eem.js} +11073 -7495
  147. package/dist/esm/index.mjs +7 -5
  148. package/dist/esm/internals.mjs +11073 -7495
  149. package/dist/esm/previewEntry.mjs +10905 -7327
  150. package/dist/esm/renderEntry.mjs +2 -3
  151. package/dist/helpers/browser-studio-operations.d.ts +2 -0
  152. package/dist/helpers/browser-studio-operations.js +10 -1
  153. package/dist/helpers/get-timeline-max-zoom.d.ts +26 -0
  154. package/dist/helpers/get-timeline-max-zoom.js +45 -0
  155. package/dist/helpers/inject-css.js +2 -2
  156. package/dist/helpers/render-codec-label.d.ts +1 -1
  157. package/dist/helpers/retry-payload.js +1 -0
  158. package/dist/helpers/studio-runtime-config.d.ts +1 -1
  159. package/dist/helpers/studio-runtime-config.js +2 -3
  160. package/dist/helpers/timeline-layout.d.ts +3 -1
  161. package/dist/helpers/timeline-layout.js +6 -1
  162. package/dist/helpers/url-state.js +3 -2
  163. package/dist/helpers/use-menu-structure.js +1 -5
  164. package/dist/helpers/use-runtime-values.d.ts +2 -1
  165. package/dist/helpers/use-runtime-values.js +7 -3
  166. package/dist/icons/remotion-triangle.d.ts +2 -0
  167. package/dist/icons/remotion-triangle.js +7 -0
  168. package/dist/renderEntry.js +1 -1
  169. package/dist/state/composition-list.d.ts +13 -0
  170. package/dist/state/composition-list.js +21 -0
  171. package/dist/state/modals.d.ts +7 -1
  172. package/dist/state/timeline-zoom.d.ts +1 -2
  173. package/dist/state/timeline-zoom.js +9 -5
  174. package/package.json +14 -13
@@ -38,12 +38,14 @@ const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
40
40
  const colors_1 = require("../../helpers/colors");
41
+ const get_timeline_max_zoom_1 = require("../../helpers/get-timeline-max-zoom");
41
42
  const is_current_selected_still_1 = require("../../helpers/is-current-selected-still");
42
43
  const canvas_zoom_1 = require("../../icons/canvas-zoom");
43
44
  const timeline_zoom_1 = require("../../state/timeline-zoom");
44
45
  const z_index_1 = require("../../state/z-index");
45
46
  const ControlButton_1 = require("../ControlButton");
46
47
  const layout_1 = require("../layout");
48
+ const TIMELINE_ZOOM_BUTTON_FACTOR = 1.2;
47
49
  const container = {
48
50
  color: colors_1.BLACK,
49
51
  flexDirection: 'row',
@@ -53,7 +55,7 @@ const container = {
53
55
  const buttonStyle = {
54
56
  fontSize: 24,
55
57
  };
56
- const TimelineZoomSlider = ({ maxWidth }) => {
58
+ const TimelineZoomSlider = ({ maxWidth, maxZoom }) => {
57
59
  var _a;
58
60
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
59
61
  const { setZoom, zoom: zoomMap } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
@@ -63,33 +65,39 @@ const TimelineZoomSlider = ({ maxWidth }) => {
63
65
  if (canvasContent === null || canvasContent.type !== 'composition') {
64
66
  return;
65
67
  }
66
- setZoom(canvasContent.compositionId, () => Number(e.target.value), {
68
+ setZoom(canvasContent.compositionId, () => (0, get_timeline_max_zoom_1.sliderValueToTimelineZoom)({
69
+ sliderValue: Number(e.target.value),
70
+ maxZoom,
71
+ }), {
67
72
  anchorFrame: null,
68
73
  anchorContentX: null,
69
74
  });
70
- }, [canvasContent, setZoom]);
75
+ }, [canvasContent, maxZoom, setZoom]);
71
76
  if (isStill ||
72
77
  canvasContent === null ||
73
78
  canvasContent.type !== 'composition') {
74
79
  return null;
75
80
  }
76
- const zoom = (_a = zoomMap[canvasContent.compositionId]) !== null && _a !== void 0 ? _a : timeline_zoom_1.TIMELINE_MIN_ZOOM;
77
- return (jsx_runtime_1.jsx("input", { style: maxWidth === undefined ? undefined : { maxWidth }, title: `Timeline zoom (${zoom}x)`, alt: `Timeline zoom (${zoom}x)`, type: "range", min: timeline_zoom_1.TIMELINE_MIN_ZOOM, step: 0.1, value: zoom, max: timeline_zoom_1.TIMELINE_MAX_ZOOM, onChange: onChange, className: "__remotion-timeline-slider", tabIndex: tabIndex }));
81
+ const zoom = (_a = zoomMap[canvasContent.compositionId]) !== null && _a !== void 0 ? _a : get_timeline_max_zoom_1.TIMELINE_MIN_ZOOM;
82
+ return (jsx_runtime_1.jsx("input", { style: maxWidth === undefined ? undefined : { maxWidth }, title: `Timeline zoom (${zoom}x)`, alt: `Timeline zoom (${zoom}x)`, type: "range", min: get_timeline_max_zoom_1.TIMELINE_ZOOM_SLIDER_PROPS.min, max: get_timeline_max_zoom_1.TIMELINE_ZOOM_SLIDER_PROPS.max, step: get_timeline_max_zoom_1.TIMELINE_ZOOM_SLIDER_PROPS.step, value: (0, get_timeline_max_zoom_1.timelineZoomToSliderValue)({ zoom, maxZoom }), onChange: onChange, className: "__remotion-timeline-slider", tabIndex: tabIndex }));
78
83
  };
79
84
  const TimelineZoomControlsInner = ({ sliderMaxWidth }) => {
85
+ var _a;
80
86
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
81
87
  const { setZoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
88
+ const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
89
+ const maxZoom = (0, get_timeline_max_zoom_1.getTimelineMaxZoom)((_a = videoConfig === null || videoConfig === void 0 ? void 0 : videoConfig.durationInFrames) !== null && _a !== void 0 ? _a : 1);
82
90
  const onMinusClicked = (0, react_1.useCallback)(() => {
83
91
  if (canvasContent === null || canvasContent.type !== 'composition') {
84
92
  return;
85
93
  }
86
- setZoom(canvasContent.compositionId, (z) => Math.max(timeline_zoom_1.TIMELINE_MIN_ZOOM, z - 0.2), { anchorFrame: null, anchorContentX: null });
94
+ setZoom(canvasContent.compositionId, (z) => z / TIMELINE_ZOOM_BUTTON_FACTOR, { anchorFrame: null, anchorContentX: null });
87
95
  }, [canvasContent, setZoom]);
88
96
  const onPlusClicked = (0, react_1.useCallback)(() => {
89
97
  if (canvasContent === null || canvasContent.type !== 'composition') {
90
98
  return;
91
99
  }
92
- setZoom(canvasContent.compositionId, (z) => Math.min(timeline_zoom_1.TIMELINE_MAX_ZOOM, z + 0.2), { anchorFrame: null, anchorContentX: null });
100
+ setZoom(canvasContent.compositionId, (z) => z * TIMELINE_ZOOM_BUTTON_FACTOR, { anchorFrame: null, anchorContentX: null });
93
101
  }, [canvasContent, setZoom]);
94
102
  const isStill = (0, is_current_selected_still_1.useIsStill)();
95
103
  if (isStill ||
@@ -98,7 +106,7 @@ const TimelineZoomControlsInner = ({ sliderMaxWidth }) => {
98
106
  return null;
99
107
  }
100
108
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
101
- jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onMinusClicked, style: buttonStyle, title: "Zoom out timeline", role: 'ControlButton', type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomOutIcon, { color: color }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineZoomSlider, { maxWidth: sliderMaxWidth }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onPlusClicked, style: buttonStyle, title: "Zoom in timeline", role: 'button', type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomIcon, { color: color }) })
109
+ jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onMinusClicked, style: buttonStyle, title: "Zoom out timeline", role: 'ControlButton', type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomOutIcon, { color: color }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineZoomSlider, { maxWidth: sliderMaxWidth, maxZoom: maxZoom }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onPlusClicked, style: buttonStyle, title: "Zoom in timeline", role: 'button', type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomIcon, { color: color }) })
102
110
  ] }));
103
111
  };
104
112
  exports.TimelineZoomControls = react_1.default.memo(TimelineZoomControlsInner);
@@ -2,9 +2,37 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.callAddEffectKeyframe = exports.callAddKeyframes = exports.callAddSequenceKeyframe = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
5
6
  const call_api_1 = require("../call-api");
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");
9
+ const addSequenceKeyframe = (request) => {
10
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
11
+ if (!browserStudioOperations) {
12
+ return (0, call_api_1.callApi)('/api/add-sequence-keyframe', request);
13
+ }
14
+ return browserStudioOperations.keyframes
15
+ ? browserStudioOperations.keyframes.addSequenceKeyframe(request)
16
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
17
+ };
18
+ const addEffectKeyframe = (request) => {
19
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
20
+ if (!browserStudioOperations) {
21
+ return (0, call_api_1.callApi)('/api/add-effect-keyframe', request);
22
+ }
23
+ return browserStudioOperations.keyframes
24
+ ? browserStudioOperations.keyframes.addEffectKeyframe(request)
25
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
26
+ };
27
+ const addKeyframes = (request) => {
28
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
29
+ if (!browserStudioOperations) {
30
+ return (0, call_api_1.callApi)('/api/add-keyframes', request);
31
+ }
32
+ return browserStudioOperations.keyframes
33
+ ? browserStudioOperations.keyframes.addKeyframes(request)
34
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
35
+ };
8
36
  const groupByNodePath = (keyframes) => {
9
37
  var _a;
10
38
  const groups = new Map();
@@ -27,7 +55,7 @@ const callAddSequenceKeyframe = ({ fileName, nodePath, fieldKey, sourceFrame, va
27
55
  value,
28
56
  schema,
29
57
  }),
30
- apiCall: () => (0, call_api_1.callApi)('/api/add-sequence-keyframe', {
58
+ apiCall: () => addSequenceKeyframe({
31
59
  fileName,
32
60
  nodePath,
33
61
  key: fieldKey,
@@ -71,7 +99,7 @@ const callAddKeyframes = ({ sequenceKeyframes, effectKeyframes, setPropStatuses,
71
99
  schema: keyframe.schema,
72
100
  }), prev));
73
101
  }
74
- return (0, call_api_1.callApi)('/api/add-keyframes', {
102
+ return addKeyframes({
75
103
  sequenceKeyframes: sequenceKeyframes.map((keyframe) => ({
76
104
  fileName: keyframe.fileName,
77
105
  nodePath: keyframe.nodePath,
@@ -106,7 +134,7 @@ const callAddEffectKeyframe = ({ fileName, nodePath, effectIndex, fieldKey, sour
106
134
  schema,
107
135
  }),
108
136
  applyServerResponse: (prev, response) => (0, apply_effect_response_to_prop_statuses_1.applyEffectResponseToPropStatuses)({ previous: prev, response }),
109
- apiCall: () => (0, call_api_1.callApi)('/api/add-effect-keyframe', {
137
+ apiCall: () => addEffectKeyframe({
110
138
  fileName,
111
139
  sequenceNodePath: nodePath,
112
140
  effectIndex,
@@ -2,8 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.callDeleteKeyframes = exports.callDeleteEffectKeyframe = exports.callDeleteSequenceKeyframe = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
5
6
  const call_api_1 = require("../call-api");
6
7
  const save_prop_queue_1 = require("./save-prop-queue");
8
+ const deleteKeyframes = (request) => {
9
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
10
+ if (!browserStudioOperations) {
11
+ return (0, call_api_1.callApi)('/api/delete-keyframes', request);
12
+ }
13
+ return browserStudioOperations.keyframes
14
+ ? browserStudioOperations.keyframes.deleteKeyframes(request)
15
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
16
+ };
7
17
  const groupByNodePath = (keyframes) => {
8
18
  var _a;
9
19
  const groups = new Map();
@@ -24,7 +34,7 @@ const callDeleteSequenceKeyframe = ({ fileName, nodePath, fieldKey, sourceFrame,
24
34
  fieldKey,
25
35
  frame: sourceFrame,
26
36
  }),
27
- apiCall: () => (0, call_api_1.callApi)('/api/delete-keyframes', {
37
+ apiCall: () => deleteKeyframes({
28
38
  sequenceKeyframes: [
29
39
  {
30
40
  fileName,
@@ -51,7 +61,7 @@ const callDeleteEffectKeyframe = ({ fileName, nodePath, effectIndex, fieldKey, s
51
61
  fieldKey,
52
62
  frame: sourceFrame,
53
63
  }),
54
- apiCall: () => (0, call_api_1.callApi)('/api/delete-keyframes', {
64
+ apiCall: () => deleteKeyframes({
55
65
  sequenceKeyframes: [],
56
66
  effectKeyframes: [
57
67
  {
@@ -102,7 +112,7 @@ const callDeleteKeyframes = ({ sequenceKeyframes, effectKeyframes, setPropStatus
102
112
  })),
103
113
  }));
104
114
  }
105
- return (0, call_api_1.callApi)('/api/delete-keyframes', {
115
+ return deleteKeyframes({
106
116
  sequenceKeyframes: sequenceKeyframes.map((keyframe) => ({
107
117
  fileName: keyframe.fileName,
108
118
  nodePath: keyframe.nodePath,
@@ -2,7 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.callMoveKeyframes = exports.applyOptimisticKeyframeMoves = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
5
6
  const call_api_1 = require("../call-api");
7
+ const moveKeyframes = (request) => {
8
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
9
+ if (!browserStudioOperations) {
10
+ return (0, call_api_1.callApi)('/api/move-keyframes', request);
11
+ }
12
+ return browserStudioOperations.keyframes
13
+ ? browserStudioOperations.keyframes.moveKeyframes(request)
14
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
15
+ };
6
16
  const groupByNodePath = (keyframes) => {
7
17
  var _a;
8
18
  const groups = new Map();
@@ -111,7 +121,7 @@ const callMoveKeyframes = ({ sequenceKeyframes, effectKeyframes, setPropStatuses
111
121
  effectKeyframes,
112
122
  setPropStatuses,
113
123
  });
114
- return (0, call_api_1.callApi)('/api/move-keyframes', {
124
+ return moveKeyframes({
115
125
  sequenceKeyframes: sequenceKeyframes.map((keyframe) => ({
116
126
  fileName: keyframe.fileName,
117
127
  nodePath: keyframe.nodePath,
@@ -2,10 +2,38 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.callBatchUpdateKeyframeSettings = exports.callUpdateEffectKeyframeSettings = exports.callUpdateSequenceKeyframeSettings = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
+ const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
5
6
  const call_api_1 = require("../call-api");
6
7
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
7
8
  const apply_effect_response_to_prop_statuses_1 = require("./apply-effect-response-to-prop-statuses");
8
9
  const save_prop_queue_1 = require("./save-prop-queue");
10
+ const updateSequenceKeyframeSettings = (request) => {
11
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
12
+ if (!browserStudioOperations) {
13
+ return (0, call_api_1.callApi)('/api/update-sequence-keyframe-settings', request);
14
+ }
15
+ return browserStudioOperations.keyframes
16
+ ? browserStudioOperations.keyframes.updateSequenceKeyframeSettings(request)
17
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
18
+ };
19
+ const updateEffectKeyframeSettings = (request) => {
20
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
21
+ if (!browserStudioOperations) {
22
+ return (0, call_api_1.callApi)('/api/update-effect-keyframe-settings', request);
23
+ }
24
+ return browserStudioOperations.keyframes
25
+ ? browserStudioOperations.keyframes.updateEffectKeyframeSettings(request)
26
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
27
+ };
28
+ const batchUpdateKeyframeSettings = (request) => {
29
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
30
+ if (!browserStudioOperations) {
31
+ return (0, call_api_1.callApi)('/api/batch-update-keyframe-settings', request);
32
+ }
33
+ return browserStudioOperations.keyframes
34
+ ? browserStudioOperations.keyframes.batchUpdateKeyframeSettings(request)
35
+ : Promise.reject(new Error('Keyframe editing is unavailable'));
36
+ };
9
37
  const callUpdateSequenceKeyframeSettings = ({ fileName, nodePath, fieldKey, settings, schema, setPropStatuses, clientId, }) => {
10
38
  return (0, save_prop_queue_1.enqueueSavePropChange)({
11
39
  nodePath,
@@ -15,7 +43,7 @@ const callUpdateSequenceKeyframeSettings = ({ fileName, nodePath, fieldKey, sett
15
43
  fieldKey,
16
44
  settings,
17
45
  }),
18
- apiCall: () => (0, call_api_1.callApi)('/api/update-sequence-keyframe-settings', {
46
+ apiCall: () => updateSequenceKeyframeSettings({
19
47
  fileName,
20
48
  nodePath,
21
49
  key: fieldKey,
@@ -38,7 +66,7 @@ const callUpdateEffectKeyframeSettings = ({ fileName, nodePath, effectIndex, fie
38
66
  settings,
39
67
  }),
40
68
  applyServerResponse: (prev, response) => (0, apply_effect_response_to_prop_statuses_1.applyEffectResponseToPropStatuses)({ previous: prev, response }),
41
- apiCall: () => (0, call_api_1.callApi)('/api/update-effect-keyframe-settings', {
69
+ apiCall: () => updateEffectKeyframeSettings({
42
70
  fileName,
43
71
  sequenceNodePath: nodePath,
44
72
  effectIndex,
@@ -67,7 +95,7 @@ const callBatchUpdateKeyframeSettings = ({ sequenceKeyframes, effectKeyframes, s
67
95
  settings: update.settings,
68
96
  }));
69
97
  }
70
- return (0, call_api_1.callApi)('/api/batch-update-keyframe-settings', {
98
+ return batchUpdateKeyframeSettings({
71
99
  sequenceKeyframes: sequenceKeyframes.map((update) => ({
72
100
  fileName: update.fileName,
73
101
  nodePath: update.nodePath,
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deleteSelectedTimelineItems = exports.getTimelineSelectionAfterDeletingItems = exports.deleteSequencesFromSource = void 0;
4
4
  const remotion_1 = require("remotion");
5
5
  const call_api_1 = require("../call-api");
6
+ const delete_jsx_node_api_1 = require("../delete-jsx-node-api");
6
7
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
7
8
  const delete_selected_keyframe_1 = require("./delete-selected-keyframe");
8
9
  const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
@@ -37,7 +38,7 @@ const deleteSequencesFromSource = async (nodePathInfos, confirm) => {
37
38
  if (!(await confirmDeletingDuplicatedSequences(nodePathInfos, confirm))) {
38
39
  return false;
39
40
  }
40
- return (0, call_api_1.callApi)('/api/delete-jsx-node', {
41
+ return (0, delete_jsx_node_api_1.deleteJsxNode)({
41
42
  nodes: nodePathInfos.map((nodePathInfo) => {
42
43
  const nodePath = nodePathInfo.sequenceSubscriptionKey;
43
44
  return {
@@ -1,5 +1,4 @@
1
- import type { CanUpdateSequencePropStatus, CanUpdateSequencePropStatusFalse } from 'remotion';
2
- export declare const getComputedStatusLabel: (propStatus: CanUpdateSequencePropStatusFalse) => string;
1
+ import type { CanUpdateSequencePropStatus } from 'remotion';
3
2
  export declare const getTimelineKeyframes: (propStatus: CanUpdateSequencePropStatus | null | undefined, keyframeDisplayOffset?: number) => {
4
3
  frame: number;
5
4
  value: unknown;
@@ -1,13 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getKeyframeDisplayOffset = exports.getTimelineKeyframes = exports.getComputedStatusLabel = void 0;
4
- const getComputedStatusLabel = (propStatus) => {
5
- if (propStatus.status === 'computed') {
6
- return 'computed';
7
- }
8
- throw new Error(`Unsupported prop status: ${propStatus.status}`);
9
- };
10
- exports.getComputedStatusLabel = getComputedStatusLabel;
3
+ exports.getKeyframeDisplayOffset = exports.getTimelineKeyframes = void 0;
11
4
  const getTimelineKeyframes = (propStatus, keyframeDisplayOffset = 0) => {
12
5
  if (!propStatus) {
13
6
  return [];
@@ -0,0 +1,30 @@
1
+ type TimelineSequenceVisibleLayout = {
2
+ readonly marginLeft: number;
3
+ readonly width: number;
4
+ readonly cropLeft: number;
5
+ readonly leftEdgeVisible: boolean;
6
+ readonly rightEdgeVisible: boolean;
7
+ readonly premount: {
8
+ readonly left: number;
9
+ readonly width: number;
10
+ } | null;
11
+ readonly postmount: {
12
+ readonly left: number;
13
+ readonly width: number;
14
+ } | null;
15
+ readonly media: {
16
+ readonly left: number;
17
+ readonly width: number;
18
+ readonly offset: number;
19
+ readonly fullWidth: number;
20
+ } | null;
21
+ };
22
+ export declare const getTimelineSequenceVisibleLayout: ({ marginLeft, width, premountWidth, postmountWidth, renderWindowLeft, renderWindowWidth, }: {
23
+ readonly marginLeft: number;
24
+ readonly width: number;
25
+ readonly premountWidth: number;
26
+ readonly postmountWidth: number;
27
+ readonly renderWindowLeft: number;
28
+ readonly renderWindowWidth: number;
29
+ }) => TimelineSequenceVisibleLayout | null;
30
+ export {};
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTimelineSequenceVisibleLayout = void 0;
4
+ const getVisibleSection = ({ sectionStart, sectionEnd, cropStart, cropEnd, }) => {
5
+ const start = Math.max(sectionStart, cropStart);
6
+ const end = Math.min(sectionEnd, cropEnd);
7
+ if (end <= start) {
8
+ return null;
9
+ }
10
+ return {
11
+ left: start - cropStart,
12
+ width: end - start,
13
+ };
14
+ };
15
+ const getTimelineSequenceVisibleLayout = ({ marginLeft, width, premountWidth, postmountWidth, renderWindowLeft, renderWindowWidth, }) => {
16
+ const itemStart = marginLeft;
17
+ const itemEnd = marginLeft + width;
18
+ const renderWindowEnd = renderWindowLeft + renderWindowWidth;
19
+ const visibleStart = Math.max(itemStart, renderWindowLeft);
20
+ const visibleEnd = Math.min(itemEnd, renderWindowEnd);
21
+ if (visibleEnd <= visibleStart) {
22
+ return null;
23
+ }
24
+ const cropStart = visibleStart - itemStart;
25
+ const cropEnd = visibleEnd - itemStart;
26
+ const mediaStart = premountWidth;
27
+ const mediaEnd = Math.max(mediaStart, width - postmountWidth);
28
+ const media = getVisibleSection({
29
+ sectionStart: mediaStart,
30
+ sectionEnd: mediaEnd,
31
+ cropStart,
32
+ cropEnd,
33
+ });
34
+ return {
35
+ marginLeft: visibleStart,
36
+ width: visibleEnd - visibleStart,
37
+ cropLeft: cropStart,
38
+ leftEdgeVisible: visibleStart === itemStart,
39
+ rightEdgeVisible: visibleEnd === itemEnd,
40
+ premount: getVisibleSection({
41
+ sectionStart: 0,
42
+ sectionEnd: premountWidth,
43
+ cropStart,
44
+ cropEnd,
45
+ }),
46
+ postmount: getVisibleSection({
47
+ sectionStart: Math.max(0, width - postmountWidth),
48
+ sectionEnd: width,
49
+ cropStart,
50
+ cropEnd,
51
+ }),
52
+ media: media
53
+ ? {
54
+ ...media,
55
+ offset: Math.max(0, cropStart - mediaStart),
56
+ fullWidth: Math.max(0, mediaEnd - mediaStart),
57
+ }
58
+ : null,
59
+ };
60
+ };
61
+ exports.getTimelineSequenceVisibleLayout = getTimelineSequenceVisibleLayout;
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.splitSelectedTimelineItems = exports.shouldHandleTimelineSplitShortcut = exports.shouldHandleTimelineDuplicateShortcut = exports.splitTimelineSequenceFromSource = exports.getTimelineSequenceSplitEligibility = void 0;
4
4
  const studio_shared_1 = require("@remotion/studio-shared");
5
5
  const remotion_1 = require("remotion");
6
- const call_api_1 = require("../call-api");
7
6
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
7
+ const split_jsx_sequence_api_1 = require("../split-jsx-sequence-api");
8
8
  const find_track_for_node_path_info_1 = require("./find-track-for-node-path-info");
9
9
  const staticNumberish = (status) => {
10
10
  if (!status) {
@@ -89,7 +89,7 @@ const getTimelineSequenceSplitEligibility = ({ selection, sequence, splitFrame,
89
89
  exports.getTimelineSequenceSplitEligibility = getTimelineSequenceSplitEligibility;
90
90
  const splitTimelineSequenceFromSource = ({ nodePathInfo, splitFrame, }) => {
91
91
  const nodePath = nodePathInfo.sequenceSubscriptionKey;
92
- return (0, call_api_1.callApi)('/api/split-jsx-sequence', {
92
+ return (0, split_jsx_sequence_api_1.splitJsxSequence)({
93
93
  fileName: nodePath.absolutePath,
94
94
  nodePath: nodePath.nodePath,
95
95
  sequenceKeys: nodePath.sequenceKeys,
@@ -2,6 +2,30 @@ export declare const canScrollTimelineIntoDirection: () => {
2
2
  canScrollRight: boolean;
3
3
  canScrollLeft: boolean;
4
4
  };
5
+ export declare const SCROLL_INCREMENT = 200;
6
+ export declare const EDGE_SCROLL_VERTICAL_INCREMENT = 60;
7
+ export type TimelineEdgeScrollDirections = {
8
+ x: 'left' | 'right' | null;
9
+ y: 'up' | 'down' | null;
10
+ };
11
+ export type TimelineEdgeAutoScroller = {
12
+ update: (e: {
13
+ clientX: number;
14
+ clientY: number;
15
+ }) => TimelineEdgeScrollDirections;
16
+ stop: () => void;
17
+ };
18
+ /**
19
+ * Shared edge auto-scroll loop for drag gestures on the timeline (playhead
20
+ * scrubbing, marquee selection). Detects when the pointer is in an edge zone
21
+ * and repeatedly invokes `onTick` while it stays there. The consumer performs
22
+ * the actual scrolling (and any dependent updates) inside `onTick`, so it can
23
+ * read a settled scroll position afterwards.
24
+ */
25
+ export declare const startTimelineEdgeAutoScroll: ({ includeVertical, onTick, }: {
26
+ includeVertical: boolean;
27
+ onTick: (directions: TimelineEdgeScrollDirections) => void;
28
+ }) => TimelineEdgeAutoScroller;
5
29
  export declare const getFrameWhileScrollingLeft: ({ durationInFrames, width, }: {
6
30
  durationInFrames: number;
7
31
  width: number;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prepareToPreserveTimelineCursor = exports.getScrollLeftToKeepCursorInPlace = exports.viewportClientXToScrollContentX = exports.getFrameFromTimelineDrop = exports.getFrameFromX = exports.getFrameWhileScrollingRight = exports.getFrameIncrementFromWidth = exports.getScrollPositionForCursorOnRightEdge = exports.getScrollPositionForCursorOnLeftEdge = exports.scrollToTimelineXOffset = exports.ensureFrameIsInViewport = exports.isCursorInViewport = exports.getFrameWhileScrollingLeft = exports.canScrollTimelineIntoDirection = void 0;
3
+ exports.prepareToPreserveTimelineCursor = exports.getScrollLeftToKeepCursorInPlace = exports.viewportClientXToScrollContentX = exports.getFrameFromTimelineDrop = exports.getFrameFromX = exports.getFrameWhileScrollingRight = exports.getFrameIncrementFromWidth = exports.getScrollPositionForCursorOnRightEdge = exports.getScrollPositionForCursorOnLeftEdge = exports.scrollToTimelineXOffset = exports.ensureFrameIsInViewport = exports.isCursorInViewport = exports.getFrameWhileScrollingLeft = exports.startTimelineEdgeAutoScroll = exports.EDGE_SCROLL_VERTICAL_INCREMENT = exports.SCROLL_INCREMENT = exports.canScrollTimelineIntoDirection = void 0;
4
4
  const remotion_1 = require("remotion");
5
5
  const timeline_layout_1 = require("../../helpers/timeline-layout");
6
+ const imperative_state_1 = require("./imperative-state");
6
7
  const timeline_refs_1 = require("./timeline-refs");
7
8
  const TimelineSlider_1 = require("./TimelineSlider");
8
9
  const canScrollTimelineIntoDirection = () => {
@@ -13,7 +14,126 @@ const canScrollTimelineIntoDirection = () => {
13
14
  return { canScrollRight, canScrollLeft };
14
15
  };
15
16
  exports.canScrollTimelineIntoDirection = canScrollTimelineIntoDirection;
16
- const SCROLL_INCREMENT = 200;
17
+ exports.SCROLL_INCREMENT = 200;
18
+ exports.EDGE_SCROLL_VERTICAL_INCREMENT = 60;
19
+ const EDGE_SCROLL_INTERVAL_MS = 100;
20
+ // Once edge-scrolling has started, the pointer must move this many pixels
21
+ // back inside the timeline to stop it. Prevents pixel jitter around the edge
22
+ // threshold from rapidly cancelling and restarting the auto-scroll.
23
+ const EDGE_SCROLL_EXIT_HYSTERESIS = 8;
24
+ // The vertical edge zones extend this many pixels into the viewport, so the
25
+ // auto-scroll already engages when dragging close to (not exactly onto) the
26
+ // top or bottom edge.
27
+ const EDGE_SCROLL_VERTICAL_INSET = 8;
28
+ const canScrollTimelineVerticallyIntoDirection = () => {
29
+ const { current } = timeline_refs_1.timelineVerticalScroll;
30
+ if (!current) {
31
+ return { canScrollUp: false, canScrollDown: false };
32
+ }
33
+ const { scrollTop, scrollHeight, clientHeight } = current;
34
+ return {
35
+ canScrollUp: scrollTop > 0,
36
+ canScrollDown: scrollHeight - scrollTop - clientHeight > 0,
37
+ };
38
+ };
39
+ const getEdgeScrollDirections = ({ clientX, clientY, includeVertical, active, }) => {
40
+ let x = null;
41
+ const scrollable = timeline_refs_1.scrollableRef.current;
42
+ if (scrollable) {
43
+ const rect = scrollable.getBoundingClientRect();
44
+ const leftThreshold = rect.left + (active.x === 'left' ? EDGE_SCROLL_EXIT_HYSTERESIS : 0);
45
+ const rightThreshold = rect.left +
46
+ scrollable.clientWidth -
47
+ timeline_layout_1.TIMELINE_PADDING -
48
+ (active.x === 'right' ? EDGE_SCROLL_EXIT_HYSTERESIS : 0);
49
+ const { canScrollLeft, canScrollRight } = (0, exports.canScrollTimelineIntoDirection)();
50
+ if (clientX <= leftThreshold && canScrollLeft) {
51
+ x = 'left';
52
+ }
53
+ else if (clientX >= rightThreshold && canScrollRight) {
54
+ x = 'right';
55
+ }
56
+ }
57
+ let y = null;
58
+ const vertical = timeline_refs_1.timelineVerticalScroll.current;
59
+ if (includeVertical && vertical) {
60
+ const rect = vertical.getBoundingClientRect();
61
+ const topThreshold = rect.top +
62
+ EDGE_SCROLL_VERTICAL_INSET +
63
+ (active.y === 'up' ? EDGE_SCROLL_EXIT_HYSTERESIS : 0);
64
+ const bottomThreshold = rect.bottom -
65
+ EDGE_SCROLL_VERTICAL_INSET -
66
+ (active.y === 'down' ? EDGE_SCROLL_EXIT_HYSTERESIS : 0);
67
+ const { canScrollUp, canScrollDown } = canScrollTimelineVerticallyIntoDirection();
68
+ if (clientY <= topThreshold && canScrollUp) {
69
+ y = 'up';
70
+ }
71
+ else if (clientY >= bottomThreshold && canScrollDown) {
72
+ y = 'down';
73
+ }
74
+ }
75
+ return { x, y };
76
+ };
77
+ /**
78
+ * Shared edge auto-scroll loop for drag gestures on the timeline (playhead
79
+ * scrubbing, marquee selection). Detects when the pointer is in an edge zone
80
+ * and repeatedly invokes `onTick` while it stays there. The consumer performs
81
+ * the actual scrolling (and any dependent updates) inside `onTick`, so it can
82
+ * read a settled scroll position afterwards.
83
+ */
84
+ const startTimelineEdgeAutoScroll = ({ includeVertical, onTick, }) => {
85
+ let active = { x: null, y: null };
86
+ let lastPointer = null;
87
+ let interval = null;
88
+ const stopInterval = () => {
89
+ if (interval !== null) {
90
+ clearInterval(interval);
91
+ interval = null;
92
+ }
93
+ };
94
+ const tick = () => {
95
+ if (lastPointer === null) {
96
+ return;
97
+ }
98
+ active = getEdgeScrollDirections({
99
+ clientX: lastPointer.clientX,
100
+ clientY: lastPointer.clientY,
101
+ includeVertical,
102
+ active,
103
+ });
104
+ if (active.x === null && active.y === null) {
105
+ stopInterval();
106
+ return;
107
+ }
108
+ onTick(active);
109
+ };
110
+ const update = (e) => {
111
+ lastPointer = { clientX: e.clientX, clientY: e.clientY };
112
+ active = getEdgeScrollDirections({
113
+ clientX: e.clientX,
114
+ clientY: e.clientY,
115
+ includeVertical,
116
+ active,
117
+ });
118
+ if (active.x !== null || active.y !== null) {
119
+ if (interval === null) {
120
+ onTick(active);
121
+ interval = setInterval(tick, EDGE_SCROLL_INTERVAL_MS);
122
+ }
123
+ }
124
+ else {
125
+ stopInterval();
126
+ }
127
+ return active;
128
+ };
129
+ const stop = () => {
130
+ stopInterval();
131
+ lastPointer = null;
132
+ active = { x: null, y: null };
133
+ };
134
+ return { update, stop };
135
+ };
136
+ exports.startTimelineEdgeAutoScroll = startTimelineEdgeAutoScroll;
17
137
  const calculateFrameWhileScrollingRight = ({ durationInFrames, width, scrollLeft, }) => {
18
138
  var _a;
19
139
  return ((0, exports.getFrameFromX)({
@@ -28,7 +148,7 @@ const calculateFrameWhileScrollingRight = ({ durationInFrames, width, scrollLeft
28
148
  const getFrameWhileScrollingLeft = ({ durationInFrames, width, }) => {
29
149
  var _a, _b;
30
150
  const nextFrame = (0, exports.getFrameFromX)({
31
- clientX: ((_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollLeft) - SCROLL_INCREMENT,
151
+ clientX: ((_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollLeft) - exports.SCROLL_INCREMENT,
32
152
  durationInFrames,
33
153
  width,
34
154
  extrapolate: 'clamp',
@@ -71,6 +191,9 @@ exports.isCursorInViewport = isCursorInViewport;
71
191
  const ensureFrameIsInViewport = ({ direction, durationInFrames, frame, }) => {
72
192
  var _a, _b, _c;
73
193
  var _d, _e;
194
+ // Sync the imperative frame first: scrolling below triggers the scroll
195
+ // listener in TimelineSlider, which reads the frame imperatively.
196
+ (0, imperative_state_1.setCurrentFrame)(frame);
74
197
  (_a = TimelineSlider_1.redrawTimelineSliderFast.current) === null || _a === void 0 ? void 0 : _a.draw(frame);
75
198
  const width = (_d = (_b = timeline_refs_1.scrollableRef.current) === null || _b === void 0 ? void 0 : _b.scrollWidth) !== null && _d !== void 0 ? _d : 0;
76
199
  const scrollLeft = (_e = (_c = timeline_refs_1.scrollableRef.current) === null || _c === void 0 ? void 0 : _c.scrollLeft) !== null && _e !== void 0 ? _e : 0;
@@ -183,7 +306,7 @@ const getFrameWhileScrollingRight = ({ durationInFrames, width, }) => {
183
306
  const nextFrame = calculateFrameWhileScrollingRight({
184
307
  durationInFrames,
185
308
  width,
186
- scrollLeft: ((_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollLeft) + SCROLL_INCREMENT,
309
+ scrollLeft: ((_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollLeft) + exports.SCROLL_INCREMENT,
187
310
  });
188
311
  const currentFrame = calculateFrameWhileScrollingRight({
189
312
  durationInFrames,
@@ -1,6 +1,4 @@
1
1
  import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
2
- export declare const useTimelineHeight: ({ shown, hasBeenCut, isStill, }: {
3
- shown: TimelineTrackData[];
4
- hasBeenCut: boolean;
5
- isStill: boolean;
6
- }) => number;
2
+ export declare const useTimelineTrackHeights: ({ timeline, }: {
3
+ timeline: readonly TimelineTrackData[];
4
+ }) => readonly number[];