@remotion/studio 4.0.471 → 4.0.472

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 (91) hide show
  1. package/dist/components/AssetSelector.js +10 -1
  2. package/dist/components/Canvas.js +98 -0
  3. package/dist/components/CompositionSelectorItem.d.ts +1 -0
  4. package/dist/components/CompositionSelectorItem.js +12 -4
  5. package/dist/components/ContextMenu.js +54 -46
  6. package/dist/components/Editor.js +14 -6
  7. package/dist/components/Modals.js +3 -1
  8. package/dist/components/NewComposition/CodemodFooter.js +2 -2
  9. package/dist/components/NewComposition/DeleteFolder.d.ts +6 -0
  10. package/dist/components/NewComposition/DeleteFolder.js +39 -0
  11. package/dist/components/NewComposition/RenameFolder.d.ts +6 -0
  12. package/dist/components/NewComposition/RenameFolder.js +60 -0
  13. package/dist/components/SelectedOutlineOverlay.d.ts +81 -4
  14. package/dist/components/SelectedOutlineOverlay.js +405 -54
  15. package/dist/components/Splitter/SplitterContainer.js +9 -0
  16. package/dist/components/Splitter/SplitterHandle.js +63 -70
  17. package/dist/components/Timeline/Timeline.js +47 -2
  18. package/dist/components/Timeline/TimelineArrayField.d.ts +9 -0
  19. package/dist/components/Timeline/TimelineArrayField.js +210 -0
  20. package/dist/components/Timeline/TimelineBooleanField.d.ts +2 -2
  21. package/dist/components/Timeline/TimelineBooleanField.js +2 -2
  22. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +20 -0
  23. package/dist/components/Timeline/TimelineClipboardKeybindings.js +265 -0
  24. package/dist/components/Timeline/TimelineColorField.d.ts +2 -2
  25. package/dist/components/Timeline/TimelineColorField.js +2 -8
  26. package/dist/components/Timeline/TimelineEffectItem.js +2 -2
  27. package/dist/components/Timeline/TimelineEffectPropItem.js +95 -25
  28. package/dist/components/Timeline/TimelineEnumField.d.ts +2 -2
  29. package/dist/components/Timeline/TimelineEnumField.js +3 -3
  30. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +4 -3
  31. package/dist/components/Timeline/TimelineKeyframeControls.js +37 -23
  32. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +7 -2
  33. package/dist/components/Timeline/TimelineKeyframedValue.js +22 -8
  34. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -0
  35. package/dist/components/Timeline/TimelineLayerEye.js +8 -3
  36. package/dist/components/Timeline/TimelineNumberField.d.ts +2 -2
  37. package/dist/components/Timeline/TimelineNumberField.js +7 -11
  38. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +17 -0
  39. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +53 -0
  40. package/dist/components/Timeline/TimelineRotationField.d.ts +2 -2
  41. package/dist/components/Timeline/TimelineRotationField.js +41 -24
  42. package/dist/components/Timeline/TimelineRowChrome.js +8 -7
  43. package/dist/components/Timeline/TimelineScaleField.d.ts +20 -0
  44. package/dist/components/Timeline/TimelineScaleField.js +314 -0
  45. package/dist/components/Timeline/TimelineSchemaField.d.ts +3 -2
  46. package/dist/components/Timeline/TimelineSchemaField.js +8 -42
  47. package/dist/components/Timeline/TimelineSelection.js +3 -2
  48. package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
  49. package/dist/components/Timeline/TimelineSequence.js +51 -10
  50. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  51. package/dist/components/Timeline/TimelineSequenceItem.js +7 -7
  52. package/dist/components/Timeline/TimelineSequencePropItem.js +82 -21
  53. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +58 -0
  54. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +528 -0
  55. package/dist/components/Timeline/TimelineTrack.js +1 -1
  56. package/dist/components/Timeline/TimelineTranslateField.d.ts +2 -2
  57. package/dist/components/Timeline/TimelineTranslateField.js +21 -25
  58. package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +2 -2
  59. package/dist/components/Timeline/TimelineUvCoordinateField.js +20 -26
  60. package/dist/components/Timeline/call-add-keyframe.js +2 -0
  61. package/dist/components/Timeline/get-node-keyframes.d.ts +5 -2
  62. package/dist/components/Timeline/get-node-keyframes.js +38 -5
  63. package/dist/components/Timeline/get-timeline-keyframes.js +4 -4
  64. package/dist/components/Timeline/reset-selected-timeline-props.js +19 -6
  65. package/dist/components/Timeline/timeline-field-utils.d.ts +1 -0
  66. package/dist/components/Timeline/timeline-field-utils.js +5 -1
  67. package/dist/components/Timeline/timeline-translate-utils.js +6 -2
  68. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -0
  69. package/dist/components/TopPanel.d.ts +1 -1
  70. package/dist/components/folder-menu-items.d.ts +12 -0
  71. package/dist/components/folder-menu-items.js +147 -0
  72. package/dist/components/import-assets.d.ts +6 -0
  73. package/dist/components/import-assets.js +157 -0
  74. package/dist/esm/{chunk-z0z9d4r0.js → chunk-48grt472.js} +8936 -5886
  75. package/dist/esm/internals.mjs +8936 -5886
  76. package/dist/esm/previewEntry.mjs +8748 -5698
  77. package/dist/esm/renderEntry.mjs +1 -1
  78. package/dist/helpers/calculate-timeline.js +7 -3
  79. package/dist/helpers/create-folder-tree.js +1 -0
  80. package/dist/helpers/detect-file-type.d.ts +69 -0
  81. package/dist/helpers/detect-file-type.js +278 -0
  82. package/dist/helpers/get-folder-id.d.ts +4 -0
  83. package/dist/helpers/get-folder-id.js +7 -0
  84. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +2 -0
  85. package/dist/helpers/timeline-layout.js +5 -1
  86. package/dist/helpers/validate-folder-rename.d.ts +6 -0
  87. package/dist/helpers/validate-folder-rename.js +19 -0
  88. package/dist/state/modals.d.ts +10 -0
  89. package/dist/state/scale-lock.d.ts +18 -0
  90. package/dist/state/scale-lock.js +59 -0
  91. package/package.json +10 -10
@@ -33,21 +33,26 @@ 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.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");
43
44
  const get_box_quads_ponyfill_1 = require("../helpers/get-box-quads-ponyfill");
45
+ const scale_lock_1 = require("../state/scale-lock");
44
46
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
47
+ const call_add_keyframe_1 = require("./Timeline/call-add-keyframe");
45
48
  const save_effect_prop_1 = require("./Timeline/save-effect-prop");
46
49
  const save_sequence_prop_1 = require("./Timeline/save-sequence-prop");
47
50
  const timeline_field_utils_1 = require("./Timeline/timeline-field-utils");
48
51
  const timeline_translate_utils_1 = require("./Timeline/timeline-translate-utils");
52
+ const TimelineScaleField_1 = require("./Timeline/TimelineScaleField");
49
53
  const TimelineSelection_1 = require("./Timeline/TimelineSelection");
50
54
  const translateFieldKey = 'style.translate';
55
+ const scaleFieldKey = 'style.scale';
51
56
  const outlineContainer = {
52
57
  position: 'absolute',
53
58
  inset: 0,
@@ -78,6 +83,15 @@ const mixPoint = (from, to, progress) => {
78
83
  y: mix(from.y, to.y, progress),
79
84
  };
80
85
  };
86
+ const midpoint = (from, to) => {
87
+ return mixPoint(from, to, 0.5);
88
+ };
89
+ const dot = (left, right) => {
90
+ return left.x * right.x + left.y * right.y;
91
+ };
92
+ const vectorLength = (vector) => {
93
+ return Math.hypot(vector.x, vector.y);
94
+ };
81
95
  const getBilinearUvHandlePosition = (points, uv) => {
82
96
  const [tl, tr, br, bl] = points;
83
97
  const top = mixPoint(tl, tr, uv[0]);
@@ -249,6 +263,11 @@ const getElementOutlinePoints = (element, containerRect) => {
249
263
  const getSelectedSequenceKeys = (selectedItems) => {
250
264
  return new Set(selectedItems.map((item) => (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(item.nodePathInfo)));
251
265
  };
266
+ const getOutlineSelectionInteraction = ({ shiftKey, metaKey, ctrlKey, }) => ({
267
+ shiftKey,
268
+ toggleKey: metaKey || ctrlKey,
269
+ });
270
+ exports.getOutlineSelectionInteraction = getOutlineSelectionInteraction;
252
271
  const getSelectedEffectFieldsBySequenceKey = (selectedItems) => {
253
272
  var _a, _b;
254
273
  const selectedEffects = new Map();
@@ -270,11 +289,7 @@ const getSelectedEffectFieldsBySequenceKey = (selectedItems) => {
270
289
  return selectedEffects;
271
290
  };
272
291
  exports.getSelectedEffectFieldsBySequenceKey = getSelectedEffectFieldsBySequenceKey;
273
- const getSequencesWithSelectedOutlines = ({ selectedItems, sequences, overrideIdsToNodePaths, }) => {
274
- const selectedSequenceKeys = getSelectedSequenceKeys(selectedItems);
275
- if (selectedSequenceKeys.size === 0) {
276
- return [];
277
- }
292
+ const getSequencesWithSelectableOutlines = ({ sequences, overrideIdsToNodePaths, }) => {
278
293
  return (0, calculate_timeline_1.calculateTimeline)({
279
294
  sequences: [...sequences],
280
295
  overrideIdsToNodePaths,
@@ -283,20 +298,24 @@ const getSequencesWithSelectedOutlines = ({ selectedItems, sequences, overrideId
283
298
  if (track.nodePathInfo === null) {
284
299
  return false;
285
300
  }
286
- return selectedSequenceKeys.has((0, TimelineSelection_1.getTimelineSequenceSelectionKey)(track.nodePathInfo));
301
+ return track.nodePathInfo.auxiliaryKeys.length === 0;
287
302
  })
288
303
  .filter((track) => track.sequence.refForOutline !== null)
304
+ .sort((a, b) => a.depth - b.depth)
289
305
  .map((track) => {
290
306
  if (track.nodePathInfo === null) {
291
307
  throw new Error('Expected selected outline to have a node path');
292
308
  }
293
309
  return {
310
+ depth: track.depth,
311
+ keyframeDisplayOffset: track.keyframeDisplayOffset,
294
312
  key: (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(track.nodePathInfo),
295
313
  nodePathInfo: track.nodePathInfo,
296
314
  sequence: track.sequence,
297
315
  };
298
316
  });
299
317
  };
318
+ exports.getSequencesWithSelectableOutlines = getSequencesWithSelectableOutlines;
300
319
  const getSelectedUvHandles = ({ codeValues, clientId, getEffectDragOverrides, nodePath, selectedEffects, sequence, }) => {
301
320
  if (clientId === null || selectedEffects === undefined) {
302
321
  return [];
@@ -317,12 +336,12 @@ const getSelectedUvHandles = ({ codeValues, clientId, getEffectDragOverrides, no
317
336
  }
318
337
  const dragOverrides = getEffectDragOverrides(nodePath, effectIndex);
319
338
  const activeSchema = remotion_1.Internals.flattenActiveSchema(effect.schema, (key) => {
320
- const dragOverride = dragOverrides[key];
339
+ const dragOverride = remotion_1.Internals.getStaticDragOverrideValue(dragOverrides[key]);
321
340
  if (dragOverride !== undefined) {
322
341
  return dragOverride;
323
342
  }
324
343
  const propStatus = effectStatus.props[key];
325
- if (!(propStatus === null || propStatus === void 0 ? void 0 : propStatus.canUpdate)) {
344
+ if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static') {
326
345
  return undefined;
327
346
  }
328
347
  return propStatus.codeValue;
@@ -333,7 +352,7 @@ const getSelectedUvHandles = ({ codeValues, clientId, getEffectDragOverrides, no
333
352
  continue;
334
353
  }
335
354
  const propStatus = effectStatus.props[fieldKey];
336
- if (!(propStatus === null || propStatus === void 0 ? void 0 : propStatus.canUpdate)) {
355
+ if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static') {
337
356
  continue;
338
357
  }
339
358
  const dragOverrideValue = dragOverrides[fieldKey];
@@ -395,14 +414,16 @@ const outlinesAreEqual = (a, b) => {
395
414
  }
396
415
  return true;
397
416
  };
398
- const getSelectedOutlineDragStates = ({ dragTargets, getDragOverrides, }) => {
417
+ const getSelectedOutlineDragStates = ({ dragTargets, getDragOverrides, timelinePosition, }) => {
399
418
  return dragTargets.map((target) => {
400
419
  var _a;
401
420
  const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[translateFieldKey];
421
+ const sourceFrame = timelinePosition - target.keyframeDisplayOffset;
402
422
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
403
423
  codeValue: target.codeValue,
404
424
  dragOverrideValue,
405
425
  defaultValue: target.fieldDefault,
426
+ frame: sourceFrame,
406
427
  shouldResortToDefaultValueIfUndefined: true,
407
428
  });
408
429
  const [startX, startY] = (0, timeline_translate_utils_1.parseTranslate)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px'));
@@ -411,6 +432,7 @@ const getSelectedOutlineDragStates = ({ dragTargets, getDragOverrides, }) => {
411
432
  ? JSON.stringify(target.fieldDefault)
412
433
  : null,
413
434
  key: remotion_1.Internals.makeSequencePropsSubscriptionKey(target.nodePath),
435
+ sourceFrame,
414
436
  startX,
415
437
  startY,
416
438
  target,
@@ -425,13 +447,134 @@ const getSelectedOutlineDragValues = ({ dragStates, deltaX, deltaY, }) => {
425
447
  };
426
448
  exports.getSelectedOutlineDragValues = getSelectedOutlineDragValues;
427
449
  const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
450
+ const changes = [];
451
+ for (const dragState of dragStates) {
452
+ const value = lastValues.get(dragState.key);
453
+ if (value === undefined) {
454
+ continue;
455
+ }
456
+ if (dragState.target.codeValue.status === 'keyframed') {
457
+ const startValue = (0, timeline_translate_utils_1.serializeTranslate)(dragState.startX, dragState.startY);
458
+ if (value === startValue) {
459
+ continue;
460
+ }
461
+ changes.push({
462
+ type: 'keyframed',
463
+ fileName: dragState.target.nodePath.absolutePath,
464
+ nodePath: dragState.target.nodePath,
465
+ fieldKey: translateFieldKey,
466
+ sourceFrame: dragState.sourceFrame,
467
+ value,
468
+ schema: dragState.target.schema,
469
+ clientId: dragState.target.clientId,
470
+ });
471
+ continue;
472
+ }
473
+ const stringifiedValue = JSON.stringify(value);
474
+ const shouldSave = value !== dragState.target.codeValue.codeValue &&
475
+ !(dragState.defaultValue === stringifiedValue &&
476
+ dragState.target.codeValue.codeValue === undefined);
477
+ if (!shouldSave) {
478
+ continue;
479
+ }
480
+ changes.push({
481
+ type: 'static',
482
+ fileName: dragState.target.nodePath.absolutePath,
483
+ nodePath: dragState.target.nodePath,
484
+ fieldKey: translateFieldKey,
485
+ value,
486
+ defaultValue: dragState.defaultValue,
487
+ schema: dragState.target.schema,
488
+ });
489
+ }
490
+ return changes;
491
+ };
492
+ exports.getSelectedOutlineDragChanges = getSelectedOutlineDragChanges;
493
+ const getSelectedOutlineScaleEdgeInfo = (points, edge) => {
494
+ const [tl, tr, br, bl] = points;
495
+ const edgePoints = {
496
+ top: { start: tl, end: tr, oppositeStart: bl, oppositeEnd: br },
497
+ right: { start: tr, end: br, oppositeStart: tl, oppositeEnd: bl },
498
+ bottom: { start: bl, end: br, oppositeStart: tl, oppositeEnd: tr },
499
+ left: { start: tl, end: bl, oppositeStart: tr, oppositeEnd: br },
500
+ }[edge];
501
+ const edgeMidpoint = midpoint(edgePoints.start, edgePoints.end);
502
+ const oppositeMidpoint = midpoint(edgePoints.oppositeStart, edgePoints.oppositeEnd);
503
+ const outward = vectorBetween(oppositeMidpoint, edgeMidpoint);
504
+ const length = vectorLength(outward);
505
+ if (length < 0.001) {
506
+ return null;
507
+ }
508
+ return {
509
+ axis: edge === 'left' || edge === 'right' ? 'x' : 'y',
510
+ cursor: edge === 'left' || edge === 'right' ? 'ew-resize' : 'ns-resize',
511
+ end: edgePoints.end,
512
+ extent: length,
513
+ normal: { x: outward.x / length, y: outward.y / length },
514
+ start: edgePoints.start,
515
+ };
516
+ };
517
+ exports.getSelectedOutlineScaleEdgeInfo = getSelectedOutlineScaleEdgeInfo;
518
+ const getSelectedOutlineScaleDragStates = ({ dragTargets, getDragOverrides, }) => {
519
+ return dragTargets.map((target) => {
520
+ var _a;
521
+ const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[scaleFieldKey];
522
+ const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
523
+ codeValue: target.codeValue,
524
+ dragOverrideValue,
525
+ defaultValue: target.fieldDefault,
526
+ shouldResortToDefaultValueIfUndefined: true,
527
+ });
528
+ const [startX, startY, startZ] = no_react_1.NoReactInternals.parseScaleValue(effectiveValue);
529
+ return {
530
+ defaultValue: target.fieldDefault !== undefined
531
+ ? JSON.stringify(target.fieldDefault)
532
+ : null,
533
+ key: remotion_1.Internals.makeSequencePropsSubscriptionKey(target.nodePath),
534
+ startX,
535
+ startY,
536
+ startZ,
537
+ target,
538
+ };
539
+ });
540
+ };
541
+ exports.getSelectedOutlineScaleDragStates = getSelectedOutlineScaleDragStates;
542
+ const getSelectedOutlineScaleDragValues = ({ axis, dragStates, scaleFactor, }) => {
543
+ return new Map(dragStates.map((dragState) => {
544
+ var _a, _b;
545
+ const min = (_a = dragState.target.fieldSchema.min) !== null && _a !== void 0 ? _a : -Infinity;
546
+ const max = (_b = dragState.target.fieldSchema.max) !== null && _b !== void 0 ? _b : Infinity;
547
+ const baseX = dragState.startX;
548
+ const baseY = dragState.startY;
549
+ const newValue = (axis === 'x' ? baseX : baseY) * scaleFactor;
550
+ const [x, y] = dragState.target.linked
551
+ ? (0, TimelineScaleField_1.getLinkedScale)({
552
+ axis,
553
+ newValue,
554
+ baseX,
555
+ baseY,
556
+ min,
557
+ max,
558
+ })
559
+ : axis === 'x'
560
+ ? [clamp(newValue, min, max), baseY]
561
+ : [baseX, clamp(newValue, min, max)];
562
+ return [
563
+ dragState.key,
564
+ no_react_1.NoReactInternals.serializeScaleValue([x, y, dragState.startZ]),
565
+ ];
566
+ }));
567
+ };
568
+ exports.getSelectedOutlineScaleDragValues = getSelectedOutlineScaleDragValues;
569
+ const getSelectedOutlineScaleDragChanges = ({ dragStates, lastValues, }) => {
428
570
  return dragStates.flatMap((dragState) => {
429
571
  const value = lastValues.get(dragState.key);
430
572
  if (value === undefined) {
431
573
  return [];
432
574
  }
433
575
  const stringifiedValue = JSON.stringify(value);
434
- const shouldSave = value !== dragState.target.codeValue.codeValue &&
576
+ const shouldSave = stringifiedValue !==
577
+ JSON.stringify(dragState.target.codeValue.codeValue) &&
435
578
  !(dragState.defaultValue === stringifiedValue &&
436
579
  dragState.target.codeValue.codeValue === undefined);
437
580
  if (!shouldSave) {
@@ -441,7 +584,7 @@ const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
441
584
  {
442
585
  fileName: dragState.target.nodePath.absolutePath,
443
586
  nodePath: dragState.target.nodePath,
444
- fieldKey: translateFieldKey,
587
+ fieldKey: scaleFieldKey,
445
588
  value,
446
589
  defaultValue: dragState.defaultValue,
447
590
  schema: dragState.target.schema,
@@ -449,29 +592,48 @@ const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
449
592
  ];
450
593
  });
451
594
  };
452
- exports.getSelectedOutlineDragChanges = getSelectedOutlineDragChanges;
595
+ exports.getSelectedOutlineScaleDragChanges = getSelectedOutlineScaleDragChanges;
453
596
  const clearSelectedOutlineDragOverrides = ({ clearDragOverrides, dragStates, }) => {
454
597
  for (const dragState of dragStates) {
455
598
  clearDragOverrides(dragState.target.nodePath);
456
599
  }
457
600
  };
458
- const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
459
- var _a;
601
+ const clearSelectedOutlineScaleDragOverrides = ({ clearDragOverrides, dragStates, }) => {
602
+ for (const dragState of dragStates) {
603
+ clearDragOverrides(dragState.target.nodePath);
604
+ }
605
+ };
606
+ const SelectedOutlinePolygon = ({ allDragTargets, hovered, outline, onHoverChange, onSelect, scale, target, }) => {
607
+ var _a, _b;
460
608
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
461
609
  const { setCodeValues, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
610
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
611
+ const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
612
+ timelinePositionRef.current = timelinePosition;
462
613
  const points = (0, react_1.useMemo)(() => outline.points.map(pointToString).join(' '), [outline.points]);
463
614
  const drag = (_a = target === null || target === void 0 ? void 0 : target.drag) !== null && _a !== void 0 ? _a : null;
615
+ const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
616
+ const visible = selected || hovered;
464
617
  const onPointerDown = react_1.default.useCallback((event) => {
465
- if (event.button !== 0 || drag === null) {
618
+ if (event.button !== 0 || target === undefined) {
466
619
  return;
467
620
  }
468
621
  event.preventDefault();
469
622
  event.stopPropagation();
623
+ const interaction = (0, exports.getOutlineSelectionInteraction)(event);
624
+ const shouldUpdateSelection = !selected || interaction.shiftKey || interaction.toggleKey;
625
+ if (shouldUpdateSelection) {
626
+ onSelect(target.selection, interaction);
627
+ }
628
+ if (drag === null || interaction.shiftKey || interaction.toggleKey) {
629
+ return;
630
+ }
470
631
  const startPointerX = event.clientX;
471
632
  const startPointerY = event.clientY;
472
633
  const dragStates = getSelectedOutlineDragStates({
473
- dragTargets: allDragTargets,
634
+ dragTargets: selected ? allDragTargets : [drag],
474
635
  getDragOverrides,
636
+ timelinePosition: timelinePositionRef.current,
475
637
  });
476
638
  let lastValues = new Map();
477
639
  const onPointerMove = (moveEvent) => {
@@ -486,7 +648,16 @@ const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
486
648
  if (value === undefined) {
487
649
  throw new Error('Expected drag value to be available');
488
650
  }
489
- setDragOverrides(dragState.target.nodePath, translateFieldKey, value);
651
+ if (dragState.target.codeValue.status === 'keyframed') {
652
+ setDragOverrides(dragState.target.nodePath, translateFieldKey, remotion_1.Internals.makeKeyframedDragOverride({
653
+ status: dragState.target.codeValue,
654
+ frame: dragState.sourceFrame,
655
+ value,
656
+ }));
657
+ }
658
+ else {
659
+ setDragOverrides(dragState.target.nodePath, translateFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
660
+ }
490
661
  }
491
662
  };
492
663
  const onPointerUp = () => {
@@ -501,13 +672,29 @@ const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
501
672
  clearSelectedOutlineDragOverrides({ clearDragOverrides, dragStates });
502
673
  return;
503
674
  }
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
- })
675
+ const staticChanges = changes.filter((change) => change.type === 'static');
676
+ const keyframedChanges = changes.filter((change) => change.type === 'keyframed');
677
+ Promise.all([
678
+ staticChanges.length > 0
679
+ ? (0, save_sequence_prop_1.saveSequenceProps)({
680
+ changes: staticChanges,
681
+ setCodeValues,
682
+ clientId: drag.clientId,
683
+ undoLabel: changes.length > 1 ? 'Move selected sequences' : null,
684
+ redoLabel: changes.length > 1 ? 'Move selected sequences back' : null,
685
+ })
686
+ : Promise.resolve(),
687
+ ...keyframedChanges.map((change) => (0, call_add_keyframe_1.callAddSequenceKeyframe)({
688
+ fileName: change.fileName,
689
+ nodePath: change.nodePath,
690
+ fieldKey: change.fieldKey,
691
+ sourceFrame: change.sourceFrame,
692
+ value: change.value,
693
+ schema: change.schema,
694
+ setCodeValues,
695
+ clientId: change.clientId,
696
+ })),
697
+ ])
511
698
  .catch((err) => {
512
699
  (0, NotificationCenter_1.showNotification)(`Could not save sequence props: ${err instanceof Error ? err.message : String(err)}`, 4000);
513
700
  })
@@ -523,11 +710,114 @@ const SelectedOutlinePolygon = ({ allDragTargets, outline, scale, target }) => {
523
710
  clearDragOverrides,
524
711
  drag,
525
712
  getDragOverrides,
713
+ onSelect,
526
714
  scale,
715
+ selected,
527
716
  setCodeValues,
528
717
  setDragOverrides,
718
+ target,
529
719
  ]);
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 }));
720
+ return (jsx_runtime_1.jsx("polygon", { points: points, fill: "transparent", stroke: colors_1.BLUE, strokeOpacity: visible ? 1 : 0, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: target === undefined ? undefined : 'all', onPointerEnter: () => onHoverChange(outline.key), onPointerLeave: () => onHoverChange(null), onPointerDown: onPointerDown }));
721
+ };
722
+ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, edge, outline, onHoverChange, onSelect, target, }) => {
723
+ var _a, _b;
724
+ const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
725
+ const { setCodeValues, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
726
+ const scaleDrag = (_a = target === null || target === void 0 ? void 0 : target.scaleDrag) !== null && _a !== void 0 ? _a : null;
727
+ const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
728
+ const edgeInfo = (0, react_1.useMemo)(() => (0, exports.getSelectedOutlineScaleEdgeInfo)(outline.points, edge), [edge, outline.points]);
729
+ const onPointerDown = react_1.default.useCallback((event) => {
730
+ if (event.button !== 0 || scaleDrag === null || edgeInfo === null) {
731
+ return;
732
+ }
733
+ event.preventDefault();
734
+ event.stopPropagation();
735
+ const interaction = (0, exports.getOutlineSelectionInteraction)(event);
736
+ const shouldUpdateSelection = !selected || interaction.shiftKey || interaction.toggleKey;
737
+ if (shouldUpdateSelection && target !== undefined) {
738
+ onSelect(target.selection, interaction);
739
+ }
740
+ if (interaction.shiftKey || interaction.toggleKey) {
741
+ return;
742
+ }
743
+ const startPointer = { x: event.clientX, y: event.clientY };
744
+ const dragStates = (0, exports.getSelectedOutlineScaleDragStates)({
745
+ dragTargets: selected ? allScaleDragTargets : [scaleDrag],
746
+ getDragOverrides,
747
+ });
748
+ let lastValues = new Map();
749
+ const onPointerMove = (moveEvent) => {
750
+ moveEvent.preventDefault();
751
+ const delta = {
752
+ x: moveEvent.clientX - startPointer.x,
753
+ y: moveEvent.clientY - startPointer.y,
754
+ };
755
+ const projectedDelta = dot(delta, edgeInfo.normal);
756
+ const scaleFactor = Math.max(0.001, 1 + projectedDelta / edgeInfo.extent);
757
+ lastValues = (0, exports.getSelectedOutlineScaleDragValues)({
758
+ dragStates,
759
+ axis: edgeInfo.axis,
760
+ scaleFactor,
761
+ });
762
+ for (const dragState of dragStates) {
763
+ const value = lastValues.get(dragState.key);
764
+ if (value === undefined) {
765
+ throw new Error('Expected scale drag value to be available');
766
+ }
767
+ setDragOverrides(dragState.target.nodePath, scaleFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
768
+ }
769
+ };
770
+ const onPointerUp = () => {
771
+ window.removeEventListener('pointermove', onPointerMove);
772
+ window.removeEventListener('pointerup', onPointerUp);
773
+ window.removeEventListener('pointercancel', onPointerUp);
774
+ const changes = (0, exports.getSelectedOutlineScaleDragChanges)({
775
+ dragStates,
776
+ lastValues,
777
+ });
778
+ if (changes.length === 0) {
779
+ clearSelectedOutlineScaleDragOverrides({
780
+ clearDragOverrides,
781
+ dragStates,
782
+ });
783
+ return;
784
+ }
785
+ (0, save_sequence_prop_1.saveSequenceProps)({
786
+ changes,
787
+ setCodeValues,
788
+ clientId: scaleDrag.clientId,
789
+ undoLabel: changes.length > 1 ? 'Scale selected sequences' : null,
790
+ redoLabel: changes.length > 1 ? 'Scale selected sequences back' : null,
791
+ })
792
+ .catch((err) => {
793
+ (0, NotificationCenter_1.showNotification)(`Could not save sequence props: ${err instanceof Error ? err.message : String(err)}`, 4000);
794
+ })
795
+ .finally(() => {
796
+ clearSelectedOutlineScaleDragOverrides({
797
+ clearDragOverrides,
798
+ dragStates,
799
+ });
800
+ });
801
+ };
802
+ window.addEventListener('pointermove', onPointerMove);
803
+ window.addEventListener('pointerup', onPointerUp);
804
+ window.addEventListener('pointercancel', onPointerUp);
805
+ }, [
806
+ allScaleDragTargets,
807
+ clearDragOverrides,
808
+ edgeInfo,
809
+ getDragOverrides,
810
+ onSelect,
811
+ scaleDrag,
812
+ selected,
813
+ setCodeValues,
814
+ setDragOverrides,
815
+ target,
816
+ ]);
817
+ if (scaleDrag === null || edgeInfo === null) {
818
+ return null;
819
+ }
820
+ return (jsx_runtime_1.jsx("line", { 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: () => onHoverChange(outline.key), onPointerLeave: () => onHoverChange(null), onPointerDown: onPointerDown }));
531
821
  };
532
822
  const getSvgPointFromPointerEvent = ({ event, rect, }) => {
533
823
  return {
@@ -560,7 +850,7 @@ const SelectedUvHandleCircle = ({ handle, outline }) => {
560
850
  });
561
851
  const nextValue = constrainUv((0, exports.getUvCoordinateForPoint)(outline.points, point), handle.fieldSchema);
562
852
  lastValue = nextValue;
563
- setEffectDragOverrides(handle.nodePath, handle.effectIndex, handle.fieldKey, nextValue);
853
+ setEffectDragOverrides(handle.nodePath, handle.effectIndex, handle.fieldKey, remotion_1.Internals.makeStaticDragOverride(nextValue));
564
854
  };
565
855
  updateFromPointerEvent(event);
566
856
  const onPointerMove = (moveEvent) => {
@@ -607,84 +897,139 @@ const SelectedUvHandleCircle = ({ handle, outline }) => {
607
897
  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
898
  };
609
899
  const SelectedOutlineOverlay = ({ scale }) => {
610
- const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
900
+ const { selectedItems, selectItem } = (0, TimelineSelection_1.useTimelineSelection)();
611
901
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
612
902
  const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
613
903
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
614
904
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
615
- const { getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
905
+ const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
906
+ const { getScaleLockState } = (0, react_1.useContext)(scale_lock_1.ScaleLockContext);
616
907
  const [outlines, setOutlines] = (0, react_1.useState)([]);
908
+ const [hoveredOutlineKey, setHoveredOutlineKey] = (0, react_1.useState)(null);
617
909
  const overlayRef = (0, react_1.useRef)(null);
618
- const selectedOutlineTargets = (0, react_1.useMemo)(() => {
910
+ const outlineTargets = (0, react_1.useMemo)(() => {
619
911
  if (!TimelineSelection_1.ENABLE_OUTLINES) {
620
912
  return [];
621
913
  }
914
+ const selectedSequenceKeys = getSelectedSequenceKeys(selectedItems);
622
915
  const selectedEffectsBySequenceKey = (0, exports.getSelectedEffectFieldsBySequenceKey)(selectedItems);
623
916
  const clientId = previewServerState.type === 'connected'
624
917
  ? previewServerState.clientId
625
918
  : null;
626
- return getSequencesWithSelectedOutlines({
627
- selectedItems,
919
+ return (0, exports.getSequencesWithSelectableOutlines)({
628
920
  sequences,
629
921
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
630
- }).map(({ key, nodePathInfo, sequence }) => {
631
- var _a;
922
+ }).map(({ key, keyframeDisplayOffset, nodePathInfo, sequence }) => {
923
+ var _a, _b;
632
924
  if (sequence.refForOutline === null) {
633
925
  throw new Error('Expected sequence to have a ref for outline');
634
926
  }
927
+ const selected = selectedSequenceKeys.has(key);
635
928
  const nodePath = nodePathInfo.sequenceSubscriptionKey;
636
929
  const { controls } = sequence;
637
930
  const fieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[translateFieldKey];
638
931
  const codeValue = (_a = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _a === void 0 ? void 0 : _a[translateFieldKey];
932
+ const scaleFieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[scaleFieldKey];
933
+ const scaleCodeValue = (_b = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _b === void 0 ? void 0 : _b[scaleFieldKey];
934
+ const canDragStatus = (codeValue === null || codeValue === void 0 ? void 0 : codeValue.status) === 'static' ||
935
+ ((codeValue === null || codeValue === void 0 ? void 0 : codeValue.status) === 'keyframed' &&
936
+ codeValue.interpolationFunction === 'interpolate');
639
937
  const canDrag = previewServerState.type === 'connected' &&
640
938
  controls !== null &&
641
939
  (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) === 'translate' &&
642
- (codeValue === null || codeValue === void 0 ? void 0 : codeValue.canUpdate) === true;
940
+ canDragStatus;
941
+ const canScaleDrag = previewServerState.type === 'connected' &&
942
+ controls !== null &&
943
+ (scaleFieldSchema === null || scaleFieldSchema === void 0 ? void 0 : scaleFieldSchema.type) === 'scale' &&
944
+ (scaleCodeValue === null || scaleCodeValue === void 0 ? void 0 : scaleCodeValue.status) === 'static';
643
945
  return {
644
946
  key,
947
+ nodePathInfo,
645
948
  ref: sequence.refForOutline,
949
+ selected,
950
+ selection: { type: 'sequence', nodePathInfo },
646
951
  drag: canDrag
647
952
  ? {
648
953
  codeValue,
649
954
  clientId: previewServerState.clientId,
650
955
  fieldDefault: fieldSchema.default,
956
+ keyframeDisplayOffset,
957
+ nodePath,
958
+ schema: controls.schema,
959
+ }
960
+ : null,
961
+ scaleDrag: canScaleDrag
962
+ ? {
963
+ codeValue: scaleCodeValue,
964
+ clientId: previewServerState.clientId,
965
+ fieldDefault: scaleFieldSchema.default,
966
+ fieldSchema: scaleFieldSchema,
967
+ linked: getScaleLockState({
968
+ nodePath,
969
+ fieldKey: scaleFieldKey,
970
+ defaultValue: (() => {
971
+ var _a;
972
+ const dragOverrideValue = ((_a = getDragOverrides(nodePath)) !== null && _a !== void 0 ? _a : {})[scaleFieldKey];
973
+ const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
974
+ codeValue: scaleCodeValue,
975
+ dragOverrideValue,
976
+ defaultValue: scaleFieldSchema.default,
977
+ shouldResortToDefaultValueIfUndefined: true,
978
+ });
979
+ const [x, y] = no_react_1.NoReactInternals.parseScaleValue(effectiveValue);
980
+ return x === y;
981
+ })(),
982
+ }),
651
983
  nodePath,
652
984
  schema: controls.schema,
653
985
  }
654
986
  : null,
655
- uvHandles: getSelectedUvHandles({
656
- codeValues,
657
- clientId,
658
- getEffectDragOverrides,
659
- nodePath,
660
- selectedEffects: selectedEffectsBySequenceKey.get(key),
661
- sequence,
662
- }),
987
+ uvHandles: selected
988
+ ? getSelectedUvHandles({
989
+ codeValues,
990
+ clientId,
991
+ getEffectDragOverrides,
992
+ nodePath,
993
+ selectedEffects: selectedEffectsBySequenceKey.get(key),
994
+ sequence,
995
+ })
996
+ : [],
663
997
  };
664
998
  });
665
999
  }, [
666
1000
  codeValues,
1001
+ getDragOverrides,
667
1002
  getEffectDragOverrides,
1003
+ getScaleLockState,
668
1004
  overrideIdToNodePathMappings,
669
1005
  previewServerState,
670
1006
  selectedItems,
671
1007
  sequences,
672
1008
  ]);
1009
+ (0, react_1.useEffect)(() => {
1010
+ if (hoveredOutlineKey !== null &&
1011
+ !outlineTargets.some((target) => target.key === hoveredOutlineKey)) {
1012
+ setHoveredOutlineKey(null);
1013
+ }
1014
+ }, [hoveredOutlineKey, outlineTargets]);
673
1015
  const targetsByKey = (0, react_1.useMemo)(() => {
674
- return new Map(selectedOutlineTargets.map((target) => [target.key, target]));
675
- }, [selectedOutlineTargets]);
1016
+ return new Map(outlineTargets.map((target) => [target.key, target]));
1017
+ }, [outlineTargets]);
676
1018
  const allDragTargets = (0, react_1.useMemo)(() => {
677
- return selectedOutlineTargets.flatMap((target) => target.drag === null ? [] : [target.drag]);
678
- }, [selectedOutlineTargets]);
1019
+ return outlineTargets.flatMap((target) => target.selected && target.drag !== null ? [target.drag] : []);
1020
+ }, [outlineTargets]);
1021
+ const allScaleDragTargets = (0, react_1.useMemo)(() => {
1022
+ return outlineTargets.flatMap((target) => target.selected && target.scaleDrag !== null ? [target.scaleDrag] : []);
1023
+ }, [outlineTargets]);
679
1024
  (0, react_1.useEffect)(() => {
680
- if (selectedOutlineTargets.length === 0) {
1025
+ if (outlineTargets.length === 0) {
681
1026
  setOutlines((prevOutlines) => prevOutlines.length === 0 ? prevOutlines : []);
682
1027
  return;
683
1028
  }
684
1029
  let animationFrame = null;
685
1030
  const updateOutlines = () => {
686
1031
  if (overlayRef.current) {
687
- const nextOutlines = measureOutlines(overlayRef.current, selectedOutlineTargets);
1032
+ const nextOutlines = measureOutlines(overlayRef.current, outlineTargets);
688
1033
  setOutlines((prevOutlines) => outlinesAreEqual(prevOutlines, nextOutlines)
689
1034
  ? prevOutlines
690
1035
  : nextOutlines);
@@ -697,14 +1042,20 @@ const SelectedOutlineOverlay = ({ scale }) => {
697
1042
  cancelAnimationFrame(animationFrame);
698
1043
  }
699
1044
  };
700
- }, [selectedOutlineTargets]);
701
- if (selectedOutlineTargets.length === 0) {
1045
+ }, [outlineTargets]);
1046
+ if (outlineTargets.length === 0) {
702
1047
  return null;
703
1048
  }
704
1049
  return (jsx_runtime_1.jsx("svg", { ref: overlayRef, style: outlineContainer, width: "100%", height: "100%", "aria-hidden": "true", children: outlines.map((outline) => {
705
- var _a;
1050
+ var _a, _b, _c;
706
1051
  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));
1052
+ jsx_runtime_1.jsx(SelectedOutlinePolygon, { allDragTargets: allDragTargets, hovered: hoveredOutlineKey === outline.key, outline: outline, onHoverChange: setHoveredOutlineKey, onSelect: selectItem, scale: scale, target: targetsByKey.get(outline.key) }), ((_a = targetsByKey.get(outline.key)) === null || _a === void 0 ? void 0 : _a.selected) ||
1053
+ hoveredOutlineKey === outline.key
1054
+ ? ['top', 'right', 'bottom', 'left'].map((edge) => (jsx_runtime_1.jsx(SelectedOutlineScaleEdgeLine, { allScaleDragTargets: allScaleDragTargets, edge: edge, outline: outline, onHoverChange: setHoveredOutlineKey, onSelect: selectItem, target: targetsByKey.get(outline.key) }, edge)))
1055
+ : null, ((_b = targetsByKey.get(outline.key)) === null || _b === void 0 ? void 0 : _b.selected)
1056
+ ? (_c = targetsByKey
1057
+ .get(outline.key)) === null || _c === void 0 ? void 0 : _c.uvHandles.map((handle) => (jsx_runtime_1.jsx(SelectedUvHandleCircle, { handle: handle, outline: outline }, `${handle.effectIndex}-${handle.fieldKey}`)))
1058
+ : null] }, outline.key));
708
1059
  }) }));
709
1060
  };
710
1061
  exports.SelectedOutlineOverlay = SelectedOutlineOverlay;