@remotion/studio 4.0.520 → 4.0.521

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 (70) hide show
  1. package/dist/api/shut-down-studio.d.ts +6 -0
  2. package/dist/api/shut-down-studio.js +23 -0
  3. package/dist/components/AudioWaveform.js +10 -6
  4. package/dist/components/Canvas.js +84 -12
  5. package/dist/components/CaptionInspector.d.ts +1 -0
  6. package/dist/components/CaptionInspector.js +43 -2
  7. package/dist/components/CaptionTextEditor.js +1 -1
  8. package/dist/components/CompositionSelector.js +41 -30
  9. package/dist/components/CompositionSelectorItem.d.ts +7 -0
  10. package/dist/components/CompositionSelectorItem.js +343 -67
  11. package/dist/components/ElementInstallConfirmation.js +74 -64
  12. package/dist/components/ElementLibraryModal.js +3 -1
  13. package/dist/components/InlineCaptionInspector.js +37 -1
  14. package/dist/components/InspectorPanel/ElementLibraryButton.js +3 -18
  15. package/dist/components/InspectorSequenceSection.js +1 -4
  16. package/dist/components/Menu/MenuSubItem.js +1 -1
  17. package/dist/components/ModalContainer.d.ts +1 -0
  18. package/dist/components/ModalContainer.js +2 -2
  19. package/dist/components/ModalHeader.js +5 -1
  20. package/dist/components/QuickSwitcher/asset-search.d.ts +0 -1
  21. package/dist/components/QuickSwitcher/asset-search.js +1 -16
  22. package/dist/components/RenderButton.js +2 -2
  23. package/dist/components/RenderModal/RenderStatusModal.js +7 -1
  24. package/dist/components/RenderModal/ServerRenderModal.js +1 -1
  25. package/dist/components/RenderModal/WebRenderModal.js +1 -1
  26. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +1 -1
  27. package/dist/components/SettingsModal.js +8 -5
  28. package/dist/components/TimeValue.js +36 -7
  29. package/dist/components/Timeline/Timeline.d.ts +1 -1
  30. package/dist/components/Timeline/Timeline.js +31 -19
  31. package/dist/components/Timeline/TimelineAssetField.d.ts +0 -1
  32. package/dist/components/Timeline/TimelineAssetField.js +16 -9
  33. package/dist/components/Timeline/TimelineCollapseToggle.js +1 -1
  34. package/dist/components/Timeline/TimelineFontWeightField.d.ts +11 -0
  35. package/dist/components/Timeline/TimelineFontWeightField.js +65 -0
  36. package/dist/components/Timeline/TimelineLayerChildren.d.ts +21 -0
  37. package/dist/components/Timeline/TimelineLayerChildren.js +129 -0
  38. package/dist/components/Timeline/TimelineNumberField.js +13 -5
  39. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  40. package/dist/components/Timeline/TimelineSequence.js +38 -32
  41. package/dist/components/Timeline/TimelineSequenceItem.js +2 -1
  42. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +19 -7
  43. package/dist/components/Timeline/TimelineTickFormatProvider.d.ts +8 -0
  44. package/dist/components/Timeline/TimelineTickFormatProvider.js +16 -0
  45. package/dist/components/Timeline/TimelineTimeIndicators.js +7 -3
  46. package/dist/components/Timeline/TimelineVideoInfo.js +7 -3
  47. package/dist/components/Timeline/timeline-field-display-utils.js +1 -0
  48. package/dist/components/UpdateStatusContext.d.ts +5 -0
  49. package/dist/components/UpdateStatusContext.js +53 -2
  50. package/dist/components/UpdatesSettings.js +25 -4
  51. package/dist/components/WebMcp.js +26 -0
  52. package/dist/components/composition-selector-drag-data.d.ts +27 -0
  53. package/dist/components/composition-selector-drag-data.js +80 -0
  54. package/dist/components/import-assets.d.ts +2 -1
  55. package/dist/components/import-assets.js +11 -1
  56. package/dist/components/parse-caption-file.d.ts +5 -0
  57. package/dist/components/parse-caption-file.js +63 -0
  58. package/dist/esm/chunk-emw4k5b0.js +99527 -0
  59. package/dist/esm/{chunk-np6q13k5.js → chunk-vkrvnx2h.js} +5913 -4699
  60. package/dist/esm/index.mjs +23 -8
  61. package/dist/esm/internals.mjs +6729 -5366
  62. package/dist/esm/previewEntry.mjs +6779 -5416
  63. package/dist/esm/renderEntry.mjs +1 -1
  64. package/dist/helpers/get-preview-file-type.js +22 -3
  65. package/dist/helpers/inserted-element-selection.d.ts +2 -1
  66. package/dist/helpers/use-menu-structure.js +2 -2
  67. package/dist/index.d.ts +1 -0
  68. package/dist/index.js +3 -1
  69. package/dist/state/modals.d.ts +0 -2
  70. package/package.json +16 -16
@@ -115,7 +115,7 @@ const TimelineSequenceNegativeStartInner = ({ left, width, leftEdgeVisible, clip
115
115
  return (jsx_runtime_1.jsx("div", { style: outerStyle, children: jsx_runtime_1.jsx("div", { style: innerStyle }) }));
116
116
  };
117
117
  const TimelineSequenceNegativeStart = react_1.default.memo(TimelineSequenceNegativeStartInner);
118
- const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premount, postmount, negativeStart, leftEdgeVisible, negativeStartClipped, style, children, nodePathInfo, sequenceFrameOffset, fromCanUpdate, frozenFrame, onMoveDragPointerDown, onPointerDownCapture, onDoubleClick, }) => {
118
+ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premount, postmount, negativeStart, leftEdgeVisible, negativeStartClipped, style, children, edgeDragHandles, nodePathInfo, sequenceFrameOffset, fromCanUpdate, frozenFrame, onMoveDragPointerDown, onPointerDownCapture, onDoubleClick, }) => {
119
119
  var _a, _b, _c;
120
120
  const ref = (0, react_1.useRef)(null);
121
121
  const { onSelect, selectable, selected, selectionItem } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
@@ -197,31 +197,36 @@ const TimelineSequenceCurrentFrame = ({ s, displayDurationInFrames, premount, po
197
197
  display: 'flex',
198
198
  alignItems: 'center',
199
199
  }, children: jsx_runtime_1.jsx(TimelineSequenceFrame_1.TimelineSequenceFrame, { premounted: isPremounting, postmounted: isPostmounting ? s.duration - 1 : null, roundedFrame: roundedFrame, frozenFrame: frozenFrame }) })) : null] }));
200
- return (jsx_runtime_1.jsx("div", { ref: ref, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, style: actualStyle, title: s.displayName, onPointerDownCapture: onPointerDownCapture, onPointerDown: selectable ? onPointerDown : undefined, onDoubleClick: onDoubleClick, children: negativeStart ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
201
- jsx_runtime_1.jsx(TimelineSequenceNegativeStart, { left: negativeStart.left, width: negativeStart.width, leftEdgeVisible: leftEdgeVisible, clipped: negativeStartClipped }), jsx_runtime_1.jsx("div", { style: {
202
- background: style.background,
203
- border: style.border,
204
- borderBottomLeftRadius: 0,
205
- borderBottomRightRadius: style.borderBottomRightRadius,
206
- borderLeft: 'none',
207
- borderRightColor: style.borderRightColor,
208
- borderTopLeftRadius: 0,
209
- borderTopRightRadius: style.borderTopRightRadius,
210
- boxSizing: 'border-box',
211
- height: '100%',
212
- left: negativeStartEnd,
213
- overflow: 'hidden',
214
- position: 'absolute',
215
- top: 0,
216
- width: `calc(100% - ${negativeStartEnd}px)`,
217
- }, children: jsx_runtime_1.jsx("div", { style: {
200
+ return (jsx_runtime_1.jsxs("div", { ref: ref, [TimelineSelection_1.TIMELINE_MARQUEE_ITEM_ATTR]: true, style: actualStyle, title: s.displayName, onPointerDownCapture: onPointerDownCapture, onPointerDown: selectable ? onPointerDown : undefined, onDoubleClick: onDoubleClick, children: [negativeStart ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
201
+ jsx_runtime_1.jsx(TimelineSequenceNegativeStart, { left: negativeStart.left, width: negativeStart.width, leftEdgeVisible: leftEdgeVisible, clipped: negativeStartClipped }), jsx_runtime_1.jsx("div", { style: {
202
+ background: style.background,
203
+ border: style.border,
204
+ borderBottomLeftRadius: 0,
205
+ borderBottomRightRadius: style.borderBottomRightRadius,
206
+ borderLeft: 'none',
207
+ borderRightColor: style.borderRightColor,
208
+ borderTopLeftRadius: 0,
209
+ borderTopRightRadius: style.borderTopRightRadius,
210
+ boxSizing: 'border-box',
218
211
  height: '100%',
219
- left: -negativeStartEnd,
212
+ left: negativeStartEnd,
213
+ overflow: 'hidden',
220
214
  position: 'absolute',
221
215
  top: 0,
222
- width: style.width,
223
- }, children: content }) })
224
- ] })) : (content) }));
216
+ width: `calc(100% - ${negativeStartEnd}px)`,
217
+ }, children: jsx_runtime_1.jsx("div", { style: {
218
+ height: '100%',
219
+ left: -negativeStartEnd,
220
+ position: 'absolute',
221
+ top: 0,
222
+ width: style.width,
223
+ }, children: content }) })
224
+ ] })) : (jsx_runtime_1.jsx("div", { style: {
225
+ position: 'absolute',
226
+ inset: 0,
227
+ overflow: 'hidden',
228
+ borderRadius: 'inherit',
229
+ }, children: content })), edgeDragHandles] }));
225
230
  };
226
231
  const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePathInfo, sequenceFrameOffset, cascadedStart, localStart, }) => {
227
232
  // If a duration is 1, it is essentially a still and it should have width 0
@@ -569,7 +574,8 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
569
574
  marginLeft: (_a = visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.marginLeft) !== null && _a !== void 0 ? _a : 0,
570
575
  width: (_b = visibleLayout === null || visibleLayout === void 0 ? void 0 : visibleLayout.width) !== null && _b !== void 0 ? _b : 0,
571
576
  color: colors_1.WHITE,
572
- overflow: 'hidden',
577
+ // Edge handles extend outside the layer; media is clipped separately.
578
+ overflow: 'visible',
573
579
  };
574
580
  }, [negativeStartClipped, s.type, showLeftBorderRadius, visibleLayout]);
575
581
  const showRightEdgeDragHandle = (0, TimelineSequenceRightEdgeDragHandle_1.isTimelineSequenceDurationDraggable)(s) &&
@@ -592,14 +598,14 @@ const TimelineSequenceInner = ({ s, connectedCompositions, windowWidth, nodePath
592
598
  const mediaDisplayDurationInFrames = visibleLayout.media
593
599
  ? visibleLayout.media.width / frameIncrement
594
600
  : 0;
595
- const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premount: visibleLayout.premount, postmount: visibleLayout.postmount, negativeStart: visibleLayout.negativeStart, leftEdgeVisible: visibleLayout.leftEdgeVisible, negativeStartClipped: negativeStartClipped, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, onPointerDownCapture: dragAwareDoubleClick.beginPointerGesture, onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, children: [s.type === 'audio' && visibleLayout.media ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, muted: s.muted, visualizationWidth: visibleLayout.media.width, startFrom: s.startMediaFrom, durationInFrames: s.duration, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay }) })) : null, s.type === 'video' && visibleLayout.media ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: visibleLayout.media.width, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, playbackRate: s.playbackRate, volume: s.volume, muted: s.muted, doesVolumeChange: s.doesVolumeChange, marginLeft: visibleLayout.media.left, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame, extendLastFrame: extendVideoLastFrame })) : null, s.type === 'image' && visibleLayout.media ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, offsetInPixels: visibleLayout.media.offset }) })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes, fullWidth: width, visibleOffset: visibleLayout.cropLeft, visibleWidth: visibleLayout.width })), showLeftEdgeDragHandle &&
596
- visibleLayout.leftEdgeVisible &&
597
- negativeStartWidth === 0 &&
598
- nodePathInfo &&
599
- validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture })) : null, showRightEdgeDragHandle &&
600
- visibleLayout.rightEdgeVisible &&
601
- nodePathInfo &&
602
- validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_k = video.durationInFrames) !== null && _k !== void 0 ? _k : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture })) : null] }));
601
+ const sequence = (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premount: visibleLayout.premount, postmount: visibleLayout.postmount, negativeStart: visibleLayout.negativeStart, leftEdgeVisible: visibleLayout.leftEdgeVisible, negativeStartClipped: negativeStartClipped, style: style, nodePathInfo: nodePathInfo, sequenceFrameOffset: sequenceFrameOffset, fromCanUpdate: fromCanUpdate, frozenFrame: frozenFrame, onMoveDragPointerDown: onMoveDragPointerDown, onPointerDownCapture: dragAwareDoubleClick.beginPointerGesture, edgeDragHandles: jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showLeftEdgeDragHandle &&
602
+ visibleLayout.leftEdgeVisible &&
603
+ negativeStartWidth === 0 &&
604
+ nodePathInfo &&
605
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceLeftEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_j = video.durationInFrames) !== null && _j !== void 0 ? _j : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture })) : null, showRightEdgeDragHandle &&
606
+ visibleLayout.rightEdgeVisible &&
607
+ nodePathInfo &&
608
+ validatedLocation ? (jsx_runtime_1.jsx(TimelineSequenceRightEdgeDragHandle_1.TimelineSequenceRightEdgeDragHandle, { nodePathInfo: nodePathInfo, windowWidth: windowWidth, timelineDurationInFrames: (_k = video.durationInFrames) !== null && _k !== void 0 ? _k : 1, onDragEnd: dragAwareDoubleClick.endPointerGesture })) : null] }), onDoubleClick: canHandleSequenceDoubleClick ? onSequenceDoubleClick : undefined, children: [s.type === 'audio' && visibleLayout.media ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, muted: s.muted, visualizationWidth: visibleLayout.media.width, startFrom: s.startMediaFrom, durationInFrames: s.duration, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay }) })) : null, s.type === 'video' && visibleLayout.media ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: visibleLayout.media.width, displayOffsetInFrames: mediaDisplayOffsetInFrames, displayDurationInFrames: mediaDisplayDurationInFrames, startMediaFrom: s.startMediaFrom, mediaFrameAtSequenceZero: s.mediaFrameAtSequenceZero, sequenceFrameOffset: sequenceFrameOffset, playbackRate: s.playbackRate, volume: s.volume, muted: s.muted, doesVolumeChange: s.doesVolumeChange, marginLeft: visibleLayout.media.left, loopDisplay: s.loopDisplay, frozenMediaFrame: s.frozenMediaFrame, extendLastFrame: extendVideoLastFrame })) : null, s.type === 'image' && visibleLayout.media ? (jsx_runtime_1.jsx("div", { style: mediaVisualizationStyle, children: jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, offsetInPixels: visibleLayout.media.offset }) })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes, fullWidth: width, visibleOffset: visibleLayout.cropLeft, visibleWidth: visibleLayout.width }))] }));
603
609
  return previewConnected || window.remotion_isReadOnlyStudio ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { getItems: getContextMenuItems, children: sequence })) : (sequence);
604
610
  };
605
611
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
@@ -70,6 +70,7 @@ const timeline_asset_link_1 = require("./timeline-asset-link");
70
70
  const TimelineDuplicateCount_1 = require("./TimelineDuplicateCount");
71
71
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
72
72
  const TimelineExpandedSection_1 = require("./TimelineExpandedSection");
73
+ const TimelineLayerChildren_1 = require("./TimelineLayerChildren");
73
74
  const TimelineLayerEye_1 = require("./TimelineLayerEye");
74
75
  const TimelineMediaInfo_1 = require("./TimelineMediaInfo");
75
76
  const TimelineRowChrome_1 = require("./TimelineRowChrome");
@@ -923,7 +924,7 @@ const TimelineSequenceItemInner = ({ afterDropLineOffset, connectedCompositions,
923
924
  clientId: previewServerState.clientId,
924
925
  });
925
926
  }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
926
- 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(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {}), 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: [
927
+ 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: [
927
928
  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 })
928
929
  ] })) : 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: [
929
930
  jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewInteractive, isExpanded: isExpanded, nodePathInfo: nodePathInfo, sequence: sequence })
@@ -49,13 +49,15 @@ const editor_snapping_1 = require("../../state/editor-snapping");
49
49
  const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
50
50
  const save_sequence_prop_1 = require("./save-sequence-prop");
51
51
  const TimelineSelection_1 = require("./TimelineSelection");
52
- const HANDLE_WIDTH = 6;
52
+ const HANDLE_INSET = 6;
53
+ const HANDLE_OUTSET = 8;
53
54
  exports.timelineSequenceFromDragSnapThresholdPx = 10;
54
55
  const baseStyle = {
55
56
  position: 'absolute',
56
57
  top: 0,
57
58
  bottom: 0,
58
- width: HANDLE_WIDTH,
59
+ // Keep the middle half of narrow layers available for moving.
60
+ width: `calc(${HANDLE_OUTSET}px + min(${HANDLE_INSET}px, 25%))`,
59
61
  cursor: 'ew-resize',
60
62
  zIndex: 1,
61
63
  touchAction: 'none',
@@ -822,6 +824,8 @@ const TimelineSequenceLeftEdgeDragHandleInner = ({ nodePathInfo, windowWidth, ti
822
824
  if (!dragState || e.pointerId !== dragState.pointerId) {
823
825
  return;
824
826
  }
827
+ // Include the release position even if the final pointermove was skipped.
828
+ onMove(e);
825
829
  finishDrag(true);
826
830
  };
827
831
  const onCancel = (e) => {
@@ -840,7 +844,9 @@ const TimelineSequenceLeftEdgeDragHandleInner = ({ nodePathInfo, windowWidth, ti
840
844
  captureTarget: activeDragState.target,
841
845
  onMove,
842
846
  onEnd: (reason, endEvent) => {
843
- if ((reason === 'pointerup' || reason === 'buttons-released') &&
847
+ if ((reason === 'pointerup' ||
848
+ reason === 'buttons-released' ||
849
+ (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
844
850
  endEvent) {
845
851
  onUp(endEvent);
846
852
  }
@@ -855,7 +861,7 @@ const TimelineSequenceLeftEdgeDragHandleInner = ({ nodePathInfo, windowWidth, ti
855
861
  }, [dragging, finishDrag]);
856
862
  const style = {
857
863
  ...baseStyle,
858
- left: 0,
864
+ left: -HANDLE_OUTSET,
859
865
  background: colors_1.TRANSPARENT,
860
866
  };
861
867
  return (jsx_runtime_1.jsx("div", { role: "separator", "aria-orientation": "vertical", title: "Drag to trim start", style: style, onPointerDown: onPointerDown }));
@@ -1041,7 +1047,9 @@ const useTimelineSequenceFromDrag = ({ nodePathInfo, windowWidth, timelineDurati
1041
1047
  },
1042
1048
  onEnd: (reason, endEvent) => {
1043
1049
  stopPointerSessionRef.current = null;
1044
- finishDrag((reason === 'pointerup' || reason === 'buttons-released') &&
1050
+ finishDrag((reason === 'pointerup' ||
1051
+ reason === 'buttons-released' ||
1052
+ (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
1045
1053
  endEvent !== null);
1046
1054
  },
1047
1055
  });
@@ -1218,6 +1226,8 @@ const TimelineSequenceRightEdgeDragHandleInner = ({ nodePathInfo, windowWidth, t
1218
1226
  if (!dragState || e.pointerId !== dragState.pointerId) {
1219
1227
  return;
1220
1228
  }
1229
+ // Include the release position even if the final pointermove was skipped.
1230
+ onMove(e);
1221
1231
  finishDrag(true);
1222
1232
  };
1223
1233
  const onCancel = (e) => {
@@ -1236,7 +1246,9 @@ const TimelineSequenceRightEdgeDragHandleInner = ({ nodePathInfo, windowWidth, t
1236
1246
  captureTarget: activeDragState.target,
1237
1247
  onMove,
1238
1248
  onEnd: (reason, endEvent) => {
1239
- if ((reason === 'pointerup' || reason === 'buttons-released') &&
1249
+ if ((reason === 'pointerup' ||
1250
+ reason === 'buttons-released' ||
1251
+ (reason === 'lostpointercapture' && (endEvent === null || endEvent === void 0 ? void 0 : endEvent.buttons) === 0)) &&
1240
1252
  endEvent) {
1241
1253
  onUp(endEvent);
1242
1254
  }
@@ -1251,7 +1263,7 @@ const TimelineSequenceRightEdgeDragHandleInner = ({ nodePathInfo, windowWidth, t
1251
1263
  }, [dragging, finishDrag]);
1252
1264
  const style = {
1253
1265
  ...baseStyle,
1254
- right: 0,
1266
+ right: -HANDLE_OUTSET,
1255
1267
  background: colors_1.TRANSPARENT,
1256
1268
  };
1257
1269
  return (jsx_runtime_1.jsx("div", { role: "separator", "aria-orientation": "vertical", title: "Drag to change duration", style: style, onPointerDown: onPointerDown }));
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ export declare const TimelineTickFormatContext: React.Context<{
3
+ showFrames: boolean;
4
+ setShowFrames: React.Dispatch<React.SetStateAction<boolean>>;
5
+ }>;
6
+ export declare const TimelineTickFormatProvider: React.FC<{
7
+ readonly children: React.ReactNode;
8
+ }>;
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineTickFormatProvider = exports.TimelineTickFormatContext = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const STORAGE_KEY = 'remotion.timelineShowFrames';
7
+ exports.TimelineTickFormatContext = (0, react_1.createContext)({ showFrames: false, setShowFrames: () => undefined });
8
+ const TimelineTickFormatProvider = ({ children }) => {
9
+ const [showFrames, setShowFrames] = (0, react_1.useState)(() => localStorage.getItem(STORAGE_KEY) === 'true');
10
+ (0, react_1.useEffect)(() => {
11
+ localStorage.setItem(STORAGE_KEY, String(showFrames));
12
+ }, [showFrames]);
13
+ const value = (0, react_1.useMemo)(() => ({ showFrames, setShowFrames }), [showFrames]);
14
+ return (jsx_runtime_1.jsx(exports.TimelineTickFormatContext.Provider, { value: value, children: children }));
15
+ };
16
+ exports.TimelineTickFormatProvider = TimelineTickFormatProvider;
@@ -44,6 +44,7 @@ const TimeValue_1 = require("../TimeValue");
44
44
  const timeline_refs_1 = require("./timeline-refs");
45
45
  const timeline_scroll_logic_1 = require("./timeline-scroll-logic");
46
46
  const TimelineSelection_1 = require("./TimelineSelection");
47
+ const TimelineTickFormatProvider_1 = require("./TimelineTickFormatProvider");
47
48
  const TimelineWidthProvider_1 = require("./TimelineWidthProvider");
48
49
  exports.TIMELINE_TIME_INDICATOR_HEIGHT = 39;
49
50
  const container = {
@@ -190,6 +191,7 @@ const TimelineTimeIndicators = () => {
190
191
  exports.TimelineTimeIndicators = TimelineTimeIndicators;
191
192
  const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, durationInFrames, fps }) => {
192
193
  const canvasRef = (0, react_1.useRef)(null);
194
+ const { showFrames } = (0, react_1.useContext)(TimelineTickFormatProvider_1.TimelineTickFormatContext);
193
195
  (0, react_1.useLayoutEffect)(() => {
194
196
  const canvas = canvasRef.current;
195
197
  const scrollable = timeline_refs_1.scrollableRef.current;
@@ -201,7 +203,9 @@ const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, duratio
201
203
  return;
202
204
  }
203
205
  const frameInterval = (0, timeline_scroll_logic_1.getFrameIncrementFromWidth)(durationInFrames, windowWidth);
204
- const maxTickLabelWidth = (0, render_frame_1.renderFrame)(durationInFrames - 1, fps).length *
206
+ const maxTickLabelWidth = (showFrames
207
+ ? `${durationInFrames - 1}f`
208
+ : (0, render_frame_1.renderFrame)(durationInFrames - 1, fps)).length *
205
209
  TICK_LABEL_FONT_SIZE *
206
210
  0.6;
207
211
  const tickScale = (0, exports.getTimelineTickScale)({
@@ -242,7 +246,7 @@ const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, duratio
242
246
  context.fillStyle = colors_1.LIGHT_TEXT;
243
247
  context.font = `${TICK_LABEL_FONT_SIZE}px ${getComputedStyle(canvas).fontFamily}`;
244
248
  context.textBaseline = 'top';
245
- context.fillText((0, render_frame_1.renderFrame)(frame, fps), xForFrame(frame) + TICK_LABEL_MARGIN_LEFT, 7);
249
+ context.fillText(showFrames ? `${Math.round(frame)}f` : (0, render_frame_1.renderFrame)(frame, fps), xForFrame(frame) + TICK_LABEL_MARGIN_LEFT, 7);
246
250
  context.fillStyle = colors_1.WHITE_ALPHA_15;
247
251
  }
248
252
  }
@@ -286,7 +290,7 @@ const TimelineTimeIndicatorsInner = react_1.default.memo(({ windowWidth, duratio
286
290
  scrollable.removeEventListener('scroll', onScroll);
287
291
  resizeObserver.disconnect();
288
292
  };
289
- }, [durationInFrames, fps, windowWidth]);
293
+ }, [durationInFrames, fps, showFrames, windowWidth]);
290
294
  const style = (0, react_1.useMemo)(() => {
291
295
  return {
292
296
  ...container,
@@ -53,6 +53,7 @@ const filmstripContainerStyle = {
53
53
  height: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
54
54
  backgroundColor: colors_1.BLACK_ALPHA_30,
55
55
  display: 'flex',
56
+ overflow: 'hidden',
56
57
  borderTopLeftRadius: 2,
57
58
  fontSize: 10,
58
59
  fontFamily: 'Arial, Helvetica',
@@ -86,8 +87,8 @@ const TimelineVideoInfoSegment = ({ src, visualizationWidth, startMediaFrom, med
86
87
  const canvas = document.createElement('canvas');
87
88
  canvas.width = Math.ceil(visualizationWidth * pixelRatio);
88
89
  canvas.height = Math.ceil(timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT * pixelRatio);
89
- canvas.style.width = visualizationWidth + 'px';
90
- canvas.style.height = timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT + 'px';
90
+ canvas.style.width = canvas.width / pixelRatio + 'px';
91
+ canvas.style.height = canvas.height / pixelRatio + 'px';
91
92
  const ctx = canvas.getContext('2d');
92
93
  if (!ctx) {
93
94
  return;
@@ -194,7 +195,10 @@ const TimelineVideoInfoSegment = ({ src, visualizationWidth, startMediaFrom, med
194
195
  // desired-timestamp -> filled-timestamp
195
196
  const filledSlots = new Map();
196
197
  const { fromSeconds, toSeconds } = times;
197
- const targetWidth = targetCanvas.width;
198
+ // Keep the time-to-pixel scale independent of the integer canvas backing size.
199
+ const targetWidth = tiledLoop
200
+ ? tiledLoop.loopWidth * pixelRatio
201
+ : visualizationWidth * pixelRatio;
198
202
  const repeatTarget = () => {
199
203
  if (!tiledLoop) {
200
204
  return;
@@ -243,6 +243,7 @@ const formatTimelineFieldValueForDisplay = ({ fieldSchema, value, }) => {
243
243
  case 'color':
244
244
  case 'enum':
245
245
  case 'font-family':
246
+ case 'font-weight':
246
247
  case 'hidden':
247
248
  return formatUnknownTimelineValueForDisplay(value);
248
249
  default:
@@ -6,7 +6,12 @@ export type Bug = {
6
6
  link: string;
7
7
  versions: string[];
8
8
  };
9
+ type UpgradeState = 'idle' | 'upgrading' | 'upgraded' | 'shutting-down' | 'shutdown';
9
10
  type UpdateStatusContextValue = {
11
+ readonly upgradeState: UpgradeState;
12
+ readonly upgradeError: string | null;
13
+ readonly upgrade: (version: string) => Promise<void>;
14
+ readonly shutdown: () => Promise<void>;
10
15
  readonly error: string | null;
11
16
  readonly info: UpdateAvailableResponse | null;
12
17
  readonly knownBugs: Bug[] | null;
@@ -4,13 +4,56 @@ exports.useUpdateStatus = exports.UpdateStatusProvider = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
+ const shut_down_studio_1 = require("../api/shut-down-studio");
7
8
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
8
9
  const can_show_updates_1 = require("../helpers/can-show-updates");
9
10
  const client_id_1 = require("../helpers/client-id");
11
+ const call_api_1 = require("./call-api");
10
12
  const actions_1 = require("./RenderQueue/actions");
11
13
  const UpdateStatusContext = (0, react_1.createContext)(null);
12
14
  const UpdateStatusProvider = ({ children }) => {
13
15
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
16
+ const [upgradeState, setUpgradeState] = (0, react_1.useState)('idle');
17
+ const [upgradeError, setUpgradeError] = (0, react_1.useState)(null);
18
+ const busy = (0, react_1.useRef)(false);
19
+ const upgrade = (0, react_1.useCallback)(async (version) => {
20
+ if (busy.current) {
21
+ return;
22
+ }
23
+ busy.current = true;
24
+ setUpgradeState('upgrading');
25
+ setUpgradeError(null);
26
+ try {
27
+ await (0, call_api_1.callApi)('/api/upgrade-remotion', { version });
28
+ setUpgradeState('upgraded');
29
+ }
30
+ catch (err) {
31
+ setUpgradeError(err.message);
32
+ setUpgradeState('idle');
33
+ }
34
+ finally {
35
+ busy.current = false;
36
+ }
37
+ }, []);
38
+ const shutdown = (0, react_1.useCallback)(async () => {
39
+ if (busy.current) {
40
+ return;
41
+ }
42
+ busy.current = true;
43
+ setUpgradeState('shutting-down');
44
+ setUpgradeError(null);
45
+ try {
46
+ await (0, shut_down_studio_1.shutDownStudio)();
47
+ setUpgradeState('shutdown');
48
+ }
49
+ catch (err) {
50
+ setUpgradeError(err.message);
51
+ setUpgradeState('upgraded');
52
+ }
53
+ finally {
54
+ busy.current = false;
55
+ }
56
+ }, []);
14
57
  const [info, setInfo] = (0, react_1.useState)(null);
15
58
  const [knownBugs, setKnownBugs] = (0, react_1.useState)(null);
16
59
  const [error, setError] = (0, react_1.useState)(null);
@@ -59,8 +102,16 @@ const UpdateStatusProvider = ({ children }) => {
59
102
  };
60
103
  }, [showUpdates]);
61
104
  const value = (0, react_1.useMemo)(() => {
62
- return { error, info, knownBugs };
63
- }, [error, info, knownBugs]);
105
+ return {
106
+ error,
107
+ info,
108
+ knownBugs,
109
+ upgradeState,
110
+ upgradeError,
111
+ upgrade,
112
+ shutdown,
113
+ };
114
+ }, [error, info, knownBugs, upgradeState, upgradeError, upgrade, shutdown]);
64
115
  return (jsx_runtime_1.jsx(UpdateStatusContext.Provider, { value: value, children: children }));
65
116
  };
66
117
  exports.UpdateStatusProvider = UpdateStatusProvider;
@@ -8,6 +8,7 @@ const copy_text_1 = require("../helpers/copy-text");
8
8
  const clipboard_1 = require("../icons/clipboard");
9
9
  const InlineAction_1 = require("./InlineAction");
10
10
  const KnownBugs_1 = require("./KnownBugs");
11
+ const ModalButton_1 = require("./ModalButton");
11
12
  const ValidationMessage_1 = require("./NewComposition/ValidationMessage");
12
13
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
13
14
  const actions_1 = require("./RenderQueue/actions");
@@ -86,6 +87,7 @@ const commands = {
86
87
  yarn: 'yarn remotion upgrade',
87
88
  pnpm: 'pnpm exec remotion upgrade',
88
89
  bun: 'bun remotion upgrade',
90
+ nub: 'nubx remotion upgrade',
89
91
  unknown: 'npx remotion upgrade',
90
92
  };
91
93
  const skillsUpdateCommand = 'npx remotion skills update';
@@ -170,7 +172,7 @@ const RenderedReleaseNotes = ({ release }) => {
170
172
  };
171
173
  const UpdatesSettings = () => {
172
174
  const { remotionSkillsInfo } = (0, SettingsContext_1.useSettings)();
173
- const { error, info, knownBugs } = (0, UpdateStatusContext_1.useUpdateStatus)();
175
+ const { error, info, knownBugs, upgradeState, upgradeError, upgrade, shutdown, } = (0, UpdateStatusContext_1.useUpdateStatus)();
174
176
  const [releaseNotes, setReleaseNotes] = (0, react_1.useState)(null);
175
177
  (0, react_1.useEffect)(() => {
176
178
  if (!(info === null || info === void 0 ? void 0 : info.updateAvailable)) {
@@ -222,6 +224,23 @@ const UpdatesSettings = () => {
222
224
  const renderCopyAction = (0, react_1.useCallback)((color) => {
223
225
  return jsx_runtime_1.jsx(clipboard_1.ClipboardIcon, { color: color, style: copyIcon });
224
226
  }, []);
227
+ const onUpgrade = (0, react_1.useCallback)(() => {
228
+ if (info) {
229
+ upgrade(info.latestVersion);
230
+ }
231
+ }, [info, upgrade]);
232
+ if (upgradeState !== 'idle') {
233
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [
234
+ jsx_runtime_1.jsx("div", { style: title, children: upgradeState === 'upgrading'
235
+ ? 'Upgrading Remotion...'
236
+ : 'Remotion has been upgraded.' }), jsx_runtime_1.jsx("div", { style: text, children: upgradeState === 'upgrading'
237
+ ? 'This may take a few minutes. You can follow the progress in your terminal.'
238
+ : upgradeState === 'shutdown'
239
+ ? 'Studio is shutting down. Run your Studio start command again in the terminal to use the new version.'
240
+ : 'Restart Studio to use the new version. Shut down the server below, then run your Studio start command again in the terminal.' }), upgradeState === 'upgraded' || upgradeState === 'shutting-down' ? (jsx_runtime_1.jsx("div", { style: { marginTop: 12 }, children: jsx_runtime_1.jsx(ModalButton_1.ModalButton, { onClick: shutdown, disabled: upgradeState === 'shutting-down', children: upgradeState === 'shutting-down'
241
+ ? 'Shutting down...'
242
+ : 'Shut down Studio' }) })) : null, upgradeError ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: upgradeError, type: "error", align: "flex-start" })) : null] }));
243
+ }
225
244
  if (info === null) {
226
245
  return (jsx_runtime_1.jsx("div", { style: container, children: error ? (jsx_runtime_1.jsx("div", { style: { paddingTop: 12 }, children: jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: 'Could not check for updates: ' + error, align: "flex-start", type: "error" }) })) : (jsx_runtime_1.jsx("div", { style: title, children: "Checking for updates..." })) }));
227
246
  }
@@ -235,9 +254,11 @@ const UpdatesSettings = () => {
235
254
  jsx_runtime_1.jsxs("div", { style: title, children: ["You", "'re", " up to date."] }), jsx_runtime_1.jsxs("div", { style: text, children: ["Remotion ", info.currentVersion, " and your Remotion Agent Skills are up to date."] })
236
255
  ] }));
237
256
  }
238
- return (jsx_runtime_1.jsxs("div", { style: container, children: [hasKnownBugs && info.updateAvailable ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
239
- jsx_runtime_1.jsxs("div", { style: title, children: ["The currently installed version ", info.currentVersion, " has the following known bugs:"] }), jsx_runtime_1.jsx(KnownBugs_1.KnownBugs, { bugs: knownBugs !== null && knownBugs !== void 0 ? knownBugs : [] }), jsx_runtime_1.jsx("div", { style: { height: '20px' } }), jsx_runtime_1.jsxs("div", { style: text, children: ["To update, run the following ", updateActionType, ":"] })
240
- ] })) : info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["A new Remotion update is available. Run the following", ' ', updateActionType, ":"] })) : (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["Your Remotion Agent Skills are out of date. Run the following", ' ', updateActionType, ":"] })), jsx_runtime_1.jsxs("div", { style: commandField, children: [
257
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [info.updateAvailable && info.packageManager !== 'unknown' ? (jsx_runtime_1.jsxs("div", { style: { paddingTop: 12 }, children: [
258
+ jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: onUpgrade, children: ["Upgrade to ", info.latestVersion] }), jsx_runtime_1.jsx("div", { style: { ...text, marginTop: 8 }, children: "You will need to restart Studio after upgrading." })
259
+ ] })) : null, upgradeError ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { message: upgradeError, type: "error", align: "flex-start" })) : null, hasKnownBugs && info.updateAvailable ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
260
+ jsx_runtime_1.jsxs("div", { style: title, children: ["The currently installed version ", info.currentVersion, " has the following known bugs:"] }), jsx_runtime_1.jsx(KnownBugs_1.KnownBugs, { bugs: knownBugs !== null && knownBugs !== void 0 ? knownBugs : [] }), jsx_runtime_1.jsx("div", { style: { height: '20px' } }), jsx_runtime_1.jsxs("div", { style: text, children: ["Or run the following ", updateActionType, ":"] })
261
+ ] })) : info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["A new Remotion update is available. You can also run the following", ' ', updateActionType, ":"] })) : (jsx_runtime_1.jsxs("div", { style: titleBeforeCommand, children: ["Your Remotion Agent Skills are out of date. Run the following", ' ', updateActionType, ":"] })), jsx_runtime_1.jsxs("div", { style: commandField, children: [
241
262
  jsx_runtime_1.jsx("pre", { style: code, children: updateAction }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { variant: null, onClick: onClick, renderAction: renderCopyAction, title: "Copy command" })
242
263
  ] }), info.updateAvailable ? (jsx_runtime_1.jsxs("div", { style: text, children: ["This will update Remotion from ", info.currentVersion, " to", ' ', info.latestVersion, info.skillsUpdateAvailable
243
264
  ? ' and update your project Remotion Agent Skills.'
@@ -5,7 +5,9 @@ const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const pause_1 = require("../api/pause");
7
7
  const play_1 = require("../api/play");
8
+ const restart_studio_1 = require("../api/restart-studio");
8
9
  const seek_1 = require("../api/seek");
10
+ const shut_down_studio_1 = require("../api/shut-down-studio");
9
11
  const current_error_1 = require("../error-overlay/current-error");
10
12
  const calculate_timeline_1 = require("../helpers/calculate-timeline");
11
13
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
@@ -203,6 +205,30 @@ const WebMcp = () => {
203
205
  }).filter((timelineTrack) => (0, should_show_track_in_timeline_1.shouldShowTrackInTimeline)(timelineTrack, durationInFrames));
204
206
  };
205
207
  Promise.all([
208
+ modelContext.registerTool({
209
+ name: 'restart_studio',
210
+ title: 'Restart Studio',
211
+ description: 'Restart the Studio server. The browser temporarily disconnects and reconnects when Studio is ready. Only available in a writable Studio with a server backend.',
212
+ inputSchema: {
213
+ type: 'object',
214
+ properties: {},
215
+ additionalProperties: false,
216
+ },
217
+ annotations: { readOnlyHint: false },
218
+ execute: () => (0, restart_studio_1.restartStudio)(),
219
+ }, { signal: controller.signal }),
220
+ modelContext.registerTool({
221
+ name: 'shut_down_studio',
222
+ title: 'Shut down Studio',
223
+ description: 'Gracefully shut down the Studio server. The browser disconnects. Start Studio again from the terminal to reconnect. Only available in a writable Studio with a server backend.',
224
+ inputSchema: {
225
+ type: 'object',
226
+ properties: {},
227
+ additionalProperties: false,
228
+ },
229
+ annotations: { readOnlyHint: false },
230
+ execute: () => (0, shut_down_studio_1.shutDownStudio)(),
231
+ }, { signal: controller.signal }),
206
232
  modelContext.registerTool({
207
233
  name: 'get_current_error',
208
234
  title: 'Get current Studio error',
@@ -0,0 +1,27 @@
1
+ import type { CompositionOrFolder, SymbolicatedStackFrame } from '@remotion/studio-shared';
2
+ export type CompositionSelectorDragData = {
3
+ readonly type: 'remotion-composition-selector';
4
+ readonly version: 1;
5
+ readonly item: CompositionOrFolder;
6
+ readonly sourceFile: string | null;
7
+ };
8
+ export type CompositionSelectorActiveDrag = {
9
+ readonly item: CompositionOrFolder;
10
+ readonly parentFolderPath: string | null;
11
+ };
12
+ type DragDataTransfer = {
13
+ readonly types: ArrayLike<string>;
14
+ readonly getData: (mimeType: string) => string;
15
+ };
16
+ export declare const makeCompositionSelectorDragData: ({ item, sourceFile, }: {
17
+ readonly item: CompositionOrFolder;
18
+ readonly sourceFile: string | null;
19
+ }) => {
20
+ mimeType: string;
21
+ payload: string;
22
+ data: CompositionSelectorDragData;
23
+ };
24
+ export declare const hasCompositionSelectorDragData: (mimeTypes: ArrayLike<string>) => boolean;
25
+ export declare const parseCompositionSelectorDragData: (dataTransfer: DragDataTransfer) => CompositionSelectorDragData | null;
26
+ export declare const compositionSelectorDragDataToSymbolicatedStack: (dragData: CompositionSelectorDragData) => SymbolicatedStackFrame | null;
27
+ export {};