@remotion/studio 4.0.473 → 4.0.475

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 (123) hide show
  1. package/dist/components/AssetSelectorItem.js +30 -6
  2. package/dist/components/Canvas.js +77 -0
  3. package/dist/components/ColorPicker/ColorPicker.js +4 -31
  4. package/dist/components/CompositionSelectorItem.js +4 -4
  5. package/dist/components/Editor.js +4 -1
  6. package/dist/components/Modals.js +2 -2
  7. package/dist/components/NewComposition/ComboBox.js +1 -0
  8. package/dist/components/NewComposition/InputDragger.d.ts +1 -0
  9. package/dist/components/NewComposition/InputDragger.js +9 -6
  10. package/dist/components/PreviewToolbar.js +2 -2
  11. package/dist/components/SelectedOutlineOverlay.d.ts +61 -33
  12. package/dist/components/SelectedOutlineOverlay.js +813 -351
  13. package/dist/components/SelectedOutlineUvControls.d.ts +17 -0
  14. package/dist/components/SelectedOutlineUvControls.js +167 -0
  15. package/dist/components/StudioCanvasCapture.d.ts +5 -0
  16. package/dist/components/StudioCanvasCapture.js +40 -0
  17. package/dist/components/Timeline/EasingEditorModal.d.ts +11 -0
  18. package/dist/components/Timeline/EasingEditorModal.js +247 -0
  19. package/dist/components/Timeline/KeyframeSettingsModal.js +5 -4
  20. package/dist/components/Timeline/SequencePropsObserver.js +3 -3
  21. package/dist/components/Timeline/Timeline.js +10 -7
  22. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +7 -7
  23. package/dist/components/Timeline/TimelineClipboardKeybindings.js +19 -16
  24. package/dist/components/Timeline/TimelineDeleteKeybindings.js +71 -40
  25. package/dist/components/Timeline/TimelineDragHandler.js +2 -2
  26. package/dist/components/Timeline/TimelineEffectItem.js +8 -9
  27. package/dist/components/Timeline/TimelineEffectPropItem.js +18 -18
  28. package/dist/components/Timeline/TimelineExpandedKeyframeRow.d.ts +1 -0
  29. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +7 -2
  30. package/dist/components/Timeline/TimelineExpandedSection.js +5 -5
  31. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +1 -1
  32. package/dist/components/Timeline/TimelineHeightContainer.js +2 -0
  33. package/dist/components/Timeline/TimelineItemStack.js +3 -56
  34. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +7 -0
  35. package/dist/components/Timeline/TimelineKeyframeControls.js +265 -68
  36. package/dist/components/Timeline/TimelineKeyframeDiamond.js +4 -3
  37. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +9 -0
  38. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +245 -0
  39. package/dist/components/Timeline/TimelineKeyframeTracksContext.d.ts +7 -0
  40. package/dist/components/Timeline/TimelineKeyframeTracksContext.js +17 -0
  41. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -1
  42. package/dist/components/Timeline/TimelineMediaInfo.js +4 -24
  43. package/dist/components/Timeline/TimelineNumberField.js +15 -7
  44. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  45. package/dist/components/Timeline/TimelineRotationField.js +22 -34
  46. package/dist/components/Timeline/TimelineScaleField.js +16 -12
  47. package/dist/components/Timeline/TimelineScrollable.js +19 -3
  48. package/dist/components/Timeline/TimelineSelection.d.ts +82 -3
  49. package/dist/components/Timeline/TimelineSelection.js +312 -30
  50. package/dist/components/Timeline/TimelineSequence.js +23 -15
  51. package/dist/components/Timeline/TimelineSequenceItem.js +48 -73
  52. package/dist/components/Timeline/TimelineSequenceName.js +3 -17
  53. package/dist/components/Timeline/TimelineSequencePropItem.js +37 -37
  54. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +5 -5
  55. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +46 -44
  56. package/dist/components/Timeline/TimelineTimeIndicators.js +4 -2
  57. package/dist/components/Timeline/TimelineTransformOriginField.d.ts +11 -0
  58. package/dist/components/Timeline/TimelineTransformOriginField.js +138 -0
  59. package/dist/components/Timeline/TimelineTranslateField.js +24 -19
  60. package/dist/components/Timeline/TimelineUvCoordinateField.js +18 -12
  61. package/dist/components/Timeline/{apply-effect-response-to-code-values.d.ts → apply-effect-response-to-prop-statuses.d.ts} +1 -1
  62. package/dist/components/Timeline/{apply-effect-response-to-code-values.js → apply-effect-response-to-prop-statuses.js} +3 -3
  63. package/dist/components/Timeline/call-add-keyframe.d.ts +22 -5
  64. package/dist/components/Timeline/call-add-keyframe.js +71 -7
  65. package/dist/components/Timeline/call-delete-keyframe.d.ts +7 -7
  66. package/dist/components/Timeline/call-delete-keyframe.js +7 -7
  67. package/dist/components/Timeline/call-move-keyframe.d.ts +3 -3
  68. package/dist/components/Timeline/call-move-keyframe.js +3 -3
  69. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +5 -5
  70. package/dist/components/Timeline/call-update-keyframe-settings.js +6 -6
  71. package/dist/components/Timeline/delete-selected-keyframe.d.ts +5 -5
  72. package/dist/components/Timeline/delete-selected-keyframe.js +5 -5
  73. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +5 -5
  74. package/dist/components/Timeline/delete-selected-timeline-item.js +28 -16
  75. package/dist/components/Timeline/get-node-keyframes.d.ts +3 -3
  76. package/dist/components/Timeline/get-node-keyframes.js +4 -4
  77. package/dist/components/Timeline/get-timeline-easing-segments.d.ts +9 -0
  78. package/dist/components/Timeline/get-timeline-easing-segments.js +19 -0
  79. package/dist/components/Timeline/reset-selected-timeline-props.d.ts +7 -7
  80. package/dist/components/Timeline/reset-selected-timeline-props.js +23 -15
  81. package/dist/components/Timeline/save-effect-prop.d.ts +2 -2
  82. package/dist/components/Timeline/save-effect-prop.js +5 -5
  83. package/dist/components/Timeline/save-prop-queue.d.ts +3 -3
  84. package/dist/components/Timeline/save-prop-queue.js +3 -3
  85. package/dist/components/Timeline/save-sequence-prop.d.ts +3 -3
  86. package/dist/components/Timeline/save-sequence-prop.js +4 -4
  87. package/dist/components/Timeline/timeline-field-utils.d.ts +10 -0
  88. package/dist/components/Timeline/timeline-field-utils.js +26 -5
  89. package/dist/components/Timeline/timeline-rotation-utils.d.ts +2 -0
  90. package/dist/components/Timeline/timeline-rotation-utils.js +32 -0
  91. package/dist/components/Timeline/timeline-translate-utils.d.ts +1 -1
  92. package/dist/components/Timeline/timeline-translate-utils.js +4 -5
  93. package/dist/components/Timeline/transform-origin-utils.d.ts +24 -0
  94. package/dist/components/Timeline/transform-origin-utils.js +170 -0
  95. package/dist/components/Timeline/update-selected-easing.d.ts +35 -0
  96. package/dist/components/Timeline/update-selected-easing.js +133 -0
  97. package/dist/components/Timeline/use-expanded-track-keyframe-rows.d.ts +1 -0
  98. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +35 -7
  99. package/dist/components/Timeline/use-sequence-props-subscription.js +3 -3
  100. package/dist/components/Timeline/use-timeline-height.js +3 -3
  101. package/dist/components/Timeline/use-timeline-keyframe-drag.js +13 -11
  102. package/dist/components/canvas-capture-enabled.d.ts +1 -0
  103. package/dist/components/canvas-capture-enabled.js +4 -0
  104. package/dist/components/effect-drag-and-drop.d.ts +11 -0
  105. package/dist/components/effect-drag-and-drop.js +73 -0
  106. package/dist/components/import-assets.d.ts +15 -0
  107. package/dist/components/import-assets.js +63 -1
  108. package/dist/components/selected-outline-geometry.d.ts +20 -0
  109. package/dist/components/selected-outline-geometry.js +18 -0
  110. package/dist/components/selected-outline-uv.d.ts +46 -0
  111. package/dist/components/selected-outline-uv.js +240 -0
  112. package/dist/esm/{chunk-q0jkt0zq.js → chunk-qaqqvw4q.js} +8096 -5307
  113. package/dist/esm/internals.mjs +8096 -5307
  114. package/dist/esm/previewEntry.mjs +8106 -5317
  115. package/dist/esm/renderEntry.mjs +1 -1
  116. package/dist/helpers/colors.d.ts +0 -1
  117. package/dist/helpers/colors.js +1 -2
  118. package/dist/helpers/timeline-layout.d.ts +6 -6
  119. package/dist/helpers/timeline-layout.js +5 -5
  120. package/dist/state/modals.d.ts +2 -4
  121. package/package.json +11 -10
  122. package/dist/components/NewComposition/DeleteStaticFile.d.ts +0 -4
  123. package/dist/components/NewComposition/DeleteStaticFile.js +0 -44
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.SelectedOutlineOverlay = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineDragValues = exports.getSequencesWithSelectableOutlines = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.getUvCoordinateForPoint = exports.getUvHandleConnectionLines = exports.getUvHandlePosition = void 0;
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;
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");
@@ -47,17 +47,25 @@ const open_in_editor_1 = require("../helpers/open-in-editor");
47
47
  const editor_outlines_1 = require("../state/editor-outlines");
48
48
  const scale_lock_1 = require("../state/scale-lock");
49
49
  const ContextMenu_1 = require("./ContextMenu");
50
+ const effect_drag_and_drop_1 = require("./effect-drag-and-drop");
51
+ const ForceSpecificCursor_1 = require("./ForceSpecificCursor");
50
52
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
53
+ const selected_outline_geometry_1 = require("./selected-outline-geometry");
54
+ const selected_outline_uv_1 = require("./selected-outline-uv");
55
+ const SelectedOutlineUvControls_1 = require("./SelectedOutlineUvControls");
51
56
  const call_add_keyframe_1 = require("./Timeline/call-add-keyframe");
52
- const save_effect_prop_1 = require("./Timeline/save-effect-prop");
57
+ const parse_keyframe_field_from_node_path_1 = require("./Timeline/parse-keyframe-field-from-node-path");
53
58
  const save_sequence_prop_1 = require("./Timeline/save-sequence-prop");
54
- const timeline_field_utils_1 = require("./Timeline/timeline-field-utils");
59
+ const timeline_rotation_utils_1 = require("./Timeline/timeline-rotation-utils");
55
60
  const timeline_translate_utils_1 = require("./Timeline/timeline-translate-utils");
56
61
  const TimelineScaleField_1 = require("./Timeline/TimelineScaleField");
57
62
  const TimelineSelection_1 = require("./Timeline/TimelineSelection");
58
63
  const get_stack_1 = require("./Timeline/TimelineStack/get-stack");
64
+ const transform_origin_utils_1 = require("./Timeline/transform-origin-utils");
59
65
  const translateFieldKey = 'style.translate';
60
66
  const scaleFieldKey = 'style.scale';
67
+ const rotateFieldKey = 'style.rotate';
68
+ const transformOriginFieldKey = 'style.transformOrigin';
61
69
  const outlineContainer = {
62
70
  position: 'absolute',
63
71
  inset: 0,
@@ -66,198 +74,74 @@ const outlineContainer = {
66
74
  };
67
75
  const emptyContextMenuValues = [];
68
76
  const pointToString = (point) => `${point.x},${point.y}`;
69
- const parseUvCoordinate = (value) => {
70
- if (Array.isArray(value) &&
71
- value.length === 2 &&
72
- value.every((item) => typeof item === 'number' && Number.isFinite(item))) {
73
- return [value[0], value[1]];
74
- }
75
- return null;
76
- };
77
- const tuplesEqual = (left, right) => {
78
- if (!Array.isArray(left) || left.length !== 2) {
79
- return false;
80
- }
81
- return left[0] === right[0] && left[1] === right[1];
82
- };
83
- const mix = (from, to, progress) => {
84
- return from + (to - from) * progress;
77
+ const midpoint = (from, to) => {
78
+ return (0, selected_outline_geometry_1.mixPoint)(from, to, 0.5);
85
79
  };
86
- const mixPoint = (from, to, progress) => {
80
+ const getOutlineCenter = (points) => {
81
+ const [tl, tr, br, bl] = points;
87
82
  return {
88
- x: mix(from.x, to.x, progress),
89
- y: mix(from.y, to.y, progress),
83
+ x: (tl.x + tr.x + br.x + bl.x) / 4,
84
+ y: (tl.y + tr.y + br.y + bl.y) / 4,
90
85
  };
91
86
  };
92
- const midpoint = (from, to) => {
93
- return mixPoint(from, to, 0.5);
94
- };
95
87
  const dot = (left, right) => {
96
88
  return left.x * right.x + left.y * right.y;
97
89
  };
98
90
  const vectorLength = (vector) => {
99
91
  return Math.hypot(vector.x, vector.y);
100
92
  };
101
- const getBilinearUvHandlePosition = (points, uv) => {
102
- const [tl, tr, br, bl] = points;
103
- const top = mixPoint(tl, tr, uv[0]);
104
- const bottom = mixPoint(bl, br, uv[0]);
105
- return mixPoint(top, bottom, uv[1]);
106
- };
107
- const projectiveEpsilon = 0.000001;
108
- const getProjectiveTransform = (points) => {
109
- const [tl, tr, br, bl] = points;
110
- const dx1 = tr.x - br.x;
111
- const dx2 = bl.x - br.x;
112
- const dx3 = tl.x - tr.x + br.x - bl.x;
113
- const dy1 = tr.y - br.y;
114
- const dy2 = bl.y - br.y;
115
- const dy3 = tl.y - tr.y + br.y - bl.y;
116
- let g = 0;
117
- let h = 0;
118
- if (Math.abs(dx3) > projectiveEpsilon || Math.abs(dy3) > projectiveEpsilon) {
119
- const determinant = dx1 * dy2 - dx2 * dy1;
120
- if (Math.abs(determinant) < projectiveEpsilon) {
121
- return null;
122
- }
123
- g = (dx3 * dy2 - dx2 * dy3) / determinant;
124
- h = (dx1 * dy3 - dx3 * dy1) / determinant;
125
- }
126
- return {
127
- a: tr.x - tl.x + g * tr.x,
128
- b: bl.x - tl.x + h * bl.x,
129
- c: tl.x,
130
- d: tr.y - tl.y + g * tr.y,
131
- e: bl.y - tl.y + h * bl.y,
132
- f: tl.y,
133
- g,
134
- h,
135
- };
136
- };
137
- const applyProjectiveTransform = (transform, uv) => {
138
- const denominator = transform.g * uv[0] + transform.h * uv[1] + 1;
139
- return {
140
- x: (transform.a * uv[0] + transform.b * uv[1] + transform.c) / denominator,
141
- y: (transform.d * uv[0] + transform.e * uv[1] + transform.f) / denominator,
142
- };
143
- };
144
- const getUvHandlePosition = (points, uv) => {
145
- const transform = getProjectiveTransform(points);
146
- return transform === null
147
- ? getBilinearUvHandlePosition(points, uv)
148
- : applyProjectiveTransform(transform, uv);
149
- };
150
- exports.getUvHandlePosition = getUvHandlePosition;
151
- const getUvHandleConnectionLines = ({ handles, points, }) => {
152
- const handlesByField = new Map(handles.map((handle) => [
153
- `${handle.effectIndex}\u0000${handle.fieldKey}`,
154
- handle,
155
- ]));
156
- const seenPairs = new Set();
157
- const lines = [];
158
- for (const handle of handles) {
159
- const targetFieldKey = handle.fieldSchema.lineTo;
160
- if (targetFieldKey === undefined || targetFieldKey === handle.fieldKey) {
161
- continue;
162
- }
163
- const target = handlesByField.get(`${handle.effectIndex}\u0000${targetFieldKey}`);
164
- if (target === undefined) {
165
- continue;
166
- }
167
- const pairKey = [
168
- handle.effectIndex,
169
- ...[handle.fieldKey, targetFieldKey].sort(),
170
- ].join('\u0000');
171
- if (seenPairs.has(pairKey)) {
172
- continue;
173
- }
174
- seenPairs.add(pairKey);
175
- lines.push({
176
- key: `${handle.effectIndex}-${handle.fieldKey}-${targetFieldKey}`,
177
- from: (0, exports.getUvHandlePosition)(points, handle.value),
178
- to: (0, exports.getUvHandlePosition)(points, target.value),
179
- });
180
- }
181
- return lines;
182
- };
183
- exports.getUvHandleConnectionLines = getUvHandleConnectionLines;
184
93
  const vectorBetween = (from, to) => {
185
94
  return { x: to.x - from.x, y: to.y - from.y };
186
95
  };
187
- const getBilinearUvCoordinateForPoint = (points, point) => {
188
- const [tl, tr, br, bl] = points;
189
- let u = 0.5;
190
- let v = 0.5;
191
- for (let i = 0; i < 8; i++) {
192
- const current = getBilinearUvHandlePosition(points, [u, v]);
193
- const errorX = current.x - point.x;
194
- const errorY = current.y - point.y;
195
- if (Math.abs(errorX) + Math.abs(errorY) < 0.001) {
196
- break;
197
- }
198
- const du = {
199
- x: mix(tr.x - tl.x, br.x - bl.x, v),
200
- y: mix(tr.y - tl.y, br.y - bl.y, v),
201
- };
202
- const dv = vectorBetween(mixPoint(tl, tr, u), mixPoint(bl, br, u));
203
- const determinant = du.x * dv.y - du.y * dv.x;
204
- if (Math.abs(determinant) < 0.000001) {
205
- break;
206
- }
207
- u -= (errorX * dv.y - errorY * dv.x) / determinant;
208
- v -= (du.x * errorY - du.y * errorX) / determinant;
209
- }
210
- return [u, v];
96
+ const getAngleDegrees = (from, to) => {
97
+ return Math.atan2(to.y - from.y, to.x - from.x) * (180 / Math.PI);
211
98
  };
212
- const getUvCoordinateForPoint = (points, point) => {
213
- const transform = getProjectiveTransform(points);
214
- if (transform === null) {
215
- return getBilinearUvCoordinateForPoint(points, point);
216
- }
217
- const determinant = transform.a * (transform.e - transform.f * transform.h) -
218
- transform.b * (transform.d - transform.f * transform.g) +
219
- transform.c * (transform.d * transform.h - transform.e * transform.g);
220
- if (Math.abs(determinant) < projectiveEpsilon) {
221
- return getBilinearUvCoordinateForPoint(points, point);
222
- }
223
- const inverseA = transform.e - transform.f * transform.h;
224
- const inverseB = transform.c * transform.h - transform.b;
225
- const inverseC = transform.b * transform.f - transform.c * transform.e;
226
- const inverseD = transform.f * transform.g - transform.d;
227
- const inverseE = transform.a - transform.c * transform.g;
228
- const inverseF = transform.c * transform.d - transform.a * transform.f;
229
- const inverseG = transform.d * transform.h - transform.e * transform.g;
230
- const inverseH = transform.b * transform.g - transform.a * transform.h;
231
- const inverseI = transform.a * transform.e - transform.b * transform.d;
232
- const denominator = inverseG * point.x + inverseH * point.y + inverseI;
233
- if (Math.abs(denominator) < projectiveEpsilon) {
234
- return getBilinearUvCoordinateForPoint(points, point);
235
- }
236
- return [
237
- (inverseA * point.x + inverseB * point.y + inverseC) / denominator,
238
- (inverseD * point.x + inverseE * point.y + inverseF) / denominator,
239
- ];
99
+ const getSelectedOutlineRotationDeltaDegrees = ({ from, to, }) => {
100
+ return ((((to - from) % 360) + 540) % 360) - 180;
240
101
  };
241
- exports.getUvCoordinateForPoint = getUvCoordinateForPoint;
242
- const clamp = (value, min, max) => {
243
- return Math.min(max, Math.max(min, value));
102
+ exports.getSelectedOutlineRotationDeltaDegrees = getSelectedOutlineRotationDeltaDegrees;
103
+ const normalizeRotationCursorDegrees = (rotation) => {
104
+ const normalizedRotation = ((rotation % 360) + 360) % 360;
105
+ return Number(normalizedRotation.toFixed(3));
244
106
  };
245
- const roundToStep = (value, step) => {
246
- if (step === undefined || !Number.isFinite(step) || step <= 0) {
247
- return value;
248
- }
249
- const decimals = (0, timeline_field_utils_1.getDecimalPlaces)(step);
250
- return Number((Math.round(value / step) * step).toFixed(decimals));
107
+ const getRotationCursor = (rotation) => {
108
+ const normalizedRotation = normalizeRotationCursorDegrees(rotation);
109
+ const transform = normalizedRotation === 0
110
+ ? ''
111
+ : `<g transform="rotate(${normalizedRotation} 32 32)">`;
112
+ const transformEnd = normalizedRotation === 0 ? '' : '</g>';
113
+ const svg = `<svg width="24" height="24" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">${transform}<g transform="scale(0.876712329)" filter="url(#filter0_d_1_14)"><path d="M10.9111 17.7687C10.3413 18.3701 10.367 19.3195 10.9684 19.8893L20.7687 29.1738C21.3701 29.7436 22.3195 29.7179 22.8893 29.1165C23.459 28.5151 23.4334 27.5657 22.832 26.996L14.1206 18.7431L22.3735 10.0316C22.9432 9.43022 22.9176 8.48082 22.3162 7.91107C21.7148 7.34133 20.7654 7.36699 20.1956 7.96839L10.9111 17.7687ZM49.3923 58.3118C49.9509 58.9235 50.8996 58.9667 51.5114 58.4081L61.481 49.3055C62.0927 48.7469 62.1359 47.7981 61.5773 47.1863C61.0187 46.5745 60.0699 46.5314 59.4581 47.09L50.5963 55.1812L42.5051 46.3194C41.9465 45.7076 40.9977 45.6645 40.386 46.2231C39.7742 46.7817 39.7311 47.7304 40.2896 48.3422L49.3923 58.3118ZM12.6747 18.7431L13 19.8893C22.1283 19.6426 30.7584 21.4283 37.8564 26.6927C44.8518 31.8809 49.734 39.8538 49 56H50.5963H51.5114C52.2774 39.1461 47.6482 30.2198 39.6436 24.2831C31.7416 18.4224 22.3717 17.2467 13 17.5L12.6747 18.7431Z" fill="black"/><path d="M19.1064 6.93652C20.2459 5.73379 22.1448 5.68278 23.3477 6.82227C24.5505 7.96181 24.6022 9.86076 23.4629 11.0635L18.7373 16.0508C26.3487 16.4239 33.9128 18.1651 40.5371 23.0781C44.7339 26.1907 48.0794 30.1189 50.2568 35.4834C51.9666 39.6958 52.9327 44.7395 53.0742 50.8867L58.4463 45.9824C59.6697 44.8654 61.5673 44.9514 62.6846 46.1748C63.8018 47.3985 63.7155 49.296 62.4922 50.4131L52.5225 59.5156C51.337 60.5979 49.5196 60.5507 48.3916 59.4346L48.2842 59.3232L39.1816 49.3535C38.0648 48.1301 38.1507 46.2324 39.374 45.1152C40.5975 43.9979 42.4961 44.0841 43.6133 45.3076L47.4756 49.5381C47.1908 44.7613 46.2876 40.9448 44.9482 37.8291C43.0666 33.4521 40.2851 30.3614 36.9629 27.8975C31.8259 24.0875 25.8071 22.1663 19.2891 21.5732L23.8633 25.9072C25.0662 27.0468 25.1178 28.9457 23.9785 30.1484C22.8746 31.3135 21.0576 31.3982 19.8516 30.3662L19.7373 30.2627L9.93652 20.9785C8.73384 19.839 8.6828 17.9401 9.82227 16.7373L19.1064 6.93652Z" stroke="white" stroke-width="3"/></g>${transformEnd}<defs><filter id="filter0_d_1_14" x="0" y="0" width="72.4696" height="72.3004" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/><feOffset dy="3"/><feGaussianBlur stdDeviation="3.75"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/><feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_1_14"/><feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_1_14" result="shape"/></filter></defs></svg>`;
114
+ return `url("data:image/svg+xml,${encodeURIComponent(svg)}") 12 12, alias`;
251
115
  };
252
- const constrainUv = (value, schema) => {
253
- var _a, _b;
254
- const min = (_a = schema.min) !== null && _a !== void 0 ? _a : -Infinity;
255
- const max = (_b = schema.max) !== null && _b !== void 0 ? _b : Infinity;
256
- return [
257
- clamp(roundToStep(value[0], schema.step), min, max),
258
- clamp(roundToStep(value[1], schema.step), min, max),
259
- ];
116
+ const rotationCursorBaseDegrees = {
117
+ 'top-left': 270,
118
+ 'top-right': 0,
119
+ 'bottom-right': 90,
120
+ 'bottom-left': 180,
121
+ };
122
+ const getOutlineRotationDegrees = (points) => {
123
+ const [tl, tr] = points;
124
+ return getAngleDegrees(tl, tr);
260
125
  };
126
+ const getRotationCursorDegrees = (points, corner) => normalizeRotationCursorDegrees(getOutlineRotationDegrees(points) + rotationCursorBaseDegrees[corner]);
127
+ const getSelectedOutlineRotationCornerInfo = (points, corner) => {
128
+ const [tl, tr, br, bl] = points;
129
+ const point = {
130
+ 'top-left': tl,
131
+ 'top-right': tr,
132
+ 'bottom-right': br,
133
+ 'bottom-left': bl,
134
+ }[corner];
135
+ const center = getOutlineCenter(points);
136
+ const cursorDegrees = getRotationCursorDegrees(points, corner);
137
+ return {
138
+ center,
139
+ cursor: getRotationCursor(cursorDegrees),
140
+ cursorDegrees,
141
+ point,
142
+ };
143
+ };
144
+ exports.getSelectedOutlineRotationCornerInfo = getSelectedOutlineRotationCornerInfo;
261
145
  const rectToPoints = (elementRect, containerRect) => {
262
146
  const left = elementRect.left - containerRect.left;
263
147
  const top = elementRect.top - containerRect.top;
@@ -300,6 +184,12 @@ const getElementOutlinePoints = (element, containerRect) => {
300
184
  return quadToPoints(quad, containerRect);
301
185
  };
302
186
  const getSelectedSequenceKeys = (selectedItems) => {
187
+ return new Set(selectedItems
188
+ .filter((item) => item.type === 'sequence')
189
+ .map((item) => (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(item.nodePathInfo)));
190
+ };
191
+ exports.getSelectedSequenceKeys = getSelectedSequenceKeys;
192
+ const getSequenceKeysContainingSelection = (selectedItems) => {
303
193
  return new Set(selectedItems.map((item) => (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(item.nodePathInfo)));
304
194
  };
305
195
  const getOutlineSelectionInteraction = ({ shiftKey, metaKey, ctrlKey, }) => ({
@@ -321,13 +211,43 @@ const getSelectedEffectFieldsBySequenceKey = (selectedItems) => {
321
211
  allFields: false,
322
212
  fieldKeys: new Set(),
323
213
  };
324
- selectedFields.allFields = true;
214
+ if (item.type === 'sequence-effect') {
215
+ selectedFields.allFields = true;
216
+ }
217
+ else {
218
+ selectedFields.fieldKeys.add(item.key);
219
+ }
325
220
  effectsForSequence.set(item.i, selectedFields);
326
221
  selectedEffects.set(sequenceKey, effectsForSequence);
327
222
  }
328
223
  return selectedEffects;
329
224
  };
330
225
  exports.getSelectedEffectFieldsBySequenceKey = getSelectedEffectFieldsBySequenceKey;
226
+ const getSelectedTransformOriginInfo = (selectedItems) => {
227
+ if (selectedItems.length !== 1) {
228
+ return null;
229
+ }
230
+ const [selectedItem] = selectedItems;
231
+ if (selectedItem.type === 'sequence-prop' &&
232
+ selectedItem.key === transformOriginFieldKey) {
233
+ return {
234
+ sequenceKey: (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(selectedItem.nodePathInfo),
235
+ displayFrame: null,
236
+ };
237
+ }
238
+ if (selectedItem.type !== 'keyframe') {
239
+ return null;
240
+ }
241
+ const field = (0, parse_keyframe_field_from_node_path_1.parseKeyframeFieldFromNodePath)(selectedItem.nodePathInfo.auxiliaryKeys);
242
+ if ((field === null || field === void 0 ? void 0 : field.type) !== 'sequence' ||
243
+ field.fieldKey !== transformOriginFieldKey) {
244
+ return null;
245
+ }
246
+ return {
247
+ sequenceKey: (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(selectedItem.nodePathInfo),
248
+ displayFrame: selectedItem.frame,
249
+ };
250
+ };
331
251
  const getSequencesWithSelectableOutlines = ({ sequences, overrideIdsToNodePaths, }) => {
332
252
  return (0, calculate_timeline_1.calculateTimeline)({
333
253
  sequences: [...sequences],
@@ -337,7 +257,8 @@ const getSequencesWithSelectableOutlines = ({ sequences, overrideIdsToNodePaths,
337
257
  if (track.nodePathInfo === null) {
338
258
  return false;
339
259
  }
340
- return track.nodePathInfo.auxiliaryKeys.length === 0;
260
+ return (track.sequence.showInTimeline &&
261
+ track.nodePathInfo.auxiliaryKeys.length === 0);
341
262
  })
342
263
  .filter((track) => track.sequence.refForOutline !== null)
343
264
  .sort((a, b) => a.depth - b.depth)
@@ -355,71 +276,6 @@ const getSequencesWithSelectableOutlines = ({ sequences, overrideIdsToNodePaths,
355
276
  });
356
277
  };
357
278
  exports.getSequencesWithSelectableOutlines = getSequencesWithSelectableOutlines;
358
- const getSelectedUvHandles = ({ codeValues, clientId, getEffectDragOverrides, nodePath, selectedEffects, sequence, }) => {
359
- if (clientId === null || selectedEffects === undefined) {
360
- return [];
361
- }
362
- const handles = [];
363
- for (const [effectIndex, selectedFields] of selectedEffects) {
364
- const effect = sequence.effects[effectIndex];
365
- if (!effect) {
366
- continue;
367
- }
368
- const effectStatus = remotion_1.Internals.getEffectCodeValuesCtx({
369
- codeValues,
370
- nodePath,
371
- effectIndex,
372
- });
373
- if (effectStatus.type !== 'can-update-effect') {
374
- continue;
375
- }
376
- const dragOverrides = getEffectDragOverrides(nodePath, effectIndex);
377
- const activeSchema = remotion_1.Internals.flattenActiveSchema(effect.schema, (key) => {
378
- const dragOverride = remotion_1.Internals.getStaticDragOverrideValue(dragOverrides[key]);
379
- if (dragOverride !== undefined) {
380
- return dragOverride;
381
- }
382
- const propStatus = effectStatus.props[key];
383
- if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static') {
384
- return undefined;
385
- }
386
- return propStatus.codeValue;
387
- });
388
- for (const [fieldKey, fieldSchema] of Object.entries(activeSchema)) {
389
- if (fieldSchema.type !== 'uv-coordinate' ||
390
- (!selectedFields.allFields && !selectedFields.fieldKeys.has(fieldKey))) {
391
- continue;
392
- }
393
- const propStatus = effectStatus.props[fieldKey];
394
- if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) !== 'static') {
395
- continue;
396
- }
397
- const dragOverrideValue = dragOverrides[fieldKey];
398
- const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
399
- codeValue: propStatus,
400
- dragOverrideValue,
401
- defaultValue: fieldSchema.default,
402
- shouldResortToDefaultValueIfUndefined: true,
403
- });
404
- const value = parseUvCoordinate(effectiveValue);
405
- if (value === null) {
406
- continue;
407
- }
408
- handles.push({
409
- clientId,
410
- codeValue: propStatus,
411
- effectIndex,
412
- fieldDefault: fieldSchema.default,
413
- fieldKey,
414
- fieldSchema,
415
- nodePath,
416
- schema: effect.schema,
417
- value,
418
- });
419
- }
420
- }
421
- return handles;
422
- };
423
279
  const measureOutlines = (container, targets) => {
424
280
  const containerRect = container.getBoundingClientRect();
425
281
  const outlines = [];
@@ -432,11 +288,21 @@ const measureOutlines = (container, targets) => {
432
288
  if (points === null) {
433
289
  continue;
434
290
  }
435
- outlines.push({ key: target.key, points });
291
+ outlines.push({
292
+ key: target.key,
293
+ dimensions: element instanceof HTMLElement
294
+ ? {
295
+ width: element.offsetWidth,
296
+ height: element.offsetHeight,
297
+ }
298
+ : null,
299
+ points,
300
+ });
436
301
  }
437
302
  return outlines;
438
303
  };
439
304
  const outlinesAreEqual = (a, b) => {
305
+ var _a, _b, _c, _d;
440
306
  if (a.length !== b.length) {
441
307
  return false;
442
308
  }
@@ -444,6 +310,10 @@ const outlinesAreEqual = (a, b) => {
444
310
  if (a[i].key !== b[i].key) {
445
311
  return false;
446
312
  }
313
+ if (((_a = a[i].dimensions) === null || _a === void 0 ? void 0 : _a.width) !== ((_b = b[i].dimensions) === null || _b === void 0 ? void 0 : _b.width) ||
314
+ ((_c = a[i].dimensions) === null || _c === void 0 ? void 0 : _c.height) !== ((_d = b[i].dimensions) === null || _d === void 0 ? void 0 : _d.height)) {
315
+ return false;
316
+ }
447
317
  for (let j = 0; j < a[i].points.length; j++) {
448
318
  if (Math.abs(a[i].points[j].x - b[i].points[j].x) > 0.01 ||
449
319
  Math.abs(a[i].points[j].y - b[i].points[j].y) > 0.01) {
@@ -459,7 +329,7 @@ const getSelectedOutlineDragStates = ({ dragTargets, getDragOverrides, timelineP
459
329
  const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[translateFieldKey];
460
330
  const sourceFrame = timelinePosition - target.keyframeDisplayOffset;
461
331
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
462
- codeValue: target.codeValue,
332
+ propStatus: target.propStatus,
463
333
  dragOverrideValue,
464
334
  defaultValue: target.fieldDefault,
465
335
  frame: sourceFrame,
@@ -485,6 +355,16 @@ const getSelectedOutlineDragValues = ({ dragStates, deltaX, deltaY, }) => {
485
355
  ]));
486
356
  };
487
357
  exports.getSelectedOutlineDragValues = getSelectedOutlineDragValues;
358
+ const applySelectedOutlineDragAxisLock = ({ deltaX, deltaY, axisLocked, }) => {
359
+ if (!axisLocked) {
360
+ return { deltaX, deltaY };
361
+ }
362
+ if (Math.abs(deltaX) >= Math.abs(deltaY)) {
363
+ return { deltaX, deltaY: 0 };
364
+ }
365
+ return { deltaX: 0, deltaY };
366
+ };
367
+ exports.applySelectedOutlineDragAxisLock = applySelectedOutlineDragAxisLock;
488
368
  const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
489
369
  const changes = [];
490
370
  for (const dragState of dragStates) {
@@ -492,7 +372,7 @@ const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
492
372
  if (value === undefined) {
493
373
  continue;
494
374
  }
495
- if (dragState.target.codeValue.status === 'keyframed') {
375
+ if (dragState.target.propStatus.status === 'keyframed') {
496
376
  const startValue = (0, timeline_translate_utils_1.serializeTranslate)(dragState.startX, dragState.startY);
497
377
  if (value === startValue) {
498
378
  continue;
@@ -510,9 +390,9 @@ const getSelectedOutlineDragChanges = ({ dragStates, lastValues, }) => {
510
390
  continue;
511
391
  }
512
392
  const stringifiedValue = JSON.stringify(value);
513
- const shouldSave = value !== dragState.target.codeValue.codeValue &&
393
+ const shouldSave = value !== dragState.target.propStatus.codeValue &&
514
394
  !(dragState.defaultValue === stringifiedValue &&
515
- dragState.target.codeValue.codeValue === undefined);
395
+ dragState.target.propStatus.codeValue === undefined);
516
396
  if (!shouldSave) {
517
397
  continue;
518
398
  }
@@ -559,7 +439,7 @@ const getSelectedOutlineScaleDragStates = ({ dragTargets, getDragOverrides, }) =
559
439
  var _a;
560
440
  const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[scaleFieldKey];
561
441
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
562
- codeValue: target.codeValue,
442
+ propStatus: target.propStatus,
563
443
  dragOverrideValue,
564
444
  defaultValue: target.fieldDefault,
565
445
  shouldResortToDefaultValueIfUndefined: true,
@@ -596,8 +476,8 @@ const getSelectedOutlineScaleDragValues = ({ axis, dragStates, scaleFactor, }) =
596
476
  max,
597
477
  })
598
478
  : axis === 'x'
599
- ? [clamp(newValue, min, max), baseY]
600
- : [baseX, clamp(newValue, min, max)];
479
+ ? [(0, selected_outline_geometry_1.clamp)(newValue, min, max), baseY]
480
+ : [baseX, (0, selected_outline_geometry_1.clamp)(newValue, min, max)];
601
481
  return [
602
482
  dragState.key,
603
483
  no_react_1.NoReactInternals.serializeScaleValue([x, y, dragState.startZ]),
@@ -613,9 +493,9 @@ const getSelectedOutlineScaleDragChanges = ({ dragStates, lastValues, }) => {
613
493
  }
614
494
  const stringifiedValue = JSON.stringify(value);
615
495
  const shouldSave = stringifiedValue !==
616
- JSON.stringify(dragState.target.codeValue.codeValue) &&
496
+ JSON.stringify(dragState.target.propStatus.codeValue) &&
617
497
  !(dragState.defaultValue === stringifiedValue &&
618
- dragState.target.codeValue.codeValue === undefined);
498
+ dragState.target.propStatus.codeValue === undefined);
619
499
  if (!shouldSave) {
620
500
  return [];
621
501
  }
@@ -632,6 +512,81 @@ const getSelectedOutlineScaleDragChanges = ({ dragStates, lastValues, }) => {
632
512
  });
633
513
  };
634
514
  exports.getSelectedOutlineScaleDragChanges = getSelectedOutlineScaleDragChanges;
515
+ const getSelectedOutlineRotationDragStates = ({ dragTargets, getDragOverrides, timelinePosition, }) => {
516
+ return dragTargets.map((target) => {
517
+ var _a;
518
+ const dragOverrideValue = ((_a = getDragOverrides(target.nodePath)) !== null && _a !== void 0 ? _a : {})[rotateFieldKey];
519
+ const sourceFrame = timelinePosition - target.keyframeDisplayOffset;
520
+ const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
521
+ propStatus: target.propStatus,
522
+ dragOverrideValue,
523
+ defaultValue: target.fieldDefault,
524
+ frame: sourceFrame,
525
+ shouldResortToDefaultValueIfUndefined: true,
526
+ });
527
+ return {
528
+ defaultValue: target.fieldDefault !== undefined
529
+ ? JSON.stringify(target.fieldDefault)
530
+ : null,
531
+ key: remotion_1.Internals.makeSequencePropsSubscriptionKey(target.nodePath),
532
+ sourceFrame,
533
+ startDegrees: (0, timeline_rotation_utils_1.parseCssRotationToDegrees)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0deg')),
534
+ target,
535
+ };
536
+ });
537
+ };
538
+ exports.getSelectedOutlineRotationDragStates = getSelectedOutlineRotationDragStates;
539
+ 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
+ ]));
544
+ };
545
+ exports.getSelectedOutlineRotationDragValues = getSelectedOutlineRotationDragValues;
546
+ const getSelectedOutlineRotationDragChanges = ({ dragStates, lastValues, }) => {
547
+ const changes = [];
548
+ for (const dragState of dragStates) {
549
+ const value = lastValues.get(dragState.key);
550
+ if (value === undefined) {
551
+ continue;
552
+ }
553
+ if (dragState.target.propStatus.status === 'keyframed') {
554
+ const startValue = (0, timeline_rotation_utils_1.serializeCssRotation)(dragState.startDegrees);
555
+ if (value === startValue) {
556
+ continue;
557
+ }
558
+ changes.push({
559
+ type: 'keyframed',
560
+ fileName: dragState.target.nodePath.absolutePath,
561
+ nodePath: dragState.target.nodePath,
562
+ fieldKey: rotateFieldKey,
563
+ sourceFrame: dragState.sourceFrame,
564
+ value,
565
+ schema: dragState.target.schema,
566
+ clientId: dragState.target.clientId,
567
+ });
568
+ continue;
569
+ }
570
+ const stringifiedValue = JSON.stringify(value);
571
+ const shouldSave = value !== dragState.target.propStatus.codeValue &&
572
+ !(dragState.defaultValue === stringifiedValue &&
573
+ dragState.target.propStatus.codeValue === undefined);
574
+ if (!shouldSave) {
575
+ continue;
576
+ }
577
+ changes.push({
578
+ type: 'static',
579
+ fileName: dragState.target.nodePath.absolutePath,
580
+ nodePath: dragState.target.nodePath,
581
+ fieldKey: rotateFieldKey,
582
+ value,
583
+ defaultValue: dragState.defaultValue,
584
+ schema: dragState.target.schema,
585
+ });
586
+ }
587
+ return changes;
588
+ };
589
+ exports.getSelectedOutlineRotationDragChanges = getSelectedOutlineRotationDragChanges;
635
590
  const clearSelectedOutlineDragOverrides = ({ clearDragOverrides, dragStates, }) => {
636
591
  for (const dragState of dragStates) {
637
592
  clearDragOverrides(dragState.target.nodePath);
@@ -642,10 +597,252 @@ const clearSelectedOutlineScaleDragOverrides = ({ clearDragOverrides, dragStates
642
597
  clearDragOverrides(dragState.target.nodePath);
643
598
  }
644
599
  };
600
+ const clearSelectedOutlineRotationDragOverrides = ({ clearDragOverrides, dragStates, }) => {
601
+ for (const dragState of dragStates) {
602
+ clearDragOverrides(dragState.target.nodePath);
603
+ }
604
+ };
605
+ const parseCssRotationToRadians = (value) => {
606
+ const match = value
607
+ .trim()
608
+ .match(/^([+-]?(?:\d+\.?\d*|\.\d+))(deg|rad|turn|grad)$/);
609
+ if (!match) {
610
+ return null;
611
+ }
612
+ const number = Number(match[1]);
613
+ if (!Number.isFinite(number)) {
614
+ return null;
615
+ }
616
+ if (match[2] === 'rad') {
617
+ return number;
618
+ }
619
+ if (match[2] === 'turn') {
620
+ return number * Math.PI * 2;
621
+ }
622
+ if (match[2] === 'grad') {
623
+ return (number / 400) * Math.PI * 2;
624
+ }
625
+ return (number / 180) * Math.PI;
626
+ };
627
+ const compensateTranslateForTransformOrigin = ({ startTranslate, deltaOrigin, rotate, scale, }) => {
628
+ const cos = Math.cos(rotate);
629
+ const sin = Math.sin(rotate);
630
+ const matrixA = cos * scale[0];
631
+ const matrixB = sin * scale[0];
632
+ const matrixC = -sin * scale[1];
633
+ const matrixD = cos * scale[1];
634
+ const transformedDeltaX = matrixA * deltaOrigin[0] + matrixC * deltaOrigin[1];
635
+ const transformedDeltaY = matrixB * deltaOrigin[0] + matrixD * deltaOrigin[1];
636
+ const compensationX = deltaOrigin[0] - transformedDeltaX;
637
+ const compensationY = deltaOrigin[1] - transformedDeltaY;
638
+ return [startTranslate[0] - compensationX, startTranslate[1] - compensationY];
639
+ };
640
+ exports.compensateTranslateForTransformOrigin = compensateTranslateForTransformOrigin;
641
+ const uvsEqual = (left, right) => Math.abs(left[0] - right[0]) < 0.000001 &&
642
+ Math.abs(left[1] - right[1]) < 0.000001;
643
+ const SelectedOutlineTransformOriginHandle = ({ outline, onDraggingChange, target }) => {
644
+ var _a;
645
+ const { setDragOverrides, clearDragOverrides, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
646
+ const transformOriginDrag = (_a = target === null || target === void 0 ? void 0 : target.transformOriginDrag) !== null && _a !== void 0 ? _a : null;
647
+ const parsed = (0, react_1.useMemo)(() => transformOriginDrag === null
648
+ ? null
649
+ : (0, transform_origin_utils_1.parseTransformOrigin)(transformOriginDrag.originValue), [transformOriginDrag]);
650
+ const uv = (0, react_1.useMemo)(() => {
651
+ if (parsed === null || outline.dimensions === null) {
652
+ return null;
653
+ }
654
+ return (0, transform_origin_utils_1.parsedTransformOriginToUv)({
655
+ parsed,
656
+ width: outline.dimensions.width,
657
+ height: outline.dimensions.height,
658
+ });
659
+ }, [outline.dimensions, parsed]);
660
+ const position = (0, react_1.useMemo)(() => (uv === null ? null : (0, selected_outline_uv_1.getUvHandlePosition)(outline.points, uv)), [outline.points, uv]);
661
+ const onPointerDown = react_1.default.useCallback((event) => {
662
+ if (event.button !== 0 ||
663
+ transformOriginDrag === null ||
664
+ parsed === null ||
665
+ uv === null ||
666
+ outline.dimensions === null) {
667
+ return;
668
+ }
669
+ event.preventDefault();
670
+ event.stopPropagation();
671
+ const svg = event.currentTarget.ownerSVGElement;
672
+ if (svg === null) {
673
+ return;
674
+ }
675
+ const rotation = parseCssRotationToRadians(transformOriginDrag.rotateValue);
676
+ if (rotation === null) {
677
+ return;
678
+ }
679
+ const { dimensions } = outline;
680
+ if (dimensions === null) {
681
+ return;
682
+ }
683
+ const [scaleX, scaleY] = no_react_1.NoReactInternals.parseScaleValue(transformOriginDrag.scaleValue);
684
+ const startTranslate = (0, timeline_translate_utils_1.parseTranslate)(transformOriginDrag.translateValue);
685
+ const svgRect = svg.getBoundingClientRect();
686
+ const defaultOrigin = transformOriginDrag.originDefault !== undefined
687
+ ? JSON.stringify(transformOriginDrag.originDefault)
688
+ : null;
689
+ const defaultTranslate = transformOriginDrag.translateDefault !== undefined
690
+ ? JSON.stringify(transformOriginDrag.translateDefault)
691
+ : null;
692
+ let last = null;
693
+ onDraggingChange(true);
694
+ (0, ForceSpecificCursor_1.forceSpecificCursor)('crosshair');
695
+ const updateFromPointerEvent = (pointerEvent) => {
696
+ const point = {
697
+ x: pointerEvent.clientX - svgRect.left,
698
+ y: pointerEvent.clientY - svgRect.top,
699
+ };
700
+ const nextUv = (0, selected_outline_uv_1.getUvCoordinateForPoint)(outline.points, point);
701
+ const deltaOrigin = [
702
+ (nextUv[0] - uv[0]) * dimensions.width,
703
+ (nextUv[1] - uv[1]) * dimensions.height,
704
+ ];
705
+ const [nextTranslateX, nextTranslateY] = (0, exports.compensateTranslateForTransformOrigin)({
706
+ startTranslate,
707
+ deltaOrigin,
708
+ rotate: rotation,
709
+ scale: [scaleX, scaleY],
710
+ });
711
+ const origin = (0, transform_origin_utils_1.serializeTransformOrigin)({
712
+ uv: nextUv,
713
+ z: parsed.z,
714
+ });
715
+ const translate = (0, timeline_translate_utils_1.serializeTranslate)(nextTranslateX, nextTranslateY);
716
+ last = { uv: nextUv, origin, translate };
717
+ setDragOverrides(transformOriginDrag.nodePath, transformOriginFieldKey, transformOriginDrag.originPropStatus.status === 'keyframed'
718
+ ? remotion_1.Internals.makeKeyframedDragOverride({
719
+ status: transformOriginDrag.originPropStatus,
720
+ frame: transformOriginDrag.sourceFrame,
721
+ value: origin,
722
+ })
723
+ : remotion_1.Internals.makeStaticDragOverride(origin));
724
+ setDragOverrides(transformOriginDrag.nodePath, translateFieldKey, transformOriginDrag.translatePropStatus.status === 'keyframed'
725
+ ? remotion_1.Internals.makeKeyframedDragOverride({
726
+ status: transformOriginDrag.translatePropStatus,
727
+ frame: transformOriginDrag.sourceFrame,
728
+ value: translate,
729
+ })
730
+ : remotion_1.Internals.makeStaticDragOverride(translate));
731
+ };
732
+ updateFromPointerEvent(event);
733
+ const onPointerMove = (moveEvent) => {
734
+ moveEvent.preventDefault();
735
+ updateFromPointerEvent(moveEvent);
736
+ };
737
+ const onPointerUp = () => {
738
+ window.removeEventListener('pointermove', onPointerMove);
739
+ window.removeEventListener('pointerup', onPointerUp);
740
+ window.removeEventListener('pointercancel', onPointerUp);
741
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
742
+ onDraggingChange(false);
743
+ if (last === null || uvsEqual(last.uv, uv)) {
744
+ clearDragOverrides(transformOriginDrag.nodePath);
745
+ return;
746
+ }
747
+ const originChanged = last.origin !== transformOriginDrag.originValue;
748
+ const translateChanged = last.translate !== transformOriginDrag.translateValue;
749
+ if (!originChanged && !translateChanged) {
750
+ clearDragOverrides(transformOriginDrag.nodePath);
751
+ return;
752
+ }
753
+ const shouldSaveAsKeyframes = transformOriginDrag.originPropStatus.status === 'keyframed' ||
754
+ transformOriginDrag.translatePropStatus.status === 'keyframed';
755
+ const promise = shouldSaveAsKeyframes
756
+ ? (0, call_add_keyframe_1.callAddKeyframes)({
757
+ sequenceKeyframes: [
758
+ originChanged
759
+ ? {
760
+ fileName: transformOriginDrag.nodePath.absolutePath,
761
+ nodePath: transformOriginDrag.nodePath,
762
+ fieldKey: transformOriginFieldKey,
763
+ sourceFrame: transformOriginDrag.sourceFrame,
764
+ value: last.origin,
765
+ schema: transformOriginDrag.schema,
766
+ }
767
+ : null,
768
+ translateChanged
769
+ ? {
770
+ fileName: transformOriginDrag.nodePath.absolutePath,
771
+ nodePath: transformOriginDrag.nodePath,
772
+ fieldKey: translateFieldKey,
773
+ sourceFrame: transformOriginDrag.sourceFrame,
774
+ value: last.translate,
775
+ schema: transformOriginDrag.schema,
776
+ }
777
+ : null,
778
+ ].filter(no_react_1.NoReactInternals.truthy),
779
+ effectKeyframes: [],
780
+ setPropStatuses,
781
+ clientId: transformOriginDrag.clientId,
782
+ })
783
+ : (0, save_sequence_prop_1.saveSequenceProps)({
784
+ changes: [
785
+ originChanged
786
+ ? {
787
+ fileName: transformOriginDrag.nodePath.absolutePath,
788
+ nodePath: transformOriginDrag.nodePath,
789
+ fieldKey: transformOriginFieldKey,
790
+ value: last.origin,
791
+ defaultValue: defaultOrigin,
792
+ schema: transformOriginDrag.schema,
793
+ }
794
+ : null,
795
+ translateChanged
796
+ ? {
797
+ fileName: transformOriginDrag.nodePath.absolutePath,
798
+ nodePath: transformOriginDrag.nodePath,
799
+ fieldKey: translateFieldKey,
800
+ value: last.translate,
801
+ defaultValue: defaultTranslate,
802
+ schema: transformOriginDrag.schema,
803
+ }
804
+ : null,
805
+ ].filter(no_react_1.NoReactInternals.truthy),
806
+ setPropStatuses,
807
+ clientId: transformOriginDrag.clientId,
808
+ undoLabel: 'Move transform origin',
809
+ redoLabel: 'Move transform origin back',
810
+ });
811
+ promise
812
+ .catch((err) => {
813
+ (0, NotificationCenter_1.showNotification)(`Could not save transform origin: ${err instanceof Error ? err.message : String(err)}`, 4000);
814
+ })
815
+ .finally(() => {
816
+ clearDragOverrides(transformOriginDrag.nodePath);
817
+ });
818
+ };
819
+ window.addEventListener('pointermove', onPointerMove);
820
+ window.addEventListener('pointerup', onPointerUp);
821
+ window.addEventListener('pointercancel', onPointerUp);
822
+ }, [
823
+ clearDragOverrides,
824
+ onDraggingChange,
825
+ outline,
826
+ parsed,
827
+ setDragOverrides,
828
+ setPropStatuses,
829
+ transformOriginDrag,
830
+ uv,
831
+ ]);
832
+ if (transformOriginDrag === null ||
833
+ parsed === null ||
834
+ uv === null ||
835
+ position === null) {
836
+ return null;
837
+ }
838
+ 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" })
840
+ ] }));
841
+ };
645
842
  const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, hovered, onContextMenuOpen, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
646
- var _a, _b;
843
+ var _a, _b, _c, _d;
647
844
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
648
- const { setCodeValues, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
845
+ const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
649
846
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
650
847
  const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
651
848
  timelinePositionRef.current = timelinePosition;
@@ -653,7 +850,10 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
653
850
  const points = (0, react_1.useMemo)(() => outline.points.map(pointToString).join(' '), [outline.points]);
654
851
  const drag = (_a = target === null || target === void 0 ? void 0 : target.drag) !== null && _a !== void 0 ? _a : null;
655
852
  const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
656
- const visible = selected || hovered;
853
+ const containsSelection = (_c = target === null || target === void 0 ? void 0 : target.containsSelection) !== null && _c !== void 0 ? _c : false;
854
+ const effectDrop = (_d = target === null || target === void 0 ? void 0 : target.effectDrop) !== null && _d !== void 0 ? _d : null;
855
+ const [effectDropHovered, setEffectDropHovered] = (0, react_1.useState)(false);
856
+ const visible = containsSelection || hovered;
657
857
  const onPointerDown = react_1.default.useCallback((event) => {
658
858
  if (event.button !== 0 || target === undefined) {
659
859
  return;
@@ -677,21 +877,28 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
677
877
  timelinePosition: timelinePositionRef.current,
678
878
  });
679
879
  let lastValues = new Map();
680
- const onPointerMove = (moveEvent) => {
681
- moveEvent.preventDefault();
880
+ let currentPointerX = startPointerX;
881
+ let currentPointerY = startPointerY;
882
+ let axisLocked = false;
883
+ const updateDragOverrides = () => {
884
+ const dragDelta = (0, exports.applySelectedOutlineDragAxisLock)({
885
+ deltaX: (currentPointerX - startPointerX) / scale,
886
+ deltaY: (currentPointerY - startPointerY) / scale,
887
+ axisLocked,
888
+ });
682
889
  lastValues = (0, exports.getSelectedOutlineDragValues)({
683
890
  dragStates,
684
- deltaX: (moveEvent.clientX - startPointerX) / scale,
685
- deltaY: (moveEvent.clientY - startPointerY) / scale,
891
+ deltaX: dragDelta.deltaX,
892
+ deltaY: dragDelta.deltaY,
686
893
  });
687
894
  for (const dragState of dragStates) {
688
895
  const value = lastValues.get(dragState.key);
689
896
  if (value === undefined) {
690
897
  throw new Error('Expected drag value to be available');
691
898
  }
692
- if (dragState.target.codeValue.status === 'keyframed') {
899
+ if (dragState.target.propStatus.status === 'keyframed') {
693
900
  setDragOverrides(dragState.target.nodePath, translateFieldKey, remotion_1.Internals.makeKeyframedDragOverride({
694
- status: dragState.target.codeValue,
901
+ status: dragState.target.propStatus,
695
902
  frame: dragState.sourceFrame,
696
903
  value,
697
904
  }));
@@ -701,10 +908,30 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
701
908
  }
702
909
  }
703
910
  };
911
+ const onPointerMove = (moveEvent) => {
912
+ moveEvent.preventDefault();
913
+ currentPointerX = moveEvent.clientX;
914
+ currentPointerY = moveEvent.clientY;
915
+ axisLocked = moveEvent.shiftKey;
916
+ updateDragOverrides();
917
+ };
918
+ const onKeyChange = (keyEvent) => {
919
+ if (keyEvent.key !== 'Shift') {
920
+ return;
921
+ }
922
+ const nextAxisLocked = keyEvent.type === 'keydown';
923
+ if (nextAxisLocked === axisLocked) {
924
+ return;
925
+ }
926
+ axisLocked = nextAxisLocked;
927
+ updateDragOverrides();
928
+ };
704
929
  const onPointerUp = () => {
705
930
  window.removeEventListener('pointermove', onPointerMove);
706
931
  window.removeEventListener('pointerup', onPointerUp);
707
932
  window.removeEventListener('pointercancel', onPointerUp);
933
+ window.removeEventListener('keydown', onKeyChange);
934
+ window.removeEventListener('keyup', onKeyChange);
708
935
  onDraggingChange(false);
709
936
  const changes = (0, exports.getSelectedOutlineDragChanges)({
710
937
  dragStates,
@@ -720,7 +947,7 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
720
947
  staticChanges.length > 0
721
948
  ? (0, save_sequence_prop_1.saveSequenceProps)({
722
949
  changes: staticChanges,
723
- setCodeValues,
950
+ setPropStatuses,
724
951
  clientId: drag.clientId,
725
952
  undoLabel: changes.length > 1
726
953
  ? 'Move selected sequences'
@@ -737,7 +964,7 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
737
964
  sourceFrame: change.sourceFrame,
738
965
  value: change.value,
739
966
  schema: change.schema,
740
- setCodeValues,
967
+ setPropStatuses,
741
968
  clientId: change.clientId,
742
969
  })),
743
970
  ])
@@ -751,6 +978,8 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
751
978
  window.addEventListener('pointermove', onPointerMove);
752
979
  window.addEventListener('pointerup', onPointerUp);
753
980
  window.addEventListener('pointercancel', onPointerUp);
981
+ window.addEventListener('keydown', onKeyChange);
982
+ window.addEventListener('keyup', onKeyChange);
754
983
  }, [
755
984
  allDragTargets,
756
985
  clearDragOverrides,
@@ -760,12 +989,51 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
760
989
  onSelect,
761
990
  scale,
762
991
  selected,
763
- setCodeValues,
992
+ setPropStatuses,
764
993
  setDragOverrides,
765
994
  target,
766
995
  ]);
996
+ const onEffectDragOver = react_1.default.useCallback((event) => {
997
+ if (effectDrop === null || !(0, effect_drag_and_drop_1.hasEffectDragType)(event.dataTransfer)) {
998
+ return;
999
+ }
1000
+ event.preventDefault();
1001
+ event.stopPropagation();
1002
+ event.dataTransfer.dropEffect = 'copy';
1003
+ setEffectDropHovered(true);
1004
+ }, [effectDrop]);
1005
+ const onEffectDragLeave = react_1.default.useCallback((event) => {
1006
+ if (event.currentTarget.contains(event.relatedTarget)) {
1007
+ return;
1008
+ }
1009
+ setEffectDropHovered(false);
1010
+ }, []);
1011
+ const onEffectDrop = react_1.default.useCallback(async (event) => {
1012
+ if (effectDrop === null || !(0, effect_drag_and_drop_1.hasEffectDragType)(event.dataTransfer)) {
1013
+ return;
1014
+ }
1015
+ const dragData = (0, effect_drag_and_drop_1.getEffectDragData)(event.dataTransfer);
1016
+ if (!dragData) {
1017
+ if ((0, effect_drag_and_drop_1.hasExplicitEffectDragType)(event.dataTransfer)) {
1018
+ event.preventDefault();
1019
+ event.stopPropagation();
1020
+ setEffectDropHovered(false);
1021
+ (0, NotificationCenter_1.showNotification)('Could not read effect drag data', 3000);
1022
+ }
1023
+ return;
1024
+ }
1025
+ event.preventDefault();
1026
+ event.stopPropagation();
1027
+ setEffectDropHovered(false);
1028
+ await (0, effect_drag_and_drop_1.addEffectFromDragData)({
1029
+ dragData,
1030
+ fileName: effectDrop.fileName,
1031
+ nodePath: effectDrop.nodePath,
1032
+ clientId: effectDrop.clientId,
1033
+ });
1034
+ }, [effectDrop]);
767
1035
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
768
- jsx_runtime_1.jsx("polygon", { ref: polygonRef, points: points, fill: "transparent", stroke: colors_1.BLUE, strokeOpacity: visible ? 1 : 0, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: target === undefined ? undefined : 'all', onPointerEnter: () => {
1036
+ jsx_runtime_1.jsx("polygon", { ref: polygonRef, points: points, fill: effectDropHovered ? 'rgba(0, 155, 255, 0.12)' : 'transparent', stroke: colors_1.BLUE, strokeOpacity: visible || effectDropHovered ? 1 : 0, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: target === undefined ? undefined : 'all', onPointerEnter: () => {
769
1037
  if (!dragging) {
770
1038
  onHoverChange(outline.key);
771
1039
  }
@@ -773,13 +1041,13 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
773
1041
  if (!dragging) {
774
1042
  onHoverChange(null);
775
1043
  }
776
- }, onPointerDown: onPointerDown }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: polygonRef, values: [...contextMenuValues], onOpen: onContextMenuOpen })
1044
+ }, onPointerDown: onPointerDown, onDragOver: effectDrop === null ? undefined : onEffectDragOver, onDragLeave: effectDrop === null ? undefined : onEffectDragLeave, onDrop: effectDrop === null ? undefined : onEffectDrop }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: polygonRef, values: [...contextMenuValues], onOpen: onContextMenuOpen })
777
1045
  ] }));
778
1046
  };
779
1047
  const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues, dragging, edge, outline, onDraggingChange, onContextMenuOpen, onHoverChange, onSelect, target, }) => {
780
1048
  var _a, _b;
781
1049
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
782
- const { setCodeValues, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
1050
+ const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
783
1051
  const scaleDrag = (_a = target === null || target === void 0 ? void 0 : target.scaleDrag) !== null && _a !== void 0 ? _a : null;
784
1052
  const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
785
1053
  const lineRef = (0, react_1.useRef)(null);
@@ -844,7 +1112,7 @@ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues,
844
1112
  }
845
1113
  (0, save_sequence_prop_1.saveSequenceProps)({
846
1114
  changes,
847
- setCodeValues,
1115
+ setPropStatuses,
848
1116
  clientId: scaleDrag.clientId,
849
1117
  undoLabel: changes.length > 1 ? 'Scale selected sequences' : 'Scale sequence',
850
1118
  redoLabel: changes.length > 1
@@ -873,7 +1141,7 @@ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues,
873
1141
  onSelect,
874
1142
  scaleDrag,
875
1143
  selected,
876
- setCodeValues,
1144
+ setPropStatuses,
877
1145
  setDragOverrides,
878
1146
  target,
879
1147
  ]);
@@ -892,21 +1160,25 @@ const SelectedOutlineScaleEdgeLine = ({ allScaleDragTargets, contextMenuValues,
892
1160
  }, onPointerDown: onPointerDown }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: lineRef, values: [...contextMenuValues], onOpen: onContextMenuOpen })
893
1161
  ] }));
894
1162
  };
895
- const getSvgPointFromPointerEvent = ({ event, rect, }) => {
1163
+ const svgPointToClientPoint = (point, rect) => {
896
1164
  return {
897
- x: event.clientX - rect.left,
898
- y: event.clientY - rect.top,
1165
+ x: point.x + rect.left,
1166
+ y: point.y + rect.top,
899
1167
  };
900
1168
  };
901
- const SelectedUvHandleConnectionLines = ({ handles, outline }) => {
902
- const lines = (0, react_1.useMemo)(() => (0, exports.getUvHandleConnectionLines)({ handles, points: outline.points }), [handles, outline.points]);
903
- return (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: lines.map((line) => (jsx_runtime_1.jsx("line", { x1: line.from.x, y1: line.from.y, x2: line.to.x, y2: line.to.y, stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: "none" }, line.key))) }));
904
- };
905
- const SelectedUvHandleCircle = ({ handle, onDraggingChange, outline }) => {
906
- const { setEffectDragOverrides, clearEffectDragOverrides, setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
907
- const position = (0, react_1.useMemo)(() => (0, exports.getUvHandlePosition)(outline.points, handle.value), [handle.value, outline.points]);
1169
+ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMenuValues, corner, dragging, outline, onDraggingChange, onContextMenuOpen, onHoverChange, onSelect, target, }) => {
1170
+ var _a, _b;
1171
+ const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
1172
+ const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
1173
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
1174
+ const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
1175
+ timelinePositionRef.current = timelinePosition;
1176
+ const rotationDrag = (_a = target === null || target === void 0 ? void 0 : target.rotationDrag) !== null && _a !== void 0 ? _a : null;
1177
+ const selected = (_b = target === null || target === void 0 ? void 0 : target.selected) !== null && _b !== void 0 ? _b : false;
1178
+ const circleRef = (0, react_1.useRef)(null);
1179
+ const cornerInfo = (0, react_1.useMemo)(() => (0, exports.getSelectedOutlineRotationCornerInfo)(outline.points, corner), [corner, outline.points]);
908
1180
  const onPointerDown = react_1.default.useCallback((event) => {
909
- if (event.button !== 0) {
1181
+ if (event.button !== 0 || rotationDrag === null) {
910
1182
  return;
911
1183
  }
912
1184
  event.preventDefault();
@@ -915,69 +1187,148 @@ const SelectedUvHandleCircle = ({ handle, onDraggingChange, outline }) => {
915
1187
  if (svg === null) {
916
1188
  return;
917
1189
  }
918
- const svgRect = svg.getBoundingClientRect();
919
- let lastValue = null;
1190
+ const interaction = (0, exports.getOutlineSelectionInteraction)(event);
1191
+ const shouldUpdateSelection = !selected || interaction.shiftKey || interaction.toggleKey;
1192
+ if (shouldUpdateSelection && target !== undefined) {
1193
+ onSelect(target.selection, interaction);
1194
+ }
1195
+ if (interaction.shiftKey || interaction.toggleKey) {
1196
+ return;
1197
+ }
920
1198
  onDraggingChange(true);
921
- const defaultValue = handle.fieldDefault !== undefined
922
- ? JSON.stringify(handle.fieldDefault)
923
- : null;
924
- const updateFromPointerEvent = (pointerEvent) => {
925
- const point = getSvgPointFromPointerEvent({
926
- event: pointerEvent,
927
- rect: svgRect,
928
- });
929
- const nextValue = constrainUv((0, exports.getUvCoordinateForPoint)(outline.points, point), handle.fieldSchema);
930
- lastValue = nextValue;
931
- setEffectDragOverrides(handle.nodePath, handle.effectIndex, handle.fieldKey, remotion_1.Internals.makeStaticDragOverride(nextValue));
932
- };
933
- updateFromPointerEvent(event);
1199
+ (0, ForceSpecificCursor_1.forceSpecificCursor)(cornerInfo.cursor);
1200
+ const svgRect = svg.getBoundingClientRect();
1201
+ const center = svgPointToClientPoint(cornerInfo.center, svgRect);
1202
+ const dragStates = (0, exports.getSelectedOutlineRotationDragStates)({
1203
+ dragTargets: selected ? allRotationDragTargets : [rotationDrag],
1204
+ getDragOverrides,
1205
+ timelinePosition: timelinePositionRef.current,
1206
+ });
1207
+ let previousAngle = getAngleDegrees(center, {
1208
+ x: event.clientX,
1209
+ y: event.clientY,
1210
+ });
1211
+ let accumulatedDelta = 0;
1212
+ let lastValues = new Map();
934
1213
  const onPointerMove = (moveEvent) => {
935
1214
  moveEvent.preventDefault();
936
- updateFromPointerEvent(moveEvent);
1215
+ const nextAngle = getAngleDegrees(center, {
1216
+ x: moveEvent.clientX,
1217
+ y: moveEvent.clientY,
1218
+ });
1219
+ accumulatedDelta += (0, exports.getSelectedOutlineRotationDeltaDegrees)({
1220
+ from: previousAngle,
1221
+ to: nextAngle,
1222
+ });
1223
+ previousAngle = nextAngle;
1224
+ lastValues = (0, exports.getSelectedOutlineRotationDragValues)({
1225
+ dragStates,
1226
+ rotationDeltaDegrees: accumulatedDelta,
1227
+ });
1228
+ (0, ForceSpecificCursor_1.forceSpecificCursor)(getRotationCursor(cornerInfo.cursorDegrees + accumulatedDelta));
1229
+ for (const dragState of dragStates) {
1230
+ const value = lastValues.get(dragState.key);
1231
+ if (value === undefined) {
1232
+ throw new Error('Expected rotation drag value to be available');
1233
+ }
1234
+ if (dragState.target.propStatus.status === 'keyframed') {
1235
+ setDragOverrides(dragState.target.nodePath, rotateFieldKey, remotion_1.Internals.makeKeyframedDragOverride({
1236
+ status: dragState.target.propStatus,
1237
+ frame: dragState.sourceFrame,
1238
+ value,
1239
+ }));
1240
+ }
1241
+ else {
1242
+ setDragOverrides(dragState.target.nodePath, rotateFieldKey, remotion_1.Internals.makeStaticDragOverride(value));
1243
+ }
1244
+ }
937
1245
  };
938
1246
  const onPointerUp = () => {
939
1247
  window.removeEventListener('pointermove', onPointerMove);
940
1248
  window.removeEventListener('pointerup', onPointerUp);
941
1249
  window.removeEventListener('pointercancel', onPointerUp);
1250
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
942
1251
  onDraggingChange(false);
943
- const stringifiedValue = lastValue === null ? null : JSON.stringify(lastValue);
944
- const shouldSave = lastValue !== null &&
945
- !tuplesEqual(handle.codeValue.codeValue, lastValue) &&
946
- !(defaultValue === stringifiedValue &&
947
- handle.codeValue.codeValue === undefined);
948
- if (!shouldSave) {
949
- clearEffectDragOverrides(handle.nodePath, handle.effectIndex);
1252
+ const changes = (0, exports.getSelectedOutlineRotationDragChanges)({
1253
+ dragStates,
1254
+ lastValues,
1255
+ });
1256
+ if (changes.length === 0) {
1257
+ clearSelectedOutlineRotationDragOverrides({
1258
+ clearDragOverrides,
1259
+ dragStates,
1260
+ });
950
1261
  return;
951
1262
  }
952
- (0, save_effect_prop_1.saveEffectProp)({
953
- type: 'value',
954
- fileName: handle.nodePath.absolutePath,
955
- nodePath: handle.nodePath,
956
- effectIndex: handle.effectIndex,
957
- fieldKey: handle.fieldKey,
958
- value: lastValue,
959
- defaultValue,
960
- schema: handle.schema,
961
- setCodeValues,
962
- clientId: handle.clientId,
963
- }).finally(() => {
964
- clearEffectDragOverrides(handle.nodePath, handle.effectIndex);
1263
+ const staticChanges = changes.filter((change) => change.type === 'static');
1264
+ const keyframedChanges = changes.filter((change) => change.type === 'keyframed');
1265
+ Promise.all([
1266
+ staticChanges.length > 0
1267
+ ? (0, save_sequence_prop_1.saveSequenceProps)({
1268
+ changes: staticChanges,
1269
+ setPropStatuses,
1270
+ clientId: rotationDrag.clientId,
1271
+ undoLabel: changes.length > 1
1272
+ ? 'Rotate selected sequences'
1273
+ : 'Rotate sequence',
1274
+ redoLabel: changes.length > 1
1275
+ ? 'Rotate selected sequences back'
1276
+ : 'Rotate sequence back',
1277
+ })
1278
+ : Promise.resolve(),
1279
+ ...keyframedChanges.map((change) => (0, call_add_keyframe_1.callAddSequenceKeyframe)({
1280
+ fileName: change.fileName,
1281
+ nodePath: change.nodePath,
1282
+ fieldKey: change.fieldKey,
1283
+ sourceFrame: change.sourceFrame,
1284
+ value: change.value,
1285
+ schema: change.schema,
1286
+ setPropStatuses,
1287
+ clientId: change.clientId,
1288
+ })),
1289
+ ])
1290
+ .catch((err) => {
1291
+ (0, NotificationCenter_1.showNotification)(`Could not save sequence props: ${err instanceof Error ? err.message : String(err)}`, 4000);
1292
+ })
1293
+ .finally(() => {
1294
+ clearSelectedOutlineRotationDragOverrides({
1295
+ clearDragOverrides,
1296
+ dragStates,
1297
+ });
965
1298
  });
966
1299
  };
967
1300
  window.addEventListener('pointermove', onPointerMove);
968
1301
  window.addEventListener('pointerup', onPointerUp);
969
1302
  window.addEventListener('pointercancel', onPointerUp);
970
1303
  }, [
971
- clearEffectDragOverrides,
972
- handle,
1304
+ allRotationDragTargets,
1305
+ clearDragOverrides,
1306
+ cornerInfo,
1307
+ getDragOverrides,
973
1308
  onDraggingChange,
974
- outline.points,
975
- setCodeValues,
976
- setEffectDragOverrides,
1309
+ onSelect,
1310
+ rotationDrag,
1311
+ selected,
1312
+ setPropStatuses,
1313
+ setDragOverrides,
1314
+ target,
977
1315
  ]);
978
- return (jsx_runtime_1.jsx("circle", { cx: position.x, cy: position.y, r: 6, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: "all", cursor: "move", onPointerDown: onPointerDown }));
1316
+ if (rotationDrag === null) {
1317
+ return null;
1318
+ }
1319
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1320
+ jsx_runtime_1.jsx("circle", { ref: circleRef, cx: cornerInfo.point.x, cy: cornerInfo.point.y, r: 12, fill: "transparent", stroke: "transparent", vectorEffect: "non-scaling-stroke", pointerEvents: "all", cursor: cornerInfo.cursor, onPointerEnter: () => {
1321
+ if (!dragging) {
1322
+ onHoverChange(outline.key);
1323
+ }
1324
+ }, onPointerLeave: () => {
1325
+ if (!dragging) {
1326
+ onHoverChange(null);
1327
+ }
1328
+ }, onPointerDown: onPointerDown }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: circleRef, values: [...contextMenuValues], onOpen: onContextMenuOpen })
1329
+ ] }));
979
1330
  };
980
- const SelectedOutlineElement = ({ allDragTargets, allScaleDragTargets, dragging, hovered, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
1331
+ const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allScaleDragTargets, dragging, hovered, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
981
1332
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
982
1333
  const updateResolvedStackTrace = (0, react_1.useContext)(remotion_1.Internals.SequenceStackTracesUpdateContext);
983
1334
  const onContextMenuOpen = react_1.default.useCallback(async () => {
@@ -1054,25 +1405,23 @@ const SelectedOutlineElement = ({ allDragTargets, allScaleDragTargets, dragging,
1054
1405
  ].filter(no_react_1.NoReactInternals.truthy);
1055
1406
  }, [onSelect, previewServerState.type, target, updateResolvedStackTrace]);
1056
1407
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1057
- jsx_runtime_1.jsx(SelectedOutlinePolygon, { allDragTargets: allDragTargets, contextMenuValues: emptyContextMenuValues, dragging: dragging, hovered: hovered, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, scale: scale, target: target }), (target === null || target === void 0 ? void 0 : target.selected) || hovered
1408
+ 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
1058
1409
  ? ['top', 'right', 'bottom', 'left'].map((edge) => (jsx_runtime_1.jsx(SelectedOutlineScaleEdgeLine, { allScaleDragTargets: allScaleDragTargets, contextMenuValues: emptyContextMenuValues, dragging: dragging, edge: edge, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, target: target }, edge)))
1059
- : null, (target === null || target === void 0 ? void 0 : target.selected)
1060
- ? (() => {
1061
- const { uvHandles } = target;
1062
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1063
- jsx_runtime_1.jsx(SelectedUvHandleConnectionLines, { handles: uvHandles, outline: outline }), uvHandles.map((handle) => (jsx_runtime_1.jsx(SelectedUvHandleCircle, { handle: handle, onDraggingChange: onDraggingChange, outline: outline }, `${handle.effectIndex}-${handle.fieldKey}`)))] }));
1064
- })()
1065
- : null] }));
1410
+ : null, (target === null || target === void 0 ? void 0 : target.containsSelection) || hovered
1411
+ ? ['top-left', 'top-right', 'bottom-right', 'bottom-left'].map((corner) => (jsx_runtime_1.jsx(SelectedOutlineRotationCornerHandle, { allRotationDragTargets: allRotationDragTargets, contextMenuValues: emptyContextMenuValues, corner: corner, dragging: dragging, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, target: target }, corner)))
1412
+ : null, jsx_runtime_1.jsx(SelectedOutlineTransformOriginHandle, { outline: outline, onDraggingChange: onDraggingChange, target: target })
1413
+ ] }));
1066
1414
  };
1067
1415
  const SelectedOutlineOverlay = ({ scale }) => {
1068
1416
  const { selectedItems, selectItem } = (0, TimelineSelection_1.useTimelineSelection)();
1069
1417
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
1070
- const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
1418
+ const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
1071
1419
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
1072
1420
  const { overrideIdToNodePathMappings } = (0, react_1.useContext)(remotion_1.Internals.OverrideIdsToNodePathsGettersContext);
1073
1421
  const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
1074
1422
  const { getScaleLockState } = (0, react_1.useContext)(scale_lock_1.ScaleLockContext);
1075
1423
  const { editorShowOutlines } = (0, react_1.useContext)(editor_outlines_1.EditorShowOutlinesContext);
1424
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
1076
1425
  const [outlines, setOutlines] = (0, react_1.useState)([]);
1077
1426
  const [hoveredOutlineKey, setHoveredOutlineKey] = (0, react_1.useState)(null);
1078
1427
  const [draggingOutline, setDraggingOutline] = (0, react_1.useState)(false);
@@ -1084,11 +1433,13 @@ const SelectedOutlineOverlay = ({ scale }) => {
1084
1433
  }
1085
1434
  }, []);
1086
1435
  const outlineTargets = (0, react_1.useMemo)(() => {
1087
- if (!TimelineSelection_1.ENABLE_OUTLINES || !editorShowOutlines) {
1436
+ if (!editorShowOutlines) {
1088
1437
  return [];
1089
1438
  }
1090
- const selectedSequenceKeys = getSelectedSequenceKeys(selectedItems);
1439
+ const selectedSequenceKeys = (0, exports.getSelectedSequenceKeys)(selectedItems);
1440
+ const sequenceKeysContainingSelection = getSequenceKeysContainingSelection(selectedItems);
1091
1441
  const selectedEffectsBySequenceKey = (0, exports.getSelectedEffectFieldsBySequenceKey)(selectedItems);
1442
+ const selectedTransformOriginInfo = getSelectedTransformOriginInfo(selectedItems);
1092
1443
  const clientId = previewServerState.type === 'connected'
1093
1444
  ? previewServerState.clientId
1094
1445
  : null;
@@ -1096,20 +1447,30 @@ const SelectedOutlineOverlay = ({ scale }) => {
1096
1447
  sequences,
1097
1448
  overrideIdsToNodePaths: overrideIdToNodePathMappings,
1098
1449
  }).map(({ key, keyframeDisplayOffset, nodePathInfo, sequence }) => {
1099
- var _a, _b;
1450
+ var _a;
1451
+ var _b, _c, _d, _e, _f, _g, _h, _j;
1100
1452
  if (sequence.refForOutline === null) {
1101
1453
  throw new Error('Expected sequence to have a ref for outline');
1102
1454
  }
1103
1455
  const selected = selectedSequenceKeys.has(key);
1456
+ const containsSelection = sequenceKeysContainingSelection.has(key);
1104
1457
  const nodePath = nodePathInfo.sequenceSubscriptionKey;
1105
1458
  const { controls } = sequence;
1106
1459
  const fieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[translateFieldKey];
1107
- const codeValue = (_a = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _a === void 0 ? void 0 : _a[translateFieldKey];
1460
+ const nodePropStatuses = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath);
1461
+ const propStatus = nodePropStatuses === null || nodePropStatuses === void 0 ? void 0 : nodePropStatuses[translateFieldKey];
1108
1462
  const scaleFieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[scaleFieldKey];
1109
- const scaleCodeValue = (_b = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _b === void 0 ? void 0 : _b[scaleFieldKey];
1110
- const canDragStatus = (codeValue === null || codeValue === void 0 ? void 0 : codeValue.status) === 'static' ||
1111
- ((codeValue === null || codeValue === void 0 ? void 0 : codeValue.status) === 'keyframed' &&
1112
- codeValue.interpolationFunction === 'interpolate');
1463
+ const scalePropStatus = nodePropStatuses === null || nodePropStatuses === void 0 ? void 0 : nodePropStatuses[scaleFieldKey];
1464
+ const rotationFieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[rotateFieldKey];
1465
+ const rotationPropStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[rotateFieldKey];
1466
+ const transformOriginFieldSchema = controls === null || controls === void 0 ? void 0 : controls.schema[transformOriginFieldKey];
1467
+ const transformOriginPropStatus = nodePropStatuses === null || nodePropStatuses === void 0 ? void 0 : nodePropStatuses[transformOriginFieldKey];
1468
+ const canDragStatus = (propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) === 'static' ||
1469
+ ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) === 'keyframed' &&
1470
+ propStatus.interpolationFunction === 'interpolate');
1471
+ const canRotationDragStatus = (rotationPropStatus === null || rotationPropStatus === void 0 ? void 0 : rotationPropStatus.status) === 'static' ||
1472
+ ((rotationPropStatus === null || rotationPropStatus === void 0 ? void 0 : rotationPropStatus.status) === 'keyframed' &&
1473
+ rotationPropStatus.interpolationFunction === 'interpolate');
1113
1474
  const canDrag = previewServerState.type === 'connected' &&
1114
1475
  controls !== null &&
1115
1476
  (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) === 'translate' &&
@@ -1117,9 +1478,41 @@ const SelectedOutlineOverlay = ({ scale }) => {
1117
1478
  const canScaleDrag = previewServerState.type === 'connected' &&
1118
1479
  controls !== null &&
1119
1480
  (scaleFieldSchema === null || scaleFieldSchema === void 0 ? void 0 : scaleFieldSchema.type) === 'scale' &&
1120
- (scaleCodeValue === null || scaleCodeValue === void 0 ? void 0 : scaleCodeValue.status) === 'static';
1481
+ (scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'static';
1482
+ const canRotationDrag = previewServerState.type === 'connected' &&
1483
+ controls !== null &&
1484
+ (rotationFieldSchema === null || rotationFieldSchema === void 0 ? void 0 : rotationFieldSchema.type) === 'rotation-css' &&
1485
+ canRotationDragStatus;
1486
+ const selectedForTransformOrigin = (selectedTransformOriginInfo === null || selectedTransformOriginInfo === void 0 ? void 0 : selectedTransformOriginInfo.sequenceKey) === key;
1487
+ const transformOriginSourceFrame = (selectedTransformOriginInfo === null || selectedTransformOriginInfo === void 0 ? void 0 : selectedTransformOriginInfo.displayFrame) === null ||
1488
+ (selectedTransformOriginInfo === null || selectedTransformOriginInfo === void 0 ? void 0 : selectedTransformOriginInfo.displayFrame) === undefined
1489
+ ? timelinePosition - keyframeDisplayOffset
1490
+ : selectedTransformOriginInfo.displayFrame - keyframeDisplayOffset;
1491
+ const canTransformOriginStatus = (transformOriginPropStatus === null || transformOriginPropStatus === void 0 ? void 0 : transformOriginPropStatus.status) === 'static' ||
1492
+ ((transformOriginPropStatus === null || transformOriginPropStatus === void 0 ? void 0 : transformOriginPropStatus.status) === 'keyframed' &&
1493
+ transformOriginPropStatus.interpolationFunction === 'interpolate');
1494
+ const canTransformOriginTranslateStatus = (propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) === 'static' ||
1495
+ ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.status) === 'keyframed' &&
1496
+ propStatus.interpolationFunction === 'interpolate');
1497
+ const canTransformOriginDrag = previewServerState.type === 'connected' &&
1498
+ selectedForTransformOrigin &&
1499
+ controls !== null &&
1500
+ (transformOriginFieldSchema === null || transformOriginFieldSchema === void 0 ? void 0 : transformOriginFieldSchema.type) === 'transform-origin' &&
1501
+ (fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.type) === 'translate' &&
1502
+ canTransformOriginStatus &&
1503
+ canTransformOriginTranslateStatus;
1504
+ const canDropEffect = previewServerState.type === 'connected' &&
1505
+ (controls === null || controls === void 0 ? void 0 : controls.supportsEffects) === true;
1121
1506
  return {
1122
1507
  key,
1508
+ containsSelection,
1509
+ effectDrop: canDropEffect
1510
+ ? {
1511
+ clientId: previewServerState.clientId,
1512
+ fileName: nodePath.absolutePath,
1513
+ nodePath,
1514
+ }
1515
+ : null,
1123
1516
  nodePathInfo,
1124
1517
  ref: sequence.refForOutline,
1125
1518
  selected,
@@ -1127,7 +1520,7 @@ const SelectedOutlineOverlay = ({ scale }) => {
1127
1520
  sequence,
1128
1521
  drag: canDrag
1129
1522
  ? {
1130
- codeValue,
1523
+ propStatus,
1131
1524
  clientId: previewServerState.clientId,
1132
1525
  fieldDefault: fieldSchema.default,
1133
1526
  keyframeDisplayOffset,
@@ -1137,7 +1530,7 @@ const SelectedOutlineOverlay = ({ scale }) => {
1137
1530
  : null,
1138
1531
  scaleDrag: canScaleDrag
1139
1532
  ? {
1140
- codeValue: scaleCodeValue,
1533
+ propStatus: scalePropStatus,
1141
1534
  clientId: previewServerState.clientId,
1142
1535
  fieldDefault: scaleFieldSchema.default,
1143
1536
  fieldSchema: scaleFieldSchema,
@@ -1148,7 +1541,7 @@ const SelectedOutlineOverlay = ({ scale }) => {
1148
1541
  var _a;
1149
1542
  const dragOverrideValue = ((_a = getDragOverrides(nodePath)) !== null && _a !== void 0 ? _a : {})[scaleFieldKey];
1150
1543
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
1151
- codeValue: scaleCodeValue,
1544
+ propStatus: scalePropStatus,
1152
1545
  dragOverrideValue,
1153
1546
  defaultValue: scaleFieldSchema.default,
1154
1547
  shouldResortToDefaultValueIfUndefined: true,
@@ -1161,20 +1554,83 @@ const SelectedOutlineOverlay = ({ scale }) => {
1161
1554
  schema: controls.schema,
1162
1555
  }
1163
1556
  : null,
1164
- uvHandles: selected
1165
- ? getSelectedUvHandles({
1166
- codeValues,
1557
+ rotationDrag: canRotationDrag
1558
+ ? {
1559
+ propStatus: rotationPropStatus,
1560
+ clientId: previewServerState.clientId,
1561
+ fieldDefault: rotationFieldSchema.default,
1562
+ fieldSchema: rotationFieldSchema,
1563
+ keyframeDisplayOffset,
1564
+ nodePath,
1565
+ schema: controls.schema,
1566
+ }
1567
+ : null,
1568
+ transformOriginDrag: canTransformOriginDrag
1569
+ ? {
1570
+ clientId: previewServerState.clientId,
1571
+ keyframeDisplayOffset,
1572
+ nodePath,
1573
+ originDefault: transformOriginFieldSchema.default,
1574
+ originPropStatus: transformOriginPropStatus,
1575
+ originValue: String((_c = remotion_1.Internals.getEffectiveVisualModeValue({
1576
+ propStatus: transformOriginPropStatus,
1577
+ dragOverrideValue: ((_b = getDragOverrides(nodePath)) !== null && _b !== void 0 ? _b : {})[transformOriginFieldKey],
1578
+ defaultValue: transformOriginFieldSchema.default,
1579
+ frame: transformOriginSourceFrame,
1580
+ shouldResortToDefaultValueIfUndefined: true,
1581
+ })) !== null && _c !== void 0 ? _c : transformOriginFieldSchema.default),
1582
+ rotateValue: String((rotationPropStatus === null || rotationPropStatus === void 0 ? void 0 : rotationPropStatus.status) === 'static' ||
1583
+ (rotationPropStatus === null || rotationPropStatus === void 0 ? void 0 : rotationPropStatus.status) === 'keyframed'
1584
+ ? ((_e = remotion_1.Internals.getEffectiveVisualModeValue({
1585
+ propStatus: rotationPropStatus,
1586
+ dragOverrideValue: ((_d = getDragOverrides(nodePath)) !== null && _d !== void 0 ? _d : {})[rotateFieldKey],
1587
+ defaultValue: (rotationFieldSchema === null || rotationFieldSchema === void 0 ? void 0 : rotationFieldSchema.type) === 'rotation-css'
1588
+ ? rotationFieldSchema.default
1589
+ : '0deg',
1590
+ frame: transformOriginSourceFrame,
1591
+ shouldResortToDefaultValueIfUndefined: true,
1592
+ })) !== null && _e !== void 0 ? _e : '0deg')
1593
+ : '0deg'),
1594
+ scaleValue: (scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'static' ||
1595
+ (scalePropStatus === null || scalePropStatus === void 0 ? void 0 : scalePropStatus.status) === 'keyframed'
1596
+ ? String((_g = remotion_1.Internals.getEffectiveVisualModeValue({
1597
+ propStatus: scalePropStatus,
1598
+ dragOverrideValue: ((_f = getDragOverrides(nodePath)) !== null && _f !== void 0 ? _f : {})[scaleFieldKey],
1599
+ defaultValue: (scaleFieldSchema === null || scaleFieldSchema === void 0 ? void 0 : scaleFieldSchema.type) === 'scale'
1600
+ ? scaleFieldSchema.default
1601
+ : 1,
1602
+ frame: transformOriginSourceFrame,
1603
+ shouldResortToDefaultValueIfUndefined: true,
1604
+ })) !== null && _g !== void 0 ? _g : 1)
1605
+ : '1',
1606
+ schema: controls.schema,
1607
+ sourceFrame: transformOriginSourceFrame,
1608
+ translateDefault: fieldSchema.default,
1609
+ translatePropStatus: propStatus,
1610
+ translateValue: String((_j = remotion_1.Internals.getEffectiveVisualModeValue({
1611
+ propStatus,
1612
+ dragOverrideValue: ((_h = getDragOverrides(nodePath)) !== null && _h !== void 0 ? _h : {})[translateFieldKey],
1613
+ defaultValue: fieldSchema.default,
1614
+ frame: transformOriginSourceFrame,
1615
+ shouldResortToDefaultValueIfUndefined: true,
1616
+ })) !== null && _j !== void 0 ? _j : fieldSchema.default),
1617
+ }
1618
+ : null,
1619
+ uvHandles: containsSelection
1620
+ ? (0, selected_outline_uv_1.getSelectedUvHandles)({
1621
+ propStatuses,
1167
1622
  clientId,
1168
1623
  getEffectDragOverrides,
1169
1624
  nodePath,
1170
1625
  selectedEffects: selectedEffectsBySequenceKey.get(key),
1171
1626
  sequence,
1627
+ sourceFrame: timelinePosition - keyframeDisplayOffset,
1172
1628
  })
1173
1629
  : [],
1174
1630
  };
1175
1631
  });
1176
1632
  }, [
1177
- codeValues,
1633
+ propStatuses,
1178
1634
  getDragOverrides,
1179
1635
  getEffectDragOverrides,
1180
1636
  getScaleLockState,
@@ -1183,6 +1639,7 @@ const SelectedOutlineOverlay = ({ scale }) => {
1183
1639
  previewServerState,
1184
1640
  selectedItems,
1185
1641
  sequences,
1642
+ timelinePosition,
1186
1643
  ]);
1187
1644
  (0, react_1.useEffect)(() => {
1188
1645
  if (hoveredOutlineKey !== null &&
@@ -1199,6 +1656,11 @@ const SelectedOutlineOverlay = ({ scale }) => {
1199
1656
  const allScaleDragTargets = (0, react_1.useMemo)(() => {
1200
1657
  return outlineTargets.flatMap((target) => target.selected && target.scaleDrag !== null ? [target.scaleDrag] : []);
1201
1658
  }, [outlineTargets]);
1659
+ const allRotationDragTargets = (0, react_1.useMemo)(() => {
1660
+ return outlineTargets.flatMap((target) => target.selected && target.rotationDrag !== null
1661
+ ? [target.rotationDrag]
1662
+ : []);
1663
+ }, [outlineTargets]);
1202
1664
  (0, react_1.useEffect)(() => {
1203
1665
  if (outlineTargets.length === 0) {
1204
1666
  setOutlines((prevOutlines) => prevOutlines.length === 0 ? prevOutlines : []);
@@ -1224,6 +1686,6 @@ const SelectedOutlineOverlay = ({ scale }) => {
1224
1686
  if (outlineTargets.length === 0) {
1225
1687
  return null;
1226
1688
  }
1227
- return (jsx_runtime_1.jsx("svg", { ref: overlayRef, style: outlineContainer, width: "100%", height: "100%", "aria-hidden": "true", children: outlines.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineElement, { allDragTargets: allDragTargets, allScaleDragTargets: allScaleDragTargets, dragging: draggingOutline, hovered: hoveredOutlineKey === outline.key, outline: outline, onDraggingChange: onDraggingChange, onHoverChange: setHoveredOutlineKey, onSelect: selectItem, scale: scale, target: targetsByKey.get(outline.key) }, outline.key))) }));
1689
+ return (jsx_runtime_1.jsxs("svg", { ref: overlayRef, style: outlineContainer, width: "100%", height: "100%", "aria-hidden": "true", children: [outlines.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineElement, { allDragTargets: allDragTargets, allRotationDragTargets: allRotationDragTargets, allScaleDragTargets: allScaleDragTargets, dragging: draggingOutline, hovered: hoveredOutlineKey === outline.key, outline: outline, onDraggingChange: onDraggingChange, onHoverChange: setHoveredOutlineKey, onSelect: selectItem, scale: scale, target: targetsByKey.get(outline.key) }, outline.key))), outlines.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineUvControls_1.SelectedOutlineUvHandleConnectionLayer, { outline: outline, target: targetsByKey.get(outline.key) }, `${outline.key}-uv-connection-lines`))), outlines.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineUvControls_1.SelectedOutlineUvHandleCircleLayer, { onDraggingChange: onDraggingChange, outline: outline, target: targetsByKey.get(outline.key) }, `${outline.key}-uv-handles`)))] }));
1228
1690
  };
1229
1691
  exports.SelectedOutlineOverlay = SelectedOutlineOverlay;