@remotion/studio 4.0.481 → 4.0.483

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 (56) hide show
  1. package/dist/components/Canvas.js +19 -0
  2. package/dist/components/Editor.js +1 -1
  3. package/dist/components/GlobalKeybindings.js +1 -1
  4. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +3 -2
  5. package/dist/components/InspectorPanel/styles.js +2 -0
  6. package/dist/components/InspectorSequenceSection.js +45 -2
  7. package/dist/components/MediaVolumeProvider.js +4 -4
  8. package/dist/components/Modals.js +2 -1
  9. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  10. package/dist/components/NewComposition/CodemodFooter.js +25 -3
  11. package/dist/components/NewComposition/InputDragger.d.ts +4 -0
  12. package/dist/components/NewComposition/InputDragger.js +18 -2
  13. package/dist/components/NewComposition/NewComposition.d.ts +2 -0
  14. package/dist/components/NewComposition/NewComposition.js +178 -0
  15. package/dist/components/PreviewToolbar.js +3 -3
  16. package/dist/components/SelectedOutlineOverlay.d.ts +6 -0
  17. package/dist/components/SelectedOutlineOverlay.js +18 -2
  18. package/dist/components/SelectedOutlineUvControls.js +461 -2
  19. package/dist/components/Timeline/EasingEditorModal.js +39 -1
  20. package/dist/components/Timeline/Timeline.js +2 -1
  21. package/dist/components/Timeline/TimelineEffectItem.js +8 -5
  22. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +2 -2
  23. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
  24. package/dist/components/Timeline/TimelineRowChrome.js +6 -4
  25. package/dist/components/Timeline/TimelineSelection.d.ts +13 -4
  26. package/dist/components/Timeline/TimelineSelection.js +100 -39
  27. package/dist/components/Timeline/TimelineSequence.js +20 -8
  28. package/dist/components/Timeline/TimelineSequenceItem.js +17 -16
  29. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +40 -1
  30. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +308 -1
  31. package/dist/components/Timeline/TimelineTrack.js +2 -4
  32. package/dist/components/Timeline/should-subscribe-to-sequence-props.d.ts +4 -0
  33. package/dist/components/Timeline/should-subscribe-to-sequence-props.js +10 -0
  34. package/dist/components/Timeline/timeline-field-display-utils.js +3 -0
  35. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +2 -1
  36. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +19 -13
  37. package/dist/components/composition-menu-items.js +17 -0
  38. package/dist/components/element-drag-and-drop.d.ts +3 -0
  39. package/dist/components/element-drag-and-drop.js +30 -0
  40. package/dist/components/import-assets.d.ts +11 -0
  41. package/dist/components/import-assets.js +23 -1
  42. package/dist/components/selected-outline-uv.d.ts +71 -1
  43. package/dist/components/selected-outline-uv.js +332 -10
  44. package/dist/esm/{chunk-4rq5gt8c.js → chunk-fq0j774v.js} +3438 -1648
  45. package/dist/esm/internals.mjs +3438 -1648
  46. package/dist/esm/previewEntry.mjs +3455 -1665
  47. package/dist/esm/renderEntry.mjs +1 -1
  48. package/dist/helpers/calculate-timeline.js +6 -2
  49. package/dist/helpers/get-sequence-visible-range.d.ts +1 -0
  50. package/dist/helpers/get-sequence-visible-range.js +15 -1
  51. package/dist/helpers/timeline-layout.d.ts +3 -3
  52. package/dist/helpers/timeline-layout.js +3 -1
  53. package/dist/state/modals.d.ts +2 -0
  54. package/package.json +11 -11
  55. package/dist/components/Timeline/TimelineItemStack.d.ts +0 -5
  56. package/dist/components/Timeline/TimelineItemStack.js +0 -29
@@ -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.selectedOutlineDragThresholdPx = exports.getTransformedSvgViewportPoints = exports.getSequencesWithSelectableOutlines = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.selectedOutlineUvSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineActiveSchema = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = void 0;
36
+ exports.SelectedOutlineOverlay = exports.orderOutlinesForRendering = exports.selectedOutlineDragThresholdPx = exports.getTransformedSvgViewportPoints = exports.getSequencesWithSelectableOutlines = exports.getSelectedSequenceKeys = exports.getSelectedOutlineRotationPivot = exports.getSelectedOutlineRotationDeltaDegrees = exports.getSelectedOutlineRotationCornerInfo = exports.getSelectedEffectFieldsBySequenceKey = exports.getOutlineSelectionInteraction = exports.snapSelectedOutlineTransformOriginUv = exports.snapSelectedOutlineUv = exports.snapSelectedOutlineRotationDeltaDegrees = exports.selectedOutlineTransformOriginSnapThresholdPx = exports.selectedOutlineUvSnapThresholdPx = exports.isSelectedOutlineDragPastThreshold = exports.getSelectedOutlineTransformOriginLockedAxis = exports.getSelectedOutlineScaleEdgeInfo = exports.getSelectedOutlineScaleDragValues = exports.getSelectedOutlineScaleDragStates = exports.getSelectedOutlineScaleDragChanges = exports.getSelectedOutlineRotationDragValues = exports.getSelectedOutlineRotationDragStates = exports.getSelectedOutlineRotationDragChanges = exports.getSelectedOutlineKeyboardNudgeDeltas = exports.getSelectedOutlineKeyboardNudgeDelta = exports.getSelectedOutlineDragValues = exports.getSelectedOutlineDragChanges = exports.getSelectedOutlineActiveSchema = exports.compensateTranslateForTransformOrigin = exports.applySelectedOutlineTransformOriginAxisLock = exports.applySelectedOutlineDragAxisLock = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const player_1 = require("@remotion/player");
39
39
  const react_1 = __importStar(require("react"));
@@ -95,6 +95,16 @@ const outlineContainer = {
95
95
  pointerEvents: 'none',
96
96
  overflow: 'visible',
97
97
  };
98
+ const orderOutlinesForRendering = ({ outlines, targetsByKey, }) => {
99
+ return [...outlines].sort((a, b) => {
100
+ var _a, _b;
101
+ var _c, _d;
102
+ const aSelected = (_c = (_a = targetsByKey.get(a.key)) === null || _a === void 0 ? void 0 : _a.selected) !== null && _c !== void 0 ? _c : false;
103
+ const bSelected = (_d = (_b = targetsByKey.get(b.key)) === null || _b === void 0 ? void 0 : _b.selected) !== null && _d !== void 0 ? _d : false;
104
+ return Number(aSelected) - Number(bSelected);
105
+ });
106
+ };
107
+ exports.orderOutlinesForRendering = orderOutlinesForRendering;
98
108
  const SelectedOutlineOverlay = ({ scale }) => {
99
109
  const { selectedItems, selectItem } = (0, TimelineSelection_1.useTimelineSelection)();
100
110
  const { sequences } = (0, react_1.useContext)(remotion_1.Internals.SequenceManager);
@@ -120,6 +130,9 @@ const SelectedOutlineOverlay = ({ scale }) => {
120
130
  setHoveredOutlineKey(null);
121
131
  }
122
132
  }, []);
133
+ const selectOutlineItem = (0, react_1.useCallback)((item, interaction) => {
134
+ selectItem(item, interaction, undefined, { reveal: true });
135
+ }, [selectItem]);
123
136
  const outlineTargets = (0, react_1.useMemo)(() => {
124
137
  if (!editorShowOutlines) {
125
138
  return [];
@@ -363,6 +376,9 @@ const SelectedOutlineOverlay = ({ scale }) => {
363
376
  const targetsByKey = (0, react_1.useMemo)(() => {
364
377
  return new Map(outlineTargets.map((target) => [target.key, target]));
365
378
  }, [outlineTargets]);
379
+ const outlinesForRendering = (0, react_1.useMemo)(() => {
380
+ return (0, exports.orderOutlinesForRendering)({ outlines, targetsByKey });
381
+ }, [outlines, targetsByKey]);
366
382
  const allDragTargets = (0, react_1.useMemo)(() => {
367
383
  return outlineTargets.flatMap((target) => (target.selected || target.containsSelection) && target.drag !== null
368
384
  ? [target.drag]
@@ -622,6 +638,6 @@ const SelectedOutlineOverlay = ({ scale }) => {
622
638
  if (outlineTargets.length === 0) {
623
639
  return null;
624
640
  }
625
- 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_1.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, onSelect: selectItem, outline: outline, target: targetsByKey.get(outline.key) }, `${outline.key}-uv-handles`)))] }));
641
+ return (jsx_runtime_1.jsxs("svg", { ref: overlayRef, style: outlineContainer, width: "100%", height: "100%", "aria-hidden": "true", children: [outlinesForRendering.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineElement_1.SelectedOutlineElement, { allDragTargets: allDragTargets, allRotationDragTargets: allRotationDragTargets, allScaleDragTargets: allScaleDragTargets, dragging: draggingOutline, hovered: hoveredOutlineKey === outline.key, outline: outline, onDraggingChange: onDraggingChange, onHoverChange: setHoveredOutlineKey, onSelect: selectOutlineItem, scale: scale, target: targetsByKey.get(outline.key) }, outline.key))), outlinesForRendering.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineUvControls_1.SelectedOutlineUvHandleConnectionLayer, { outline: outline, target: targetsByKey.get(outline.key) }, `${outline.key}-uv-connection-lines`))), outlinesForRendering.map((outline) => (jsx_runtime_1.jsx(SelectedOutlineUvControls_1.SelectedOutlineUvHandleCircleLayer, { onDraggingChange: onDraggingChange, onSelect: selectOutlineItem, outline: outline, target: targetsByKey.get(outline.key) }, `${outline.key}-uv-handles`)))] }));
626
642
  };
627
643
  exports.SelectedOutlineOverlay = SelectedOutlineOverlay;
@@ -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;