@remotion/studio 4.0.482 → 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 (34) hide show
  1. package/dist/components/Canvas.js +19 -0
  2. package/dist/components/InspectorPanel/styles.js +2 -0
  3. package/dist/components/InspectorSequenceSection.js +45 -2
  4. package/dist/components/SelectedOutlineUvControls.js +461 -2
  5. package/dist/components/Timeline/EasingEditorModal.js +39 -1
  6. package/dist/components/Timeline/Timeline.js +2 -1
  7. package/dist/components/Timeline/TimelineEffectItem.js +8 -5
  8. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +2 -2
  9. package/dist/components/Timeline/TimelineKeyframedValue.js +1 -0
  10. package/dist/components/Timeline/TimelineRowChrome.js +6 -4
  11. package/dist/components/Timeline/TimelineSelection.d.ts +7 -1
  12. package/dist/components/Timeline/TimelineSelection.js +19 -3
  13. package/dist/components/Timeline/TimelineSequence.js +20 -8
  14. package/dist/components/Timeline/TimelineSequenceItem.js +16 -13
  15. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +40 -1
  16. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +308 -1
  17. package/dist/components/Timeline/TimelineTrack.js +2 -4
  18. package/dist/components/Timeline/should-subscribe-to-sequence-props.d.ts +4 -0
  19. package/dist/components/Timeline/should-subscribe-to-sequence-props.js +10 -0
  20. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.d.ts +2 -1
  21. package/dist/components/Timeline/use-sequence-freeze-frame-menu-item.js +19 -13
  22. package/dist/components/element-drag-and-drop.d.ts +3 -0
  23. package/dist/components/element-drag-and-drop.js +30 -0
  24. package/dist/components/import-assets.d.ts +11 -0
  25. package/dist/components/import-assets.js +23 -1
  26. package/dist/components/selected-outline-uv.d.ts +71 -1
  27. package/dist/components/selected-outline-uv.js +332 -10
  28. package/dist/esm/{chunk-nkqfa5bw.js → chunk-fq0j774v.js} +2191 -817
  29. package/dist/esm/internals.mjs +2191 -817
  30. package/dist/esm/previewEntry.mjs +2201 -827
  31. package/dist/esm/renderEntry.mjs +1 -1
  32. package/dist/helpers/timeline-layout.d.ts +3 -3
  33. package/dist/helpers/timeline-layout.js +3 -1
  34. package/package.json +11 -11
@@ -23,6 +23,7 @@ const EditorGuides_1 = __importDefault(require("./EditorGuides"));
23
23
  const EditorRuler_1 = require("./EditorRuler");
24
24
  const use_is_ruler_visible_1 = require("./EditorRuler/use-is-ruler-visible");
25
25
  const effect_drag_and_drop_1 = require("./effect-drag-and-drop");
26
+ const element_drag_and_drop_1 = require("./element-drag-and-drop");
26
27
  const import_assets_1 = require("./import-assets");
27
28
  const layout_1 = require("./layout");
28
29
  const Preview_1 = require("./Preview");
@@ -57,6 +58,11 @@ const isComponentDragEvent = (event) => {
57
58
  var _b;
58
59
  return Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) !== null && _b !== void 0 ? _b : []).includes(studio_shared_1.COMPONENT_DRAG_MIME_TYPE);
59
60
  };
61
+ const isElementDragEvent = (event) => {
62
+ var _a;
63
+ var _b;
64
+ return Array.from((_b = (_a = event.dataTransfer) === null || _a === void 0 ? void 0 : _a.types) !== null && _b !== void 0 ? _b : []).includes(studio_shared_1.ELEMENT_DRAG_MIME_TYPE);
65
+ };
60
66
  const isSfxDragEvent = (event) => {
61
67
  var _a;
62
68
  var _b;
@@ -66,6 +72,7 @@ const isRemoteAssetDragEvent = (event) => {
66
72
  return (!isFileDragEvent(event) &&
67
73
  !isAssetDragEvent(event) &&
68
74
  !isComponentDragEvent(event) &&
75
+ !isElementDragEvent(event) &&
69
76
  !isSfxDragEvent(event) &&
70
77
  (0, remote_asset_drag_1.hasRemoteAssetDragData)(event.dataTransfer));
71
78
  };
@@ -560,6 +567,7 @@ const Canvas = ({ canvasContent, size }) => {
560
567
  (!isFileDragEvent(event) &&
561
568
  !isAssetDragEvent(event) &&
562
569
  !isComponentDragEvent(event) &&
570
+ !isElementDragEvent(event) &&
563
571
  !isSfxDragEvent(event) &&
564
572
  !isRemoteAssetDragEvent(event)) ||
565
573
  !isDragEventInsideCanvas(event)) {
@@ -579,6 +587,7 @@ const Canvas = ({ canvasContent, size }) => {
579
587
  (!isFileDragEvent(event) &&
580
588
  !isAssetDragEvent(event) &&
581
589
  !isComponentDragEvent(event) &&
590
+ !isElementDragEvent(event) &&
582
591
  !isSfxDragEvent(event) &&
583
592
  !isRemoteAssetDragEvent(event)) ||
584
593
  !isDragEventInsideCanvas(event)) {
@@ -636,6 +645,16 @@ const Canvas = ({ canvasContent, size }) => {
636
645
  });
637
646
  }
638
647
  else {
648
+ const elementDragData = (0, element_drag_and_drop_1.getElementDragData)(event.dataTransfer);
649
+ if (elementDragData !== null) {
650
+ await (0, import_assets_1.insertElement)({
651
+ element: elementDragData.element,
652
+ compositionFile,
653
+ compositionId: currentCompositionId,
654
+ dropPosition,
655
+ });
656
+ return;
657
+ }
639
658
  const componentDragData = getComponentDragData(event);
640
659
  if (componentDragData !== null) {
641
660
  await (0, import_assets_1.insertComponent)({
@@ -36,6 +36,7 @@ exports.sectionHeader = {
36
36
  fontSize: 12,
37
37
  fontWeight: 'bold',
38
38
  padding: `8px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px`,
39
+ userSelect: 'none',
39
40
  };
40
41
  exports.sequenceHeader = {
41
42
  backgroundColor: colors_1.BACKGROUND,
@@ -96,6 +97,7 @@ exports.sectionHeaderTitle = {
96
97
  minWidth: 0,
97
98
  overflow: 'hidden',
98
99
  textOverflow: 'ellipsis',
100
+ userSelect: 'none',
99
101
  whiteSpace: 'nowrap',
100
102
  };
101
103
  exports.sectionHeaderStart = {
@@ -1,8 +1,41 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.InspectorSequenceSection = exports.hasSequenceControls = exports.getInspectorSelectableItems = void 0;
4
37
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("react");
38
+ const react_1 = __importStar(require("react"));
6
39
  const client_id_1 = require("../helpers/client-id");
7
40
  const colors_1 = require("../helpers/colors");
8
41
  const timeline_layout_1 = require("../helpers/timeline-layout");
@@ -55,6 +88,15 @@ const isEffectsRoot = (node) => {
55
88
  const getInspectorExpansionKey = (nodePathInfo) => {
56
89
  return JSON.stringify(nodePathInfo);
57
90
  };
91
+ const getInspectorControlGroups = (rows) => {
92
+ return timeline_layout_1.SCHEMA_FIELD_GROUPS.map((group) => ({
93
+ ...group,
94
+ rows: rows.filter(({ node }) => {
95
+ var _a;
96
+ return node.kind === 'field' && ((_a = node.field) === null || _a === void 0 ? void 0 : _a.group) === group.id;
97
+ }),
98
+ })).filter((group) => group.rows.length > 0);
99
+ };
58
100
  const getInspectorSelectableItems = (rows) => {
59
101
  return rows.flatMap(({ node }) => {
60
102
  const selection = (0, TimelineSelection_1.getTimelineSelectionFromNodePathInfo)(node.nodePathInfo);
@@ -116,6 +158,7 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
116
158
  }, [getIsExpanded, tree]);
117
159
  const controlSelectableItems = (0, react_1.useMemo)(() => (0, exports.getInspectorSelectableItems)(controlRows), [controlRows]);
118
160
  const effectSelectableItems = (0, react_1.useMemo)(() => (0, exports.getInspectorSelectableItems)(effectRows), [effectRows]);
161
+ const controlGroups = (0, react_1.useMemo)(() => getInspectorControlGroups(controlRows), [controlRows]);
119
162
  const { schema } = sequence.controls;
120
163
  const showEffectsSection = nodePathInfo.supportsEffects || effectRows.length > 0;
121
164
  const showControlsEffectsDivider = controlRows.length > 0 && showEffectsSection;
@@ -152,6 +195,6 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
152
195
  ] }));
153
196
  }
154
197
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
155
- jsx_runtime_1.jsx("div", { style: divider }), controlRows.length > 0 ? renderSectionHeader('Controls') : null, jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: controlRows.map(renderRow) }), showEffectsSection ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showControlsEffectsDivider ? (jsx_runtime_1.jsx("div", { style: controlsEffectsDivider })) : null, renderEffectsHeader(), effectRows.length === 0 ? (jsx_runtime_1.jsx("div", { style: emptyState, children: "None" })) : (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: effectSelectableItems, children: effectRows.map(renderRow) }))] })) : null] }));
198
+ jsx_runtime_1.jsx("div", { style: divider }), controlRows.length > 0 ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: controlGroups.map((group, i) => (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [i === 0 ? null : jsx_runtime_1.jsx("div", { style: controlsEffectsDivider }), renderSectionHeader(group.label), group.rows.map(renderRow)] }, group.id))) })) : null, showEffectsSection ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showControlsEffectsDivider ? (jsx_runtime_1.jsx("div", { style: controlsEffectsDivider })) : null, renderEffectsHeader(), effectRows.length === 0 ? (jsx_runtime_1.jsx("div", { style: emptyState, children: "None" })) : (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: effectSelectableItems, children: effectRows.map(renderRow) }))] })) : null] }));
156
199
  };
157
200
  exports.InspectorSequenceSection = InspectorSequenceSection;
@@ -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;