@remotion/studio 4.0.482 → 4.0.484

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 (77) hide show
  1. package/dist/components/Canvas.js +19 -0
  2. package/dist/components/ColorPicker/ColorPicker.js +65 -3
  3. package/dist/components/ColorPicker/ColorPickerPopup.d.ts +1 -0
  4. package/dist/components/ColorPicker/ColorPickerPopup.js +3 -2
  5. package/dist/components/InspectorPanel/EasingInspector.js +184 -10
  6. package/dist/components/InspectorPanel/KeyframeEasingNavigator.d.ts +14 -0
  7. package/dist/components/InspectorPanel/KeyframeEasingNavigator.js +146 -0
  8. package/dist/components/InspectorPanel/KeyframeInspector.d.ts +1 -1
  9. package/dist/components/InspectorPanel/KeyframeInspector.js +228 -5
  10. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +17 -0
  11. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +93 -0
  12. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -58
  13. package/dist/components/InspectorPanel/common.d.ts +12 -0
  14. package/dist/components/InspectorPanel/common.js +78 -1
  15. package/dist/components/InspectorPanel/easing-inspector-selection.d.ts +14 -0
  16. package/dist/components/InspectorPanel/easing-inspector-selection.js +18 -0
  17. package/dist/components/InspectorPanel/keyframe-easing-navigator-items.d.ts +24 -0
  18. package/dist/components/InspectorPanel/keyframe-easing-navigator-items.js +40 -0
  19. package/dist/components/InspectorPanel/keyframe-inspector-frame.d.ts +8 -0
  20. package/dist/components/InspectorPanel/keyframe-inspector-frame.js +14 -0
  21. package/dist/components/InspectorPanel/styles.d.ts +1 -0
  22. package/dist/components/InspectorPanel/styles.js +9 -1
  23. package/dist/components/InspectorSequenceSection.js +47 -10
  24. package/dist/components/Preview.js +1 -1
  25. package/dist/components/SelectedOutlineOverlay.d.ts +2 -0
  26. package/dist/components/SelectedOutlineOverlay.js +33 -12
  27. package/dist/components/SelectedOutlineUvControls.js +461 -2
  28. package/dist/components/Timeline/EasingEditorModal.js +48 -5
  29. package/dist/components/Timeline/Timeline.js +2 -1
  30. package/dist/components/Timeline/TimelineDeleteKeybindings.js +11 -1
  31. package/dist/components/Timeline/TimelineEffectItem.js +8 -5
  32. package/dist/components/Timeline/TimelineEffectPropItem.js +82 -1
  33. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +2 -2
  34. package/dist/components/Timeline/TimelineKeyframeControls.js +37 -7
  35. package/dist/components/Timeline/TimelineKeyframeEasingLine.d.ts +4 -0
  36. package/dist/components/Timeline/TimelineKeyframeEasingLine.js +12 -6
  37. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
  38. package/dist/components/Timeline/TimelineRowChrome.js +6 -4
  39. package/dist/components/Timeline/TimelineSelection.d.ts +7 -1
  40. package/dist/components/Timeline/TimelineSelection.js +19 -3
  41. package/dist/components/Timeline/TimelineSequence.js +20 -8
  42. package/dist/components/Timeline/TimelineSequenceItem.js +64 -28
  43. package/dist/components/Timeline/TimelineSequenceName.d.ts +1 -0
  44. package/dist/components/Timeline/TimelineSequenceName.js +7 -6
  45. package/dist/components/Timeline/TimelineSequencePropItem.d.ts +1 -1
  46. package/dist/components/Timeline/TimelineSequencePropItem.js +80 -1
  47. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +40 -1
  48. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +308 -1
  49. package/dist/components/Timeline/TimelineSlider.js +17 -3
  50. package/dist/components/Timeline/TimelineTrack.js +2 -4
  51. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +8 -2
  52. package/dist/components/Timeline/delete-selected-timeline-item.js +80 -1
  53. package/dist/components/Timeline/get-animation-item-selection-for-frame.d.ts +18 -0
  54. package/dist/components/Timeline/get-animation-item-selection-for-frame.js +49 -0
  55. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.d.ts +15 -0
  56. package/dist/components/Timeline/get-easing-selection-after-keyframe-delete.js +26 -0
  57. package/dist/components/Timeline/save-sequence-prop.js +2 -0
  58. package/dist/components/Timeline/should-subscribe-to-sequence-props.d.ts +4 -0
  59. package/dist/components/Timeline/should-subscribe-to-sequence-props.js +10 -0
  60. package/dist/components/Timeline/update-selected-easing.d.ts +1 -0
  61. package/dist/components/Timeline/update-selected-easing.js +4 -3
  62. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +2 -1
  63. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +19 -13
  64. package/dist/components/element-drag-and-drop.d.ts +3 -0
  65. package/dist/components/element-drag-and-drop.js +30 -0
  66. package/dist/components/import-assets.d.ts +11 -0
  67. package/dist/components/import-assets.js +23 -1
  68. package/dist/components/selected-outline-uv.d.ts +71 -1
  69. package/dist/components/selected-outline-uv.js +332 -10
  70. package/dist/esm/{chunk-nkqfa5bw.js → chunk-9erwh79m.js} +11896 -9019
  71. package/dist/esm/internals.mjs +11896 -9019
  72. package/dist/esm/previewEntry.mjs +11923 -9046
  73. package/dist/esm/renderEntry.mjs +1 -1
  74. package/dist/helpers/timeline-layout.d.ts +3 -3
  75. package/dist/helpers/timeline-layout.js +3 -1
  76. package/dist/helpers/use-menu-structure.js +0 -14
  77. package/package.json +11 -11
@@ -41,6 +41,7 @@ const colors_1 = require("../helpers/colors");
41
41
  const ForceSpecificCursor_1 = require("./ForceSpecificCursor");
42
42
  const selected_outline_drag_1 = require("./selected-outline-drag");
43
43
  const selected_outline_measurement_1 = require("./selected-outline-measurement");
44
+ const selected_outline_measurement_2 = require("./selected-outline-measurement");
44
45
  const selected_outline_uv_1 = require("./selected-outline-uv");
45
46
  const call_add_keyframe_1 = require("./Timeline/call-add-keyframe");
46
47
  const save_effect_prop_1 = require("./Timeline/save-effect-prop");
@@ -52,6 +53,7 @@ const getSvgPointFromPointerEvent = ({ event, rect, }) => {
52
53
  };
53
54
  const uvHandleRadius = 4.25;
54
55
  const selectedUvHandleRadius = 6.8;
56
+ const ellipseControlRadius = 5.2;
55
57
  const uvHandleStyle = {
56
58
  filter: 'drop-shadow(0 1px 2px rgba(0, 0, 0, 0.28))',
57
59
  };
@@ -69,7 +71,454 @@ const getSelectedOutlineUvHandleTimelineSelection = ({ effectIndex, fieldKey, no
69
71
  exports.getSelectedOutlineUvHandleTimelineSelection = getSelectedOutlineUvHandleTimelineSelection;
70
72
  const SelectedUvHandleConnectionLines = ({ handles, outline }) => {
71
73
  const lines = (0, react_1.useMemo)(() => (0, selected_outline_uv_1.getUvHandleConnectionLines)({ handles, points: outline.points }), [handles, outline.points]);
72
- 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))) }));
74
+ const ellipses = (0, react_1.useMemo)(() => (0, selected_outline_uv_1.getUvHandleConnectionEllipses)({
75
+ handles,
76
+ dimensions: outline.dimensions,
77
+ points: outline.points,
78
+ }), [handles, outline.dimensions, outline.points]);
79
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [ellipses.map((ellipse) => (jsx_runtime_1.jsx("polyline", { points: ellipse.points
80
+ .map((point) => `${point.x},${point.y}`)
81
+ .join(' '), fill: "none", stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: "none" }, ellipse.key))), 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)))] }));
82
+ };
83
+ const fieldDefaultToString = (value) => value !== undefined ? JSON.stringify(value) : null;
84
+ const shouldSaveNumericEffectValue = ({ defaultValue, field, value, }) => {
85
+ if (value === null) {
86
+ return false;
87
+ }
88
+ if (field.propStatus.status === 'keyframed') {
89
+ return field.value !== value;
90
+ }
91
+ const stringifiedValue = JSON.stringify(value);
92
+ return (field.propStatus.codeValue !== value &&
93
+ !(defaultValue === stringifiedValue &&
94
+ field.propStatus.codeValue === undefined));
95
+ };
96
+ const saveNumericEffectField = ({ clearEffectDragOverrides, clientId, effectIndex, field, lastValue, nodePath, schema, setPropStatuses, sourceFrame, }) => {
97
+ const defaultValue = fieldDefaultToString(field.fieldDefault);
98
+ if (!shouldSaveNumericEffectValue({
99
+ defaultValue,
100
+ field,
101
+ value: lastValue,
102
+ })) {
103
+ clearEffectDragOverrides(nodePath, effectIndex);
104
+ return;
105
+ }
106
+ (field.propStatus.status === 'keyframed'
107
+ ? (0, call_add_keyframe_1.callAddEffectKeyframe)({
108
+ fileName: nodePath.absolutePath,
109
+ nodePath,
110
+ effectIndex,
111
+ fieldKey: field.fieldKey,
112
+ sourceFrame,
113
+ value: lastValue,
114
+ schema,
115
+ setPropStatuses,
116
+ clientId,
117
+ })
118
+ : (0, save_effect_prop_1.saveEffectProp)({
119
+ type: 'value',
120
+ fileName: nodePath.absolutePath,
121
+ nodePath,
122
+ effectIndex,
123
+ fieldKey: field.fieldKey,
124
+ value: lastValue,
125
+ defaultValue,
126
+ schema,
127
+ setPropStatuses,
128
+ clientId,
129
+ })).finally(() => {
130
+ clearEffectDragOverrides(nodePath, effectIndex);
131
+ });
132
+ };
133
+ const getLocalEllipseAxisValue = ({ axis, center, dimensions, point, rotation, }) => {
134
+ const radians = (rotation / 180) * Math.PI;
135
+ const deltaX = point[0] - center[0];
136
+ const deltaY = point[1] - center[1];
137
+ const axisX = axis === 'width' ? Math.cos(radians) : -Math.sin(radians);
138
+ const axisY = axis === 'width' ? Math.sin(radians) : Math.cos(radians);
139
+ if (dimensions !== null && dimensions.width > 0 && dimensions.height > 0) {
140
+ const pixelDeltaX = deltaX * dimensions.width;
141
+ const pixelDeltaY = deltaY * dimensions.height;
142
+ const pixelAxisValue = pixelDeltaX * axisX + pixelDeltaY * axisY;
143
+ return (pixelAxisValue / (axis === 'width' ? dimensions.width : dimensions.height));
144
+ }
145
+ return deltaX * axisX + deltaY * axisY;
146
+ };
147
+ const getLocalEllipseWidthProgress = ({ center, dimensions, point, rotation, width, }) => {
148
+ if (width <= 0.000001) {
149
+ return 0;
150
+ }
151
+ return (getLocalEllipseAxisValue({
152
+ axis: 'width',
153
+ center,
154
+ dimensions,
155
+ point,
156
+ rotation,
157
+ }) /
158
+ (width / 2));
159
+ };
160
+ const SelectedUvEllipseStartHandle = ({ control, onDraggingChange, outline }) => {
161
+ const { setEffectDragOverrides, clearEffectDragOverrides, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
162
+ const { startControl } = control;
163
+ const field = startControl === null || startControl === void 0 ? void 0 : startControl.field;
164
+ const onPointerDown = react_1.default.useCallback((event) => {
165
+ if (startControl === null || field === undefined) {
166
+ return;
167
+ }
168
+ if (event.button !== 0) {
169
+ return;
170
+ }
171
+ event.preventDefault();
172
+ event.stopPropagation();
173
+ const svg = event.currentTarget.ownerSVGElement;
174
+ if (svg === null) {
175
+ return;
176
+ }
177
+ const svgRect = svg.getBoundingClientRect();
178
+ const startPointerX = event.clientX;
179
+ const startPointerY = event.clientY;
180
+ let dragging = false;
181
+ let lastValue = null;
182
+ const updateFromPointerEvent = (pointerEvent) => {
183
+ const point = getSvgPointFromPointerEvent({
184
+ event: pointerEvent,
185
+ rect: svgRect,
186
+ });
187
+ const uv = (0, selected_outline_uv_1.getUvCoordinateForPoint)(outline.points, point);
188
+ const nextValue = (0, selected_outline_uv_1.roundNumericUvEllipseValue)(getLocalEllipseWidthProgress({
189
+ center: control.handle.value,
190
+ dimensions: outline.dimensions,
191
+ point: uv,
192
+ rotation: control.rotation,
193
+ width: control.width,
194
+ }), field.fieldSchema);
195
+ lastValue = nextValue;
196
+ setEffectDragOverrides(control.handle.nodePath, control.handle.effectIndex, field.fieldKey, field.propStatus.status === 'keyframed'
197
+ ? remotion_1.Internals.makeKeyframedDragOverride({
198
+ status: field.propStatus,
199
+ frame: control.handle.sourceFrame,
200
+ value: nextValue,
201
+ })
202
+ : remotion_1.Internals.makeStaticDragOverride(nextValue));
203
+ };
204
+ const onPointerMove = (moveEvent) => {
205
+ moveEvent.preventDefault();
206
+ const deltaX = moveEvent.clientX - startPointerX;
207
+ const deltaY = moveEvent.clientY - startPointerY;
208
+ if (!dragging) {
209
+ if (!(0, selected_outline_drag_1.isSelectedOutlineDragPastThreshold)({ deltaX, deltaY })) {
210
+ return;
211
+ }
212
+ dragging = true;
213
+ (0, ForceSpecificCursor_1.forceSpecificCursor)(startControl.cursor);
214
+ onDraggingChange(true);
215
+ }
216
+ updateFromPointerEvent(moveEvent);
217
+ };
218
+ const onPointerUp = () => {
219
+ window.removeEventListener('pointermove', onPointerMove);
220
+ window.removeEventListener('pointerup', onPointerUp);
221
+ window.removeEventListener('pointercancel', onPointerUp);
222
+ if (dragging) {
223
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
224
+ onDraggingChange(false);
225
+ }
226
+ saveNumericEffectField({
227
+ clearEffectDragOverrides,
228
+ clientId: control.handle.clientId,
229
+ effectIndex: control.handle.effectIndex,
230
+ field,
231
+ lastValue,
232
+ nodePath: control.handle.nodePath,
233
+ schema: control.handle.schema,
234
+ setPropStatuses,
235
+ sourceFrame: control.handle.sourceFrame,
236
+ });
237
+ };
238
+ window.addEventListener('pointermove', onPointerMove);
239
+ window.addEventListener('pointerup', onPointerUp);
240
+ window.addEventListener('pointercancel', onPointerUp);
241
+ }, [
242
+ clearEffectDragOverrides,
243
+ control.handle,
244
+ control.rotation,
245
+ control.width,
246
+ field,
247
+ onDraggingChange,
248
+ outline.dimensions,
249
+ outline.points,
250
+ setEffectDragOverrides,
251
+ setPropStatuses,
252
+ startControl,
253
+ ]);
254
+ if (startControl === null || field === undefined) {
255
+ return null;
256
+ }
257
+ return (jsx_runtime_1.jsx("circle", { cx: startControl.position.x, cy: startControl.position.y, r: ellipseControlRadius, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, style: uvHandleStyle, vectorEffect: "non-scaling-stroke", pointerEvents: "all", cursor: startControl.cursor, onPointerDown: onPointerDown }));
258
+ };
259
+ const SelectedUvEllipseResizeHandle = ({ axis, control, onDraggingChange, outline }) => {
260
+ const { setEffectDragOverrides, clearEffectDragOverrides, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
261
+ const resizeControl = control.resize.find((item) => item.axis === axis);
262
+ const field = resizeControl === null || resizeControl === void 0 ? void 0 : resizeControl.field;
263
+ const onPointerDown = react_1.default.useCallback((event) => {
264
+ if (resizeControl === undefined || field === undefined) {
265
+ return;
266
+ }
267
+ if (event.button !== 0) {
268
+ return;
269
+ }
270
+ event.preventDefault();
271
+ event.stopPropagation();
272
+ const svg = event.currentTarget.ownerSVGElement;
273
+ if (svg === null) {
274
+ return;
275
+ }
276
+ const svgRect = svg.getBoundingClientRect();
277
+ const startPointerX = event.clientX;
278
+ const startPointerY = event.clientY;
279
+ let dragging = false;
280
+ let lastValue = null;
281
+ const updateFromPointerEvent = (pointerEvent) => {
282
+ const point = getSvgPointFromPointerEvent({
283
+ event: pointerEvent,
284
+ rect: svgRect,
285
+ });
286
+ const uv = (0, selected_outline_uv_1.getUvCoordinateForPoint)(outline.points, point);
287
+ const axisValue = getLocalEllipseAxisValue({
288
+ axis,
289
+ center: control.handle.value,
290
+ dimensions: outline.dimensions,
291
+ point: uv,
292
+ rotation: control.rotation,
293
+ });
294
+ const nextValue = (0, selected_outline_uv_1.roundNumericUvEllipseValue)(Math.max(0, axisValue * 2), field.fieldSchema);
295
+ lastValue = nextValue;
296
+ setEffectDragOverrides(control.handle.nodePath, control.handle.effectIndex, field.fieldKey, field.propStatus.status === 'keyframed'
297
+ ? remotion_1.Internals.makeKeyframedDragOverride({
298
+ status: field.propStatus,
299
+ frame: control.handle.sourceFrame,
300
+ value: nextValue,
301
+ })
302
+ : remotion_1.Internals.makeStaticDragOverride(nextValue));
303
+ };
304
+ const onPointerMove = (moveEvent) => {
305
+ moveEvent.preventDefault();
306
+ const deltaX = moveEvent.clientX - startPointerX;
307
+ const deltaY = moveEvent.clientY - startPointerY;
308
+ if (!dragging) {
309
+ if (!(0, selected_outline_drag_1.isSelectedOutlineDragPastThreshold)({ deltaX, deltaY })) {
310
+ return;
311
+ }
312
+ dragging = true;
313
+ (0, ForceSpecificCursor_1.forceSpecificCursor)(resizeControl.cursor);
314
+ onDraggingChange(true);
315
+ }
316
+ updateFromPointerEvent(moveEvent);
317
+ };
318
+ const onPointerUp = () => {
319
+ window.removeEventListener('pointermove', onPointerMove);
320
+ window.removeEventListener('pointerup', onPointerUp);
321
+ window.removeEventListener('pointercancel', onPointerUp);
322
+ if (dragging) {
323
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
324
+ onDraggingChange(false);
325
+ }
326
+ saveNumericEffectField({
327
+ clearEffectDragOverrides,
328
+ clientId: control.handle.clientId,
329
+ effectIndex: control.handle.effectIndex,
330
+ field,
331
+ lastValue,
332
+ nodePath: control.handle.nodePath,
333
+ schema: control.handle.schema,
334
+ setPropStatuses,
335
+ sourceFrame: control.handle.sourceFrame,
336
+ });
337
+ };
338
+ window.addEventListener('pointermove', onPointerMove);
339
+ window.addEventListener('pointerup', onPointerUp);
340
+ window.addEventListener('pointercancel', onPointerUp);
341
+ }, [
342
+ axis,
343
+ clearEffectDragOverrides,
344
+ control.handle,
345
+ control.rotation,
346
+ field,
347
+ onDraggingChange,
348
+ outline.dimensions,
349
+ outline.points,
350
+ resizeControl,
351
+ setEffectDragOverrides,
352
+ setPropStatuses,
353
+ ]);
354
+ if (resizeControl === undefined || field === undefined) {
355
+ return null;
356
+ }
357
+ return (jsx_runtime_1.jsx("circle", { cx: resizeControl.position.x, cy: resizeControl.position.y, r: ellipseControlRadius, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, style: uvHandleStyle, vectorEffect: "non-scaling-stroke", pointerEvents: "all", cursor: resizeControl.cursor, onPointerDown: onPointerDown }));
358
+ };
359
+ const snapRotationDegrees = (value) => Math.round(value / selected_outline_drag_1.selectedOutlineRotationSnapStepDegrees) *
360
+ selected_outline_drag_1.selectedOutlineRotationSnapStepDegrees;
361
+ const trimLineToCircleEdges = ({ from, fromRadius, to, toRadius, }) => {
362
+ const deltaX = to.x - from.x;
363
+ const deltaY = to.y - from.y;
364
+ const distance = Math.hypot(deltaX, deltaY);
365
+ if (distance <= fromRadius + toRadius || distance <= 0.000001) {
366
+ const middle = {
367
+ x: (from.x + to.x) / 2,
368
+ y: (from.y + to.y) / 2,
369
+ };
370
+ return { from: middle, to: middle };
371
+ }
372
+ const unitX = deltaX / distance;
373
+ const unitY = deltaY / distance;
374
+ return {
375
+ from: {
376
+ x: from.x + unitX * fromRadius,
377
+ y: from.y + unitY * fromRadius,
378
+ },
379
+ to: {
380
+ x: to.x - unitX * toRadius,
381
+ y: to.y - unitY * toRadius,
382
+ },
383
+ };
384
+ };
385
+ const SelectedUvEllipseRotationHandle = ({ control, onDraggingChange }) => {
386
+ const { setEffectDragOverrides, clearEffectDragOverrides, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
387
+ const { rotationControl } = control;
388
+ const field = rotationControl === null || rotationControl === void 0 ? void 0 : rotationControl.field;
389
+ const onPointerDown = react_1.default.useCallback((event) => {
390
+ if (rotationControl === null || field === undefined) {
391
+ return;
392
+ }
393
+ if (event.button !== 0) {
394
+ return;
395
+ }
396
+ event.preventDefault();
397
+ event.stopPropagation();
398
+ const svg = event.currentTarget.ownerSVGElement;
399
+ if (svg === null) {
400
+ return;
401
+ }
402
+ const svgRect = svg.getBoundingClientRect();
403
+ const { center } = control;
404
+ const startPointer = { x: event.clientX, y: event.clientY };
405
+ let previousAngle = (0, selected_outline_measurement_2.getAngleDegrees)(center, {
406
+ x: event.clientX - svgRect.left,
407
+ y: event.clientY - svgRect.top,
408
+ });
409
+ const startCursorDegrees = previousAngle;
410
+ let accumulatedDelta = 0;
411
+ let rotationLocked = event.shiftKey;
412
+ let dragging = false;
413
+ let lastValue = null;
414
+ const updateRotationDragOverride = () => {
415
+ const rawValue = control.rotation + accumulatedDelta;
416
+ const snappedValue = rotationLocked
417
+ ? snapRotationDegrees(rawValue)
418
+ : rawValue;
419
+ const nextValue = (0, selected_outline_uv_1.roundNumericUvEllipseValue)(snappedValue, field.fieldSchema);
420
+ const cursorDelta = (0, selected_outline_measurement_2.getSelectedOutlineRotationDeltaDegrees)({
421
+ from: control.rotation,
422
+ to: nextValue,
423
+ });
424
+ lastValue = nextValue;
425
+ (0, ForceSpecificCursor_1.forceSpecificCursor)((0, selected_outline_measurement_2.getRotationCursor)(startCursorDegrees + cursorDelta));
426
+ setEffectDragOverrides(control.handle.nodePath, control.handle.effectIndex, field.fieldKey, field.propStatus.status === 'keyframed'
427
+ ? remotion_1.Internals.makeKeyframedDragOverride({
428
+ status: field.propStatus,
429
+ frame: control.handle.sourceFrame,
430
+ value: nextValue,
431
+ })
432
+ : remotion_1.Internals.makeStaticDragOverride(nextValue));
433
+ };
434
+ const onPointerMove = (moveEvent) => {
435
+ moveEvent.preventDefault();
436
+ const deltaX = moveEvent.clientX - startPointer.x;
437
+ const deltaY = moveEvent.clientY - startPointer.y;
438
+ if (!dragging) {
439
+ if (!(0, selected_outline_drag_1.isSelectedOutlineDragPastThreshold)({ deltaX, deltaY })) {
440
+ return;
441
+ }
442
+ dragging = true;
443
+ onDraggingChange(true);
444
+ }
445
+ const nextAngle = (0, selected_outline_measurement_2.getAngleDegrees)(center, {
446
+ x: moveEvent.clientX - svgRect.left,
447
+ y: moveEvent.clientY - svgRect.top,
448
+ });
449
+ accumulatedDelta += (0, selected_outline_measurement_2.getSelectedOutlineRotationDeltaDegrees)({
450
+ from: previousAngle,
451
+ to: nextAngle,
452
+ });
453
+ previousAngle = nextAngle;
454
+ rotationLocked = moveEvent.shiftKey;
455
+ updateRotationDragOverride();
456
+ };
457
+ const onKeyChange = (keyEvent) => {
458
+ if (keyEvent.key !== 'Shift') {
459
+ return;
460
+ }
461
+ const nextRotationLocked = keyEvent.type === 'keydown';
462
+ if (nextRotationLocked === rotationLocked) {
463
+ return;
464
+ }
465
+ rotationLocked = nextRotationLocked;
466
+ if (dragging) {
467
+ updateRotationDragOverride();
468
+ }
469
+ };
470
+ const onPointerUp = () => {
471
+ window.removeEventListener('pointermove', onPointerMove);
472
+ window.removeEventListener('pointerup', onPointerUp);
473
+ window.removeEventListener('pointercancel', onPointerUp);
474
+ window.removeEventListener('keydown', onKeyChange);
475
+ window.removeEventListener('keyup', onKeyChange);
476
+ if (dragging) {
477
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
478
+ onDraggingChange(false);
479
+ }
480
+ saveNumericEffectField({
481
+ clearEffectDragOverrides,
482
+ clientId: control.handle.clientId,
483
+ effectIndex: control.handle.effectIndex,
484
+ field,
485
+ lastValue,
486
+ nodePath: control.handle.nodePath,
487
+ schema: control.handle.schema,
488
+ setPropStatuses,
489
+ sourceFrame: control.handle.sourceFrame,
490
+ });
491
+ };
492
+ window.addEventListener('pointermove', onPointerMove);
493
+ window.addEventListener('pointerup', onPointerUp);
494
+ window.addEventListener('pointercancel', onPointerUp);
495
+ window.addEventListener('keydown', onKeyChange);
496
+ window.addEventListener('keyup', onKeyChange);
497
+ }, [
498
+ clearEffectDragOverrides,
499
+ control,
500
+ field,
501
+ onDraggingChange,
502
+ rotationControl,
503
+ setEffectDragOverrides,
504
+ setPropStatuses,
505
+ ]);
506
+ if (rotationControl === null || field === undefined) {
507
+ return null;
508
+ }
509
+ const heightControl = control.resize.find((item) => item.axis === 'height');
510
+ if (heightControl === undefined) {
511
+ return null;
512
+ }
513
+ const connector = trimLineToCircleEdges({
514
+ from: heightControl.position,
515
+ fromRadius: ellipseControlRadius,
516
+ to: rotationControl.position,
517
+ toRadius: ellipseControlRadius,
518
+ });
519
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
520
+ jsx_runtime_1.jsx("line", { x1: connector.from.x, y1: connector.from.y, x2: connector.to.x, y2: connector.to.y, stroke: colors_1.BLUE, strokeWidth: 2, vectorEffect: "non-scaling-stroke", pointerEvents: "none" }), jsx_runtime_1.jsx("circle", { cx: rotationControl.position.x, cy: rotationControl.position.y, r: ellipseControlRadius, fill: "white", stroke: colors_1.BLUE, strokeWidth: 2, style: uvHandleStyle, vectorEffect: "non-scaling-stroke", pointerEvents: "all", cursor: (0, selected_outline_measurement_2.getRotationCursor)((0, selected_outline_measurement_2.getAngleDegrees)(control.center, rotationControl.position)), onPointerDown: onPointerDown })
521
+ ] }));
73
522
  };
74
523
  const SelectedUvHandleCircle = ({ handle, nodePathInfo, onDraggingChange, onSelect, outline }) => {
75
524
  const { setEffectDragOverrides, clearEffectDragOverrides, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
@@ -213,9 +662,19 @@ const SelectedOutlineUvHandleConnectionLayer = ({ outline, target }) => {
213
662
  };
214
663
  exports.SelectedOutlineUvHandleConnectionLayer = SelectedOutlineUvHandleConnectionLayer;
215
664
  const SelectedOutlineUvHandleCircleLayer = ({ onDraggingChange, onSelect, outline, target }) => {
665
+ const ellipseControls = (0, react_1.useMemo)(() => {
666
+ var _a;
667
+ return (0, selected_outline_uv_1.getUvEllipseInteractiveControls)({
668
+ handles: (_a = target === null || target === void 0 ? void 0 : target.uvHandles) !== null && _a !== void 0 ? _a : [],
669
+ dimensions: outline.dimensions,
670
+ points: outline.points,
671
+ });
672
+ }, [outline.dimensions, outline.points, target === null || target === void 0 ? void 0 : target.uvHandles]);
216
673
  if (!(target === null || target === void 0 ? void 0 : target.containsSelection) || target.uvHandles.length === 0) {
217
674
  return null;
218
675
  }
219
- return (jsx_runtime_1.jsx(jsx_runtime_1.Fragment, { children: target.uvHandles.map((handle) => (jsx_runtime_1.jsx(SelectedUvHandleCircle, { handle: handle, nodePathInfo: target.nodePathInfo, onDraggingChange: onDraggingChange, onSelect: onSelect, outline: outline }, `${handle.effectIndex}-${handle.fieldKey}`))) }));
676
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [ellipseControls.map((control) => (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [
677
+ jsx_runtime_1.jsx(SelectedUvEllipseStartHandle, { control: control, onDraggingChange: onDraggingChange, outline: outline }), jsx_runtime_1.jsx(SelectedUvEllipseResizeHandle, { axis: "width", control: control, onDraggingChange: onDraggingChange, outline: outline }), jsx_runtime_1.jsx(SelectedUvEllipseResizeHandle, { axis: "height", control: control, onDraggingChange: onDraggingChange, outline: outline }), jsx_runtime_1.jsx(SelectedUvEllipseRotationHandle, { control: control, onDraggingChange: onDraggingChange })
678
+ ] }, `${control.handle.effectIndex}-${control.handle.fieldKey}-ellipse-controls`))), target.uvHandles.map((handle) => (jsx_runtime_1.jsx(SelectedUvHandleCircle, { handle: handle, nodePathInfo: target.nodePathInfo, onDraggingChange: onDraggingChange, onSelect: onSelect, outline: outline }, `${handle.effectIndex}-${handle.fieldKey}`)))] }));
220
679
  };
221
680
  exports.SelectedOutlineUvHandleCircleLayer = SelectedOutlineUvHandleCircleLayer;