@remotion/cli 3.1.11 → 3.2.0

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 (77) hide show
  1. package/dist/editor/components/Editor.js +3 -1
  2. package/dist/editor/components/InitialCompositionLoader.js +13 -0
  3. package/dist/editor/components/PlayPause.js +41 -23
  4. package/dist/editor/components/PreviewToolbar.js +2 -2
  5. package/dist/editor/components/Splitter/SplitterElement.js +1 -0
  6. package/dist/editor/components/TimeValue.js +9 -5
  7. package/dist/editor/components/Timeline/MaxTimelineTracks.d.ts +1 -0
  8. package/dist/editor/components/Timeline/MaxTimelineTracks.js +5 -3
  9. package/dist/editor/components/Timeline/Timeline.js +11 -4
  10. package/dist/editor/components/Timeline/TimelineDragHandler.js +120 -23
  11. package/dist/editor/components/Timeline/TimelineList.js +5 -4
  12. package/dist/editor/components/Timeline/TimelineListItem.d.ts +1 -0
  13. package/dist/editor/components/Timeline/TimelineListItem.js +8 -4
  14. package/dist/editor/components/Timeline/TimelinePlayCursorSyncer.d.ts +2 -0
  15. package/dist/editor/components/Timeline/TimelinePlayCursorSyncer.js +76 -0
  16. package/dist/editor/components/Timeline/TimelineScrollable.js +4 -2
  17. package/dist/editor/components/Timeline/TimelineSlider.d.ts +3 -0
  18. package/dist/editor/components/Timeline/TimelineSlider.js +35 -2
  19. package/dist/editor/components/Timeline/TimelineSliderHandle.js +1 -3
  20. package/dist/editor/components/Timeline/TimelineTimeIndicators.d.ts +5 -0
  21. package/dist/editor/components/Timeline/TimelineTimeIndicators.js +168 -0
  22. package/dist/editor/components/Timeline/TimelineTracks.js +14 -9
  23. package/dist/editor/components/Timeline/TimelineZoomControls.js +18 -2
  24. package/dist/editor/components/Timeline/imperative-state.d.ts +12 -0
  25. package/dist/editor/components/Timeline/imperative-state.js +39 -0
  26. package/dist/editor/components/Timeline/timeline-refs.d.ts +2 -0
  27. package/dist/editor/components/Timeline/timeline-refs.js +3 -1
  28. package/dist/editor/components/Timeline/timeline-scroll-logic.d.ts +40 -0
  29. package/dist/editor/components/Timeline/timeline-scroll-logic.js +206 -1
  30. package/dist/editor/components/ZoomPersistor.d.ts +4 -0
  31. package/dist/editor/components/ZoomPersistor.js +37 -0
  32. package/dist/editor/helpers/colors.d.ts +1 -0
  33. package/dist/editor/helpers/colors.js +2 -1
  34. package/dist/editor/helpers/get-left-of-timeline-slider.d.ts +1 -0
  35. package/dist/editor/helpers/get-left-of-timeline-slider.js +7 -4
  36. package/dist/editor/helpers/get-timeline-sequence-layout.js +29 -9
  37. package/dist/editor/icons/minus.d.ts +3 -0
  38. package/dist/editor/icons/minus.js +8 -0
  39. package/dist/editor/icons/plus.d.ts +3 -0
  40. package/dist/editor/icons/plus.js +8 -0
  41. package/dist/editor/state/timeline-zoom.d.ts +1 -1
  42. package/dist/editor/state/timeline-zoom.js +15 -1
  43. package/dist/handle-common-errors.js +5 -0
  44. package/dist/preview-server/live-events.js +4 -0
  45. package/dist/preview-server/routes.js +16 -2
  46. package/dist/preview-server/start-server.js +1 -1
  47. package/dist/upgrade.js +1 -0
  48. package/dist/versions.js +1 -0
  49. package/package.json +7 -7
  50. package/dist/bundle-on-cli.d.ts +0 -2
  51. package/dist/bundle-on-cli.js +0 -41
  52. package/dist/bundle.d.ts +0 -1
  53. package/dist/bundle.js +0 -31
  54. package/dist/chalk/symbols.d.ts +0 -111
  55. package/dist/chalk/symbols.js +0 -75
  56. package/dist/chalk/utilities.d.ts +0 -2
  57. package/dist/chalk/utilities.js +0 -37
  58. package/dist/editor/components/CompositionManager.d.ts +0 -4
  59. package/dist/editor/components/CompositionManager.js +0 -60
  60. package/dist/editor/components/LoadingIndicator.d.ts +0 -2
  61. package/dist/editor/components/LoadingIndicator.js +0 -35
  62. package/dist/prepare-entry-point.d.ts +0 -11
  63. package/dist/prepare-entry-point.js +0 -36
  64. package/dist/preview-server/fast-refresh/helpers.d.ts +0 -39
  65. package/dist/preview-server/fast-refresh/helpers.js +0 -145
  66. package/dist/preview-server/fast-refresh/index.d.ts +0 -30
  67. package/dist/preview-server/fast-refresh/index.js +0 -86
  68. package/dist/preview-server/fast-refresh/loader.d.ts +0 -35
  69. package/dist/preview-server/fast-refresh/loader.js +0 -81
  70. package/dist/preview-server/fast-refresh/runtime.d.ts +0 -35
  71. package/dist/preview-server/fast-refresh/runtime.js +0 -32
  72. package/dist/preview-server/static-preview.d.ts +0 -1
  73. package/dist/preview-server/static-preview.js +0 -40
  74. package/dist/preview-server/webpack-cache.d.ts +0 -12
  75. package/dist/preview-server/webpack-cache.js +0 -66
  76. package/dist/webpack-cache.d.ts +0 -12
  77. package/dist/webpack-cache.js +0 -66
@@ -20,6 +20,7 @@ const mute_1 = require("../state/mute");
20
20
  const preview_size_1 = require("../state/preview-size");
21
21
  const rich_timeline_1 = require("../state/rich-timeline");
22
22
  const sidebar_1 = require("../state/sidebar");
23
+ const timeline_zoom_1 = require("../state/timeline-zoom");
23
24
  const z_index_1 = require("../state/z-index");
24
25
  const EditorContent_1 = require("./EditorContent");
25
26
  const FramePersistor_1 = require("./FramePersistor");
@@ -29,6 +30,7 @@ const NewComposition_1 = __importDefault(require("./NewComposition/NewCompositio
29
30
  const NoRegisterRoot_1 = require("./NoRegisterRoot");
30
31
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
31
32
  const UpdateModal_1 = require("./UpdateModal/UpdateModal");
33
+ const ZoomPersistor_1 = require("./ZoomPersistor");
32
34
  const background = {
33
35
  backgroundColor: colors_1.BACKGROUND,
34
36
  display: 'flex',
@@ -131,7 +133,7 @@ const Editor = () => {
131
133
  });
132
134
  return () => cleanup();
133
135
  }, [Root, waitForRoot]);
134
- return ((0, jsx_runtime_1.jsx)(keybindings_1.KeybindingContextProvider, { children: (0, jsx_runtime_1.jsx)(rich_timeline_1.RichTimelineContext.Provider, { value: richTimelineCtx, children: (0, jsx_runtime_1.jsx)(checkerboard_1.CheckerboardContext.Provider, { value: checkerboardCtx, children: (0, jsx_runtime_1.jsx)(preview_size_1.PreviewSizeContext.Provider, { value: previewSizeCtx, children: (0, jsx_runtime_1.jsx)(modals_1.ModalsContext.Provider, { value: modalsContext, children: (0, jsx_runtime_1.jsx)(in_out_1.TimelineInOutContext.Provider, { value: timelineInOutContextValue, children: (0, jsx_runtime_1.jsx)(in_out_1.SetTimelineInOutContext.Provider, { value: setTimelineInOutContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.MediaVolumeContext.Provider, { value: mediaVolumeContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.SetMediaVolumeContext.Provider, { value: setMediaVolumeContextValue, children: (0, jsx_runtime_1.jsx)(player_1.PlayerInternals.PlayerEventEmitterContext.Provider, { value: emitter, children: (0, jsx_runtime_1.jsx)(sidebar_1.SidebarContextProvider, { children: (0, jsx_runtime_1.jsx)(folders_1.FolderContextProvider, { children: (0, jsx_runtime_1.jsx)(highest_z_index_1.HighestZIndexProvider, { children: (0, jsx_runtime_1.jsxs)(z_index_1.HigherZIndex, { onEscape: noop_1.noop, onOutsideClick: noop_1.noop, children: [(0, jsx_runtime_1.jsxs)("div", { style: background, children: [Root === null ? null : (0, jsx_runtime_1.jsx)(Root, {}), (0, jsx_runtime_1.jsxs)(remotion_1.Internals.CanUseRemotionHooksProvider, { children: [(0, jsx_runtime_1.jsx)(FramePersistor_1.FramePersistor, {}), Root === null ? ((0, jsx_runtime_1.jsx)(NoRegisterRoot_1.NoRegisterRoot, {})) : ((0, jsx_runtime_1.jsx)(EditorContent_1.EditorContent, {})), (0, jsx_runtime_1.jsx)(GlobalKeybindings_1.GlobalKeybindings, {})] })] }), (0, jsx_runtime_1.jsx)(NotificationCenter_1.NotificationCenter, {}), modalContextType &&
136
+ return ((0, jsx_runtime_1.jsx)(keybindings_1.KeybindingContextProvider, { children: (0, jsx_runtime_1.jsx)(rich_timeline_1.RichTimelineContext.Provider, { value: richTimelineCtx, children: (0, jsx_runtime_1.jsx)(checkerboard_1.CheckerboardContext.Provider, { value: checkerboardCtx, children: (0, jsx_runtime_1.jsx)(preview_size_1.PreviewSizeContext.Provider, { value: previewSizeCtx, children: (0, jsx_runtime_1.jsx)(modals_1.ModalsContext.Provider, { value: modalsContext, children: (0, jsx_runtime_1.jsx)(in_out_1.TimelineInOutContext.Provider, { value: timelineInOutContextValue, children: (0, jsx_runtime_1.jsx)(in_out_1.SetTimelineInOutContext.Provider, { value: setTimelineInOutContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.MediaVolumeContext.Provider, { value: mediaVolumeContextValue, children: (0, jsx_runtime_1.jsx)(remotion_1.Internals.SetMediaVolumeContext.Provider, { value: setMediaVolumeContextValue, children: (0, jsx_runtime_1.jsx)(player_1.PlayerInternals.PlayerEventEmitterContext.Provider, { value: emitter, children: (0, jsx_runtime_1.jsx)(sidebar_1.SidebarContextProvider, { children: (0, jsx_runtime_1.jsx)(folders_1.FolderContextProvider, { children: (0, jsx_runtime_1.jsx)(highest_z_index_1.HighestZIndexProvider, { children: (0, jsx_runtime_1.jsxs)(z_index_1.HigherZIndex, { onEscape: noop_1.noop, onOutsideClick: noop_1.noop, children: [(0, jsx_runtime_1.jsx)(timeline_zoom_1.TimelineZoomContext, { children: (0, jsx_runtime_1.jsxs)("div", { style: background, children: [Root === null ? null : (0, jsx_runtime_1.jsx)(Root, {}), (0, jsx_runtime_1.jsxs)(remotion_1.Internals.CanUseRemotionHooksProvider, { children: [(0, jsx_runtime_1.jsx)(FramePersistor_1.FramePersistor, {}), (0, jsx_runtime_1.jsx)(ZoomPersistor_1.ZoomPersistor, {}), Root === null ? ((0, jsx_runtime_1.jsx)(NoRegisterRoot_1.NoRegisterRoot, {})) : ((0, jsx_runtime_1.jsx)(EditorContent_1.EditorContent, {})), (0, jsx_runtime_1.jsx)(GlobalKeybindings_1.GlobalKeybindings, {})] })] }) }), (0, jsx_runtime_1.jsx)(NotificationCenter_1.NotificationCenter, {}), modalContextType &&
135
137
  modalContextType.type === 'new-comp' && ((0, jsx_runtime_1.jsx)(NewComposition_1.default, { initialCompType: modalContextType.compType })), modalContextType &&
136
138
  modalContextType.type === 'update' && ((0, jsx_runtime_1.jsx)(UpdateModal_1.UpdateModal, { info: modalContextType.info })), modalContextType &&
137
139
  modalContextType.type === 'shortcuts' && ((0, jsx_runtime_1.jsx)(KeyboardShortcutsModal_1.KeyboardShortcuts, {}))] }) }) }) }) }) }) }) }) }) }) }) }) }) }));
@@ -5,13 +5,17 @@ const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const folders_1 = require("../state/folders");
7
7
  const marks_1 = require("../state/marks");
8
+ const timeline_zoom_1 = require("../state/timeline-zoom");
8
9
  const CompositionSelector_1 = require("./CompositionSelector");
9
10
  const FramePersistor_1 = require("./FramePersistor");
11
+ const timeline_scroll_logic_1 = require("./Timeline/timeline-scroll-logic");
10
12
  const TimelineInOutToggle_1 = require("./TimelineInOutToggle");
13
+ const ZoomPersistor_1 = require("./ZoomPersistor");
11
14
  const useSelectComposition = () => {
12
15
  const setCurrentFrame = remotion_1.Internals.Timeline.useTimelineSetFrame();
13
16
  const { setCurrentComposition } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
14
17
  const { setFoldersExpanded } = (0, react_1.useContext)(folders_1.FolderContext);
18
+ const { setZoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
15
19
  return (c, push) => {
16
20
  var _a;
17
21
  (_a = TimelineInOutToggle_1.inOutHandles.current) === null || _a === void 0 ? void 0 : _a.setMarks((0, marks_1.loadMarks)(c.id, c.durationInFrames));
@@ -19,9 +23,18 @@ const useSelectComposition = () => {
19
23
  window.history.pushState({}, 'Preview', `/${c.id}`);
20
24
  }
21
25
  const frame = (0, FramePersistor_1.getFrameForComposition)(c.id);
26
+ const zoom = (0, ZoomPersistor_1.getZoomForComposition)(c.id);
22
27
  const frameInBounds = Math.min(c.durationInFrames - 1, frame);
23
28
  setCurrentFrame(frameInBounds);
24
29
  setCurrentComposition(c.id);
30
+ setZoom(() => zoom);
31
+ setTimeout(() => {
32
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
33
+ direction: 'center',
34
+ frame,
35
+ durationInFrames: c.durationInFrames,
36
+ });
37
+ });
25
38
  const { folderName, parentFolderName } = c;
26
39
  if (folderName !== null) {
27
40
  setFoldersExpanded((ex) => {
@@ -4,7 +4,6 @@ exports.PlayPause = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const player_1 = require("@remotion/player");
6
6
  const react_1 = require("react");
7
- const remotion_1 = require("remotion");
8
7
  const is_current_selected_still_1 = require("../helpers/is-current-selected-still");
9
8
  const use_keybinding_1 = require("../helpers/use-keybinding");
10
9
  const jump_to_start_1 = require("../icons/jump-to-start");
@@ -14,15 +13,14 @@ const step_back_1 = require("../icons/step-back");
14
13
  const step_forward_1 = require("../icons/step-forward");
15
14
  const in_out_1 = require("../state/in-out");
16
15
  const ControlButton_1 = require("./ControlButton");
16
+ const imperative_state_1 = require("./Timeline/imperative-state");
17
+ const timeline_scroll_logic_1 = require("./Timeline/timeline-scroll-logic");
17
18
  const forwardBackStyle = {
18
19
  height: 16,
19
20
  color: 'white',
20
21
  };
21
22
  const PlayPause = ({ playbackRate, loop }) => {
22
- var _a;
23
23
  const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)();
24
- const frame = remotion_1.Internals.Timeline.useTimelinePosition();
25
- const video = remotion_1.Internals.useVideo();
26
24
  player_1.PlayerInternals.usePlayback({
27
25
  loop,
28
26
  playbackRate,
@@ -30,7 +28,7 @@ const PlayPause = ({ playbackRate, loop }) => {
30
28
  inFrame,
31
29
  outFrame,
32
30
  });
33
- const { playing, play, pause, pauseAndReturnToPlayStart, frameBack, seek, frameForward, isLastFrame, } = player_1.PlayerInternals.usePlayer();
31
+ const { playing, play, pause, pauseAndReturnToPlayStart, frameBack, seek, frameForward, isLastFrame, isFirstFrame, } = player_1.PlayerInternals.usePlayer();
34
32
  const isStill = (0, is_current_selected_still_1.useIsStill)();
35
33
  (0, react_1.useEffect)(() => {
36
34
  if (isStill) {
@@ -52,37 +50,60 @@ const PlayPause = ({ playbackRate, loop }) => {
52
50
  }
53
51
  e.preventDefault();
54
52
  }, [pauseAndReturnToPlayStart, playing]);
55
- const videoFps = (_a = video === null || video === void 0 ? void 0 : video.fps) !== null && _a !== void 0 ? _a : null;
56
53
  const onArrowLeft = (0, react_1.useCallback)((e) => {
57
- if (!videoFps) {
58
- return null;
59
- }
60
54
  e.preventDefault();
61
55
  if (e.altKey) {
62
56
  seek(0);
57
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
58
+ direction: 'fit-left',
59
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
60
+ frame: 0,
61
+ });
63
62
  }
64
63
  else if (e.shiftKey) {
65
- frameBack(videoFps);
64
+ frameBack((0, imperative_state_1.getCurrentFps)());
65
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
66
+ direction: 'fit-left',
67
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
68
+ frame: Math.max(0, (0, imperative_state_1.getCurrentFrame)() - (0, imperative_state_1.getCurrentFps)()),
69
+ });
66
70
  }
67
71
  else {
68
72
  frameBack(1);
73
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
74
+ direction: 'fit-left',
75
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
76
+ frame: Math.max(0, (0, imperative_state_1.getCurrentFrame)() - 1),
77
+ });
69
78
  }
70
- }, [frameBack, seek, videoFps]);
79
+ }, [frameBack, seek]);
71
80
  const onArrowRight = (0, react_1.useCallback)((e) => {
72
- if (!video) {
73
- return null;
74
- }
75
81
  if (e.altKey) {
76
- seek(video.durationInFrames - 1);
82
+ seek((0, imperative_state_1.getCurrentDuration)() - 1);
83
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
84
+ direction: 'fit-right',
85
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)() - 1,
86
+ frame: (0, imperative_state_1.getCurrentDuration)() - 1,
87
+ });
77
88
  }
78
89
  else if (e.shiftKey) {
79
- frameForward(video.fps);
90
+ frameForward((0, imperative_state_1.getCurrentFps)());
91
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
92
+ direction: 'fit-right',
93
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
94
+ frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, (0, imperative_state_1.getCurrentFrame)() + (0, imperative_state_1.getCurrentFps)()),
95
+ });
80
96
  }
81
97
  else {
82
98
  frameForward(1);
99
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
100
+ direction: 'fit-right',
101
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
102
+ frame: (0, imperative_state_1.getCurrentFrame)() + 1,
103
+ });
83
104
  }
84
105
  e.preventDefault();
85
- }, [frameForward, seek, video]);
106
+ }, [frameForward, seek]);
86
107
  const oneFrameBack = (0, react_1.useCallback)(() => {
87
108
  frameBack(1);
88
109
  }, [frameBack]);
@@ -93,11 +114,8 @@ const PlayPause = ({ playbackRate, loop }) => {
93
114
  seek(0);
94
115
  }, [seek]);
95
116
  const jumpToEnd = (0, react_1.useCallback)(() => {
96
- if (!video) {
97
- return;
98
- }
99
- seek(video.durationInFrames - 1);
100
- }, [seek, video]);
117
+ seek((0, imperative_state_1.getCurrentDuration)() - 1);
118
+ }, [seek]);
101
119
  const keybindings = (0, use_keybinding_1.useKeybinding)();
102
120
  (0, react_1.useEffect)(() => {
103
121
  const arrowLeft = keybindings.registerKeybinding({
@@ -156,7 +174,7 @@ const PlayPause = ({ playbackRate, loop }) => {
156
174
  if (isStill) {
157
175
  return null;
158
176
  }
159
- return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": "Jump to beginning", title: "Jump to beginning", disabled: frame === 0, onClick: jumpToStart, children: (0, jsx_runtime_1.jsx)(jump_to_start_1.JumpToStart, { style: forwardBackStyle }) }), (0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": "Step back one frame", title: "Step back one frame", disabled: frame === 0, onClick: oneFrameBack, children: (0, jsx_runtime_1.jsx)(step_back_1.StepBack, { style: forwardBackStyle }) }), (0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": playing ? 'Pause' : 'Play', title: playing ? 'Pause' : 'Play', disabled: !video, onClick: playing ? pause : play, children: playing ? ((0, jsx_runtime_1.jsx)(pause_1.Pause, { style: {
177
+ return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": "Jump to beginning", title: "Jump to beginning", disabled: isFirstFrame, onClick: jumpToStart, children: (0, jsx_runtime_1.jsx)(jump_to_start_1.JumpToStart, { style: forwardBackStyle }) }), (0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": "Step back one frame", title: "Step back one frame", disabled: isFirstFrame, onClick: oneFrameBack, children: (0, jsx_runtime_1.jsx)(step_back_1.StepBack, { style: forwardBackStyle }) }), (0, jsx_runtime_1.jsx)(ControlButton_1.ControlButton, { "aria-label": playing ? 'Pause' : 'Play', title: playing ? 'Pause' : 'Play', onClick: playing ? pause : play, children: playing ? ((0, jsx_runtime_1.jsx)(pause_1.Pause, { style: {
160
178
  height: 14,
161
179
  width: 14,
162
180
  color: 'white',
@@ -18,8 +18,8 @@ const PlaybackRateSelector_1 = require("./PlaybackRateSelector");
18
18
  const PlayPause_1 = require("./PlayPause");
19
19
  const RichTimelineToggle_1 = require("./RichTimelineToggle");
20
20
  const SizeSelector_1 = require("./SizeSelector");
21
+ const TimelineZoomControls_1 = require("./Timeline/TimelineZoomControls");
21
22
  const TimelineInOutToggle_1 = require("./TimelineInOutToggle");
22
- const TimeValue_1 = require("./TimeValue");
23
23
  const container = {
24
24
  display: 'flex',
25
25
  justifyContent: 'center',
@@ -45,6 +45,6 @@ const PreviewToolbar = () => {
45
45
  const { mediaMuted } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
46
46
  const { setMediaMuted } = (0, react_1.useContext)(remotion_1.Internals.SetMediaVolumeContext);
47
47
  const [loop, setLoop] = (0, react_1.useState)((0, loop_1.loadLoopOption)());
48
- return ((0, jsx_runtime_1.jsxs)("div", { style: container, className: "css-reset", children: [(0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: padding }), (0, jsx_runtime_1.jsx)(TimeValue_1.TimeValue, {})] }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), (0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(PlayPause_1.PlayPause, { loop: loop, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }), (0, jsx_runtime_1.jsx)(CheckboardToggle_1.CheckboardToggle, {}), (0, jsx_runtime_1.jsx)(RichTimelineToggle_1.RichTimelineToggle, {}), (0, jsx_runtime_1.jsx)(TimelineInOutToggle_1.TimelineInOutPointToggle, {}), (0, jsx_runtime_1.jsx)(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), (0, jsx_runtime_1.jsx)("div", { style: padding })] }), (0, jsx_runtime_1.jsx)(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), (0, jsx_runtime_1.jsx)(PlaybackRatePersistor_1.PlaybackRatePersistor, {})] }));
48
+ return ((0, jsx_runtime_1.jsxs)("div", { style: container, className: "css-reset", children: [(0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)("div", { style: padding }), (0, jsx_runtime_1.jsx)(TimelineZoomControls_1.TimelineZoomControls, {})] }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(SizeSelector_1.SizeSelector, {}), (0, jsx_runtime_1.jsx)(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(PlayPause_1.PlayPause, { loop: loop, playbackRate: playbackRate }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 2 }), (0, jsx_runtime_1.jsx)(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }), (0, jsx_runtime_1.jsx)(CheckboardToggle_1.CheckboardToggle, {}), (0, jsx_runtime_1.jsx)(RichTimelineToggle_1.RichTimelineToggle, {}), (0, jsx_runtime_1.jsx)(TimelineInOutToggle_1.TimelineInOutPointToggle, {}), (0, jsx_runtime_1.jsx)(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsxs)("div", { style: sideContainer, children: [(0, jsx_runtime_1.jsx)(layout_1.Flex, {}), (0, jsx_runtime_1.jsx)(FpsCounter_1.FpsCounter, { playbackSpeed: playbackRate }), (0, jsx_runtime_1.jsx)("div", { style: padding })] }), (0, jsx_runtime_1.jsx)(PlaybackKeyboardShortcutsManager_1.PlaybackKeyboardShortcutsManager, { setPlaybackRate: setPlaybackRate }), (0, jsx_runtime_1.jsx)(PlaybackRatePersistor_1.PlaybackRatePersistor, {})] }));
49
49
  };
50
50
  exports.PreviewToolbar = PreviewToolbar;
@@ -13,6 +13,7 @@ const SplitterElement = ({ children, type }) => {
13
13
  (type === 'flexer' ? context.flexValue : 1 - context.flexValue) * 1000,
14
14
  display: 'flex',
15
15
  position: 'relative',
16
+ overflow: 'hidden',
16
17
  };
17
18
  }, [context.flexValue, type]);
18
19
  return (0, jsx_runtime_1.jsx)("div", { style: style, children: children });
@@ -5,24 +5,28 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const remotion_1 = require("remotion");
6
6
  const is_current_selected_still_1 = require("../helpers/is-current-selected-still");
7
7
  const render_frame_1 = require("../state/render-frame");
8
+ const layout_1 = require("./layout");
8
9
  const text = {
9
10
  color: 'white',
10
- fontSize: 16,
11
+ fontSize: 18,
11
12
  display: 'flex',
12
- flexDirection: 'column',
13
- justifyContent: 'center',
13
+ flexDirection: 'row',
14
+ alignItems: 'flex-end',
14
15
  fontVariantNumeric: 'tabular-nums',
15
16
  lineHeight: 1,
16
17
  };
17
18
  const time = {
18
19
  display: 'inline-block',
19
- fontSize: 16,
20
+ fontSize: 18,
20
21
  };
21
22
  const frameStyle = {
22
23
  color: '#ccc',
23
24
  fontSize: 10,
24
25
  fontWeight: 500,
25
26
  };
27
+ const spacer = {
28
+ width: layout_1.SPACING_UNIT,
29
+ };
26
30
  const TimeValue = () => {
27
31
  const frame = (0, remotion_1.useCurrentFrame)();
28
32
  const config = remotion_1.Internals.useUnsafeVideoConfig();
@@ -33,6 +37,6 @@ const TimeValue = () => {
33
37
  if (isStill) {
34
38
  return null;
35
39
  }
36
- return ((0, jsx_runtime_1.jsxs)("div", { style: text, children: [(0, jsx_runtime_1.jsx)("div", { style: time, children: (0, render_frame_1.renderFrame)(frame, config.fps) }), ' ', (0, jsx_runtime_1.jsxs)("div", { style: frameStyle, children: [frame, " ", (0, jsx_runtime_1.jsxs)("span", { style: frameStyle, children: ["(", config.fps, " fps)"] })] })] }));
40
+ return ((0, jsx_runtime_1.jsxs)("div", { style: text, children: [(0, jsx_runtime_1.jsx)("div", { style: time, children: (0, render_frame_1.renderFrame)(frame, config.fps) }), ' ', (0, jsx_runtime_1.jsx)("div", { style: spacer }), (0, jsx_runtime_1.jsxs)("div", { style: frameStyle, children: [frame, " ", (0, jsx_runtime_1.jsxs)("span", { style: frameStyle, children: ["(", config.fps, " fps)"] })] })] }));
37
41
  };
38
42
  exports.TimeValue = TimeValue;
@@ -1,3 +1,4 @@
1
1
  import React from 'react';
2
2
  export declare const MAX_TIMELINE_TRACKS: number;
3
+ export declare const MAX_TIMELINE_TRACKS_NOTICE_HEIGHT = 24;
3
4
  export declare const MaxTimelineTracksReached: React.FC;
@@ -1,14 +1,16 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.MaxTimelineTracksReached = exports.MAX_TIMELINE_TRACKS = void 0;
3
+ exports.MaxTimelineTracksReached = exports.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT = exports.MAX_TIMELINE_TRACKS = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const timeline_layout_1 = require("../../helpers/timeline-layout");
6
6
  exports.MAX_TIMELINE_TRACKS = typeof process.env.MAX_TIMELINE_TRACKS === 'undefined'
7
7
  ? 15
8
8
  : Number(process.env.MAX_TIMELINE_TRACKS);
9
+ exports.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT = 24;
9
10
  const container = {
10
- paddingTop: 6,
11
- paddingBottom: 6,
11
+ height: exports.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT,
12
+ display: 'flex',
13
+ alignItems: 'center',
12
14
  color: 'rgba(255, 255, 255, 0.6)',
13
15
  fontFamily: 'sans-serif',
14
16
  fontSize: 12,
@@ -12,18 +12,22 @@ const SplitterElement_1 = require("../Splitter/SplitterElement");
12
12
  const SplitterHandle_1 = require("../Splitter/SplitterHandle");
13
13
  const is_collapsed_1 = require("./is-collapsed");
14
14
  const MaxTimelineTracks_1 = require("./MaxTimelineTracks");
15
+ const timeline_refs_1 = require("./timeline-refs");
15
16
  const timeline_state_reducer_1 = require("./timeline-state-reducer");
16
17
  const TimelineDragHandler_1 = require("./TimelineDragHandler");
17
18
  const TimelineInOutPointer_1 = require("./TimelineInOutPointer");
18
19
  const TimelineList_1 = require("./TimelineList");
20
+ const TimelinePlayCursorSyncer_1 = require("./TimelinePlayCursorSyncer");
21
+ const TimelineScrollable_1 = require("./TimelineScrollable");
19
22
  const TimelineSlider_1 = require("./TimelineSlider");
23
+ const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
20
24
  const TimelineTracks_1 = require("./TimelineTracks");
21
25
  const container = {
22
26
  minHeight: '100%',
23
27
  flex: 1,
24
28
  display: 'flex',
25
29
  height: 0,
26
- overflow: 'auto',
30
+ overflowY: 'auto',
27
31
  };
28
32
  const noop = () => undefined;
29
33
  const Timeline = () => {
@@ -61,18 +65,21 @@ const Timeline = () => {
61
65
  return timeline.filter((t) => !(0, is_collapsed_1.isTrackHidden)(t, timeline, state));
62
66
  }, [state, timeline]);
63
67
  const shown = withoutHidden.slice(0, MaxTimelineTracks_1.MAX_TIMELINE_TRACKS);
68
+ const hasBeenCut = withoutHidden.length > shown.length;
64
69
  const inner = (0, react_1.useMemo)(() => {
65
70
  return {
66
- height: shown.length * (timeline_layout_1.TIMELINE_LAYER_HEIGHT + timeline_layout_1.TIMELINE_BORDER * 2),
71
+ height: shown.length * (timeline_layout_1.TIMELINE_LAYER_HEIGHT + timeline_layout_1.TIMELINE_BORDER * 2) +
72
+ (hasBeenCut ? MaxTimelineTracks_1.MAX_TIMELINE_TRACKS_NOTICE_HEIGHT : 0) +
73
+ TimelineTimeIndicators_1.TIMELINE_TIME_INDICATOR_HEIGHT,
67
74
  display: 'flex',
68
75
  flex: 1,
69
76
  minHeight: '100%',
70
77
  overflowX: 'hidden',
71
78
  };
72
- }, [shown.length]);
79
+ }, [hasBeenCut, shown.length]);
73
80
  if (!videoConfig) {
74
81
  return null;
75
82
  }
76
- return ((0, jsx_runtime_1.jsx)("div", { style: container, className: "css-reset", children: (0, jsx_runtime_1.jsx)("div", { style: inner, children: (0, jsx_runtime_1.jsxs)(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [(0, jsx_runtime_1.jsx)(SplitterElement_1.SplitterElement, { type: "flexer", children: (0, jsx_runtime_1.jsx)(TimelineList_1.TimelineList, { dispatchStateChange: dispatch, viewState: state, timeline: shown }) }), (0, jsx_runtime_1.jsx)(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: false }), (0, jsx_runtime_1.jsxs)(SplitterElement_1.SplitterElement, { type: "anti-flexer", children: [(0, jsx_runtime_1.jsx)(TimelineTracks_1.TimelineTracks, { viewState: state, timeline: shown, fps: videoConfig.fps, hasBeenCut: withoutHidden.length > shown.length }), (0, jsx_runtime_1.jsx)(TimelineInOutPointer_1.TimelineInOutPointer, {}), (0, jsx_runtime_1.jsx)(TimelineDragHandler_1.TimelineDragHandler, {}), (0, jsx_runtime_1.jsx)(TimelineSlider_1.TimelineSlider, {})] })] }) }) }));
83
+ return ((0, jsx_runtime_1.jsx)("div", { ref: timeline_refs_1.timelineVerticalScroll, style: container, className: "css-reset", children: (0, jsx_runtime_1.jsx)("div", { style: inner, children: (0, jsx_runtime_1.jsxs)(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [(0, jsx_runtime_1.jsx)(SplitterElement_1.SplitterElement, { type: "flexer", children: (0, jsx_runtime_1.jsx)(TimelineList_1.TimelineList, { dispatchStateChange: dispatch, viewState: state, timeline: shown }) }), (0, jsx_runtime_1.jsx)(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: false }), (0, jsx_runtime_1.jsx)(SplitterElement_1.SplitterElement, { type: "anti-flexer", children: (0, jsx_runtime_1.jsxs)(TimelineScrollable_1.TimelineScrollable, { children: [(0, jsx_runtime_1.jsx)(TimelineTracks_1.TimelineTracks, { viewState: state, timeline: shown, fps: videoConfig.fps, hasBeenCut: hasBeenCut }), (0, jsx_runtime_1.jsx)(TimelineInOutPointer_1.TimelineInOutPointer, {}), (0, jsx_runtime_1.jsx)(TimelineDragHandler_1.TimelineDragHandler, {}), (0, jsx_runtime_1.jsx)(TimelineSlider_1.TimelineSlider, {}), (0, jsx_runtime_1.jsx)(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {})] }) })] }) }) }));
77
84
  };
78
85
  exports.Timeline = Timeline;
@@ -8,41 +8,38 @@ const remotion_1 = require("remotion");
8
8
  const get_left_of_timeline_slider_1 = require("../../helpers/get-left-of-timeline-slider");
9
9
  const timeline_layout_1 = require("../../helpers/timeline-layout");
10
10
  const in_out_1 = require("../../state/in-out");
11
+ const timeline_zoom_1 = require("../../state/timeline-zoom");
11
12
  const FramePersistor_1 = require("../FramePersistor");
12
13
  const timeline_refs_1 = require("./timeline-refs");
14
+ const timeline_scroll_logic_1 = require("./timeline-scroll-logic");
13
15
  const TimelineInOutPointer_1 = require("./TimelineInOutPointer");
14
16
  const TimelineInOutPointerHandle_1 = require("./TimelineInOutPointerHandle");
17
+ const TimelineSlider_1 = require("./TimelineSlider");
15
18
  const inner = {
16
19
  overflowY: 'auto',
17
20
  overflowX: 'hidden',
18
21
  };
19
22
  const container = {
20
23
  userSelect: 'none',
21
- overflow: 'hidden',
22
24
  position: 'absolute',
23
- width: '100%',
24
25
  height: '100%',
26
+ top: 0,
25
27
  };
26
- const getFrameFromX = (clientX, durationInFrames, width, extrapolate) => {
28
+ const getClientXWithScroll = (x) => {
27
29
  var _a;
28
- const pos = clientX - timeline_layout_1.TIMELINE_PADDING;
29
- const frame = Math.round((0, remotion_1.interpolate)(pos, [0, width - timeline_layout_1.TIMELINE_PADDING * 2], [0, (_a = durationInFrames - 1) !== null && _a !== void 0 ? _a : 0], {
30
- extrapolateLeft: extrapolate,
31
- extrapolateRight: extrapolate,
32
- }));
33
- return frame;
30
+ return x + ((_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollLeft);
34
31
  };
35
32
  const TimelineDragHandler = () => {
36
- var _a, _b;
37
- const size = player_1.PlayerInternals.useElementSize(timeline_refs_1.sliderAreaRef, {
33
+ var _a, _b, _c;
34
+ const size = player_1.PlayerInternals.useElementSize(timeline_refs_1.scrollableRef, {
38
35
  triggerOnWindowResize: true,
39
36
  shouldApplyCssTransforms: true,
40
37
  });
41
38
  const [inOutDragging, setInOutDragging] = (0, react_1.useState)({
42
39
  dragging: false,
43
40
  });
44
- const width = (_a = size === null || size === void 0 ? void 0 : size.width) !== null && _a !== void 0 ? _a : 0;
45
- const left = (_b = size === null || size === void 0 ? void 0 : size.left) !== null && _b !== void 0 ? _b : 0;
41
+ const width = (_b = (_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.scrollWidth) !== null && _b !== void 0 ? _b : 0;
42
+ const left = (_c = size === null || size === void 0 ? void 0 : size.left) !== null && _c !== void 0 ? _c : 0;
46
43
  const { inFrame, outFrame } = (0, in_out_1.useTimelineInOutFramePosition)();
47
44
  const { setInAndOutFrames } = (0, in_out_1.useTimelineSetInOutFramePosition)();
48
45
  const { get } = (0, get_left_of_timeline_slider_1.useGetXPositionOfItemInTimeline)();
@@ -51,7 +48,15 @@ const TimelineDragHandler = () => {
51
48
  });
52
49
  const { playing, play, pause, seek } = player_1.PlayerInternals.usePlayer();
53
50
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
51
+ const scroller = (0, react_1.useRef)(null);
52
+ const stopInterval = () => {
53
+ if (scroller.current) {
54
+ clearInterval(scroller.current);
55
+ scroller.current = null;
56
+ }
57
+ };
54
58
  const onPointerDown = (0, react_1.useCallback)((e) => {
59
+ stopInterval();
55
60
  if (!videoConfig) {
56
61
  return;
57
62
  }
@@ -63,7 +68,7 @@ const TimelineDragHandler = () => {
63
68
  const outMarker = outFrame === null ? Infinity : get(outFrame - 1);
64
69
  setInOutDragging({
65
70
  dragging: 'in',
66
- initialOffset: e.clientX,
71
+ initialOffset: getClientXWithScroll(e.clientX),
67
72
  boundaries: [-Infinity, outMarker - inMarker],
68
73
  });
69
74
  return;
@@ -76,12 +81,17 @@ const TimelineDragHandler = () => {
76
81
  const inMarker = inFrame === null ? -Infinity : get(inFrame + 1);
77
82
  setInOutDragging({
78
83
  dragging: 'out',
79
- initialOffset: e.clientX,
84
+ initialOffset: getClientXWithScroll(e.clientX),
80
85
  boundaries: [inMarker - outMarker, Infinity],
81
86
  });
82
87
  return;
83
88
  }
84
- const frame = getFrameFromX(e.clientX - left, videoConfig.durationInFrames, width, 'clamp');
89
+ const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
90
+ clientX: getClientXWithScroll(e.clientX) - left,
91
+ durationInFrames: videoConfig.durationInFrames,
92
+ width,
93
+ extrapolate: 'clamp',
94
+ });
85
95
  seek(frame);
86
96
  setDragging({
87
97
  dragging: true,
@@ -90,15 +100,84 @@ const TimelineDragHandler = () => {
90
100
  pause();
91
101
  }, [videoConfig, left, width, seek, playing, pause, outFrame, get, inFrame]);
92
102
  const onPointerMoveScrubbing = (0, react_1.useCallback)((e) => {
103
+ var _a;
93
104
  if (!videoConfig) {
94
105
  return;
95
106
  }
96
107
  if (!dragging.dragging) {
97
108
  return;
98
109
  }
99
- const frame = getFrameFromX(e.clientX - left, videoConfig.durationInFrames, width, 'clamp');
100
- seek(frame);
101
- }, [dragging.dragging, seek, left, videoConfig, width]);
110
+ const isRightOfArea = e.clientX >=
111
+ ((_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) +
112
+ left -
113
+ timeline_layout_1.TIMELINE_PADDING;
114
+ const isLeftOfArea = e.clientX <= left;
115
+ const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
116
+ clientX: getClientXWithScroll(e.clientX) - left,
117
+ durationInFrames: videoConfig.durationInFrames,
118
+ width,
119
+ extrapolate: 'clamp',
120
+ });
121
+ if (isLeftOfArea && (0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollLeft) {
122
+ if (scroller.current) {
123
+ return;
124
+ }
125
+ const scrollEvery = () => {
126
+ var _a;
127
+ if (!(0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollLeft) {
128
+ stopInterval();
129
+ return;
130
+ }
131
+ const nextFrame = (0, timeline_scroll_logic_1.getFrameWhileScrollingLeft)({
132
+ durationInFrames: videoConfig.durationInFrames,
133
+ width,
134
+ });
135
+ const scrollPos = (0, timeline_scroll_logic_1.getScrollPositionForCursorOnLeftEdge)({
136
+ nextFrame,
137
+ durationInFrames: videoConfig.durationInFrames,
138
+ });
139
+ (_a = TimelineSlider_1.redrawTimelineSliderFast.current) === null || _a === void 0 ? void 0 : _a.draw(nextFrame);
140
+ seek(nextFrame);
141
+ (0, timeline_scroll_logic_1.scrollToTimelineXOffset)(scrollPos);
142
+ };
143
+ scrollEvery();
144
+ scroller.current = setInterval(() => {
145
+ scrollEvery();
146
+ }, 100);
147
+ }
148
+ else if (isRightOfArea &&
149
+ (0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollRight) {
150
+ if (scroller.current) {
151
+ return;
152
+ }
153
+ const scrollEvery = () => {
154
+ var _a;
155
+ if (!(0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollRight) {
156
+ stopInterval();
157
+ return;
158
+ }
159
+ const nextFrame = (0, timeline_scroll_logic_1.getFrameWhileScrollingRight)({
160
+ durationInFrames: videoConfig.durationInFrames,
161
+ width,
162
+ });
163
+ const scrollPos = (0, timeline_scroll_logic_1.getScrollPositionForCursorOnRightEdge)({
164
+ nextFrame,
165
+ durationInFrames: videoConfig.durationInFrames,
166
+ });
167
+ (_a = TimelineSlider_1.redrawTimelineSliderFast.current) === null || _a === void 0 ? void 0 : _a.draw(nextFrame);
168
+ seek(nextFrame);
169
+ (0, timeline_scroll_logic_1.scrollToTimelineXOffset)(scrollPos);
170
+ };
171
+ scrollEvery();
172
+ scroller.current = setInterval(() => {
173
+ scrollEvery();
174
+ }, 100);
175
+ }
176
+ else {
177
+ stopInterval();
178
+ seek(frame);
179
+ }
180
+ }, [videoConfig, dragging.dragging, left, width, seek]);
102
181
  const onPointerMoveInOut = (0, react_1.useCallback)((e) => {
103
182
  if (!videoConfig) {
104
183
  return;
@@ -106,7 +185,7 @@ const TimelineDragHandler = () => {
106
185
  if (!inOutDragging.dragging) {
107
186
  return;
108
187
  }
109
- const offset = Math.max(inOutDragging.boundaries[0], Math.min(inOutDragging.boundaries[1], e.clientX - inOutDragging.initialOffset));
188
+ const offset = Math.max(inOutDragging.boundaries[0], Math.min(inOutDragging.boundaries[1], getClientXWithScroll(e.clientX) - inOutDragging.initialOffset));
110
189
  if (inOutDragging.dragging === 'in') {
111
190
  if (!TimelineInOutPointerHandle_1.inPointerHandle.current) {
112
191
  throw new Error('in pointer handle');
@@ -139,6 +218,7 @@ const TimelineDragHandler = () => {
139
218
  }
140
219
  }, [get, inFrame, inOutDragging, outFrame, videoConfig, width]);
141
220
  const onPointerUpScrubbing = (0, react_1.useCallback)((e) => {
221
+ stopInterval();
142
222
  if (!videoConfig) {
143
223
  return;
144
224
  }
@@ -148,7 +228,12 @@ const TimelineDragHandler = () => {
148
228
  setDragging({
149
229
  dragging: false,
150
230
  });
151
- const frame = getFrameFromX(e.clientX - left, videoConfig.durationInFrames, width, 'clamp');
231
+ const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
232
+ clientX: getClientXWithScroll(e.clientX) - left,
233
+ durationInFrames: videoConfig.durationInFrames,
234
+ width,
235
+ extrapolate: 'clamp',
236
+ });
152
237
  (0, FramePersistor_1.persistCurrentFrame)(frame);
153
238
  if (dragging.wasPlaying) {
154
239
  play();
@@ -164,7 +249,12 @@ const TimelineDragHandler = () => {
164
249
  setInOutDragging({
165
250
  dragging: false,
166
251
  });
167
- const frame = getFrameFromX(e.clientX - left, videoConfig.durationInFrames, width, 'extend');
252
+ const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
253
+ clientX: getClientXWithScroll(e.clientX) - left,
254
+ durationInFrames: videoConfig.durationInFrames,
255
+ width,
256
+ extrapolate: 'extend',
257
+ });
168
258
  if (inOutDragging.dragging === 'in') {
169
259
  if (frame < 1) {
170
260
  return setInAndOutFrames((prev) => ({
@@ -222,6 +312,13 @@ const TimelineDragHandler = () => {
222
312
  window.removeEventListener('pointerup', onPointerUpInOut);
223
313
  };
224
314
  }, [inOutDragging.dragging, onPointerMoveInOut, onPointerUpInOut]);
225
- return ((0, jsx_runtime_1.jsxs)("div", { ref: timeline_refs_1.sliderAreaRef, style: container, onPointerDown: onPointerDown, children: [(0, jsx_runtime_1.jsx)("div", { style: inner }), inFrame !== null && ((0, jsx_runtime_1.jsx)(TimelineInOutPointerHandle_1.TimelineInOutPointerHandle, { type: "in", atFrame: inFrame, dragging: inOutDragging.dragging === 'in' })), outFrame !== null && ((0, jsx_runtime_1.jsx)(TimelineInOutPointerHandle_1.TimelineInOutPointerHandle, { type: "out", dragging: inOutDragging.dragging === 'out', atFrame: outFrame }))] }));
315
+ const { zoom } = (0, react_1.useContext)(timeline_zoom_1.TimelineZoomCtx);
316
+ const containerStyle = (0, react_1.useMemo)(() => {
317
+ return {
318
+ ...container,
319
+ width: 100 * zoom + '%',
320
+ };
321
+ }, [zoom]);
322
+ return ((0, jsx_runtime_1.jsxs)("div", { ref: timeline_refs_1.sliderAreaRef, style: containerStyle, onPointerDown: onPointerDown, children: [(0, jsx_runtime_1.jsx)("div", { style: inner }), inFrame !== null && ((0, jsx_runtime_1.jsx)(TimelineInOutPointerHandle_1.TimelineInOutPointerHandle, { type: "in", atFrame: inFrame, dragging: inOutDragging.dragging === 'in' })), outFrame !== null && ((0, jsx_runtime_1.jsx)(TimelineInOutPointerHandle_1.TimelineInOutPointerHandle, { type: "out", dragging: inOutDragging.dragging === 'out', atFrame: outFrame }))] }));
226
323
  };
227
324
  exports.TimelineDragHandler = TimelineDragHandler;
@@ -5,6 +5,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const colors_1 = require("../../helpers/colors");
6
6
  const is_collapsed_1 = require("./is-collapsed");
7
7
  const TimelineListItem_1 = require("./TimelineListItem");
8
+ const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
8
9
  const container = {
9
10
  flex: 1,
10
11
  display: 'flex',
@@ -12,9 +13,9 @@ const container = {
12
13
  background: colors_1.BACKGROUND,
13
14
  };
14
15
  const TimelineList = ({ timeline, viewState, dispatchStateChange }) => {
15
- return ((0, jsx_runtime_1.jsx)("div", { style: container, children: timeline.map((track, i) => {
16
- const beforeDepth = i === 0 ? 0 : timeline[i - 1].depth;
17
- return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(TimelineListItem_1.TimelineListItem, { hash: track.hash, dispatchStateChange: dispatchStateChange, collapsed: (0, is_collapsed_1.isTrackCollapsed)(track.hash, viewState), nestedDepth: track.depth, sequence: track.sequence, beforeDepth: beforeDepth, canCollapse: track.canCollapse }, track.sequence.id) }, track.sequence.id));
18
- }) }));
16
+ return ((0, jsx_runtime_1.jsxs)("div", { style: container, children: [(0, jsx_runtime_1.jsx)(TimelineTimeIndicators_1.TimelineTimePadding, {}), timeline.map((track, i) => {
17
+ const beforeDepth = i === 0 ? 0 : timeline[i - 1].depth;
18
+ return ((0, jsx_runtime_1.jsx)("div", { children: (0, jsx_runtime_1.jsx)(TimelineListItem_1.TimelineListItem, { hash: track.hash, dispatchStateChange: dispatchStateChange, collapsed: (0, is_collapsed_1.isTrackCollapsed)(track.hash, viewState), nestedDepth: track.depth, sequence: track.sequence, beforeDepth: beforeDepth, canCollapse: track.canCollapse }, track.sequence.id) }, track.sequence.id));
19
+ }), (0, jsx_runtime_1.jsx)(TimelineTimeIndicators_1.TimelineTimePlaceholders, {})] }));
19
20
  };
20
21
  exports.TimelineList = TimelineList;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import type { TSequence } from 'remotion';
3
3
  import type { TimelineActionState } from './timeline-state-reducer';
4
+ export declare const TOTAL_TIMELINE_LAYER_LEFT_PADDING: number;
4
5
  export declare const TimelineListItem: React.FC<{
5
6
  sequence: TSequence;
6
7
  nestedDepth: number;