@remotion/studio 4.0.525 → 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 (141) 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/AgentPrompt.d.ts +6 -0
  5. package/dist/components/AgentPrompt.js +107 -0
  6. package/dist/components/AssetFileIcon.js +2 -0
  7. package/dist/components/AssetSelectorItem.d.ts +1 -23
  8. package/dist/components/AssetSelectorItem.js +10 -200
  9. package/dist/components/Canvas.js +21 -18
  10. package/dist/components/CaptionInspector.js +9 -3
  11. package/dist/{error-overlay/remotion-overlay → components}/CodeFrame.d.ts +2 -0
  12. package/dist/components/CodeFrame.js +77 -0
  13. package/dist/components/CompositionSelectorItem.js +6 -17
  14. package/dist/components/CurrentAsset.js +5 -4
  15. package/dist/components/ElementInstallConfirmation.js +69 -38
  16. package/dist/components/FilePreview.js +4 -0
  17. package/dist/components/FixComputedValueModal.js +64 -96
  18. package/dist/components/GenerateWithAgentModal.d.ts +9 -0
  19. package/dist/components/GenerateWithAgentModal.js +39 -0
  20. package/dist/components/InlineEditableTitle.js +2 -0
  21. package/dist/components/InspectorOpenInEditor.js +8 -4
  22. package/dist/components/InspectorPanel/CollapsibleInspectorSection.d.ts +7 -0
  23. package/dist/components/InspectorPanel/CollapsibleInspectorSection.js +14 -0
  24. package/dist/components/InspectorPanel/CollapsibleInspectorSectionHeader.d.ts +1 -1
  25. package/dist/components/InspectorPanel/CollapsibleInspectorSectionHeader.js +19 -8
  26. package/dist/components/InspectorPanel/CompositionInspector.js +30 -13
  27. package/dist/components/InspectorPanel/CompositionMetadata.js +3 -0
  28. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +6 -12
  29. package/dist/components/InspectorPanel/ElementLibraryButton.js +1 -0
  30. package/dist/components/InspectorPanel/GuideInspector.js +2 -3
  31. package/dist/components/InspectorPanel/KeyframeSettings.js +5 -6
  32. package/dist/components/InspectorPanel/MultiSequenceInspector.js +2 -1
  33. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +4 -3
  34. package/dist/components/InspectorPanel/common.d.ts +4 -0
  35. package/dist/components/InspectorPanel/common.js +14 -2
  36. package/dist/components/InspectorPanel/styles.d.ts +0 -3
  37. package/dist/components/InspectorPanel/styles.js +1 -27
  38. package/dist/components/InspectorPanel/use-composition-actions.d.ts +2 -0
  39. package/dist/components/InspectorPanel/use-composition-actions.js +15 -0
  40. package/dist/components/InspectorPanel/use-inspector-section-expanded.d.ts +1 -0
  41. package/dist/components/InspectorPanel/use-inspector-section-expanded.js +21 -0
  42. package/dist/components/InspectorSequenceSection.js +44 -35
  43. package/dist/components/InspectorSourceLocation.js +1 -0
  44. package/dist/components/KeyboardShortcutsSettings.js +12 -4
  45. package/dist/components/LutPreview.d.ts +4 -0
  46. package/dist/components/LutPreview.js +192 -0
  47. package/dist/components/MenuCompositionName.js +4 -9
  48. package/dist/components/Modals.js +3 -6
  49. package/dist/components/ModelsSettings.js +15 -4
  50. package/dist/components/Notifications/NotificationCenter.d.ts +0 -1
  51. package/dist/components/Notifications/NotificationCenter.js +1 -22
  52. package/dist/components/QuickSwitcher/QuickSwitcherResult.js +4 -9
  53. package/dist/components/RenderModal/SchemaEditor/scroll-to-default-props-path.d.ts +1 -0
  54. package/dist/components/RenderModal/SchemaEditor/scroll-to-default-props-path.js +2 -1
  55. package/dist/components/RenderModal/WebRenderModal.js +10 -2
  56. package/dist/components/RendersTab.js +2 -0
  57. package/dist/components/SelectedOutlineElement.js +6 -0
  58. package/dist/components/SettingsButton.js +11 -2
  59. package/dist/components/SettingsModal.d.ts +1 -2
  60. package/dist/components/SettingsModal.js +24 -6
  61. package/dist/components/SettingsModalFooter.js +17 -3
  62. package/dist/components/SkillsSettings.d.ts +5 -0
  63. package/dist/components/SkillsSettings.js +29 -26
  64. package/dist/components/Timeline/Timeline.js +10 -11
  65. package/dist/components/Timeline/TimelineAssetField.js +81 -51
  66. package/dist/components/Timeline/TimelineHeightContainer.js +11 -1
  67. package/dist/components/Timeline/TimelineKeyframeControls.js +15 -1
  68. package/dist/components/Timeline/TimelineLayerChildren.d.ts +3 -3
  69. package/dist/components/Timeline/TimelineLayerChildren.js +11 -9
  70. package/dist/components/Timeline/TimelineLayerEye.d.ts +1 -1
  71. package/dist/components/Timeline/TimelineLayerEye.js +6 -3
  72. package/dist/components/Timeline/TimelineList.js +9 -3
  73. package/dist/components/Timeline/TimelineSchemaField.js +2 -6
  74. package/dist/components/Timeline/TimelineSelection.d.ts +14 -3
  75. package/dist/components/Timeline/TimelineSelection.js +91 -49
  76. package/dist/components/Timeline/TimelineSequence.js +2 -2
  77. package/dist/components/Timeline/TimelineSequenceItem.d.ts +2 -0
  78. package/dist/components/Timeline/TimelineSequenceItem.js +17 -13
  79. package/dist/components/Timeline/TimelineVirtualization.d.ts +3 -3
  80. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +3 -1
  81. package/dist/components/Timeline/get-sequence-context-menu-items.js +130 -45
  82. package/dist/components/Timeline/normalize-font-weight-for-keyframe.d.ts +1 -0
  83. package/dist/components/Timeline/normalize-font-weight-for-keyframe.js +19 -0
  84. package/dist/components/Timeline/timeline-display-groups.d.ts +9 -0
  85. package/dist/components/Timeline/timeline-display-groups.js +66 -0
  86. package/dist/components/Timeline/use-timeline-asset-drop.js +21 -21
  87. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +2 -1
  88. package/dist/components/Timeline/use-timeline-expanded-tree.js +1 -2
  89. package/dist/components/UpdateStatusContext.d.ts +2 -2
  90. package/dist/components/UpdateStatusContext.js +6 -7
  91. package/dist/components/UpdatesSettings.js +6 -6
  92. package/dist/components/WebMcp.js +40 -41
  93. package/dist/components/asset-context-menu.d.ts +32 -0
  94. package/dist/components/asset-context-menu.js +242 -0
  95. package/dist/components/composition-menu-items.d.ts +4 -6
  96. package/dist/components/composition-menu-items.js +191 -75
  97. package/dist/components/get-open-in-menu-items.d.ts +6 -5
  98. package/dist/components/get-open-in-menu-items.js +15 -9
  99. package/dist/components/selected-outline-order.js +18 -12
  100. package/dist/components/use-open-in-menu-apps.d.ts +14 -0
  101. package/dist/components/use-open-in-menu-apps.js +33 -0
  102. package/dist/error-overlay/remotion-overlay/ErrorDisplay.js +2 -2
  103. package/dist/error-overlay/remotion-overlay/OpenInEditor.d.ts +1 -0
  104. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +3 -3
  105. package/dist/error-overlay/remotion-overlay/StackFrame.d.ts +5 -1
  106. package/dist/error-overlay/remotion-overlay/StackFrame.js +26 -19
  107. package/dist/esm/{LazyModels-gfmpcy4h.mjs → LazyModels-mtggyjye.mjs} +3 -3
  108. package/dist/esm/{LazyModels-m1rf06wh.mjs → LazyModels-nk7py0zt.mjs} +3 -3
  109. package/dist/esm/{TranscriptionModal-8pvrehg4.mjs → TranscriptionModal-ymnx1c7m.mjs} +6 -6
  110. package/dist/esm/{VideoMattingModal-fefbzgka.mjs → VideoMattingModal-05vpczks.mjs} +6 -6
  111. package/dist/esm/{index-s848rffx.mjs → index-0gewwxse.mjs} +5330 -4668
  112. package/dist/esm/{index-tzxb8808.mjs → index-4dsz9035.mjs} +8 -8
  113. package/dist/esm/{index-hbezgbbq.mjs → index-5bfxbpca.mjs} +1 -1
  114. package/dist/esm/{index-vsxrxfpj.mjs → index-5gd8k9yv.mjs} +1 -1
  115. package/dist/esm/{index-ggqpre9v.mjs → index-bs39wngg.mjs} +4216 -3571
  116. package/dist/esm/{index-0x13f28h.mjs → index-cdy8v54v.mjs} +1 -1
  117. package/dist/esm/{index-41kqns5c.mjs → index-eb5txqp6.mjs} +8 -7
  118. package/dist/esm/{index-1089795y.mjs → index-f97r9e2g.mjs} +4 -21
  119. package/dist/esm/{index-jrw61pkj.mjs → index-g7k2dvar.mjs} +1 -1
  120. package/dist/esm/{index-mww32xc8.mjs → index-x40wwfmt.mjs} +3 -3
  121. package/dist/esm/index.mjs +12 -6
  122. package/dist/esm/internals.mjs +7 -7
  123. package/dist/esm/previewEntry.mjs +7 -7
  124. package/dist/helpers/client-id.d.ts +1 -0
  125. package/dist/helpers/client-id.js +8 -4
  126. package/dist/helpers/cube-lut.d.ts +12 -0
  127. package/dist/helpers/cube-lut.js +160 -0
  128. package/dist/helpers/get-preview-file-type.d.ts +1 -1
  129. package/dist/helpers/get-preview-file-type.js +3 -0
  130. package/dist/helpers/open-in-editor.d.ts +5 -2
  131. package/dist/helpers/open-in-editor.js +12 -4
  132. package/dist/helpers/settings-tab-availability.d.ts +14 -0
  133. package/dist/helpers/settings-tab-availability.js +35 -0
  134. package/dist/helpers/use-menu-structure.js +16 -12
  135. package/dist/icons/lut.d.ts +4 -0
  136. package/dist/icons/lut.js +6 -0
  137. package/dist/icons/sparkles.d.ts +4 -0
  138. package/dist/icons/sparkles.js +6 -0
  139. package/dist/state/modals.d.ts +12 -2
  140. package/package.json +19 -19
  141. package/dist/error-overlay/remotion-overlay/CodeFrame.js +0 -62
@@ -14,6 +14,7 @@ const pointer_session_1 = require("../../helpers/pointer-session");
14
14
  const timeline_layout_1 = require("../../helpers/timeline-layout");
15
15
  const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
16
16
  const use_keybinding_1 = require("../../helpers/use-keybinding");
17
+ const use_sync_external_store_1 = require("../../helpers/use-sync-external-store");
17
18
  const z_index_1 = require("../../state/z-index");
18
19
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
19
20
  const options_sidebar_tabs_1 = require("../options-sidebar-tabs");
@@ -225,6 +226,7 @@ const defaultTimelineSelectionContextValue = {
225
226
  clearSelection: () => undefined,
226
227
  };
227
228
  const TimelineSelectionContext = (0, react_1.createContext)(defaultTimelineSelectionContextValue);
229
+ const TimelineRowSelectionContext = (0, react_1.createContext)(null);
228
230
  const EMPTY_SELECTABLE_TIMELINE_ITEMS = [];
229
231
  const SelectableTimelineItemsContext = (0, react_1.createContext)({ current: EMPTY_SELECTABLE_TIMELINE_ITEMS });
230
232
  const TimelineSelectionOrderProvider = ({ children, items }) => {
@@ -561,6 +563,9 @@ const TimelineSelectionProvider = ({ children }) => {
561
563
  ? selectionState
562
564
  : exports.EMPTY_TIMELINE_SELECTION_STATE;
563
565
  const availableSelectedItems = availableSelectionState.selectedItems;
566
+ const getAvailableSelectionState = (0, react_1.useCallback)(() => selectionScope.current === timelineSelectionScope
567
+ ? selectionController.getSnapshot()
568
+ : exports.EMPTY_TIMELINE_SELECTION_STATE, [selectionController, timelineSelectionScope]);
564
569
  const requestRevealSelectionItem = (0, react_1.useCallback)((item) => {
565
570
  setRevealRequest((previousRequest) => {
566
571
  var _a;
@@ -790,9 +795,24 @@ const TimelineSelectionProvider = ({ children }) => {
790
795
  ]);
791
796
  const currentSelection = (0, react_1.useRef)(value);
792
797
  currentSelection.current = value;
793
- return (jsx_runtime_1.jsx(CurrentTimelineSelectionContext.Provider, { value: currentSelection, children: jsx_runtime_1.jsxs(TimelineSelectionContext.Provider, { value: value, children: [children, jsx_runtime_1.jsx(TimelineEscapeKeybindings, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
794
- jsx_runtime_1.jsx(TimelineClipboardKeybindings_1.TimelineClipboardKeybindings, {}), jsx_runtime_1.jsx(TimelineDeleteKeybindings_1.TimelineDeleteKeybindings, {})
795
- ] })) : null] }) }));
798
+ const rowSelectionContextValue = (0, react_1.useMemo)(() => ({
799
+ canSelect,
800
+ clearSelection,
801
+ getSnapshot: getAvailableSelectionState,
802
+ registerMarqueeSelectableItem,
803
+ selectItem,
804
+ subscribe: selectionController.subscribe,
805
+ }), [
806
+ canSelect,
807
+ clearSelection,
808
+ getAvailableSelectionState,
809
+ registerMarqueeSelectableItem,
810
+ selectItem,
811
+ selectionController.subscribe,
812
+ ]);
813
+ return (jsx_runtime_1.jsx(CurrentTimelineSelectionContext.Provider, { value: currentSelection, children: jsx_runtime_1.jsx(TimelineRowSelectionContext.Provider, { value: rowSelectionContextValue, children: jsx_runtime_1.jsxs(TimelineSelectionContext.Provider, { value: value, children: [children, jsx_runtime_1.jsx(TimelineEscapeKeybindings, {}), (0, interactivity_enabled_1.isStudioInteractivityEnabled)() ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
814
+ jsx_runtime_1.jsx(TimelineClipboardKeybindings_1.TimelineClipboardKeybindings, {}), jsx_runtime_1.jsx(TimelineDeleteKeybindings_1.TimelineDeleteKeybindings, {})
815
+ ] })) : null] }) }) }));
796
816
  };
797
817
  exports.TimelineSelectionProvider = TimelineSelectionProvider;
798
818
  const useTimelineSelection = () => {
@@ -974,7 +994,11 @@ const useTimelineMarqueeSelection = () => {
974
994
  };
975
995
  exports.useTimelineMarqueeSelection = useTimelineMarqueeSelection;
976
996
  const useTimelineMarqueeSelectableItem = (item, ref) => {
977
- const { registerMarqueeSelectableItem } = (0, exports.useTimelineSelection)();
997
+ const selectionContext = (0, react_1.useContext)(TimelineRowSelectionContext);
998
+ if (selectionContext === null) {
999
+ throw new Error('useTimelineMarqueeSelectableItem must be used inside TimelineSelectionProvider');
1000
+ }
1001
+ const { registerMarqueeSelectableItem } = selectionContext;
978
1002
  (0, react_1.useEffect)(() => {
979
1003
  if (item === null) {
980
1004
  return;
@@ -988,47 +1012,68 @@ const useTimelineMarqueeSelectableItem = (item, ref) => {
988
1012
  };
989
1013
  exports.useTimelineMarqueeSelectableItem = useTimelineMarqueeSelectableItem;
990
1014
  const useTimelineRowSelection = (nodePathInfo, revealInInspector = false) => {
991
- const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
992
- const selectableTimelineItemsRef = (0, react_1.useContext)(SelectableTimelineItemsContext);
993
1015
  const selectionItem = (0, react_1.useMemo)(() => (0, exports.getTimelineSelectionFromNodePathInfo)(nodePathInfo), [nodePathInfo]);
994
- const selected = selectionItem === null ? false : isSelected(selectionItem);
1016
+ return useTimelineSelectionItem({
1017
+ revealInInspector,
1018
+ selectionItem,
1019
+ useSelectionOrder: true,
1020
+ });
1021
+ };
1022
+ exports.useTimelineRowSelection = useTimelineRowSelection;
1023
+ const useTimelineSelectionItem = ({ revealInInspector, selectionItem, useSelectionOrder, }) => {
1024
+ var _a;
1025
+ const selectionContext = (0, react_1.useContext)(TimelineRowSelectionContext);
1026
+ if (selectionContext === null) {
1027
+ throw new Error('useTimelineSelectionItem must be used inside TimelineSelectionProvider');
1028
+ }
1029
+ const selectableTimelineItemsRef = (0, react_1.useContext)(SelectableTimelineItemsContext);
1030
+ const selectionItemKey = (0, react_1.useMemo)(() => selectionItem === null ? null : (0, exports.getTimelineSelectionKey)(selectionItem), [selectionItem]);
1031
+ const getSelectedState = (0, react_1.useCallback)(() => {
1032
+ if (selectionItemKey === null) {
1033
+ return null;
1034
+ }
1035
+ const snapshot = selectionContext.getSnapshot();
1036
+ return snapshot.selectedItems.some((item) => (0, exports.getTimelineSelectionKey)(item) === selectionItemKey)
1037
+ ? snapshot
1038
+ : null;
1039
+ }, [selectionContext, selectionItemKey]);
1040
+ const selectedState = (0, use_sync_external_store_1.useSyncExternalStore)(selectionContext.subscribe, getSelectedState, getSelectedState);
995
1041
  const onSelect = (0, react_1.useCallback)((interaction) => {
996
1042
  if (selectionItem === null) {
997
1043
  return;
998
1044
  }
999
- selectItem(selectionItem, interaction, selectableTimelineItemsRef.current, { revealInInspector });
1000
- }, [revealInInspector, selectItem, selectableTimelineItemsRef, selectionItem]);
1045
+ selectionContext.selectItem(selectionItem, interaction, useSelectionOrder ? selectableTimelineItemsRef.current : undefined, { revealInInspector });
1046
+ }, [
1047
+ revealInInspector,
1048
+ selectableTimelineItemsRef,
1049
+ selectionContext,
1050
+ selectionItem,
1051
+ useSelectionOrder,
1052
+ ]);
1001
1053
  return {
1054
+ clearSelection: selectionContext.clearSelection,
1002
1055
  onSelect,
1003
- selectable: canSelect && selectionItem !== null,
1056
+ selectable: selectionContext.canSelect && selectionItem !== null,
1057
+ selectedItems: (_a = selectedState === null || selectedState === void 0 ? void 0 : selectedState.selectedItems) !== null && _a !== void 0 ? _a : exports.EMPTY_TIMELINE_SELECTION_STATE.selectedItems,
1058
+ selectItem: selectionContext.selectItem,
1004
1059
  selectionItem,
1005
- selected,
1060
+ selected: selectedState !== null,
1006
1061
  };
1007
1062
  };
1008
- exports.useTimelineRowSelection = useTimelineRowSelection;
1009
1063
  const useTimelineKeyframeSelection = (nodePathInfo, frame) => {
1010
- const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
1011
- const selectableTimelineItemsRef = (0, react_1.useContext)(SelectableTimelineItemsContext);
1012
1064
  const selectionItem = (0, react_1.useMemo)(() => ({
1013
1065
  type: 'keyframe',
1014
1066
  nodePathInfo,
1015
1067
  frame,
1016
1068
  }), [nodePathInfo, frame]);
1017
- const selected = isSelected(selectionItem);
1018
- const onSelect = (0, react_1.useCallback)((interaction) => {
1019
- selectItem(selectionItem, interaction, selectableTimelineItemsRef.current);
1020
- }, [selectItem, selectableTimelineItemsRef, selectionItem]);
1021
- return {
1022
- onSelect,
1023
- selectable: canSelect,
1069
+ return useTimelineSelectionItem({
1070
+ revealInInspector: false,
1024
1071
  selectionItem,
1025
- selected,
1026
- };
1072
+ useSelectionOrder: true,
1073
+ });
1027
1074
  };
1028
1075
  exports.useTimelineKeyframeSelection = useTimelineKeyframeSelection;
1029
1076
  const useTimelineEasingSelection = ({ nodePathInfo, fromFrame, toFrame, segmentIndex, }) => {
1030
- const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
1031
- const selectableTimelineItemsRef = (0, react_1.useContext)(SelectableTimelineItemsContext);
1032
1077
  const selectionItem = (0, react_1.useMemo)(() => ({
1033
1078
  type: 'easing',
1034
1079
  nodePathInfo,
@@ -1036,43 +1081,40 @@ const useTimelineEasingSelection = ({ nodePathInfo, fromFrame, toFrame, segmentI
1036
1081
  toFrame,
1037
1082
  segmentIndex,
1038
1083
  }), [nodePathInfo, fromFrame, segmentIndex, toFrame]);
1039
- const selected = isSelected(selectionItem);
1040
- const onSelect = (0, react_1.useCallback)((interaction) => {
1041
- selectItem(selectionItem, interaction, selectableTimelineItemsRef.current);
1042
- }, [selectItem, selectableTimelineItemsRef, selectionItem]);
1043
- return {
1044
- onSelect,
1045
- selectable: canSelect,
1046
- selected,
1084
+ return useTimelineSelectionItem({
1085
+ revealInInspector: false,
1047
1086
  selectionItem,
1048
- };
1087
+ useSelectionOrder: true,
1088
+ });
1049
1089
  };
1050
1090
  exports.useTimelineEasingSelection = useTimelineEasingSelection;
1051
1091
  const useTimelineGuideSelection = (guideId) => {
1052
- const { canSelect, clearSelection, isSelected, selectItem } = (0, exports.useTimelineSelection)();
1053
1092
  const selectionItem = (0, react_1.useMemo)(() => ({
1054
1093
  type: 'guide',
1055
1094
  guideId,
1056
1095
  }), [guideId]);
1057
- const selected = isSelected(selectionItem);
1058
- const onSelect = (0, react_1.useCallback)(() => {
1059
- selectItem(selectionItem);
1060
- }, [selectItem, selectionItem]);
1061
- return {
1062
- clearSelection,
1063
- onSelect,
1064
- selectable: canSelect,
1065
- selected,
1096
+ return useTimelineSelectionItem({
1097
+ revealInInspector: false,
1066
1098
  selectionItem,
1067
- };
1099
+ useSelectionOrder: false,
1100
+ });
1068
1101
  };
1069
1102
  exports.useTimelineGuideSelection = useTimelineGuideSelection;
1070
1103
  const useTimelineRowContainsSelection = (nodePathInfo) => {
1071
- const { containsSelection } = (0, exports.useTimelineSelection)();
1072
- if (nodePathInfo === null) {
1073
- return false;
1104
+ const selectionContext = (0, react_1.useContext)(TimelineRowSelectionContext);
1105
+ if (selectionContext === null) {
1106
+ throw new Error('useTimelineRowContainsSelection must be used inside TimelineSelectionProvider');
1074
1107
  }
1075
- return containsSelection(nodePathInfo);
1108
+ const getContainsSelection = (0, react_1.useCallback)(() => {
1109
+ if (nodePathInfo === null) {
1110
+ return false;
1111
+ }
1112
+ return selectionContext
1113
+ .getSnapshot()
1114
+ .selectedItems.some((selected) => selected.type !== 'guide' &&
1115
+ nodePathDescendsFrom(selected.nodePathInfo, nodePathInfo));
1116
+ }, [nodePathInfo, selectionContext]);
1117
+ return (0, use_sync_external_store_1.useSyncExternalStore)(selectionContext.subscribe, getContainsSelection, getContainsSelection);
1076
1118
  };
1077
1119
  exports.useTimelineRowContainsSelection = useTimelineRowContainsSelection;
1078
1120
  const useTimelineRowHighlightBackground = (nodePathInfo, { hovered, selectedBackground, }) => {
@@ -304,8 +304,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
304
304
  const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
305
305
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
306
306
  const deleteTimelineItems = (0, use_delete_timeline_items_1.useDeleteTimelineItems)();
307
- const { onSelect, selectable, selected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
308
- const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
307
+ const { onSelect, selectable, selected, selectedItems } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
309
308
  const selectedSequenceNodePathInfos = (0, react_1.useMemo)(() => {
310
309
  if (!selected ||
311
310
  selectedItems.length < 2 ||
@@ -462,6 +461,7 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
462
461
  assetLinkInfo: mediaSrc ? (0, timeline_asset_link_1.getTimelineAssetLinkInfo)(mediaSrc) : null,
463
462
  canOpenInEditor,
464
463
  codingAgentInfo,
464
+ copyImageElement: null,
465
465
  deleteDisabled,
466
466
  disableInteractivityDisabled,
467
467
  duplicateDisabled,
@@ -10,4 +10,6 @@ export declare const TimelineSequenceItem: React.NamedExoticComponent<{
10
10
  readonly keyframeDisplayOffset: number;
11
11
  readonly sequenceFrameOffset: number;
12
12
  readonly siblingIndex: number;
13
+ readonly numberOfHiddenDuplicates: number;
14
+ readonly showProvisionalVisibilityToggle: boolean;
13
15
  }>;
@@ -106,11 +106,12 @@ const effectDropHighlight = {
106
106
  outline: colors_1.BORDER_TIMELINE_DROP_BLUE,
107
107
  outlineOffset: -1,
108
108
  };
109
- const TimelineSequenceExpandArrowInner = ({ disabled, isExpanded, nodePathInfo, sequence }) => {
109
+ const TimelineSequenceExpandArrowInner = ({ disabled, isExpanded, nodePathInfo, selectedItems, sequence }) => {
110
110
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
111
111
  const hasExpandableContent = (0, use_timeline_expanded_tree_1.useTimelineSequenceHasExpandableContent)({
112
112
  sequence,
113
113
  nodePathInfo,
114
+ selectedItems,
114
115
  });
115
116
  const onToggleExpand = (0, react_1.useCallback)(() => toggleTrack(nodePathInfo), [nodePathInfo, toggleTrack]);
116
117
  if (!hasExpandableContent) {
@@ -122,6 +123,7 @@ const areTimelineSequenceExpandArrowPropsEqual = (first, second) => {
122
123
  var _a, _b, _c, _d;
123
124
  return (first.disabled === second.disabled &&
124
125
  first.isExpanded === second.isExpanded &&
126
+ first.selectedItems === second.selectedItems &&
125
127
  ((_a = first.sequence.controls) === null || _a === void 0 ? void 0 : _a.schema) === ((_b = second.sequence.controls) === null || _b === void 0 ? void 0 : _b.schema) &&
126
128
  ((_c = first.sequence.controls) === null || _c === void 0 ? void 0 : _c.runtimeValues) ===
127
129
  ((_d = second.sequence.controls) === null || _d === void 0 ? void 0 : _d.runtimeValues) &&
@@ -169,9 +171,9 @@ const getSequencePointerDropTargetAtPoint = ({ clientX, clientY, }) => {
169
171
  return null;
170
172
  };
171
173
  const SEQUENCE_REORDER_POINTER_THRESHOLD = 3;
172
- const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, siblingIndex, }) => {
174
+ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions, nestedDepth, sequence, nodePathInfo, keyframeDisplayOffset, sequenceFrameOffset, siblingIndex, numberOfHiddenDuplicates, showProvisionalVisibilityToggle, }) => {
173
175
  var _a, _b;
174
- var _c, _d, _e, _f;
176
+ var _c, _d, _e;
175
177
  const nodePath = (_c = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _c !== void 0 ? _c : null;
176
178
  const { hovered, onPointerEnter, onPointerLeave } = (0, timeline_sequence_hover_1.useTimelineSequenceHover)(nodePathInfo);
177
179
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
@@ -187,8 +189,7 @@ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions,
187
189
  const assetContextMenu = (0, use_asset_timeline_context_menu_1.useAssetTimelineContextMenu)();
188
190
  const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
189
191
  const deleteTimelineItems = (0, use_delete_timeline_items_1.useDeleteTimelineItems)();
190
- const { onSelect, selectable, selected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
191
- const { selectItem, selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
192
+ const { onSelect, selectable, selected, selectedItems, selectItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
192
193
  const selectedSequenceNodePathInfos = (0, react_1.useMemo)(() => {
193
194
  if (!selected ||
194
195
  selectedItems.length < 2 ||
@@ -229,17 +230,16 @@ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions,
229
230
  const timelineDisplayName = sequence.displayName === '' && connectedCompositions.length === 1
230
231
  ? connectedCompositions[0].id
231
232
  : displayName;
232
- const numberOfHiddenDuplicates = Math.max(0, ((_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.numberOfSequencesWithThisNodePath) !== null && _d !== void 0 ? _d : 1) - 1);
233
233
  const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
234
234
  const nodePathKey = (0, react_1.useMemo)(() => nodePath ? remotion_1.Internals.makeSequencePropsSubscriptionKey(nodePath) : null, [nodePath]);
235
- const parentId = (_e = sequence.parent) !== null && _e !== void 0 ? _e : null;
235
+ const parentId = (_d = sequence.parent) !== null && _d !== void 0 ? _d : null;
236
236
  const canReorderSequence = previewInteractive &&
237
237
  Boolean(nodePath && nodePathKey && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source)) &&
238
238
  (nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.numberOfSequencesWithThisNodePath) === 1;
239
239
  const canHandleSequenceDrag = previewInteractive;
240
240
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
241
241
  const deleteDisabled = (0, react_1.useMemo)(() => !previewInteractive || !sequence.controls || !canDeleteFromSource, [previewInteractive, sequence.controls, canDeleteFromSource]);
242
- const isProgrammaticallyDuplicated = ((_f = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.numberOfSequencesWithThisNodePath) !== null && _f !== void 0 ? _f : 1) > 1;
242
+ const isProgrammaticallyDuplicated = ((_e = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.numberOfSequencesWithThisNodePath) !== null && _e !== void 0 ? _e : 1) > 1;
243
243
  const duplicateDisabled = deleteDisabled || isProgrammaticallyDuplicated;
244
244
  const disableInteractivityDisabled = !previewInteractive ||
245
245
  !sequence.showInTimeline ||
@@ -641,6 +641,8 @@ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions,
641
641
  codeHiddenStatus !== undefined &&
642
642
  codeHiddenStatus !== null &&
643
643
  codeHiddenStatus.status === 'static';
644
+ const showVisibilityToggle = canToggleVisibility ||
645
+ (previewInteractive && showProvisionalVisibilityToggle);
644
646
  const onSequenceDoubleClick = (0, react_1.useCallback)((e) => {
645
647
  if ((0, TimelineSelection_1.isTimelineSelectionModifierEvent)(e)) {
646
648
  e.stopPropagation();
@@ -704,7 +706,8 @@ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions,
704
706
  return;
705
707
  }
706
708
  if (document.activeElement instanceof HTMLInputElement ||
707
- document.activeElement instanceof HTMLTextAreaElement) {
709
+ document.activeElement instanceof HTMLTextAreaElement ||
710
+ document.activeElement instanceof HTMLButtonElement) {
708
711
  return;
709
712
  }
710
713
  e.preventDefault();
@@ -831,6 +834,7 @@ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions,
831
834
  assetLinkInfo: mediaSrc ? (0, timeline_asset_link_1.getTimelineAssetLinkInfo)(mediaSrc) : null,
832
835
  canOpenInEditor,
833
836
  codingAgentInfo,
837
+ copyImageElement: null,
834
838
  deleteDisabled,
835
839
  disableInteractivityDisabled,
836
840
  duplicateDisabled,
@@ -1034,12 +1038,12 @@ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions,
1034
1038
  clientId: previewServerState.clientId,
1035
1039
  });
1036
1040
  }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
1037
- const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineLayerChildren_1.TimelineLayerChildrenToggle, { sequence: sequence }), style: rowStyle, selected: selected, selectable: selectable, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, hovered: hovered, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1041
+ const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: showVisibilityToggle ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: canToggleVisibility ? onToggleVisibility : null })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: jsx_runtime_1.jsx(TimelineLayerChildren_1.TimelineLayerChildrenToggle, { sequence: sequence }), style: rowStyle, selected: selected, selectable: selectable, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, hovered: hovered, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, onPointerEnter: onPointerEnter, onPointerLeave: onPointerLeave, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [connectedCompositions.length > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1038
1042
  jsx_runtime_1.jsx(CompositionOrStillIcon_1.CompositionOrStillIcon, { color: (0, TimelineSelection_1.getTimelineColor)(false, false), composition: connectedCompositions[0], style: connectedCompositionIconStyle }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 })
1039
- ] })) : null, jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: timelineDisplayName, fallbackDisplayName: fallbackDisplayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1040
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewInteractive, isExpanded: isExpanded, nodePathInfo: nodePathInfo, sequence: sequence })
1041
- ] })) : null, numberOfHiddenDuplicates > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1043
+ ] })) : null, jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: timelineDisplayName, fallbackDisplayName: fallbackDisplayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), numberOfHiddenDuplicates > 0 ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1042
1044
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineDuplicateCount_1.TimelineDuplicateCount, { count: numberOfHiddenDuplicates })
1045
+ ] })) : null, hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1046
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewInteractive, isExpanded: isExpanded, nodePathInfo: nodePathInfo, selectedItems: selectedItems, sequence: sequence })
1043
1047
  ] })) : null, mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1044
1048
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }),
1045
1049
  " ",
@@ -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 {};
@@ -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,6 +1,6 @@
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
6
  const get_git_menu_item_1 = require("../../helpers/get-git-menu-item");
@@ -28,6 +28,74 @@ const normalizeMenuDividers = (items) => {
28
28
  return normalized;
29
29
  };
30
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
+ };
31
99
  const getMultiSequenceContextMenuItems = ({ deleteDisabled, duplicateDisabled, onDeleteSelectedSequences, onDuplicateSelectedSequences, }) => {
32
100
  return [
33
101
  {
@@ -61,9 +129,9 @@ const getMultiSequenceContextMenuItems = ({ deleteDisabled, duplicateDisabled, o
61
129
  ];
62
130
  };
63
131
  exports.getMultiSequenceContextMenuItems = getMultiSequenceContextMenuItems;
64
- 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 = [], }) => {
65
133
  var _a, _b, _c;
66
- var _d, _e, _f;
134
+ var _d, _e;
67
135
  const isInteractiveSvg = ((_a = sequence.controls) === null || _a === void 0 ? void 0 : _a.componentIdentity) === interactiveSvgComponentIdentity;
68
136
  const installedEditors = (_d = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors) !== null && _d !== void 0 ? _d : [];
69
137
  const defaultEditorId = (0, use_default_editor_info_1.getPreferredEditorId)(editorInfo);
@@ -74,7 +142,7 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
74
142
  ? (0, get_git_menu_item_1.getGitSourceName)(window.remotion_gitSource)
75
143
  : null;
76
144
  const defaultOpenInName = defaultOpenInTarget === 'editor' ? editorName : gitSourceName;
77
- const defaultCodingAgent = codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents.find((codingAgent) => codingAgent.id === codingAgentInfo.defaultCodingAgent);
145
+ const copyImageLabel = copyImageElement && sequence.type === 'image' ? 'Copy image' : 'Copy frame';
78
146
  const contextForAgents = (0, format_file_location_1.formatContextForAgents)({
79
147
  location: originalLocation,
80
148
  name: sequence.displayName || ((_b = sequence.controls) === null || _b === void 0 ? void 0 : _b.componentName) || null,
@@ -83,31 +151,34 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
83
151
  const openInCodingAgentWithContext = (codingAgentId, codingAgentName) => {
84
152
  openInCodingAgent(codingAgentId, codingAgentName, codingAgentId === 'copilot' ? null : contextForAgents);
85
153
  };
86
- const openInMenuItems = onConfigureApps
87
- ? (0, get_open_in_menu_items_1.getOpenInMenuItems)({
88
- codingAgentInfo,
89
- editorDisabled: !canOpenInEditor || !originalLocation,
90
- editorInfo,
91
- excludeCodingAgentId: (_f = defaultCodingAgent === null || defaultCodingAgent === void 0 ? void 0 : defaultCodingAgent.id) !== null && _f !== void 0 ? _f : null,
92
- excludeEditorId: defaultEditorId,
93
- fileManagerDisabled: !(originalLocation === null || originalLocation === void 0 ? void 0 : originalLocation.source),
94
- folder: false,
95
- location: originalLocation,
96
- onConfigureApps,
97
- onOpenInCodingAgent: openInCodingAgentWithContext,
98
- onOpenInEditor: openInEditor,
99
- onOpenInFileExplorer: () => {
100
- if (!(originalLocation === null || originalLocation === void 0 ? void 0 : originalLocation.source)) {
101
- return;
102
- }
103
- (0, actions_1.openInFileExplorer)({ directory: originalLocation.source }).catch((err) => {
104
- (0, NotificationCenter_1.showNotification)(`Could not open file: ${err.message}`, 2000);
105
- });
106
- },
107
- onOpenInGitClient: () => undefined,
108
- onOpenInTerminal: null,
109
- })
110
- : [];
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;
171
+ }
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
+ });
111
182
  const items = [
112
183
  defaultOpenInTarget && defaultOpenInName
113
184
  ? {
@@ -133,21 +204,7 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
133
204
  : 'open-in-git-source',
134
205
  }
135
206
  : null,
136
- defaultCodingAgent
137
- ? {
138
- type: 'item',
139
- id: 'open-in-default-coding-agent',
140
- keyHint: null,
141
- label: `Open in ${defaultCodingAgent.nameWithType}`,
142
- leftItem: null,
143
- disabled: false,
144
- onClick: () => openInCodingAgentWithContext(defaultCodingAgent.id, defaultCodingAgent.nameWithType),
145
- quickSwitcherLabel: null,
146
- subMenu: null,
147
- value: 'open-in-default-coding-agent',
148
- }
149
- : null,
150
- onConfigureApps
207
+ openInMenuItems.length > 0
151
208
  ? {
152
209
  type: 'item',
153
210
  id: 'open-in-another-app',
@@ -182,7 +239,35 @@ const getSequenceContextMenuItems = ({ assetLinkInfo, canOpenInEditor, deleteDis
182
239
  value: 'show-asset',
183
240
  }
184
241
  : null,
185
- 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
186
271
  ? {
187
272
  type: 'divider',
188
273
  id: 'sequence-link-divider',
@@ -0,0 +1 @@
1
+ export declare const normalizeFontWeightForKeyframe: (value: unknown) => number | null;