@remotion/studio 4.0.517 → 4.0.519

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 (146) hide show
  1. package/dist/components/AppLaunchButton.d.ts +16 -0
  2. package/dist/components/AppLaunchButton.js +90 -0
  3. package/dist/components/AssetSelector.js +64 -22
  4. package/dist/components/AssetSelectorItem.d.ts +14 -1
  5. package/dist/components/AssetSelectorItem.js +219 -70
  6. package/dist/components/Button.js +20 -7
  7. package/dist/components/Canvas.js +109 -78
  8. package/dist/components/CanvasOrLoading.js +7 -7
  9. package/dist/components/CaptionTextEditor.js +32 -8
  10. package/dist/components/CodingAgentButton.d.ts +7 -0
  11. package/dist/components/CodingAgentButton.js +59 -0
  12. package/dist/components/CompositionContextButton.d.ts +1 -0
  13. package/dist/components/CompositionContextButton.js +7 -3
  14. package/dist/components/CompositionSelector.js +16 -11
  15. package/dist/components/CompositionSelectorItem.js +16 -23
  16. package/dist/components/ConfigureLicenseModal.js +4 -48
  17. package/dist/components/CurrentAsset.js +1 -1
  18. package/dist/components/EditorContent.js +6 -3
  19. package/dist/components/ElementInstallConfirmation.d.ts +25 -7
  20. package/dist/components/ElementInstallConfirmation.js +347 -30
  21. package/dist/components/ElementLibraryModal.js +3 -1
  22. package/dist/components/FixComputedValueModal.js +5 -131
  23. package/dist/components/InitialCompositionLoader.js +3 -2
  24. package/dist/components/InlineCaptionInspector.js +13 -2
  25. package/dist/components/InspectorOpenInEditor.js +48 -33
  26. package/dist/components/InspectorPanel/CompositionInspector.js +35 -3
  27. package/dist/components/InspectorPanel/CompositionInspectorHeader.js +22 -14
  28. package/dist/components/InspectorPanel/ConnectedCompositionsSection.js +3 -1
  29. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +1 -1
  30. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +10 -5
  31. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +1 -1
  32. package/dist/components/InspectorPanel/common.js +1 -0
  33. package/dist/components/InspectorPanel/styles.js +1 -0
  34. package/dist/components/InspectorSequenceSection.js +8 -3
  35. package/dist/components/InspectorSourceLocation.js +5 -1
  36. package/dist/components/KnownBugs.d.ts +1 -1
  37. package/dist/components/KnownBugs.js +1 -1
  38. package/dist/components/LicenseExplanation.d.ts +2 -0
  39. package/dist/components/LicenseExplanation.js +63 -0
  40. package/dist/components/MenuToolbar.js +7 -1
  41. package/dist/components/Modals.js +50 -2
  42. package/dist/components/NewComposition/InputDragger.js +29 -2
  43. package/dist/components/NewComposition/NewCompDuration.js +1 -1
  44. package/dist/components/NewComposition/NewComposition.d.ts +23 -0
  45. package/dist/components/NewComposition/NewComposition.js +217 -80
  46. package/dist/components/{UpdateModal/OpenIssueButton.js → OpenIssueButton.js} +1 -1
  47. package/dist/components/PlaybackRateSelector.js +2 -5
  48. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.d.ts +2 -0
  49. package/dist/components/QuickSwitcher/ExplorerQuickSwitcherTrigger.js +28 -7
  50. package/dist/components/QuickSwitcher/QuickSwitcherContent.js +21 -13
  51. package/dist/components/RenderQueue/actions.d.ts +1 -0
  52. package/dist/components/RenderQueue/actions.js +5 -1
  53. package/dist/components/SelectedOutlineCanvasRotation.js +27 -1
  54. package/dist/components/SelectedOutlineElement.js +2 -1
  55. package/dist/components/SelectedOutlineOverlay.js +9 -10
  56. package/dist/components/SelectedOutlinePolygon.d.ts +1 -0
  57. package/dist/components/SelectedOutlinePolygon.js +12 -4
  58. package/dist/components/SelectedOutlineRenderer.d.ts +1 -1
  59. package/dist/components/SelectedOutlineRenderer.js +33 -35
  60. package/dist/components/SettingsContext.js +2 -1
  61. package/dist/components/SettingsModal.d.ts +1 -1
  62. package/dist/components/SettingsModal.js +19 -3
  63. package/dist/components/SidebarRenderButton.d.ts +1 -0
  64. package/dist/components/SidebarRenderButton.js +15 -5
  65. package/dist/components/Timeline/SequencePropsObserver.js +29 -14
  66. package/dist/components/Timeline/TimelineKeyframeControls.js +3 -1
  67. package/dist/components/Timeline/TimelineRowChrome.js +4 -2
  68. package/dist/components/Timeline/TimelineSequence.js +40 -8
  69. package/dist/components/Timeline/TimelineSequenceItem.js +34 -1
  70. package/dist/components/Timeline/TimelineStack/get-stack.d.ts +1 -0
  71. package/dist/components/Timeline/TimelineStack/get-stack.js +35 -3
  72. package/dist/components/Timeline/duplicate-selected-timeline-item.js +23 -25
  73. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +6 -0
  74. package/dist/components/Timeline/get-sequence-context-menu-items.js +34 -1
  75. package/dist/components/Timeline/sequence-props-subscription-store.d.ts +2 -0
  76. package/dist/components/Timeline/sequence-props-subscription-store.js +22 -1
  77. package/dist/components/Timeline/use-sequence-props-subscription.js +7 -0
  78. package/dist/components/TimelineCombobox.js +1 -0
  79. package/dist/components/UpdateCheck.d.ts +0 -8
  80. package/dist/components/UpdateCheck.js +7 -54
  81. package/dist/components/UpdateStatusContext.d.ts +18 -0
  82. package/dist/components/UpdateStatusContext.js +74 -0
  83. package/dist/components/UpdatesSettings.d.ts +2 -0
  84. package/dist/components/UpdatesSettings.js +251 -0
  85. package/dist/components/WebMcp.d.ts +2 -0
  86. package/dist/components/WebMcp.js +945 -0
  87. package/dist/components/composition-menu-items.js +26 -0
  88. package/dist/components/get-open-in-menu-items.d.ts +4 -0
  89. package/dist/components/get-open-in-menu-items.js +28 -24
  90. package/dist/components/root-composition-menu-items.d.ts +4 -1
  91. package/dist/components/root-composition-menu-items.js +38 -1
  92. package/dist/components/selected-outline-measurement.d.ts +11 -0
  93. package/dist/components/selected-outline-measurement.js +13 -5
  94. package/dist/components/use-configure-default-apps.d.ts +1 -0
  95. package/dist/components/use-configure-default-apps.js +24 -0
  96. package/dist/error-overlay/remotion-overlay/CodeFrame.js +5 -6
  97. package/dist/error-overlay/remotion-overlay/CopyStackTrace.js +1 -1
  98. package/dist/error-overlay/remotion-overlay/ErrorDisplay.js +47 -18
  99. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +1 -1
  100. package/dist/error-overlay/remotion-overlay/ErrorTitle.js +5 -4
  101. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +48 -76
  102. package/dist/error-overlay/remotion-overlay/SearchGitHubIssues.js +1 -1
  103. package/dist/error-overlay/remotion-overlay/ShortcutHint.js +2 -2
  104. package/dist/error-overlay/remotion-overlay/StackFrame.js +13 -8
  105. package/dist/error-overlay/remotion-overlay/Symbolicating.js +1 -1
  106. package/dist/esm/{chunk-gzqm3g2m.js → chunk-1fkq5bfq.js} +24093 -21093
  107. package/dist/esm/chunk-6jf1natv.js +25 -0
  108. package/dist/esm/{chunk-4bxz1d3g.js → chunk-je0h1bgt.js} +1 -28
  109. package/dist/esm/chunk-m0jqdbkr.js +14571 -0
  110. package/dist/esm/index.mjs +0 -2
  111. package/dist/esm/internals.mjs +43231 -25675
  112. package/dist/esm/previewEntry.mjs +46334 -28776
  113. package/dist/esm/renderEntry.mjs +6 -3
  114. package/dist/helpers/can-show-updates.d.ts +5 -0
  115. package/dist/helpers/can-show-updates.js +7 -0
  116. package/dist/helpers/colors.d.ts +0 -3
  117. package/dist/helpers/colors.js +2 -5
  118. package/dist/helpers/create-folder-tree.d.ts +5 -0
  119. package/dist/helpers/create-folder-tree.js +40 -2
  120. package/dist/helpers/format-file-location.d.ts +8 -0
  121. package/dist/helpers/format-file-location.js +14 -3
  122. package/dist/helpers/get-asset-metadata.js +1 -1
  123. package/dist/helpers/get-git-menu-item.d.ts +5 -0
  124. package/dist/helpers/get-git-menu-item.js +15 -1
  125. package/dist/helpers/get-timeline-max-zoom.d.ts +8 -0
  126. package/dist/helpers/get-timeline-max-zoom.js +17 -6
  127. package/dist/helpers/hoverable.d.ts +1 -0
  128. package/dist/helpers/hoverable.js +14 -6
  129. package/dist/helpers/open-in-editor.js +51 -1
  130. package/dist/helpers/preview-server-events.js +3 -0
  131. package/dist/helpers/timeline-layout.d.ts +0 -1
  132. package/dist/helpers/timeline-layout.js +1 -5
  133. package/dist/helpers/url-state.d.ts +1 -0
  134. package/dist/helpers/url-state.js +12 -5
  135. package/dist/icons/enter.d.ts +4 -0
  136. package/dist/icons/enter.js +10 -0
  137. package/dist/renderEntry.js +2 -0
  138. package/dist/state/folders.d.ts +3 -0
  139. package/dist/state/folders.js +40 -1
  140. package/dist/state/modals.d.ts +1 -6
  141. package/dist/state/playbackrate.d.ts +1 -0
  142. package/dist/state/playbackrate.js +4 -1
  143. package/package.json +17 -14
  144. package/dist/components/UpdateModal/UpdateModal.d.ts +0 -6
  145. package/dist/components/UpdateModal/UpdateModal.js +0 -104
  146. /package/dist/components/{UpdateModal/OpenIssueButton.d.ts → OpenIssueButton.d.ts} +0 -0
@@ -30,7 +30,6 @@ const modals_1 = require("../state/modals");
30
30
  const call_api_1 = require("./call-api");
31
31
  const canvas_capture_drop_1 = require("./canvas-capture-drop");
32
32
  const composition_drop_preview_1 = require("./composition-drop-preview");
33
- const ConfirmationDialog_1 = require("./ConfirmationDialog");
34
33
  const drop_handler_data_1 = require("./drop-handler-data");
35
34
  const EditorGuides_1 = __importDefault(require("./EditorGuides"));
36
35
  const EditorRuler_1 = require("./EditorRuler");
@@ -127,7 +126,6 @@ const Canvas = ({ canvasContent, size }) => {
127
126
  const suppressWheelFromWebKitPinchRef = (0, react_1.useRef)(false);
128
127
  const touchPinchRef = (0, react_1.useRef)(null);
129
128
  const keybindings = (0, use_keybinding_1.useKeybinding)();
130
- const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
131
129
  const chooseSvgImportMode = (0, SvgImportDialog_1.useSvgImportDialog)();
132
130
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
133
131
  const config = remotion_1.Internals.useUnsafeVideoConfig();
@@ -145,6 +143,7 @@ const Canvas = ({ canvasContent, size }) => {
145
143
  const [installingElementName, setInstallingElementName] = (0, react_1.useState)(null);
146
144
  const [pendingElementInstallRequests, setPendingElementInstallRequests] = (0, react_1.useState)([]);
147
145
  const [activeElementInstallRequest, setActiveElementInstallRequest] = (0, react_1.useState)(null);
146
+ const [elementInstallReview, setElementInstallReview] = (0, react_1.useState)(null);
148
147
  const lastFocusedAtRef = (0, react_1.useRef)(typeof document === 'undefined' || document.hasFocus() ? Date.now() : null);
149
148
  const [assetResolution, setAssetResolution] = (0, react_1.useState)(null);
150
149
  const metadataRequestRef = (0, react_1.useRef)(0);
@@ -162,12 +161,13 @@ const Canvas = ({ canvasContent, size }) => {
162
161
  compositionFile,
163
162
  compositionId: currentCompositionId,
164
163
  });
165
- const canInstallElements = previewServerClientId !== null &&
164
+ const canReceiveElementInstallRequest = previewServerClientId !== null &&
166
165
  !window.remotion_isReadOnlyStudio &&
167
- (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === true &&
168
166
  currentCompositionId !== null &&
169
167
  compositionFile !== null;
170
- const canDropAssets = canInstallElements && !isAddingAsset;
168
+ const canInsertIntoCurrentComposition = canReceiveElementInstallRequest &&
169
+ (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === true;
170
+ const canDropAssets = canInsertIntoCurrentComposition && !isAddingAsset;
171
171
  const cannotAddSequence = (compositionComponentInfo === null || compositionComponentInfo === void 0 ? void 0 : compositionComponentInfo.canAddSequence) === false;
172
172
  const contentDimensions = (0, react_1.useMemo)(() => {
173
173
  if ((canvasContent.type === 'asset' ||
@@ -566,15 +566,18 @@ const Canvas = ({ canvasContent, size }) => {
566
566
  (0, call_api_1.callApi)('/api/update-element-install-target', {
567
567
  requestId,
568
568
  clientId: previewServerClientId,
569
- compositionFile: canInstallElements ? compositionFile : null,
570
- compositionId: canInstallElements ? currentCompositionId : null,
571
- canInstall: canInstallElements,
569
+ compositionFile: canReceiveElementInstallRequest
570
+ ? compositionFile
571
+ : null,
572
+ compositionId: canReceiveElementInstallRequest
573
+ ? currentCompositionId
574
+ : null,
572
575
  lastFocusedAt: lastFocusedAtRef.current,
573
576
  readOnly: window.remotion_isReadOnlyStudio,
574
577
  studioUrl: window.location.href,
575
578
  }).catch(() => undefined);
576
579
  }, [
577
- canInstallElements,
580
+ canReceiveElementInstallRequest,
578
581
  compositionFile,
579
582
  currentCompositionId,
580
583
  previewServerClientId,
@@ -617,21 +620,31 @@ const Canvas = ({ canvasContent, size }) => {
617
620
  event.request.clientId !== previewServerClientId) {
618
621
  return;
619
622
  }
620
- setPendingElementInstallRequests((requests) => [
621
- ...requests,
622
- event.request,
623
- ]);
623
+ (0, element_install_request_1.enqueueElementInstallRequest)(event.request);
624
624
  });
625
625
  }, [previewServerClientId, subscribeToEvent]);
626
626
  (0, react_1.useEffect)(() => {
627
627
  return (0, element_install_request_1.subscribeToElementInstallRequests)((request) => {
628
- setPendingElementInstallRequests((requests) => [...requests, request]);
628
+ const requestWithFrom = request.source.type === 'drag-and-drop' || request.from !== null
629
+ ? request
630
+ : {
631
+ ...request,
632
+ from: (0, import_assets_1.getFromForDrop)({
633
+ durationInFrames: request.element.durationInFrames,
634
+ from: (0, imperative_state_1.getCurrentFrame)(),
635
+ preferCompositionStart: true,
636
+ }),
637
+ };
638
+ setPendingElementInstallRequests((requests) => [
639
+ ...requests,
640
+ requestWithFrom,
641
+ ]);
629
642
  });
630
643
  }, []);
631
644
  (0, react_1.useEffect)(() => {
632
645
  var _a;
633
646
  var _b;
634
- if (!canInstallElements ||
647
+ if (!canReceiveElementInstallRequest ||
635
648
  compositionFile === null ||
636
649
  currentCompositionId === null) {
637
650
  return;
@@ -654,7 +667,7 @@ const Canvas = ({ canvasContent, size }) => {
654
667
  type: 'browser-studio-link',
655
668
  },
656
669
  });
657
- }, [canInstallElements, compositionFile, currentCompositionId]);
670
+ }, [canReceiveElementInstallRequest, compositionFile, currentCompositionId]);
658
671
  (0, react_1.useEffect)(() => {
659
672
  if (activeElementInstallRequest !== null ||
660
673
  pendingElementInstallRequests.length === 0) {
@@ -675,73 +688,82 @@ const Canvas = ({ canvasContent, size }) => {
675
688
  const handleInstallRequest = async () => {
676
689
  var _a;
677
690
  setInstallingElementName(activeElementInstallRequest.element.displayName);
678
- const preflight = await (0, element_install_api_1.prepareElementInstall)({
679
- compositionFile: activeElementInstallRequest.compositionFile,
680
- compositionId: activeElementInstallRequest.compositionId,
681
- element: activeElementInstallRequest.element,
682
- });
683
- if (!preflight.success) {
684
- (0, NotificationCenter_1.showNotification)(`Could not review Element installation: ${preflight.reason}`, 4000);
685
- return;
686
- }
687
- if (canceled) {
688
- return;
689
- }
690
- const declaredDependencies = Array.from(new Map(activeElementInstallRequest.element.dependencies.map((dependency) => [
691
- dependency.name,
692
- dependency,
693
- ])).values());
694
- const missingPackages = (0, install_required_package_1.getMissingPackages)(declaredDependencies).map((dependency) => dependency.name);
695
- const ignoredDependencies = declaredDependencies.filter((dependency) => elementInstallDependencyIgnoreList.includes(dependency.name) &&
696
- !missingPackages.includes(dependency.name));
697
- const dependenciesToReview = declaredDependencies
698
- .filter((dependency) => !ignoredDependencies.includes(dependency))
699
- .map((dependency) => dependency.version === null
700
- ? dependency.name
701
- : `${dependency.name}@${dependency.version}`);
702
- const { source } = activeElementInstallRequest;
703
- const sourceLabel = source.type === 'studio-protocol'
704
- ? source.origin
705
- : source.type === 'browser-studio-link'
706
- ? ((_a = source.origin) !== null && _a !== void 0 ? _a : 'Unverified Browser Studio link')
707
- : 'Unverified drag-and-drop payload';
708
- const sourceIsUnverified = source.type === 'drag-and-drop' ||
709
- (source.type === 'browser-studio-link' && source.origin === null);
710
- const accepted = await confirm({
711
- title: 'Install Element',
712
- message: (jsx_runtime_1.jsx(ElementInstallConfirmation_1.ElementInstallConfirmation, { displayName: activeElementInstallRequest.element.displayName, sourceLabel: sourceLabel, sourceIsUnverified: sourceIsUnverified, compositionId: activeElementInstallRequest.compositionId, filePath: preflight.plan.filePath, overwritesExistingFile: preflight.plan.expectedFileState.exists, dependenciesToReview: dependenciesToReview, missingPackages: missingPackages, sourceCode: activeElementInstallRequest.element.sourceCode, usesBrowserDependencyResolution: (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null })),
713
- confirmLabel: 'Install',
714
- cancelLabel: 'Cancel',
715
- });
716
- if (accepted && !canceled) {
717
- await (0, import_assets_1.insertElement)({
718
- element: activeElementInstallRequest.element,
719
- compositionFile: activeElementInstallRequest.compositionFile,
720
- compositionId: activeElementInstallRequest.compositionId,
721
- expectedFileState: preflight.plan.expectedFileState,
722
- from: activeElementInstallRequest.from,
723
- position: activeElementInstallRequest.position,
724
- overwriteExisting: preflight.plan.expectedFileState.exists,
691
+ try {
692
+ const [newPreflight, currentPreflight] = await Promise.all([
693
+ (0, element_install_api_1.prepareElementInstall)({
694
+ destination: {
695
+ type: 'new-composition',
696
+ compositionFile: null,
697
+ },
698
+ element: activeElementInstallRequest.element,
699
+ }),
700
+ (0, element_install_api_1.prepareElementInstall)({
701
+ destination: {
702
+ type: 'current-composition',
703
+ compositionFile: activeElementInstallRequest.compositionFile,
704
+ compositionId: activeElementInstallRequest.compositionId,
705
+ },
706
+ element: activeElementInstallRequest.element,
707
+ }),
708
+ ]);
709
+ if (canceled) {
710
+ return;
711
+ }
712
+ if (!newPreflight.success) {
713
+ (0, NotificationCenter_1.showNotification)(`Could not review Element installation: ${newPreflight.reason}`, 4000);
714
+ setInstallingElementName(null);
715
+ setActiveElementInstallRequest(null);
716
+ return;
717
+ }
718
+ const declaredDependencies = Array.from(new Map(activeElementInstallRequest.element.dependencies.map((dependency) => [dependency.name, dependency])).values());
719
+ const missingPackages = (0, install_required_package_1.getMissingPackages)(declaredDependencies).map((dependency) => dependency.name);
720
+ const ignoredDependencies = declaredDependencies.filter((dependency) => elementInstallDependencyIgnoreList.includes(dependency.name) &&
721
+ !missingPackages.includes(dependency.name));
722
+ const dependenciesToReview = declaredDependencies
723
+ .filter((dependency) => !ignoredDependencies.includes(dependency))
724
+ .map((dependency) => dependency.version === null
725
+ ? dependency.name
726
+ : `${dependency.name}@${dependency.version}`);
727
+ const { source } = activeElementInstallRequest;
728
+ const sourceLabel = source.type === 'studio-protocol'
729
+ ? source.origin
730
+ : source.type === 'browser-studio-link'
731
+ ? ((_a = source.origin) !== null && _a !== void 0 ? _a : 'Unverified Browser Studio link')
732
+ : 'Unverified drag-and-drop payload';
733
+ const sourceIsUnverified = source.type === 'drag-and-drop' ||
734
+ (source.type === 'browser-studio-link' && source.origin === null);
735
+ const currentPlan = currentPreflight.success
736
+ ? currentPreflight.plan
737
+ : null;
738
+ setSelectedModal(null);
739
+ setElementInstallReview({
740
+ currentPlan,
741
+ dependenciesToReview,
742
+ missingPackages,
743
+ newPlan: newPreflight.plan,
744
+ sourceIsUnverified,
745
+ sourceLabel,
725
746
  });
726
747
  }
727
- };
728
- handleInstallRequest()
729
- .finally(() => {
730
- if (canceled) {
731
- return;
748
+ catch (error) {
749
+ if (canceled) {
750
+ return;
751
+ }
752
+ (0, NotificationCenter_1.showNotification)(`Could not review Element installation: ${error instanceof Error ? error.message : String(error)}`, 4000);
753
+ setInstallingElementName(null);
754
+ setActiveElementInstallRequest(null);
732
755
  }
733
- setInstallingElementName(null);
734
- setActiveElementInstallRequest(null);
735
- })
736
- .catch((err) => {
737
- setTimeout(() => {
738
- throw err;
739
- }, 0);
740
- });
756
+ };
757
+ handleInstallRequest();
741
758
  return () => {
742
759
  canceled = true;
743
760
  };
744
- }, [activeElementInstallRequest, confirm]);
761
+ }, [activeElementInstallRequest, setSelectedModal]);
762
+ const closeElementInstallDialog = (0, react_1.useCallback)(() => {
763
+ setElementInstallReview(null);
764
+ setInstallingElementName(null);
765
+ setActiveElementInstallRequest(null);
766
+ }, []);
745
767
  const onDragOver = (0, react_1.useCallback)((event) => {
746
768
  var _a;
747
769
  var _b;
@@ -1100,6 +1122,15 @@ const Canvas = ({ canvasContent, size }) => {
1100
1122
  };
1101
1123
  }, [compositionDropPreview, contentDimensions, previewSize, size]);
1102
1124
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1103
- jsx_runtime_1.jsxs("div", { ref: canvas_ref_1.canvasRef, style: getContainerStyle(editorZoomGestures), children: [size ? (jsx_runtime_1.jsx(Preview_1.VideoPreview, { canvasContent: canvasContent, contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, onRetryAssetMetadata: fetchMetadata })) : null, compositionDropPreviewStyle === null ? null : (jsx_runtime_1.jsx("div", { className: "css-reset", "data-testid": "composition-drop-preview", style: compositionDropPreviewStyle })), isFit ? null : (jsx_runtime_1.jsx("div", { style: resetZoom, className: "css-reset", children: jsx_runtime_1.jsx(ResetZoomButton_1.ResetZoomButton, { onClick: onReset }) })), editorShowGuides && canvasContent.type === 'composition' && (jsx_runtime_1.jsx(EditorGuides_1.default, { canvasSize: size, contentDimensions: contentDimensions, assetMetadata: assetResolution }))] }), areRulersVisible && (jsx_runtime_1.jsx(EditorRuler_1.EditorRulers, { canCreateGuides: canvasContent.type === 'composition', contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, containerRef: canvas_ref_1.canvasRef }))] }));
1125
+ jsx_runtime_1.jsxs("div", { ref: canvas_ref_1.canvasRef, style: getContainerStyle(editorZoomGestures), children: [size ? (jsx_runtime_1.jsx(Preview_1.VideoPreview, { canvasContent: canvasContent, contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, onRetryAssetMetadata: fetchMetadata })) : null, compositionDropPreviewStyle === null ? null : (jsx_runtime_1.jsx("div", { className: "css-reset", "data-testid": "composition-drop-preview", style: compositionDropPreviewStyle })), isFit ? null : (jsx_runtime_1.jsx("div", { style: resetZoom, className: "css-reset", children: jsx_runtime_1.jsx(ResetZoomButton_1.ResetZoomButton, { onClick: onReset }) })), editorShowGuides && canvasContent.type === 'composition' && (jsx_runtime_1.jsx(EditorGuides_1.default, { canvasSize: size, contentDimensions: contentDimensions, assetMetadata: assetResolution }))] }), areRulersVisible && (jsx_runtime_1.jsx(EditorRuler_1.EditorRulers, { canCreateGuides: canvasContent.type === 'composition', contentDimensions: contentDimensions, canvasSize: size, assetMetadata: assetResolution, containerRef: canvas_ref_1.canvasRef })), activeElementInstallRequest === null ||
1126
+ elementInstallReview === null ? null : (jsx_runtime_1.jsx(ElementInstallConfirmation_1.ElementInstallConfirmation, { currentCompositionMetadata: config === null ||
1127
+ currentCompositionId !== activeElementInstallRequest.compositionId
1128
+ ? null
1129
+ : {
1130
+ durationInFrames: config.durationInFrames,
1131
+ fps: config.fps,
1132
+ height: config.height,
1133
+ width: config.width,
1134
+ }, currentPlan: elementInstallReview.currentPlan, dependenciesToReview: elementInstallReview.dependenciesToReview, missingPackages: elementInstallReview.missingPackages, newPlan: elementInstallReview.newPlan, onClose: closeElementInstallDialog, request: activeElementInstallRequest, sourceIsUnverified: elementInstallReview.sourceIsUnverified, sourceLabel: elementInstallReview.sourceLabel, usesBrowserDependencyResolution: (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null }))] }));
1104
1135
  };
1105
1136
  exports.Canvas = Canvas;
@@ -47,7 +47,7 @@ const CanvasOrLoading = ({ size }) => {
47
47
  });
48
48
  }, [resolved, setZoom]);
49
49
  if (renderError) {
50
- return (jsx_runtime_1.jsx(ErrorLoading, { error: renderError, calculateMetadataContext: false }));
50
+ return (jsx_runtime_1.jsx(ErrorLoading, { error: renderError, calculateMetadataContext: false, onRetry: null }));
51
51
  }
52
52
  if (!canvasContent) {
53
53
  if (compositionListState !== 'ready') {
@@ -71,7 +71,10 @@ const CanvasOrLoading = ({ size }) => {
71
71
  return (jsx_runtime_1.jsx("div", { style: container, className: "css-reset", children: jsx_runtime_1.jsx(RunningCalculateMetadata_1.RunningCalculateMetadata, {}) }));
72
72
  }
73
73
  if (resolved.type === 'error') {
74
- return jsx_runtime_1.jsx(ErrorLoading, { error: resolved.error, calculateMetadataContext: true });
74
+ return (jsx_runtime_1.jsx(ErrorLoading, { error: resolved.error, calculateMetadataContext: true, onRetry: () => {
75
+ var _a;
76
+ return (_a = remotion_1.Internals.resolveCompositionsRef.current) === null || _a === void 0 ? void 0 : _a.reloadCurrentlySelectedComposition();
77
+ } }));
75
78
  }
76
79
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
77
80
  jsx_runtime_1.jsx(FramePersistor_1.FramePersistor, {}),
@@ -86,9 +89,6 @@ const loaderContainer = {
86
89
  height: '100%',
87
90
  overflowY: 'auto',
88
91
  };
89
- const ErrorLoading = ({ error, calculateMetadataContext }) => {
90
- return (jsx_runtime_1.jsx("div", { style: loaderContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ErrorLoader_1.ErrorLoader, { canHaveDismissButton: false, keyboardShortcuts: true, error: error, onRetry: () => {
91
- var _a;
92
- return (_a = remotion_1.Internals.resolveCompositionsRef.current) === null || _a === void 0 ? void 0 : _a.reloadCurrentlySelectedComposition();
93
- }, calculateMetadata: calculateMetadataContext }, error.stack) }));
92
+ const ErrorLoading = ({ error, calculateMetadataContext, onRetry }) => {
93
+ return (jsx_runtime_1.jsx("div", { style: loaderContainer, className: is_menu_item_1.VERTICAL_SCROLLBAR_CLASSNAME, children: jsx_runtime_1.jsx(ErrorLoader_1.ErrorLoader, { canHaveDismissButton: false, keyboardShortcuts: true, error: error, onRetry: onRetry, calculateMetadata: calculateMetadataContext }, error.stack) }));
94
94
  };
@@ -4,6 +4,9 @@ exports.CaptionTextEditor = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const colors_1 = require("../helpers/colors");
7
+ const hoverable_1 = require("../helpers/hoverable");
8
+ const enter_1 = require("../icons/enter");
9
+ const InlineAction_1 = require("./InlineAction");
7
10
  const RemInput_1 = require("./NewComposition/RemInput");
8
11
  const container = {
9
12
  alignSelf: 'stretch',
@@ -21,8 +24,8 @@ const row = {
21
24
  alignItems: 'center',
22
25
  borderBottom: `1px solid ${colors_1.LINE_COLOR}`,
23
26
  display: 'grid',
24
- gap: 12,
25
- gridTemplateColumns: '100px minmax(0, 1fr)',
27
+ gap: 8,
28
+ gridTemplateColumns: '100px minmax(0, 1fr) 24px',
26
29
  padding: '5px 12px',
27
30
  };
28
31
  const timing = {
@@ -77,18 +80,33 @@ const CaptionTextEditor = ({ captions, onChange, onSave, onCancel, readOnly }) =
77
80
  (0, react_1.useEffect)(() => {
78
81
  return commitPending;
79
82
  }, [commitPending]);
80
- const updateText = (0, react_1.useCallback)((index, text) => {
81
- var _a;
82
- if (((_a = latestRef.current.captions[index]) === null || _a === void 0 ? void 0 : _a.text) === text) {
83
+ const updateCaption = (0, react_1.useCallback)((index, changes) => {
84
+ const currentCaption = latestRef.current.captions[index];
85
+ if (!currentCaption) {
83
86
  return;
84
87
  }
85
88
  const nextCaptions = latestRef.current.captions.map((caption, captionIndex) => {
86
- return captionIndex === index ? { ...caption, text } : caption;
89
+ return captionIndex === index ? { ...caption, ...changes } : caption;
87
90
  });
88
91
  latestRef.current.captions = nextCaptions;
89
92
  dirtyRef.current = true;
90
93
  onChange(nextCaptions);
91
94
  }, [onChange]);
95
+ const updateText = (0, react_1.useCallback)((index, text) => {
96
+ var _a;
97
+ if (((_a = latestRef.current.captions[index]) === null || _a === void 0 ? void 0 : _a.text) === text) {
98
+ return;
99
+ }
100
+ updateCaption(index, { text });
101
+ }, [updateCaption]);
102
+ const updatePageBreakAfter = (0, react_1.useCallback)((index, pageBreakAfter) => {
103
+ var _a;
104
+ if (Boolean((_a = latestRef.current.captions[index]) === null || _a === void 0 ? void 0 : _a.pageBreakAfter) ===
105
+ pageBreakAfter) {
106
+ return;
107
+ }
108
+ updateCaption(index, { pageBreakAfter });
109
+ }, [updateCaption]);
92
110
  const focusSibling = (0, react_1.useCallback)((index) => {
93
111
  var _a;
94
112
  const input = (_a = listRef.current) === null || _a === void 0 ? void 0 : _a.querySelector(`[data-caption-index="${index}"]`);
@@ -96,6 +114,10 @@ const CaptionTextEditor = ({ captions, onChange, onSave, onCancel, readOnly }) =
96
114
  input === null || input === void 0 ? void 0 : input.scrollIntoView({ block: 'nearest' });
97
115
  }, []);
98
116
  return (jsx_runtime_1.jsx("div", { style: container, children: jsx_runtime_1.jsxs("div", { ref: listRef, style: list, children: [captions.length === 0 ? jsx_runtime_1.jsx("div", { style: empty, children: "No captions" }) : null, captionRows.map(({ caption, key }, index) => {
117
+ const hasPageBreakAfter = Boolean(caption.pageBreakAfter);
118
+ const pageBreakTitle = hasPageBreakAfter
119
+ ? `Remove page break after caption ${index + 1}`
120
+ : `Add page break after caption ${index + 1}`;
99
121
  return (jsx_runtime_1.jsxs("div", { style: row, children: [
100
122
  jsx_runtime_1.jsxs("div", { style: timing, children: [formatMilliseconds(caption.startMs), " \u2192", ' ', formatMilliseconds(caption.endMs), " ms"] }), jsx_runtime_1.jsx(RemInput_1.RemotionInput, { "data-caption-index": index, disabled: readOnly, onBlur: (event) => {
101
123
  if (cancelledBlurIndexes.current.delete(index)) {
@@ -125,8 +147,10 @@ const CaptionTextEditor = ({ captions, onChange, onSave, onCancel, readOnly }) =
125
147
  fontFamily: 'sans-serif',
126
148
  fontSize: 12,
127
149
  lineHeight: '16px',
128
- }, value: caption.text })
129
- ] }, key));
150
+ }, value: caption.text }), jsx_runtime_1.jsx(InlineAction_1.InlineAction, { "aria-pressed": hasPageBreakAfter, className: hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME, disabled: readOnly, onClick: () => {
151
+ updatePageBreakAfter(index, !hasPageBreakAfter);
152
+ commitPending();
153
+ }, renderAction: (color) => (jsx_runtime_1.jsx(enter_1.EnterIcon, { "aria-hidden": "true", color: hasPageBreakAfter ? colors_1.BLUE : color, focusable: "false", style: { height: 16, width: 16 } })), title: pageBreakTitle, variant: null })] }, key));
130
154
  })] }) }));
131
155
  };
132
156
  exports.CaptionTextEditor = CaptionTextEditor;
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ export declare const CodingAgentButton: React.FC<{
3
+ readonly label: 'Fix with' | 'Open in';
4
+ readonly prompt: string;
5
+ readonly size: 'compact' | 'default';
6
+ readonly style: React.CSSProperties | null;
7
+ }>;
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CodingAgentButton = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const open_in_editor_1 = require("../helpers/open-in-editor");
7
+ const AppLaunchButton_1 = require("./AppLaunchButton");
8
+ const CodingAgentIcon_1 = require("./CodingAgentIcon");
9
+ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
10
+ const SettingsContext_1 = require("./SettingsContext");
11
+ const use_configure_default_apps_1 = require("./use-configure-default-apps");
12
+ const menuLabel = {
13
+ color: 'inherit',
14
+ fontFamily: 'sans-serif',
15
+ fontSize: 13,
16
+ lineHeight: '16px',
17
+ };
18
+ const CodingAgentButton = ({ label, prompt, size, style }) => {
19
+ var _a, _b;
20
+ const { codingAgentInfo } = (0, SettingsContext_1.useSettings)();
21
+ const configureDefaultApps = (0, use_configure_default_apps_1.useConfigureDefaultApps)();
22
+ const installedCodingAgents = (_a = codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents) !== null && _a !== void 0 ? _a : [];
23
+ const defaultCodingAgent = (_b = installedCodingAgents.find((agent) => agent.id === (codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.defaultCodingAgent))) !== null && _b !== void 0 ? _b : installedCodingAgents[0];
24
+ const alternativeCodingAgents = installedCodingAgents.filter((agent) => agent.id !== (defaultCodingAgent === null || defaultCodingAgent === void 0 ? void 0 : defaultCodingAgent.id));
25
+ const openWithCodingAgent = (0, react_1.useCallback)(async (codingAgentId, codingAgentName) => {
26
+ try {
27
+ const response = await (0, open_in_editor_1.openInCodingAgent)(codingAgentId, codingAgentId === 'copilot' ? null : prompt);
28
+ if (!response.success) {
29
+ (0, NotificationCenter_1.showNotification)(`Could not open ${codingAgentName}`, 2000);
30
+ }
31
+ }
32
+ catch (err) {
33
+ (0, NotificationCenter_1.showNotification)(err.message, 2000);
34
+ }
35
+ }, [prompt]);
36
+ const agentMenuItems = (0, react_1.useMemo)(() => {
37
+ return alternativeCodingAgents.map((codingAgent) => ({
38
+ id: `open-in-${codingAgent.id}`,
39
+ keyHint: null,
40
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: codingAgent.name }),
41
+ leftItem: jsx_runtime_1.jsx(CodingAgentIcon_1.CodingAgentIcon, { codingAgentId: codingAgent.id, size: 18 }),
42
+ onClick: () => {
43
+ openWithCodingAgent(codingAgent.id, codingAgent.nameWithType).catch(() => undefined);
44
+ },
45
+ quickSwitcherLabel: null,
46
+ subMenu: null,
47
+ type: 'item',
48
+ value: `coding-agent-${codingAgent.id}`,
49
+ }));
50
+ }, [alternativeCodingAgents, openWithCodingAgent]);
51
+ if (!defaultCodingAgent) {
52
+ return null;
53
+ }
54
+ return (jsx_runtime_1.jsxs(AppLaunchButton_1.AppLaunchButton, { actionButtonId: null, ariaLabel: `${label} ${defaultCodingAgent.nameWithType}`, disabled: false, menuAriaLabel: `${label} another coding agent`, menuButtonId: null, menuItems: agentMenuItems, onConfigureApps: configureDefaultApps, onClick: () => {
55
+ openWithCodingAgent(defaultCodingAgent.id, defaultCodingAgent.nameWithType).catch(() => undefined);
56
+ }, size: size, style: style, title: `${label} ${defaultCodingAgent.nameWithType}`, children: [
57
+ jsx_runtime_1.jsx(CodingAgentIcon_1.CodingAgentIcon, { codingAgentId: defaultCodingAgent.id, size: size === 'default' ? 14 : 18 }), label, " ", defaultCodingAgent.name] }));
58
+ };
59
+ exports.CodingAgentButton = CodingAgentButton;
@@ -3,4 +3,5 @@ import type { ComboboxValue } from './NewComposition/ComboBox';
3
3
  export declare const CompositionContextButton: React.FC<{
4
4
  readonly visible: boolean;
5
5
  readonly getItems: () => ComboboxValue[];
6
+ readonly readOnlyStudio: boolean;
6
7
  }>;
@@ -4,9 +4,13 @@ exports.CompositionContextButton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const client_id_1 = require("../helpers/client-id");
7
+ const hoverable_1 = require("../helpers/hoverable");
7
8
  const ellipsis_1 = require("../icons/ellipsis");
8
9
  const InlineDropdown_1 = require("./InlineDropdown");
9
- const CompositionContextButton = ({ visible, getItems }) => {
10
+ const revealStyle = {
11
+ display: 'flex',
12
+ };
13
+ const CompositionContextButton = ({ visible, getItems, readOnlyStudio }) => {
10
14
  const iconStyle = (0, react_1.useMemo)(() => {
11
15
  return {
12
16
  style: {
@@ -19,9 +23,9 @@ const CompositionContextButton = ({ visible, getItems }) => {
19
23
  const renderAction = (0, react_1.useCallback)((color) => {
20
24
  return jsx_runtime_1.jsx(ellipsis_1.EllipsisIcon, { fill: color, svgProps: iconStyle });
21
25
  }, [iconStyle]);
22
- if (!visible || connectionStatus !== 'connected') {
26
+ if (!visible || (connectionStatus !== 'connected' && !readOnlyStudio)) {
23
27
  return null;
24
28
  }
25
- return (jsx_runtime_1.jsx(InlineDropdown_1.InlineDropdown, { renderAction: renderAction, getItems: getItems, variant: null }));
29
+ return (jsx_runtime_1.jsx("div", { className: hoverable_1.HOVER_GROUP_REVEAL_CLASS_NAME, style: revealStyle, children: jsx_runtime_1.jsx(InlineDropdown_1.InlineDropdown, { renderAction: renderAction, getItems: getItems, variant: null, style: hoverable_1.NO_HOVER_BACKGROUND_STYLE, className: hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME }) }));
26
30
  };
27
31
  exports.CompositionContextButton = CompositionContextButton;
@@ -10,7 +10,7 @@ const client_id_1 = require("../helpers/client-id");
10
10
  const colors_1 = require("../helpers/colors");
11
11
  const create_folder_tree_1 = require("../helpers/create-folder-tree");
12
12
  const persist_open_folders_1 = require("../helpers/persist-open-folders");
13
- const sort_by_nonce_history_1 = require("../helpers/sort-by-nonce-history");
13
+ const folders_1 = require("../state/folders");
14
14
  const modals_1 = require("../state/modals");
15
15
  const z_index_1 = require("../state/z-index");
16
16
  const CompositionSelectorItem_1 = require("./CompositionSelectorItem");
@@ -87,6 +87,7 @@ const getAutoScrollSpeed = ({ clientY, element, }) => {
87
87
  const CompositionSelector = () => {
88
88
  const { compositions, canvasContent, folders } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
89
89
  const { foldersExpanded } = (0, react_1.useContext)(persist_open_folders_1.ExpandedFoldersContext);
90
+ const { compositionSortOrder, setCompositionSortOrder } = (0, react_1.useContext)(folders_1.FolderContext);
90
91
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
91
92
  const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
92
93
  .previewServerState.type;
@@ -95,23 +96,27 @@ const CompositionSelector = () => {
95
96
  connectionStatus,
96
97
  readOnlyStudio: window.remotion_isReadOnlyStudio,
97
98
  setSelectedModal,
99
+ compositionSortOrder,
100
+ setCompositionSortOrder,
98
101
  });
99
- }, [connectionStatus, setSelectedModal]);
102
+ }, [
103
+ compositionSortOrder,
104
+ connectionStatus,
105
+ setCompositionSortOrder,
106
+ setSelectedModal,
107
+ ]);
100
108
  const [rootDragHovered, setRootDragHovered] = (0, react_1.useState)(false);
101
109
  const listRef = (0, react_1.useRef)(null);
102
110
  const autoScrollAnimation = (0, react_1.useRef)(null);
103
111
  const autoScrollSpeed = (0, react_1.useRef)(0);
104
112
  const { tabIndex } = (0, z_index_1.useZIndex)();
105
113
  const selectComposition = (0, InitialCompositionLoader_1.useSelectComposition)();
106
- const sortedCompositions = (0, react_1.useMemo)(() => {
107
- return (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(compositions);
108
- }, [compositions]);
109
- const sortedFolders = (0, react_1.useMemo)(() => {
110
- return (0, sort_by_nonce_history_1.sortItemsByNonceHistory)(folders);
111
- }, [folders]);
112
114
  const items = (0, react_1.useMemo)(() => {
113
- return (0, create_folder_tree_1.createFolderTree)(sortedCompositions, sortedFolders, foldersExpanded);
114
- }, [sortedCompositions, sortedFolders, foldersExpanded]);
115
+ const tree = (0, create_folder_tree_1.createFolderTree)(compositions, folders, foldersExpanded);
116
+ return compositionSortOrder === 'alphabetical'
117
+ ? (0, create_folder_tree_1.sortFolderTreeAlphabetically)(tree)
118
+ : tree;
119
+ }, [compositionSortOrder, compositions, folders, foldersExpanded]);
115
120
  const list = (0, react_1.useMemo)(() => {
116
121
  return {
117
122
  flex: 1,
@@ -239,7 +244,7 @@ const CompositionSelector = () => {
239
244
  }
240
245
  }, [compositions, stopCompositionListAutoScroll]);
241
246
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
242
- jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: listRef, getItems: getRootContextMenuItems }), jsx_runtime_1.jsx(ExplorerQuickSwitcherTrigger_1.ExplorerQuickSwitcherTrigger, { mode: "compositions", showShortcut: true, tabIndex: tabIndex }), jsx_runtime_1.jsx("div", { ref: listRef, className: "__remotion-vertical-scrollbar", style: list, onDragOverCapture: onCompositionListDragOverCapture, onDragEndCapture: stopCompositionListAutoScroll, onDragOver: onRootDragOver, onDragLeave: onRootDragLeave, onDropCapture: stopCompositionListAutoScroll, onDrop: onRootDrop, children: items.map((c) => {
247
+ jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: listRef, getItems: getRootContextMenuItems }), jsx_runtime_1.jsx(ExplorerQuickSwitcherTrigger_1.ExplorerQuickSwitcherTrigger, { mode: "compositions", showShortcut: true, tabIndex: tabIndex, getActions: getRootContextMenuItems }), jsx_runtime_1.jsx("div", { ref: listRef, className: "__remotion-vertical-scrollbar", style: list, onDragOverCapture: onCompositionListDragOverCapture, onDragEndCapture: stopCompositionListAutoScroll, onDragOver: onRootDragOver, onDragLeave: onRootDragLeave, onDropCapture: stopCompositionListAutoScroll, onDrop: onRootDrop, children: items.map((c) => {
243
248
  return (jsx_runtime_1.jsx(CompositionSelectorItem_1.CompositionSelectorItem, { level: 0, currentComposition: canvasContent && canvasContent.type === 'composition'
244
249
  ? canvasContent.compositionId
245
250
  : null, selectComposition: selectComposition, toggleFolder: toggleFolder, clearRootDragHover: clearRootDragHover, tabIndex: tabIndex, item: c }, c.key + c.type));