@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
@@ -37,7 +37,7 @@ const SettingsModalFooter = () => {
37
37
  column: 1,
38
38
  };
39
39
  }, []);
40
- return (jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { style: footer, noBorder: true, children: jsx_runtime_1.jsx("div", { style: footerRow, children: jsx_runtime_1.jsxs("div", { style: configFileHint, children: ["Changes save to",
40
+ return (jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { style: footer, children: jsx_runtime_1.jsx("div", { style: footerRow, children: jsx_runtime_1.jsxs("div", { style: configFileHint, children: ["Changes save to",
41
41
  jsx_runtime_1.jsx(InspectorOpenInEditor_1.InspectorOpenInEditor, { locationType: null, location: configFileLocation, label: jsx_runtime_1.jsx("strong", { style: configFileName, children: "remotion.config.ts" }) })
42
42
  ] }) }) }));
43
43
  };
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const StudioSettings: React.FC;
@@ -0,0 +1,185 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StudioSettings = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const client_1 = require("@remotion/renderer/client");
6
+ const studio_shared_1 = require("@remotion/studio-shared");
7
+ const react_1 = require("react");
8
+ const colors_1 = require("../helpers/colors");
9
+ const Checkmark_1 = require("../icons/Checkmark");
10
+ const undo_1 = require("../icons/undo");
11
+ const Button_1 = require("./Button");
12
+ const styles_1 = require("./InspectorPanel/styles");
13
+ const layout_1 = require("./layout");
14
+ const ComboBox_1 = require("./NewComposition/ComboBox");
15
+ const InputDragger_1 = require("./NewComposition/InputDragger");
16
+ const ValidationMessage_1 = require("./NewComposition/ValidationMessage");
17
+ const layout_2 = require("./RenderModal/layout");
18
+ const RenderModalHr_1 = require("./RenderModal/RenderModalHr");
19
+ const SettingsContext_1 = require("./SettingsContext");
20
+ const use_auto_save_config_1 = require("./use-auto-save-config");
21
+ const container = {
22
+ display: 'flex',
23
+ flex: 1,
24
+ flexDirection: 'column',
25
+ minWidth: 0,
26
+ };
27
+ const dividerLabel = {
28
+ ...styles_1.sectionHeader,
29
+ margin: 0,
30
+ padding: '4px 16px',
31
+ };
32
+ const controlWidth = {
33
+ boxSizing: 'border-box',
34
+ width: 180,
35
+ };
36
+ const resetIcon = {
37
+ height: 12,
38
+ width: 12,
39
+ };
40
+ const DEFAULT_VALUE = 'studio-default';
41
+ const initialSettings = {
42
+ askAIEnabled: null,
43
+ audioLatencyHint: null,
44
+ beepOnFinish: null,
45
+ enableCrossSiteIsolation: null,
46
+ interactivityEnabled: null,
47
+ keyboardShortcutsEnabled: null,
48
+ logLevel: null,
49
+ maxTimelineTracks: null,
50
+ numberOfSharedAudioTags: null,
51
+ rspack: null,
52
+ };
53
+ const ConfigSelect = ({ defaultLabel, name, onChange, options, value, }) => {
54
+ const values = [
55
+ {
56
+ id: DEFAULT_VALUE,
57
+ keyHint: null,
58
+ label: `Default (${defaultLabel})`,
59
+ leftItem: value === null ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
60
+ onClick: () => onChange(null),
61
+ quickSwitcherLabel: null,
62
+ subMenu: null,
63
+ type: 'item',
64
+ value: DEFAULT_VALUE,
65
+ },
66
+ { id: `${DEFAULT_VALUE}-divider`, type: 'divider' },
67
+ ...options.map((option) => {
68
+ const id = `${name}-${String(option.value)}`;
69
+ return {
70
+ id,
71
+ keyHint: null,
72
+ label: option.label,
73
+ leftItem: value === option.value ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
74
+ onClick: () => onChange(option.value),
75
+ quickSwitcherLabel: null,
76
+ subMenu: null,
77
+ type: 'item',
78
+ value: id,
79
+ };
80
+ }),
81
+ ];
82
+ return (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
83
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: name }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: values, selectedId: value === null ? DEFAULT_VALUE : `${name}-${String(value)}`, style: controlWidth, title: name }) })
84
+ ] }));
85
+ };
86
+ const ConfigNumber = ({ defaultLabel, defaultValue, name, onChange, onChangeEnd, value, }) => {
87
+ const resolvedDefaultLabel = defaultLabel !== null && defaultLabel !== void 0 ? defaultLabel : String(defaultValue);
88
+ return (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
89
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: name }), jsx_runtime_1.jsxs("div", { style: { ...layout_2.rightRow, gap: 6 }, children: [
90
+ jsx_runtime_1.jsx(InputDragger_1.InputDragger, { "aria-label": name, buttonStyle: { textAlign: 'right', width: 140 }, formatter: () => value === null ? `Default (${resolvedDefaultLabel})` : String(value), min: 0, onTextChange: () => undefined, onValueChange: onChange, onValueChangeEnd: onChangeEnd, placeholder: `Default (${resolvedDefaultLabel})`, rightAlign: true, status: "ok", step: 1, value: value !== null && value !== void 0 ? value : defaultValue }), jsx_runtime_1.jsx(Button_1.Button, { disabled: value === null, onClick: () => onChangeEnd(null), size: "compact", style: { color: colors_1.LIGHT_TEXT }, title: `Use default (${resolvedDefaultLabel})`, children: jsx_runtime_1.jsx(undo_1.UndoIcon, { style: resetIcon }) })
91
+ ] })
92
+ ] }));
93
+ };
94
+ const booleanOptions = [
95
+ { label: 'Enabled', value: true },
96
+ { label: 'Disabled', value: false },
97
+ ];
98
+ const StudioSettings = () => {
99
+ var _a;
100
+ const { error: settingsError, revision, studioRuntimeConfig } = (0, SettingsContext_1.useSettings)();
101
+ const [settings, setSettings] = (0, react_1.useState)(initialSettings);
102
+ const [committedNumberSettings, setCommittedNumberSettings] = (0, react_1.useState)({ maxTimelineTracks: null, numberOfSharedAudioTags: null });
103
+ const [editedSetters, setEditedSetters] = (0, react_1.useState)(() => new Set());
104
+ const [syncedRevision, setSyncedRevision] = (0, react_1.useState)(-1);
105
+ const [error, setError] = (0, react_1.useState)(null);
106
+ (0, react_1.useEffect)(() => {
107
+ var _a, _b;
108
+ var _c, _d, _e;
109
+ if (studioRuntimeConfig === null) {
110
+ return;
111
+ }
112
+ setSettings((_c = studioRuntimeConfig.configFileStudioSettings) !== null && _c !== void 0 ? _c : initialSettings);
113
+ setCommittedNumberSettings({
114
+ maxTimelineTracks: (_d = (_a = studioRuntimeConfig.configFileStudioSettings) === null || _a === void 0 ? void 0 : _a.maxTimelineTracks) !== null && _d !== void 0 ? _d : null,
115
+ numberOfSharedAudioTags: (_e = (_b = studioRuntimeConfig.configFileStudioSettings) === null || _b === void 0 ? void 0 : _b.numberOfSharedAudioTags) !== null && _e !== void 0 ? _e : null,
116
+ });
117
+ setEditedSetters(new Set());
118
+ setSyncedRevision(revision);
119
+ setError(null);
120
+ }, [revision, studioRuntimeConfig]);
121
+ const changeSetting = (0, react_1.useCallback)((key, setter, value) => {
122
+ setSettings((current) => ({ ...current, [key]: value }));
123
+ setEditedSetters((current) => new Set(current).add(setter));
124
+ }, []);
125
+ const previewNumberSetting = (0, react_1.useCallback)((key, value) => {
126
+ setSettings((current) => ({ ...current, [key]: value }));
127
+ }, []);
128
+ const commitNumberSetting = (0, react_1.useCallback)((key, setter, value) => {
129
+ setSettings((current) => ({ ...current, [key]: value }));
130
+ setCommittedNumberSettings((current) => ({ ...current, [key]: value }));
131
+ setEditedSetters((current) => new Set(current).add(setter));
132
+ }, []);
133
+ const updates = (0, react_1.useMemo)(() => {
134
+ const update = (setter, value) => value === null ? { setter, type: 'delete' } : { setter, type: 'set', value };
135
+ const updatesForEditedSetters = [
136
+ update('setAskAIEnabled', settings.askAIEnabled),
137
+ update('setEnableCrossSiteIsolation', settings.enableCrossSiteIsolation),
138
+ update('setBeepOnFinish', settings.beepOnFinish),
139
+ update('setMaxTimelineTracks', committedNumberSettings.maxTimelineTracks),
140
+ update('setAudioLatencyHint', settings.audioLatencyHint),
141
+ update('setNumberOfSharedAudioTags', committedNumberSettings.numberOfSharedAudioTags),
142
+ update('setRspack', settings.rspack),
143
+ update('setKeyboardShortcutsEnabled', settings.keyboardShortcutsEnabled),
144
+ update('setInteractivityEnabled', settings.interactivityEnabled),
145
+ update('setLogLevel', settings.logLevel),
146
+ ].filter((item) => editedSetters.has(item.setter));
147
+ if (editedSetters.has('setRspack')) {
148
+ updatesForEditedSetters.push({
149
+ setter: 'setExperimentalRspackEnabled',
150
+ type: 'delete',
151
+ });
152
+ }
153
+ if (editedSetters.has('setLogLevel')) {
154
+ updatesForEditedSetters.push({ setter: 'setLevel', type: 'delete' });
155
+ }
156
+ return updatesForEditedSetters;
157
+ }, [committedNumberSettings, editedSetters, settings]);
158
+ const ready = studioRuntimeConfig !== null && syncedRevision === revision;
159
+ (0, use_auto_save_config_1.useAutoSaveConfig)({
160
+ enabled: ready,
161
+ onError: setError,
162
+ ready,
163
+ syncRevision: syncedRevision,
164
+ updates,
165
+ });
166
+ if (studioRuntimeConfig === null) {
167
+ return null;
168
+ }
169
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [
170
+ jsx_runtime_1.jsx("p", { style: dividerLabel, children: "Interface" }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Enabled", name: "Ask AI enabled", onChange: (value) => changeSetting('askAIEnabled', 'setAskAIEnabled', value), options: booleanOptions, value: settings.askAIEnabled }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Enabled", name: "Keyboard shortcuts enabled", onChange: (value) => changeSetting('keyboardShortcutsEnabled', 'setKeyboardShortcutsEnabled', value), options: booleanOptions, value: settings.keyboardShortcutsEnabled }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Enabled", name: "Interactivity enabled", onChange: (value) => changeSetting('interactivityEnabled', 'setInteractivityEnabled', value), options: booleanOptions, value: settings.interactivityEnabled }), jsx_runtime_1.jsx(ConfigNumber, { defaultLabel: "Unlimited", defaultValue: studio_shared_1.DEFAULT_TIMELINE_TRACKS, name: "Max timeline tracks", onChange: (value) => previewNumberSetting('maxTimelineTracks', value), onChangeEnd: (value) => commitNumberSetting('maxTimelineTracks', 'setMaxTimelineTracks', value), value: settings.maxTimelineTracks }), jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {}), jsx_runtime_1.jsx("p", { style: dividerLabel, children: "Audio" }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Playback", name: "Audio latency hint", onChange: (value) => changeSetting('audioLatencyHint', 'setAudioLatencyHint', value), options: [
171
+ { label: 'Interactive', value: 'interactive' },
172
+ { label: 'Balanced', value: 'balanced' },
173
+ { label: 'Playback', value: 'playback' },
174
+ ], value: settings.audioLatencyHint }), jsx_runtime_1.jsx(ConfigNumber, { defaultValue: 0, name: "Number of shared audio tags", onChange: (value) => previewNumberSetting('numberOfSharedAudioTags', value), onChangeEnd: (value) => commitNumberSetting('numberOfSharedAudioTags', 'setNumberOfSharedAudioTags', value), value: settings.numberOfSharedAudioTags }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Disabled", name: "Beep on finish", onChange: (value) => changeSetting('beepOnFinish', 'setBeepOnFinish', value), options: booleanOptions, value: settings.beepOnFinish }), jsx_runtime_1.jsx(RenderModalHr_1.RenderModalHr, {}), jsx_runtime_1.jsx("p", { style: dividerLabel, children: "Development" }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Webpack", name: "Bundler", onChange: (value) => changeSetting('rspack', 'setRspack', value), options: [
175
+ { label: 'Rspack', value: true },
176
+ { label: 'Webpack', value: false },
177
+ ], value: settings.rspack }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Disabled", name: "Cross-site isolation", onChange: (value) => changeSetting('enableCrossSiteIsolation', 'setEnableCrossSiteIsolation', value), options: booleanOptions, value: settings.enableCrossSiteIsolation }), jsx_runtime_1.jsx(ConfigSelect, { defaultLabel: "Info", name: "Log level", onChange: (value) => changeSetting('logLevel', 'setLogLevel', value), options: client_1.BrowserSafeApis.logLevels.map((value) => ({
178
+ label: value[0].toUpperCase() + value.slice(1),
179
+ value,
180
+ })), value: settings.logLevel }), (error !== null && error !== void 0 ? error : settingsError) ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
181
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx("div", { style: { paddingLeft: 16, paddingRight: 16 }, children: jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: (_a = error !== null && error !== void 0 ? error : settingsError) !== null && _a !== void 0 ? _a : '', type: "error" }) })
182
+ ] })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { y: 2, block: true })
183
+ ] }));
184
+ };
185
+ exports.StudioSettings = StudioSettings;
@@ -26,7 +26,7 @@ const centerContainer = {
26
26
  };
27
27
  const LoopedIndicator = () => {
28
28
  return (jsx_runtime_1.jsxs("div", { style: width, children: [
29
- jsx_runtime_1.jsx(remotion_1.AbsoluteFill, { style: centerContainer, children: jsx_runtime_1.jsx("div", { style: verticalLine }) }), jsx_runtime_1.jsx(remotion_1.AbsoluteFill, { style: centerContainer, children: jsx_runtime_1.jsx(Icon, {}) })
29
+ jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteFillElement, { style: centerContainer, children: jsx_runtime_1.jsx("div", { style: verticalLine }) }), jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteFillElement, { style: centerContainer, children: jsx_runtime_1.jsx(Icon, {}) })
30
30
  ] }));
31
31
  };
32
32
  exports.LoopedIndicator = LoopedIndicator;
@@ -1,4 +1,7 @@
1
1
  import React from 'react';
2
2
  export declare const LoopedTimelineIndicator: React.FC<{
3
3
  readonly loops: number;
4
+ readonly fullWidth: number;
5
+ readonly visibleOffset: number;
6
+ readonly visibleWidth: number;
4
7
  }>;
@@ -1,24 +1,32 @@
1
1
  "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
2
  Object.defineProperty(exports, "__esModule", { value: true });
6
3
  exports.LoopedTimelineIndicator = void 0;
7
4
  const jsx_runtime_1 = require("react/jsx-runtime");
8
- const react_1 = __importDefault(require("react"));
9
5
  const remotion_1 = require("remotion");
10
- const layout_1 = require("../layout");
11
6
  const LoopedIndicator_1 = require("./LoopedIndicator");
12
7
  const row = {
13
- flexDirection: 'row',
8
+ overflow: 'hidden',
14
9
  };
15
- const LoopedTimelineIndicator = ({ loops }) => {
16
- const leftOver = loops % 1;
17
- return (jsx_runtime_1.jsxs(remotion_1.AbsoluteFill, { style: row, children: [new Array(Math.floor(loops)).fill(true).map((_l, i) => {
18
- return (jsx_runtime_1.jsxs(react_1.default.Fragment
19
- // eslint-disable-next-line
20
- , { children: [
21
- jsx_runtime_1.jsx(layout_1.Flex, {}), i === loops - 1 ? null : jsx_runtime_1.jsx(LoopedIndicator_1.LoopedIndicator, {})] }, i));
22
- }), leftOver > 0 ? jsx_runtime_1.jsx("div", { style: { flex: leftOver } }) : null] }));
10
+ const LoopedTimelineIndicator = ({ loops, fullWidth, visibleOffset, visibleWidth }) => {
11
+ if (loops <= 1 || fullWidth <= 0 || visibleWidth <= 0) {
12
+ return null;
13
+ }
14
+ const loopWidth = fullWidth / loops;
15
+ const lastBoundaryIndex = Math.ceil(loops) - 1;
16
+ const firstVisibleBoundaryIndex = Math.max(1, Math.floor(visibleOffset / loopWidth));
17
+ const lastVisibleBoundaryIndex = Math.min(lastBoundaryIndex, Math.ceil((visibleOffset + visibleWidth) / loopWidth));
18
+ const visibleBoundaryCount = Math.max(0, lastVisibleBoundaryIndex - firstVisibleBoundaryIndex + 1);
19
+ const boundaries = new Array(visibleBoundaryCount)
20
+ .fill(true)
21
+ .map((_, index) => (firstVisibleBoundaryIndex + index) * loopWidth);
22
+ return (jsx_runtime_1.jsx(remotion_1.Internals.AbsoluteFillElement, { style: row, children: boundaries.map((boundary) => {
23
+ return (jsx_runtime_1.jsx("div", { style: {
24
+ position: 'absolute',
25
+ display: 'flex',
26
+ left: boundary - visibleOffset,
27
+ top: 0,
28
+ bottom: 0,
29
+ }, children: jsx_runtime_1.jsx(LoopedIndicator_1.LoopedIndicator, {}) }, boundary));
30
+ }) }));
23
31
  };
24
32
  exports.LoopedTimelineIndicator = LoopedTimelineIndicator;
@@ -75,6 +75,7 @@ const TimelineSelection_1 = require("./TimelineSelection");
75
75
  const TimelineSlider_1 = require("./TimelineSlider");
76
76
  const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
77
77
  const TimelineTracks_1 = require("./TimelineTracks");
78
+ const TimelineVirtualization_1 = require("./TimelineVirtualization");
78
79
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
79
80
  const use_resolved_stack_1 = require("./use-resolved-stack");
80
81
  const use_timeline_asset_drop_1 = require("./use-timeline-asset-drop");
@@ -329,7 +330,7 @@ const TimelineInner = () => {
329
330
  }, [filtered]);
330
331
  const maxTimelineTracks = (0, studio_runtime_config_1.getStudioMaxTimelineTracks)();
331
332
  const shown = (0, react_1.useMemo)(() => {
332
- return collapsed.length > maxTimelineTracks
333
+ return maxTimelineTracks !== null && collapsed.length > maxTimelineTracks
333
334
  ? collapsed.slice(0, maxTimelineTracks)
334
335
  : collapsed;
335
336
  }, [collapsed, maxTimelineTracks]);
@@ -339,14 +340,15 @@ const TimelineInner = () => {
339
340
  return null;
340
341
  }
341
342
  return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, componentIdentity: sequence.controls.componentIdentity, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
342
- }), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: [(0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, isStill: isStill, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown, showTimePadding: false })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
343
- jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, maxFlexerSize: null, minFlexerSize: MIN_TIMELINE_LABELS_WIDTH, maxAntiFlexerSize: null, minAntiFlexerSize: null, children: [
344
- jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown, showTimePadding: true }) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: null, children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
345
- jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null, jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
346
- ] }) })
347
- ] })
348
- ] })) })
349
- ] }) })
343
+ }), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: jsx_runtime_1.jsxs(TimelineVirtualization_1.TimelineVirtualizationProvider, { hasBeenCut: hasBeenCut, isStill: isStill, timeline: shown, children: [(0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, {})) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
344
+ jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, maxFlexerSize: null, minFlexerSize: MIN_TIMELINE_LABELS_WIDTH, maxAntiFlexerSize: null, minAntiFlexerSize: null, children: [
345
+ jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, {}) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
346
+ jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
347
+ ] }), children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
348
+ jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null] }) })
349
+ ] })
350
+ ] })) })
351
+ ] }) }) })
350
352
  ] }));
351
353
  };
352
354
  exports.Timeline = react_1.default.memo(TimelineInner);
@@ -1,8 +1,8 @@
1
1
  import React from 'react';
2
2
  import { type CanUpdateSequencePropStatusStatic } from 'remotion';
3
3
  import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
- import { type InspectorInlineActionProps } from '../InspectorPanel/common';
5
- export type InspectorSourceAction = Omit<InspectorInlineActionProps, 'variant'>;
4
+ import { type InspectorQuickActionProps } from '../InspectorPanel/common';
5
+ export type InspectorSourceAction = Omit<InspectorQuickActionProps, 'variant'>;
6
6
  type AssetSelectionContextValue = {
7
7
  readonly initialQuery: string;
8
8
  readonly getSourceAction: (src: string) => InspectorSourceAction | null;
@@ -100,7 +100,7 @@ const TimelineAssetField = ({ field, effectiveValue, propStatus, onSave, onDragV
100
100
  if (inlineSourceAction === null) {
101
101
  return action;
102
102
  }
103
- return (jsx_runtime_1.jsx(common_1.InspectorInlineAction, { ...inlineSourceAction, size: "compact", variant: {
103
+ return (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { ...inlineSourceAction, size: "compact", variant: {
104
104
  type: 'segmented',
105
105
  trailing: {
106
106
  disabled: window.remotion_isReadOnlyStudio,
@@ -40,10 +40,10 @@ const react_1 = __importStar(require("react"));
40
40
  const remotion_1 = require("remotion");
41
41
  const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
42
42
  const pointer_session_1 = require("../../helpers/pointer-session");
43
- const timeline_layout_1 = require("../../helpers/timeline-layout");
44
43
  const timeline_zoom_1 = require("../../state/timeline-zoom");
45
44
  const z_index_1 = require("../../state/z-index");
46
45
  const is_menu_item_1 = require("../Menu/is-menu-item");
46
+ const imperative_state_1 = require("./imperative-state");
47
47
  const timeline_refs_1 = require("./timeline-refs");
48
48
  const timeline_scroll_logic_1 = require("./timeline-scroll-logic");
49
49
  const TimelineSelection_1 = require("./TimelineSelection");
@@ -109,13 +109,7 @@ const TimelineDragHandlerInner = () => {
109
109
  dragging: false,
110
110
  });
111
111
  const { isPlaying, play, pause, seek } = player_1.PlayerInternals.usePlayerMethods();
112
- const scroller = (0, react_1.useRef)(null);
113
- const stopInterval = () => {
114
- if (scroller.current) {
115
- clearInterval(scroller.current);
116
- scroller.current = null;
117
- }
118
- };
112
+ const autoScroller = (0, react_1.useRef)(null);
119
113
  const onPointerDown = (0, react_1.useCallback)((e) => {
120
114
  var _a, _b;
121
115
  if (e.button !== 0) {
@@ -124,7 +118,6 @@ const TimelineDragHandlerInner = () => {
124
118
  if (!isHighestContext) {
125
119
  return;
126
120
  }
127
- stopInterval();
128
121
  if (!videoConfig) {
129
122
  return;
130
123
  }
@@ -148,87 +141,66 @@ const TimelineDragHandlerInner = () => {
148
141
  (_b = (_a = e.currentTarget).setPointerCapture) === null || _b === void 0 ? void 0 : _b.call(_a, e.pointerId);
149
142
  pause();
150
143
  }, [isHighestContext, videoConfig, left, width, seek, isPlaying, pause]);
144
+ const onEdgeScrollTick = (0, react_1.useCallback)((directions) => {
145
+ var _a;
146
+ if (!videoConfig || directions.x === null) {
147
+ return;
148
+ }
149
+ const nextFrame = directions.x === 'left'
150
+ ? (0, timeline_scroll_logic_1.getFrameWhileScrollingLeft)({
151
+ durationInFrames: videoConfig.durationInFrames,
152
+ width,
153
+ })
154
+ : (0, timeline_scroll_logic_1.getFrameWhileScrollingRight)({
155
+ durationInFrames: videoConfig.durationInFrames,
156
+ width,
157
+ });
158
+ const scrollPos = directions.x === 'left'
159
+ ? (0, timeline_scroll_logic_1.getScrollPositionForCursorOnLeftEdge)({
160
+ nextFrame,
161
+ durationInFrames: videoConfig.durationInFrames,
162
+ })
163
+ : (0, timeline_scroll_logic_1.getScrollPositionForCursorOnRightEdge)({
164
+ nextFrame,
165
+ durationInFrames: videoConfig.durationInFrames,
166
+ });
167
+ // Update the imperative frame and apply the scroll before drawing, so
168
+ // every redraw (including the scroll event listener in TimelineSlider)
169
+ // sees a consistent (frame, scrollLeft) pair. Otherwise the playhead
170
+ // flickers between stale combinations while React commits the seek.
171
+ (0, imperative_state_1.setCurrentFrame)(nextFrame);
172
+ (0, timeline_scroll_logic_1.scrollToTimelineXOffset)(scrollPos);
173
+ (_a = TimelineSlider_1.redrawTimelineSliderFast.current) === null || _a === void 0 ? void 0 : _a.draw(nextFrame);
174
+ seek(nextFrame);
175
+ }, [videoConfig, width, seek]);
151
176
  const onPointerMoveScrubbing = (0, react_1.useCallback)((e) => {
152
177
  var _a;
178
+ var _b;
153
179
  if (!videoConfig) {
154
180
  return;
155
181
  }
156
182
  if (!dragging.dragging) {
157
183
  return;
158
184
  }
159
- const isRightOfArea = e.clientX >=
160
- ((_a = timeline_refs_1.scrollableRef.current) === null || _a === void 0 ? void 0 : _a.clientWidth) +
161
- left -
162
- timeline_layout_1.TIMELINE_PADDING;
163
- const isLeftOfArea = e.clientX <= left;
185
+ const directions = (_b = (_a = autoScroller.current) === null || _a === void 0 ? void 0 : _a.update(e)) !== null && _b !== void 0 ? _b : {
186
+ x: null,
187
+ y: null,
188
+ };
189
+ // While edge auto-scrolling is active, the tick owns seeking
190
+ if (directions.x !== null) {
191
+ return;
192
+ }
164
193
  const frame = (0, timeline_scroll_logic_1.getFrameFromX)({
165
194
  clientX: getClientXWithScroll(e.clientX) - left,
166
195
  durationInFrames: videoConfig.durationInFrames,
167
196
  width,
168
197
  extrapolate: 'clamp',
169
198
  });
170
- if (isLeftOfArea && (0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollLeft) {
171
- if (scroller.current) {
172
- return;
173
- }
174
- const scrollEvery = () => {
175
- var _a;
176
- if (!(0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollLeft) {
177
- stopInterval();
178
- return;
179
- }
180
- const nextFrame = (0, timeline_scroll_logic_1.getFrameWhileScrollingLeft)({
181
- durationInFrames: videoConfig.durationInFrames,
182
- width,
183
- });
184
- const scrollPos = (0, timeline_scroll_logic_1.getScrollPositionForCursorOnLeftEdge)({
185
- nextFrame,
186
- durationInFrames: videoConfig.durationInFrames,
187
- });
188
- (_a = TimelineSlider_1.redrawTimelineSliderFast.current) === null || _a === void 0 ? void 0 : _a.draw(nextFrame);
189
- seek(nextFrame);
190
- (0, timeline_scroll_logic_1.scrollToTimelineXOffset)(scrollPos);
191
- };
192
- scrollEvery();
193
- scroller.current = setInterval(() => {
194
- scrollEvery();
195
- }, 100);
196
- }
197
- else if (isRightOfArea &&
198
- (0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollRight) {
199
- if (scroller.current) {
200
- return;
201
- }
202
- const scrollEvery = () => {
203
- var _a;
204
- if (!(0, timeline_scroll_logic_1.canScrollTimelineIntoDirection)().canScrollRight) {
205
- stopInterval();
206
- return;
207
- }
208
- const nextFrame = (0, timeline_scroll_logic_1.getFrameWhileScrollingRight)({
209
- durationInFrames: videoConfig.durationInFrames,
210
- width,
211
- });
212
- const scrollPos = (0, timeline_scroll_logic_1.getScrollPositionForCursorOnRightEdge)({
213
- nextFrame,
214
- durationInFrames: videoConfig.durationInFrames,
215
- });
216
- (_a = TimelineSlider_1.redrawTimelineSliderFast.current) === null || _a === void 0 ? void 0 : _a.draw(nextFrame);
217
- seek(nextFrame);
218
- (0, timeline_scroll_logic_1.scrollToTimelineXOffset)(scrollPos);
219
- };
220
- scrollEvery();
221
- scroller.current = setInterval(() => {
222
- scrollEvery();
223
- }, 100);
224
- }
225
- else {
226
- stopInterval();
227
- seek(frame);
228
- }
199
+ seek(frame);
229
200
  }, [videoConfig, dragging.dragging, left, width, seek]);
230
201
  const onPointerUpScrubbing = (0, react_1.useCallback)((e) => {
231
- stopInterval();
202
+ var _a;
203
+ (_a = autoScroller.current) === null || _a === void 0 ? void 0 : _a.stop();
232
204
  document.body.style.userSelect = '';
233
205
  document.body.style.webkitUserSelect = '';
234
206
  if (!videoConfig) {
@@ -259,7 +231,8 @@ const TimelineDragHandlerInner = () => {
259
231
  }
260
232
  }, [dragging, left, play, videoConfig, setFrame, width]);
261
233
  const onPointerCancelScrubbing = (0, react_1.useCallback)(() => {
262
- stopInterval();
234
+ var _a;
235
+ (_a = autoScroller.current) === null || _a === void 0 ? void 0 : _a.stop();
263
236
  document.body.style.userSelect = '';
264
237
  document.body.style.webkitUserSelect = '';
265
238
  if (!dragging.dragging) {
@@ -274,7 +247,12 @@ const TimelineDragHandlerInner = () => {
274
247
  if (!dragging.dragging) {
275
248
  return;
276
249
  }
277
- return (0, pointer_session_1.startCapturedPointerSession)({
250
+ const scroller = (0, timeline_scroll_logic_1.startTimelineEdgeAutoScroll)({
251
+ includeVertical: false,
252
+ onTick: onEdgeScrollTick,
253
+ });
254
+ autoScroller.current = scroller;
255
+ const endSession = (0, pointer_session_1.startCapturedPointerSession)({
278
256
  event: dragging,
279
257
  captureTarget: dragging.target,
280
258
  onMove: onPointerMoveScrubbing,
@@ -288,8 +266,16 @@ const TimelineDragHandlerInner = () => {
288
266
  }
289
267
  },
290
268
  });
269
+ return () => {
270
+ scroller.stop();
271
+ if (autoScroller.current === scroller) {
272
+ autoScroller.current = null;
273
+ }
274
+ endSession();
275
+ };
291
276
  }, [
292
277
  dragging,
278
+ onEdgeScrollTick,
293
279
  onPointerCancelScrubbing,
294
280
  onPointerMoveScrubbing,
295
281
  onPointerUpScrubbing,
@@ -321,7 +321,7 @@ const TimelineEffectItem = ({ label, nodePathInfo, effectIndex, effectSchema, do
321
321
  ...(dropIndicator === 'before' ? { top: -1 } : { bottom: -1 }),
322
322
  };
323
323
  }, [dropIndicator]);
324
- const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, selected: selection.selected, selectable: selection.selectable, selectionItem: selection.selectionItem, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: containsSelection, isFieldRow: false, outerHeight: null, children: jsx_runtime_1.jsx("span", { title: label, style: labelStyle, children: label }) }));
324
+ const row = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: canToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: "effect", hidden: isDisabled, onInvoked: onToggle })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: () => toggleTrack(nodePathInfo), label: `${label} section`, disabled: false }), style: rowStyle, selected: selection.selected, selectable: selection.selectable, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: containsSelection, isFieldRow: false, outerHeight: null, children: jsx_runtime_1.jsx("span", { title: label, style: labelStyle, children: label }) }));
325
325
  const draggableRow = canReorder ? (jsx_runtime_1.jsxs("div", { draggable: true, onDragStart: onDragStart, onDragEnd: onDragEnd, onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, style: reorderWrapper, children: [reorderLineStyle ? jsx_runtime_1.jsx("div", { style: reorderLineStyle }) : null, row] })) : (row);
326
326
  return previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: draggableRow })) : (draggableRow);
327
327
  };
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { SequencePropsSubscriptionKey } from 'remotion';
2
+ import type { RuntimeValueStore, SequencePropsSubscriptionKey } from 'remotion';
3
3
  import type { CodePosition } from '../../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
5
5
  import type { EffectSchemaFieldInfo } from '../../helpers/timeline-layout';
@@ -9,6 +9,7 @@ export declare const TimelineEffectPropValue: React.FC<{
9
9
  readonly nodePath: SequencePropsSubscriptionKey;
10
10
  readonly validatedLocation: CodePosition;
11
11
  readonly sourceFrame: number;
12
+ readonly runtimeValueStore: RuntimeValueStore | null;
12
13
  }>;
13
14
  export declare const TimelineEffectPropItem: React.FC<{
14
15
  readonly field: EffectSchemaFieldInfo;
@@ -17,5 +18,6 @@ export declare const TimelineEffectPropItem: React.FC<{
17
18
  readonly nodePath: SequencePropsSubscriptionKey;
18
19
  readonly nodePathInfo: SequenceNodePathInfo;
19
20
  readonly keyframeDisplayOffset: number;
20
- readonly keyframeControlsMode?: TimelineKeyframeControlsMode;
21
+ readonly keyframeControlsMode: TimelineKeyframeControlsMode;
22
+ readonly runtimeValueStore: RuntimeValueStore | null;
21
23
  }>;