@remotion/studio 4.0.498 → 4.0.499

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 (48) hide show
  1. package/dist/components/AssetSelectorItem.js +31 -3
  2. package/dist/components/Canvas.js +162 -7
  3. package/dist/components/CompositionSelector.js +13 -10
  4. package/dist/components/CompositionSelectorItem.js +21 -13
  5. package/dist/components/EditorContent.js +1 -1
  6. package/dist/components/EditorRuler/Ruler.js +5 -3
  7. package/dist/components/ForceSpecificCursor.js +13 -1
  8. package/dist/components/NewComposition/InputDragger.d.ts +27 -0
  9. package/dist/components/NewComposition/InputDragger.js +151 -23
  10. package/dist/components/Splitter/SplitterContainer.d.ts +2 -0
  11. package/dist/components/Splitter/SplitterContainer.js +5 -1
  12. package/dist/components/Splitter/SplitterContext.d.ts +2 -0
  13. package/dist/components/Splitter/SplitterContext.js +2 -0
  14. package/dist/components/Splitter/SplitterElement.js +6 -1
  15. package/dist/components/Splitter/SplitterHandle.js +27 -2
  16. package/dist/components/Timeline/Timeline.js +1 -1
  17. package/dist/components/Timeline/TimelineInOutDragHandler.js +25 -1
  18. package/dist/components/Timeline/TimelineLayerEye.js +4 -1
  19. package/dist/components/Timeline/TimelineSequence.js +6 -1
  20. package/dist/components/Timeline/TimelineSequenceName.js +1 -0
  21. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +5 -1
  22. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +29 -11
  23. package/dist/components/Timeline/use-timeline-keyframe-drag.js +6 -4
  24. package/dist/components/TopPanel.js +2 -1
  25. package/dist/components/composition-drop-preview.d.ts +33 -0
  26. package/dist/components/composition-drop-preview.js +67 -0
  27. package/dist/components/drop-handler-data.d.ts +1 -1
  28. package/dist/components/drop-handler-data.js +27 -60
  29. package/dist/components/effect-drag-and-drop.d.ts +1 -1
  30. package/dist/components/effect-drag-and-drop.js +7 -55
  31. package/dist/components/element-drag-and-drop.d.ts +1 -1
  32. package/dist/components/element-drag-and-drop.js +5 -17
  33. package/dist/components/handle-drop.js +0 -1
  34. package/dist/components/import-assets.d.ts +7 -8
  35. package/dist/components/import-assets.js +2 -9
  36. package/dist/esm/{chunk-7a6q9hk2.js → chunk-pk1zwsn1.js} +3549 -2482
  37. package/dist/esm/internals.mjs +3549 -2482
  38. package/dist/esm/previewEntry.mjs +8342 -7275
  39. package/dist/esm/renderEntry.mjs +1 -1
  40. package/dist/helpers/get-effective-translation.d.ts +13 -1
  41. package/dist/helpers/get-effective-translation.js +12 -6
  42. package/dist/helpers/ruler-canvas-size.d.ts +7 -0
  43. package/dist/helpers/ruler-canvas-size.js +14 -1
  44. package/dist/helpers/use-image-metadata.d.ts +1 -0
  45. package/dist/helpers/use-image-metadata.js +8 -5
  46. package/dist/helpers/use-media-metadata.d.ts +1 -0
  47. package/dist/helpers/use-media-metadata.js +8 -5
  48. package/package.json +13 -12
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.InputDragger = exports.deriveInputDraggerValueDiff = exports.isInputDraggerValueInRange = exports.deriveInputDraggerDragStartValue = exports.deriveInputDraggerStep = exports.inputDraggerContainerStyle = void 0;
36
+ exports.InputDragger = exports.deriveInputDraggerValueDiff = exports.isInputDraggerValueInRange = exports.deriveInputDraggerDragStartValue = exports.deriveInputDraggerStep = exports.deriveInputDraggerArrowValue = exports.validateInputDraggerValue = exports.isInputDraggerValueAlignedToStep = exports.parseInputDraggerNumber = exports.inputDraggerContainerStyle = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
@@ -60,6 +60,93 @@ const roundToDecimalPlaces = (val, decimalPlaces) => {
60
60
  const rounded = Math.round(val * factor) / factor;
61
61
  return Object.is(rounded, -0) ? 0 : rounded;
62
62
  };
63
+ const validNumberPattern = /^[+-]?(?:(?:\d+(?:\.\d*)?)|(?:\.\d+))(?:e[+-]?\d+)?$/i;
64
+ const parseInputDraggerNumber = (value) => {
65
+ const trimmedValue = value.trim();
66
+ if (!validNumberPattern.test(trimmedValue)) {
67
+ return null;
68
+ }
69
+ const parsed = Number(trimmedValue);
70
+ return Number.isFinite(parsed) ? parsed : null;
71
+ };
72
+ exports.parseInputDraggerNumber = parseInputDraggerNumber;
73
+ const getFiniteAttribute = (value) => {
74
+ const parsed = Number(value);
75
+ return Number.isFinite(parsed) ? parsed : null;
76
+ };
77
+ const getPositiveStep = (step) => {
78
+ if (step === 'any') {
79
+ return null;
80
+ }
81
+ const parsed = Number(step);
82
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : 1;
83
+ };
84
+ const isInputDraggerValueAlignedToStep = ({ min, step, value, }) => {
85
+ var _a;
86
+ const numericStep = getPositiveStep(step);
87
+ if (numericStep === null) {
88
+ return true;
89
+ }
90
+ const stepBase = (_a = getFiniteAttribute(min)) !== null && _a !== void 0 ? _a : 0;
91
+ const stepsFromBase = (value - stepBase) / numericStep;
92
+ const tolerance = Number.EPSILON *
93
+ 10 *
94
+ Math.max(1, Math.abs(value / numericStep), Math.abs(stepBase / numericStep));
95
+ return Math.abs(stepsFromBase - Math.round(stepsFromBase)) <= tolerance;
96
+ };
97
+ exports.isInputDraggerValueAlignedToStep = isInputDraggerValueAlignedToStep;
98
+ const validateInputDraggerValue = ({ max, min, step, value, }) => {
99
+ const parsed = (0, exports.parseInputDraggerNumber)(value);
100
+ if (parsed === null) {
101
+ return {
102
+ valid: false,
103
+ message: 'Enter a valid number.',
104
+ };
105
+ }
106
+ const numericMin = getFiniteAttribute(min);
107
+ if (numericMin !== null && parsed < numericMin) {
108
+ return {
109
+ valid: false,
110
+ message: `Value must be greater than or equal to ${numericMin}.`,
111
+ };
112
+ }
113
+ const numericMax = getFiniteAttribute(max);
114
+ if (numericMax !== null && parsed > numericMax) {
115
+ return {
116
+ valid: false,
117
+ message: `Value must be less than or equal to ${numericMax}.`,
118
+ };
119
+ }
120
+ if (!(0, exports.isInputDraggerValueAlignedToStep)({ min, step, value: parsed })) {
121
+ return {
122
+ valid: false,
123
+ message: `Value must align to a step of ${step}.`,
124
+ };
125
+ }
126
+ return { valid: true, value: parsed };
127
+ };
128
+ exports.validateInputDraggerValue = validateInputDraggerValue;
129
+ const getDecimalPlaces = (value) => {
130
+ var _a;
131
+ var _b;
132
+ const [mantissa, exponentString] = String(value).toLowerCase().split('e');
133
+ const exponent = Number(exponentString !== null && exponentString !== void 0 ? exponentString : 0);
134
+ const fractionLength = (_b = (_a = mantissa.split('.')[1]) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
135
+ return Math.max(0, fractionLength - exponent);
136
+ };
137
+ const deriveInputDraggerArrowValue = ({ direction, max, min, step, value, }) => {
138
+ var _a, _b, _c;
139
+ const numericStep = (_a = getPositiveStep(step)) !== null && _a !== void 0 ? _a : 1;
140
+ const decimalPlaces = Math.max(getDecimalPlaces(value), getDecimalPlaces(numericStep));
141
+ const unroundedValue = value + direction * numericStep;
142
+ const steppedValue = decimalPlaces <= 15
143
+ ? roundToDecimalPlaces(unroundedValue, decimalPlaces)
144
+ : Number(unroundedValue.toPrecision(15));
145
+ const numericMin = (_b = getFiniteAttribute(min)) !== null && _b !== void 0 ? _b : -Infinity;
146
+ const numericMax = (_c = getFiniteAttribute(max)) !== null && _c !== void 0 ? _c : Infinity;
147
+ return Math.min(numericMax, Math.max(numericMin, steppedValue));
148
+ };
149
+ exports.deriveInputDraggerArrowValue = deriveInputDraggerArrowValue;
63
150
  const deriveInputDraggerStep = ({ min, snapToStep, step, }) => {
64
151
  if (!snapToStep) {
65
152
  return 'any';
@@ -96,11 +183,18 @@ const deriveInputDraggerValueDiff = ({ dragSensitivity, step, xDistance, }) => {
96
183
  return (0, remotion_1.interpolate)(xDistance, [-5, -4, 0, 4, 5], [-step * dragSensitivity, 0, 0, 0, step * dragSensitivity]);
97
184
  };
98
185
  exports.deriveInputDraggerValueDiff = deriveInputDraggerValueDiff;
99
- const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min, max: _max, step: _step, value, onTextChange, formatter = (q) => String(q), status, rightAlign, small, snapToStep = true, dragDecimalPlaces, dragSensitivity = 1, ...props }, ref) => {
186
+ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min, max: _max, step: _step, value, onTextChange, formatter = (q) => String(q), status, rightAlign, small, snapToStep = true, dragDecimalPlaces, dragSensitivity = 1, type: _type, ...props }, ref) => {
100
187
  const [inputFallback, setInputFallback] = (0, react_1.useState)(false);
101
188
  const [dragging, setDragging] = (0, react_1.useState)(false);
102
189
  const fallbackRef = (0, react_1.useRef)(null);
103
190
  const pointerDownRef = (0, react_1.useRef)(false);
191
+ const deriveStep = (0, react_1.useMemo)(() => {
192
+ return (0, exports.deriveInputDraggerStep)({
193
+ min: _min,
194
+ snapToStep,
195
+ step: _step,
196
+ });
197
+ }, [_min, _step, snapToStep]);
104
198
  const span = (0, react_1.useMemo)(() => ({
105
199
  color: dragging ? 'var(--remotion-cli-internals-blue-hovered)' : colors_1.BLUE,
106
200
  cursor: 'ew-resize',
@@ -136,9 +230,9 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
136
230
  setInputFallback(false);
137
231
  }, []);
138
232
  const onInputChange = (0, react_1.useCallback)((e) => {
139
- const parsed = Number(e.target.value);
140
- if (e.target.value !== '' &&
141
- !Number.isNaN(parsed) &&
233
+ e.target.setCustomValidity('');
234
+ const parsed = (0, exports.parseInputDraggerNumber)(e.target.value);
235
+ if (parsed !== null &&
142
236
  (0, exports.isInputDraggerValueInRange)({
143
237
  max: _max,
144
238
  min: _min,
@@ -156,20 +250,48 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
156
250
  onEscape();
157
251
  return;
158
252
  }
159
- if (fallbackRef.current.checkValidity()) {
160
- onValueChangeEnd === null || onValueChangeEnd === void 0 ? void 0 : onValueChangeEnd(Number(newValue));
253
+ const validation = (0, exports.validateInputDraggerValue)({
254
+ max: _max,
255
+ min: _min,
256
+ step: deriveStep,
257
+ value: newValue,
258
+ });
259
+ if (validation.valid) {
260
+ fallbackRef.current.setCustomValidity('');
261
+ onValueChangeEnd === null || onValueChangeEnd === void 0 ? void 0 : onValueChangeEnd(validation.value);
161
262
  setInputFallback(false);
162
263
  }
163
264
  else {
265
+ fallbackRef.current.setCustomValidity(validation.message);
164
266
  fallbackRef.current.reportValidity();
165
267
  }
166
- }, [onEscape, onValueChangeEnd]);
167
- const onKeyPress = (0, react_1.useCallback)((e) => {
268
+ }, [_max, _min, deriveStep, onEscape, onValueChangeEnd]);
269
+ const onInputKeyDown = (0, react_1.useCallback)((e) => {
168
270
  var _a;
169
271
  if (e.key === 'Enter') {
170
272
  (_a = fallbackRef.current) === null || _a === void 0 ? void 0 : _a.blur();
273
+ return;
171
274
  }
172
- }, []);
275
+ if (e.key !== 'ArrowUp' && e.key !== 'ArrowDown') {
276
+ return;
277
+ }
278
+ e.preventDefault();
279
+ const parsedInputValue = (0, exports.parseInputDraggerNumber)(e.currentTarget.value);
280
+ const currentValue = parsedInputValue !== null && parsedInputValue !== void 0 ? parsedInputValue : (0, exports.deriveInputDraggerDragStartValue)({
281
+ min: _min,
282
+ value,
283
+ });
284
+ const nextValue = (0, exports.deriveInputDraggerArrowValue)({
285
+ direction: e.key === 'ArrowUp' ? 1 : -1,
286
+ max: _max,
287
+ min: _min,
288
+ step: deriveStep,
289
+ value: currentValue,
290
+ });
291
+ e.currentTarget.value = String(nextValue);
292
+ e.currentTarget.setCustomValidity('');
293
+ onValueChange(nextValue);
294
+ }, [_max, _min, deriveStep, onValueChange, value]);
173
295
  const roundToStep = (val, stepSize) => {
174
296
  const factor = 1 / stepSize;
175
297
  return Math.ceil(val * factor) / factor;
@@ -214,20 +336,33 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
214
336
  onValueChange(nextValue);
215
337
  };
216
338
  window.addEventListener('mousemove', moveListener);
217
- window.addEventListener('pointerup', () => {
339
+ const endDrag = (commit) => {
218
340
  window.removeEventListener('mousemove', moveListener);
341
+ window.removeEventListener('pointerup', onPointerUp);
342
+ window.removeEventListener('pointercancel', onPointerCancel);
343
+ window.removeEventListener('blur', onWindowBlur);
219
344
  pointerDownRef.current = false;
220
345
  setDragging(false);
221
346
  (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
222
- if (lastDragValue !== null && onValueChangeEnd) {
347
+ if (commit && lastDragValue !== null && onValueChangeEnd) {
223
348
  onValueChangeEnd(lastDragValue);
224
349
  }
225
350
  setTimeout(() => {
226
351
  (0, input_dragger_click_lock_1.setClickLock)(false);
227
352
  }, 2);
228
- }, {
229
- once: true,
230
- });
353
+ };
354
+ const onPointerUp = () => {
355
+ endDrag(true);
356
+ };
357
+ const onPointerCancel = () => {
358
+ endDrag(false);
359
+ };
360
+ const onWindowBlur = () => {
361
+ endDrag(false);
362
+ };
363
+ window.addEventListener('pointerup', onPointerUp);
364
+ window.addEventListener('pointercancel', onPointerCancel);
365
+ window.addEventListener('blur', onWindowBlur);
231
366
  }, [
232
367
  _step,
233
368
  _min,
@@ -245,15 +380,8 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
245
380
  (_a = fallbackRef.current) === null || _a === void 0 ? void 0 : _a.select();
246
381
  }
247
382
  }, [inputFallback]);
248
- const deriveStep = (0, react_1.useMemo)(() => {
249
- return (0, exports.deriveInputDraggerStep)({
250
- min: _min,
251
- snapToStep,
252
- step: _step,
253
- });
254
- }, [_min, _step, snapToStep]);
255
383
  if (inputFallback) {
256
- return (jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: onEscape, onOutsideClick: noop_1.noop, children: jsx_runtime_1.jsx(RemInput_1.RemotionInput, { ref: fallbackRef, autoFocus: true, onKeyPress: onKeyPress, onBlur: onBlur, onChange: onInputChange, min: _min, max: _max, step: deriveStep, defaultValue: value, status: status, pattern: '[0-9]*[.]?[0-9]*', rightAlign: rightAlign, small: small, ...props }) }));
384
+ return (jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: onEscape, onOutsideClick: noop_1.noop, children: jsx_runtime_1.jsx(RemInput_1.RemotionInput, { ref: fallbackRef, autoFocus: true, onKeyDown: onInputKeyDown, onBlur: onBlur, onChange: onInputChange, min: _min, max: _max, step: deriveStep, defaultValue: value, status: status, rightAlign: rightAlign, small: small, ...props, type: "text" }) }));
257
385
  }
258
386
  return (jsx_runtime_1.jsx("button", { ref: ref, type: "button", className: '__remotion_input_dragger', style: exports.inputDraggerContainerStyle, onClick: onClick, onFocus: onFocus, onKeyDown: onKeyDown, onPointerDown: onPointerDown, children: jsx_runtime_1.jsx("span", { style: span, children: formatter(value) }) }));
259
387
  };
@@ -5,6 +5,8 @@ export declare const SplitterContainer: React.FC<{
5
5
  readonly orientation: SplitterOrientation;
6
6
  readonly maxFlex: number;
7
7
  readonly minFlex: number;
8
+ readonly maxFlexerSize: number | null;
9
+ readonly maxAntiFlexerSize: number | null;
8
10
  readonly id: string;
9
11
  readonly defaultFlex: number;
10
12
  readonly children: React.ReactNode;
@@ -19,7 +19,7 @@ exports.containerColumn = {
19
19
  flex: 1,
20
20
  height: 0,
21
21
  };
22
- const SplitterContainer = ({ orientation, children, defaultFlex, maxFlex, minFlex, id }) => {
22
+ const SplitterContainer = ({ orientation, children, defaultFlex, maxFlex, minFlex, maxFlexerSize, maxAntiFlexerSize, id, }) => {
23
23
  const [initialTimelineFlex, persistFlex] = (0, timeline_1.useTimelineFlex)(id);
24
24
  const [flexValue, setFlexValue] = (0, react_1.useState)(initialTimelineFlex !== null && initialTimelineFlex !== void 0 ? initialTimelineFlex : defaultFlex);
25
25
  const ref = (0, react_1.useRef)(null);
@@ -34,6 +34,8 @@ const SplitterContainer = ({ orientation, children, defaultFlex, maxFlex, minFle
34
34
  id,
35
35
  maxFlex,
36
36
  minFlex,
37
+ maxFlexerSize,
38
+ maxAntiFlexerSize,
37
39
  defaultFlex,
38
40
  persistFlex,
39
41
  };
@@ -42,6 +44,8 @@ const SplitterContainer = ({ orientation, children, defaultFlex, maxFlex, minFle
42
44
  flexValue,
43
45
  id,
44
46
  maxFlex,
47
+ maxFlexerSize,
48
+ maxAntiFlexerSize,
45
49
  minFlex,
46
50
  orientation,
47
51
  persistFlex,
@@ -11,6 +11,8 @@ export type TSplitterContext = {
11
11
  ref: React.RefObject<HTMLDivElement | null>;
12
12
  maxFlex: number;
13
13
  minFlex: number;
14
+ maxFlexerSize: number | null;
15
+ maxAntiFlexerSize: number | null;
14
16
  defaultFlex: number;
15
17
  id: string;
16
18
  persistFlex: (value: number) => void;
@@ -13,6 +13,8 @@ exports.SplitterContext = react_1.default.createContext({
13
13
  orientation: 'horizontal',
14
14
  maxFlex: 1,
15
15
  minFlex: 1,
16
+ maxFlexerSize: null,
17
+ maxAntiFlexerSize: null,
16
18
  defaultFlex: 1,
17
19
  id: '--',
18
20
  persistFlex: () => undefined,
@@ -8,6 +8,7 @@ const colors_1 = require("../../helpers/colors");
8
8
  const SplitterContext_1 = require("./SplitterContext");
9
9
  const SplitterElement = ({ children, type, sticky }) => {
10
10
  const context = (0, react_1.useContext)(SplitterContext_1.SplitterContext);
11
+ const maxSize = type === 'flexer' ? context.maxFlexerSize : context.maxAntiFlexerSize;
11
12
  const style = (0, react_1.useMemo)(() => {
12
13
  return {
13
14
  flex:
@@ -17,8 +18,12 @@ const SplitterElement = ({ children, type, sticky }) => {
17
18
  position: 'relative',
18
19
  overflow: 'hidden',
19
20
  flexDirection: 'column',
21
+ maxWidth: context.orientation === 'vertical' ? (maxSize !== null && maxSize !== void 0 ? maxSize : undefined) : undefined,
22
+ maxHeight: context.orientation === 'horizontal'
23
+ ? (maxSize !== null && maxSize !== void 0 ? maxSize : undefined)
24
+ : undefined,
20
25
  };
21
- }, [context.flexValue, type]);
26
+ }, [context.flexValue, context.orientation, maxSize, type]);
22
27
  const stickStyle = (0, react_1.useMemo)(() => {
23
28
  return {
24
29
  position: 'absolute',
@@ -31,6 +31,8 @@ const SplitterHandle = ({ allowToCollapse, onCollapse }) => {
31
31
  // Cleanup for the listeners that only exist for the duration of a drag.
32
32
  let endDrag = null;
33
33
  const onPointerDown = (e) => {
34
+ var _a;
35
+ var _b;
34
36
  if (e.button !== 0) {
35
37
  return;
36
38
  }
@@ -40,7 +42,20 @@ const SplitterHandle = ({ allowToCollapse, onCollapse }) => {
40
42
  // value updates on every pointermove, so it must not be re-read live.
41
43
  const dragContext = latest.current.context;
42
44
  const start = { x: e.clientX, y: e.clientY };
43
- const startFlex = dragContext.flexValue;
45
+ const { width: containerWidth, height: containerHeight } = (_b = (_a = dragContext.ref.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) !== null && _b !== void 0 ? _b : {
46
+ width: 0,
47
+ height: 0,
48
+ };
49
+ const availableSize = (dragContext.orientation === 'vertical'
50
+ ? containerWidth
51
+ : containerHeight) - exports.SPLITTER_HANDLE_SIZE;
52
+ const minFlex = dragContext.maxAntiFlexerSize === null || availableSize <= 0
53
+ ? dragContext.minFlex
54
+ : Math.max(dragContext.minFlex, 1 - dragContext.maxAntiFlexerSize / availableSize);
55
+ const maxFlex = dragContext.maxFlexerSize === null || availableSize <= 0
56
+ ? dragContext.maxFlex
57
+ : Math.min(dragContext.maxFlex, dragContext.maxFlexerSize / availableSize);
58
+ const startFlex = Math.min(maxFlex, Math.max(minFlex, dragContext.flexValue));
44
59
  dragContext.isDragging.current = start;
45
60
  (0, ForceSpecificCursor_1.forceSpecificCursor)(dragContext.orientation === 'horizontal' ? 'row-resize' : 'col-resize');
46
61
  current.classList.add('remotion-splitter-active');
@@ -54,7 +69,7 @@ const SplitterHandle = ({ allowToCollapse, onCollapse }) => {
54
69
  : (ev.clientY - start.y) / (height - exports.SPLITTER_HANDLE_SIZE);
55
70
  const newFlex = startFlex + change;
56
71
  if (clamp) {
57
- return Math.min(dragContext.maxFlex, Math.max(dragContext.minFlex, newFlex));
72
+ return Math.min(maxFlex, Math.max(minFlex, newFlex));
58
73
  }
59
74
  return newFlex;
60
75
  };
@@ -64,6 +79,8 @@ const SplitterHandle = ({ allowToCollapse, onCollapse }) => {
64
79
  current.classList.remove('remotion-splitter-active');
65
80
  window.removeEventListener('pointermove', onPointerMove);
66
81
  window.removeEventListener('pointerup', onPointerUp);
82
+ window.removeEventListener('pointercancel', onPointerCancel);
83
+ window.removeEventListener('blur', onWindowBlur);
67
84
  endDrag = null;
68
85
  player_1.PlayerInternals.updateAllElementsSizes();
69
86
  };
@@ -95,8 +112,16 @@ const SplitterHandle = ({ allowToCollapse, onCollapse }) => {
95
112
  dragContext.persistFlex(getNewValue(ev, true));
96
113
  endDrag === null || endDrag === void 0 ? void 0 : endDrag();
97
114
  };
115
+ const onPointerCancel = () => {
116
+ endDrag === null || endDrag === void 0 ? void 0 : endDrag();
117
+ };
118
+ const onWindowBlur = () => {
119
+ endDrag === null || endDrag === void 0 ? void 0 : endDrag();
120
+ };
98
121
  window.addEventListener('pointermove', onPointerMove);
99
122
  window.addEventListener('pointerup', onPointerUp);
123
+ window.addEventListener('pointercancel', onPointerCancel);
124
+ window.addEventListener('blur', onWindowBlur);
100
125
  };
101
126
  current.addEventListener('pointerdown', onPointerDown);
102
127
  return () => {
@@ -253,7 +253,7 @@ const TimelineInner = () => {
253
253
  }
254
254
  return (jsx_runtime_1.jsx(SubscribeToNodePaths_1.SubscribeToNodePaths, { overrideId: sequence.controls.overrideId, componentIdentity: sequence.controls.componentIdentity, schema: sequence.controls.schema, getStack: sequence.getStack, effects: sequence.effects }, sequence.id));
255
255
  }), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? jsx_runtime_1.jsx(SequencePropsObserver_1.SequencePropsObserver, {}) : null, jsx_runtime_1.jsx(TimelineKeyframeTracksContext_1.TimelineKeyframeTracksProvider, { tracks: filtered, children: jsx_runtime_1.jsxs(TimelineSelection_1.TimelineSelectableItemsProvider, { timeline: shown, children: [(0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectAllKeybindings, { timeline: shown })) : null, jsx_runtime_1.jsx(TimelineHeightContainer_1.TimelineHeightContainer, { shown: shown, hasBeenCut: hasBeenCut, children: isStill ? (jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown })) : (jsx_runtime_1.jsxs(TimelineWidthProvider_1.TimelineWidthProvider, { children: [
256
- jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, children: [
256
+ jsx_runtime_1.jsx(TimelinePinchZoom_1.TimelinePinchZoom, {}), jsx_runtime_1.jsxs(SplitterContainer_1.SplitterContainer, { orientation: "vertical", defaultFlex: 0.2, id: "names-to-timeline", maxFlex: 0.5, minFlex: 0.15, maxFlexerSize: null, maxAntiFlexerSize: null, children: [
257
257
  jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "flexer", sticky: jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePlaceholders, {}), children: jsx_runtime_1.jsx(TimelineList_1.TimelineList, { timeline: shown }) }), jsx_runtime_1.jsx(SplitterHandle_1.SplitterHandle, { onCollapse: noop, allowToCollapse: "none" }), jsx_runtime_1.jsx(SplitterElement_1.SplitterElement, { type: "anti-flexer", sticky: null, children: jsx_runtime_1.jsxs(TimelineScrollable_1.TimelineScrollable, { children: [
258
258
  jsx_runtime_1.jsx(TimelineTracks_1.TimelineTracks, { timeline: shown, hasBeenCut: hasBeenCut }), jsx_runtime_1.jsx(TimelinePlayCursorSyncer_1.TimelinePlayCursorSyncer, {}), jsx_runtime_1.jsx(TimelineInOutPointer_1.TimelineInOutPointer, {}), jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimeIndicators, {}), jsx_runtime_1.jsx(TimelineDragHandler_1.TimelineDragHandler, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsx(TimelineInOutDragHandler_1.TimelineInOutDragHandler, {})) : null, jsx_runtime_1.jsx(TimelineSlider_1.TimelineSlider, {})
259
259
  ] }) })
@@ -252,17 +252,41 @@ const TimelineInOutDragHandlerInner = () => {
252
252
  videoConfig,
253
253
  width,
254
254
  ]);
255
+ const onPointerCancelInOut = (0, react_1.useCallback)(() => {
256
+ document.body.style.userSelect = '';
257
+ document.body.style.webkitUserSelect = '';
258
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
259
+ setInOutDragging({
260
+ dragging: false,
261
+ });
262
+ }, []);
255
263
  (0, react_1.useEffect)(() => {
256
264
  if (inOutDragging.dragging === false) {
257
265
  return;
258
266
  }
259
267
  window.addEventListener('pointermove', onPointerMoveInOut);
260
268
  window.addEventListener('pointerup', onPointerUpInOut);
269
+ window.addEventListener('pointercancel', onPointerCancelInOut);
270
+ window.addEventListener('blur', onPointerCancelInOut);
261
271
  return () => {
262
272
  window.removeEventListener('pointermove', onPointerMoveInOut);
263
273
  window.removeEventListener('pointerup', onPointerUpInOut);
274
+ window.removeEventListener('pointercancel', onPointerCancelInOut);
275
+ window.removeEventListener('blur', onPointerCancelInOut);
276
+ };
277
+ }, [
278
+ inOutDragging.dragging,
279
+ onPointerCancelInOut,
280
+ onPointerMoveInOut,
281
+ onPointerUpInOut,
282
+ ]);
283
+ (0, react_1.useEffect)(() => {
284
+ return () => {
285
+ document.body.style.userSelect = '';
286
+ document.body.style.webkitUserSelect = '';
287
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
264
288
  };
265
- }, [inOutDragging.dragging, onPointerMoveInOut, onPointerUpInOut]);
289
+ }, []);
266
290
  const inContextMenu = (0, react_1.useMemo)(() => {
267
291
  return [
268
292
  {
@@ -64,7 +64,10 @@ const TimelineLayerEye = ({ onInvoked, hidden, type }) => {
64
64
  onInvoked(layerPointedDown);
65
65
  }
66
66
  }, [onInvoked]);
67
- return (jsx_runtime_1.jsx("div", { style: exports.timelineLayerIconContainer, draggable: false, onDragStart: onDragStart, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, children: renderAction(colors_1.LIGHT_COLOR) }));
67
+ const onDoubleClick = (0, react_1.useCallback)((e) => {
68
+ e.stopPropagation();
69
+ }, []);
70
+ return (jsx_runtime_1.jsx("div", { style: exports.timelineLayerIconContainer, draggable: false, onDragStart: onDragStart, onDoubleClick: onDoubleClick, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, children: renderAction(colors_1.LIGHT_COLOR) }));
68
71
  };
69
72
  exports.TimelineLayerEye = TimelineLayerEye;
70
73
  const spacerStyle = {
@@ -185,6 +185,11 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
185
185
  }, [propStatuses, nodePath]);
186
186
  const durationCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
187
187
  ((_a = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames) === null || _a === void 0 ? void 0 : _a.status) === 'static');
188
+ const durationCanResize = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
189
+ (0, TimelineSequenceRightEdgeDragHandle_1.canResizeTimelineSequenceDuration)({
190
+ sequence: s,
191
+ status: propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.durationInFrames,
192
+ }));
188
193
  const fromCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
189
194
  ((_b = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.from) === null || _b === void 0 ? void 0 : _b.status) === 'static');
190
195
  const trimBeforeCanUpdate = Boolean((0, interactivity_enabled_1.isStudioInteractivityEnabled)() &&
@@ -446,7 +451,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
446
451
  const showRightEdgeDragHandle = (0, TimelineSequenceRightEdgeDragHandle_1.isTimelineSequenceDurationDraggable)(s) &&
447
452
  nodePath !== null &&
448
453
  validatedLocation !== null &&
449
- durationCanUpdate;
454
+ durationCanResize;
450
455
  const showLeftEdgeDragHandle = (0, TimelineSequenceRightEdgeDragHandle_1.isTimelineSequenceLeftEdgeDraggable)(s) &&
451
456
  nodePath !== null &&
452
457
  validatedLocation !== null &&
@@ -24,6 +24,7 @@ const TimelineSequenceName = ({ displayName, fallbackDisplayName, selected, cont
24
24
  alignSelf: 'stretch',
25
25
  ...(0, TimelineSelection_1.getTimelineSelectedLabelStyle)(selected, false),
26
26
  display: 'inline-flex',
27
+ flexShrink: 0,
27
28
  fontFamily: 'inherit',
28
29
  fontSize: 12,
29
30
  lineHeight: 'normal',
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatusKeyframed, OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, TSequence, InteractivitySchema } from 'remotion';
2
+ import type { CanUpdateSequencePropStatus, CanUpdateSequencePropStatusKeyframed, OverrideIdToNodePaths, PropStatuses, SequencePropsSubscriptionKey, TSequence, InteractivitySchema } from 'remotion';
3
3
  import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
4
4
  import type { MoveEffectKeyframeChange, MoveSequenceKeyframeChange } from './call-move-keyframe';
5
5
  import { type SaveSequencePropChange } from './save-sequence-prop';
@@ -42,6 +42,10 @@ type TimelineSequenceEffectKeyframeDragTarget = TimelineSequenceKeyframeDragTarg
42
42
  export declare const isTransitionSeriesSequence: (sequence: TSequence) => boolean;
43
43
  export declare const isCascadingSequence: (sequence: TSequence) => boolean;
44
44
  export declare const isTimelineSequenceDurationDraggable: (sequence: TSequence) => boolean;
45
+ export declare const canResizeTimelineSequenceDuration: ({ sequence, status, }: {
46
+ readonly sequence: TSequence;
47
+ readonly status: CanUpdateSequencePropStatus | undefined;
48
+ }) => boolean;
45
49
  export declare const isTimelineSequenceLeftEdgeDraggable: (sequence: TSequence) => boolean;
46
50
  export declare const getTimelineSequenceDurationDragValue: ({ initialDuration, deltaFrames, minimumDuration, }: {
47
51
  readonly initialDuration: number;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineSequenceRightEdgeDragHandle = exports.useTimelineSequenceFromDrag = exports.TimelineSequenceLeftEdgeDragHandle = exports.getTimelineSequenceFromDragTargets = exports.getTimelineSequenceLeftEdgeDragTargets = exports.getTimelineSequenceDurationDragTargets = exports.getTimelineSequenceFromDragKeyframeMoves = exports.getTimelineSequenceFromDragChanges = exports.getTimelineSequenceFromDragDelta = exports.getTimelineSequenceFromDragValue = exports.getTimelineSequenceDurationDragChanges = exports.getTimelineSequenceLeftEdgeDragChanges = exports.getTimelineSequenceLeftEdgeDragValues = exports.getTimelineSequenceLeftEdgeDragDelta = exports.getTimelineSequenceDurationDragValue = exports.isTimelineSequenceLeftEdgeDraggable = exports.isTimelineSequenceDurationDraggable = exports.isCascadingSequence = exports.isTransitionSeriesSequence = exports.timelineSequenceFromDragSnapThresholdPx = void 0;
3
+ exports.TimelineSequenceRightEdgeDragHandle = exports.useTimelineSequenceFromDrag = exports.TimelineSequenceLeftEdgeDragHandle = exports.getTimelineSequenceFromDragTargets = exports.getTimelineSequenceLeftEdgeDragTargets = exports.getTimelineSequenceDurationDragTargets = exports.getTimelineSequenceFromDragKeyframeMoves = exports.getTimelineSequenceFromDragChanges = exports.getTimelineSequenceFromDragDelta = exports.getTimelineSequenceFromDragValue = exports.getTimelineSequenceDurationDragChanges = exports.getTimelineSequenceLeftEdgeDragChanges = exports.getTimelineSequenceLeftEdgeDragValues = exports.getTimelineSequenceLeftEdgeDragDelta = exports.getTimelineSequenceDurationDragValue = exports.isTimelineSequenceLeftEdgeDraggable = exports.canResizeTimelineSequenceDuration = exports.isTimelineSequenceDurationDraggable = exports.isCascadingSequence = exports.isTransitionSeriesSequence = exports.timelineSequenceFromDragSnapThresholdPx = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
@@ -129,6 +129,16 @@ const isTimelineSequenceDurationDraggable = (sequence) => {
129
129
  Boolean(sequence.controls));
130
130
  };
131
131
  exports.isTimelineSequenceDurationDraggable = isTimelineSequenceDurationDraggable;
132
+ const canResizeTimelineSequenceDuration = ({ sequence, status, }) => {
133
+ if ((status === null || status === void 0 ? void 0 : status.status) !== 'static') {
134
+ return false;
135
+ }
136
+ if (sequence.type === 'audio' || sequence.type === 'video') {
137
+ return status.codeValue !== undefined;
138
+ }
139
+ return true;
140
+ };
141
+ exports.canResizeTimelineSequenceDuration = canResizeTimelineSequenceDuration;
132
142
  const isTimelineSequenceLeftEdgeDraggable = (sequence) => {
133
143
  return ((!sequence.isInsideSeries || (0, exports.isCascadingSequence)(sequence)) &&
134
144
  Boolean(sequence.controls) &&
@@ -338,6 +348,7 @@ const findSequenceTrack = ({ tracks, nodePathInfo, }) => {
338
348
  });
339
349
  };
340
350
  const getTimelineSequenceDurationDragTargets = ({ draggedNodePathInfo, selectedItems, sequences, overrideIdsToNodePaths, propStatuses, }) => {
351
+ var _a;
341
352
  const draggedSelectionKey = (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(draggedNodePathInfo);
342
353
  const selectedSequenceItems = selectedItems.filter((item) => item.type === 'sequence');
343
354
  const draggedItemIsSelected = selectedSequenceItems.some((item) => (0, TimelineSelection_1.getTimelineSequenceSelectionKey)(item.nodePathInfo) ===
@@ -363,7 +374,11 @@ const getTimelineSequenceDurationDragTargets = ({ draggedNodePathInfo, selectedI
363
374
  return null;
364
375
  }
365
376
  const nodePath = track.nodePathInfo.sequenceSubscriptionKey;
366
- if (!canUpdateDurationInFrames({ propStatuses, nodePath })) {
377
+ const durationStatus = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a.durationInFrames;
378
+ if (!(0, exports.canResizeTimelineSequenceDuration)({
379
+ sequence: originalSequence,
380
+ status: durationStatus,
381
+ })) {
367
382
  return null;
368
383
  }
369
384
  const { controls } = originalSequence;
@@ -543,14 +558,14 @@ const TimelineSequenceLeftEdgeDragHandle = ({ nodePathInfo, windowWidth, timelin
543
558
  };
544
559
  const finishDrag = (0, react_1.useCallback)((commit) => {
545
560
  const dragState = dragStateRef.current;
561
+ if (!dragState) {
562
+ return;
563
+ }
546
564
  dragStateRef.current = null;
547
565
  document.body.style.userSelect = '';
548
566
  document.body.style.webkitUserSelect = '';
549
567
  (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
550
568
  setDragging(false);
551
- if (!dragState) {
552
- return;
553
- }
554
569
  const { setPropStatuses: latestSetPropStatuses, clearDragOverrides: latestClear, previewServerState: latestServerState, } = latestRef.current;
555
570
  const changes = (0, exports.getTimelineSequenceLeftEdgeDragChanges)({
556
571
  targets: dragState.targets,
@@ -685,6 +700,7 @@ const TimelineSequenceLeftEdgeDragHandle = ({ nodePathInfo, windowWidth, timelin
685
700
  window.removeEventListener('pointerup', onUp);
686
701
  window.removeEventListener('pointercancel', onCancel);
687
702
  window.removeEventListener('blur', onWindowBlur);
703
+ finishDrag(false);
688
704
  };
689
705
  }, [dragging, finishDrag]);
690
706
  const style = {
@@ -729,13 +745,13 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
729
745
  };
730
746
  const finishDrag = (0, react_1.useCallback)((commit) => {
731
747
  const dragState = dragStateRef.current;
748
+ if (!dragState) {
749
+ return;
750
+ }
732
751
  dragStateRef.current = null;
733
752
  document.body.style.userSelect = '';
734
753
  document.body.style.webkitUserSelect = '';
735
754
  setDragging(false);
736
- if (!dragState) {
737
- return;
738
- }
739
755
  const { setPropStatuses: latestSetPropStatuses, clearDragOverrides: latestClear, clearEffectDragOverrides: latestClearEffect, previewServerState: latestServerState, } = latestRef.current;
740
756
  const changes = (0, exports.getTimelineSequenceFromDragChanges)({
741
757
  targets: dragState.targets,
@@ -897,6 +913,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
897
913
  window.removeEventListener('pointerup', onUp);
898
914
  window.removeEventListener('pointercancel', onCancel);
899
915
  window.removeEventListener('blur', onWindowBlur);
916
+ finishDrag(false);
900
917
  };
901
918
  }, [dragging, finishDrag]);
902
919
  return {
@@ -933,14 +950,14 @@ const TimelineSequenceRightEdgeDragHandle = ({ nodePathInfo, windowWidth, timeli
933
950
  };
934
951
  const finishDrag = (0, react_1.useCallback)((commit) => {
935
952
  const dragState = dragStateRef.current;
953
+ if (!dragState) {
954
+ return;
955
+ }
936
956
  dragStateRef.current = null;
937
957
  document.body.style.userSelect = '';
938
958
  document.body.style.webkitUserSelect = '';
939
959
  (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
940
960
  setDragging(false);
941
- if (!dragState) {
942
- return;
943
- }
944
961
  const { setPropStatuses: latestSetPropStatuses, clearDragOverrides: latestClear, previewServerState: latestServerState, } = latestRef.current;
945
962
  const changes = (0, exports.getTimelineSequenceDurationDragChanges)({
946
963
  targets: dragState.targets,
@@ -1069,6 +1086,7 @@ const TimelineSequenceRightEdgeDragHandle = ({ nodePathInfo, windowWidth, timeli
1069
1086
  window.removeEventListener('pointerup', onUp);
1070
1087
  window.removeEventListener('pointercancel', onCancel);
1071
1088
  window.removeEventListener('blur', onWindowBlur);
1089
+ finishDrag(false);
1072
1090
  };
1073
1091
  }, [dragging, finishDrag]);
1074
1092
  const style = {
@@ -366,10 +366,12 @@ const useTimelineKeyframeDrag = ({ frame, nodePathInfo, onSelect, selectable, se
366
366
  clearDraggedKeyframes();
367
367
  return;
368
368
  }
369
- setDraggedKeyframes(targets.map((target) => ({
370
- nodePathInfo: target.nodePathInfo,
371
- frame: target.displayFrame + delta,
372
- })));
369
+ setDraggedKeyframes(shouldDragExistingSelection
370
+ ? targets.map((target) => ({
371
+ nodePathInfo: target.nodePathInfo,
372
+ frame: target.displayFrame + delta,
373
+ }))
374
+ : []);
373
375
  applyDragOverrides({
374
376
  delta,
375
377
  setDragOverrides,