@remotion/studio 4.0.524 → 4.0.526

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 (230) hide show
  1. package/dist/api/focus-default-props-path.js +7 -1
  2. package/dist/api/restart-studio.d.ts +1 -1
  3. package/dist/api/restart-studio.js +1 -1
  4. package/dist/components/ActionTooltip.d.ts +2 -0
  5. package/dist/components/ActionTooltip.js +14 -4
  6. package/dist/components/AgentPrompt.d.ts +6 -0
  7. package/dist/components/AgentPrompt.js +107 -0
  8. package/dist/components/AppLaunchButton.js +2 -0
  9. package/dist/components/AssetFileIcon.js +2 -0
  10. package/dist/components/AssetSelectorItem.d.ts +1 -23
  11. package/dist/components/AssetSelectorItem.js +10 -200
  12. package/dist/components/AssetSelectorModal.d.ts +6 -0
  13. package/dist/components/AssetSelectorModal.js +174 -0
  14. package/dist/components/Canvas.js +21 -4
  15. package/dist/components/CaptionInspector.js +9 -3
  16. package/dist/components/CheckboardToggle.js +2 -1
  17. package/dist/{error-overlay/remotion-overlay → components}/CodeFrame.d.ts +2 -0
  18. package/dist/components/CodeFrame.js +77 -0
  19. package/dist/components/ColorPicker/AlphaSlider.js +1 -1
  20. package/dist/components/ColorPicker/HueSlider.js +1 -1
  21. package/dist/components/ColorPicker/SaturationValueArea.js +1 -1
  22. package/dist/components/CompositionSelector.js +1 -0
  23. package/dist/components/CompositionSelectorItem.js +7 -17
  24. package/dist/components/CurrentAsset.js +5 -4
  25. package/dist/components/EditorGuides/Guide.js +1 -1
  26. package/dist/components/ElementInstallConfirmation.js +100 -61
  27. package/dist/components/FilePreview.js +4 -0
  28. package/dist/components/FixComputedValueModal.js +64 -96
  29. package/dist/components/FullscreenToggle.js +1 -1
  30. package/dist/components/GenerateWithAgentModal.d.ts +9 -0
  31. package/dist/components/GenerateWithAgentModal.js +39 -0
  32. package/dist/components/GlobalKeybindings.js +14 -0
  33. package/dist/components/InlineEditableTitle.js +2 -0
  34. package/dist/components/InspectorLocationCopy.js +1 -1
  35. package/dist/components/InspectorOpenInEditor.d.ts +1 -0
  36. package/dist/components/InspectorOpenInEditor.js +25 -18
  37. package/dist/components/InspectorPanel/CollapsibleInspectorSection.d.ts +7 -0
  38. package/dist/components/InspectorPanel/CollapsibleInspectorSection.js +14 -0
  39. package/dist/components/InspectorPanel/CollapsibleInspectorSectionHeader.d.ts +1 -1
  40. package/dist/components/InspectorPanel/CollapsibleInspectorSectionHeader.js +19 -8
  41. package/dist/components/InspectorPanel/CompositionInspector.js +30 -13
  42. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +6 -7
  43. package/dist/components/InspectorPanel/CompositionMetadata.js +4 -0
  44. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +6 -12
  45. package/dist/components/InspectorPanel/ElementLibraryButton.js +2 -0
  46. package/dist/components/InspectorPanel/GuideInspector.js +2 -3
  47. package/dist/components/InspectorPanel/KeyframeSettings.js +5 -6
  48. package/dist/components/InspectorPanel/MultiSequenceInspector.js +2 -1
  49. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +4 -12
  50. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -3
  51. package/dist/components/InspectorPanel/common.d.ts +4 -0
  52. package/dist/components/InspectorPanel/common.js +14 -2
  53. package/dist/components/InspectorPanel/styles.d.ts +0 -3
  54. package/dist/components/InspectorPanel/styles.js +1 -27
  55. package/dist/components/InspectorPanel/use-composition-actions.d.ts +2 -0
  56. package/dist/components/InspectorPanel/use-composition-actions.js +15 -0
  57. package/dist/components/InspectorPanel/use-inspector-section-expanded.d.ts +1 -0
  58. package/dist/components/InspectorPanel/use-inspector-section-expanded.js +21 -0
  59. package/dist/components/InspectorSequenceSection.js +61 -43
  60. package/dist/components/InspectorSourceLocation.js +1 -0
  61. package/dist/components/KeyboardShortcutsSettings.js +12 -4
  62. package/dist/components/LoopToggle.js +2 -1
  63. package/dist/components/LutPreview.d.ts +4 -0
  64. package/dist/components/LutPreview.js +192 -0
  65. package/dist/components/Menu/MenuItem.js +1 -2
  66. package/dist/components/MenuBuildIndicator.js +1 -1
  67. package/dist/components/MenuCompositionName.js +4 -9
  68. package/dist/components/Modals.js +4 -6
  69. package/dist/components/ModelsSettings.js +15 -4
  70. package/dist/components/MuteToggle.js +2 -1
  71. package/dist/components/NewComposition/CodemodFooter.js +1 -0
  72. package/dist/components/NewComposition/DeleteComposition.js +42 -6
  73. package/dist/components/NewComposition/DeleteFolder.js +1 -0
  74. package/dist/components/NewComposition/DuplicateComposition.js +5 -0
  75. package/dist/components/NewComposition/InputDragger.js +2 -2
  76. package/dist/components/NewComposition/NewFolder.js +29 -2
  77. package/dist/components/NewComposition/RenameFolder.js +1 -0
  78. package/dist/components/NewComposition/duplicate-composition-api.d.ts +3 -2
  79. package/dist/components/NewComposition/duplicate-composition-api.js +9 -2
  80. package/dist/components/OutlineToggle.js +2 -1
  81. package/dist/components/PlayPause.js +1 -1
  82. package/dist/components/Preview.js +0 -3
  83. package/dist/components/PreviewToolbar.js +3 -6
  84. package/dist/components/PreviewToolbarOverflowButton.js +2 -1
  85. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +1 -1
  86. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +4 -9
  87. package/dist/components/RenderButton.js +40 -4
  88. package/dist/components/RenderModal/SchemaEditor/scroll-to-default-props-path.d.ts +1 -0
  89. package/dist/components/RenderModal/SchemaEditor/scroll-to-default-props-path.js +2 -1
  90. package/dist/components/RenderModal/WebRenderModal.js +10 -2
  91. package/dist/components/RenderModal/WebRenderModalBasic.js +1 -1
  92. package/dist/components/RenderModal/render-modals.js +3 -0
  93. package/dist/components/RenderQueue/RenderQueueCopyToClipboard.js +1 -1
  94. package/dist/components/RenderQueue/RenderQueueItemCancelButton.js +1 -1
  95. package/dist/components/RenderQueue/actions.d.ts +2 -1
  96. package/dist/components/RenderQueue/actions.js +2 -1
  97. package/dist/components/RendersTab.js +2 -0
  98. package/dist/components/RulersAndGuidesToggle.js +2 -1
  99. package/dist/components/SegmentedButton.d.ts +1 -0
  100. package/dist/components/SegmentedButton.js +9 -3
  101. package/dist/components/SelectedOutlineElement.js +22 -6
  102. package/dist/components/SelectedOutlinePolygon.js +4 -2
  103. package/dist/components/SettingsButton.js +11 -2
  104. package/dist/components/SettingsContext.d.ts +8 -0
  105. package/dist/components/SettingsContext.js +57 -2
  106. package/dist/components/SettingsModal.d.ts +1 -2
  107. package/dist/components/SettingsModal.js +27 -6
  108. package/dist/components/SettingsModalFooter.js +17 -3
  109. package/dist/components/SidebarCollapserControls.js +1 -1
  110. package/dist/components/SkillsSettings.d.ts +5 -0
  111. package/dist/components/SkillsSettings.js +49 -15
  112. package/dist/components/SnappingToggle.js +2 -1
  113. package/dist/components/Splitter/SplitterHandle.js +1 -2
  114. package/dist/components/Tabs/vertical.d.ts +1 -1
  115. package/dist/components/Tabs/vertical.js +16 -2
  116. package/dist/components/Timeline/EasingEditorModal.js +2 -2
  117. package/dist/components/Timeline/Timeline.js +10 -11
  118. package/dist/components/Timeline/TimelineAssetField.js +178 -9
  119. package/dist/components/Timeline/TimelineDragHandler.js +1 -2
  120. package/dist/components/Timeline/TimelineEffectItem.d.ts +1 -0
  121. package/dist/components/Timeline/TimelineEffectItem.js +2 -2
  122. package/dist/components/Timeline/TimelineEffectPropItem.d.ts +1 -0
  123. package/dist/components/Timeline/TimelineEffectPropItem.js +2 -2
  124. package/dist/components/Timeline/TimelineExpandedRow.js +2 -2
  125. package/dist/components/Timeline/TimelineHeightContainer.js +11 -1
  126. package/dist/components/Timeline/TimelineInOutDragHandler.js +1 -2
  127. package/dist/components/Timeline/TimelineKeyframeControls.js +15 -1
  128. package/dist/components/Timeline/TimelineLayerChildren.d.ts +3 -3
  129. package/dist/components/Timeline/TimelineLayerChildren.js +11 -9
  130. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -1
  131. package/dist/components/Timeline/TimelineLayerEye.js +6 -3
  132. package/dist/components/Timeline/TimelineList.js +9 -3
  133. package/dist/components/Timeline/TimelineSchemaField.js +10 -7
  134. package/dist/components/Timeline/TimelineSelection.d.ts +17 -4
  135. package/dist/components/Timeline/TimelineSelection.js +121 -52
  136. package/dist/components/Timeline/TimelineSequence.js +8 -8
  137. package/dist/components/Timeline/TimelineSequenceItem.d.ts +2 -0
  138. package/dist/components/Timeline/TimelineSequenceItem.js +29 -23
  139. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +3 -12
  140. package/dist/components/Timeline/TimelineTranslateField.js +25 -12
  141. package/dist/components/Timeline/TimelineVirtualization.d.ts +3 -3
  142. package/dist/components/Timeline/TimelineZoomControls.js +1 -1
  143. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +3 -1
  144. package/dist/components/Timeline/get-sequence-context-menu-items.js +152 -51
  145. package/dist/components/Timeline/normalize-font-weight-for-keyframe.d.ts +1 -0
  146. package/dist/components/Timeline/normalize-font-weight-for-keyframe.js +19 -0
  147. package/dist/components/Timeline/timeline-display-groups.d.ts +9 -0
  148. package/dist/components/Timeline/timeline-display-groups.js +66 -0
  149. package/dist/components/Timeline/timeline-field-display-utils.js +4 -2
  150. package/dist/components/Timeline/timeline-translate-utils.d.ts +17 -0
  151. package/dist/components/Timeline/timeline-translate-utils.js +53 -12
  152. package/dist/components/Timeline/use-open-sequence-in-apps.d.ts +2 -0
  153. package/dist/components/Timeline/use-open-sequence-in-apps.js +17 -0
  154. package/dist/components/Timeline/use-timeline-asset-drop.js +20 -6
  155. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +2 -1
  156. package/dist/components/Timeline/use-timeline-expanded-tree.js +1 -2
  157. package/dist/components/Timeline/use-timeline-keyframe-drag.js +4 -4
  158. package/dist/components/TimelineCombobox.js +1 -0
  159. package/dist/components/UndoRedoButtons.js +11 -0
  160. package/dist/components/UpdateStatusContext.d.ts +2 -2
  161. package/dist/components/UpdateStatusContext.js +6 -7
  162. package/dist/components/UpdatesSettings.js +6 -6
  163. package/dist/components/WebMcp.js +40 -41
  164. package/dist/components/asset-context-menu.d.ts +32 -0
  165. package/dist/components/asset-context-menu.js +242 -0
  166. package/dist/components/composition-menu-items.d.ts +4 -6
  167. package/dist/components/composition-menu-items.js +212 -42
  168. package/dist/components/folder-menu-items.js +44 -0
  169. package/dist/components/get-open-in-menu-items.d.ts +6 -5
  170. package/dist/components/get-open-in-menu-items.js +16 -10
  171. package/dist/components/import-assets.d.ts +24 -1
  172. package/dist/components/import-assets.js +3 -1
  173. package/dist/components/keyboard-shortcuts.d.ts +4 -4
  174. package/dist/components/keyboard-shortcuts.js +5 -0
  175. package/dist/components/selected-outline-order.js +18 -12
  176. package/dist/components/use-open-in-menu-apps.d.ts +14 -0
  177. package/dist/components/use-open-in-menu-apps.js +33 -0
  178. package/dist/error-overlay/remotion-overlay/ErrorDisplay.js +2 -2
  179. package/dist/error-overlay/remotion-overlay/OpenInEditor.d.ts +1 -0
  180. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +3 -3
  181. package/dist/error-overlay/remotion-overlay/StackFrame.d.ts +5 -1
  182. package/dist/error-overlay/remotion-overlay/StackFrame.js +26 -19
  183. package/dist/esm/{LazyModels-hc33szyn.mjs → LazyModels-mtggyjye.mjs} +3 -3
  184. package/dist/esm/{LazyModels-sg40rjw6.mjs → LazyModels-nk7py0zt.mjs} +3 -3
  185. package/dist/esm/{TranscriptionModal-3ctnxpt6.mjs → TranscriptionModal-ymnx1c7m.mjs} +6 -6
  186. package/dist/esm/{VideoMattingModal-b0r7e60n.mjs → VideoMattingModal-05vpczks.mjs} +6 -6
  187. package/dist/esm/{index-er3mh6em.mjs → index-0gewwxse.mjs} +7031 -5834
  188. package/dist/esm/{index-q5xv20xx.mjs → index-4dsz9035.mjs} +8 -8
  189. package/dist/esm/{index-wbmp5srk.mjs → index-5bfxbpca.mjs} +1 -1
  190. package/dist/esm/{index-e3zwf3e7.mjs → index-5gd8k9yv.mjs} +1 -1
  191. package/dist/esm/{index-c37kme2v.mjs → index-bs39wngg.mjs} +4929 -3801
  192. package/dist/esm/{index-yfrysr5f.mjs → index-cdy8v54v.mjs} +17 -3
  193. package/dist/esm/{index-9qtvmwtx.mjs → index-eb5txqp6.mjs} +12 -9
  194. package/dist/esm/{index-q2epbw93.mjs → index-f97r9e2g.mjs} +4 -21
  195. package/dist/esm/{index-2j3d1g81.mjs → index-g7k2dvar.mjs} +1 -1
  196. package/dist/esm/{index-1b9skrrd.mjs → index-x40wwfmt.mjs} +3 -3
  197. package/dist/esm/index.mjs +12 -6
  198. package/dist/esm/internals.mjs +7 -7
  199. package/dist/esm/previewEntry.mjs +7 -7
  200. package/dist/helpers/client-id.d.ts +1 -0
  201. package/dist/helpers/client-id.js +8 -4
  202. package/dist/helpers/cube-lut.d.ts +12 -0
  203. package/dist/helpers/cube-lut.js +160 -0
  204. package/dist/helpers/get-git-menu-item.d.ts +4 -0
  205. package/dist/helpers/get-git-menu-item.js +8 -1
  206. package/dist/helpers/get-preview-file-type.d.ts +1 -1
  207. package/dist/helpers/get-preview-file-type.js +3 -0
  208. package/dist/helpers/get-sequence-double-click-action.d.ts +3 -3
  209. package/dist/helpers/get-sequence-double-click-action.js +2 -2
  210. package/dist/helpers/open-in-editor.d.ts +5 -2
  211. package/dist/helpers/open-in-editor.js +12 -4
  212. package/dist/helpers/pointer-session.d.ts +1 -0
  213. package/dist/helpers/pointer-session.js +10 -1
  214. package/dist/helpers/settings-tab-availability.d.ts +14 -0
  215. package/dist/helpers/settings-tab-availability.js +35 -0
  216. package/dist/helpers/studio-runtime-config.d.ts +1 -1
  217. package/dist/helpers/use-create-composition.js +5 -0
  218. package/dist/helpers/use-keybinding.d.ts +1 -1
  219. package/dist/helpers/use-keyboard-shortcut-label.d.ts +2 -2
  220. package/dist/helpers/use-media-metadata.js +5 -1
  221. package/dist/helpers/use-menu-structure.js +21 -13
  222. package/dist/helpers/use-rename-composition.js +6 -1
  223. package/dist/icons/lut.d.ts +4 -0
  224. package/dist/icons/lut.js +6 -0
  225. package/dist/icons/sparkles.d.ts +4 -0
  226. package/dist/icons/sparkles.js +6 -0
  227. package/dist/state/modals.d.ts +25 -3
  228. package/dist/state/z-index.js +1 -3
  229. package/package.json +19 -19
  230. package/dist/error-overlay/remotion-overlay/CodeFrame.js +0 -62
@@ -899,10 +899,7 @@ const TimelineSequenceLeftEdgeDragHandleInner = ({ nodePathInfo, windowWidth, ti
899
899
  onMove,
900
900
  onEnd: (reason, endEvent) => {
901
901
  stopPointerSessionRef.current = null;
902
- if ((reason === 'pointerup' ||
903
- reason === 'buttons-released' ||
904
- (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
905
- endEvent) {
902
+ if ((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent)) {
906
903
  onUp(endEvent);
907
904
  }
908
905
  else if (endEvent) {
@@ -1122,10 +1119,7 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
1122
1119
  },
1123
1120
  onEnd: (reason, endEvent) => {
1124
1121
  stopPointerSessionRef.current = null;
1125
- finishDrag((reason === 'pointerup' ||
1126
- reason === 'buttons-released' ||
1127
- (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
1128
- endEvent !== null);
1122
+ finishDrag((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent));
1129
1123
  },
1130
1124
  });
1131
1125
  }, [
@@ -1325,10 +1319,7 @@ const TimelineSequenceRightEdgeDragHandleInner = ({ nodePathInfo, mediaDurationD
1325
1319
  onMove,
1326
1320
  onEnd: (reason, endEvent) => {
1327
1321
  stopPointerSessionRef.current = null;
1328
- if ((reason === 'pointerup' ||
1329
- reason === 'buttons-released' ||
1330
- (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
1331
- endEvent) {
1322
+ if ((0, pointer_session_1.isPointerSessionRelease)(reason, endEvent)) {
1332
1323
  onUp(endEvent);
1333
1324
  }
1334
1325
  else if (endEvent) {
@@ -4,9 +4,9 @@ exports.TimelineTranslateField = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const InputDragger_1 = require("../NewComposition/InputDragger");
7
- const timeline_field_display_utils_1 = require("./timeline-field-display-utils");
8
7
  const timeline_field_utils_1 = require("./timeline-field-utils");
9
8
  const timeline_translate_utils_1 = require("./timeline-translate-utils");
9
+ const TimelineSchemaField_1 = require("./TimelineSchemaField");
10
10
  const Transform3DModeContext_1 = require("./Transform3DModeContext");
11
11
  const leftDraggerStyle = {
12
12
  paddingLeft: 0,
@@ -21,11 +21,15 @@ const containerStyle = {
21
21
  const translateDragSensitivity = 3;
22
22
  const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onDragValueChange, onDragEnd, }) => {
23
23
  var _a;
24
+ var _b, _c, _d, _e;
24
25
  const [dragX, setDragX] = (0, react_1.useState)(null);
25
26
  const [dragY, setDragY] = (0, react_1.useState)(null);
26
27
  const [dragZ, setDragZ] = (0, react_1.useState)(null);
27
28
  const transform3DMode = (0, react_1.useContext)(Transform3DModeContext_1.Transform3DModeContext);
28
- const [codeX, codeY, codeZ] = (0, react_1.useMemo)(() => (0, timeline_translate_utils_1.parseTranslate)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px')), [effectiveValue]);
29
+ const parsedTranslate = (0, react_1.useMemo)(() => (0, timeline_translate_utils_1.parseTranslateWithUnits)(String(effectiveValue !== null && effectiveValue !== void 0 ? effectiveValue : '0px 0px')), [effectiveValue]);
30
+ const codeX = (_b = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[0].value) !== null && _b !== void 0 ? _b : 0;
31
+ const codeY = (_c = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[1].value) !== null && _c !== void 0 ? _c : 0;
32
+ const codeZ = (_d = (_a = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[2]) === null || _a === void 0 ? void 0 : _a.value) !== null && _d !== void 0 ? _d : null;
29
33
  const show3D = transform3DMode || (codeZ !== null && codeZ !== 0);
30
34
  const configuredStep = field.fieldSchema.type === 'translate' ? field.fieldSchema.step : undefined;
31
35
  const step = configuredStep !== null && configuredStep !== void 0 ? configuredStep : 1;
@@ -33,15 +37,21 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
33
37
  defaultDecimalPlaces: 1,
34
38
  step: configuredStep,
35
39
  }), [configuredStep]);
36
- const formatter = (0, react_1.useCallback)((v) => {
37
- return (0, timeline_field_display_utils_1.formatTimelineFieldValueForDisplay)({
38
- fieldSchema: field.fieldSchema,
39
- value: v,
40
- });
41
- }, [field.fieldSchema]);
40
+ const formatCoordinate = (0, react_1.useCallback)((v, unit) => {
41
+ return `${(0, timeline_field_utils_1.formatTimelineNumber)({
42
+ decimalPlaces,
43
+ fixed: false,
44
+ value: (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(v)),
45
+ })}${unit}`;
46
+ }, [decimalPlaces]);
42
47
  const serialize = (0, react_1.useCallback)((x, y, z = dragZ !== null && dragZ !== void 0 ? dragZ : codeZ) => {
43
- return (0, timeline_translate_utils_1.serializeTranslate)([x, y, z], decimalPlaces);
44
- }, [codeZ, decimalPlaces, dragZ]);
48
+ var _a, _b;
49
+ return (0, timeline_translate_utils_1.serializeTranslateWithUnits)([
50
+ { value: x, unit: (_a = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[0].unit) !== null && _a !== void 0 ? _a : 'px' },
51
+ { value: y, unit: (_b = parsedTranslate === null || parsedTranslate === void 0 ? void 0 : parsedTranslate[1].unit) !== null && _b !== void 0 ? _b : 'px' },
52
+ z === null ? null : { value: z, unit: 'px' },
53
+ ], decimalPlaces);
54
+ }, [codeZ, decimalPlaces, dragZ, parsedTranslate]);
45
55
  // --- X callbacks ---
46
56
  const onXChange = (0, react_1.useCallback)((newVal) => {
47
57
  setDragX(newVal);
@@ -135,9 +145,12 @@ const TimelineTranslateField = ({ field, propStatus, effectiveValue, onSave, onD
135
145
  }
136
146
  }
137
147
  }, [codeX, codeY, dragX, dragY, onSave, propStatus, serialize]);
148
+ if (parsedTranslate === null) {
149
+ return (jsx_runtime_1.jsx(TimelineSchemaField_1.UnsupportedStatus, { label: "unsupported offset", formattedValue: false }));
150
+ }
138
151
  return (jsx_runtime_1.jsxs("span", { style: containerStyle, children: [
139
- jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, buttonStyle: leftDraggerStyle, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset X" }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Y" }), show3D ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
140
- jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: (_a = dragZ !== null && dragZ !== void 0 ? dragZ : codeZ) !== null && _a !== void 0 ? _a : 0, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onZChange, onValueChangeEnd: onZChangeEnd, onTextChange: onZTextChange, min: -Infinity, max: Infinity, step: step, formatter: formatter, rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Z" })
152
+ jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, buttonStyle: leftDraggerStyle, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: -Infinity, max: Infinity, step: step, formatter: (value) => formatCoordinate(value, parsedTranslate[0].unit), rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset X" }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: -Infinity, max: Infinity, step: step, formatter: (value) => formatCoordinate(value, parsedTranslate[1].unit), rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Y" }), show3D ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
153
+ jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: (_e = dragZ !== null && dragZ !== void 0 ? dragZ : codeZ) !== null && _e !== void 0 ? _e : 0, buttonStyle: rightDraggerStyle, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onZChange, onValueChangeEnd: onZChangeEnd, onTextChange: onZTextChange, min: -Infinity, max: Infinity, step: step, formatter: (value) => formatCoordinate(value, 'px'), rightAlign: false, snapToStep: false, dragDecimalPlaces: decimalPlaces, dragSensitivity: translateDragSensitivity, "aria-label": "Offset Z" })
141
154
  ] })) : null] }));
142
155
  };
143
156
  exports.TimelineTranslateField = TimelineTranslateField;
@@ -1,10 +1,10 @@
1
1
  import { type VirtualItem } from '@tanstack/react-virtual';
2
2
  import React from 'react';
3
- import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
3
+ import type { TimelineTrackWithDisplayGroup } from './timeline-display-groups';
4
4
  export type TimelineVirtualRow = {
5
5
  readonly afterDropLineOffset: number;
6
6
  readonly siblingIndex: number;
7
- readonly track: TimelineTrackData;
7
+ readonly track: TimelineTrackWithDisplayGroup;
8
8
  };
9
9
  type TimelineVirtualizationContextValue = {
10
10
  readonly rows: readonly TimelineVirtualRow[];
@@ -16,7 +16,7 @@ export declare const TimelineVirtualizationProvider: React.FC<{
16
16
  readonly children: React.ReactNode;
17
17
  readonly hasBeenCut: boolean;
18
18
  readonly isStill: boolean;
19
- readonly timeline: readonly TimelineTrackData[];
19
+ readonly timeline: readonly TimelineTrackWithDisplayGroup[];
20
20
  }>;
21
21
  export declare const useTimelineVirtualization: () => TimelineVirtualizationContextValue;
22
22
  export {};
@@ -124,7 +124,7 @@ const TimelineZoomControlsInner = ({ sliderMaxWidth }) => {
124
124
  return null;
125
125
  }
126
126
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
127
- jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "Zoom out timeline", shortcut: null, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onMinusClicked, style: buttonStyle, title: "", "aria-label": "Zoom out timeline", type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomOutIcon, { color: color }) }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineZoomSlider, { maxWidth: sliderMaxWidth, minZoom: minZoom, timelineViewportWidth: timelineViewportWidth }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "Zoom in timeline", shortcut: null, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onPlusClicked, style: buttonStyle, title: "", "aria-label": "Zoom in timeline", type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomIcon, { color: color }) }) })
127
+ jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "Zoom out", shortcut: null, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onMinusClicked, style: buttonStyle, title: "", "aria-label": "Zoom out timeline", type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomOutIcon, { color: color }) }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineZoomSlider, { maxWidth: sliderMaxWidth, minZoom: minZoom, timelineViewportWidth: timelineViewportWidth }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(ActionTooltip_1.ActionTooltip, { label: "Zoom in", shortcut: null, delay: 800, dismissOnClick: true, children: jsx_runtime_1.jsx(ControlButton_1.ControlButton, { onClick: onPlusClicked, style: buttonStyle, title: "", "aria-label": "Zoom in timeline", type: "button", children: (color) => jsx_runtime_1.jsx(canvas_zoom_1.CanvasZoomIcon, { color: color }) }) })
128
128
  ] }));
129
129
  };
130
130
  exports.TimelineZoomControls = react_1.default.memo(TimelineZoomControlsInner);
@@ -2,15 +2,17 @@ import type { EditorPickerId, GetDefaultCodingAgentInfoResponse, GetDefaultEdito
2
2
  import type { ResolvedStackLocation, TSequence } from 'remotion';
3
3
  import type { ComboboxValue } from '../NewComposition/ComboBox';
4
4
  import type { TimelineAssetLinkInfo } from './timeline-asset-link';
5
+ export declare const findCopyableFrameElement: (element: Element | null) => Element | null;
5
6
  export declare const getMultiSequenceContextMenuItems: ({ deleteDisabled, duplicateDisabled, onDeleteSelectedSequences, onDuplicateSelectedSequences, }: {
6
7
  readonly deleteDisabled: boolean;
7
8
  readonly duplicateDisabled: boolean;
8
9
  readonly onDeleteSelectedSequences: () => void;
9
10
  readonly onDuplicateSelectedSequences: () => void;
10
11
  }) => ComboboxValue[];
11
- export declare const getSequenceContextMenuItems: ({ assetLinkInfo, canOpenInEditor, deleteDisabled, disableInteractivityDisabled, duplicateDisabled, isProgrammaticallyDuplicated, includeSourceEditItems, codingAgentInfo, editorInfo, onConfigureApps, onDeleteSequenceFromSource, onDisableSequenceInteractivity, onDuplicateSequenceFromSource, openInCodingAgent, openInEditor, originalLocation, selectAsset, sequence, sourceActions, }: {
12
+ export declare const getSequenceContextMenuItems: ({ assetLinkInfo, canOpenInEditor, copyImageElement, deleteDisabled, disableInteractivityDisabled, duplicateDisabled, isProgrammaticallyDuplicated, includeSourceEditItems, codingAgentInfo, editorInfo, onConfigureApps, onDeleteSequenceFromSource, onDisableSequenceInteractivity, onDuplicateSequenceFromSource, openInCodingAgent, openInEditor, originalLocation, selectAsset, sequence, sourceActions, }: {
12
13
  readonly assetLinkInfo: TimelineAssetLinkInfo | null;
13
14
  readonly canOpenInEditor: boolean;
15
+ readonly copyImageElement: Element | null;
14
16
  readonly deleteDisabled: boolean;
15
17
  readonly disableInteractivityDisabled: boolean;
16
18
  readonly duplicateDisabled: boolean;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getSequenceContextMenuItems = exports.getMultiSequenceContextMenuItems = void 0;
3
+ exports.getSequenceContextMenuItems = exports.getMultiSequenceContextMenuItems = exports.findCopyableFrameElement = void 0;
4
4
  const no_react_1 = require("remotion/no-react");
5
5
  const format_file_location_1 = require("../../helpers/format-file-location");
6
+ const get_git_menu_item_1 = require("../../helpers/get-git-menu-item");
6
7
  const get_open_in_menu_items_1 = require("../get-open-in-menu-items");
7
8
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
8
9
  const actions_1 = require("../RenderQueue/actions");
@@ -27,6 +28,74 @@ const normalizeMenuDividers = (items) => {
27
28
  return normalized;
28
29
  };
29
30
  const interactiveSvgComponentIdentity = 'dev.remotion.remotion.Interactive.Svg';
31
+ const findCopyableFrameElement = (element) => {
32
+ var _a;
33
+ if ((element === null || element === void 0 ? void 0 : element.tagName) === 'CANVAS' || (element === null || element === void 0 ? void 0 : element.tagName) === 'VIDEO') {
34
+ return element;
35
+ }
36
+ return (_a = element === null || element === void 0 ? void 0 : element.querySelector('canvas, video')) !== null && _a !== void 0 ? _a : null;
37
+ };
38
+ exports.findCopyableFrameElement = findCopyableFrameElement;
39
+ const copyImageToClipboard = async (element) => {
40
+ let canvas;
41
+ if (element.tagName === 'CANVAS') {
42
+ const sourceCanvas = element;
43
+ canvas = document.createElement('canvas');
44
+ canvas.width = sourceCanvas.width;
45
+ canvas.height = sourceCanvas.height;
46
+ const context = canvas.getContext('2d');
47
+ if (!context) {
48
+ throw new Error('Could not create canvas context');
49
+ }
50
+ context.drawImage(sourceCanvas, 0, 0);
51
+ }
52
+ else if (element.tagName === 'IMG') {
53
+ const image = element;
54
+ if (image.naturalWidth === 0 || image.naturalHeight === 0) {
55
+ throw new Error('Image has not loaded');
56
+ }
57
+ canvas = document.createElement('canvas');
58
+ canvas.width = image.naturalWidth;
59
+ canvas.height = image.naturalHeight;
60
+ const context = canvas.getContext('2d');
61
+ if (!context) {
62
+ throw new Error('Could not create canvas context');
63
+ }
64
+ context.drawImage(image, 0, 0);
65
+ }
66
+ else if (element.tagName === 'VIDEO') {
67
+ const video = element;
68
+ if (video.videoWidth === 0 || video.videoHeight === 0) {
69
+ throw new Error('Video frame has not loaded');
70
+ }
71
+ canvas = document.createElement('canvas');
72
+ canvas.width = video.videoWidth;
73
+ canvas.height = video.videoHeight;
74
+ const context = canvas.getContext('2d');
75
+ if (!context) {
76
+ throw new Error('Could not create canvas context');
77
+ }
78
+ context.drawImage(video, 0, 0);
79
+ }
80
+ else {
81
+ throw new Error('Expected an image, video, or canvas element');
82
+ }
83
+ const blob = new Promise((resolve, reject) => {
84
+ canvas.toBlob((result) => {
85
+ if (result) {
86
+ resolve(result);
87
+ }
88
+ else {
89
+ reject(new Error('Could not convert image to PNG'));
90
+ }
91
+ }, 'image/png');
92
+ });
93
+ await navigator.clipboard.write([
94
+ new ClipboardItem({
95
+ 'image/png': blob,
96
+ }),
97
+ ]);
98
+ };
30
99
  const getMultiSequenceContextMenuItems = ({ deleteDisabled, duplicateDisabled, onDeleteSelectedSequences, onDuplicateSelectedSequences, }) => {
31
100
  return [
32
101
  {
@@ -60,15 +129,20 @@ const getMultiSequenceContextMenuItems = ({ deleteDisabled, duplicateDisabled, o
60
129
  ];
61
130
  };
62
131
  exports.getMultiSequenceContextMenuItems = getMultiSequenceContextMenuItems;
63
- const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDisabled, disableInteractivityDisabled, duplicateDisabled, isProgrammaticallyDuplicated, includeSourceEditItems, codingAgentInfo, editorInfo, onConfigureApps, onDeleteSequenceFromSource, onDisableSequenceInteractivity, onDuplicateSequenceFromSource, openInCodingAgent, openInEditor, originalLocation, selectAsset, sequence, sourceActions = [], }) => {
132
+ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, copyImageElement, deleteDisabled, disableInteractivityDisabled, duplicateDisabled, isProgrammaticallyDuplicated, includeSourceEditItems, codingAgentInfo, editorInfo, onConfigureApps, onDeleteSequenceFromSource, onDisableSequenceInteractivity, onDuplicateSequenceFromSource, openInCodingAgent, openInEditor, originalLocation, selectAsset, sequence, sourceActions = [], }) => {
64
133
  var _a, _b, _c;
65
- var _d, _e, _f;
134
+ var _d, _e;
66
135
  const isInteractiveSvg = ((_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.componentIdentity) === interactiveSvgComponentIdentity;
67
136
  const installedEditors = (_d = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors) !== null && _d !== void 0 ? _d : [];
68
137
  const defaultEditorId = (0, use_default_editor_info_1.getPreferredEditorId)(editorInfo);
69
138
  const defaultEditor = installedEditors.find((editor) => editor.id === defaultEditorId);
70
139
  const editorName = (_e = defaultEditor === null || defaultEditor === void 0 ? void 0 : defaultEditor.nameWithType) !== null && _e !== void 0 ? _e : null;
71
- const defaultCodingAgent = codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents.find((codingAgent) => codingAgent.id === codingAgentInfo.defaultCodingAgent);
140
+ const defaultOpenInTarget = (0, get_git_menu_item_1.getDefaultOpenInTarget)({ canOpenInEditor });
141
+ const gitSourceName = window.remotion_gitSource
142
+ ? (0, get_git_menu_item_1.getGitSourceName)(window.remotion_gitSource)
143
+ : null;
144
+ const defaultOpenInName = defaultOpenInTarget === 'editor' ? editorName : gitSourceName;
145
+ const copyImageLabel = copyImageElement && sequence.type === 'image' ? 'Copy image' : 'Copy frame';
72
146
  const contextForAgents = (0, format_file_location_1.formatContextForAgents)({
73
147
  location: originalLocation,
74
148
  name: sequence.displayName || ((_b = sequence.controls) === null || _b === void 0 ? void 0 : _b.componentName) || null,
@@ -77,61 +151,60 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
77
151
  const openInCodingAgentWithContext = (codingAgentId, codingAgentName) => {
78
152
  openInCodingAgent(codingAgentId, codingAgentName, codingAgentId === 'copilot' ? null : contextForAgents);
79
153
  };
80
- const openInMenuItems = onConfigureApps
81
- ? (0, get_open_in_menu_items_1.getOpenInMenuItems)({
82
- codingAgentInfo,
83
- editorDisabled: !canOpenInEditor || !originalLocation,
84
- editorInfo,
85
- excludeCodingAgentId: (_f = defaultCodingAgent === null || defaultCodingAgent === void 0 ? void 0 : defaultCodingAgent.id) !== null && _f !== void 0 ? _f : null,
86
- excludeEditorId: defaultEditorId,
87
- fileManagerDisabled: !(originalLocation === null || originalLocation === void 0 ? void 0 : originalLocation.source),
88
- folder: false,
89
- location: originalLocation,
90
- onConfigureApps,
91
- onOpenInCodingAgent: openInCodingAgentWithContext,
92
- onOpenInEditor: openInEditor,
93
- onOpenInFileExplorer: () => {
94
- if (!(originalLocation === null || originalLocation === void 0 ? void 0 : originalLocation.source)) {
95
- return;
96
- }
97
- (0, actions_1.openInFileExplorer)({ directory: originalLocation.source }).catch((err) => {
98
- (0, NotificationCenter_1.showNotification)(`Could not open file: ${err.message}`, 2000);
99
- });
100
- },
101
- onOpenInGitClient: () => undefined,
102
- onOpenInTerminal: null,
103
- })
104
- : [];
105
- const items = [
106
- editorName
107
- ? {
108
- type: 'item',
109
- id: 'open-in-editor',
110
- keyHint: null,
111
- label: `Open in ${editorName}`,
112
- leftItem: null,
113
- disabled: !canOpenInEditor || !originalLocation,
114
- onClick: () => openInEditor(null),
115
- quickSwitcherLabel: null,
116
- subMenu: null,
117
- value: 'open-in-editor',
154
+ const openInMenuItems = (0, get_open_in_menu_items_1.getOpenInMenuItems)({
155
+ canOpenDesktopApps: onConfigureApps !== null,
156
+ codingAgentInfo,
157
+ editorDisabled: !canOpenInEditor || !originalLocation,
158
+ editorInfo,
159
+ excludeCodingAgentId: null,
160
+ excludeEditorId: defaultEditorId,
161
+ excludeGitSource: defaultOpenInTarget === 'git-source',
162
+ fileManagerDisabled: !(originalLocation === null || originalLocation === void 0 ? void 0 : originalLocation.source),
163
+ folder: false,
164
+ gitSourceDisabled: !originalLocation,
165
+ onConfigureApps,
166
+ onOpenInCodingAgent: openInCodingAgentWithContext,
167
+ onOpenInEditor: openInEditor,
168
+ onOpenInFileExplorer: () => {
169
+ if (!(originalLocation === null || originalLocation === void 0 ? void 0 : originalLocation.source)) {
170
+ return;
118
171
  }
119
- : null,
120
- defaultCodingAgent
172
+ (0, actions_1.openInFileExplorer)({ directory: originalLocation.source }).catch((err) => {
173
+ (0, NotificationCenter_1.showNotification)(`Could not open file: ${err.message}`, 2000);
174
+ });
175
+ },
176
+ onOpenInGitClient: () => undefined,
177
+ onOpenInGitSource: () => {
178
+ (0, get_git_menu_item_1.openGitSource)({ folder: false, location: originalLocation });
179
+ },
180
+ onOpenInTerminal: null,
181
+ });
182
+ const items = [
183
+ defaultOpenInTarget && defaultOpenInName
121
184
  ? {
122
185
  type: 'item',
123
- id: 'open-in-default-coding-agent',
186
+ id: defaultOpenInTarget === 'editor'
187
+ ? 'open-in-editor'
188
+ : 'open-in-git-source',
124
189
  keyHint: null,
125
- label: `Open in ${defaultCodingAgent.nameWithType}`,
190
+ label: `Open in ${defaultOpenInName}`,
126
191
  leftItem: null,
127
- disabled: false,
128
- onClick: () => openInCodingAgentWithContext(defaultCodingAgent.id, defaultCodingAgent.nameWithType),
192
+ disabled: !originalLocation,
193
+ onClick: () => {
194
+ if (defaultOpenInTarget === 'editor') {
195
+ openInEditor(null);
196
+ return;
197
+ }
198
+ (0, get_git_menu_item_1.openGitSource)({ folder: false, location: originalLocation });
199
+ },
129
200
  quickSwitcherLabel: null,
130
201
  subMenu: null,
131
- value: 'open-in-default-coding-agent',
202
+ value: defaultOpenInTarget === 'editor'
203
+ ? 'open-in-editor'
204
+ : 'open-in-git-source',
132
205
  }
133
206
  : null,
134
- onConfigureApps
207
+ openInMenuItems.length > 0
135
208
  ? {
136
209
  type: 'item',
137
210
  id: 'open-in-another-app',
@@ -166,7 +239,35 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
166
239
  value: 'show-asset',
167
240
  }
168
241
  : null,
169
- assetLinkInfo
242
+ copyImageElement
243
+ ? {
244
+ type: 'divider',
245
+ id: 'copy-image-divider',
246
+ }
247
+ : null,
248
+ copyImageElement
249
+ ? {
250
+ type: 'item',
251
+ id: copyImageLabel === 'Copy image' ? 'copy-image' : 'copy-frame',
252
+ keyHint: null,
253
+ label: copyImageLabel,
254
+ leftItem: null,
255
+ disabled: false,
256
+ onClick: () => {
257
+ copyImageToClipboard(copyImageElement)
258
+ .then(() => {
259
+ (0, NotificationCenter_1.showNotification)(`Copied ${copyImageLabel === 'Copy image' ? 'image' : 'frame'} to clipboard`, 1000);
260
+ })
261
+ .catch((err) => {
262
+ (0, NotificationCenter_1.showNotification)(`Could not copy ${copyImageLabel === 'Copy image' ? 'image' : 'frame'}: ${err.message}`, 2000);
263
+ });
264
+ },
265
+ quickSwitcherLabel: null,
266
+ subMenu: null,
267
+ value: copyImageLabel === 'Copy image' ? 'copy-image' : 'copy-frame',
268
+ }
269
+ : null,
270
+ assetLinkInfo || copyImageElement
170
271
  ? {
171
272
  type: 'divider',
172
273
  id: 'sequence-link-divider',
@@ -0,0 +1 @@
1
+ export declare const normalizeFontWeightForKeyframe: (value: unknown) => number | null;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeFontWeightForKeyframe = void 0;
4
+ const normalizeFontWeightForKeyframe = (value) => {
5
+ if (value === 'normal') {
6
+ return 400;
7
+ }
8
+ if (value === 'bold') {
9
+ return 700;
10
+ }
11
+ if (typeof value === 'number') {
12
+ return Number.isFinite(value) ? value : null;
13
+ }
14
+ if (typeof value === 'string' && /^\d+(?:\.\d+)?$/.test(value)) {
15
+ return Number(value);
16
+ }
17
+ return null;
18
+ };
19
+ exports.normalizeFontWeightForKeyframe = normalizeFontWeightForKeyframe;
@@ -0,0 +1,9 @@
1
+ import type { TimelineTrackData } from '../../helpers/get-timeline-sequence-sort-key';
2
+ export type TimelineDisplayGroup = {
3
+ readonly key: string;
4
+ readonly numberOfSequences: number;
5
+ };
6
+ export type TimelineTrackWithDisplayGroup = TimelineTrackData & {
7
+ readonly displayGroup: TimelineDisplayGroup | null;
8
+ };
9
+ export declare const addTimelineDisplayGroups: (tracks: readonly TimelineTrackData[]) => TimelineTrackWithDisplayGroup[];
@@ -0,0 +1,66 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.addTimelineDisplayGroups = void 0;
4
+ const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
5
+ const addTimelineDisplayGroups = (tracks) => {
6
+ var _a, _b;
7
+ const stacksBySequenceId = new Map();
8
+ const resolvedNodePathKeysByStack = new Map();
9
+ for (const track of tracks) {
10
+ // Only controlled sequences can eventually resolve to a source node.
11
+ const stack = track.sequence.controls === null ? null : track.sequence.getStack();
12
+ stacksBySequenceId.set(track.sequence.id, stack);
13
+ if (stack === null || track.nodePathInfo === null) {
14
+ continue;
15
+ }
16
+ const nodePathKey = `node-path:${(0, timeline_node_path_key_1.timelineSequenceNodePathToKey)(track.nodePathInfo.sequenceSubscriptionKey)}`;
17
+ const nodePathKeys = (_a = resolvedNodePathKeysByStack.get(stack)) !== null && _a !== void 0 ? _a : new Set();
18
+ nodePathKeys.add(nodePathKey);
19
+ resolvedNodePathKeysByStack.set(stack, nodePathKeys);
20
+ }
21
+ const displayKeys = tracks.map((track) => {
22
+ var _a;
23
+ if (track.nodePathInfo !== null) {
24
+ return `node-path:${(0, timeline_node_path_key_1.timelineSequenceNodePathToKey)(track.nodePathInfo.sequenceSubscriptionKey)}`;
25
+ }
26
+ const stack = (_a = stacksBySequenceId.get(track.sequence.id)) !== null && _a !== void 0 ? _a : null;
27
+ if (stack === null) {
28
+ return null;
29
+ }
30
+ const resolvedNodePathKeys = resolvedNodePathKeysByStack.get(stack);
31
+ if ((resolvedNodePathKeys === null || resolvedNodePathKeys === void 0 ? void 0 : resolvedNodePathKeys.size) === 1) {
32
+ const resolvedNodePathKey = resolvedNodePathKeys.values().next().value;
33
+ if (resolvedNodePathKey === undefined) {
34
+ throw new Error('Expected a resolved timeline node path key');
35
+ }
36
+ return resolvedNodePathKey;
37
+ }
38
+ // This identity is display-only. Source operations continue to require
39
+ // track.nodePathInfo.
40
+ return `stack:${stack}`;
41
+ });
42
+ const counts = new Map();
43
+ for (const key of displayKeys) {
44
+ if (key !== null) {
45
+ counts.set(key, ((_b = counts.get(key)) !== null && _b !== void 0 ? _b : 0) + 1);
46
+ }
47
+ }
48
+ return tracks.map((track, index) => {
49
+ const key = displayKeys[index];
50
+ if (key === null) {
51
+ return { ...track, displayGroup: null };
52
+ }
53
+ const numberOfSequences = counts.get(key);
54
+ if (numberOfSequences === undefined) {
55
+ throw new Error('Expected a timeline display group count');
56
+ }
57
+ return {
58
+ ...track,
59
+ displayGroup: {
60
+ key,
61
+ numberOfSequences,
62
+ },
63
+ };
64
+ });
65
+ };
66
+ exports.addTimelineDisplayGroups = addTimelineDisplayGroups;
@@ -153,8 +153,10 @@ const formatTranslateTimelineFieldValueForDisplay = ({ fieldSchema, value, }) =>
153
153
  if (numericValue !== null) {
154
154
  return formatTranslateCoordinateForDisplay(numericValue, decimalPlaces);
155
155
  }
156
- const translate = (0, timeline_translate_utils_1.parseTranslate)(String(value !== null && value !== void 0 ? value : '0px 0px'));
157
- return (0, timeline_translate_utils_1.serializeTranslate)(translate, decimalPlaces);
156
+ const translate = (0, timeline_translate_utils_1.parseTranslateWithUnits)(String(value !== null && value !== void 0 ? value : '0px 0px'));
157
+ return translate === null
158
+ ? null
159
+ : (0, timeline_translate_utils_1.serializeTranslateWithUnits)(translate, decimalPlaces);
158
160
  };
159
161
  const formatTransformOriginAxisValueForDisplay = ({ decimalPlaces, unit, value, }) => {
160
162
  return `${(0, timeline_field_utils_1.formatTimelineNumber)({
@@ -1,3 +1,20 @@
1
1
  export type ParsedTranslate = readonly [number, number, number | null];
2
+ export type TranslateUnit = 'px' | '%';
3
+ export type ParsedTranslateWithUnits = readonly [
4
+ {
5
+ readonly value: number;
6
+ readonly unit: TranslateUnit;
7
+ },
8
+ {
9
+ readonly value: number;
10
+ readonly unit: TranslateUnit;
11
+ },
12
+ {
13
+ readonly value: number;
14
+ readonly unit: 'px';
15
+ } | null
16
+ ];
17
+ export declare const parseTranslateWithUnits: (value: string) => ParsedTranslateWithUnits | null;
2
18
  export declare const parseTranslate: (value: string) => ParsedTranslate;
3
19
  export declare const serializeTranslate: ([x, y, z]: ParsedTranslate, decimalPlaces?: number) => string;
20
+ export declare const serializeTranslateWithUnits: ([x, y, z]: ParsedTranslateWithUnits, decimalPlaces?: number) => string;
@@ -1,20 +1,53 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.serializeTranslate = exports.parseTranslate = void 0;
3
+ exports.serializeTranslateWithUnits = exports.serializeTranslate = exports.parseTranslate = exports.parseTranslateWithUnits = void 0;
4
4
  const timeline_field_utils_1 = require("./timeline-field-utils");
5
- const PIXEL_PATTERN = /^(-?\d+(?:\.\d+)?)px(?:\s+(-?\d+(?:\.\d+)?)px)?(?:\s+(-?\d+(?:\.\d+)?)px)?$/;
5
+ const TRANSLATE_PATTERN = /^(-?\d+(?:\.\d+)?)(px|%)?(?:\s+(-?\d+(?:\.\d+)?)(px|%)?)?(?:\s+(-?\d+(?:\.\d+)?)(px)?)?$/i;
6
6
  const translateDecimalPlaces = 1;
7
- const parseTranslate = (value) => {
8
- const m = value.match(PIXEL_PATTERN);
9
- if (!m) {
10
- return [0, 0, null];
7
+ const parseTranslateWithUnits = (value) => {
8
+ const match = value.match(TRANSLATE_PATTERN);
9
+ if (!match) {
10
+ return null;
11
+ }
12
+ const x = (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(match[1]));
13
+ const y = match[3] === undefined ? 0 : (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(match[3]));
14
+ const z = match[5] === undefined ? null : (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(match[5]));
15
+ if ((match[2] === undefined && x !== 0) ||
16
+ (match[3] !== undefined && match[4] === undefined && y !== 0) ||
17
+ (match[5] !== undefined && match[6] === undefined && z !== 0)) {
18
+ return null;
11
19
  }
12
20
  return [
13
- (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[1])),
14
- m[2] !== undefined ? (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[2])) : 0,
15
- m[3] !== undefined ? (0, timeline_field_utils_1.normalizeTimelineNumber)(Number(m[3])) : null,
21
+ {
22
+ value: x,
23
+ unit: match[2] === undefined
24
+ ? 'px'
25
+ : match[2].toLowerCase(),
26
+ },
27
+ {
28
+ value: y,
29
+ unit: match[4] === undefined
30
+ ? 'px'
31
+ : match[4].toLowerCase(),
32
+ },
33
+ z === null
34
+ ? z
35
+ : {
36
+ value: z,
37
+ unit: 'px',
38
+ },
16
39
  ];
17
40
  };
41
+ exports.parseTranslateWithUnits = parseTranslateWithUnits;
42
+ const parseTranslate = (value) => {
43
+ var _a;
44
+ var _b;
45
+ const parsed = (0, exports.parseTranslateWithUnits)(value);
46
+ if (parsed === null || parsed[0].unit !== 'px' || parsed[1].unit !== 'px') {
47
+ return [0, 0, null];
48
+ }
49
+ return [parsed[0].value, parsed[1].value, (_b = (_a = parsed[2]) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null];
50
+ };
18
51
  exports.parseTranslate = parseTranslate;
19
52
  const formatTranslateCoordinate = (value, decimalPlaces) => {
20
53
  const normalized = (0, timeline_field_utils_1.normalizeTimelineNumber)(value);
@@ -22,9 +55,17 @@ const formatTranslateCoordinate = (value, decimalPlaces) => {
22
55
  return String(Object.is(rounded, -0) ? 0 : rounded);
23
56
  };
24
57
  const serializeTranslate = ([x, y, z], decimalPlaces = translateDecimalPlaces) => {
25
- const xy = `${formatTranslateCoordinate(x, decimalPlaces)}px ${formatTranslateCoordinate(y, decimalPlaces)}px`;
58
+ return (0, exports.serializeTranslateWithUnits)([
59
+ { value: x, unit: 'px' },
60
+ { value: y, unit: 'px' },
61
+ z === null ? null : { value: z, unit: 'px' },
62
+ ], decimalPlaces);
63
+ };
64
+ exports.serializeTranslate = serializeTranslate;
65
+ const serializeTranslateWithUnits = ([x, y, z], decimalPlaces = translateDecimalPlaces) => {
66
+ const xy = `${formatTranslateCoordinate(x.value, decimalPlaces)}${x.unit} ${formatTranslateCoordinate(y.value, decimalPlaces)}${y.unit}`;
26
67
  return z === null
27
68
  ? xy
28
- : `${xy} ${formatTranslateCoordinate(z, decimalPlaces)}px`;
69
+ : `${xy} ${formatTranslateCoordinate(z.value, decimalPlaces)}${z.unit}`;
29
70
  };
30
- exports.serializeTranslate = serializeTranslate;
71
+ exports.serializeTranslateWithUnits = serializeTranslateWithUnits;