@remotion/studio 4.0.499 → 4.0.501

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 (204) hide show
  1. package/dist/Studio.js +1 -1
  2. package/dist/api/delete-static-file.js +8 -3
  3. package/dist/api/rename-static-file.js +8 -0
  4. package/dist/api/watch-public-folder.js +2 -1
  5. package/dist/api/watch-static-file.js +2 -1
  6. package/dist/api/write-static-file.js +8 -3
  7. package/dist/components/AssetSelector.js +11 -7
  8. package/dist/components/AssetSelectorItem.d.ts +25 -0
  9. package/dist/components/AssetSelectorItem.js +116 -80
  10. package/dist/components/Canvas.js +6 -1
  11. package/dist/components/CaptionInspector.d.ts +10 -0
  12. package/dist/components/CaptionInspector.js +24 -0
  13. package/dist/components/CaptionTextEditor.d.ts +9 -0
  14. package/dist/components/CaptionTextEditor.js +132 -0
  15. package/dist/components/CompositionSelector.js +2 -32
  16. package/dist/components/ControlButton.js +1 -0
  17. package/dist/components/CurrentAsset.js +3 -2
  18. package/dist/components/EditorContexts.d.ts +0 -1
  19. package/dist/components/EditorContexts.js +2 -2
  20. package/dist/components/ExplorerPanel.js +2 -1
  21. package/dist/components/ExplorerPanelRef.d.ts +2 -0
  22. package/dist/components/FpsCounter.js +3 -3
  23. package/dist/components/FullscreenToggle.js +2 -1
  24. package/dist/components/GlobalKeybindings.js +9 -1
  25. package/dist/components/InitialCompositionLoader.d.ts +1 -1
  26. package/dist/components/InlineAction.d.ts +2 -1
  27. package/dist/components/InlineAction.js +3 -2
  28. package/dist/components/InlineCaptionInspector.d.ts +11 -0
  29. package/dist/components/InlineCaptionInspector.js +108 -0
  30. package/dist/components/InlineDropdown.d.ts +1 -1
  31. package/dist/components/InlineDropdown.js +3 -2
  32. package/dist/components/InspectorPanel/AlignmentControls.d.ts +2 -2
  33. package/dist/components/InspectorPanel/AlignmentControls.js +5 -2
  34. package/dist/components/InspectorPanel/CompositionInspector.js +12 -9
  35. package/dist/components/InspectorPanel/CompositionMetadata.js +170 -57
  36. package/dist/components/InspectorPanel/ConnectedCompositionsSection.d.ts +2 -2
  37. package/dist/components/InspectorPanel/SelectedInspector.d.ts +1 -0
  38. package/dist/components/InspectorPanel/SelectedInspector.js +2 -2
  39. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -3
  40. package/dist/components/InspectorPanel/SequenceSelectionInspector.d.ts +1 -0
  41. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +10 -10
  42. package/dist/components/InspectorPanel/common.d.ts +17 -4
  43. package/dist/components/InspectorPanel/common.js +60 -6
  44. package/dist/components/InspectorPanel/inspector-section-collapse.d.ts +22 -0
  45. package/dist/components/InspectorPanel/inspector-section-collapse.js +165 -0
  46. package/dist/components/InspectorPanel/styles.js +7 -1
  47. package/dist/components/InspectorPanel/use-composition-actions.d.ts +3 -0
  48. package/dist/components/InspectorPanel/use-composition-actions.js +91 -5
  49. package/dist/components/InspectorPanel/use-track-for-selection.d.ts +1 -1
  50. package/dist/components/InspectorPanel.js +2 -2
  51. package/dist/components/InspectorSequenceSection.d.ts +2 -1
  52. package/dist/components/InspectorSequenceSection.js +279 -25
  53. package/dist/components/KeyboardShortcutsExplainer.js +4 -2
  54. package/dist/components/Menu/MenuItem.js +2 -1
  55. package/dist/components/MenuCompositionName.js +30 -7
  56. package/dist/components/MenuToolbar.d.ts +0 -1
  57. package/dist/components/MenuToolbar.js +15 -7
  58. package/dist/components/MobilePanel.d.ts +2 -1
  59. package/dist/components/MobilePanel.js +29 -25
  60. package/dist/components/ModalContainer.d.ts +1 -0
  61. package/dist/components/ModalContainer.js +2 -2
  62. package/dist/components/Modals.js +1 -1
  63. package/dist/components/NewComposition/DismissableModal.d.ts +1 -0
  64. package/dist/components/NewComposition/DismissableModal.js +2 -2
  65. package/dist/components/NewComposition/InputDragger.d.ts +7 -0
  66. package/dist/components/NewComposition/InputDragger.js +119 -8
  67. package/dist/components/OutlineToggle.d.ts +1 -3
  68. package/dist/components/OutlineToggle.js +2 -2
  69. package/dist/components/PreviewToolbar.js +10 -4
  70. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.d.ts +7 -0
  71. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +45 -0
  72. package/dist/components/QuickSwitcher/NoResults.d.ts +1 -1
  73. package/dist/components/QuickSwitcher/NoResults.js +1 -0
  74. package/dist/components/QuickSwitcher/QuickSwitcher.d.ts +10 -0
  75. package/dist/components/QuickSwitcher/QuickSwitcher.js +6 -2
  76. package/dist/components/QuickSwitcher/QuickSwitcherContent.d.ts +10 -0
  77. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +95 -13
  78. package/dist/components/QuickSwitcher/QuickSwitcherResult.d.ts +4 -0
  79. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +11 -8
  80. package/dist/components/QuickSwitcher/asset-search.d.ts +9 -0
  81. package/dist/components/QuickSwitcher/asset-search.js +42 -0
  82. package/dist/components/RenderQueue/ClientRenderQueueProcessor.d.ts +0 -1
  83. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +3 -14
  84. package/dist/components/RenderQueue/RenderQueueDownloadItem.js +2 -2
  85. package/dist/components/SelectedOutlineCropControls.d.ts +8 -0
  86. package/dist/components/SelectedOutlineCropControls.js +299 -0
  87. package/dist/components/SelectedOutlineElement.js +84 -47
  88. package/dist/components/SelectedOutlineOverlay.d.ts +2 -2
  89. package/dist/components/SelectedOutlineOverlay.js +147 -16
  90. package/dist/components/SequencePropsSubscriptionProvider.d.ts +2 -0
  91. package/dist/components/SequencePropsSubscriptionProvider.js +31 -3
  92. package/dist/components/ShowOutlinesProvider.js +4 -1
  93. package/dist/components/SidebarCollapserControls.d.ts +3 -1
  94. package/dist/components/SidebarCollapserControls.js +34 -29
  95. package/dist/components/SnappingToggle.d.ts +1 -3
  96. package/dist/components/SnappingToggle.js +2 -2
  97. package/dist/components/Timeline/Timeline.js +19 -5
  98. package/dist/components/Timeline/TimelineAssetField.d.ts +9 -1
  99. package/dist/components/Timeline/TimelineAssetField.js +53 -100
  100. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +7 -3
  101. package/dist/components/Timeline/TimelineClipboardKeybindings.js +65 -38
  102. package/dist/components/Timeline/TimelineColorField.js +20 -1
  103. package/dist/components/Timeline/TimelineEffectPropItem.js +8 -77
  104. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +8 -1
  105. package/dist/components/Timeline/TimelineHeightContainer.d.ts +2 -2
  106. package/dist/components/Timeline/TimelineKeyframeTracksContext.d.ts +3 -3
  107. package/dist/components/Timeline/TimelineList.d.ts +2 -2
  108. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +7 -2
  109. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +10 -2
  110. package/dist/components/Timeline/TimelineRowChrome.d.ts +3 -0
  111. package/dist/components/Timeline/TimelineRowChrome.js +4 -3
  112. package/dist/components/Timeline/TimelineSelection.d.ts +9 -7
  113. package/dist/components/Timeline/TimelineSelection.js +17 -12
  114. package/dist/components/Timeline/TimelineSequence.js +2 -9
  115. package/dist/components/Timeline/TimelineSequenceItem.js +61 -15
  116. package/dist/components/Timeline/TimelineSequencePropItem.js +36 -85
  117. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +0 -1
  118. package/dist/components/Timeline/TimelineTrack.d.ts +2 -2
  119. package/dist/components/Timeline/TimelineTrack.js +4 -2
  120. package/dist/components/Timeline/TimelineTracks.d.ts +2 -2
  121. package/dist/components/Timeline/border-radius-representation.d.ts +16 -0
  122. package/dist/components/Timeline/border-radius-representation.js +60 -0
  123. package/dist/components/Timeline/delete-selected-timeline-item.js +1 -6
  124. package/dist/components/Timeline/find-track-for-node-path-info.d.ts +1 -1
  125. package/dist/components/Timeline/get-sequence-context-menu-items.js +14 -12
  126. package/dist/components/Timeline/get-sequence-prop-reset-changes.d.ts +10 -0
  127. package/dist/components/Timeline/get-sequence-prop-reset-changes.js +33 -0
  128. package/dist/components/Timeline/reset-selected-timeline-props.js +20 -18
  129. package/dist/components/Timeline/save-effect-prop.d.ts +10 -0
  130. package/dist/components/Timeline/save-effect-prop.js +52 -1
  131. package/dist/components/Timeline/save-sequence-prop.d.ts +12 -1
  132. package/dist/components/Timeline/save-sequence-prop.js +25 -1
  133. package/dist/components/Timeline/should-show-track-in-timeline.d.ts +2 -2
  134. package/dist/components/Timeline/timeline-asset-link.js +17 -1
  135. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  136. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +4 -0
  137. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +9 -3
  138. package/dist/components/Timeline/use-timeline-asset-drop.js +4 -0
  139. package/dist/components/Timeline/use-timeline-height.d.ts +2 -2
  140. package/dist/components/TopPanel.js +2 -2
  141. package/dist/components/UndoRedoButtons.js +42 -11
  142. package/dist/components/composition-drop-preview.js +1 -0
  143. package/dist/components/handle-drop.d.ts +3 -2
  144. package/dist/components/handle-drop.js +2 -1
  145. package/dist/components/import-assets.d.ts +4 -2
  146. package/dist/components/import-assets.js +20 -7
  147. package/dist/components/menu-toolbar-height.d.ts +1 -0
  148. package/dist/components/menu-toolbar-height.js +4 -0
  149. package/dist/components/selected-outline-drag.d.ts +41 -4
  150. package/dist/components/selected-outline-drag.js +179 -2
  151. package/dist/components/selected-outline-geometry.d.ts +1 -0
  152. package/dist/components/selected-outline-measurement.d.ts +11 -0
  153. package/dist/components/selected-outline-measurement.js +64 -3
  154. package/dist/components/selected-outline-types.d.ts +44 -1
  155. package/dist/components/selected-outline-types.js +21 -1
  156. package/dist/components/use-element-overwrite-confirmation.d.ts +2 -0
  157. package/dist/components/use-element-overwrite-confirmation.js +73 -0
  158. package/dist/components/use-static-files.js +7 -2
  159. package/dist/error-overlay/react-overlay/effects/resolve-file-source.js +13 -2
  160. package/dist/error-overlay/remotion-overlay/Overlay.js +3 -3
  161. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +2 -3
  162. package/dist/esm/{chunk-pk1zwsn1.js → chunk-n1kj09yv.js} +10618 -8002
  163. package/dist/esm/index.mjs +24 -8
  164. package/dist/esm/internals.mjs +10618 -8002
  165. package/dist/esm/previewEntry.mjs +40002 -37388
  166. package/dist/esm/renderEntry.mjs +1 -1
  167. package/dist/helpers/browser-studio-operations.d.ts +3 -0
  168. package/dist/helpers/browser-studio-operations.js +14 -0
  169. package/dist/helpers/calculate-timeline.d.ts +2 -2
  170. package/dist/helpers/calculate-timeline.js +8 -28
  171. package/dist/helpers/client-id.d.ts +0 -1
  172. package/dist/helpers/client-id.js +15 -10
  173. package/dist/helpers/download-blob.d.ts +1 -0
  174. package/dist/helpers/download-blob.js +15 -0
  175. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +3 -10
  176. package/dist/helpers/get-timeline-sequence-sort-key.js +5 -13
  177. package/dist/helpers/inject-css.js +5 -3
  178. package/dist/helpers/interactivity-enabled.d.ts +1 -0
  179. package/dist/helpers/interactivity-enabled.js +7 -2
  180. package/dist/helpers/is-mac.d.ts +1 -0
  181. package/dist/helpers/is-mac.js +4 -0
  182. package/dist/helpers/open-in-editor.d.ts +5 -1
  183. package/dist/helpers/open-in-editor.js +39 -4
  184. package/dist/helpers/preview-server-events.js +46 -9
  185. package/dist/helpers/sort-by-nonce-history.js +97 -19
  186. package/dist/helpers/use-create-composition.js +8 -6
  187. package/dist/helpers/use-keybinding.js +2 -3
  188. package/dist/helpers/use-menu-structure.js +39 -1
  189. package/dist/hot-middleware-client/client.js +3 -3
  190. package/dist/icons/border-radius.d.ts +4 -0
  191. package/dist/icons/border-radius.js +8 -0
  192. package/dist/icons/caret.d.ts +1 -0
  193. package/dist/icons/caret.js +2 -2
  194. package/dist/icons/fullscreen.d.ts +4 -0
  195. package/dist/icons/fullscreen.js +6 -0
  196. package/dist/icons/pen.d.ts +5 -0
  197. package/dist/icons/pen.js +8 -0
  198. package/dist/previewEntry.js +1 -1
  199. package/dist/state/modals.d.ts +9 -0
  200. package/dist/state/timeline-sequence-hover.d.ts +17 -0
  201. package/dist/state/timeline-sequence-hover.js +33 -0
  202. package/package.json +13 -12
  203. package/dist/helpers/get-timeline-sequence-hash.d.ts +0 -6
  204. package/dist/helpers/get-timeline-sequence-hash.js +0 -33
@@ -212,7 +212,7 @@ var renderContent = (Root) => {
212
212
  renderToDOM(/* @__PURE__ */ jsx("div", {
213
213
  children: /* @__PURE__ */ jsx(DelayedSpinner, {})
214
214
  }));
215
- import("./chunk-pk1zwsn1.js").then(({ StudioInternals }) => {
215
+ import("./chunk-n1kj09yv.js").then(({ StudioInternals }) => {
216
216
  window.remotion_isStudio = true;
217
217
  window.remotion_isReadOnlyStudio = true;
218
218
  window.remotion_inputProps = "{}";
@@ -0,0 +1,3 @@
1
+ import type { BrowserStudioOperations } from '@remotion/studio-shared';
2
+ export declare const BROWSER_STUDIO_OPERATIONS_READY_EVENT = "remotion-browser-studio-operations-ready";
3
+ export declare const getBrowserStudioOperations: () => BrowserStudioOperations | null;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getBrowserStudioOperations = exports.BROWSER_STUDIO_OPERATIONS_READY_EVENT = void 0;
4
+ // Browser Studio may be hosted by a different studio-shared version, so this
5
+ // handshake intentionally has no shared runtime import.
6
+ exports.BROWSER_STUDIO_OPERATIONS_READY_EVENT = 'remotion-browser-studio-operations-ready';
7
+ const getBrowserStudioOperations = () => {
8
+ var _a;
9
+ if (typeof window === 'undefined') {
10
+ return null;
11
+ }
12
+ return (_a = window.remotion_browserStudio) !== null && _a !== void 0 ? _a : null;
13
+ };
14
+ exports.getBrowserStudioOperations = getBrowserStudioOperations;
@@ -1,7 +1,7 @@
1
1
  import type { OverrideIdToNodePaths, TSequence } from 'remotion';
2
- import type { TrackWithHash } from './get-timeline-sequence-sort-key';
2
+ import type { TimelineTrackData } from './get-timeline-sequence-sort-key';
3
3
  export declare const calculateTimeline: ({ sequences, overrideIdsToNodePaths, compositions, }: {
4
4
  sequences: TSequence[];
5
5
  overrideIdsToNodePaths: OverrideIdToNodePaths;
6
6
  compositions?: readonly import("remotion").AnyComposition[] | undefined;
7
- }) => TrackWithHash[];
7
+ }) => TimelineTrackData[];
@@ -5,7 +5,6 @@ const studio_shared_1 = require("@remotion/studio-shared");
5
5
  const get_connected_compositions_1 = require("./get-connected-compositions");
6
6
  const get_sequence_visible_range_1 = require("./get-sequence-visible-range");
7
7
  const get_timeline_nestedness_1 = require("./get-timeline-nestedness");
8
- const get_timeline_sequence_hash_1 = require("./get-timeline-sequence-hash");
9
8
  const get_timeline_sequence_sort_key_1 = require("./get-timeline-sequence-sort-key");
10
9
  const sort_by_nonce_history_1 = require("./sort-by-nonce-history");
11
10
  const getInheritedLoopDisplay = (sequence, sequences) => {
@@ -52,19 +51,8 @@ const calculateTimeline = ({ sequences, overrideIdsToNodePaths, compositions = [
52
51
  }
53
52
  return true;
54
53
  });
55
- const sameHashes = {};
56
- const hashesUsedInRoot = {};
57
- const cache = {};
58
54
  for (let i = 0; i < timelineSequences.length; i++) {
59
55
  const sequence = timelineSequences[i];
60
- if (!hashesUsedInRoot[sequence.rootId]) {
61
- hashesUsedInRoot[sequence.rootId] = [];
62
- }
63
- const actualHash = (0, get_timeline_sequence_hash_1.getTimelineSequenceHash)(sequence, sortedSequences, hashesUsedInRoot, cache);
64
- if (!sameHashes[actualHash]) {
65
- sameHashes[actualHash] = [];
66
- }
67
- sameHashes[actualHash].push(sequence.id);
68
56
  const cascadedStart = (0, get_sequence_visible_range_1.getCascadedStart)(sequence, sortedSequences);
69
57
  const cascadedStartWithTrim = (0, get_sequence_visible_range_1.getCascadedStartWithTrim)(sequence, sortedSequences);
70
58
  const effectiveFrom = sequence.trimBefore === null
@@ -87,7 +75,6 @@ const calculateTimeline = ({ sequences, overrideIdsToNodePaths, compositions = [
87
75
  : sequence.loopDisplay,
88
76
  },
89
77
  depth: (0, get_timeline_nestedness_1.getTimelineNestedLevel)(sequence, sortedSequences, 0),
90
- hash: actualHash,
91
78
  cascadedStart,
92
79
  cascadedDuration: sequence.duration,
93
80
  keyframeDisplayOffset: hasKeyframeRows
@@ -105,26 +92,19 @@ const calculateTimeline = ({ sequences, overrideIdsToNodePaths, compositions = [
105
92
  : null,
106
93
  });
107
94
  }
108
- const uniqueTracks = [];
109
- for (const track of tracks) {
110
- const existingTrack = uniqueTracks.find((t) => t.hash === track.hash);
111
- if (!existingTrack) {
112
- const { cascadedDuration, cascadedStart, ...cleanTrack } = track;
113
- uniqueTracks.push(cleanTrack);
114
- }
115
- else if (existingTrack.connectedCompositions === undefined &&
116
- track.connectedCompositions !== undefined) {
117
- existingTrack.connectedCompositions = track.connectedCompositions;
118
- }
119
- }
120
95
  const nonceRanks = new Map();
121
96
  for (let i = 0; i < tracks.length; i++) {
122
97
  nonceRanks.set(tracks[i].sequence.id, i);
123
98
  }
124
- const sortedTracks = uniqueTracks.sort((a, b) => {
125
- const sortKeyA = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(a, tracks, sameHashes, nonceRanks);
126
- const sortKeyB = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(b, tracks, sameHashes, nonceRanks);
99
+ const sortedTracks = tracks
100
+ .sort((a, b) => {
101
+ const sortKeyA = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSortKey)(a, tracks, nonceRanks);
102
+ const sortKeyB = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSortKey)(b, tracks, nonceRanks);
127
103
  return sortKeyA.localeCompare(sortKeyB);
104
+ })
105
+ .map((track) => {
106
+ const { cascadedDuration, cascadedStart, ...cleanTrack } = track;
107
+ return cleanTrack;
128
108
  });
129
109
  const nodePathIndexCounters = new Map();
130
110
  return sortedTracks
@@ -8,6 +8,5 @@ type Context = {
8
8
  export declare const StudioServerConnectionCtx: React.Context<Context>;
9
9
  export declare const PreviewServerConnection: React.FC<{
10
10
  readonly children: React.ReactNode;
11
- readonly readOnlyStudio: boolean;
12
11
  }>;
13
12
  export {};
@@ -53,10 +53,14 @@ exports.StudioServerConnectionCtx = react_1.default.createContext({
53
53
  throw new Error('Context not initalized');
54
54
  },
55
55
  });
56
- const PreviewServerConnection = ({ children, readOnlyStudio }) => {
56
+ const PreviewServerConnection = ({ children }) => {
57
57
  const listeners = (0, react_1.useRef)([]);
58
+ const latestUndoRedoEvent = (0, react_1.useRef)(undefined);
58
59
  const subscribeToEvent = (0, react_1.useCallback)((type, listener) => {
59
60
  listeners.current.push({ type, listener });
61
+ if (type === 'undo-redo-stack-changed' && latestUndoRedoEvent.current) {
62
+ listener(latestUndoRedoEvent.current);
63
+ }
60
64
  return () => {
61
65
  listeners.current = listeners.current.filter((l) => l.type !== type || l.listener !== listener);
62
66
  };
@@ -65,9 +69,6 @@ const PreviewServerConnection = ({ children, readOnlyStudio }) => {
65
69
  type: 'init',
66
70
  });
67
71
  (0, react_1.useEffect)(() => {
68
- if (readOnlyStudio) {
69
- return;
70
- }
71
72
  const handleEvent = (newEvent) => {
72
73
  var _a, _b;
73
74
  if (newEvent.type === 'new-input-props' ||
@@ -76,16 +77,20 @@ const PreviewServerConnection = ({ children, readOnlyStudio }) => {
76
77
  (0, url_state_1.reloadUrl)();
77
78
  }
78
79
  if (newEvent.type === 'init') {
80
+ latestUndoRedoEvent.current = {
81
+ type: 'undo-redo-stack-changed',
82
+ undoFile: newEvent.undoFile,
83
+ redoFile: newEvent.redoFile,
84
+ };
79
85
  listeners.current.forEach((l) => {
80
86
  if (l.type === 'undo-redo-stack-changed') {
81
- l.listener({
82
- type: 'undo-redo-stack-changed',
83
- undoFile: newEvent.undoFile,
84
- redoFile: newEvent.redoFile,
85
- });
87
+ l.listener(latestUndoRedoEvent.current);
86
88
  }
87
89
  });
88
90
  }
91
+ if (newEvent.type === 'undo-redo-stack-changed') {
92
+ latestUndoRedoEvent.current = newEvent;
93
+ }
89
94
  if (newEvent.type === 'render-queue-updated') {
90
95
  (_a = context_1.renderJobsRef.current) === null || _a === void 0 ? void 0 : _a.updateRenderJobs(newEvent.queue);
91
96
  for (const job of newEvent.queue) {
@@ -122,7 +127,7 @@ const PreviewServerConnection = ({ children, readOnlyStudio }) => {
122
127
  unsubscribeFromEvents();
123
128
  unsubscribeFromConnectionState();
124
129
  };
125
- }, [readOnlyStudio]);
130
+ }, []);
126
131
  const context = (0, react_1.useMemo)(() => {
127
132
  return {
128
133
  previewServerState: state,
@@ -0,0 +1 @@
1
+ export declare const downloadBlob: (blob: Blob, filename: string) => void;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.downloadBlob = void 0;
4
+ const downloadBlob = (blob, filename) => {
5
+ const url = URL.createObjectURL(blob);
6
+ const a = document.createElement('a');
7
+ a.href = url;
8
+ const cleanFilename = filename.includes('/')
9
+ ? filename.substring(filename.lastIndexOf('/') + 1)
10
+ : filename;
11
+ a.download = cleanFilename;
12
+ a.click();
13
+ URL.revokeObjectURL(url);
14
+ };
15
+ exports.downloadBlob = downloadBlob;
@@ -6,7 +6,7 @@ export type SequenceNodePathInfo = {
6
6
  numberOfSequencesWithThisNodePath: number;
7
7
  supportsEffects: boolean;
8
8
  };
9
- type Track = {
9
+ export type TimelineTrackData = {
10
10
  sequence: TSequence;
11
11
  connectedCompositions?: readonly _InternalTypes['AnyComposition'][];
12
12
  depth: number;
@@ -14,15 +14,8 @@ type Track = {
14
14
  keyframeDisplayOffset: number;
15
15
  sequenceFrameOffset: number;
16
16
  };
17
- export type TrackWithHash = Track & {
18
- hash: string;
19
- };
20
- export type TrackWithHashAndOriginalTimings = TrackWithHash & {
21
- hash: string;
17
+ export type TimelineTrackWithOriginalTimings = TimelineTrackData & {
22
18
  cascadedStart: number;
23
19
  cascadedDuration: number;
24
20
  };
25
- export declare const getTimelineSequenceSequenceSortKey: (track: TrackWithHash, tracks: TrackWithHash[], sameHashes?: {
26
- [hash: string]: string[];
27
- }, nonceRanks?: Map<string, number>) => string;
28
- export {};
21
+ export declare const getTimelineSequenceSortKey: (track: TimelineTrackData, tracks: TimelineTrackData[], nonceRanks: Map<string, number>) => string;
@@ -1,11 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getTimelineSequenceSequenceSortKey = void 0;
4
- const getTimelineSequenceSequenceSortKey = (track, tracks, sameHashes = {}, nonceRanks = new Map()) => {
3
+ exports.getTimelineSequenceSortKey = void 0;
4
+ const getTimelineSequenceSortKey = (track, tracks, nonceRanks) => {
5
5
  var _a;
6
- const firstSequenceWithSameHash = tracks.find((t) => sameHashes[track.hash].includes(t.sequence.id));
7
- const sequenceId = firstSequenceWithSameHash.sequence.id;
8
- const rank = (_a = nonceRanks.get(sequenceId)) !== null && _a !== void 0 ? _a : 0;
6
+ const rank = (_a = nonceRanks.get(track.sequence.id)) !== null && _a !== void 0 ? _a : 0;
9
7
  const id = String(rank).padStart(6, '0');
10
8
  if (!track.sequence.parent) {
11
9
  return id;
@@ -16,12 +14,6 @@ const getTimelineSequenceSequenceSortKey = (track, tracks, sameHashes = {}, nonc
16
14
  // may not exist in the `allTracks` array.
17
15
  return id;
18
16
  }
19
- const firstParentWithSameHash = tracks.find((a) => {
20
- return sameHashes[parent.hash].includes(a.sequence.id);
21
- });
22
- if (!firstParentWithSameHash) {
23
- throw new Error('could not find parent: ' + track.sequence.parent);
24
- }
25
- return `${(0, exports.getTimelineSequenceSequenceSortKey)(firstParentWithSameHash, tracks, sameHashes, nonceRanks)}-${id}`;
17
+ return `${(0, exports.getTimelineSequenceSortKey)(parent, tracks, nonceRanks)}-${id}`;
26
18
  };
27
- exports.getTimelineSequenceSequenceSortKey = getTimelineSequenceSequenceSortKey;
19
+ exports.getTimelineSequenceSortKey = getTimelineSequenceSortKey;
@@ -83,20 +83,22 @@ const makeDefaultGlobalCSS = () => {
83
83
 
84
84
  input:focus,
85
85
  textarea:focus,
86
- button:focus:not(.__remotion_input_dragger):not(.__remotion_color_swatch),
86
+ button:focus:not(.__remotion_input_dragger):not(.__remotion_color_swatch):not(.__remotion-inspector-section-title),
87
87
  a:focus {
88
88
  outline: none;
89
89
  box-shadow: ${colors_1.FOCUS_BOX_SHADOW};
90
90
  }
91
91
 
92
92
  .__remotion-composition-selector-item:focus,
93
- .__remotion-inspector-inline-action:focus {
93
+ .__remotion-inspector-inline-action:focus,
94
+ .__remotion-inspector-section-title:focus {
94
95
  outline: none;
95
96
  box-shadow: none;
96
97
  }
97
98
 
98
99
  .__remotion-composition-selector-item:focus-visible,
99
- .__remotion-inspector-inline-action:focus-visible {
100
+ .__remotion-inspector-inline-action:focus-visible,
101
+ .__remotion-inspector-section-title:focus-visible {
100
102
  box-shadow: ${colors_1.FOCUS_BOX_SHADOW};
101
103
  }
102
104
 
@@ -1 +1,2 @@
1
1
  export declare const isStudioInteractivityEnabled: () => boolean;
2
+ export declare const isStudioSelectionEnabled: () => boolean;
@@ -1,5 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isStudioInteractivityEnabled = void 0;
3
+ exports.isStudioSelectionEnabled = exports.isStudioInteractivityEnabled = void 0;
4
4
  const studio_runtime_config_1 = require("./studio-runtime-config");
5
- exports.isStudioInteractivityEnabled = studio_runtime_config_1.getStudioInteractivityEnabled;
5
+ const isStudioInteractivityEnabled = () => {
6
+ return ((0, studio_runtime_config_1.getStudioInteractivityEnabled)() &&
7
+ (typeof window === 'undefined' || !window.remotion_isReadOnlyStudio));
8
+ };
9
+ exports.isStudioInteractivityEnabled = isStudioInteractivityEnabled;
10
+ exports.isStudioSelectionEnabled = studio_runtime_config_1.getStudioInteractivityEnabled;
@@ -0,0 +1 @@
1
+ export declare const isMac: boolean;
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isMac = void 0;
4
+ exports.isMac = typeof window !== 'undefined' && window.navigator.platform.startsWith('Mac');
@@ -1,7 +1,11 @@
1
1
  import type { CompositionComponentInfoResponse, SymbolicatedStackFrame } from '@remotion/studio-shared';
2
- import type { OriginalPosition } from '../error-overlay/react-overlay/utils/get-source-map';
2
+ import type { CodePosition, OriginalPosition } from '../error-overlay/react-overlay/utils/get-source-map';
3
3
  export declare const openInEditor: (stack: SymbolicatedStackFrame) => Promise<import("@remotion/studio-shared").OpenInEditorResponse>;
4
4
  export declare const openOriginalPositionInEditor: (originalPosition: OriginalPosition) => Promise<void>;
5
+ export declare const openOriginalPositionInEditorAtProperty: ({ originalPosition, property, }: {
6
+ originalPosition: CodePosition;
7
+ property: string;
8
+ }) => Promise<void>;
5
9
  type ResolvedCompositionComponentInfo = {
6
10
  location: CompositionComponentInfoResponse['location'];
7
11
  canAddSequence: boolean;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.openCompositionComponentInEditor = exports.preloadCompositionComponentInfo = exports.loadCompositionComponentInfo = exports.useCachedCompositionComponentInfo = exports.getCachedCompositionComponentInfo = exports.subscribeToCompositionComponentInfo = exports.openOriginalPositionInEditor = exports.openInEditor = void 0;
3
+ exports.openCompositionComponentInEditor = exports.preloadCompositionComponentInfo = exports.loadCompositionComponentInfo = exports.useCachedCompositionComponentInfo = exports.getCachedCompositionComponentInfo = exports.subscribeToCompositionComponentInfo = exports.openOriginalPositionInEditorAtProperty = exports.openOriginalPositionInEditor = exports.openInEditor = void 0;
4
4
  const react_1 = require("react");
5
5
  const call_api_1 = require("../components/call-api");
6
+ const browser_studio_operations_1 = require("./browser-studio-operations");
6
7
  const openInEditor = (stack) => {
7
8
  const { originalFileName, originalLineNumber, originalColumnNumber, originalFunctionName, originalScriptCode, } = stack;
8
9
  return (0, call_api_1.callApi)('/api/open-in-editor', {
@@ -26,6 +27,24 @@ const openOriginalPositionInEditor = async (originalPosition) => {
26
27
  });
27
28
  };
28
29
  exports.openOriginalPositionInEditor = openOriginalPositionInEditor;
30
+ const openOriginalPositionInEditorAtProperty = async ({ originalPosition, property, }) => {
31
+ const request = {
32
+ fileName: originalPosition.source,
33
+ lineNumber: originalPosition.line,
34
+ columnNumber: originalPosition.column,
35
+ search: property,
36
+ };
37
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
38
+ const position = browserStudioOperations
39
+ ? await browserStudioOperations.findInFile(request)
40
+ : await (0, call_api_1.callApi)('/api/find-in-file', request);
41
+ await (0, exports.openOriginalPositionInEditor)({
42
+ source: originalPosition.source,
43
+ line: position.lineNumber,
44
+ column: position.columnNumber,
45
+ });
46
+ };
47
+ exports.openOriginalPositionInEditorAtProperty = openOriginalPositionInEditorAtProperty;
29
48
  const componentResolutionCache = new Map();
30
49
  const componentResolutionResults = new Map();
31
50
  const componentResolutionListeners = new Set();
@@ -50,7 +69,7 @@ const getCachedCompositionComponentInfo = ({ compositionFile, compositionId, })
50
69
  };
51
70
  exports.getCachedCompositionComponentInfo = getCachedCompositionComponentInfo;
52
71
  const useCachedCompositionComponentInfo = ({ compositionFile, compositionId, }) => {
53
- return (0, react_1.useSyncExternalStore)(exports.subscribeToCompositionComponentInfo, () => {
72
+ const result = (0, react_1.useSyncExternalStore)(exports.subscribeToCompositionComponentInfo, () => {
54
73
  if (compositionFile === null || compositionId === null) {
55
74
  return null;
56
75
  }
@@ -59,6 +78,18 @@ const useCachedCompositionComponentInfo = ({ compositionFile, compositionId, })
59
78
  compositionId,
60
79
  });
61
80
  }, () => null);
81
+ (0, react_1.useEffect)(() => {
82
+ if (!(0, browser_studio_operations_1.getBrowserStudioOperations)() ||
83
+ compositionFile === null ||
84
+ compositionId === null) {
85
+ return;
86
+ }
87
+ (0, exports.preloadCompositionComponentInfo)({
88
+ compositionFile,
89
+ compositionId,
90
+ });
91
+ }, [compositionFile, compositionId]);
92
+ return result;
62
93
  };
63
94
  exports.useCachedCompositionComponentInfo = useCachedCompositionComponentInfo;
64
95
  const loadCompositionComponentInfo = async ({ compositionFile, compositionId, }) => {
@@ -71,10 +102,14 @@ const loadCompositionComponentInfo = async ({ compositionFile, compositionId, })
71
102
  return existing;
72
103
  }
73
104
  const promise = (async () => {
74
- const body = await (0, call_api_1.callApi)('/api/composition-component-info', {
105
+ const request = {
75
106
  compositionFile,
76
107
  compositionId,
77
- });
108
+ };
109
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
110
+ const body = browserStudioOperations
111
+ ? await browserStudioOperations.getCompositionComponentInfo(request)
112
+ : await (0, call_api_1.callApi)('/api/composition-component-info', request);
78
113
  const result = {
79
114
  location: body.location,
80
115
  canAddSequence: body.canAddSequence,
@@ -3,9 +3,13 @@
3
3
  /// <reference lib="dom.iterable" />
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
5
  exports.subscribeToPreviewServerConnectionState = exports.subscribeToPreviewServerEvents = exports.ensurePreviewServerEventSource = void 0;
6
+ const browser_studio_operations_1 = require("./browser-studio-operations");
6
7
  let source = null;
8
+ let unsubscribeFromBrowserStudio = null;
9
+ let browserStudioReadyListenerInstalled = false;
7
10
  let connectionState = { type: 'init' };
8
11
  let lastInitEvent = null;
12
+ let pendingHmrEvent = null;
9
13
  const messageListeners = new Set();
10
14
  const connectionStateListeners = new Set();
11
15
  const notifyConnectionState = () => {
@@ -14,10 +18,37 @@ const notifyConnectionState = () => {
14
18
  }
15
19
  };
16
20
  const dispatch = (event) => {
21
+ if (event.type === 'init') {
22
+ lastInitEvent = event;
23
+ connectionState = {
24
+ type: 'connected',
25
+ clientId: event.clientId,
26
+ };
27
+ notifyConnectionState();
28
+ }
29
+ if (event.type === 'hmr' && messageListeners.size === 0) {
30
+ pendingHmrEvent = event;
31
+ }
17
32
  for (const listener of messageListeners) {
18
33
  listener(event);
19
34
  }
20
35
  };
36
+ const connectToBrowserStudio = () => {
37
+ if (unsubscribeFromBrowserStudio) {
38
+ return true;
39
+ }
40
+ const browserStudioOperations = (0, browser_studio_operations_1.getBrowserStudioOperations)();
41
+ if (!browserStudioOperations) {
42
+ return false;
43
+ }
44
+ if (source) {
45
+ source.close();
46
+ source = null;
47
+ }
48
+ unsubscribeFromBrowserStudio =
49
+ browserStudioOperations.subscribeToEvent(dispatch);
50
+ return true;
51
+ };
21
52
  const openEventSource = () => {
22
53
  if (source) {
23
54
  return;
@@ -26,14 +57,6 @@ const openEventSource = () => {
26
57
  source.addEventListener('message', (event) => {
27
58
  try {
28
59
  const newEvent = JSON.parse(event.data);
29
- if (newEvent.type === 'init') {
30
- lastInitEvent = newEvent;
31
- connectionState = {
32
- type: 'connected',
33
- clientId: newEvent.clientId,
34
- };
35
- notifyConnectionState();
36
- }
37
60
  dispatch(newEvent);
38
61
  }
39
62
  catch (_a) {
@@ -53,7 +76,17 @@ const openEventSource = () => {
53
76
  });
54
77
  };
55
78
  const ensurePreviewServerEventSource = () => {
56
- if (typeof window === 'undefined' || typeof EventSource === 'undefined') {
79
+ if (typeof window === 'undefined') {
80
+ return;
81
+ }
82
+ if (!browserStudioReadyListenerInstalled) {
83
+ browserStudioReadyListenerInstalled = true;
84
+ window.addEventListener(browser_studio_operations_1.BROWSER_STUDIO_OPERATIONS_READY_EVENT, connectToBrowserStudio);
85
+ }
86
+ if (connectToBrowserStudio()) {
87
+ return;
88
+ }
89
+ if (typeof EventSource === 'undefined') {
57
90
  return;
58
91
  }
59
92
  openEventSource();
@@ -65,6 +98,10 @@ const subscribeToPreviewServerEvents = (listener) => {
65
98
  if (lastInitEvent && connectionState.type === 'connected') {
66
99
  listener(lastInitEvent);
67
100
  }
101
+ if (pendingHmrEvent) {
102
+ listener(pendingHmrEvent);
103
+ pendingHmrEvent = null;
104
+ }
68
105
  return () => {
69
106
  messageListeners.delete(listener);
70
107
  };
@@ -25,45 +25,123 @@ const compareNonceHistories = (a, b) => {
25
25
  return aLatestEpoch - bLatestEpoch;
26
26
  };
27
27
  exports.compareNonceHistories = compareNonceHistories;
28
+ // Compare two histories, each pre-collapsed to parallel arrays of epochs and
29
+ // nonces sorted by descending epoch, without rebuilding a Map per comparison.
30
+ // Equivalent to getSharedEpochOrder: both find the newest shared epoch and
31
+ // compare its nonces.
32
+ const sharedEpochOrderFromSorted = (aEpochs, aNonces, bEpochs, bNonces) => {
33
+ let i = 0;
34
+ let j = 0;
35
+ while (i < aEpochs.length && j < bEpochs.length) {
36
+ const ae = aEpochs[i];
37
+ const be = bEpochs[j];
38
+ if (ae === be) {
39
+ return aNonces[i] - bNonces[j];
40
+ }
41
+ if (ae > be) {
42
+ i++;
43
+ }
44
+ else {
45
+ j++;
46
+ }
47
+ }
48
+ return null;
49
+ };
28
50
  const sortItemsByNonceHistory = (items) => {
29
51
  const n = items.length;
30
52
  if (n <= 1) {
31
53
  return items.slice();
32
54
  }
33
- // Build a pairwise ordering matrix from shared epochs.
34
- // order[i][j] < 0 means i before j, > 0 means j before i, null means no direct relationship.
35
- const order = Array.from({ length: n }, () => Array(n).fill(null));
55
+ // Collapse each history once into epoch/nonce arrays sorted by descending
56
+ // epoch. `new Map(nonce)` keeps the last value per duplicated epoch, matching
57
+ // getSharedEpochOrder. This removes the per-pair Map/Set construction the
58
+ // pairwise loop below would otherwise repeat O(n^2) times.
59
+ const epochsOf = new Array(n);
60
+ const noncesOf = new Array(n);
61
+ for (let i = 0; i < n; i++) {
62
+ const map = new Map(items[i].nonce);
63
+ const epochs = [...map.keys()].sort((x, y) => y - x);
64
+ epochsOf[i] = epochs;
65
+ noncesOf[i] = epochs.map((e) => map.get(e));
66
+ }
67
+ // Pairwise "strictly before" relation, stored as bitsets: `before[i]` has
68
+ // bit j set when i must come before j, `known[i]` has bit j set when the
69
+ // pair (i, j) is directly determined by a shared epoch. Bitsets let the
70
+ // transitive closure below combine 32 relationships per word.
71
+ const words = (n + 31) >> 5;
72
+ const before = new Uint32Array(n * words);
73
+ const known = new Uint32Array(n * words);
74
+ // Direct comparison sign per ordered pair; only read where `known` is set.
75
+ const sign = new Int8Array(n * n);
36
76
  for (let i = 0; i < n; i++) {
37
77
  for (let j = i + 1; j < n; j++) {
38
- const cmp = getSharedEpochOrder(items[i].nonce, items[j].nonce);
39
- order[i][j] = cmp;
40
- order[j][i] = cmp !== null ? -cmp : null;
78
+ const cmp = sharedEpochOrderFromSorted(epochsOf[i], noncesOf[i], epochsOf[j], noncesOf[j]);
79
+ if (cmp === null) {
80
+ continue;
81
+ }
82
+ known[i * words + (j >> 5)] |= 1 << (j & 31);
83
+ known[j * words + (i >> 5)] |= 1 << (i & 31);
84
+ sign[i * n + j] = cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
85
+ sign[j * n + i] = cmp < 0 ? 1 : cmp > 0 ? -1 : 0;
86
+ if (cmp < 0) {
87
+ before[i * words + (j >> 5)] |= 1 << (j & 31);
88
+ }
89
+ else if (cmp > 0) {
90
+ before[j * words + (i >> 5)] |= 1 << (i & 31);
91
+ }
41
92
  }
42
93
  }
43
- // Compute transitive closure: if i < j and j < k, then i < k.
94
+ // Transitive closure: if i < k and k < j, then i < j. This is the same
95
+ // Floyd-Warshall relation as before, but the inner sweep is bitwise
96
+ // (`before[k] & ~known[i]` finds all reachable j at once). A newly derived
97
+ // edge is marked known immediately so the first path decides an otherwise
98
+ // undetermined pair — preserving behavior on the inputs where the pairwise
99
+ // comparison is intentionally non-transitive.
44
100
  for (let k = 0; k < n; k++) {
101
+ const kBase = k * words;
102
+ const kWord = k >> 5;
103
+ const kBit = 1 << (k & 31);
45
104
  for (let i = 0; i < n; i++) {
46
- for (let j = 0; j < n; j++) {
47
- if (order[i][j] === null &&
48
- order[i][k] !== null &&
49
- order[k][j] !== null &&
50
- order[i][k] < 0 &&
51
- order[k][j] < 0) {
52
- order[i][j] = -1;
53
- order[j][i] = 1;
105
+ if (i === k) {
106
+ continue;
107
+ }
108
+ const iBase = i * words;
109
+ if ((before[iBase + kWord] & kBit) === 0) {
110
+ continue; // i is not before k, so k adds nothing for i
111
+ }
112
+ for (let w = 0; w < words; w++) {
113
+ const add = before[kBase + w] & ~known[iBase + w];
114
+ if (add === 0) {
115
+ continue;
116
+ }
117
+ before[iBase + w] |= add;
118
+ known[iBase + w] |= add;
119
+ // Set the mirror relationship (j after i) for each newly known pair.
120
+ let bits = add;
121
+ while (bits !== 0) {
122
+ const lowest = bits & -bits;
123
+ const j = (w << 5) + (31 - Math.clz32(lowest));
124
+ sign[i * n + j] = -1;
125
+ known[j * words + (i >> 5)] |= 1 << (i & 31);
126
+ sign[j * n + i] = 1;
127
+ bits ^= lowest;
54
128
  }
55
129
  }
56
130
  }
57
131
  }
58
- // Sort using transitive order, falling back to lower latest epoch first.
59
132
  const indexMap = new Map(items.map((item, i) => [item, i]));
60
133
  const result = items.slice();
61
134
  result.sort((a, b) => {
62
135
  const ai = indexMap.get(a);
63
136
  const bi = indexMap.get(b);
64
- const transitiveOrder = order[ai][bi];
65
- if (transitiveOrder !== null) {
66
- return transitiveOrder;
137
+ if ((known[ai * words + (bi >> 5)] >> (bi & 31)) & 1) {
138
+ return sign[ai * n + bi];
139
+ }
140
+ if ((before[ai * words + (bi >> 5)] >> (bi & 31)) & 1) {
141
+ return -1;
142
+ }
143
+ if ((before[bi * words + (ai >> 5)] >> (ai & 31)) & 1) {
144
+ return 1;
67
145
  }
68
146
  // No transitive relationship — lower latest epoch first
69
147
  return a.nonce[a.nonce.length - 1][0] - b.nonce[b.nonce.length - 1][0];