@remotion/studio 4.0.471 → 4.0.473

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 (192) hide show
  1. package/dist/api/rename-static-file.d.ts +6 -0
  2. package/dist/api/rename-static-file.js +18 -0
  3. package/dist/components/AssetSelector.js +55 -5
  4. package/dist/components/AssetSelectorItem.js +153 -27
  5. package/dist/components/Canvas.js +147 -0
  6. package/dist/components/CompositionSelectorItem.d.ts +1 -0
  7. package/dist/components/CompositionSelectorItem.js +12 -4
  8. package/dist/components/ConfirmationDialog-types.d.ts +8 -0
  9. package/dist/components/ConfirmationDialog-types.js +2 -0
  10. package/dist/components/ConfirmationDialog.d.ts +7 -0
  11. package/dist/components/ConfirmationDialog.js +103 -0
  12. package/dist/components/ContextMenu.d.ts +9 -1
  13. package/dist/components/ContextMenu.js +99 -47
  14. package/dist/components/CurrentAsset.d.ts +1 -0
  15. package/dist/components/CurrentAsset.js +13 -2
  16. package/dist/components/Editor.js +14 -6
  17. package/dist/components/EditorContent.js +15 -2
  18. package/dist/components/EditorContexts.js +2 -1
  19. package/dist/components/EditorRuler/Ruler.js +2 -0
  20. package/dist/components/ExplorerPanel.d.ts +0 -4
  21. package/dist/components/ExplorerPanel.js +8 -4
  22. package/dist/components/ExplorerPanelRef.d.ts +4 -0
  23. package/dist/components/ExplorerPanelRef.js +5 -0
  24. package/dist/components/FilePreview.d.ts +1 -1
  25. package/dist/components/InitialCompositionLoader.d.ts +0 -1
  26. package/dist/components/InitialCompositionLoader.js +5 -27
  27. package/dist/components/Menu/MenuItem.js +7 -1
  28. package/dist/components/Menu/SubMenu.js +5 -1
  29. package/dist/components/Menu/portals.js +17 -8
  30. package/dist/components/MenuToolbar.js +5 -1
  31. package/dist/components/ModalContainer.js +6 -1
  32. package/dist/components/Modals.js +8 -2
  33. package/dist/components/NewComposition/CodemodFooter.js +2 -2
  34. package/dist/components/NewComposition/ComboBox.js +8 -2
  35. package/dist/components/NewComposition/DeleteFolder.d.ts +6 -0
  36. package/dist/components/NewComposition/DeleteFolder.js +39 -0
  37. package/dist/components/NewComposition/DeleteStaticFile.d.ts +4 -0
  38. package/dist/components/NewComposition/DeleteStaticFile.js +44 -0
  39. package/dist/components/NewComposition/RenameFolder.d.ts +6 -0
  40. package/dist/components/NewComposition/RenameFolder.js +60 -0
  41. package/dist/components/NewComposition/RenameStaticFile.d.ts +4 -0
  42. package/dist/components/NewComposition/RenameStaticFile.js +118 -0
  43. package/dist/components/OptionsPanel.js +5 -1
  44. package/dist/components/OutlineToggle.d.ts +2 -0
  45. package/dist/components/OutlineToggle.js +20 -0
  46. package/dist/components/Preview.d.ts +0 -2
  47. package/dist/components/Preview.js +23 -33
  48. package/dist/components/PreviewToolbar.js +19 -6
  49. package/dist/components/RenderButton.js +8 -2
  50. package/dist/components/RenderPreview.js +2 -2
  51. package/dist/components/SelectedOutlineOverlay.d.ts +105 -4
  52. package/dist/components/SelectedOutlineOverlay.js +578 -59
  53. package/dist/components/ShowOutlinesProvider.d.ts +4 -0
  54. package/dist/components/ShowOutlinesProvider.js +24 -0
  55. package/dist/components/SizeSelector.js +3 -3
  56. package/dist/components/Splitter/SplitterContainer.js +9 -0
  57. package/dist/components/Splitter/SplitterHandle.js +65 -70
  58. package/dist/components/StaticFilePreview.js +2 -2
  59. package/dist/components/Timeline/KeyframeSettingsModal.d.ts +15 -0
  60. package/dist/components/Timeline/KeyframeSettingsModal.js +150 -0
  61. package/dist/components/Timeline/Timeline.js +50 -15
  62. package/dist/components/Timeline/TimelineArrayField.d.ts +9 -0
  63. package/dist/components/Timeline/TimelineArrayField.js +210 -0
  64. package/dist/components/Timeline/TimelineBooleanField.d.ts +2 -2
  65. package/dist/components/Timeline/TimelineBooleanField.js +2 -2
  66. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +43 -0
  67. package/dist/components/Timeline/TimelineClipboardKeybindings.js +479 -0
  68. package/dist/components/Timeline/TimelineColorField.d.ts +2 -2
  69. package/dist/components/Timeline/TimelineColorField.js +2 -8
  70. package/dist/components/Timeline/TimelineDeleteKeybindings.js +12 -2
  71. package/dist/components/Timeline/TimelineEffectItem.js +3 -2
  72. package/dist/components/Timeline/TimelineEffectPropItem.js +146 -26
  73. package/dist/components/Timeline/TimelineEnumField.d.ts +2 -2
  74. package/dist/components/Timeline/TimelineEnumField.js +3 -3
  75. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +4 -3
  76. package/dist/components/Timeline/TimelineKeyframeControls.js +41 -37
  77. package/dist/components/Timeline/TimelineKeyframeDiamond.js +24 -21
  78. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.d.ts +6 -0
  79. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.js +14 -0
  80. package/dist/components/Timeline/TimelineKeyframeDragState.d.ts +17 -0
  81. package/dist/components/Timeline/TimelineKeyframeDragState.js +39 -0
  82. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +7 -2
  83. package/dist/components/Timeline/TimelineKeyframedValue.js +22 -8
  84. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -0
  85. package/dist/components/Timeline/TimelineLayerEye.js +8 -3
  86. package/dist/components/Timeline/TimelineList.js +2 -2
  87. package/dist/components/Timeline/TimelineMediaInfo.d.ts +0 -13
  88. package/dist/components/Timeline/TimelineMediaInfo.js +8 -73
  89. package/dist/components/Timeline/TimelineNumberField.d.ts +2 -2
  90. package/dist/components/Timeline/TimelineNumberField.js +7 -11
  91. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +17 -0
  92. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +53 -0
  93. package/dist/components/Timeline/TimelineRotationField.d.ts +2 -2
  94. package/dist/components/Timeline/TimelineRotationField.js +41 -24
  95. package/dist/components/Timeline/TimelineRowChrome.js +8 -7
  96. package/dist/components/Timeline/TimelineScaleField.d.ts +20 -0
  97. package/dist/components/Timeline/TimelineScaleField.js +314 -0
  98. package/dist/components/Timeline/TimelineSchemaField.d.ts +3 -2
  99. package/dist/components/Timeline/TimelineSchemaField.js +8 -42
  100. package/dist/components/Timeline/TimelineSelection.js +3 -2
  101. package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
  102. package/dist/components/Timeline/TimelineSequence.js +51 -10
  103. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  104. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  105. package/dist/components/Timeline/TimelineSequenceItem.js +282 -28
  106. package/dist/components/Timeline/TimelineSequencePropItem.js +161 -35
  107. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +58 -0
  108. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +525 -0
  109. package/dist/components/Timeline/TimelineTrack.js +1 -1
  110. package/dist/components/Timeline/TimelineTranslateField.d.ts +2 -2
  111. package/dist/components/Timeline/TimelineTranslateField.js +21 -25
  112. package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +2 -2
  113. package/dist/components/Timeline/TimelineUvCoordinateField.js +20 -26
  114. package/dist/components/Timeline/apply-effect-response-to-code-values.d.ts +5 -0
  115. package/dist/components/Timeline/apply-effect-response-to-code-values.js +19 -0
  116. package/dist/components/Timeline/call-add-keyframe.js +4 -0
  117. package/dist/components/Timeline/call-move-keyframe.d.ts +19 -0
  118. package/dist/components/Timeline/call-move-keyframe.js +71 -0
  119. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +22 -0
  120. package/dist/components/Timeline/call-update-keyframe-settings.js +52 -0
  121. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +7 -4
  122. package/dist/components/Timeline/delete-selected-timeline-item.js +33 -21
  123. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +4 -2
  124. package/dist/components/Timeline/duplicate-selected-timeline-item.js +39 -34
  125. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.d.ts +8 -0
  126. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.js +12 -0
  127. package/dist/components/Timeline/get-keyframe-navigation.d.ts +2 -2
  128. package/dist/components/Timeline/get-keyframe-navigation.js +14 -6
  129. package/dist/components/Timeline/get-node-keyframes.d.ts +5 -2
  130. package/dist/components/Timeline/get-node-keyframes.js +38 -5
  131. package/dist/components/Timeline/get-timeline-keyframes.js +4 -4
  132. package/dist/components/Timeline/reset-selected-timeline-props.js +22 -8
  133. package/dist/components/Timeline/save-effect-prop.d.ts +14 -3
  134. package/dist/components/Timeline/save-effect-prop.js +36 -18
  135. package/dist/components/Timeline/save-prop-queue.d.ts +2 -1
  136. package/dist/components/Timeline/save-prop-queue.js +5 -2
  137. package/dist/components/Timeline/save-sequence-prop.d.ts +2 -7
  138. package/dist/components/Timeline/save-sequence-prop.js +33 -30
  139. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +3 -0
  140. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +7 -0
  141. package/dist/components/Timeline/timeline-asset-link.d.ts +13 -0
  142. package/dist/components/Timeline/timeline-asset-link.js +37 -0
  143. package/dist/components/Timeline/timeline-field-utils.d.ts +1 -0
  144. package/dist/components/Timeline/timeline-field-utils.js +5 -1
  145. package/dist/components/Timeline/timeline-translate-utils.js +9 -2
  146. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -0
  147. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +10 -0
  148. package/dist/components/Timeline/use-timeline-keyframe-drag.js +378 -0
  149. package/dist/components/TopPanel.d.ts +1 -1
  150. package/dist/components/folder-menu-items.d.ts +12 -0
  151. package/dist/components/folder-menu-items.js +147 -0
  152. package/dist/components/import-assets.d.ts +22 -0
  153. package/dist/components/import-assets.js +294 -0
  154. package/dist/components/load-canvas-content-from-url.d.ts +1 -0
  155. package/dist/components/load-canvas-content-from-url.js +9 -3
  156. package/dist/components/use-select-asset.d.ts +1 -0
  157. package/dist/components/use-select-asset.js +30 -0
  158. package/dist/error-overlay/error-origin.d.ts +3 -0
  159. package/dist/error-overlay/error-origin.js +42 -0
  160. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +6 -2
  161. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +38 -0
  162. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +1 -1
  163. package/dist/error-overlay/remotion-overlay/log-studio-error.d.ts +3 -0
  164. package/dist/error-overlay/remotion-overlay/log-studio-error.js +27 -0
  165. package/dist/esm/{chunk-z0z9d4r0.js → chunk-q0jkt0zq.js} +23062 -17350
  166. package/dist/esm/internals.mjs +23062 -17350
  167. package/dist/esm/previewEntry.mjs +22351 -16615
  168. package/dist/esm/renderEntry.mjs +1 -1
  169. package/dist/helpers/calculate-timeline.js +7 -3
  170. package/dist/helpers/create-folder-tree.js +1 -0
  171. package/dist/helpers/get-asset-metadata.js +2 -2
  172. package/dist/helpers/get-folder-id.d.ts +4 -0
  173. package/dist/helpers/get-folder-id.js +7 -0
  174. package/dist/helpers/get-preview-file-type.d.ts +2 -0
  175. package/dist/helpers/get-preview-file-type.js +33 -0
  176. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +2 -0
  177. package/dist/helpers/install-required-package.d.ts +1 -0
  178. package/dist/helpers/install-required-package.js +39 -0
  179. package/dist/helpers/remote-asset-drag.d.ts +4 -0
  180. package/dist/helpers/remote-asset-drag.js +73 -0
  181. package/dist/helpers/timeline-layout.js +5 -1
  182. package/dist/helpers/use-asset-drag-events.d.ts +5 -2
  183. package/dist/helpers/use-asset-drag-events.js +13 -2
  184. package/dist/helpers/validate-folder-rename.d.ts +6 -0
  185. package/dist/helpers/validate-folder-rename.js +19 -0
  186. package/dist/hot-middleware-client/client.js +6 -0
  187. package/dist/state/editor-outlines.d.ts +8 -0
  188. package/dist/state/editor-outlines.js +18 -0
  189. package/dist/state/modals.d.ts +29 -2
  190. package/dist/state/scale-lock.d.ts +18 -0
  191. package/dist/state/scale-lock.js +59 -0
  192. package/package.json +10 -10
@@ -33,27 +33,38 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SelectedOutlineOverlay = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineDragValues = exports.getSelectedEffectFieldsBySequenceKey = exports.getUvCoordinateForPoint = exports.getUvHandlePosition = void 0;
36
+ exports.SelectedOutlineOverlay = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineDragValues = exports.getSequencesWithSelectableOutlines = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.getUvCoordinateForPoint = exports.getUvHandleConnectionLines = exports.getUvHandlePosition = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
40
+ const no_react_1 = require("remotion/no-react");
40
41
  const calculate_timeline_1 = require("../helpers/calculate-timeline");
41
42
  const client_id_1 = require("../helpers/client-id");
42
43
  const colors_1 = require("../helpers/colors");
44
+ const format_file_location_1 = require("../helpers/format-file-location");
43
45
  const get_box_quads_ponyfill_1 = require("../helpers/get-box-quads-ponyfill");
46
+ const open_in_editor_1 = require("../helpers/open-in-editor");
47
+ const editor_outlines_1 = require("../state/editor-outlines");
48
+ const scale_lock_1 = require("../state/scale-lock");
49
+ const ContextMenu_1 = require("./ContextMenu");
44
50
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
51
+ const call_add_keyframe_1 = require("./Timeline/call-add-keyframe");
45
52
  const save_effect_prop_1 = require("./Timeline/save-effect-prop");
46
53
  const save_sequence_prop_1 = require("./Timeline/save-sequence-prop");
47
54
  const timeline_field_utils_1 = require("./Timeline/timeline-field-utils");
48
55
  const timeline_translate_utils_1 = require("./Timeline/timeline-translate-utils");
56
+ const TimelineScaleField_1 = require("./Timeline/TimelineScaleField");
49
57
  const TimelineSelection_1 = require("./Timeline/TimelineSelection");
58
+ const get_stack_1 = require("./Timeline/TimelineStack/get-stack");
50
59
  const translateFieldKey = 'style.translate';
60
+ const scaleFieldKey = 'style.scale';
51
61
  const outlineContainer = {
52
62
  position: 'absolute',
53
63
  inset: 0,
54
64
  pointerEvents: 'none',
55
65
  overflow: 'visible',
56
66
  };
67
+ const emptyContextMenuValues = [];
57
68
  const pointToString = (point) => `${point.x},${point.y}`;
58
69
  const parseUvCoordinate = (value) => {
59
70
  if (Array.isArray(value) &&
@@ -78,6 +89,15 @@ const mixPoint = (from, to, progress) => {
78
89
  y: mix(from.y, to.y, progress),
79
90
  };
80
91
  };
92
+ const midpoint = (from, to) => {
93
+ return mixPoint(from, to, 0.5);
94
+ };
95
+ const dot = (left, right) => {
96
+ return left.x * right.x + left.y * right.y;
97
+ };
98
+ const vectorLength = (vector) => {
99
+ return Math.hypot(vector.x, vector.y);
100
+ };
81
101
  const getBilinearUvHandlePosition = (points, uv) => {
82
102
  const [tl, tr, br, bl] = points;
83
103
  const top = mixPoint(tl, tr, uv[0]);
@@ -128,6 +148,39 @@ const getUvHandlePosition = (points, uv) => {
128
148
  : applyProjectiveTransform(transform, uv);
129
149
  };
130
150
  exports.getUvHandlePosition = getUvHandlePosition;
151
+ const getUvHandleConnectionLines = ({ handles, points, }) => {
152
+ const handlesByField = new Map(handles.map((handle) => [
153
+ `${handle.effectIndex}\u0000${handle.fieldKey}`,
154
+ handle,
155
+ ]));
156
+ const seenPairs = new Set();
157
+ const lines = [];
158
+ for (const handle of handles) {
159
+ const targetFieldKey = handle.fieldSchema.lineTo;
160
+ if (targetFieldKey === undefined || targetFieldKey === handle.fieldKey) {
161
+ continue;
162
+ }
163
+ const target = handlesByField.get(`${handle.effectIndex}\u0000${targetFieldKey}`);
164
+ if (target === undefined) {
165
+ continue;
166
+ }
167
+ const pairKey = [
168
+ handle.effectIndex,
169
+ ...[handle.fieldKey, targetFieldKey].sort(),
170
+ ].join('\u0000');
171
+ if (seenPairs.has(pairKey)) {
172
+ continue;
173
+ }
174
+ seenPairs.add(pairKey);
175
+ lines.push({
176
+ key: `${handle.effectIndex}-${handle.fieldKey}-${targetFieldKey}`,
177
+ from: (0, exports.getUvHandlePosition)(points, handle.value),
178
+ to: (0, exports.getUvHandlePosition)(points, target.value),
179
+ });
180
+ }
181
+ return lines;
182
+ };
183
+ exports.getUvHandleConnectionLines = getUvHandleConnectionLines;
131
184
  const vectorBetween = (from, to) => {
132
185
  return { x: to.x - from.x, y: to.y - from.y };
133
186
  };
@@ -249,6 +302,11 @@ const getElementOutlinePoints = (element, containerRect) => {
249
302
  const getSelectedSequenceKeys = (selectedItems) => {
250
303
  return new Set(selectedItems.map((item) => (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(item.nodePathInfo)));
251
304
  };
305
+ const getOutlineSelectionInteraction = ({ shiftKey, metaKey, ctrlKey, }) => ({
306
+ shiftKey,
307
+ toggleKey: metaKey || ctrlKey,
308
+ });
309
+ exports.getOutlineSelectionInteraction = getOutlineSelectionInteraction;
252
310
  const getSelectedEffectFieldsBySequenceKey = (selectedItems) => {
253
311
  var _a, _b;
254
312
  const selectedEffects = new Map();
@@ -270,11 +328,7 @@ const getSelectedEffectFieldsBySequenceKey = (selectedItems) => {
270
328
  return selectedEffects;
271
329
  };
272
330
  exports.getSelectedEffectFieldsBySequenceKey = getSelectedEffectFieldsBySequenceKey;
273
- const getSequencesWithSelectedOutlines = ({ selectedItems, sequences, overrideIdsToNodePaths, }) => {
274
- const selectedSequenceKeys = getSelectedSequenceKeys(selectedItems);
275
- if (selectedSequenceKeys.size === 0) {
276
- return [];
277
- }
331
+ const getSequencesWithSelectableOutlines = ({ sequences, overrideIdsToNodePaths, }) => {
278
332
  return (0, calculate_timeline_1.calculateTimeline)({
279
333
  sequences: [...sequences],
280
334
  overrideIdsToNodePaths,
@@ -283,20 +337,24 @@ const getSequencesWithSelectedOutlines = ({ selectedItems, sequences, overrideId
283
337
  if (track.nodePathInfo === null) {
284
338
  return false;
285
339
  }
286
- return selectedSequenceKeys.has((0, TimelineSelection_1.getTimelineSequenceSelectionKey)(track.nodePathInfo));
340
+ return track.nodePathInfo.auxiliaryKeys.length === 0;
287
341
  })
288
342
  .filter((track) => track.sequence.refForOutline !== null)
343
+ .sort((a, b) => a.depth - b.depth)
289
344
  .map((track) => {
290
345
  if (track.nodePathInfo === null) {
291
346
  throw new Error('Expected selected outline to have a node path');
292
347
  }
293
348
  return {
349
+ depth: track.depth,
350
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
294
351
  key: (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(track.nodePathInfo),
295
352
  nodePathInfo: track.nodePathInfo,
296
353
  sequence: track.sequence,
297
354
  };
298
355
  });
299
356
  };
357
+ exports.getSequencesWithSelectableOutlines = getSequencesWithSelectableOutlines;
300
358
  const getSelectedUvHandles = ({ codeValues, clientId, getEffectDragOverrides, nodePath, selectedEffects, sequence, }) => {
301
359
  if (clientId === null || selectedEffects === undefined) {
302
360
  return [];
@@ -317,12 +375,12 @@ const getSelectedUvHandles = ({ codeValues, clientId, getEffectDragOverrides, no
317
375
  }
318
376
  const dragOverrides = getEffectDragOverrides(nodePath, effectIndex);
319
377
  const activeSchema = remotion_1.Internals.flattenActiveSchema(effect.schema, (key) => {
320
- const dragOverride = dragOverrides[key];
378
+ const dragOverride = remotion_1.Internals.getStaticDragOverrideValue(dragOverrides[key]);
321
379
  if (dragOverride !== undefined) {
322
380
  return dragOverride;
323
381
  }
324
382
  const propStatus = effectStatus.props[key];
325
- if (!(propStatus === null || propStatus === void 0 ? void 0 : propStatus.canUpdate)) {
383
+ if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static') {
326
384
  return undefined;
327
385
  }
328
386
  return propStatus.codeValue;
@@ -333,7 +391,7 @@ const getSelectedUvHandles = ({ codeValues, clientId, getEffectDragOverrides, no
333
391
  continue;
334
392
  }
335
393
  const propStatus = effectStatus.props[fieldKey];
336
- if (!(propStatus === null || propStatus === void 0 ? void 0 : propStatus.canUpdate)) {
394
+ if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static') {
337
395
  continue;
338
396
  }
339
397
  const dragOverrideValue = dragOverrides[fieldKey];
@@ -395,14 +453,16 @@ const outlinesAreEqual = (a, b) => {
395
453
  }
396
454
  return true;
397
455
  };
398
- const getSelectedOutlineDragStates = ({ dragTargets, getDragOverrides, }) => {
456
+ const getSelectedOutlineDragStates = ({ dragTargets, getDragOverrides, timelinePosition, }) => {
399
457
  return dragTargets.map((target) => {
400
458
  var _a;
401
459
  const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[translateFieldKey];
460
+ const sourceFrame = timelinePosition - target.keyframeDisplayOffset;
402
461
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
403
462
  codeValue: target.codeValue,
404
463
  dragOverrideValue,
405
464
  defaultValue: target.fieldDefault,
465
+ frame: sourceFrame,
406
466
  shouldResortToDefaultValueIfUndefined: true,
407
467
  });
408
468
  const [startX, startY] = (0, timeline_translate_utils_1.parseTranslate)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px'));
@@ -411,6 +471,7 @@ const getSelectedOutlineDragStates = ({ dragTargets, getDragOverrides, }) => {
411
471
  ? JSON.stringify(target.fieldDefault)
412
472
  : null,
413
473
  key: remotion_1.Internals.makeSequencePropsSubscriptionKey(target.nodePath),
474
+ sourceFrame,
414
475
  startX,
415
476
  startY,
416
477
  target,
@@ -425,13 +486,134 @@ const getSelectedOutlineDragValues = ({ dragStates, deltaX, deltaY, }) => {
425
486
  };
426
487
  exports.getSelectedOutlineDragValues = getSelectedOutlineDragValues;
427
488
  const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
489
+ const changes = [];
490
+ for (const dragState of dragStates) {
491
+ const value = lastValues.get(dragState.key);
492
+ if (value === undefined) {
493
+ continue;
494
+ }
495
+ if (dragState.target.codeValue.status === 'keyframed') {
496
+ const startValue = (0, timeline_translate_utils_1.serializeTranslate)(dragState.startX, dragState.startY);
497
+ if (value === startValue) {
498
+ continue;
499
+ }
500
+ changes.push({
501
+ type: 'keyframed',
502
+ fileName: dragState.target.nodePath.absolutePath,
503
+ nodePath: dragState.target.nodePath,
504
+ fieldKey: translateFieldKey,
505
+ sourceFrame: dragState.sourceFrame,
506
+ value,
507
+ schema: dragState.target.schema,
508
+ clientId: dragState.target.clientId,
509
+ });
510
+ continue;
511
+ }
512
+ const stringifiedValue = JSON.stringify(value);
513
+ const shouldSave = value !== dragState.target.codeValue.codeValue &&
514
+ !(dragState.defaultValue === stringifiedValue &&
515
+ dragState.target.codeValue.codeValue === undefined);
516
+ if (!shouldSave) {
517
+ continue;
518
+ }
519
+ changes.push({
520
+ type: 'static',
521
+ fileName: dragState.target.nodePath.absolutePath,
522
+ nodePath: dragState.target.nodePath,
523
+ fieldKey: translateFieldKey,
524
+ value,
525
+ defaultValue: dragState.defaultValue,
526
+ schema: dragState.target.schema,
527
+ });
528
+ }
529
+ return changes;
530
+ };
531
+ exports.getSelectedOutlineDragChanges = getSelectedOutlineDragChanges;
532
+ const getSelectedOutlineScaleEdgeInfo = (points, edge) => {
533
+ const [tl, tr, br, bl] = points;
534
+ const edgePoints = {
535
+ top: { start: tl, end: tr, oppositeStart: bl, oppositeEnd: br },
536
+ right: { start: tr, end: br, oppositeStart: tl, oppositeEnd: bl },
537
+ bottom: { start: bl, end: br, oppositeStart: tl, oppositeEnd: tr },
538
+ left: { start: tl, end: bl, oppositeStart: tr, oppositeEnd: br },
539
+ }[edge];
540
+ const edgeMidpoint = midpoint(edgePoints.start, edgePoints.end);
541
+ const oppositeMidpoint = midpoint(edgePoints.oppositeStart, edgePoints.oppositeEnd);
542
+ const outward = vectorBetween(oppositeMidpoint, edgeMidpoint);
543
+ const length = vectorLength(outward);
544
+ if (length < 0.001) {
545
+ return null;
546
+ }
547
+ return {
548
+ axis: edge === 'left' || edge === 'right' ? 'x' : 'y',
549
+ cursor: edge === 'left' || edge === 'right' ? 'ew-resize' : 'ns-resize',
550
+ end: edgePoints.end,
551
+ extent: length,
552
+ normal: { x: outward.x / length, y: outward.y / length },
553
+ start: edgePoints.start,
554
+ };
555
+ };
556
+ exports.getSelectedOutlineScaleEdgeInfo = getSelectedOutlineScaleEdgeInfo;
557
+ const getSelectedOutlineScaleDragStates = ({ dragTargets, getDragOverrides, }) => {
558
+ return dragTargets.map((target) => {
559
+ var _a;
560
+ const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[scaleFieldKey];
561
+ const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
562
+ codeValue: target.codeValue,
563
+ dragOverrideValue,
564
+ defaultValue: target.fieldDefault,
565
+ shouldResortToDefaultValueIfUndefined: true,
566
+ });
567
+ const [startX, startY, startZ] = no_react_1.NoReactInternals.parseScaleValue(effectiveValue);
568
+ return {
569
+ defaultValue: target.fieldDefault !== undefined
570
+ ? JSON.stringify(target.fieldDefault)
571
+ : null,
572
+ key: remotion_1.Internals.makeSequencePropsSubscriptionKey(target.nodePath),
573
+ startX,
574
+ startY,
575
+ startZ,
576
+ target,
577
+ };
578
+ });
579
+ };
580
+ exports.getSelectedOutlineScaleDragStates = getSelectedOutlineScaleDragStates;
581
+ const getSelectedOutlineScaleDragValues = ({ axis, dragStates, scaleFactor, }) => {
582
+ return new Map(dragStates.map((dragState) => {
583
+ var _a, _b;
584
+ const min = (_a = dragState.target.fieldSchema.min) !== null && _a !== void 0 ? _a : -Infinity;
585
+ const max = (_b = dragState.target.fieldSchema.max) !== null && _b !== void 0 ? _b : Infinity;
586
+ const baseX = dragState.startX;
587
+ const baseY = dragState.startY;
588
+ const newValue = (axis === 'x' ? baseX : baseY) * scaleFactor;
589
+ const [x, y] = dragState.target.linked
590
+ ? (0, TimelineScaleField_1.getLinkedScale)({
591
+ axis,
592
+ newValue,
593
+ baseX,
594
+ baseY,
595
+ min,
596
+ max,
597
+ })
598
+ : axis === 'x'
599
+ ? [clamp(newValue, min, max), baseY]
600
+ : [baseX, clamp(newValue, min, max)];
601
+ return [
602
+ dragState.key,
603
+ no_react_1.NoReactInternals.serializeScaleValue([x, y, dragState.startZ]),
604
+ ];
605
+ }));
606
+ };
607
+ exports.getSelectedOutlineScaleDragValues = getSelectedOutlineScaleDragValues;
608
+ const getSelectedOutlineScaleDragChanges = ({ dragStates, lastValues, }) => {
428
609
  return dragStates.flatMap((dragState) => {
429
610
  const value = lastValues.get(dragState.key);
430
611
  if (value === undefined) {
431
612
  return [];
432
613
  }
433
614
  const stringifiedValue = JSON.stringify(value);
434
- const shouldSave = value !== dragState.target.codeValue.codeValue &&
615
+ const shouldSave = stringifiedValue !==
616
+ JSON.stringify(dragState.target.codeValue.codeValue) &&
435
617
  !(dragState.defaultValue === stringifiedValue &&
436
618
  dragState.target.codeValue.codeValue === undefined);
437
619
  if (!shouldSave) {
@@ -441,7 +623,7 @@ const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
441
623
  {
442
624
  fileName: dragState.target.nodePath.absolutePath,
443
625
  nodePath: dragState.target.nodePath,
444
- fieldKey: translateFieldKey,
626
+ fieldKey: scaleFieldKey,
445
627
  value,
446
628
  defaultValue: dragState.defaultValue,
447
629
  schema: dragState.target.schema,
@@ -449,29 +631,50 @@ const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
449
631
  ];
450
632
  });
451
633
  };
452
- exports.getSelectedOutlineDragChanges = getSelectedOutlineDragChanges;
634
+ exports.getSelectedOutlineScaleDragChanges = getSelectedOutlineScaleDragChanges;
453
635
  const clearSelectedOutlineDragOverrides = ({ clearDragOverrides, dragStates, }) => {
454
636
  for (const dragState of dragStates) {
455
637
  clearDragOverrides(dragState.target.nodePath);
456
638
  }
457
639
  };
458
- const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
459
- var _a;
640
+ const clearSelectedOutlineScaleDragOverrides = ({ clearDragOverrides, dragStates, }) => {
641
+ for (const dragState of dragStates) {
642
+ clearDragOverrides(dragState.target.nodePath);
643
+ }
644
+ };
645
+ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, hovered, onContextMenuOpen, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
646
+ var _a, _b;
460
647
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
461
648
  const { setCodeValues, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
649
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
650
+ const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
651
+ timelinePositionRef.current = timelinePosition;
652
+ const polygonRef = (0, react_1.useRef)(null);
462
653
  const points = (0, react_1.useMemo)(() => outline.points.map(pointToString).join(' '), [outline.points]);
463
654
  const drag = (_a = target === null || target === void 0 ? void 0 : target.drag) !== null && _a !== void 0 ? _a : null;
655
+ const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
656
+ const visible = selected || hovered;
464
657
  const onPointerDown = react_1.default.useCallback((event) => {
465
- if (event.button !== 0 || drag === null) {
658
+ if (event.button !== 0 || target === undefined) {
466
659
  return;
467
660
  }
468
661
  event.preventDefault();
469
662
  event.stopPropagation();
663
+ const interaction = (0, exports.getOutlineSelectionInteraction)(event);
664
+ const shouldUpdateSelection = !selected || interaction.shiftKey || interaction.toggleKey;
665
+ if (shouldUpdateSelection) {
666
+ onSelect(target.selection, interaction);
667
+ }
668
+ if (drag === null || interaction.shiftKey || interaction.toggleKey) {
669
+ return;
670
+ }
671
+ onDraggingChange(true);
470
672
  const startPointerX = event.clientX;
471
673
  const startPointerY = event.clientY;
472
674
  const dragStates = getSelectedOutlineDragStates({
473
- dragTargets: allDragTargets,
675
+ dragTargets: selected ? allDragTargets : [drag],
474
676
  getDragOverrides,
677
+ timelinePosition: timelinePositionRef.current,
475
678
  });
476
679
  let lastValues = new Map();
477
680
  const onPointerMove = (moveEvent) => {
@@ -486,13 +689,23 @@ const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
486
689
  if (value === undefined) {
487
690
  throw new Error('Expected drag value to be available');
488
691
  }
489
- setDragOverrides(dragState.target.nodePath, translateFieldKey, value);
692
+ if (dragState.target.codeValue.status === 'keyframed') {
693
+ setDragOverrides(dragState.target.nodePath, translateFieldKey, remotion_1.Internals.makeKeyframedDragOverride({
694
+ status: dragState.target.codeValue,
695
+ frame: dragState.sourceFrame,
696
+ value,
697
+ }));
698
+ }
699
+ else {
700
+ setDragOverrides(dragState.target.nodePath, translateFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
701
+ }
490
702
  }
491
703
  };
492
704
  const onPointerUp = () => {
493
705
  window.removeEventListener('pointermove', onPointerMove);
494
706
  window.removeEventListener('pointerup', onPointerUp);
495
707
  window.removeEventListener('pointercancel', onPointerUp);
708
+ onDraggingChange(false);
496
709
  const changes = (0, exports.getSelectedOutlineDragChanges)({
497
710
  dragStates,
498
711
  lastValues,
@@ -501,13 +714,33 @@ const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
501
714
  clearSelectedOutlineDragOverrides({ clearDragOverrides, dragStates });
502
715
  return;
503
716
  }
504
- (0, save_sequence_prop_1.saveSequenceProps)({
505
- changes,
506
- setCodeValues,
507
- clientId: drag.clientId,
508
- undoLabel: changes.length > 1 ? 'Move selected sequences' : null,
509
- redoLabel: changes.length > 1 ? 'Move selected sequences back' : null,
510
- })
717
+ const staticChanges = changes.filter((change) => change.type === 'static');
718
+ const keyframedChanges = changes.filter((change) => change.type === 'keyframed');
719
+ Promise.all([
720
+ staticChanges.length > 0
721
+ ? (0, save_sequence_prop_1.saveSequenceProps)({
722
+ changes: staticChanges,
723
+ setCodeValues,
724
+ clientId: drag.clientId,
725
+ undoLabel: changes.length > 1
726
+ ? 'Move selected sequences'
727
+ : 'Move sequence',
728
+ redoLabel: changes.length > 1
729
+ ? 'Move selected sequences back'
730
+ : 'Move sequence back',
731
+ })
732
+ : Promise.resolve(),
733
+ ...keyframedChanges.map((change) => (0, call_add_keyframe_1.callAddSequenceKeyframe)({
734
+ fileName: change.fileName,
735
+ nodePath: change.nodePath,
736
+ fieldKey: change.fieldKey,
737
+ sourceFrame: change.sourceFrame,
738
+ value: change.value,
739
+ schema: change.schema,
740
+ setCodeValues,
741
+ clientId: change.clientId,
742
+ })),
743
+ ])
511
744
  .catch((err) => {
512
745
  (0, NotificationCenter_1.showNotification)(`Could not save sequence props: ${err instanceof Error ? err.message : String(err)}`, 4000);
513
746
  })
@@ -523,11 +756,141 @@ const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
523
756
  clearDragOverrides,
524
757
  drag,
525
758
  getDragOverrides,
759
+ onDraggingChange,
760
+ onSelect,
526
761
  scale,
762
+ selected,
527
763
  setCodeValues,
528
764
  setDragOverrides,
765
+ target,
529
766
  ]);
530
- return (jsx_runtime_1.jsx("polygon", { points: points, fill: drag === null ? 'none' : 'transparent', stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: drag === null ? undefined : 'all', onPointerDown: drag === null ? undefined : onPointerDown }));
767
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
768
+ jsx_runtime_1.jsx("polygon", { ref: polygonRef, points: points, fill: "transparent", stroke: colors_1.BLUE, strokeOpacity: visible ? 1 : 0, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: target === undefined ? undefined : 'all', onPointerEnter: () => {
769
+ if (!dragging) {
770
+ onHoverChange(outline.key);
771
+ }
772
+ }, onPointerLeave: () => {
773
+ if (!dragging) {
774
+ onHoverChange(null);
775
+ }
776
+ }, onPointerDown: onPointerDown }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: polygonRef, values: [...contextMenuValues], onOpen: onContextMenuOpen })
777
+ ] }));
778
+ };
779
+ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues, dragging, edge, outline, onDraggingChange, onContextMenuOpen, onHoverChange, onSelect, target, }) => {
780
+ var _a, _b;
781
+ const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
782
+ const { setCodeValues, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
783
+ const scaleDrag = (_a = target === null || target === void 0 ? void 0 : target.scaleDrag) !== null && _a !== void 0 ? _a : null;
784
+ const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
785
+ const lineRef = (0, react_1.useRef)(null);
786
+ const edgeInfo = (0, react_1.useMemo)(() => (0, exports.getSelectedOutlineScaleEdgeInfo)(outline.points, edge), [edge, outline.points]);
787
+ const onPointerDown = react_1.default.useCallback((event) => {
788
+ if (event.button !== 0 || scaleDrag === null || edgeInfo === null) {
789
+ return;
790
+ }
791
+ event.preventDefault();
792
+ event.stopPropagation();
793
+ const interaction = (0, exports.getOutlineSelectionInteraction)(event);
794
+ const shouldUpdateSelection = !selected || interaction.shiftKey || interaction.toggleKey;
795
+ if (shouldUpdateSelection && target !== undefined) {
796
+ onSelect(target.selection, interaction);
797
+ }
798
+ if (interaction.shiftKey || interaction.toggleKey) {
799
+ return;
800
+ }
801
+ onDraggingChange(true);
802
+ const startPointer = { x: event.clientX, y: event.clientY };
803
+ const dragStates = (0, exports.getSelectedOutlineScaleDragStates)({
804
+ dragTargets: selected ? allScaleDragTargets : [scaleDrag],
805
+ getDragOverrides,
806
+ });
807
+ let lastValues = new Map();
808
+ const onPointerMove = (moveEvent) => {
809
+ moveEvent.preventDefault();
810
+ const delta = {
811
+ x: moveEvent.clientX - startPointer.x,
812
+ y: moveEvent.clientY - startPointer.y,
813
+ };
814
+ const projectedDelta = dot(delta, edgeInfo.normal);
815
+ const scaleFactor = Math.max(0.001, 1 + projectedDelta / edgeInfo.extent);
816
+ lastValues = (0, exports.getSelectedOutlineScaleDragValues)({
817
+ dragStates,
818
+ axis: edgeInfo.axis,
819
+ scaleFactor,
820
+ });
821
+ for (const dragState of dragStates) {
822
+ const value = lastValues.get(dragState.key);
823
+ if (value === undefined) {
824
+ throw new Error('Expected scale drag value to be available');
825
+ }
826
+ setDragOverrides(dragState.target.nodePath, scaleFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
827
+ }
828
+ };
829
+ const onPointerUp = () => {
830
+ window.removeEventListener('pointermove', onPointerMove);
831
+ window.removeEventListener('pointerup', onPointerUp);
832
+ window.removeEventListener('pointercancel', onPointerUp);
833
+ onDraggingChange(false);
834
+ const changes = (0, exports.getSelectedOutlineScaleDragChanges)({
835
+ dragStates,
836
+ lastValues,
837
+ });
838
+ if (changes.length === 0) {
839
+ clearSelectedOutlineScaleDragOverrides({
840
+ clearDragOverrides,
841
+ dragStates,
842
+ });
843
+ return;
844
+ }
845
+ (0, save_sequence_prop_1.saveSequenceProps)({
846
+ changes,
847
+ setCodeValues,
848
+ clientId: scaleDrag.clientId,
849
+ undoLabel: changes.length > 1 ? 'Scale selected sequences' : 'Scale sequence',
850
+ redoLabel: changes.length > 1
851
+ ? 'Scale selected sequences back'
852
+ : 'Scale sequence back',
853
+ })
854
+ .catch((err) => {
855
+ (0, NotificationCenter_1.showNotification)(`Could not save sequence props: ${err instanceof Error ? err.message : String(err)}`, 4000);
856
+ })
857
+ .finally(() => {
858
+ clearSelectedOutlineScaleDragOverrides({
859
+ clearDragOverrides,
860
+ dragStates,
861
+ });
862
+ });
863
+ };
864
+ window.addEventListener('pointermove', onPointerMove);
865
+ window.addEventListener('pointerup', onPointerUp);
866
+ window.addEventListener('pointercancel', onPointerUp);
867
+ }, [
868
+ allScaleDragTargets,
869
+ clearDragOverrides,
870
+ edgeInfo,
871
+ getDragOverrides,
872
+ onDraggingChange,
873
+ onSelect,
874
+ scaleDrag,
875
+ selected,
876
+ setCodeValues,
877
+ setDragOverrides,
878
+ target,
879
+ ]);
880
+ if (scaleDrag === null || edgeInfo === null) {
881
+ return null;
882
+ }
883
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
884
+ jsx_runtime_1.jsx("line", { ref: lineRef, x1: edgeInfo.start.x, y1: edgeInfo.start.y, x2: edgeInfo.end.x, y2: edgeInfo.end.y, stroke: "transparent", strokeWidth: 12, vectorEffect: "non-scaling-stroke", pointerEvents: "stroke", cursor: edgeInfo.cursor, onPointerEnter: () => {
885
+ if (!dragging) {
886
+ onHoverChange(outline.key);
887
+ }
888
+ }, onPointerLeave: () => {
889
+ if (!dragging) {
890
+ onHoverChange(null);
891
+ }
892
+ }, onPointerDown: onPointerDown }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: lineRef, values: [...contextMenuValues], onOpen: onContextMenuOpen })
893
+ ] }));
531
894
  };
532
895
  const getSvgPointFromPointerEvent = ({ event, rect, }) => {
533
896
  return {
@@ -535,7 +898,11 @@ const getSvgPointFromPointerEvent = ({ event, rect, }) => {
535
898
  y: event.clientY - rect.top,
536
899
  };
537
900
  };
538
- const SelectedUvHandleCircle = ({ handle, outline }) => {
901
+ const SelectedUvHandleConnectionLines = ({ handles, outline }) => {
902
+ const lines = (0, react_1.useMemo)(() => (0, exports.getUvHandleConnectionLines)({ handles, points: outline.points }), [handles, outline.points]);
903
+ return (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: lines.map((line) => (jsx_runtime_1.jsx("line", { x1: line.from.x, y1: line.from.y, x2: line.to.x, y2: line.to.y, stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: "none" }, line.key))) }));
904
+ };
905
+ const SelectedUvHandleCircle = ({ handle, onDraggingChange, outline }) => {
539
906
  const { setEffectDragOverrides, clearEffectDragOverrides, setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
540
907
  const position = (0, react_1.useMemo)(() => (0, exports.getUvHandlePosition)(outline.points, handle.value), [handle.value, outline.points]);
541
908
  const onPointerDown = react_1.default.useCallback((event) => {
@@ -550,6 +917,7 @@ const SelectedUvHandleCircle = ({ handle, outline }) => {
550
917
  }
551
918
  const svgRect = svg.getBoundingClientRect();
552
919
  let lastValue = null;
920
+ onDraggingChange(true);
553
921
  const defaultValue = handle.fieldDefault !== undefined
554
922
  ? JSON.stringify(handle.fieldDefault)
555
923
  : null;
@@ -560,7 +928,7 @@ const SelectedUvHandleCircle = ({ handle, outline }) => {
560
928
  });
561
929
  const nextValue = constrainUv((0, exports.getUvCoordinateForPoint)(outline.points, point), handle.fieldSchema);
562
930
  lastValue = nextValue;
563
- setEffectDragOverrides(handle.nodePath, handle.effectIndex, handle.fieldKey, nextValue);
931
+ setEffectDragOverrides(handle.nodePath, handle.effectIndex, handle.fieldKey, remotion_1.Internals.makeStaticDragOverride(nextValue));
564
932
  };
565
933
  updateFromPointerEvent(event);
566
934
  const onPointerMove = (moveEvent) => {
@@ -571,6 +939,7 @@ const SelectedUvHandleCircle = ({ handle, outline }) => {
571
939
  window.removeEventListener('pointermove', onPointerMove);
572
940
  window.removeEventListener('pointerup', onPointerUp);
573
941
  window.removeEventListener('pointercancel', onPointerUp);
942
+ onDraggingChange(false);
574
943
  const stringifiedValue = lastValue === null ? null : JSON.stringify(lastValue);
575
944
  const shouldSave = lastValue !== null &&
576
945
  !tuplesEqual(handle.codeValue.codeValue, lastValue) &&
@@ -581,6 +950,7 @@ const SelectedUvHandleCircle = ({ handle, outline }) => {
581
950
  return;
582
951
  }
583
952
  (0, save_effect_prop_1.saveEffectProp)({
953
+ type: 'value',
584
954
  fileName: handle.nodePath.absolutePath,
585
955
  nodePath: handle.nodePath,
586
956
  effectIndex: handle.effectIndex,
@@ -600,91 +970,244 @@ const SelectedUvHandleCircle = ({ handle, outline }) => {
600
970
  }, [
601
971
  clearEffectDragOverrides,
602
972
  handle,
973
+ onDraggingChange,
603
974
  outline.points,
604
975
  setCodeValues,
605
976
  setEffectDragOverrides,
606
977
  ]);
607
978
  return (jsx_runtime_1.jsx("circle", { cx: position.x, cy: position.y, r: 6, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: "all", cursor: "move", onPointerDown: onPointerDown }));
608
979
  };
980
+ const SelectedOutlineElement = ({ allDragTargets, allScaleDragTargets, dragging, hovered, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
981
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
982
+ const updateResolvedStackTrace = (0, react_1.useContext)(remotion_1.Internals.SequenceStackTracesUpdateContext);
983
+ const onContextMenuOpen = react_1.default.useCallback(async () => {
984
+ if (target === undefined || previewServerState.type !== 'connected') {
985
+ return false;
986
+ }
987
+ if (!target.selected) {
988
+ onSelect(target.selection, { shiftKey: false, toggleKey: false });
989
+ }
990
+ const stack = target.sequence.getStack();
991
+ let originalLocation = null;
992
+ if (stack) {
993
+ try {
994
+ originalLocation = await (0, get_stack_1.getOriginalLocationFromStack)(stack, 'sequence');
995
+ }
996
+ catch (err) {
997
+ (0, NotificationCenter_1.showNotification)(err.message, 2000);
998
+ }
999
+ }
1000
+ if (stack) {
1001
+ updateResolvedStackTrace(stack, originalLocation);
1002
+ }
1003
+ const fileLocation = (0, format_file_location_1.formatFileLocation)({
1004
+ location: originalLocation,
1005
+ root: window.remotion_cwd,
1006
+ });
1007
+ const editorName = window.remotion_editorName;
1008
+ return [
1009
+ editorName
1010
+ ? {
1011
+ type: 'item',
1012
+ id: 'show-outline-in-editor',
1013
+ keyHint: null,
1014
+ label: `Show in ${editorName}`,
1015
+ leftItem: null,
1016
+ disabled: !originalLocation,
1017
+ onClick: () => {
1018
+ if (!originalLocation) {
1019
+ return;
1020
+ }
1021
+ (0, open_in_editor_1.openOriginalPositionInEditor)(originalLocation).catch((err) => {
1022
+ (0, NotificationCenter_1.showNotification)(err.message, 2000);
1023
+ });
1024
+ },
1025
+ quickSwitcherLabel: null,
1026
+ subMenu: null,
1027
+ value: 'show-outline-in-editor',
1028
+ }
1029
+ : null,
1030
+ {
1031
+ type: 'item',
1032
+ id: 'copy-outline-file-location',
1033
+ keyHint: null,
1034
+ label: 'Copy file location',
1035
+ leftItem: null,
1036
+ disabled: !fileLocation,
1037
+ onClick: () => {
1038
+ if (!fileLocation) {
1039
+ return;
1040
+ }
1041
+ navigator.clipboard
1042
+ .writeText(fileLocation)
1043
+ .then(() => {
1044
+ (0, NotificationCenter_1.showNotification)('Copied file location to clipboard', 1000);
1045
+ })
1046
+ .catch((err) => {
1047
+ (0, NotificationCenter_1.showNotification)(`Could not copy to clipboard: ${err.message}`, 1000);
1048
+ });
1049
+ },
1050
+ quickSwitcherLabel: null,
1051
+ subMenu: null,
1052
+ value: 'copy-outline-file-location',
1053
+ },
1054
+ ].filter(no_react_1.NoReactInternals.truthy);
1055
+ }, [onSelect, previewServerState.type, target, updateResolvedStackTrace]);
1056
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1057
+ jsx_runtime_1.jsx(SelectedOutlinePolygon, { allDragTargets: allDragTargets, contextMenuValues: emptyContextMenuValues, dragging: dragging, hovered: hovered, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, scale: scale, target: target }), (target === null || target === void 0 ? void 0 : target.selected) || hovered
1058
+ ? ['top', 'right', 'bottom', 'left'].map((edge) => (jsx_runtime_1.jsx(SelectedOutlineScaleEdgeLine, { allScaleDragTargets: allScaleDragTargets, contextMenuValues: emptyContextMenuValues, dragging: dragging, edge: edge, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, target: target }, edge)))
1059
+ : null, (target === null || target === void 0 ? void 0 : target.selected)
1060
+ ? (() => {
1061
+ const { uvHandles } = target;
1062
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1063
+ jsx_runtime_1.jsx(SelectedUvHandleConnectionLines, { handles: uvHandles, outline: outline }), uvHandles.map((handle) => (jsx_runtime_1.jsx(SelectedUvHandleCircle, { handle: handle, onDraggingChange: onDraggingChange, outline: outline }, `${handle.effectIndex}-${handle.fieldKey}`)))] }));
1064
+ })()
1065
+ : null] }));
1066
+ };
609
1067
  const SelectedOutlineOverlay = ({ scale }) => {
610
- const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
1068
+ const { selectedItems, selectItem } = (0, TimelineSelection_1.useTimelineSelection)();
611
1069
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
612
1070
  const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
613
1071
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
614
1072
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
615
- const { getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
1073
+ const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
1074
+ const { getScaleLockState } = (0, react_1.useContext)(scale_lock_1.ScaleLockContext);
1075
+ const { editorShowOutlines } = (0, react_1.useContext)(editor_outlines_1.EditorShowOutlinesContext);
616
1076
  const [outlines, setOutlines] = (0, react_1.useState)([]);
1077
+ const [hoveredOutlineKey, setHoveredOutlineKey] = (0, react_1.useState)(null);
1078
+ const [draggingOutline, setDraggingOutline] = (0, react_1.useState)(false);
617
1079
  const overlayRef = (0, react_1.useRef)(null);
618
- const selectedOutlineTargets = (0, react_1.useMemo)(() => {
619
- if (!TimelineSelection_1.ENABLE_OUTLINES) {
1080
+ const onDraggingChange = react_1.default.useCallback((dragging) => {
1081
+ setDraggingOutline(dragging);
1082
+ if (dragging) {
1083
+ setHoveredOutlineKey(null);
1084
+ }
1085
+ }, []);
1086
+ const outlineTargets = (0, react_1.useMemo)(() => {
1087
+ if (!TimelineSelection_1.ENABLE_OUTLINES || !editorShowOutlines) {
620
1088
  return [];
621
1089
  }
1090
+ const selectedSequenceKeys = getSelectedSequenceKeys(selectedItems);
622
1091
  const selectedEffectsBySequenceKey = (0, exports.getSelectedEffectFieldsBySequenceKey)(selectedItems);
623
1092
  const clientId = previewServerState.type === 'connected'
624
1093
  ? previewServerState.clientId
625
1094
  : null;
626
- return getSequencesWithSelectedOutlines({
627
- selectedItems,
1095
+ return (0, exports.getSequencesWithSelectableOutlines)({
628
1096
  sequences,
629
1097
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
630
- }).map(({ key, nodePathInfo, sequence }) => {
631
- var _a;
1098
+ }).map(({ key, keyframeDisplayOffset, nodePathInfo, sequence }) => {
1099
+ var _a, _b;
632
1100
  if (sequence.refForOutline === null) {
633
1101
  throw new Error('Expected sequence to have a ref for outline');
634
1102
  }
1103
+ const selected = selectedSequenceKeys.has(key);
635
1104
  const nodePath = nodePathInfo.sequenceSubscriptionKey;
636
1105
  const { controls } = sequence;
637
1106
  const fieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[translateFieldKey];
638
1107
  const codeValue = (_a = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _a === void 0 ? void 0 : _a[translateFieldKey];
1108
+ const scaleFieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[scaleFieldKey];
1109
+ const scaleCodeValue = (_b = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _b === void 0 ? void 0 : _b[scaleFieldKey];
1110
+ const canDragStatus = (codeValue === null || codeValue === void 0 ? void 0 : codeValue.status) === 'static' ||
1111
+ ((codeValue === null || codeValue === void 0 ? void 0 : codeValue.status) === 'keyframed' &&
1112
+ codeValue.interpolationFunction === 'interpolate');
639
1113
  const canDrag = previewServerState.type === 'connected' &&
640
1114
  controls !== null &&
641
1115
  (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) === 'translate' &&
642
- (codeValue === null || codeValue === void 0 ? void 0 : codeValue.canUpdate) === true;
1116
+ canDragStatus;
1117
+ const canScaleDrag = previewServerState.type === 'connected' &&
1118
+ controls !== null &&
1119
+ (scaleFieldSchema === null || scaleFieldSchema === void 0 ? void 0 : scaleFieldSchema.type) === 'scale' &&
1120
+ (scaleCodeValue === null || scaleCodeValue === void 0 ? void 0 : scaleCodeValue.status) === 'static';
643
1121
  return {
644
1122
  key,
1123
+ nodePathInfo,
645
1124
  ref: sequence.refForOutline,
1125
+ selected,
1126
+ selection: { type: 'sequence', nodePathInfo },
1127
+ sequence,
646
1128
  drag: canDrag
647
1129
  ? {
648
1130
  codeValue,
649
1131
  clientId: previewServerState.clientId,
650
1132
  fieldDefault: fieldSchema.default,
1133
+ keyframeDisplayOffset,
651
1134
  nodePath,
652
1135
  schema: controls.schema,
653
1136
  }
654
1137
  : null,
655
- uvHandles: getSelectedUvHandles({
656
- codeValues,
657
- clientId,
658
- getEffectDragOverrides,
659
- nodePath,
660
- selectedEffects: selectedEffectsBySequenceKey.get(key),
661
- sequence,
662
- }),
1138
+ scaleDrag: canScaleDrag
1139
+ ? {
1140
+ codeValue: scaleCodeValue,
1141
+ clientId: previewServerState.clientId,
1142
+ fieldDefault: scaleFieldSchema.default,
1143
+ fieldSchema: scaleFieldSchema,
1144
+ linked: getScaleLockState({
1145
+ nodePath,
1146
+ fieldKey: scaleFieldKey,
1147
+ defaultValue: (() => {
1148
+ var _a;
1149
+ const dragOverrideValue = ((_a = getDragOverrides(nodePath)) !== null && _a !== void 0 ? _a : {})[scaleFieldKey];
1150
+ const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
1151
+ codeValue: scaleCodeValue,
1152
+ dragOverrideValue,
1153
+ defaultValue: scaleFieldSchema.default,
1154
+ shouldResortToDefaultValueIfUndefined: true,
1155
+ });
1156
+ const [x, y] = no_react_1.NoReactInternals.parseScaleValue(effectiveValue);
1157
+ return x === y;
1158
+ })(),
1159
+ }),
1160
+ nodePath,
1161
+ schema: controls.schema,
1162
+ }
1163
+ : null,
1164
+ uvHandles: selected
1165
+ ? getSelectedUvHandles({
1166
+ codeValues,
1167
+ clientId,
1168
+ getEffectDragOverrides,
1169
+ nodePath,
1170
+ selectedEffects: selectedEffectsBySequenceKey.get(key),
1171
+ sequence,
1172
+ })
1173
+ : [],
663
1174
  };
664
1175
  });
665
1176
  }, [
666
1177
  codeValues,
1178
+ getDragOverrides,
667
1179
  getEffectDragOverrides,
1180
+ getScaleLockState,
1181
+ editorShowOutlines,
668
1182
  overrideIdToNodePathMappings,
669
1183
  previewServerState,
670
1184
  selectedItems,
671
1185
  sequences,
672
1186
  ]);
1187
+ (0, react_1.useEffect)(() => {
1188
+ if (hoveredOutlineKey !== null &&
1189
+ !outlineTargets.some((target) => target.key === hoveredOutlineKey)) {
1190
+ setHoveredOutlineKey(null);
1191
+ }
1192
+ }, [hoveredOutlineKey, outlineTargets]);
673
1193
  const targetsByKey = (0, react_1.useMemo)(() => {
674
- return new Map(selectedOutlineTargets.map((target) => [target.key, target]));
675
- }, [selectedOutlineTargets]);
1194
+ return new Map(outlineTargets.map((target) => [target.key, target]));
1195
+ }, [outlineTargets]);
676
1196
  const allDragTargets = (0, react_1.useMemo)(() => {
677
- return selectedOutlineTargets.flatMap((target) => target.drag === null ? [] : [target.drag]);
678
- }, [selectedOutlineTargets]);
1197
+ return outlineTargets.flatMap((target) => target.selected && target.drag !== null ? [target.drag] : []);
1198
+ }, [outlineTargets]);
1199
+ const allScaleDragTargets = (0, react_1.useMemo)(() => {
1200
+ return outlineTargets.flatMap((target) => target.selected && target.scaleDrag !== null ? [target.scaleDrag] : []);
1201
+ }, [outlineTargets]);
679
1202
  (0, react_1.useEffect)(() => {
680
- if (selectedOutlineTargets.length === 0) {
1203
+ if (outlineTargets.length === 0) {
681
1204
  setOutlines((prevOutlines) => prevOutlines.length === 0 ? prevOutlines : []);
682
1205
  return;
683
1206
  }
684
1207
  let animationFrame = null;
685
1208
  const updateOutlines = () => {
686
1209
  if (overlayRef.current) {
687
- const nextOutlines = measureOutlines(overlayRef.current, selectedOutlineTargets);
1210
+ const nextOutlines = measureOutlines(overlayRef.current, outlineTargets);
688
1211
  setOutlines((prevOutlines) => outlinesAreEqual(prevOutlines, nextOutlines)
689
1212
  ? prevOutlines
690
1213
  : nextOutlines);
@@ -697,14 +1220,10 @@ const SelectedOutlineOverlay = ({ scale }) => {
697
1220
  cancelAnimationFrame(animationFrame);
698
1221
  }
699
1222
  };
700
- }, [selectedOutlineTargets]);
701
- if (selectedOutlineTargets.length === 0) {
1223
+ }, [outlineTargets]);
1224
+ if (outlineTargets.length === 0) {
702
1225
  return null;
703
1226
  }
704
- return (jsx_runtime_1.jsx("svg", { ref: overlayRef, style: outlineContainer, width: "100%", height: "100%", "aria-hidden": "true", children: outlines.map((outline) => {
705
- var _a;
706
- return (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [
707
- jsx_runtime_1.jsx(SelectedOutlinePolygon, { allDragTargets: allDragTargets, outline: outline, scale: scale, target: targetsByKey.get(outline.key) }), (_a = targetsByKey.get(outline.key)) === null || _a === void 0 ? void 0 : _a.uvHandles.map((handle) => (jsx_runtime_1.jsx(SelectedUvHandleCircle, { handle: handle, outline: outline }, `${handle.effectIndex}-${handle.fieldKey}`)))] }, outline.key));
708
- }) }));
1227
+ return (jsx_runtime_1.jsx("svg", { ref: overlayRef, style: outlineContainer, width: "100%", height: "100%", "aria-hidden": "true", children: outlines.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineElement, { allDragTargets: allDragTargets, allScaleDragTargets: allScaleDragTargets, dragging: draggingOutline, hovered: hoveredOutlineKey === outline.key, outline: outline, onDraggingChange: onDraggingChange, onHoverChange: setHoveredOutlineKey, onSelect: selectItem, scale: scale, target: targetsByKey.get(outline.key) }, outline.key))) }));
709
1228
  };
710
1229
  exports.SelectedOutlineOverlay = SelectedOutlineOverlay;