@remotion/studio 4.0.471 → 4.0.472

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 (91) hide show
  1. package/dist/components/AssetSelector.js +10 -1
  2. package/dist/components/Canvas.js +98 -0
  3. package/dist/components/CompositionSelectorItem.d.ts +1 -0
  4. package/dist/components/CompositionSelectorItem.js +12 -4
  5. package/dist/components/ContextMenu.js +54 -46
  6. package/dist/components/Editor.js +14 -6
  7. package/dist/components/Modals.js +3 -1
  8. package/dist/components/NewComposition/CodemodFooter.js +2 -2
  9. package/dist/components/NewComposition/DeleteFolder.d.ts +6 -0
  10. package/dist/components/NewComposition/DeleteFolder.js +39 -0
  11. package/dist/components/NewComposition/RenameFolder.d.ts +6 -0
  12. package/dist/components/NewComposition/RenameFolder.js +60 -0
  13. package/dist/components/SelectedOutlineOverlay.d.ts +81 -4
  14. package/dist/components/SelectedOutlineOverlay.js +405 -54
  15. package/dist/components/Splitter/SplitterContainer.js +9 -0
  16. package/dist/components/Splitter/SplitterHandle.js +63 -70
  17. package/dist/components/Timeline/Timeline.js +47 -2
  18. package/dist/components/Timeline/TimelineArrayField.d.ts +9 -0
  19. package/dist/components/Timeline/TimelineArrayField.js +210 -0
  20. package/dist/components/Timeline/TimelineBooleanField.d.ts +2 -2
  21. package/dist/components/Timeline/TimelineBooleanField.js +2 -2
  22. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +20 -0
  23. package/dist/components/Timeline/TimelineClipboardKeybindings.js +265 -0
  24. package/dist/components/Timeline/TimelineColorField.d.ts +2 -2
  25. package/dist/components/Timeline/TimelineColorField.js +2 -8
  26. package/dist/components/Timeline/TimelineEffectItem.js +2 -2
  27. package/dist/components/Timeline/TimelineEffectPropItem.js +95 -25
  28. package/dist/components/Timeline/TimelineEnumField.d.ts +2 -2
  29. package/dist/components/Timeline/TimelineEnumField.js +3 -3
  30. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +4 -3
  31. package/dist/components/Timeline/TimelineKeyframeControls.js +37 -23
  32. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +7 -2
  33. package/dist/components/Timeline/TimelineKeyframedValue.js +22 -8
  34. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -0
  35. package/dist/components/Timeline/TimelineLayerEye.js +8 -3
  36. package/dist/components/Timeline/TimelineNumberField.d.ts +2 -2
  37. package/dist/components/Timeline/TimelineNumberField.js +7 -11
  38. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +17 -0
  39. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +53 -0
  40. package/dist/components/Timeline/TimelineRotationField.d.ts +2 -2
  41. package/dist/components/Timeline/TimelineRotationField.js +41 -24
  42. package/dist/components/Timeline/TimelineRowChrome.js +8 -7
  43. package/dist/components/Timeline/TimelineScaleField.d.ts +20 -0
  44. package/dist/components/Timeline/TimelineScaleField.js +314 -0
  45. package/dist/components/Timeline/TimelineSchemaField.d.ts +3 -2
  46. package/dist/components/Timeline/TimelineSchemaField.js +8 -42
  47. package/dist/components/Timeline/TimelineSelection.js +3 -2
  48. package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
  49. package/dist/components/Timeline/TimelineSequence.js +51 -10
  50. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  51. package/dist/components/Timeline/TimelineSequenceItem.js +7 -7
  52. package/dist/components/Timeline/TimelineSequencePropItem.js +82 -21
  53. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +58 -0
  54. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +528 -0
  55. package/dist/components/Timeline/TimelineTrack.js +1 -1
  56. package/dist/components/Timeline/TimelineTranslateField.d.ts +2 -2
  57. package/dist/components/Timeline/TimelineTranslateField.js +21 -25
  58. package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +2 -2
  59. package/dist/components/Timeline/TimelineUvCoordinateField.js +20 -26
  60. package/dist/components/Timeline/call-add-keyframe.js +2 -0
  61. package/dist/components/Timeline/get-node-keyframes.d.ts +5 -2
  62. package/dist/components/Timeline/get-node-keyframes.js +38 -5
  63. package/dist/components/Timeline/get-timeline-keyframes.js +4 -4
  64. package/dist/components/Timeline/reset-selected-timeline-props.js +19 -6
  65. package/dist/components/Timeline/timeline-field-utils.d.ts +1 -0
  66. package/dist/components/Timeline/timeline-field-utils.js +5 -1
  67. package/dist/components/Timeline/timeline-translate-utils.js +6 -2
  68. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -0
  69. package/dist/components/TopPanel.d.ts +1 -1
  70. package/dist/components/folder-menu-items.d.ts +12 -0
  71. package/dist/components/folder-menu-items.js +147 -0
  72. package/dist/components/import-assets.d.ts +6 -0
  73. package/dist/components/import-assets.js +157 -0
  74. package/dist/esm/{chunk-z0z9d4r0.js → chunk-48grt472.js} +8936 -5886
  75. package/dist/esm/internals.mjs +8936 -5886
  76. package/dist/esm/previewEntry.mjs +8748 -5698
  77. package/dist/esm/renderEntry.mjs +1 -1
  78. package/dist/helpers/calculate-timeline.js +7 -3
  79. package/dist/helpers/create-folder-tree.js +1 -0
  80. package/dist/helpers/detect-file-type.d.ts +69 -0
  81. package/dist/helpers/detect-file-type.js +278 -0
  82. package/dist/helpers/get-folder-id.d.ts +4 -0
  83. package/dist/helpers/get-folder-id.js +7 -0
  84. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +2 -0
  85. package/dist/helpers/timeline-layout.js +5 -1
  86. package/dist/helpers/validate-folder-rename.d.ts +6 -0
  87. package/dist/helpers/validate-folder-rename.js +19 -0
  88. package/dist/state/modals.d.ts +10 -0
  89. package/dist/state/scale-lock.d.ts +18 -0
  90. package/dist/state/scale-lock.js +59 -0
  91. package/package.json +10 -10
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineKeyframeControls = exports.shouldShowTimelineKeyframeControls = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const studio_shared_1 = require("@remotion/studio-shared");
5
6
  const react_1 = require("react");
6
7
  const remotion_1 = require("remotion");
7
8
  const client_id_1 = require("../../helpers/client-id");
@@ -26,17 +27,21 @@ const navButtonStyle = {
26
27
  cursor: 'pointer',
27
28
  display: 'flex',
28
29
  flexShrink: 0,
29
- height: 12,
30
+ height: 14,
30
31
  justifyContent: 'center',
31
32
  lineHeight: 1,
32
33
  outline: 'none',
33
34
  padding: 0,
34
35
  userSelect: 'none',
35
- width: 12,
36
+ width: 14,
37
+ };
38
+ const isKeyframedStatus = (status) => {
39
+ return status.status === 'keyframed';
36
40
  };
37
41
  const diamondButtonStyle = {
38
42
  ...navButtonStyle,
39
43
  background: 'none',
44
+ translate: '0 -0.5px',
40
45
  };
41
46
  const diamondIconStyle = {
42
47
  borderRadius: 1,
@@ -47,32 +52,37 @@ const diamondIconStyle = {
47
52
  };
48
53
  const svgStyle = { display: 'block' };
49
54
  const getCurrentKeyframeValue = ({ propStatus, jsxFrame, defaultValue, dragOverrideValue, }) => {
50
- if (propStatus.canUpdate) {
55
+ if (isKeyframedStatus(propStatus)) {
51
56
  return remotion_1.Internals.getEffectiveVisualModeValue({
52
57
  codeValue: propStatus,
53
58
  dragOverrideValue,
59
+ frame: jsxFrame,
54
60
  defaultValue,
55
61
  shouldResortToDefaultValueIfUndefined: true,
56
62
  });
57
63
  }
58
- if (propStatus.reason === 'keyframed') {
59
- return remotion_1.Internals.interpolateKeyframedStatus({
64
+ if (propStatus.status === 'static') {
65
+ return remotion_1.Internals.getEffectiveVisualModeValue({
66
+ codeValue: propStatus,
67
+ dragOverrideValue,
60
68
  frame: jsxFrame,
61
- status: propStatus,
69
+ defaultValue,
70
+ shouldResortToDefaultValueIfUndefined: true,
62
71
  });
63
72
  }
64
73
  return null;
65
74
  };
66
- const shouldShowTimelineKeyframeControls = ({ propStatus, selected, }) => {
75
+ const shouldShowTimelineKeyframeControls = ({ propStatus, selected, keyframable, }) => {
67
76
  if (propStatus === null) {
68
77
  return false;
69
78
  }
79
+ if (!keyframable && !isKeyframedStatus(propStatus)) {
80
+ return false;
81
+ }
70
82
  if (selected) {
71
83
  return true;
72
84
  }
73
- return (TimelineSelection_1.SELECTION_ENABLED &&
74
- !propStatus.canUpdate &&
75
- propStatus.reason === 'keyframed');
85
+ return TimelineSelection_1.SELECTION_ENABLED && isKeyframedStatus(propStatus);
76
86
  };
77
87
  exports.shouldShowTimelineKeyframeControls = shouldShowTimelineKeyframeControls;
78
88
  const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, keyframeDisplayOffset, defaultValue, dragOverrideValue, schema, effectIndex, }) => {
@@ -87,14 +97,26 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
87
97
  const jsxFrame = timelinePosition - keyframeDisplayOffset;
88
98
  const keyframes = (0, react_1.useMemo)(() => (0, get_timeline_keyframes_1.getTimelineKeyframes)(propStatus, keyframeDisplayOffset), [propStatus, keyframeDisplayOffset]);
89
99
  const hasKeyframeAtCurrentFrame = (0, react_1.useMemo)(() => {
90
- if (propStatus.canUpdate || propStatus.reason === 'computed') {
100
+ if (!isKeyframedStatus(propStatus)) {
91
101
  return false;
92
102
  }
93
103
  return (0, get_keyframe_navigation_1.hasKeyframeAtSourceFrame)(propStatus.keyframes, jsxFrame);
94
104
  }, [jsxFrame, propStatus]);
105
+ const currentKeyframeValue = (0, react_1.useMemo)(() => getCurrentKeyframeValue({
106
+ propStatus,
107
+ jsxFrame,
108
+ defaultValue,
109
+ dragOverrideValue,
110
+ }), [defaultValue, dragOverrideValue, jsxFrame, propStatus]);
95
111
  const previousDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getPreviousKeyframeDisplayFrame)(keyframes, timelinePosition), [keyframes, timelinePosition]);
96
112
  const nextDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getNextKeyframeDisplayFrame)(keyframes, timelinePosition), [keyframes, timelinePosition]);
97
- const canToggleKeyframe = propStatus.canUpdate || propStatus.reason === 'keyframed';
113
+ const keyframable = (0, studio_shared_1.isSchemaFieldKeyframable)({
114
+ schema,
115
+ key: fieldKey,
116
+ });
117
+ const canAddKeyframe = keyframable;
118
+ const canToggleKeyframe = propStatus.status !== 'computed' &&
119
+ (hasKeyframeAtCurrentFrame || canAddKeyframe);
98
120
  const seekToDisplayFrame = (0, react_1.useCallback)((frame) => {
99
121
  setFrame((current) => {
100
122
  const next = { ...current, [videoConfig.id]: frame };
@@ -119,9 +141,7 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
119
141
  if (!clientId || !canToggleKeyframe) {
120
142
  return;
121
143
  }
122
- if (hasKeyframeAtCurrentFrame &&
123
- !propStatus.canUpdate &&
124
- propStatus.reason === 'keyframed') {
144
+ if (hasKeyframeAtCurrentFrame && isKeyframedStatus(propStatus)) {
125
145
  if (effectIndex === null) {
126
146
  await (0, call_delete_keyframe_1.callDeleteSequenceKeyframe)({
127
147
  fileName,
@@ -146,12 +166,7 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
146
166
  });
147
167
  return;
148
168
  }
149
- const value = getCurrentKeyframeValue({
150
- propStatus,
151
- jsxFrame,
152
- defaultValue,
153
- dragOverrideValue,
154
- });
169
+ const value = currentKeyframeValue;
155
170
  if (value === null) {
156
171
  return;
157
172
  }
@@ -182,12 +197,11 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
182
197
  }, [
183
198
  canToggleKeyframe,
184
199
  clientId,
185
- defaultValue,
186
- dragOverrideValue,
187
200
  effectIndex,
188
201
  fieldKey,
189
202
  fileName,
190
203
  hasKeyframeAtCurrentFrame,
204
+ currentKeyframeValue,
191
205
  jsxFrame,
192
206
  nodePath,
193
207
  propStatus,
@@ -1,8 +1,13 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatusKeyframed } from 'remotion';
3
- import type { SchemaFieldInfo } from '../../helpers/timeline-layout';
2
+ import type { CanUpdateSequencePropStatusKeyframed, DragOverrideValue, SequencePropsSubscriptionKey } from 'remotion';
3
+ import type { SchemaFieldInfo, TimelineFieldOnDragValueChange } from '../../helpers/timeline-layout';
4
4
  export declare const TimelineKeyframedValue: React.FC<{
5
5
  readonly field: SchemaFieldInfo;
6
6
  readonly propStatus: CanUpdateSequencePropStatusKeyframed;
7
7
  readonly keyframeDisplayOffset: number;
8
+ readonly dragOverrideValue: DragOverrideValue | undefined;
9
+ readonly onSave: (value: unknown, sourceFrame: number) => Promise<void>;
10
+ readonly onDragValueChange: TimelineFieldOnDragValueChange;
11
+ readonly onDragEnd: () => void;
12
+ readonly scaleLockNodePath: SequencePropsSubscriptionKey;
8
13
  }>;
@@ -5,13 +5,10 @@ const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
8
- const wrapperStyle = {
9
- opacity: 0.5,
10
- pointerEvents: 'none',
8
+ const valuesEqual = (left, right) => {
9
+ return JSON.stringify(left) === JSON.stringify(right);
11
10
  };
12
- const noop = () => undefined;
13
- const noopAsync = () => Promise.resolve();
14
- const TimelineKeyframedValue = ({ field, propStatus, keyframeDisplayOffset }) => {
11
+ const TimelineKeyframedValue = ({ field, propStatus, keyframeDisplayOffset, dragOverrideValue, onSave, onDragValueChange, onDragEnd, scaleLockNodePath, }) => {
15
12
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
16
13
  const jsxFrame = timelinePosition - keyframeDisplayOffset;
17
14
  const computedValue = (0, react_1.useMemo)(() => {
@@ -25,12 +22,29 @@ const TimelineKeyframedValue = ({ field, propStatus, keyframeDisplayOffset }) =>
25
22
  return raw;
26
23
  }, [jsxFrame, propStatus]);
27
24
  const fakeStatus = (0, react_1.useMemo)(() => ({
28
- canUpdate: true,
25
+ status: 'static',
29
26
  codeValue: computedValue,
30
27
  }), [computedValue]);
28
+ const effectiveValue = (0, react_1.useMemo)(() => {
29
+ return remotion_1.Internals.getEffectiveVisualModeValue({
30
+ codeValue: fakeStatus,
31
+ dragOverrideValue,
32
+ frame: jsxFrame,
33
+ defaultValue: field.fieldSchema.default,
34
+ shouldResortToDefaultValueIfUndefined: true,
35
+ });
36
+ }, [dragOverrideValue, fakeStatus, field.fieldSchema.default, jsxFrame]);
37
+ const onSaveIfChanged = (0, react_1.useCallback)((value) => {
38
+ const existingKeyframe = propStatus.keyframes.find((keyframe) => keyframe.frame === jsxFrame);
39
+ if (valuesEqual(value, computedValue) ||
40
+ (existingKeyframe && valuesEqual(value, existingKeyframe.value))) {
41
+ return Promise.resolve();
42
+ }
43
+ return onSave(value, jsxFrame);
44
+ }, [computedValue, jsxFrame, onSave, propStatus.keyframes]);
31
45
  if (computedValue === null) {
32
46
  return null;
33
47
  }
34
- return (jsx_runtime_1.jsx("div", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: fakeStatus, effectiveValue: computedValue, onSave: noopAsync, onDragValueChange: noop, onDragEnd: noop }) }));
48
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: fakeStatus, effectiveValue: effectiveValue, onSave: onSaveIfChanged, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, scaleLockNodePath: scaleLockNodePath }));
35
49
  };
36
50
  exports.TimelineKeyframedValue = TimelineKeyframedValue;
@@ -1,4 +1,5 @@
1
1
  import React from 'react';
2
+ export declare const timelineLayerIconContainer: React.CSSProperties;
2
3
  export declare const TimelineLayerEye: React.FC<{
3
4
  readonly onInvoked: (type: 'enable' | 'disable') => void;
4
5
  readonly hidden: boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TimelineLayerEyeSpacer = exports.TimelineLayerEye = void 0;
3
+ exports.TimelineLayerEyeSpacer = exports.TimelineLayerEye = exports.timelineLayerIconContainer = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const colors_1 = require("../../helpers/colors");
@@ -18,7 +18,7 @@ const speakerIcon = {
18
18
  height: 10,
19
19
  marginLeft: -1,
20
20
  };
21
- const container = {
21
+ exports.timelineLayerIconContainer = {
22
22
  height: 16,
23
23
  width: 16,
24
24
  borderRadius: 2,
@@ -47,6 +47,7 @@ const TimelineLayerEye = ({ onInvoked, hidden, type }) => {
47
47
  if (e.button !== 0) {
48
48
  return;
49
49
  }
50
+ e.preventDefault();
50
51
  e.stopPropagation();
51
52
  layerPointedDown = hidden ? 'enable' : 'disable';
52
53
  onInvoked(layerPointedDown);
@@ -54,12 +55,16 @@ const TimelineLayerEye = ({ onInvoked, hidden, type }) => {
54
55
  layerPointedDown = null;
55
56
  }, { once: true });
56
57
  }, [hidden, onInvoked]);
58
+ const onDragStart = (0, react_1.useCallback)((e) => {
59
+ e.preventDefault();
60
+ e.stopPropagation();
61
+ }, []);
57
62
  const onPointerEnter = (0, react_1.useCallback)(() => {
58
63
  if (layerPointedDown) {
59
64
  onInvoked(layerPointedDown);
60
65
  }
61
66
  }, [onInvoked]);
62
- return (jsx_runtime_1.jsx("div", { style: container, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, children: renderAction(colors_1.LIGHT_COLOR) }));
67
+ return (jsx_runtime_1.jsx("div", { style: exports.timelineLayerIconContainer, draggable: false, onDragStart: onDragStart, onPointerEnter: onPointerEnter, onPointerDown: onPointerDown, children: renderAction(colors_1.LIGHT_COLOR) }));
63
68
  };
64
69
  exports.TimelineLayerEye = TimelineLayerEye;
65
70
  const spacerStyle = {
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatus } from 'remotion';
2
+ import type { CanUpdateSequencePropStatusStatic } from 'remotion';
3
3
  import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
4
  export declare const TimelineNumberField: React.FC<{
5
5
  readonly field: SchemaFieldInfo;
6
6
  readonly effectiveValue: unknown;
7
- readonly propStatus: CanUpdateSequencePropStatus;
7
+ readonly propStatus: CanUpdateSequencePropStatusStatic;
8
8
  readonly onSave: TimelineFieldOnSave;
9
9
  readonly onDragValueChange: TimelineFieldOnDragValueChange;
10
10
  readonly onDragEnd: () => void;
@@ -13,7 +13,7 @@ const TimelineNumberField = ({ field, effectiveValue, onSave, onDragValueChange,
13
13
  onDragValueChange(newVal);
14
14
  }, [onDragValueChange]);
15
15
  const onValueChangeEnd = (0, react_1.useCallback)((newVal) => {
16
- if (propStatus.canUpdate && newVal !== propStatus.codeValue) {
16
+ if (newVal !== propStatus.codeValue) {
17
17
  onSave(newVal).finally(() => {
18
18
  setDragValue(null);
19
19
  onDragEnd();
@@ -25,16 +25,12 @@ const TimelineNumberField = ({ field, effectiveValue, onSave, onDragValueChange,
25
25
  }
26
26
  }, [onSave, propStatus, onDragEnd]);
27
27
  const onTextChange = (0, react_1.useCallback)((newVal) => {
28
- if (propStatus.canUpdate) {
29
- const parsed = Number(newVal);
30
- if (!Number.isNaN(parsed) &&
31
- propStatus.canUpdate &&
32
- parsed !== propStatus.codeValue) {
33
- setDragValue(parsed);
34
- onSave(parsed).finally(() => {
35
- setDragValue(null);
36
- });
37
- }
28
+ const parsed = Number(newVal);
29
+ if (!Number.isNaN(parsed) && parsed !== propStatus.codeValue) {
30
+ setDragValue(parsed);
31
+ onSave(parsed).finally(() => {
32
+ setDragValue(null);
33
+ });
38
34
  }
39
35
  }, [onSave, propStatus]);
40
36
  const step = field.fieldSchema.type === 'number' ? ((_a = field.fieldSchema.step) !== null && _a !== void 0 ? _a : 1) : 1;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import type { ArrayFieldSchema, CanUpdateSequencePropStatusStatic, SequencePropsSubscriptionKey, VisibleFieldSchema } from 'remotion';
3
+ import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
+ export type TimelinePrimitiveFieldInfo = Omit<SchemaFieldInfo, 'fieldSchema' | 'typeName'> & {
5
+ readonly fieldSchema: Exclude<VisibleFieldSchema, ArrayFieldSchema>;
6
+ readonly typeName: Exclude<VisibleFieldSchema['type'], 'array'>;
7
+ };
8
+ export declare const isTimelinePrimitiveFieldInfo: (field: SchemaFieldInfo) => field is TimelinePrimitiveFieldInfo;
9
+ export declare const TimelinePrimitiveFieldValue: React.FC<{
10
+ readonly field: TimelinePrimitiveFieldInfo;
11
+ readonly onSave: TimelineFieldOnSave;
12
+ readonly onDragValueChange: TimelineFieldOnDragValueChange;
13
+ readonly onDragEnd: () => void;
14
+ readonly propStatus: CanUpdateSequencePropStatusStatic;
15
+ readonly effectiveValue: unknown;
16
+ readonly scaleLockNodePath: SequencePropsSubscriptionKey | null;
17
+ }>;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelinePrimitiveFieldValue = exports.isTimelinePrimitiveFieldInfo = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const TimelineBooleanField_1 = require("./TimelineBooleanField");
6
+ const TimelineColorField_1 = require("./TimelineColorField");
7
+ const TimelineEnumField_1 = require("./TimelineEnumField");
8
+ const TimelineNumberField_1 = require("./TimelineNumberField");
9
+ const TimelineRotationField_1 = require("./TimelineRotationField");
10
+ const TimelineScaleField_1 = require("./TimelineScaleField");
11
+ const TimelineTranslateField_1 = require("./TimelineTranslateField");
12
+ const TimelineUvCoordinateField_1 = require("./TimelineUvCoordinateField");
13
+ const inlineWrapper = {
14
+ fontSize: 12,
15
+ };
16
+ const isTimelinePrimitiveFieldInfo = (field) => {
17
+ return (field.typeName !== 'array' &&
18
+ field.typeName !== 'hidden' &&
19
+ field.fieldSchema.type !== 'array');
20
+ };
21
+ exports.isTimelinePrimitiveFieldInfo = isTimelinePrimitiveFieldInfo;
22
+ const TimelinePrimitiveFieldValue = ({ field, onSave, onDragValueChange, onDragEnd, propStatus, effectiveValue, scaleLockNodePath, }) => {
23
+ if (field.typeName === 'number') {
24
+ return (jsx_runtime_1.jsx("span", { children: jsx_runtime_1.jsx(TimelineNumberField_1.TimelineNumberField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
25
+ }
26
+ if (field.typeName === 'rotation-css' ||
27
+ field.typeName === 'rotation-degrees') {
28
+ return (jsx_runtime_1.jsx("span", { children: jsx_runtime_1.jsx(TimelineRotationField_1.TimelineRotationField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
29
+ }
30
+ if (field.typeName === 'translate') {
31
+ return (jsx_runtime_1.jsx("span", { children: jsx_runtime_1.jsx(TimelineTranslateField_1.TimelineTranslateField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
32
+ }
33
+ if (field.typeName === 'scale') {
34
+ if (scaleLockNodePath === null) {
35
+ throw new Error('Expected scale lock node path for scale field');
36
+ }
37
+ return (jsx_runtime_1.jsx("span", { children: jsx_runtime_1.jsx(TimelineScaleField_1.TimelineScaleField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus, scaleLockNodePath: scaleLockNodePath }) }));
38
+ }
39
+ if (field.typeName === 'uv-coordinate') {
40
+ return (jsx_runtime_1.jsx("span", { children: jsx_runtime_1.jsx(TimelineUvCoordinateField_1.TimelineUvCoordinateField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
41
+ }
42
+ if (field.typeName === 'boolean') {
43
+ return (jsx_runtime_1.jsx("span", { children: jsx_runtime_1.jsx(TimelineBooleanField_1.TimelineBooleanField, { effectiveValue: effectiveValue, field: field, onSave: onSave, propStatus: propStatus }) }));
44
+ }
45
+ if (field.typeName === 'color') {
46
+ return (jsx_runtime_1.jsx("span", { children: jsx_runtime_1.jsx(TimelineColorField_1.TimelineColorField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
47
+ }
48
+ if (field.typeName === 'enum') {
49
+ return (jsx_runtime_1.jsx("span", { style: inlineWrapper, children: jsx_runtime_1.jsx(TimelineEnumField_1.TimelineEnumField, { effectiveValue: effectiveValue, field: field, onDragEnd: onDragEnd, onDragValueChange: onDragValueChange, onSave: onSave, propStatus: propStatus }) }));
50
+ }
51
+ throw new Error(`Unsupported field type: ${field.typeName}`);
52
+ };
53
+ exports.TimelinePrimitiveFieldValue = TimelinePrimitiveFieldValue;
@@ -1,10 +1,10 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatus } from 'remotion';
2
+ import type { CanUpdateSequencePropStatusStatic } from 'remotion';
3
3
  import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
4
  export declare const TimelineRotationField: React.FC<{
5
5
  readonly field: SchemaFieldInfo;
6
6
  readonly effectiveValue: unknown;
7
- readonly propStatus: CanUpdateSequencePropStatus;
7
+ readonly propStatus: CanUpdateSequencePropStatusStatic;
8
8
  readonly onSave: TimelineFieldOnSave;
9
9
  readonly onDragValueChange: TimelineFieldOnDragValueChange;
10
10
  readonly onDragEnd: () => void;
@@ -15,28 +15,38 @@ const unitToDegrees = {
15
15
  const parseCssRotationToDegrees = (value) => {
16
16
  const match = value.trim().match(unitPattern);
17
17
  if (match) {
18
- return Number(match[1]) * unitToDegrees[match[2]];
18
+ return (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(match[1]) * unitToDegrees[match[2]]);
19
19
  }
20
20
  try {
21
21
  const m = new DOMMatrix(`rotate(${value})`);
22
- return Math.round(Math.atan2(m.b, m.a) * (180 / Math.PI) * 1e6) / 1e6;
22
+ return (0, timeline_field_utils_1.normalizeTimelineNumber)(Math.atan2(m.b, m.a) * (180 / Math.PI));
23
23
  }
24
24
  catch (_a) {
25
25
  return 0;
26
26
  }
27
27
  };
28
28
  const TimelineRotationField = ({ field, effectiveValue, propStatus, onSave, onDragValueChange, onDragEnd, }) => {
29
- var _a;
29
+ var _a, _b, _c;
30
30
  const [dragValue, setDragValue] = (0, react_1.useState)(null);
31
- const degrees = (0, react_1.useMemo)(() => parseCssRotationToDegrees(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0deg')), [effectiveValue]);
31
+ const isCssRotation = field.fieldSchema.type === 'rotation-css';
32
+ const degrees = (0, react_1.useMemo)(() => {
33
+ if (isCssRotation) {
34
+ return parseCssRotationToDegrees(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0deg'));
35
+ }
36
+ return typeof effectiveValue === 'number' ? effectiveValue : 0;
37
+ }, [effectiveValue, isCssRotation]);
38
+ const serializeValue = (0, react_1.useCallback)((value) => {
39
+ const normalized = (0, timeline_field_utils_1.normalizeTimelineNumber)(value);
40
+ return isCssRotation ? `${normalized}deg` : normalized;
41
+ }, [isCssRotation]);
32
42
  const onValueChange = (0, react_1.useCallback)((newVal) => {
33
43
  setDragValue(newVal);
34
- onDragValueChange(`${newVal}deg`);
35
- }, [onDragValueChange]);
44
+ onDragValueChange(serializeValue(newVal));
45
+ }, [onDragValueChange, serializeValue]);
36
46
  const onValueChangeEnd = (0, react_1.useCallback)((newVal) => {
37
- const newStr = `${newVal}deg`;
38
- if (propStatus.canUpdate && newStr !== propStatus.codeValue) {
39
- onSave(newStr).finally(() => {
47
+ const newValue = serializeValue(newVal);
48
+ if (newValue !== propStatus.codeValue) {
49
+ onSave(newValue).finally(() => {
40
50
  setDragValue(null);
41
51
  onDragEnd();
42
52
  });
@@ -45,29 +55,36 @@ const TimelineRotationField = ({ field, effectiveValue, propStatus, onSave, onDr
45
55
  setDragValue(null);
46
56
  onDragEnd();
47
57
  }
48
- }, [propStatus, onSave, onDragEnd]);
58
+ }, [propStatus, onSave, onDragEnd, serializeValue]);
49
59
  const onTextChange = (0, react_1.useCallback)((newVal) => {
50
- if (propStatus.canUpdate) {
51
- const parsed = Number(newVal);
52
- if (!Number.isNaN(parsed)) {
53
- const newStr = `${parsed}deg`;
54
- if (newStr !== propStatus.codeValue) {
55
- setDragValue(parsed);
56
- onSave(newStr).finally(() => {
57
- setDragValue(null);
58
- });
59
- }
60
+ const parsed = Number(newVal);
61
+ if (!Number.isNaN(parsed)) {
62
+ const newValue = serializeValue(parsed);
63
+ if (newValue !== propStatus.codeValue) {
64
+ setDragValue(parsed);
65
+ onSave(newValue).finally(() => {
66
+ setDragValue(null);
67
+ });
60
68
  }
61
69
  }
62
- }, [propStatus, onSave]);
63
- const step = field.fieldSchema.type === 'rotation' ? ((_a = field.fieldSchema.step) !== null && _a !== void 0 ? _a : 1) : 1;
70
+ }, [propStatus, onSave, serializeValue]);
71
+ const step = field.fieldSchema.type === 'rotation-css' ||
72
+ field.fieldSchema.type === 'rotation-degrees'
73
+ ? ((_a = field.fieldSchema.step) !== null && _a !== void 0 ? _a : 1)
74
+ : 1;
75
+ const min = field.fieldSchema.type === 'rotation-degrees'
76
+ ? ((_b = field.fieldSchema.min) !== null && _b !== void 0 ? _b : -Infinity)
77
+ : -Infinity;
78
+ const max = field.fieldSchema.type === 'rotation-degrees'
79
+ ? ((_c = field.fieldSchema.max) !== null && _c !== void 0 ? _c : Infinity)
80
+ : Infinity;
64
81
  const stepDecimals = (0, react_1.useMemo)(() => (0, timeline_field_utils_1.getDecimalPlaces)(step), [step]);
65
82
  const formatter = (0, react_1.useCallback)((v) => {
66
- const num = Number(v);
83
+ const num = (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(v));
67
84
  const digits = Math.max(stepDecimals, (0, timeline_field_utils_1.getDecimalPlaces)(num));
68
85
  const formatted = digits === 0 ? String(num) : num.toFixed(digits);
69
86
  return `${formatted}\u00B0`;
70
87
  }, [stepDecimals]);
71
- return (jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragValue !== null && dragValue !== void 0 ? dragValue : degrees, style: timeline_field_utils_1.draggerStyle, status: "ok", small: true, onValueChange: onValueChange, onValueChangeEnd: onValueChangeEnd, onTextChange: onTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false }));
88
+ return (jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragValue !== null && dragValue !== void 0 ? dragValue : degrees, style: timeline_field_utils_1.draggerStyle, status: "ok", small: true, onValueChange: onValueChange, onValueChangeEnd: onValueChangeEnd, onTextChange: onTextChange, min: min, max: max, step: step, formatter: formatter, rightAlign: false }));
72
89
  };
73
90
  exports.TimelineRotationField = TimelineRotationField;
@@ -17,23 +17,25 @@ const leftChromeStyle = {
17
17
  display: 'flex',
18
18
  flexShrink: 0,
19
19
  };
20
- const keyframeControlsColumnStyle = {
20
+ const keyframeControlsColumnBaseStyle = {
21
21
  alignItems: 'center',
22
22
  display: 'flex',
23
23
  flexShrink: 0,
24
24
  justifyContent: 'flex-start',
25
- marginRight: -(timeline_row_layout_1.TIMELINE_KEYFRAME_CONTROLS_WIDTH - timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING),
26
- width: timeline_row_layout_1.TIMELINE_KEYFRAME_CONTROLS_WIDTH,
27
25
  };
28
26
  const TimelineRowChrome = ({ depth, eye, keyframeControls, arrow, children, style, selected, selectable, onSelect, showSelectedBackground, containsSelection, outerHeight, onDragLeave, onDragOver, onDrop, onDoubleClick, }) => {
29
27
  const indentWidth = (0, timeline_row_layout_1.getTimelineRowIndentWidth)(depth);
28
+ const keyframeControlsColumnStyle = (0, react_1.useMemo)(() => ({
29
+ ...keyframeControlsColumnBaseStyle,
30
+ width: (0, timeline_row_layout_1.getTimelineRowLeftChromeWidth)(depth),
31
+ }), [depth]);
30
32
  const chromeColumnStyle = (0, react_1.useMemo)(() => ({
31
33
  alignItems: 'center',
32
34
  alignSelf: 'stretch',
33
35
  display: 'flex',
34
36
  flexShrink: 0,
35
- paddingLeft: keyframeControls ? 0 : timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING,
36
- }), [keyframeControls]);
37
+ paddingLeft: timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING,
38
+ }), []);
37
39
  const onPointerDown = (0, react_1.useCallback)((e) => {
38
40
  if (e.button === 0) {
39
41
  e.stopPropagation();
@@ -69,8 +71,7 @@ const TimelineRowChrome = ({ depth, eye, keyframeControls, arrow, children, styl
69
71
  };
70
72
  }, [outerHeight, highlightBackground]);
71
73
  const chrome = (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
72
- jsx_runtime_1.jsxs("div", { style: leftChromeStyle, children: [keyframeControls ? (jsx_runtime_1.jsx("div", { style: keyframeControlsColumnStyle, children: keyframeControls })) : null, jsx_runtime_1.jsxs("div", { style: chromeColumnStyle, children: [eye, indentWidth > 0 ? jsx_runtime_1.jsx(Padder_1.Padder, { depth: depth }) : null, arrow] })
73
- ] }), children] }));
74
+ jsx_runtime_1.jsx("div", { style: leftChromeStyle, children: keyframeControls ? (jsx_runtime_1.jsx("div", { style: keyframeControlsColumnStyle, children: keyframeControls })) : (jsx_runtime_1.jsxs("div", { style: chromeColumnStyle, children: [eye, indentWidth > 0 ? jsx_runtime_1.jsx(Padder_1.Padder, { depth: depth }) : null, arrow] })) }), children] }));
74
75
  if (outerStyle) {
75
76
  return (jsx_runtime_1.jsx("div", { style: outerStyle, onDragLeave: onDragLeave, onDragOver: onDragOver, onDrop: onDrop, onPointerDown: selectable ? onPointerDown : undefined, onContextMenu: selectable ? onContextMenu : undefined, onDoubleClick: onDoubleClick, children: jsx_runtime_1.jsx("div", { style: innerRowStyle, children: chrome }) }));
76
77
  }
@@ -0,0 +1,20 @@
1
+ import React from 'react';
2
+ import type { CanUpdateSequencePropStatusStatic, SequencePropsSubscriptionKey } from 'remotion';
3
+ import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
+ export declare const getLinkedScale: ({ axis, newValue, baseX, baseY, min, max, }: {
5
+ readonly axis: "x" | "y";
6
+ readonly newValue: number;
7
+ readonly baseX: number;
8
+ readonly baseY: number;
9
+ readonly min: number;
10
+ readonly max: number;
11
+ }) => [number, number];
12
+ export declare const TimelineScaleField: React.FC<{
13
+ readonly field: SchemaFieldInfo;
14
+ readonly propStatus: CanUpdateSequencePropStatusStatic;
15
+ readonly effectiveValue: unknown;
16
+ readonly onSave: TimelineFieldOnSave;
17
+ readonly onDragValueChange: TimelineFieldOnDragValueChange;
18
+ readonly onDragEnd: () => void;
19
+ readonly scaleLockNodePath: SequencePropsSubscriptionKey;
20
+ }>;