@remotion/studio 4.0.432 → 4.0.433

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 (53) hide show
  1. package/dist/Studio.js +1 -3
  2. package/dist/components/CompositionSelector.js +16 -9
  3. package/dist/components/CurrentComposition.js +2 -5
  4. package/dist/components/EditorContent.js +4 -5
  5. package/dist/components/NewComposition/DuplicateComposition.js +4 -1
  6. package/dist/components/NewComposition/InputDragger.d.ts +1 -0
  7. package/dist/components/NewComposition/InputDragger.js +27 -8
  8. package/dist/components/OptionsPanel.js +1 -1
  9. package/dist/components/PlaybackRatePersistor.js +1 -1
  10. package/dist/components/PreviewToolbar.js +4 -2
  11. package/dist/components/RenderModal/SchemaEditor/SchemaLabel.js +3 -1
  12. package/dist/components/RenderModal/SchemaEditor/ZodArrayEditor.js +3 -1
  13. package/dist/components/RenderModal/SchemaEditor/ZodFieldValidation.js +3 -1
  14. package/dist/components/RenderModal/SchemaEditor/ZodTupleEditor.js +3 -1
  15. package/dist/components/RenderModal/WebRenderModalAudio.js +2 -0
  16. package/dist/components/RenderModal/WebRenderModalBasic.js +8 -1
  17. package/dist/components/RendersTab.js +1 -9
  18. package/dist/components/Timeline/TimelineBooleanField.d.ts +9 -0
  19. package/dist/components/Timeline/TimelineBooleanField.js +20 -0
  20. package/dist/components/Timeline/TimelineEmptyState.d.ts +2 -0
  21. package/dist/components/Timeline/TimelineEmptyState.js +15 -0
  22. package/dist/components/Timeline/TimelineExpandedSection.d.ts +5 -0
  23. package/dist/components/Timeline/TimelineExpandedSection.js +45 -7
  24. package/dist/components/Timeline/TimelineFieldRow.d.ts +3 -0
  25. package/dist/components/Timeline/TimelineFieldRow.js +17 -12
  26. package/dist/components/Timeline/TimelineListItem.d.ts +1 -0
  27. package/dist/components/Timeline/TimelineListItem.js +7 -7
  28. package/dist/components/Timeline/TimelineNumberField.d.ts +11 -0
  29. package/dist/components/Timeline/TimelineNumberField.js +53 -0
  30. package/dist/components/Timeline/TimelinePlayCursorSyncer.js +1 -1
  31. package/dist/components/Timeline/TimelineRotationField.d.ts +11 -0
  32. package/dist/components/Timeline/TimelineRotationField.js +64 -0
  33. package/dist/components/Timeline/TimelineSchemaField.d.ts +1 -3
  34. package/dist/components/Timeline/TimelineSchemaField.js +19 -74
  35. package/dist/components/Timeline/TimelineTranslateField.d.ts +11 -0
  36. package/dist/components/Timeline/TimelineTranslateField.js +115 -0
  37. package/dist/components/Timeline/timeline-field-utils.d.ts +2 -0
  38. package/dist/components/Timeline/timeline-field-utils.js +12 -0
  39. package/dist/components/Timeline/use-sequence-props-subscription.d.ts +2 -1
  40. package/dist/components/Timeline/use-sequence-props-subscription.js +32 -12
  41. package/dist/esm/{chunk-t28xqw5n.js → chunk-bd1bkakk.js} +2697 -2266
  42. package/dist/esm/internals.mjs +2697 -2266
  43. package/dist/esm/previewEntry.mjs +2702 -2271
  44. package/dist/esm/renderEntry.mjs +1 -3
  45. package/dist/helpers/calculate-timeline.js +17 -11
  46. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +1 -1
  47. package/dist/helpers/get-timeline-sequence-sort-key.js +6 -3
  48. package/dist/helpers/inject-css.js +6 -1
  49. package/dist/helpers/sort-by-nonce-history.d.ts +5 -0
  50. package/dist/helpers/sort-by-nonce-history.js +73 -0
  51. package/dist/helpers/timeline-layout.js +8 -2
  52. package/dist/renderEntry.js +2 -2
  53. package/package.json +11 -11
@@ -164,7 +164,6 @@ var renderContent = (Root) => {
164
164
  videoEnabled: window.remotion_videoEnabled,
165
165
  logLevel: window.remotion_logLevel,
166
166
  numberOfAudioTags: 0,
167
- nonceContextSeed: 0,
168
167
  audioLatencyHint: window.remotion_audioLatencyHint ?? "interactive",
169
168
  visualModeEnabled: false,
170
169
  children: /* @__PURE__ */ jsxs(Internals.RenderAssetManagerProvider, {
@@ -193,7 +192,6 @@ var renderContent = (Root) => {
193
192
  logLevel: window.remotion_logLevel,
194
193
  numberOfAudioTags: 0,
195
194
  audioLatencyHint: window.remotion_audioLatencyHint ?? "interactive",
196
- nonceContextSeed: 0,
197
195
  visualModeEnabled: false,
198
196
  children: /* @__PURE__ */ jsx(Internals.RenderAssetManagerProvider, {
199
197
  collectAssets: null,
@@ -210,7 +208,7 @@ var renderContent = (Root) => {
210
208
  renderToDOM(/* @__PURE__ */ jsx("div", {
211
209
  children: /* @__PURE__ */ jsx(DelayedSpinner, {})
212
210
  }));
213
- import("./chunk-t28xqw5n.js").then(({ StudioInternals }) => {
211
+ import("./chunk-bd1bkakk.js").then(({ StudioInternals }) => {
214
212
  window.remotion_isStudio = true;
215
213
  window.remotion_isReadOnlyStudio = true;
216
214
  window.remotion_inputProps = "{}";
@@ -5,9 +5,11 @@ const get_sequence_visible_range_1 = require("./get-sequence-visible-range");
5
5
  const get_timeline_nestedness_1 = require("./get-timeline-nestedness");
6
6
  const get_timeline_sequence_hash_1 = require("./get-timeline-sequence-hash");
7
7
  const get_timeline_sequence_sort_key_1 = require("./get-timeline-sequence-sort-key");
8
+ const sort_by_nonce_history_1 = require("./sort-by-nonce-history");
8
9
  const calculateTimeline = ({ sequences, sequenceDuration, }) => {
10
+ const sortedSequences = (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(sequences);
9
11
  const tracks = [];
10
- if (sequences.length === 0) {
12
+ if (sortedSequences.length === 0) {
11
13
  return [
12
14
  {
13
15
  sequence: {
@@ -19,7 +21,7 @@ const calculateTimeline = ({ sequences, sequenceDuration, }) => {
19
21
  type: 'sequence',
20
22
  rootId: '-',
21
23
  showInTimeline: true,
22
- nonce: 0,
24
+ nonce: [[0, 0]],
23
25
  loopDisplay: undefined,
24
26
  stack: null,
25
27
  premountDisplay: null,
@@ -34,26 +36,26 @@ const calculateTimeline = ({ sequences, sequenceDuration, }) => {
34
36
  const sameHashes = {};
35
37
  const hashesUsedInRoot = {};
36
38
  const cache = {};
37
- for (let i = 0; i < sequences.length; i++) {
38
- const sequence = sequences[i];
39
+ for (let i = 0; i < sortedSequences.length; i++) {
40
+ const sequence = sortedSequences[i];
39
41
  if (!hashesUsedInRoot[sequence.rootId]) {
40
42
  hashesUsedInRoot[sequence.rootId] = [];
41
43
  }
42
- const actualHash = (0, get_timeline_sequence_hash_1.getTimelineSequenceHash)(sequence, sequences, hashesUsedInRoot, cache);
44
+ const actualHash = (0, get_timeline_sequence_hash_1.getTimelineSequenceHash)(sequence, sortedSequences, hashesUsedInRoot, cache);
43
45
  if (!sameHashes[actualHash]) {
44
46
  sameHashes[actualHash] = [];
45
47
  }
46
48
  sameHashes[actualHash].push(sequence.id);
47
- const cascadedStart = (0, get_sequence_visible_range_1.getCascadedStart)(sequence, sequences);
48
- const visibleStart = (0, get_sequence_visible_range_1.getTimelineVisibleStart)(sequence, sequences);
49
- const visibleDuration = (0, get_sequence_visible_range_1.getTimelineVisibleDuration)(sequence, sequences);
49
+ const cascadedStart = (0, get_sequence_visible_range_1.getCascadedStart)(sequence, sortedSequences);
50
+ const visibleStart = (0, get_sequence_visible_range_1.getTimelineVisibleStart)(sequence, sortedSequences);
51
+ const visibleDuration = (0, get_sequence_visible_range_1.getTimelineVisibleDuration)(sequence, sortedSequences);
50
52
  tracks.push({
51
53
  sequence: {
52
54
  ...sequence,
53
55
  from: visibleStart,
54
56
  duration: visibleDuration,
55
57
  },
56
- depth: (0, get_timeline_nestedness_1.getTimelineNestedLevel)(sequence, sequences, 0),
58
+ depth: (0, get_timeline_nestedness_1.getTimelineNestedLevel)(sequence, sortedSequences, 0),
57
59
  hash: actualHash,
58
60
  cascadedStart,
59
61
  cascadedDuration: sequence.duration,
@@ -66,9 +68,13 @@ const calculateTimeline = ({ sequences, sequenceDuration, }) => {
66
68
  uniqueTracks.push(cleanTrack);
67
69
  }
68
70
  }
71
+ const nonceRanks = new Map();
72
+ for (let i = 0; i < tracks.length; i++) {
73
+ nonceRanks.set(tracks[i].sequence.id, i);
74
+ }
69
75
  return uniqueTracks.sort((a, b) => {
70
- const sortKeyA = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(a, tracks, sameHashes);
71
- const sortKeyB = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(b, tracks, sameHashes);
76
+ const sortKeyA = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(a, tracks, sameHashes, nonceRanks);
77
+ const sortKeyB = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(b, tracks, sameHashes, nonceRanks);
72
78
  return sortKeyA.localeCompare(sortKeyB);
73
79
  });
74
80
  };
@@ -13,5 +13,5 @@ export type TrackWithHashAndOriginalTimings = TrackWithHash & {
13
13
  };
14
14
  export declare const getTimelineSequenceSequenceSortKey: (track: TrackWithHash, tracks: TrackWithHash[], sameHashes?: {
15
15
  [hash: string]: string[];
16
- }) => string;
16
+ }, nonceRanks?: Map<string, number>) => string;
17
17
  export {};
@@ -1,9 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTimelineSequenceSequenceSortKey = void 0;
4
- const getTimelineSequenceSequenceSortKey = (track, tracks, sameHashes = {}) => {
4
+ const getTimelineSequenceSequenceSortKey = (track, tracks, sameHashes = {}, nonceRanks = new Map()) => {
5
+ var _a;
5
6
  const firstSequenceWithSameHash = tracks.find((t) => sameHashes[track.hash].includes(t.sequence.id));
6
- const id = String(firstSequenceWithSameHash.sequence.nonce).padStart(6, '0');
7
+ const sequenceId = firstSequenceWithSameHash.sequence.id;
8
+ const rank = (_a = nonceRanks.get(sequenceId)) !== null && _a !== void 0 ? _a : 0;
9
+ const id = String(rank).padStart(6, '0');
7
10
  if (!track.sequence.parent) {
8
11
  return id;
9
12
  }
@@ -19,6 +22,6 @@ const getTimelineSequenceSequenceSortKey = (track, tracks, sameHashes = {}) => {
19
22
  if (!firstParentWithSameHash) {
20
23
  throw new Error('could not find parent: ' + track.sequence.parent);
21
24
  }
22
- return `${(0, exports.getTimelineSequenceSequenceSortKey)(firstParentWithSameHash, tracks, sameHashes)}-${id}`;
25
+ return `${(0, exports.getTimelineSequenceSequenceSortKey)(firstParentWithSameHash, tracks, sameHashes, nonceRanks)}-${id}`;
23
26
  };
24
27
  exports.getTimelineSequenceSequenceSortKey = getTimelineSequenceSequenceSortKey;
@@ -11,6 +11,7 @@ const makeDefaultGlobalCSS = () => {
11
11
  return `
12
12
  html {
13
13
  --remotion-cli-internals-blue: #0b84f3;
14
+ --remotion-cli-internals-blue-hovered: #4da3f7;
14
15
  overscroll-behavior-y: none;
15
16
  overscroll-behavior-x: none;
16
17
  }
@@ -83,7 +84,7 @@ const makeDefaultGlobalCSS = () => {
83
84
 
84
85
  input:focus,
85
86
  textarea:focus,
86
- button:focus,
87
+ button:focus:not(.__remotion_input_dragger),
87
88
  a:focus {
88
89
  outline: none;
89
90
  box-shadow:
@@ -143,6 +144,10 @@ const makeDefaultGlobalCSS = () => {
143
144
  position: relative;
144
145
  }
145
146
 
147
+ .__remotion_input_dragger:hover span {
148
+ color: var(--remotion-cli-internals-blue-hovered) !important;
149
+ }
150
+
146
151
  .${scroll_to_default_props_path_1.DEFAULT_PROPS_PATH_ACTIVE_CLASSNAME} span {
147
152
  color: var(--remotion-cli-internals-blue) !important;
148
153
  transition: color 0.2s ease-in-out;
@@ -0,0 +1,5 @@
1
+ import type { NonceHistory } from 'remotion';
2
+ export declare const compareNonceHistories: (a: NonceHistory, b: NonceHistory) => number;
3
+ export declare const sortItemsByNonceHistory: <T extends {
4
+ nonce: NonceHistory;
5
+ }>(items: T[]) => T[];
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sortItemsByNonceHistory = exports.compareNonceHistories = void 0;
4
+ const getSharedEpochOrder = (a, b) => {
5
+ const aMap = new Map(a);
6
+ const bMap = new Map(b);
7
+ const allEpochs = [...new Set([...aMap.keys(), ...bMap.keys()])].sort((x, y) => y - x);
8
+ for (const epoch of allEpochs) {
9
+ const aNonce = aMap.get(epoch);
10
+ const bNonce = bMap.get(epoch);
11
+ if (aNonce !== undefined && bNonce !== undefined) {
12
+ return aNonce - bNonce;
13
+ }
14
+ }
15
+ return null;
16
+ };
17
+ const compareNonceHistories = (a, b) => {
18
+ const shared = getSharedEpochOrder(a, b);
19
+ if (shared !== null) {
20
+ return shared;
21
+ }
22
+ // No shared epoch — items from a lower latest epoch come first
23
+ const aLatestEpoch = a[a.length - 1][0];
24
+ const bLatestEpoch = b[b.length - 1][0];
25
+ return aLatestEpoch - bLatestEpoch;
26
+ };
27
+ exports.compareNonceHistories = compareNonceHistories;
28
+ const sortItemsByNonceHistory = (items) => {
29
+ const n = items.length;
30
+ if (n <= 1) {
31
+ return items.slice();
32
+ }
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));
36
+ for (let i = 0; i < n; i++) {
37
+ 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;
41
+ }
42
+ }
43
+ // Compute transitive closure: if i < j and j < k, then i < k.
44
+ for (let k = 0; k < n; k++) {
45
+ 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;
54
+ }
55
+ }
56
+ }
57
+ }
58
+ // Sort using transitive order, falling back to lower latest epoch first.
59
+ const indexMap = new Map(items.map((item, i) => [item, i]));
60
+ const result = items.slice();
61
+ result.sort((a, b) => {
62
+ const ai = indexMap.get(a);
63
+ const bi = indexMap.get(b);
64
+ const transitiveOrder = order[ai][bi];
65
+ if (transitiveOrder !== null) {
66
+ return transitiveOrder;
67
+ }
68
+ // No transitive relationship — lower latest epoch first
69
+ return a.nonce[a.nonce.length - 1][0] - b.nonce[b.nonce.length - 1][0];
70
+ });
71
+ return result;
72
+ };
73
+ exports.sortItemsByNonceHistory = sortItemsByNonceHistory;
@@ -7,7 +7,12 @@ exports.TIMELINE_ITEM_BORDER_BOTTOM = 1;
7
7
  exports.TIMELINE_TRACK_EXPANDED_HEIGHT = 100;
8
8
  exports.SCHEMA_FIELD_ROW_HEIGHT = 22;
9
9
  exports.UNSUPPORTED_FIELD_ROW_HEIGHT = 22;
10
- const SUPPORTED_SCHEMA_TYPES = new Set(['number', 'boolean']);
10
+ const SUPPORTED_SCHEMA_TYPES = new Set([
11
+ 'number',
12
+ 'boolean',
13
+ 'rotation',
14
+ 'translate',
15
+ ]);
11
16
  const getSchemaFields = (controls) => {
12
17
  if (!controls) {
13
18
  return null;
@@ -34,7 +39,8 @@ const getExpandedTrackHeight = (controls) => {
34
39
  if (!fields || fields.length === 0) {
35
40
  return exports.TIMELINE_TRACK_EXPANDED_HEIGHT;
36
41
  }
37
- return fields.reduce((sum, f) => sum + f.rowHeight, 0);
42
+ const separators = Math.max(0, fields.length - 1);
43
+ return fields.reduce((sum, f) => sum + f.rowHeight, 0) + separators;
38
44
  };
39
45
  exports.getExpandedTrackHeight = getExpandedTrackHeight;
40
46
  const getTimelineLayerHeight = (type) => {
@@ -185,13 +185,13 @@ const renderContent = (Root) => {
185
185
  defaultVideoImageFormat: bundleMode.compositionDefaultVideoImageFormat,
186
186
  defaultPixelFormat: bundleMode.compositionDefaultPixelFormat,
187
187
  defaultProResProfile: bundleMode.compositionDefaultProResProfile,
188
- }, initialCompositions: [], children: jsx_runtime_1.jsx(remotion_1.Internals.RemotionRootContexts, { frameState: null, audioEnabled: window.remotion_audioEnabled, videoEnabled: window.remotion_videoEnabled, logLevel: window.remotion_logLevel, numberOfAudioTags: 0, nonceContextSeed: 0, audioLatencyHint: (_a = window.remotion_audioLatencyHint) !== null && _a !== void 0 ? _a : 'interactive', visualModeEnabled: false, children: jsx_runtime_1.jsxs(remotion_1.Internals.RenderAssetManagerProvider, { collectAssets: null, children: [
188
+ }, initialCompositions: [], children: jsx_runtime_1.jsx(remotion_1.Internals.RemotionRootContexts, { frameState: null, audioEnabled: window.remotion_audioEnabled, videoEnabled: window.remotion_videoEnabled, logLevel: window.remotion_logLevel, numberOfAudioTags: 0, audioLatencyHint: (_a = window.remotion_audioLatencyHint) !== null && _a !== void 0 ? _a : 'interactive', visualModeEnabled: false, children: jsx_runtime_1.jsxs(remotion_1.Internals.RenderAssetManagerProvider, { collectAssets: null, children: [
189
189
  jsx_runtime_1.jsx(Root, {}), jsx_runtime_1.jsx(GetVideoComposition, { state: bundleMode })
190
190
  ] }) }) }));
191
191
  renderToDOM(markup);
192
192
  }
193
193
  if (bundleMode.type === 'evaluation') {
194
- const markup = (jsx_runtime_1.jsx(remotion_1.Internals.CompositionManagerProvider, { initialCanvasContent: null, onlyRenderComposition: null, currentCompositionMetadata: null, initialCompositions: [], children: jsx_runtime_1.jsx(remotion_1.Internals.RemotionRootContexts, { frameState: null, audioEnabled: window.remotion_audioEnabled, videoEnabled: window.remotion_videoEnabled, logLevel: window.remotion_logLevel, numberOfAudioTags: 0, audioLatencyHint: (_b = window.remotion_audioLatencyHint) !== null && _b !== void 0 ? _b : 'interactive', nonceContextSeed: 0, visualModeEnabled: false, children: jsx_runtime_1.jsx(remotion_1.Internals.RenderAssetManagerProvider, { collectAssets: null, children: jsx_runtime_1.jsx(Root, {}) }) }) }));
194
+ const markup = (jsx_runtime_1.jsx(remotion_1.Internals.CompositionManagerProvider, { initialCanvasContent: null, onlyRenderComposition: null, currentCompositionMetadata: null, initialCompositions: [], children: jsx_runtime_1.jsx(remotion_1.Internals.RemotionRootContexts, { frameState: null, audioEnabled: window.remotion_audioEnabled, videoEnabled: window.remotion_videoEnabled, logLevel: window.remotion_logLevel, numberOfAudioTags: 0, audioLatencyHint: (_b = window.remotion_audioLatencyHint) !== null && _b !== void 0 ? _b : 'interactive', visualModeEnabled: false, children: jsx_runtime_1.jsx(remotion_1.Internals.RenderAssetManagerProvider, { collectAssets: null, children: jsx_runtime_1.jsx(Root, {}) }) }) }));
195
195
  renderToDOM(markup);
196
196
  }
197
197
  if (bundleMode.type === 'index') {
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "url": "https://github.com/remotion-dev/remotion/tree/main/packages/studio"
4
4
  },
5
5
  "name": "@remotion/studio",
6
- "version": "4.0.432",
6
+ "version": "4.0.433",
7
7
  "description": "APIs for interacting with the Remotion Studio",
8
8
  "main": "dist",
9
9
  "sideEffects": false,
@@ -26,14 +26,14 @@
26
26
  },
27
27
  "dependencies": {
28
28
  "semver": "7.5.3",
29
- "remotion": "4.0.432",
30
- "@remotion/player": "4.0.432",
31
- "@remotion/media-utils": "4.0.432",
32
- "@remotion/renderer": "4.0.432",
33
- "@remotion/web-renderer": "4.0.432",
34
- "@remotion/studio-shared": "4.0.432",
35
- "@remotion/zod-types": "4.0.432",
36
- "mediabunny": "1.35.1",
29
+ "remotion": "4.0.433",
30
+ "@remotion/player": "4.0.433",
31
+ "@remotion/media-utils": "4.0.433",
32
+ "@remotion/renderer": "4.0.433",
33
+ "@remotion/web-renderer": "4.0.433",
34
+ "@remotion/studio-shared": "4.0.433",
35
+ "@remotion/zod-types": "4.0.433",
36
+ "mediabunny": "1.37.0",
37
37
  "memfs": "3.4.3",
38
38
  "source-map": "0.7.3",
39
39
  "open": "^8.4.2",
@@ -43,9 +43,9 @@
43
43
  "react": "19.2.3",
44
44
  "react-dom": "19.2.3",
45
45
  "@types/semver": "^7.3.4",
46
- "@remotion/eslint-config-internal": "4.0.432",
46
+ "@remotion/eslint-config-internal": "4.0.433",
47
47
  "eslint": "9.19.0",
48
- "@typescript/native-preview": "7.0.0-dev.20260301.1"
48
+ "@typescript/native-preview": "7.0.0-dev.20260217.1"
49
49
  },
50
50
  "publishConfig": {
51
51
  "access": "public"