@remotion/studio 4.0.471 → 4.0.473

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 (192) hide show
  1. package/dist/api/rename-static-file.d.ts +6 -0
  2. package/dist/api/rename-static-file.js +18 -0
  3. package/dist/components/AssetSelector.js +55 -5
  4. package/dist/components/AssetSelectorItem.js +153 -27
  5. package/dist/components/Canvas.js +147 -0
  6. package/dist/components/CompositionSelectorItem.d.ts +1 -0
  7. package/dist/components/CompositionSelectorItem.js +12 -4
  8. package/dist/components/ConfirmationDialog-types.d.ts +8 -0
  9. package/dist/components/ConfirmationDialog-types.js +2 -0
  10. package/dist/components/ConfirmationDialog.d.ts +7 -0
  11. package/dist/components/ConfirmationDialog.js +103 -0
  12. package/dist/components/ContextMenu.d.ts +9 -1
  13. package/dist/components/ContextMenu.js +99 -47
  14. package/dist/components/CurrentAsset.d.ts +1 -0
  15. package/dist/components/CurrentAsset.js +13 -2
  16. package/dist/components/Editor.js +14 -6
  17. package/dist/components/EditorContent.js +15 -2
  18. package/dist/components/EditorContexts.js +2 -1
  19. package/dist/components/EditorRuler/Ruler.js +2 -0
  20. package/dist/components/ExplorerPanel.d.ts +0 -4
  21. package/dist/components/ExplorerPanel.js +8 -4
  22. package/dist/components/ExplorerPanelRef.d.ts +4 -0
  23. package/dist/components/ExplorerPanelRef.js +5 -0
  24. package/dist/components/FilePreview.d.ts +1 -1
  25. package/dist/components/InitialCompositionLoader.d.ts +0 -1
  26. package/dist/components/InitialCompositionLoader.js +5 -27
  27. package/dist/components/Menu/MenuItem.js +7 -1
  28. package/dist/components/Menu/SubMenu.js +5 -1
  29. package/dist/components/Menu/portals.js +17 -8
  30. package/dist/components/MenuToolbar.js +5 -1
  31. package/dist/components/ModalContainer.js +6 -1
  32. package/dist/components/Modals.js +8 -2
  33. package/dist/components/NewComposition/CodemodFooter.js +2 -2
  34. package/dist/components/NewComposition/ComboBox.js +8 -2
  35. package/dist/components/NewComposition/DeleteFolder.d.ts +6 -0
  36. package/dist/components/NewComposition/DeleteFolder.js +39 -0
  37. package/dist/components/NewComposition/DeleteStaticFile.d.ts +4 -0
  38. package/dist/components/NewComposition/DeleteStaticFile.js +44 -0
  39. package/dist/components/NewComposition/RenameFolder.d.ts +6 -0
  40. package/dist/components/NewComposition/RenameFolder.js +60 -0
  41. package/dist/components/NewComposition/RenameStaticFile.d.ts +4 -0
  42. package/dist/components/NewComposition/RenameStaticFile.js +118 -0
  43. package/dist/components/OptionsPanel.js +5 -1
  44. package/dist/components/OutlineToggle.d.ts +2 -0
  45. package/dist/components/OutlineToggle.js +20 -0
  46. package/dist/components/Preview.d.ts +0 -2
  47. package/dist/components/Preview.js +23 -33
  48. package/dist/components/PreviewToolbar.js +19 -6
  49. package/dist/components/RenderButton.js +8 -2
  50. package/dist/components/RenderPreview.js +2 -2
  51. package/dist/components/SelectedOutlineOverlay.d.ts +105 -4
  52. package/dist/components/SelectedOutlineOverlay.js +578 -59
  53. package/dist/components/ShowOutlinesProvider.d.ts +4 -0
  54. package/dist/components/ShowOutlinesProvider.js +24 -0
  55. package/dist/components/SizeSelector.js +3 -3
  56. package/dist/components/Splitter/SplitterContainer.js +9 -0
  57. package/dist/components/Splitter/SplitterHandle.js +65 -70
  58. package/dist/components/StaticFilePreview.js +2 -2
  59. package/dist/components/Timeline/KeyframeSettingsModal.d.ts +15 -0
  60. package/dist/components/Timeline/KeyframeSettingsModal.js +150 -0
  61. package/dist/components/Timeline/Timeline.js +50 -15
  62. package/dist/components/Timeline/TimelineArrayField.d.ts +9 -0
  63. package/dist/components/Timeline/TimelineArrayField.js +210 -0
  64. package/dist/components/Timeline/TimelineBooleanField.d.ts +2 -2
  65. package/dist/components/Timeline/TimelineBooleanField.js +2 -2
  66. package/dist/components/Timeline/TimelineClipboardKeybindings.d.ts +43 -0
  67. package/dist/components/Timeline/TimelineClipboardKeybindings.js +479 -0
  68. package/dist/components/Timeline/TimelineColorField.d.ts +2 -2
  69. package/dist/components/Timeline/TimelineColorField.js +2 -8
  70. package/dist/components/Timeline/TimelineDeleteKeybindings.js +12 -2
  71. package/dist/components/Timeline/TimelineEffectItem.js +3 -2
  72. package/dist/components/Timeline/TimelineEffectPropItem.js +146 -26
  73. package/dist/components/Timeline/TimelineEnumField.d.ts +2 -2
  74. package/dist/components/Timeline/TimelineEnumField.js +3 -3
  75. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +4 -3
  76. package/dist/components/Timeline/TimelineKeyframeControls.js +41 -37
  77. package/dist/components/Timeline/TimelineKeyframeDiamond.js +24 -21
  78. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.d.ts +6 -0
  79. package/dist/components/Timeline/TimelineKeyframeDiamondIcon.js +14 -0
  80. package/dist/components/Timeline/TimelineKeyframeDragState.d.ts +17 -0
  81. package/dist/components/Timeline/TimelineKeyframeDragState.js +39 -0
  82. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +7 -2
  83. package/dist/components/Timeline/TimelineKeyframedValue.js +22 -8
  84. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -0
  85. package/dist/components/Timeline/TimelineLayerEye.js +8 -3
  86. package/dist/components/Timeline/TimelineList.js +2 -2
  87. package/dist/components/Timeline/TimelineMediaInfo.d.ts +0 -13
  88. package/dist/components/Timeline/TimelineMediaInfo.js +8 -73
  89. package/dist/components/Timeline/TimelineNumberField.d.ts +2 -2
  90. package/dist/components/Timeline/TimelineNumberField.js +7 -11
  91. package/dist/components/Timeline/TimelinePrimitiveFieldValue.d.ts +17 -0
  92. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +53 -0
  93. package/dist/components/Timeline/TimelineRotationField.d.ts +2 -2
  94. package/dist/components/Timeline/TimelineRotationField.js +41 -24
  95. package/dist/components/Timeline/TimelineRowChrome.js +8 -7
  96. package/dist/components/Timeline/TimelineScaleField.d.ts +20 -0
  97. package/dist/components/Timeline/TimelineScaleField.js +314 -0
  98. package/dist/components/Timeline/TimelineSchemaField.d.ts +3 -2
  99. package/dist/components/Timeline/TimelineSchemaField.js +8 -42
  100. package/dist/components/Timeline/TimelineSelection.js +3 -2
  101. package/dist/components/Timeline/TimelineSequence.d.ts +1 -0
  102. package/dist/components/Timeline/TimelineSequence.js +51 -10
  103. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  104. package/dist/components/Timeline/TimelineSequenceItem.d.ts +1 -0
  105. package/dist/components/Timeline/TimelineSequenceItem.js +282 -28
  106. package/dist/components/Timeline/TimelineSequencePropItem.js +161 -35
  107. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.d.ts +58 -0
  108. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +525 -0
  109. package/dist/components/Timeline/TimelineTrack.js +1 -1
  110. package/dist/components/Timeline/TimelineTranslateField.d.ts +2 -2
  111. package/dist/components/Timeline/TimelineTranslateField.js +21 -25
  112. package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +2 -2
  113. package/dist/components/Timeline/TimelineUvCoordinateField.js +20 -26
  114. package/dist/components/Timeline/apply-effect-response-to-code-values.d.ts +5 -0
  115. package/dist/components/Timeline/apply-effect-response-to-code-values.js +19 -0
  116. package/dist/components/Timeline/call-add-keyframe.js +4 -0
  117. package/dist/components/Timeline/call-move-keyframe.d.ts +19 -0
  118. package/dist/components/Timeline/call-move-keyframe.js +71 -0
  119. package/dist/components/Timeline/call-update-keyframe-settings.d.ts +22 -0
  120. package/dist/components/Timeline/call-update-keyframe-settings.js +52 -0
  121. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +7 -4
  122. package/dist/components/Timeline/delete-selected-timeline-item.js +33 -21
  123. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +4 -2
  124. package/dist/components/Timeline/duplicate-selected-timeline-item.js +39 -34
  125. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.d.ts +8 -0
  126. package/dist/components/Timeline/get-bounded-keyframe-drag-delta.js +12 -0
  127. package/dist/components/Timeline/get-keyframe-navigation.d.ts +2 -2
  128. package/dist/components/Timeline/get-keyframe-navigation.js +14 -6
  129. package/dist/components/Timeline/get-node-keyframes.d.ts +5 -2
  130. package/dist/components/Timeline/get-node-keyframes.js +38 -5
  131. package/dist/components/Timeline/get-timeline-keyframes.js +4 -4
  132. package/dist/components/Timeline/reset-selected-timeline-props.js +22 -8
  133. package/dist/components/Timeline/save-effect-prop.d.ts +14 -3
  134. package/dist/components/Timeline/save-effect-prop.js +36 -18
  135. package/dist/components/Timeline/save-prop-queue.d.ts +2 -1
  136. package/dist/components/Timeline/save-prop-queue.js +5 -2
  137. package/dist/components/Timeline/save-sequence-prop.d.ts +2 -7
  138. package/dist/components/Timeline/save-sequence-prop.js +33 -30
  139. package/dist/components/Timeline/should-clear-selection-on-pointer-down.d.ts +3 -0
  140. package/dist/components/Timeline/should-clear-selection-on-pointer-down.js +7 -0
  141. package/dist/components/Timeline/timeline-asset-link.d.ts +13 -0
  142. package/dist/components/Timeline/timeline-asset-link.js +37 -0
  143. package/dist/components/Timeline/timeline-field-utils.d.ts +1 -0
  144. package/dist/components/Timeline/timeline-field-utils.js +5 -1
  145. package/dist/components/Timeline/timeline-translate-utils.js +9 -2
  146. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +7 -0
  147. package/dist/components/Timeline/use-timeline-keyframe-drag.d.ts +10 -0
  148. package/dist/components/Timeline/use-timeline-keyframe-drag.js +378 -0
  149. package/dist/components/TopPanel.d.ts +1 -1
  150. package/dist/components/folder-menu-items.d.ts +12 -0
  151. package/dist/components/folder-menu-items.js +147 -0
  152. package/dist/components/import-assets.d.ts +22 -0
  153. package/dist/components/import-assets.js +294 -0
  154. package/dist/components/load-canvas-content-from-url.d.ts +1 -0
  155. package/dist/components/load-canvas-content-from-url.js +9 -3
  156. package/dist/components/use-select-asset.d.ts +1 -0
  157. package/dist/components/use-select-asset.js +30 -0
  158. package/dist/error-overlay/error-origin.d.ts +3 -0
  159. package/dist/error-overlay/error-origin.js +42 -0
  160. package/dist/error-overlay/react-overlay/listen-to-runtime-errors.js +6 -2
  161. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +38 -0
  162. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +1 -1
  163. package/dist/error-overlay/remotion-overlay/log-studio-error.d.ts +3 -0
  164. package/dist/error-overlay/remotion-overlay/log-studio-error.js +27 -0
  165. package/dist/esm/{chunk-z0z9d4r0.js → chunk-q0jkt0zq.js} +23062 -17350
  166. package/dist/esm/internals.mjs +23062 -17350
  167. package/dist/esm/previewEntry.mjs +22351 -16615
  168. package/dist/esm/renderEntry.mjs +1 -1
  169. package/dist/helpers/calculate-timeline.js +7 -3
  170. package/dist/helpers/create-folder-tree.js +1 -0
  171. package/dist/helpers/get-asset-metadata.js +2 -2
  172. package/dist/helpers/get-folder-id.d.ts +4 -0
  173. package/dist/helpers/get-folder-id.js +7 -0
  174. package/dist/helpers/get-preview-file-type.d.ts +2 -0
  175. package/dist/helpers/get-preview-file-type.js +33 -0
  176. package/dist/helpers/get-timeline-sequence-sort-key.d.ts +2 -0
  177. package/dist/helpers/install-required-package.d.ts +1 -0
  178. package/dist/helpers/install-required-package.js +39 -0
  179. package/dist/helpers/remote-asset-drag.d.ts +4 -0
  180. package/dist/helpers/remote-asset-drag.js +73 -0
  181. package/dist/helpers/timeline-layout.js +5 -1
  182. package/dist/helpers/use-asset-drag-events.d.ts +5 -2
  183. package/dist/helpers/use-asset-drag-events.js +13 -2
  184. package/dist/helpers/validate-folder-rename.d.ts +6 -0
  185. package/dist/helpers/validate-folder-rename.js +19 -0
  186. package/dist/hot-middleware-client/client.js +6 -0
  187. package/dist/state/editor-outlines.d.ts +8 -0
  188. package/dist/state/editor-outlines.js +18 -0
  189. package/dist/state/modals.d.ts +29 -2
  190. package/dist/state/scale-lock.d.ts +18 -0
  191. package/dist/state/scale-lock.js +59 -0
  192. package/package.json +10 -10
@@ -6,8 +6,10 @@ const studio_shared_1 = require("@remotion/studio-shared");
6
6
  const react_1 = require("react");
7
7
  const remotion_1 = require("remotion");
8
8
  const client_id_1 = require("../../helpers/client-id");
9
+ const modals_1 = require("../../state/modals");
9
10
  const call_api_1 = require("../call-api");
10
11
  const ContextMenu_1 = require("../ContextMenu");
12
+ const call_add_keyframe_1 = require("./call-add-keyframe");
11
13
  const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
12
14
  const save_effect_prop_1 = require("./save-effect-prop");
13
15
  const save_prop_queue_1 = require("./save-prop-queue");
@@ -21,6 +23,23 @@ const TimelineRowChrome_1 = require("./TimelineRowChrome");
21
23
  const TimelineSchemaField_1 = require("./TimelineSchemaField");
22
24
  const TimelineSelection_1 = require("./TimelineSelection");
23
25
  const fieldRowBase = {};
26
+ const isKeyframedStatus = (status) => {
27
+ return status.status === 'keyframed';
28
+ };
29
+ const isResettableStatus = ({ status, defaultValue, }) => {
30
+ var _a;
31
+ if (defaultValue === undefined) {
32
+ return false;
33
+ }
34
+ if (status.status === 'keyframed') {
35
+ return true;
36
+ }
37
+ if (status.status === 'computed') {
38
+ return false;
39
+ }
40
+ const effectiveCodeValue = (_a = status.codeValue) !== null && _a !== void 0 ? _a : defaultValue;
41
+ return JSON.stringify(effectiveCodeValue) !== JSON.stringify(defaultValue);
42
+ };
24
43
  const Value = ({ field, nodePath, validatedLocation, keyframeDisplayOffset }) => {
25
44
  var _a;
26
45
  var _b;
@@ -39,9 +58,25 @@ const Value = ({ field, nodePath, validatedLocation, keyframeDisplayOffset }) =>
39
58
  const propStatus = effectStatus.type === 'can-update-effect'
40
59
  ? ((_b = (_a = effectStatus.props) === null || _a === void 0 ? void 0 : _a[field.key]) !== null && _b !== void 0 ? _b : null)
41
60
  : null;
61
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
62
+ const jsxFrame = timelinePosition - keyframeDisplayOffset;
42
63
  const onDragValueChange = (0, react_1.useCallback)((value) => {
43
- setEffectDragOverrides(nodePath, field.effectIndex, field.key, value);
44
- }, [setEffectDragOverrides, nodePath, field.effectIndex, field.key]);
64
+ const nextDragOverrideValue = propStatus !== null && isKeyframedStatus(propStatus)
65
+ ? remotion_1.Internals.makeKeyframedDragOverride({
66
+ status: propStatus,
67
+ frame: jsxFrame,
68
+ value,
69
+ })
70
+ : remotion_1.Internals.makeStaticDragOverride(value);
71
+ setEffectDragOverrides(nodePath, field.effectIndex, field.key, nextDragOverrideValue);
72
+ }, [
73
+ field.effectIndex,
74
+ field.key,
75
+ jsxFrame,
76
+ nodePath,
77
+ propStatus,
78
+ setEffectDragOverrides,
79
+ ]);
45
80
  const onDragEnd = (0, react_1.useCallback)(() => {
46
81
  clearEffectDragOverrides(nodePath, field.effectIndex);
47
82
  }, [clearEffectDragOverrides, nodePath, field.effectIndex]);
@@ -56,7 +91,7 @@ const Value = ({ field, nodePath, validatedLocation, keyframeDisplayOffset }) =>
56
91
  if (!propStatus) {
57
92
  return Promise.reject(new Error('Cannot save'));
58
93
  }
59
- if (!propStatus.canUpdate) {
94
+ if (propStatus.status !== 'static') {
60
95
  return Promise.reject(new Error('Cannot save'));
61
96
  }
62
97
  if (!clientId) {
@@ -84,6 +119,7 @@ const Value = ({ field, nodePath, validatedLocation, keyframeDisplayOffset }) =>
84
119
  schema: field.effectSchema,
85
120
  }),
86
121
  apiCall: () => (0, call_api_1.callApi)('/api/save-effect-props', {
122
+ type: 'value',
87
123
  fileName: validatedLocation.source,
88
124
  sequenceNodePath: nodePath,
89
125
  effectIndex: field.effectIndex,
@@ -106,6 +142,36 @@ const Value = ({ field, nodePath, validatedLocation, keyframeDisplayOffset }) =>
106
142
  setCodeValues,
107
143
  validatedLocation,
108
144
  ]);
145
+ const onSaveKeyframed = (0, react_1.useCallback)((value, sourceFrame) => {
146
+ if (!validatedLocation) {
147
+ return Promise.reject(new Error('Cannot save'));
148
+ }
149
+ if (!clientId) {
150
+ return Promise.reject(new Error('Not connected to studio server'));
151
+ }
152
+ return (0, call_add_keyframe_1.callAddEffectKeyframe)({
153
+ fileName: validatedLocation.source,
154
+ nodePath,
155
+ effectIndex: field.effectIndex,
156
+ fieldKey: field.key,
157
+ sourceFrame,
158
+ value,
159
+ schema: field.effectSchema,
160
+ setCodeValues,
161
+ clientId,
162
+ });
163
+ }, [
164
+ clientId,
165
+ field.effectIndex,
166
+ field.effectSchema,
167
+ field.key,
168
+ nodePath,
169
+ setCodeValues,
170
+ validatedLocation,
171
+ ]);
172
+ if (field.fieldSchema.type === 'scale') {
173
+ throw new Error(`Effects do not support scale fields: ${field.key}`);
174
+ }
109
175
  if (effectStatus.type === 'cannot-update-effect') {
110
176
  if (effectStatus.reason === 'computed') {
111
177
  return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "computed" });
@@ -127,27 +193,29 @@ const Value = ({ field, nodePath, validatedLocation, keyframeDisplayOffset }) =>
127
193
  }
128
194
  throw new Error(`Unsupported effect status: ${effectStatus.reason}`);
129
195
  }
130
- if (propStatus === null || !propStatus.canUpdate) {
131
- if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.reason) === 'keyframed') {
132
- return (jsx_runtime_1.jsx(TimelineKeyframedValue_1.TimelineKeyframedValue, { field: field, propStatus: propStatus, keyframeDisplayOffset: keyframeDisplayOffset }));
133
- }
134
- if ((propStatus === null || propStatus === void 0 ? void 0 : propStatus.reason) === 'computed') {
135
- return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: (0, get_timeline_keyframes_1.getComputedStatusLabel)(propStatus) });
136
- }
196
+ if (propStatus === null) {
137
197
  return null;
138
198
  }
199
+ if (isKeyframedStatus(propStatus)) {
200
+ return (jsx_runtime_1.jsx(TimelineKeyframedValue_1.TimelineKeyframedValue, { field: field, propStatus: propStatus, keyframeDisplayOffset: keyframeDisplayOffset, dragOverrideValue: dragOverrideValue, onSave: onSaveKeyframed, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, scaleLockNodePath: nodePath }));
201
+ }
202
+ if (propStatus.status === 'computed') {
203
+ return jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: (0, get_timeline_keyframes_1.getComputedStatusLabel)(propStatus) });
204
+ }
139
205
  const effectiveValue = remotion_1.Internals.getEffectiveVisualModeValue({
140
206
  codeValue: propStatus,
141
207
  dragOverrideValue,
142
208
  defaultValue: field.fieldSchema.default,
209
+ frame: jsxFrame,
143
210
  shouldResortToDefaultValueIfUndefined: true,
144
211
  });
145
- return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: propStatus, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue }));
212
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: propStatus, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd, effectiveValue: effectiveValue, scaleLockNodePath: null }));
146
213
  };
147
214
  const TimelineEffectPropItem = ({ field, validatedLocation, rowDepth, nodePath, nodePathInfo, keyframeDisplayOffset, }) => {
148
215
  var _a;
149
216
  var _b, _c;
150
217
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
218
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
151
219
  const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
152
220
  const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
153
221
  const { getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
@@ -174,29 +242,35 @@ const TimelineEffectPropItem = ({ field, validatedLocation, rowDepth, nodePath,
174
242
  (0, TimelineKeyframeControls_1.shouldShowTimelineKeyframeControls)({
175
243
  propStatus,
176
244
  selected: selection.selected,
245
+ keyframable: (0, studio_shared_1.isSchemaFieldKeyframable)({
246
+ schema: field.effectSchema,
247
+ key: field.key,
248
+ }),
177
249
  }) ? (jsx_runtime_1.jsx(TimelineKeyframeControls_1.TimelineKeyframeControls, { fieldKey: field.key, propStatus: propStatus, nodePath: nodePath, fileName: validatedLocation.source, keyframeDisplayOffset: keyframeDisplayOffset, defaultValue: field.fieldSchema.default, dragOverrideValue: dragOverrideValue, schema: field.effectSchema, effectIndex: field.effectIndex })) : null;
178
- const isNonDefault = (0, react_1.useMemo)(() => {
179
- var _a;
180
- if (!propStatus || !propStatus.canUpdate) {
250
+ const canResetToDefault = (0, react_1.useMemo)(() => {
251
+ if (!propStatus || propStatus.status === 'computed') {
181
252
  return false;
182
253
  }
183
- const effectiveCodeValue = (_a = propStatus.codeValue) !== null && _a !== void 0 ? _a : field.fieldSchema.default;
184
- return (JSON.stringify(effectiveCodeValue) !==
185
- JSON.stringify(field.fieldSchema.default));
254
+ return isResettableStatus({
255
+ status: propStatus,
256
+ defaultValue: field.fieldSchema.default,
257
+ });
186
258
  }, [field.fieldSchema.default, propStatus]);
187
259
  const canPerformReset = previewServerState.type === 'connected' &&
188
260
  propStatus !== null &&
189
- propStatus.canUpdate;
261
+ propStatus.status !== 'computed';
262
+ const canShowReset = canPerformReset && field.fieldSchema.default !== undefined;
190
263
  const onReset = (0, react_1.useCallback)(() => {
191
- if (!canPerformReset ||
192
- previewServerState.type !== 'connected' ||
193
- !isNonDefault) {
264
+ if (!canShowReset ||
265
+ !canResetToDefault ||
266
+ previewServerState.type !== 'connected') {
194
267
  return;
195
268
  }
196
269
  const defaultValue = field.fieldSchema.default !== undefined
197
270
  ? JSON.stringify(field.fieldSchema.default)
198
271
  : null;
199
272
  (0, save_effect_prop_1.saveEffectProp)({
273
+ type: 'value',
200
274
  fileName: validatedLocation.source,
201
275
  nodePath,
202
276
  effectIndex: field.effectIndex,
@@ -208,33 +282,79 @@ const TimelineEffectPropItem = ({ field, validatedLocation, rowDepth, nodePath,
208
282
  clientId: previewServerState.clientId,
209
283
  });
210
284
  }, [
211
- canPerformReset,
285
+ canResetToDefault,
286
+ canShowReset,
212
287
  field.effectIndex,
213
288
  field.effectSchema,
214
289
  field.fieldSchema.default,
215
290
  field.key,
216
- isNonDefault,
217
291
  nodePath,
218
292
  previewServerState,
219
293
  setCodeValues,
220
294
  validatedLocation.source,
221
295
  ]);
296
+ const onOpenKeyframeSettings = (0, react_1.useCallback)(() => {
297
+ var _a;
298
+ if (propStatus === null || !isKeyframedStatus(propStatus)) {
299
+ return;
300
+ }
301
+ setSelectedModal({
302
+ type: 'keyframe-settings',
303
+ fileName: validatedLocation.source,
304
+ nodePath,
305
+ fieldKey: field.key,
306
+ fieldLabel: (_a = field.description) !== null && _a !== void 0 ? _a : field.key,
307
+ status: propStatus,
308
+ schema: field.effectSchema,
309
+ effectIndex: field.effectIndex,
310
+ });
311
+ }, [
312
+ field.description,
313
+ field.effectIndex,
314
+ field.effectSchema,
315
+ field.key,
316
+ nodePath,
317
+ propStatus,
318
+ setSelectedModal,
319
+ validatedLocation.source,
320
+ ]);
222
321
  const contextMenuValues = (0, react_1.useMemo)(() => {
223
- return [
322
+ const values = [
224
323
  {
225
324
  type: 'item',
226
325
  id: 'reset-effect-field',
227
326
  keyHint: null,
228
327
  label: 'Reset',
229
328
  leftItem: null,
230
- disabled: !canPerformReset,
329
+ disabled: !canShowReset,
231
330
  onClick: onReset,
232
331
  quickSwitcherLabel: null,
233
332
  subMenu: null,
234
333
  value: 'reset-effect-field',
235
334
  },
236
335
  ];
237
- }, [canPerformReset, onReset]);
336
+ if (propStatus !== null && isKeyframedStatus(propStatus)) {
337
+ values.push({
338
+ type: 'item',
339
+ id: 'keyframe-settings-effect-field',
340
+ keyHint: null,
341
+ label: 'Keyframe settings...',
342
+ leftItem: null,
343
+ disabled: previewServerState.type !== 'connected',
344
+ onClick: onOpenKeyframeSettings,
345
+ quickSwitcherLabel: null,
346
+ subMenu: null,
347
+ value: 'keyframe-settings-effect-field',
348
+ });
349
+ }
350
+ return values;
351
+ }, [
352
+ canShowReset,
353
+ onOpenKeyframeSettings,
354
+ onReset,
355
+ previewServerState,
356
+ propStatus,
357
+ ]);
238
358
  const row = (jsx_runtime_1.jsxs(TimelineRowChrome_1.TimelineRowChrome, { depth: rowDepth, eye: jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {}), keyframeControls: keyframeControls, arrow: jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), style: style, selected: selection.selected, selectable: selection.selectable, onSelect: selection.onSelect, showSelectedBackground: true, containsSelection: false, outerHeight: null, children: [
239
359
  jsx_runtime_1.jsx(TimelineFieldLabel_1.TimelineFieldLabel, { rowDepth: rowDepth, selected: selection.selected, label: (_c = field.description) !== null && _c !== void 0 ? _c : field.key }), jsx_runtime_1.jsx("div", { style: timeline_field_row_layout_1.timelineFieldValueColumnStyle, children: jsx_runtime_1.jsx(Value, { field: field, nodePath: nodePath, validatedLocation: validatedLocation, keyframeDisplayOffset: keyframeDisplayOffset }) })
240
360
  ] }));
@@ -1,9 +1,9 @@
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 TimelineEnumField: React.FC<{
5
5
  readonly field: SchemaFieldInfo;
6
- readonly propStatus: CanUpdateSequencePropStatus;
6
+ readonly propStatus: CanUpdateSequencePropStatusStatic;
7
7
  readonly effectiveValue: unknown;
8
8
  readonly onSave: TimelineFieldOnSave;
9
9
  readonly onDragValueChange: TimelineFieldOnDragValueChange;
@@ -15,7 +15,7 @@ const TimelineEnumField = ({ field, propStatus, effectiveValue, onSave, onDragVa
15
15
  const variantKeys = Object.keys(fieldSchema.variants);
16
16
  const current = String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : fieldSchema.default);
17
17
  const onSelect = (0, react_1.useCallback)((newValue) => {
18
- if (!propStatus.canUpdate || newValue === propStatus.codeValue) {
18
+ if (newValue === propStatus.codeValue) {
19
19
  return;
20
20
  }
21
21
  onDragValueChange(newValue);
@@ -34,9 +34,9 @@ const TimelineEnumField = ({ field, propStatus, effectiveValue, onSave, onDragVa
34
34
  leftItem: null,
35
35
  subMenu: null,
36
36
  quickSwitcherLabel: null,
37
- disabled: !propStatus.canUpdate,
37
+ disabled: false,
38
38
  }));
39
- }, [variantKeys, onSelect, propStatus]);
39
+ }, [variantKeys, onSelect]);
40
40
  return (jsx_runtime_1.jsx(ComboBox_1.Combobox, { small: true, title: field.key, selectedId: current, values: items, style: comboboxStyle }));
41
41
  };
42
42
  exports.TimelineEnumField = TimelineEnumField;
@@ -1,8 +1,9 @@
1
1
  import React from 'react';
2
- import type { CanUpdateSequencePropStatus, SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
3
- export declare const shouldShowTimelineKeyframeControls: ({ propStatus, selected, }: {
2
+ import type { CanUpdateSequencePropStatus, DragOverrideValue, SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
3
+ export declare const shouldShowTimelineKeyframeControls: ({ propStatus, selected, keyframable, }: {
4
4
  propStatus: CanUpdateSequencePropStatus | null;
5
5
  selected: boolean;
6
+ keyframable: boolean;
6
7
  }) => boolean;
7
8
  export declare const TimelineKeyframeControls: React.FC<{
8
9
  readonly fieldKey: string;
@@ -11,7 +12,7 @@ export declare const TimelineKeyframeControls: React.FC<{
11
12
  readonly fileName: string;
12
13
  readonly keyframeDisplayOffset: number;
13
14
  readonly defaultValue: unknown;
14
- readonly dragOverrideValue: unknown | undefined;
15
+ readonly dragOverrideValue: DragOverrideValue | undefined;
15
16
  readonly schema: SequenceSchema;
16
17
  readonly effectIndex: number | null;
17
18
  }>;
@@ -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");
@@ -10,6 +11,7 @@ const call_add_keyframe_1 = require("./call-add-keyframe");
10
11
  const call_delete_keyframe_1 = require("./call-delete-keyframe");
11
12
  const get_keyframe_navigation_1 = require("./get-keyframe-navigation");
12
13
  const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
14
+ const TimelineKeyframeDiamondIcon_1 = require("./TimelineKeyframeDiamondIcon");
13
15
  const TimelineSelection_1 = require("./TimelineSelection");
14
16
  const controlsContainerStyle = {
15
17
  alignItems: 'center',
@@ -26,53 +28,54 @@ const navButtonStyle = {
26
28
  cursor: 'pointer',
27
29
  display: 'flex',
28
30
  flexShrink: 0,
29
- height: 12,
31
+ height: 14,
30
32
  justifyContent: 'center',
31
33
  lineHeight: 1,
32
34
  outline: 'none',
33
35
  padding: 0,
34
36
  userSelect: 'none',
35
- width: 12,
37
+ width: 14,
38
+ };
39
+ const isKeyframedStatus = (status) => {
40
+ return status.status === 'keyframed';
36
41
  };
37
42
  const diamondButtonStyle = {
38
43
  ...navButtonStyle,
39
44
  background: 'none',
40
45
  };
41
- const diamondIconStyle = {
42
- borderRadius: 1,
43
- boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.4)',
44
- height: 7,
45
- transform: 'rotate(45deg)',
46
- width: 7,
47
- };
48
46
  const svgStyle = { display: 'block' };
49
47
  const getCurrentKeyframeValue = ({ propStatus, jsxFrame, defaultValue, dragOverrideValue, }) => {
50
- if (propStatus.canUpdate) {
48
+ if (isKeyframedStatus(propStatus)) {
51
49
  return remotion_1.Internals.getEffectiveVisualModeValue({
52
50
  codeValue: propStatus,
53
51
  dragOverrideValue,
52
+ frame: jsxFrame,
54
53
  defaultValue,
55
54
  shouldResortToDefaultValueIfUndefined: true,
56
55
  });
57
56
  }
58
- if (propStatus.reason === 'keyframed') {
59
- return remotion_1.Internals.interpolateKeyframedStatus({
57
+ if (propStatus.status === 'static') {
58
+ return remotion_1.Internals.getEffectiveVisualModeValue({
59
+ codeValue: propStatus,
60
+ dragOverrideValue,
60
61
  frame: jsxFrame,
61
- status: propStatus,
62
+ defaultValue,
63
+ shouldResortToDefaultValueIfUndefined: true,
62
64
  });
63
65
  }
64
66
  return null;
65
67
  };
66
- const shouldShowTimelineKeyframeControls = ({ propStatus, selected, }) => {
68
+ const shouldShowTimelineKeyframeControls = ({ propStatus, selected, keyframable, }) => {
67
69
  if (propStatus === null) {
68
70
  return false;
69
71
  }
72
+ if (!keyframable && !isKeyframedStatus(propStatus)) {
73
+ return false;
74
+ }
70
75
  if (selected) {
71
76
  return true;
72
77
  }
73
- return (TimelineSelection_1.SELECTION_ENABLED &&
74
- !propStatus.canUpdate &&
75
- propStatus.reason === 'keyframed');
78
+ return TimelineSelection_1.SELECTION_ENABLED && isKeyframedStatus(propStatus);
76
79
  };
77
80
  exports.shouldShowTimelineKeyframeControls = shouldShowTimelineKeyframeControls;
78
81
  const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, keyframeDisplayOffset, defaultValue, dragOverrideValue, schema, effectIndex, }) => {
@@ -87,14 +90,26 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
87
90
  const jsxFrame = timelinePosition - keyframeDisplayOffset;
88
91
  const keyframes = (0, react_1.useMemo)(() => (0, get_timeline_keyframes_1.getTimelineKeyframes)(propStatus, keyframeDisplayOffset), [propStatus, keyframeDisplayOffset]);
89
92
  const hasKeyframeAtCurrentFrame = (0, react_1.useMemo)(() => {
90
- if (propStatus.canUpdate || propStatus.reason === 'computed') {
93
+ if (!isKeyframedStatus(propStatus)) {
91
94
  return false;
92
95
  }
93
96
  return (0, get_keyframe_navigation_1.hasKeyframeAtSourceFrame)(propStatus.keyframes, jsxFrame);
94
97
  }, [jsxFrame, propStatus]);
95
- const previousDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getPreviousKeyframeDisplayFrame)(keyframes, timelinePosition), [keyframes, timelinePosition]);
96
- const nextDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getNextKeyframeDisplayFrame)(keyframes, timelinePosition), [keyframes, timelinePosition]);
97
- const canToggleKeyframe = propStatus.canUpdate || propStatus.reason === 'keyframed';
98
+ const currentKeyframeValue = (0, react_1.useMemo)(() => getCurrentKeyframeValue({
99
+ propStatus,
100
+ jsxFrame,
101
+ defaultValue,
102
+ dragOverrideValue,
103
+ }), [defaultValue, dragOverrideValue, jsxFrame, propStatus]);
104
+ const previousDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getPreviousKeyframeDisplayFrame)(keyframes, timelinePosition, videoConfig.durationInFrames), [keyframes, timelinePosition, videoConfig.durationInFrames]);
105
+ const nextDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getNextKeyframeDisplayFrame)(keyframes, timelinePosition, videoConfig.durationInFrames), [keyframes, timelinePosition, videoConfig.durationInFrames]);
106
+ const keyframable = (0, studio_shared_1.isSchemaFieldKeyframable)({
107
+ schema,
108
+ key: fieldKey,
109
+ });
110
+ const canAddKeyframe = keyframable;
111
+ const canToggleKeyframe = propStatus.status !== 'computed' &&
112
+ (hasKeyframeAtCurrentFrame || canAddKeyframe);
98
113
  const seekToDisplayFrame = (0, react_1.useCallback)((frame) => {
99
114
  setFrame((current) => {
100
115
  const next = { ...current, [videoConfig.id]: frame };
@@ -119,9 +134,7 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
119
134
  if (!clientId || !canToggleKeyframe) {
120
135
  return;
121
136
  }
122
- if (hasKeyframeAtCurrentFrame &&
123
- !propStatus.canUpdate &&
124
- propStatus.reason === 'keyframed') {
137
+ if (hasKeyframeAtCurrentFrame && isKeyframedStatus(propStatus)) {
125
138
  if (effectIndex === null) {
126
139
  await (0, call_delete_keyframe_1.callDeleteSequenceKeyframe)({
127
140
  fileName,
@@ -146,12 +159,7 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
146
159
  });
147
160
  return;
148
161
  }
149
- const value = getCurrentKeyframeValue({
150
- propStatus,
151
- jsxFrame,
152
- defaultValue,
153
- dragOverrideValue,
154
- });
162
+ const value = currentKeyframeValue;
155
163
  if (value === null) {
156
164
  return;
157
165
  }
@@ -182,12 +190,11 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
182
190
  }, [
183
191
  canToggleKeyframe,
184
192
  clientId,
185
- defaultValue,
186
- dragOverrideValue,
187
193
  effectIndex,
188
194
  fieldKey,
189
195
  fileName,
190
196
  hasKeyframeAtCurrentFrame,
197
+ currentKeyframeValue,
191
198
  jsxFrame,
192
199
  nodePath,
193
200
  propStatus,
@@ -211,12 +218,9 @@ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, ke
211
218
  cursor: canToggleKeyframe && clientId ? 'pointer' : 'default',
212
219
  opacity: canToggleKeyframe && clientId ? 1 : 0.35,
213
220
  }), [canToggleKeyframe, clientId]);
214
- const diamondIcon = (0, react_1.useMemo)(() => ({
215
- ...diamondIconStyle,
216
- backgroundColor: hasKeyframeAtCurrentFrame ? colors_1.BLUE : colors_1.LIGHT_TEXT,
217
- }), [hasKeyframeAtCurrentFrame]);
221
+ const diamondColor = hasKeyframeAtCurrentFrame ? colors_1.BLUE : colors_1.LIGHT_TEXT;
218
222
  return (jsx_runtime_1.jsxs("div", { style: controlsContainerStyle, children: [
219
- jsx_runtime_1.jsx("button", { type: "button", style: previousStyle, disabled: previousDisabled, onPointerDown: previousDisabled ? undefined : onPrevious, "aria-label": "Go to previous keyframe", title: "Previous keyframe", children: jsx_runtime_1.jsx("svg", { width: "14", height: "14", viewBox: "0 0 10 10", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M7 1.5L3 5L7 8.5Z", fill: "#ccc" }) }) }), jsx_runtime_1.jsx("button", { type: "button", style: diamondStyle, disabled: !canToggleKeyframe || !clientId, onPointerDown: canToggleKeyframe && clientId ? onToggleKeyframe : undefined, "aria-label": hasKeyframeAtCurrentFrame ? 'Remove keyframe' : 'Add keyframe', title: hasKeyframeAtCurrentFrame ? 'Remove keyframe' : 'Add keyframe', children: jsx_runtime_1.jsx("span", { style: diamondIcon }) }), jsx_runtime_1.jsx("button", { type: "button", style: nextStyle, disabled: nextDisabled, onPointerDown: nextDisabled ? undefined : onNext, "aria-label": "Go to next keyframe", title: "Next keyframe", children: jsx_runtime_1.jsx("svg", { width: "14", height: "14", viewBox: "0 0 10 10", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M3 1.5L7 5L3 8.5Z", fill: "#ccc" }) }) })
223
+ jsx_runtime_1.jsx("button", { type: "button", style: previousStyle, disabled: previousDisabled, onPointerDown: previousDisabled ? undefined : onPrevious, "aria-label": "Go to previous keyframe", title: "Previous keyframe", children: jsx_runtime_1.jsx("svg", { width: "14", height: "14", viewBox: "0 0 10 10", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M7 1.5L3 5L7 8.5Z", fill: "#ccc" }) }) }), jsx_runtime_1.jsx("button", { type: "button", style: diamondStyle, disabled: !canToggleKeyframe || !clientId, onPointerDown: canToggleKeyframe && clientId ? onToggleKeyframe : undefined, "aria-label": hasKeyframeAtCurrentFrame ? 'Remove keyframe' : 'Add keyframe', title: hasKeyframeAtCurrentFrame ? 'Remove keyframe' : 'Add keyframe', children: jsx_runtime_1.jsx(TimelineKeyframeDiamondIcon_1.TimelineKeyframeDiamondIcon, { color: diamondColor, size: 12 }) }), jsx_runtime_1.jsx("button", { type: "button", style: nextStyle, disabled: nextDisabled, onPointerDown: nextDisabled ? undefined : onNext, "aria-label": "Go to next keyframe", title: "Next keyframe", children: jsx_runtime_1.jsx("svg", { width: "14", height: "14", viewBox: "0 0 10 10", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M3 1.5L7 5L3 8.5Z", fill: "#ccc" }) }) })
220
224
  ] }));
221
225
  };
222
226
  exports.TimelineKeyframeControls = TimelineKeyframeControls;
@@ -40,49 +40,52 @@ const remotion_1 = require("remotion");
40
40
  const colors_1 = require("../../helpers/colors");
41
41
  const get_left_of_timeline_slider_1 = require("../../helpers/get-left-of-timeline-slider");
42
42
  const timeline_layout_1 = require("../../helpers/timeline-layout");
43
+ const TimelineKeyframeDiamondIcon_1 = require("./TimelineKeyframeDiamondIcon");
44
+ const TimelineKeyframeDragState_1 = require("./TimelineKeyframeDragState");
43
45
  const TimelineSelection_1 = require("./TimelineSelection");
44
46
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
47
+ const use_timeline_keyframe_drag_1 = require("./use-timeline-keyframe-drag");
48
+ const diamondSize = 12;
45
49
  const diamondBase = {
50
+ alignItems: 'center',
51
+ background: 'none',
52
+ border: 'none',
53
+ display: 'flex',
54
+ height: diamondSize,
55
+ justifyContent: 'center',
56
+ padding: 0,
46
57
  position: 'absolute',
47
- width: 8,
48
- height: 8,
49
- backgroundColor: colors_1.LIGHT_TEXT,
50
- borderRadius: 1,
51
- boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.4)',
58
+ width: diamondSize,
52
59
  };
53
60
  const TimelineKeyframeDiamondUnmemoized = ({ frame, rowHeight, nodePathInfo }) => {
54
61
  const videoConfig = (0, remotion_1.useVideoConfig)();
55
62
  const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
56
63
  const { selected, onSelect, selectable } = (0, TimelineSelection_1.useTimelineKeyframeSelection)(nodePathInfo, frame);
64
+ const { isKeyframeDragging } = (0, TimelineKeyframeDragState_1.useTimelineKeyframeDragState)();
65
+ const visuallySelected = selected || isKeyframeDragging({ nodePathInfo, frame });
57
66
  const style = (0, react_1.useMemo)(() => {
58
67
  if (timelineWidth === null) {
59
68
  return null;
60
69
  }
61
70
  return {
62
71
  ...diamondBase,
63
- backgroundColor: colors_1.LIGHT_TEXT,
64
- outline: selected ? '2px solid ' + colors_1.BLUE : 'none',
65
- border: 'none',
66
72
  cursor: 'pointer',
67
73
  left: (0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(frame, videoConfig.durationInFrames, timelineWidth) - timeline_layout_1.TIMELINE_PADDING,
68
- padding: 0,
69
74
  pointerEvents: 'auto',
70
75
  top: rowHeight / 2,
71
- transform: 'translate(-50%, -50%) rotate(45deg)',
76
+ transform: 'translate(-50%, -50%)',
72
77
  };
73
- }, [frame, rowHeight, selected, timelineWidth, videoConfig.durationInFrames]);
74
- const onPointerDown = (0, react_1.useCallback)((e) => {
75
- if (e.button === 0) {
76
- e.stopPropagation();
77
- onSelect({
78
- shiftKey: e.shiftKey,
79
- toggleKey: e.metaKey || e.ctrlKey,
80
- });
81
- }
82
- }, [onSelect]);
78
+ }, [frame, rowHeight, timelineWidth, videoConfig.durationInFrames]);
79
+ const onPointerDown = (0, use_timeline_keyframe_drag_1.useTimelineKeyframeDrag)({
80
+ frame,
81
+ nodePathInfo,
82
+ onSelect,
83
+ selectable,
84
+ selected,
85
+ });
83
86
  if (style === null) {
84
87
  return null;
85
88
  }
86
- return (jsx_runtime_1.jsx("button", { type: "button", style: style, title: `Keyframe at frame ${frame}`, "aria-label": `Select keyframe at frame ${frame}`, onPointerDown: selectable ? onPointerDown : undefined }));
89
+ return (jsx_runtime_1.jsx("button", { type: "button", style: style, title: `Keyframe at frame ${frame}`, "aria-label": `Select keyframe at frame ${frame}`, onPointerDown: selectable ? onPointerDown : undefined, children: jsx_runtime_1.jsx(TimelineKeyframeDiamondIcon_1.TimelineKeyframeDiamondIcon, { color: colors_1.LIGHT_TEXT, selected: visuallySelected, size: diamondSize }) }));
87
90
  };
88
91
  exports.TimelineKeyframeDiamond = react_1.default.memo(TimelineKeyframeDiamondUnmemoized);
@@ -0,0 +1,6 @@
1
+ import React from 'react';
2
+ export declare const TimelineKeyframeDiamondIcon: React.FC<{
3
+ readonly color: string;
4
+ readonly selected?: boolean;
5
+ readonly size: number;
6
+ }>;
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineKeyframeDiamondIcon = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const colors_1 = require("../../helpers/colors");
6
+ const svgStyle = {
7
+ display: 'block',
8
+ overflow: 'visible',
9
+ };
10
+ const TimelineKeyframeDiamondIcon = ({ color, selected = false, size }) => {
11
+ return (jsx_runtime_1.jsxs("svg", { width: size, height: size, viewBox: "0 0 12 12", style: svgStyle, "aria-hidden": "true", focusable: "false", children: [selected ? (jsx_runtime_1.jsx("polygon", { points: "6 0.75 11.25 6 6 11.25 0.75 6", fill: "none", stroke: colors_1.BLUE, strokeWidth: "1.5", strokeLinejoin: "round" })) : null, jsx_runtime_1.jsx("polygon", { points: "6 1.5 10.5 6 6 10.5 1.5 6", fill: color, stroke: "rgba(0, 0, 0, 0.4)", strokeWidth: "1", strokeLinejoin: "round" })
12
+ ] }));
13
+ };
14
+ exports.TimelineKeyframeDiamondIcon = TimelineKeyframeDiamondIcon;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
+ export type TimelineDraggedKeyframe = {
4
+ readonly nodePathInfo: SequenceNodePathInfo;
5
+ readonly frame: number;
6
+ };
7
+ export declare const getTimelineKeyframeDragKey: ({ nodePathInfo, frame, }: TimelineDraggedKeyframe) => string;
8
+ type TimelineKeyframeDragStateContextValue = {
9
+ readonly clearDraggedKeyframes: () => void;
10
+ readonly isKeyframeDragging: (keyframe: TimelineDraggedKeyframe) => boolean;
11
+ readonly setDraggedKeyframes: (keyframes: readonly TimelineDraggedKeyframe[]) => void;
12
+ };
13
+ export declare const TimelineKeyframeDragStateProvider: React.FC<{
14
+ readonly children: React.ReactNode;
15
+ }>;
16
+ export declare const useTimelineKeyframeDragState: () => TimelineKeyframeDragStateContextValue;
17
+ export {};