@remotion/studio 4.0.475 → 4.0.476

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 (36) hide show
  1. package/dist/components/ColorPicker/ColorPickerPopup.d.ts +6 -0
  2. package/dist/components/ColorPicker/ColorPickerPopup.js +11 -6
  3. package/dist/components/GlobalKeybindings.js +12 -0
  4. package/dist/components/KeyboardShortcutsExplainer.js +24 -0
  5. package/dist/components/NewComposition/InputDragger.d.ts +6 -0
  6. package/dist/components/NewComposition/InputDragger.js +40 -14
  7. package/dist/components/NewComposition/RenameComposition.js +8 -1
  8. package/dist/components/NewComposition/RenameFolder.js +8 -1
  9. package/dist/components/NewComposition/RenameStaticFile.js +11 -1
  10. package/dist/components/Notifications/Notification.js +5 -4
  11. package/dist/components/Notifications/NotificationCenter.js +1 -1
  12. package/dist/components/ObserveDefaultPropsContext.js +6 -2
  13. package/dist/components/PlayPause.js +22 -66
  14. package/dist/components/PreviewToolbar.js +15 -1
  15. package/dist/components/RenderModal/RenderModalJSONPropsEditor.js +2 -1
  16. package/dist/components/SelectedOutlineOverlay.d.ts +47 -11
  17. package/dist/components/SelectedOutlineOverlay.js +545 -54
  18. package/dist/components/Timeline/TimelineRotationField.js +17 -17
  19. package/dist/components/Timeline/TimelineScaleField.js +1 -1
  20. package/dist/components/Timeline/TimelineSequenceItem.js +301 -109
  21. package/dist/components/Timeline/TimelineSequenceName.d.ts +4 -2
  22. package/dist/components/Timeline/TimelineSequenceName.js +67 -2
  23. package/dist/components/Timeline/TimelineTransformOriginField.js +1 -1
  24. package/dist/components/Timeline/TimelineTranslateField.js +1 -1
  25. package/dist/components/Timeline/TimelineUvCoordinateField.js +1 -1
  26. package/dist/components/Timeline/disable-sequence-interactivity.d.ts +8 -0
  27. package/dist/components/Timeline/disable-sequence-interactivity.js +24 -0
  28. package/dist/components/Timeline/reset-selected-timeline-props.js +2 -2
  29. package/dist/components/Timeline/timeline-rotation-utils.d.ts +1 -1
  30. package/dist/components/Timeline/timeline-rotation-utils.js +4 -2
  31. package/dist/components/Timeline/use-timeline-keyframe-drag.js +8 -13
  32. package/dist/esm/{chunk-qaqqvw4q.js → chunk-0atarw3p.js} +2659 -1707
  33. package/dist/esm/internals.mjs +2659 -1707
  34. package/dist/esm/previewEntry.mjs +2661 -1709
  35. package/dist/esm/renderEntry.mjs +1 -1
  36. package/package.json +11 -11
@@ -33,8 +33,9 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SelectedOutlineOverlay = exports.compensateTranslateForTransformOrigin = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineDragChanges = exports.applySelectedOutlineDragAxisLock = exports.getSelectedOutlineDragValues = exports.getSequencesWithSelectableOutlines = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedOutlineRotationDeltaDegrees = void 0;
36
+ exports.SelectedOutlineOverlay = exports.compensateTranslateForTransformOrigin = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragChanges = exports.isSelectedOutlineDragPastThreshold = exports.applySelectedOutlineDragAxisLock = exports.getSelectedOutlineDragValues = exports.getSequencesWithSelectableOutlines = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.getSelectedSequenceKeys = exports.getTransformedSvgViewportPoints = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineDragThresholdPx = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const player_1 = require("@remotion/player");
38
39
  const react_1 = __importStar(require("react"));
39
40
  const remotion_1 = require("remotion");
40
41
  const no_react_1 = require("remotion/no-react");
@@ -44,6 +45,7 @@ const colors_1 = require("../helpers/colors");
44
45
  const format_file_location_1 = require("../helpers/format-file-location");
45
46
  const get_box_quads_ponyfill_1 = require("../helpers/get-box-quads-ponyfill");
46
47
  const open_in_editor_1 = require("../helpers/open-in-editor");
48
+ const use_keybinding_1 = require("../helpers/use-keybinding");
47
49
  const editor_outlines_1 = require("../state/editor-outlines");
48
50
  const scale_lock_1 = require("../state/scale-lock");
49
51
  const ContextMenu_1 = require("./ContextMenu");
@@ -54,9 +56,13 @@ const selected_outline_geometry_1 = require("./selected-outline-geometry");
54
56
  const selected_outline_uv_1 = require("./selected-outline-uv");
55
57
  const SelectedOutlineUvControls_1 = require("./SelectedOutlineUvControls");
56
58
  const call_add_keyframe_1 = require("./Timeline/call-add-keyframe");
59
+ const disable_sequence_interactivity_1 = require("./Timeline/disable-sequence-interactivity");
60
+ const imperative_state_1 = require("./Timeline/imperative-state");
57
61
  const parse_keyframe_field_from_node_path_1 = require("./Timeline/parse-keyframe-field-from-node-path");
58
62
  const save_sequence_prop_1 = require("./Timeline/save-sequence-prop");
63
+ const timeline_field_utils_1 = require("./Timeline/timeline-field-utils");
59
64
  const timeline_rotation_utils_1 = require("./Timeline/timeline-rotation-utils");
65
+ const timeline_scroll_logic_1 = require("./Timeline/timeline-scroll-logic");
60
66
  const timeline_translate_utils_1 = require("./Timeline/timeline-translate-utils");
61
67
  const TimelineScaleField_1 = require("./Timeline/TimelineScaleField");
62
68
  const TimelineSelection_1 = require("./Timeline/TimelineSelection");
@@ -66,6 +72,7 @@ const translateFieldKey = 'style.translate';
66
72
  const scaleFieldKey = 'style.scale';
67
73
  const rotateFieldKey = 'style.rotate';
68
74
  const transformOriginFieldKey = 'style.transformOrigin';
75
+ exports.selectedOutlineDragThresholdPx = 4;
69
76
  const outlineContainer = {
70
77
  position: 'absolute',
71
78
  inset: 0,
@@ -142,6 +149,25 @@ const getSelectedOutlineRotationCornerInfo = (points, corner) => {
142
149
  };
143
150
  };
144
151
  exports.getSelectedOutlineRotationCornerInfo = getSelectedOutlineRotationCornerInfo;
152
+ const getSelectedOutlineRotationPivot = ({ dimensions, points, transformOriginValue, }) => {
153
+ if (dimensions === null) {
154
+ return getOutlineCenter(points);
155
+ }
156
+ const parsed = (0, transform_origin_utils_1.parseTransformOrigin)(transformOriginValue);
157
+ if (parsed === null) {
158
+ return getOutlineCenter(points);
159
+ }
160
+ const uv = (0, transform_origin_utils_1.parsedTransformOriginToUv)({
161
+ parsed,
162
+ width: dimensions.width,
163
+ height: dimensions.height,
164
+ });
165
+ if (uv === null) {
166
+ return getOutlineCenter(points);
167
+ }
168
+ return (0, selected_outline_uv_1.getUvHandlePosition)(points, uv);
169
+ };
170
+ exports.getSelectedOutlineRotationPivot = getSelectedOutlineRotationPivot;
145
171
  const rectToPoints = (elementRect, containerRect) => {
146
172
  const left = elementRect.left - containerRect.left;
147
173
  const top = elementRect.top - containerRect.top;
@@ -154,6 +180,23 @@ const rectToPoints = (elementRect, containerRect) => {
154
180
  { x: left, y: bottom },
155
181
  ];
156
182
  };
183
+ const getTransformedSvgViewportPoints = ({ viewport, ctm, containerRect, }) => {
184
+ const transformPoint = (x, y) => ({
185
+ x: ctm.a * x + ctm.c * y + ctm.e - containerRect.left,
186
+ y: ctm.b * x + ctm.d * y + ctm.f - containerRect.top,
187
+ });
188
+ const left = viewport.x;
189
+ const top = viewport.y;
190
+ const right = viewport.x + viewport.width;
191
+ const bottom = viewport.y + viewport.height;
192
+ return [
193
+ transformPoint(left, top),
194
+ transformPoint(right, top),
195
+ transformPoint(right, bottom),
196
+ transformPoint(left, bottom),
197
+ ];
198
+ };
199
+ exports.getTransformedSvgViewportPoints = getTransformedSvgViewportPoints;
157
200
  const quadToPoints = (quad, containerRect) => {
158
201
  // `getBoxQuads`/the ponyfill returns the quad in viewport coordinates.
159
202
  // The overlay <svg> is unscaled (the canvas `scale()`/pan live on a sibling
@@ -169,11 +212,50 @@ const quadToPoints = (quad, containerRect) => {
169
212
  { x: quad.p4.x - containerRect.left, y: quad.p4.y - containerRect.top },
170
213
  ];
171
214
  };
215
+ const isSvgSvgElement = (element) => {
216
+ var _a;
217
+ const ownerSvgSvgElement = (_a = element.ownerDocument.defaultView) === null || _a === void 0 ? void 0 : _a.SVGSVGElement;
218
+ return ((typeof SVGSVGElement !== 'undefined' &&
219
+ element instanceof SVGSVGElement) ||
220
+ (ownerSvgSvgElement !== undefined && element instanceof ownerSvgSvgElement));
221
+ };
222
+ const getSvgSvgElementViewport = (element) => {
223
+ const viewBox = element.viewBox.baseVal;
224
+ if (viewBox.width > 0 && viewBox.height > 0) {
225
+ return {
226
+ x: viewBox.x,
227
+ y: viewBox.y,
228
+ width: viewBox.width,
229
+ height: viewBox.height,
230
+ };
231
+ }
232
+ return {
233
+ x: 0,
234
+ y: 0,
235
+ width: element.width.baseVal.value,
236
+ height: element.height.baseVal.value,
237
+ };
238
+ };
239
+ const getSvgSvgElementOutlinePoints = (element, containerRect) => {
240
+ const ctm = element.getScreenCTM();
241
+ const viewport = getSvgSvgElementViewport(element);
242
+ if (ctm === null || (viewport.width === 0 && viewport.height === 0)) {
243
+ return null;
244
+ }
245
+ return (0, exports.getTransformedSvgViewportPoints)({
246
+ viewport,
247
+ ctm,
248
+ containerRect,
249
+ });
250
+ };
172
251
  const getElementOutlinePoints = (element, containerRect) => {
173
252
  const elementRect = element.getBoundingClientRect();
174
253
  if (elementRect.width === 0 && elementRect.height === 0) {
175
254
  return null;
176
255
  }
256
+ if (isSvgSvgElement(element)) {
257
+ return getSvgSvgElementOutlinePoints(element, containerRect);
258
+ }
177
259
  const quads = (0, get_box_quads_ponyfill_1.getBoxQuadsPonyfill)(element, {
178
260
  box: 'border',
179
261
  });
@@ -295,7 +377,12 @@ const measureOutlines = (container, targets) => {
295
377
  width: element.offsetWidth,
296
378
  height: element.offsetHeight,
297
379
  }
298
- : null,
380
+ : element instanceof SVGSVGElement
381
+ ? {
382
+ width: element.width.baseVal.value,
383
+ height: element.height.baseVal.value,
384
+ }
385
+ : null,
299
386
  points,
300
387
  });
301
388
  }
@@ -365,6 +452,10 @@ const applySelectedOutlineDragAxisLock = ({ deltaX, deltaY, axisLocked, }) => {
365
452
  return { deltaX: 0, deltaY };
366
453
  };
367
454
  exports.applySelectedOutlineDragAxisLock = applySelectedOutlineDragAxisLock;
455
+ const isSelectedOutlineDragPastThreshold = ({ deltaX, deltaY, }) => {
456
+ return Math.hypot(deltaX, deltaY) >= exports.selectedOutlineDragThresholdPx;
457
+ };
458
+ exports.isSelectedOutlineDragPastThreshold = isSelectedOutlineDragPastThreshold;
368
459
  const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
369
460
  const changes = [];
370
461
  for (const dragState of dragStates) {
@@ -409,6 +500,22 @@ const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
409
500
  return changes;
410
501
  };
411
502
  exports.getSelectedOutlineDragChanges = getSelectedOutlineDragChanges;
503
+ const getSelectedOutlineKeyboardNudgeDelta = ({ direction, shiftKey, }) => {
504
+ const increment = shiftKey ? 10 : 1;
505
+ return direction === 'left' || direction === 'up' ? -increment : increment;
506
+ };
507
+ exports.getSelectedOutlineKeyboardNudgeDelta = getSelectedOutlineKeyboardNudgeDelta;
508
+ const getSelectedOutlineKeyboardNudgeDeltas = ({ deltaX, deltaY, direction, shiftKey, }) => {
509
+ const delta = (0, exports.getSelectedOutlineKeyboardNudgeDelta)({
510
+ direction,
511
+ shiftKey,
512
+ });
513
+ if (direction === 'left' || direction === 'right') {
514
+ return { deltaX: deltaX + delta, deltaY };
515
+ }
516
+ return { deltaX, deltaY: deltaY + delta };
517
+ };
518
+ exports.getSelectedOutlineKeyboardNudgeDeltas = getSelectedOutlineKeyboardNudgeDeltas;
412
519
  const getSelectedOutlineScaleEdgeInfo = (points, edge) => {
413
520
  const [tl, tr, br, bl] = points;
414
521
  const edgePoints = {
@@ -434,14 +541,16 @@ const getSelectedOutlineScaleEdgeInfo = (points, edge) => {
434
541
  };
435
542
  };
436
543
  exports.getSelectedOutlineScaleEdgeInfo = getSelectedOutlineScaleEdgeInfo;
437
- const getSelectedOutlineScaleDragStates = ({ dragTargets, getDragOverrides, }) => {
544
+ const getSelectedOutlineScaleDragStates = ({ dragTargets, getDragOverrides, timelinePosition, }) => {
438
545
  return dragTargets.map((target) => {
439
546
  var _a;
440
547
  const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[scaleFieldKey];
548
+ const sourceFrame = timelinePosition - target.keyframeDisplayOffset;
441
549
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
442
550
  propStatus: target.propStatus,
443
551
  dragOverrideValue,
444
552
  defaultValue: target.fieldDefault,
553
+ frame: sourceFrame,
445
554
  shouldResortToDefaultValueIfUndefined: true,
446
555
  });
447
556
  const [startX, startY, startZ] = no_react_1.NoReactInternals.parseScaleValue(effectiveValue);
@@ -450,6 +559,7 @@ const getSelectedOutlineScaleDragStates = ({ dragTargets, getDragOverrides, }) =
450
559
  ? JSON.stringify(target.fieldDefault)
451
560
  : null,
452
561
  key: remotion_1.Internals.makeSequencePropsSubscriptionKey(target.nodePath),
562
+ sourceFrame,
453
563
  startX,
454
564
  startY,
455
565
  startZ,
@@ -463,10 +573,14 @@ const getSelectedOutlineScaleDragValues = ({ axis, dragStates, scaleFactor, }) =
463
573
  var _a, _b;
464
574
  const min = (_a = dragState.target.fieldSchema.min) !== null && _a !== void 0 ? _a : -Infinity;
465
575
  const max = (_b = dragState.target.fieldSchema.max) !== null && _b !== void 0 ? _b : Infinity;
576
+ const decimalPlaces = (0, timeline_field_utils_1.getTimelineDisplayDecimalPlaces)({
577
+ defaultDecimalPlaces: 3,
578
+ step: dragState.target.fieldSchema.step,
579
+ });
466
580
  const baseX = dragState.startX;
467
581
  const baseY = dragState.startY;
468
582
  const newValue = (axis === 'x' ? baseX : baseY) * scaleFactor;
469
- const [x, y] = dragState.target.linked
583
+ const [rawX, rawY] = dragState.target.linked
470
584
  ? (0, TimelineScaleField_1.getLinkedScale)({
471
585
  axis,
472
586
  newValue,
@@ -478,6 +592,8 @@ const getSelectedOutlineScaleDragValues = ({ axis, dragStates, scaleFactor, }) =
478
592
  : axis === 'x'
479
593
  ? [(0, selected_outline_geometry_1.clamp)(newValue, min, max), baseY]
480
594
  : [baseX, (0, selected_outline_geometry_1.clamp)(newValue, min, max)];
595
+ const x = (0, timeline_field_utils_1.roundToDecimalPlaces)(rawX, decimalPlaces);
596
+ const y = (0, timeline_field_utils_1.roundToDecimalPlaces)(rawY, decimalPlaces);
481
597
  return [
482
598
  dragState.key,
483
599
  no_react_1.NoReactInternals.serializeScaleValue([x, y, dragState.startZ]),
@@ -486,10 +602,32 @@ const getSelectedOutlineScaleDragValues = ({ axis, dragStates, scaleFactor, }) =
486
602
  };
487
603
  exports.getSelectedOutlineScaleDragValues = getSelectedOutlineScaleDragValues;
488
604
  const getSelectedOutlineScaleDragChanges = ({ dragStates, lastValues, }) => {
489
- return dragStates.flatMap((dragState) => {
605
+ const changes = [];
606
+ for (const dragState of dragStates) {
490
607
  const value = lastValues.get(dragState.key);
491
608
  if (value === undefined) {
492
- return [];
609
+ continue;
610
+ }
611
+ if (dragState.target.propStatus.status === 'keyframed') {
612
+ const startValue = no_react_1.NoReactInternals.serializeScaleValue([
613
+ dragState.startX,
614
+ dragState.startY,
615
+ dragState.startZ,
616
+ ]);
617
+ if (value === startValue) {
618
+ continue;
619
+ }
620
+ changes.push({
621
+ type: 'keyframed',
622
+ fileName: dragState.target.nodePath.absolutePath,
623
+ nodePath: dragState.target.nodePath,
624
+ fieldKey: scaleFieldKey,
625
+ sourceFrame: dragState.sourceFrame,
626
+ value,
627
+ schema: dragState.target.schema,
628
+ clientId: dragState.target.clientId,
629
+ });
630
+ continue;
493
631
  }
494
632
  const stringifiedValue = JSON.stringify(value);
495
633
  const shouldSave = stringifiedValue !==
@@ -497,19 +635,19 @@ const getSelectedOutlineScaleDragChanges = ({ dragStates, lastValues, }) => {
497
635
  !(dragState.defaultValue === stringifiedValue &&
498
636
  dragState.target.propStatus.codeValue === undefined);
499
637
  if (!shouldSave) {
500
- return [];
638
+ continue;
501
639
  }
502
- return [
503
- {
504
- fileName: dragState.target.nodePath.absolutePath,
505
- nodePath: dragState.target.nodePath,
506
- fieldKey: scaleFieldKey,
507
- value,
508
- defaultValue: dragState.defaultValue,
509
- schema: dragState.target.schema,
510
- },
511
- ];
512
- });
640
+ changes.push({
641
+ type: 'static',
642
+ fileName: dragState.target.nodePath.absolutePath,
643
+ nodePath: dragState.target.nodePath,
644
+ fieldKey: scaleFieldKey,
645
+ value,
646
+ defaultValue: dragState.defaultValue,
647
+ schema: dragState.target.schema,
648
+ });
649
+ }
650
+ return changes;
513
651
  };
514
652
  exports.getSelectedOutlineScaleDragChanges = getSelectedOutlineScaleDragChanges;
515
653
  const getSelectedOutlineRotationDragStates = ({ dragTargets, getDragOverrides, timelinePosition, }) => {
@@ -537,10 +675,16 @@ const getSelectedOutlineRotationDragStates = ({ dragTargets, getDragOverrides, t
537
675
  };
538
676
  exports.getSelectedOutlineRotationDragStates = getSelectedOutlineRotationDragStates;
539
677
  const getSelectedOutlineRotationDragValues = ({ dragStates, rotationDeltaDegrees, }) => {
540
- return new Map(dragStates.map((dragState) => [
541
- dragState.key,
542
- (0, timeline_rotation_utils_1.serializeCssRotation)(dragState.startDegrees + rotationDeltaDegrees),
543
- ]));
678
+ return new Map(dragStates.map((dragState) => {
679
+ const decimalPlaces = (0, timeline_field_utils_1.getTimelineDisplayDecimalPlaces)({
680
+ defaultDecimalPlaces: 1,
681
+ step: dragState.target.fieldSchema.step,
682
+ });
683
+ return [
684
+ dragState.key,
685
+ (0, timeline_rotation_utils_1.serializeCssRotation)(dragState.startDegrees + rotationDeltaDegrees, decimalPlaces),
686
+ ];
687
+ }));
544
688
  };
545
689
  exports.getSelectedOutlineRotationDragValues = getSelectedOutlineRotationDragValues;
546
690
  const getSelectedOutlineRotationDragChanges = ({ dragStates, lastValues, }) => {
@@ -551,7 +695,11 @@ const getSelectedOutlineRotationDragChanges = ({ dragStates, lastValues, }) => {
551
695
  continue;
552
696
  }
553
697
  if (dragState.target.propStatus.status === 'keyframed') {
554
- const startValue = (0, timeline_rotation_utils_1.serializeCssRotation)(dragState.startDegrees);
698
+ const decimalPlaces = (0, timeline_field_utils_1.getTimelineDisplayDecimalPlaces)({
699
+ defaultDecimalPlaces: 1,
700
+ step: dragState.target.fieldSchema.step,
701
+ });
702
+ const startValue = (0, timeline_rotation_utils_1.serializeCssRotation)(dragState.startDegrees, decimalPlaces);
555
703
  if (value === startValue) {
556
704
  continue;
557
705
  }
@@ -592,6 +740,21 @@ const clearSelectedOutlineDragOverrides = ({ clearDragOverrides, dragStates, })
592
740
  clearDragOverrides(dragState.target.nodePath);
593
741
  }
594
742
  };
743
+ const getSelectedOutlineKeyboardNudgeDirection = (key) => {
744
+ if (key === 'ArrowLeft') {
745
+ return 'left';
746
+ }
747
+ if (key === 'ArrowRight') {
748
+ return 'right';
749
+ }
750
+ if (key === 'ArrowUp') {
751
+ return 'up';
752
+ }
753
+ if (key === 'ArrowDown') {
754
+ return 'down';
755
+ }
756
+ return null;
757
+ };
595
758
  const clearSelectedOutlineScaleDragOverrides = ({ clearDragOverrides, dragStates, }) => {
596
759
  for (const dragState of dragStates) {
597
760
  clearDragOverrides(dragState.target.nodePath);
@@ -836,7 +999,7 @@ const SelectedOutlineTransformOriginHandle = ({ outline, onDraggingChange, targe
836
999
  return null;
837
1000
  }
838
1001
  return (jsx_runtime_1.jsxs("g", { pointerEvents: "all", cursor: "crosshair", onPointerDown: onPointerDown, "aria-hidden": "true", children: [
839
- jsx_runtime_1.jsx("line", { x1: position.x - 8, y1: position.y, x2: position.x + 8, y2: position.y, stroke: "white", strokeWidth: 4, vectorEffect: "non-scaling-stroke" }), jsx_runtime_1.jsx("line", { x1: position.x, y1: position.y - 8, x2: position.x, y2: position.y + 8, stroke: "white", strokeWidth: 4, vectorEffect: "non-scaling-stroke" }), jsx_runtime_1.jsx("circle", { cx: position.x, cy: position.y, r: 4, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke" }), jsx_runtime_1.jsx("line", { x1: position.x - 8, y1: position.y, x2: position.x + 8, y2: position.y, stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke" }), jsx_runtime_1.jsx("line", { x1: position.x, y1: position.y - 8, x2: position.x, y2: position.y + 8, stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke" })
1002
+ jsx_runtime_1.jsx("circle", { cx: position.x, cy: position.y, r: 4, stroke: colors_1.BLUE, fill: "none", strokeWidth: 2, vectorEffect: "non-scaling-stroke" }), jsx_runtime_1.jsx("line", { x1: position.x - 8, y1: position.y, x2: position.x + 8, y2: position.y, stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke" }), jsx_runtime_1.jsx("line", { x1: position.x, y1: position.y - 8, x2: position.x, y2: position.y + 8, stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke" })
840
1003
  ] }));
841
1004
  };
842
1005
  const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, hovered, onContextMenuOpen, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
@@ -868,7 +1031,6 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
868
1031
  if (drag === null || interaction.shiftKey || interaction.toggleKey) {
869
1032
  return;
870
1033
  }
871
- onDraggingChange(true);
872
1034
  const startPointerX = event.clientX;
873
1035
  const startPointerY = event.clientY;
874
1036
  const dragStates = getSelectedOutlineDragStates({
@@ -880,10 +1042,23 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
880
1042
  let currentPointerX = startPointerX;
881
1043
  let currentPointerY = startPointerY;
882
1044
  let axisLocked = false;
1045
+ let dragStarted = false;
883
1046
  const updateDragOverrides = () => {
1047
+ const screenDeltaX = currentPointerX - startPointerX;
1048
+ const screenDeltaY = currentPointerY - startPointerY;
1049
+ if (!dragStarted) {
1050
+ if (!(0, exports.isSelectedOutlineDragPastThreshold)({
1051
+ deltaX: screenDeltaX,
1052
+ deltaY: screenDeltaY,
1053
+ })) {
1054
+ return;
1055
+ }
1056
+ dragStarted = true;
1057
+ onDraggingChange(true);
1058
+ }
884
1059
  const dragDelta = (0, exports.applySelectedOutlineDragAxisLock)({
885
- deltaX: (currentPointerX - startPointerX) / scale,
886
- deltaY: (currentPointerY - startPointerY) / scale,
1060
+ deltaX: screenDeltaX / scale,
1061
+ deltaY: screenDeltaY / scale,
887
1062
  axisLocked,
888
1063
  });
889
1064
  lastValues = (0, exports.getSelectedOutlineDragValues)({
@@ -932,7 +1107,9 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
932
1107
  window.removeEventListener('pointercancel', onPointerUp);
933
1108
  window.removeEventListener('keydown', onKeyChange);
934
1109
  window.removeEventListener('keyup', onKeyChange);
935
- onDraggingChange(false);
1110
+ if (dragStarted) {
1111
+ onDraggingChange(false);
1112
+ }
936
1113
  const changes = (0, exports.getSelectedOutlineDragChanges)({
937
1114
  dragStates,
938
1115
  lastValues,
@@ -1048,6 +1225,9 @@ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues,
1048
1225
  var _a, _b;
1049
1226
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
1050
1227
  const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
1228
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
1229
+ const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
1230
+ timelinePositionRef.current = timelinePosition;
1051
1231
  const scaleDrag = (_a = target === null || target === void 0 ? void 0 : target.scaleDrag) !== null && _a !== void 0 ? _a : null;
1052
1232
  const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
1053
1233
  const lineRef = (0, react_1.useRef)(null);
@@ -1067,10 +1247,12 @@ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues,
1067
1247
  return;
1068
1248
  }
1069
1249
  onDraggingChange(true);
1250
+ (0, ForceSpecificCursor_1.forceSpecificCursor)(edgeInfo.cursor);
1070
1251
  const startPointer = { x: event.clientX, y: event.clientY };
1071
1252
  const dragStates = (0, exports.getSelectedOutlineScaleDragStates)({
1072
1253
  dragTargets: selected ? allScaleDragTargets : [scaleDrag],
1073
1254
  getDragOverrides,
1255
+ timelinePosition: timelinePositionRef.current,
1074
1256
  });
1075
1257
  let lastValues = new Map();
1076
1258
  const onPointerMove = (moveEvent) => {
@@ -1091,13 +1273,23 @@ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues,
1091
1273
  if (value === undefined) {
1092
1274
  throw new Error('Expected scale drag value to be available');
1093
1275
  }
1094
- setDragOverrides(dragState.target.nodePath, scaleFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
1276
+ if (dragState.target.propStatus.status === 'keyframed') {
1277
+ setDragOverrides(dragState.target.nodePath, scaleFieldKey, remotion_1.Internals.makeKeyframedDragOverride({
1278
+ status: dragState.target.propStatus,
1279
+ frame: dragState.sourceFrame,
1280
+ value,
1281
+ }));
1282
+ }
1283
+ else {
1284
+ setDragOverrides(dragState.target.nodePath, scaleFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
1285
+ }
1095
1286
  }
1096
1287
  };
1097
1288
  const onPointerUp = () => {
1098
1289
  window.removeEventListener('pointermove', onPointerMove);
1099
1290
  window.removeEventListener('pointerup', onPointerUp);
1100
1291
  window.removeEventListener('pointercancel', onPointerUp);
1292
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
1101
1293
  onDraggingChange(false);
1102
1294
  const changes = (0, exports.getSelectedOutlineScaleDragChanges)({
1103
1295
  dragStates,
@@ -1110,15 +1302,33 @@ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues,
1110
1302
  });
1111
1303
  return;
1112
1304
  }
1113
- (0, save_sequence_prop_1.saveSequenceProps)({
1114
- changes,
1115
- setPropStatuses,
1116
- clientId: scaleDrag.clientId,
1117
- undoLabel: changes.length > 1 ? 'Scale selected sequences' : 'Scale sequence',
1118
- redoLabel: changes.length > 1
1119
- ? 'Scale selected sequences back'
1120
- : 'Scale sequence back',
1121
- })
1305
+ const staticChanges = changes.filter((change) => change.type === 'static');
1306
+ const keyframedChanges = changes.filter((change) => change.type === 'keyframed');
1307
+ Promise.all([
1308
+ staticChanges.length > 0
1309
+ ? (0, save_sequence_prop_1.saveSequenceProps)({
1310
+ changes: staticChanges,
1311
+ setPropStatuses,
1312
+ clientId: scaleDrag.clientId,
1313
+ undoLabel: changes.length > 1
1314
+ ? 'Scale selected sequences'
1315
+ : 'Scale sequence',
1316
+ redoLabel: changes.length > 1
1317
+ ? 'Scale selected sequences back'
1318
+ : 'Scale sequence back',
1319
+ })
1320
+ : Promise.resolve(),
1321
+ ...keyframedChanges.map((change) => (0, call_add_keyframe_1.callAddSequenceKeyframe)({
1322
+ fileName: change.fileName,
1323
+ nodePath: change.nodePath,
1324
+ fieldKey: change.fieldKey,
1325
+ sourceFrame: change.sourceFrame,
1326
+ value: change.value,
1327
+ schema: change.schema,
1328
+ setPropStatuses,
1329
+ clientId: change.clientId,
1330
+ })),
1331
+ ])
1122
1332
  .catch((err) => {
1123
1333
  (0, NotificationCenter_1.showNotification)(`Could not save sequence props: ${err instanceof Error ? err.message : String(err)}`, 4000);
1124
1334
  })
@@ -1198,7 +1408,11 @@ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMe
1198
1408
  onDraggingChange(true);
1199
1409
  (0, ForceSpecificCursor_1.forceSpecificCursor)(cornerInfo.cursor);
1200
1410
  const svgRect = svg.getBoundingClientRect();
1201
- const center = svgPointToClientPoint(cornerInfo.center, svgRect);
1411
+ const center = svgPointToClientPoint((0, exports.getSelectedOutlineRotationPivot)({
1412
+ dimensions: outline.dimensions,
1413
+ points: outline.points,
1414
+ transformOriginValue: rotationDrag.transformOriginValue,
1415
+ }), svgRect);
1202
1416
  const dragStates = (0, exports.getSelectedOutlineRotationDragStates)({
1203
1417
  dragTargets: selected ? allRotationDragTargets : [rotationDrag],
1204
1418
  getDragOverrides,
@@ -1306,6 +1520,8 @@ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMe
1306
1520
  cornerInfo,
1307
1521
  getDragOverrides,
1308
1522
  onDraggingChange,
1523
+ outline.dimensions,
1524
+ outline.points,
1309
1525
  onSelect,
1310
1526
  rotationDrag,
1311
1527
  selected,
@@ -1330,6 +1546,7 @@ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMe
1330
1546
  };
1331
1547
  const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allScaleDragTargets, dragging, hovered, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
1332
1548
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
1549
+ const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
1333
1550
  const updateResolvedStackTrace = (0, react_1.useContext)(remotion_1.Internals.SequenceStackTracesUpdateContext);
1334
1551
  const onContextMenuOpen = react_1.default.useCallback(async () => {
1335
1552
  if (target === undefined || previewServerState.type !== 'connected') {
@@ -1356,6 +1573,7 @@ const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allSca
1356
1573
  root: window.remotion_cwd,
1357
1574
  });
1358
1575
  const editorName = window.remotion_editorName;
1576
+ const disableInteractivityDisabled = !target.sequence.showInTimeline;
1359
1577
  return [
1360
1578
  editorName
1361
1579
  ? {
@@ -1402,8 +1620,38 @@ const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allSca
1402
1620
  subMenu: null,
1403
1621
  value: 'copy-outline-file-location',
1404
1622
  },
1623
+ {
1624
+ type: 'item',
1625
+ id: 'disable-outline-interactivity',
1626
+ keyHint: null,
1627
+ label: 'Disable interactivity',
1628
+ leftItem: null,
1629
+ disabled: disableInteractivityDisabled,
1630
+ onClick: () => {
1631
+ if (disableInteractivityDisabled ||
1632
+ previewServerState.type !== 'connected') {
1633
+ return;
1634
+ }
1635
+ const nodePath = target.nodePathInfo.sequenceSubscriptionKey;
1636
+ (0, disable_sequence_interactivity_1.disableSequenceInteractivity)({
1637
+ fileName: nodePath.absolutePath,
1638
+ nodePath,
1639
+ setPropStatuses,
1640
+ clientId: previewServerState.clientId,
1641
+ });
1642
+ },
1643
+ quickSwitcherLabel: null,
1644
+ subMenu: null,
1645
+ value: 'disable-outline-interactivity',
1646
+ },
1405
1647
  ].filter(no_react_1.NoReactInternals.truthy);
1406
- }, [onSelect, previewServerState.type, target, updateResolvedStackTrace]);
1648
+ }, [
1649
+ onSelect,
1650
+ previewServerState,
1651
+ setPropStatuses,
1652
+ target,
1653
+ updateResolvedStackTrace,
1654
+ ]);
1407
1655
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1408
1656
  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.containsSelection) || hovered
1409
1657
  ? ['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)))
@@ -1419,13 +1667,18 @@ const SelectedOutlineOverlay = ({ scale }) => {
1419
1667
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
1420
1668
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
1421
1669
  const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
1670
+ const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
1422
1671
  const { getScaleLockState } = (0, react_1.useContext)(scale_lock_1.ScaleLockContext);
1423
1672
  const { editorShowOutlines } = (0, react_1.useContext)(editor_outlines_1.EditorShowOutlinesContext);
1673
+ const { frameBack, frameForward, getCurrentFrame, seek } = player_1.PlayerInternals.usePlayer();
1674
+ const keybindings = (0, use_keybinding_1.useKeybinding)();
1424
1675
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
1425
1676
  const [outlines, setOutlines] = (0, react_1.useState)([]);
1426
1677
  const [hoveredOutlineKey, setHoveredOutlineKey] = (0, react_1.useState)(null);
1427
1678
  const [draggingOutline, setDraggingOutline] = (0, react_1.useState)(false);
1428
1679
  const overlayRef = (0, react_1.useRef)(null);
1680
+ const keyboardNudgeSessionRef = (0, react_1.useRef)(null);
1681
+ const saveKeyboardNudgeSessionRef = (0, react_1.useRef)(() => undefined);
1429
1682
  const onDraggingChange = react_1.default.useCallback((dragging) => {
1430
1683
  setDraggingOutline(dragging);
1431
1684
  if (dragging) {
@@ -1448,7 +1701,7 @@ const SelectedOutlineOverlay = ({ scale }) => {
1448
1701
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
1449
1702
  }).map(({ key, keyframeDisplayOffset, nodePathInfo, sequence }) => {
1450
1703
  var _a;
1451
- var _b, _c, _d, _e, _f, _g, _h, _j;
1704
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
1452
1705
  if (sequence.refForOutline === null) {
1453
1706
  throw new Error('Expected sequence to have a ref for outline');
1454
1707
  }
@@ -1465,6 +1718,18 @@ const SelectedOutlineOverlay = ({ scale }) => {
1465
1718
  const rotationPropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[rotateFieldKey];
1466
1719
  const transformOriginFieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[transformOriginFieldKey];
1467
1720
  const transformOriginPropStatus = nodePropStatuses === null || nodePropStatuses === void 0 ? void 0 : nodePropStatuses[transformOriginFieldKey];
1721
+ const rotationSourceFrame = timelinePosition - keyframeDisplayOffset;
1722
+ const transformOriginValueForRotation = (transformOriginFieldSchema === null || transformOriginFieldSchema === void 0 ? void 0 : transformOriginFieldSchema.type) === 'transform-origin' &&
1723
+ ((transformOriginPropStatus === null || transformOriginPropStatus === void 0 ? void 0 : transformOriginPropStatus.status) === 'static' ||
1724
+ (transformOriginPropStatus === null || transformOriginPropStatus === void 0 ? void 0 : transformOriginPropStatus.status) === 'keyframed')
1725
+ ? String((_c = remotion_1.Internals.getEffectiveVisualModeValue({
1726
+ propStatus: transformOriginPropStatus,
1727
+ dragOverrideValue: ((_b = getDragOverrides(nodePath)) !== null && _b !== void 0 ? _b : {})[transformOriginFieldKey],
1728
+ defaultValue: transformOriginFieldSchema.default,
1729
+ frame: rotationSourceFrame,
1730
+ shouldResortToDefaultValueIfUndefined: true,
1731
+ })) !== null && _c !== void 0 ? _c : transformOriginFieldSchema.default)
1732
+ : '50% 50%';
1468
1733
  const canDragStatus = (propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) === 'static' ||
1469
1734
  ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) === 'keyframed' &&
1470
1735
  propStatus.interpolationFunction === 'interpolate');
@@ -1475,10 +1740,13 @@ const SelectedOutlineOverlay = ({ scale }) => {
1475
1740
  controls !== null &&
1476
1741
  (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) === 'translate' &&
1477
1742
  canDragStatus;
1743
+ const canScaleDragStatus = (scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'static' ||
1744
+ ((scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'keyframed' &&
1745
+ scalePropStatus.interpolationFunction === 'interpolate');
1478
1746
  const canScaleDrag = previewServerState.type === 'connected' &&
1479
1747
  controls !== null &&
1480
1748
  (scaleFieldSchema === null || scaleFieldSchema === void 0 ? void 0 : scaleFieldSchema.type) === 'scale' &&
1481
- (scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'static';
1749
+ canScaleDragStatus;
1482
1750
  const canRotationDrag = previewServerState.type === 'connected' &&
1483
1751
  controls !== null &&
1484
1752
  (rotationFieldSchema === null || rotationFieldSchema === void 0 ? void 0 : rotationFieldSchema.type) === 'rotation-css' &&
@@ -1534,6 +1802,7 @@ const SelectedOutlineOverlay = ({ scale }) => {
1534
1802
  clientId: previewServerState.clientId,
1535
1803
  fieldDefault: scaleFieldSchema.default,
1536
1804
  fieldSchema: scaleFieldSchema,
1805
+ keyframeDisplayOffset,
1537
1806
  linked: getScaleLockState({
1538
1807
  nodePath,
1539
1808
  fieldKey: scaleFieldKey,
@@ -1563,6 +1832,7 @@ const SelectedOutlineOverlay = ({ scale }) => {
1563
1832
  keyframeDisplayOffset,
1564
1833
  nodePath,
1565
1834
  schema: controls.schema,
1835
+ transformOriginValue: transformOriginValueForRotation,
1566
1836
  }
1567
1837
  : null,
1568
1838
  transformOriginDrag: canTransformOriginDrag
@@ -1572,48 +1842,48 @@ const SelectedOutlineOverlay = ({ scale }) => {
1572
1842
  nodePath,
1573
1843
  originDefault: transformOriginFieldSchema.default,
1574
1844
  originPropStatus: transformOriginPropStatus,
1575
- originValue: String((_c = remotion_1.Internals.getEffectiveVisualModeValue({
1845
+ originValue: String((_e = remotion_1.Internals.getEffectiveVisualModeValue({
1576
1846
  propStatus: transformOriginPropStatus,
1577
- dragOverrideValue: ((_b = getDragOverrides(nodePath)) !== null && _b !== void 0 ? _b : {})[transformOriginFieldKey],
1847
+ dragOverrideValue: ((_d = getDragOverrides(nodePath)) !== null && _d !== void 0 ? _d : {})[transformOriginFieldKey],
1578
1848
  defaultValue: transformOriginFieldSchema.default,
1579
1849
  frame: transformOriginSourceFrame,
1580
1850
  shouldResortToDefaultValueIfUndefined: true,
1581
- })) !== null && _c !== void 0 ? _c : transformOriginFieldSchema.default),
1851
+ })) !== null && _e !== void 0 ? _e : transformOriginFieldSchema.default),
1582
1852
  rotateValue: String((rotationPropStatus === null || rotationPropStatus === void 0 ? void 0 : rotationPropStatus.status) === 'static' ||
1583
1853
  (rotationPropStatus === null || rotationPropStatus === void 0 ? void 0 : rotationPropStatus.status) === 'keyframed'
1584
- ? ((_e = remotion_1.Internals.getEffectiveVisualModeValue({
1854
+ ? ((_g = remotion_1.Internals.getEffectiveVisualModeValue({
1585
1855
  propStatus: rotationPropStatus,
1586
- dragOverrideValue: ((_d = getDragOverrides(nodePath)) !== null && _d !== void 0 ? _d : {})[rotateFieldKey],
1856
+ dragOverrideValue: ((_f = getDragOverrides(nodePath)) !== null && _f !== void 0 ? _f : {})[rotateFieldKey],
1587
1857
  defaultValue: (rotationFieldSchema === null || rotationFieldSchema === void 0 ? void 0 : rotationFieldSchema.type) === 'rotation-css'
1588
1858
  ? rotationFieldSchema.default
1589
1859
  : '0deg',
1590
1860
  frame: transformOriginSourceFrame,
1591
1861
  shouldResortToDefaultValueIfUndefined: true,
1592
- })) !== null && _e !== void 0 ? _e : '0deg')
1862
+ })) !== null && _g !== void 0 ? _g : '0deg')
1593
1863
  : '0deg'),
1594
1864
  scaleValue: (scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'static' ||
1595
1865
  (scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'keyframed'
1596
- ? String((_g = remotion_1.Internals.getEffectiveVisualModeValue({
1866
+ ? String((_j = remotion_1.Internals.getEffectiveVisualModeValue({
1597
1867
  propStatus: scalePropStatus,
1598
- dragOverrideValue: ((_f = getDragOverrides(nodePath)) !== null && _f !== void 0 ? _f : {})[scaleFieldKey],
1868
+ dragOverrideValue: ((_h = getDragOverrides(nodePath)) !== null && _h !== void 0 ? _h : {})[scaleFieldKey],
1599
1869
  defaultValue: (scaleFieldSchema === null || scaleFieldSchema === void 0 ? void 0 : scaleFieldSchema.type) === 'scale'
1600
1870
  ? scaleFieldSchema.default
1601
1871
  : 1,
1602
1872
  frame: transformOriginSourceFrame,
1603
1873
  shouldResortToDefaultValueIfUndefined: true,
1604
- })) !== null && _g !== void 0 ? _g : 1)
1874
+ })) !== null && _j !== void 0 ? _j : 1)
1605
1875
  : '1',
1606
1876
  schema: controls.schema,
1607
1877
  sourceFrame: transformOriginSourceFrame,
1608
1878
  translateDefault: fieldSchema.default,
1609
1879
  translatePropStatus: propStatus,
1610
- translateValue: String((_j = remotion_1.Internals.getEffectiveVisualModeValue({
1880
+ translateValue: String((_l = remotion_1.Internals.getEffectiveVisualModeValue({
1611
1881
  propStatus,
1612
- dragOverrideValue: ((_h = getDragOverrides(nodePath)) !== null && _h !== void 0 ? _h : {})[translateFieldKey],
1882
+ dragOverrideValue: ((_k = getDragOverrides(nodePath)) !== null && _k !== void 0 ? _k : {})[translateFieldKey],
1613
1883
  defaultValue: fieldSchema.default,
1614
1884
  frame: transformOriginSourceFrame,
1615
1885
  shouldResortToDefaultValueIfUndefined: true,
1616
- })) !== null && _j !== void 0 ? _j : fieldSchema.default),
1886
+ })) !== null && _l !== void 0 ? _l : fieldSchema.default),
1617
1887
  }
1618
1888
  : null,
1619
1889
  uvHandles: containsSelection
@@ -1661,6 +1931,227 @@ const SelectedOutlineOverlay = ({ scale }) => {
1661
1931
  ? [target.rotationDrag]
1662
1932
  : []);
1663
1933
  }, [outlineTargets]);
1934
+ const saveKeyboardNudgeSession = (0, react_1.useCallback)(() => {
1935
+ const session = keyboardNudgeSessionRef.current;
1936
+ if (session === null) {
1937
+ return;
1938
+ }
1939
+ keyboardNudgeSessionRef.current = null;
1940
+ const changes = (0, exports.getSelectedOutlineDragChanges)({
1941
+ dragStates: session.dragStates,
1942
+ lastValues: session.lastValues,
1943
+ });
1944
+ if (changes.length === 0) {
1945
+ clearSelectedOutlineDragOverrides({
1946
+ clearDragOverrides,
1947
+ dragStates: session.dragStates,
1948
+ });
1949
+ return;
1950
+ }
1951
+ const staticChanges = changes.filter((change) => change.type === 'static');
1952
+ const keyframedChanges = changes.filter((change) => change.type === 'keyframed');
1953
+ Promise.all([
1954
+ staticChanges.length > 0
1955
+ ? (0, save_sequence_prop_1.saveSequenceProps)({
1956
+ changes: staticChanges,
1957
+ setPropStatuses,
1958
+ clientId: session.clientId,
1959
+ undoLabel: changes.length > 1 ? 'Move selected sequences' : 'Move sequence',
1960
+ redoLabel: changes.length > 1
1961
+ ? 'Move selected sequences back'
1962
+ : 'Move sequence back',
1963
+ })
1964
+ : Promise.resolve(),
1965
+ ...keyframedChanges.map((change) => (0, call_add_keyframe_1.callAddSequenceKeyframe)({
1966
+ fileName: change.fileName,
1967
+ nodePath: change.nodePath,
1968
+ fieldKey: change.fieldKey,
1969
+ sourceFrame: change.sourceFrame,
1970
+ value: change.value,
1971
+ schema: change.schema,
1972
+ setPropStatuses,
1973
+ clientId: change.clientId,
1974
+ })),
1975
+ ])
1976
+ .catch((err) => {
1977
+ (0, NotificationCenter_1.showNotification)(`Could not save sequence props: ${err instanceof Error ? err.message : String(err)}`, 4000);
1978
+ })
1979
+ .finally(() => {
1980
+ clearSelectedOutlineDragOverrides({
1981
+ clearDragOverrides,
1982
+ dragStates: session.dragStates,
1983
+ });
1984
+ });
1985
+ }, [clearDragOverrides, setPropStatuses]);
1986
+ (0, react_1.useEffect)(() => {
1987
+ saveKeyboardNudgeSessionRef.current = saveKeyboardNudgeSession;
1988
+ }, [saveKeyboardNudgeSession]);
1989
+ (0, react_1.useEffect)(() => {
1990
+ return () => {
1991
+ saveKeyboardNudgeSessionRef.current();
1992
+ };
1993
+ }, []);
1994
+ const seekWithArrowKey = (0, react_1.useCallback)((event, direction) => {
1995
+ if (direction === 'up' || direction === 'down') {
1996
+ return;
1997
+ }
1998
+ event.preventDefault();
1999
+ if (direction === 'left') {
2000
+ if (event.altKey) {
2001
+ seek(0);
2002
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
2003
+ direction: 'fit-left',
2004
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
2005
+ frame: 0,
2006
+ });
2007
+ }
2008
+ else if (event.shiftKey) {
2009
+ frameBack((0, imperative_state_1.getCurrentFps)());
2010
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
2011
+ direction: 'fit-left',
2012
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
2013
+ frame: Math.max(0, getCurrentFrame() - (0, imperative_state_1.getCurrentFps)()),
2014
+ });
2015
+ }
2016
+ else {
2017
+ frameBack(1);
2018
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
2019
+ direction: 'fit-left',
2020
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
2021
+ frame: Math.max(0, getCurrentFrame() - 1),
2022
+ });
2023
+ }
2024
+ return;
2025
+ }
2026
+ if (event.altKey) {
2027
+ seek((0, imperative_state_1.getCurrentDuration)() - 1);
2028
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
2029
+ direction: 'fit-right',
2030
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)() - 1,
2031
+ frame: (0, imperative_state_1.getCurrentDuration)() - 1,
2032
+ });
2033
+ }
2034
+ else if (event.shiftKey) {
2035
+ frameForward((0, imperative_state_1.getCurrentFps)());
2036
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
2037
+ direction: 'fit-right',
2038
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
2039
+ frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, getCurrentFrame() + (0, imperative_state_1.getCurrentFps)()),
2040
+ });
2041
+ }
2042
+ else {
2043
+ frameForward(1);
2044
+ (0, timeline_scroll_logic_1.ensureFrameIsInViewport)({
2045
+ direction: 'fit-right',
2046
+ durationInFrames: (0, imperative_state_1.getCurrentDuration)(),
2047
+ frame: Math.min((0, imperative_state_1.getCurrentDuration)() - 1, getCurrentFrame() + 1),
2048
+ });
2049
+ }
2050
+ }, [frameBack, frameForward, getCurrentFrame, seek]);
2051
+ const onArrowKeyDown = (0, react_1.useCallback)((event) => {
2052
+ var _a;
2053
+ const direction = getSelectedOutlineKeyboardNudgeDirection(event.key);
2054
+ if (direction === null) {
2055
+ return;
2056
+ }
2057
+ if (selectedItems.length === 0 || allDragTargets.length === 0) {
2058
+ seekWithArrowKey(event, direction);
2059
+ return;
2060
+ }
2061
+ if (event.altKey) {
2062
+ seekWithArrowKey(event, direction);
2063
+ return;
2064
+ }
2065
+ event.preventDefault();
2066
+ const activeSession = (_a = keyboardNudgeSessionRef.current) !== null && _a !== void 0 ? _a : (() => {
2067
+ const [firstDragTarget] = allDragTargets;
2068
+ if (firstDragTarget === undefined) {
2069
+ throw new Error('Expected a drag target');
2070
+ }
2071
+ return {
2072
+ clientId: firstDragTarget.clientId,
2073
+ deltaX: 0,
2074
+ deltaY: 0,
2075
+ dragStates: getSelectedOutlineDragStates({
2076
+ dragTargets: allDragTargets,
2077
+ getDragOverrides,
2078
+ timelinePosition,
2079
+ }),
2080
+ lastValues: new Map(),
2081
+ };
2082
+ })();
2083
+ keyboardNudgeSessionRef.current = activeSession;
2084
+ const nextDeltas = (0, exports.getSelectedOutlineKeyboardNudgeDeltas)({
2085
+ deltaX: activeSession.deltaX,
2086
+ deltaY: activeSession.deltaY,
2087
+ direction,
2088
+ shiftKey: event.shiftKey,
2089
+ });
2090
+ activeSession.deltaX = nextDeltas.deltaX;
2091
+ activeSession.deltaY = nextDeltas.deltaY;
2092
+ const lastValues = (0, exports.getSelectedOutlineDragValues)({
2093
+ dragStates: activeSession.dragStates,
2094
+ deltaX: activeSession.deltaX,
2095
+ deltaY: activeSession.deltaY,
2096
+ });
2097
+ activeSession.lastValues = lastValues;
2098
+ for (const dragState of activeSession.dragStates) {
2099
+ const value = lastValues.get(dragState.key);
2100
+ if (value === undefined) {
2101
+ throw new Error('Expected drag value to be available');
2102
+ }
2103
+ if (dragState.target.propStatus.status === 'keyframed') {
2104
+ setDragOverrides(dragState.target.nodePath, translateFieldKey, remotion_1.Internals.makeKeyframedDragOverride({
2105
+ status: dragState.target.propStatus,
2106
+ frame: dragState.sourceFrame,
2107
+ value,
2108
+ }));
2109
+ }
2110
+ else {
2111
+ setDragOverrides(dragState.target.nodePath, translateFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
2112
+ }
2113
+ }
2114
+ }, [
2115
+ allDragTargets,
2116
+ getDragOverrides,
2117
+ seekWithArrowKey,
2118
+ selectedItems.length,
2119
+ setDragOverrides,
2120
+ timelinePosition,
2121
+ ]);
2122
+ const onArrowKeyUp = (0, react_1.useCallback)((event) => {
2123
+ const direction = getSelectedOutlineKeyboardNudgeDirection(event.key);
2124
+ if (direction === null || keyboardNudgeSessionRef.current === null) {
2125
+ return;
2126
+ }
2127
+ event.preventDefault();
2128
+ saveKeyboardNudgeSession();
2129
+ }, [saveKeyboardNudgeSession]);
2130
+ (0, react_1.useEffect)(() => {
2131
+ const keyDownBindings = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].map((key) => keybindings.registerKeybinding({
2132
+ event: 'keydown',
2133
+ key,
2134
+ callback: onArrowKeyDown,
2135
+ commandCtrlKey: false,
2136
+ preventDefault: false,
2137
+ triggerIfInputFieldFocused: false,
2138
+ keepRegisteredWhenNotHighestContext: false,
2139
+ }));
2140
+ const keyUpBindings = ['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].map((key) => keybindings.registerKeybinding({
2141
+ event: 'keyup',
2142
+ key,
2143
+ callback: onArrowKeyUp,
2144
+ commandCtrlKey: false,
2145
+ preventDefault: false,
2146
+ triggerIfInputFieldFocused: false,
2147
+ keepRegisteredWhenNotHighestContext: false,
2148
+ }));
2149
+ return () => {
2150
+ for (const binding of [...keyDownBindings, ...keyUpBindings]) {
2151
+ binding.unregister();
2152
+ }
2153
+ };
2154
+ }, [keybindings, onArrowKeyDown, onArrowKeyUp, saveKeyboardNudgeSession]);
1664
2155
  (0, react_1.useEffect)(() => {
1665
2156
  if (outlineTargets.length === 0) {
1666
2157
  setOutlines((prevOutlines) => prevOutlines.length === 0 ? prevOutlines : []);