@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
@@ -39,7 +39,7 @@ const container = {
39
39
  const dialogContent = {
40
40
  ...container,
41
41
  padding: 16,
42
- width: 'min(640px, calc(100vw - 40px))',
42
+ width: 'min(520px, calc(100vw - 40px))',
43
43
  maxHeight: 'min(720px, calc(100vh - 140px))',
44
44
  overflowY: 'auto',
45
45
  };
@@ -85,8 +85,19 @@ const metadataDescriptionStyle = {
85
85
  lineHeight: 1.5,
86
86
  overflowWrap: 'anywhere',
87
87
  };
88
- const unverifiedSourceStyle = {
88
+ const requestSourceStyle = {
89
+ display: 'flex',
90
+ justifyContent: 'space-between',
91
+ gap: 16,
92
+ margin: 0,
93
+ };
94
+ const requestSourceDescriptionStyle = {
89
95
  ...metadataDescriptionStyle,
96
+ color: colors_1.LIGHT_TEXT,
97
+ textAlign: 'right',
98
+ };
99
+ const unverifiedRequestSourceStyle = {
100
+ ...requestSourceDescriptionStyle,
90
101
  color: colors_1.WARNING_COLOR,
91
102
  };
92
103
  const codeStyle = {
@@ -111,32 +122,13 @@ const dependencyListStyle = {
111
122
  padding: 0,
112
123
  listStyleType: 'none',
113
124
  };
114
- const dependencyRowStyle = {
115
- display: 'flex',
116
- alignItems: 'baseline',
117
- justifyContent: 'space-between',
118
- gap: 16,
119
- minWidth: 0,
120
- };
121
125
  const dependencyNameStyle = {
122
126
  minWidth: 0,
123
127
  color: colors_1.WHITE,
124
- fontFamily: 'monospace',
125
- fontSize: 13,
126
- lineHeight: 1.5,
127
- overflowWrap: 'anywhere',
128
- };
129
- const dependencyInstallStatusStyle = {
130
- flexShrink: 0,
131
- color: colors_1.WARNING_COLOR,
132
128
  fontFamily: 'sans-serif',
133
129
  fontSize: 13,
134
- fontWeight: 500,
135
130
  lineHeight: 1.5,
136
- };
137
- const dependencyInstalledStatusStyle = {
138
- ...dependencyInstallStatusStyle,
139
- color: colors_1.LIGHT_TEXT,
131
+ overflowWrap: 'anywhere',
140
132
  };
141
133
  const warningStyle = {
142
134
  display: 'flex',
@@ -160,6 +152,10 @@ const warningDescriptionStyle = {
160
152
  fontWeight: 400,
161
153
  lineHeight: 1.5,
162
154
  };
155
+ const installWarningDescriptionStyle = {
156
+ ...warningDescriptionStyle,
157
+ color: colors_1.WHITE,
158
+ };
163
159
  const browseElementsStyle = {
164
160
  color: 'inherit',
165
161
  fontFamily: 'inherit',
@@ -174,7 +170,7 @@ const sourceDetailsStyle = {
174
170
  lineHeight: 1.5,
175
171
  };
176
172
  const sourceSummaryStyle = {
177
- cursor: 'pointer',
173
+ cursor: 'default',
178
174
  color: colors_1.WHITE,
179
175
  fontFamily: 'sans-serif',
180
176
  fontSize: 13,
@@ -206,23 +202,29 @@ const destinationControlStyle = {
206
202
  display: 'flex',
207
203
  alignItems: 'center',
208
204
  justifyContent: 'space-between',
209
- gap: 16,
205
+ columnGap: 16,
206
+ rowGap: 10,
207
+ flexWrap: 'wrap',
210
208
  };
211
209
  const destinationOptionsStyle = {
212
210
  display: 'flex',
213
211
  overflow: 'hidden',
212
+ maxWidth: '100%',
213
+ marginLeft: 'auto',
214
214
  border: `1px solid ${colors_1.WHITE_ALPHA_12}`,
215
215
  borderRadius: 4,
216
216
  };
217
217
  const destinationOptionStyle = {
218
218
  appearance: 'none',
219
+ minHeight: 26,
219
220
  border: 0,
220
221
  cursor: 'default',
221
222
  fontFamily: 'sans-serif',
222
- fontSize: 11,
223
+ fontSize: 12,
223
224
  fontWeight: 400,
224
- lineHeight: 1.5,
225
- padding: '2px 7px',
225
+ lineHeight: '18px',
226
+ padding: '4px 8px',
227
+ whiteSpace: 'nowrap',
226
228
  };
227
229
  const getDestinationOptionStyle = ({ disabled, selected, }) => ({
228
230
  ...destinationOptionStyle,
@@ -240,6 +242,7 @@ const footerStyle = {
240
242
  const cancelStyle = {
241
243
  minWidth: 90,
242
244
  };
245
+ const elementInstallTitleId = 'remotion-element-install-title';
243
246
  const makeSourceControlsVisible = (sourceCode) => {
244
247
  return sourceCode.replace(/[\u200b-\u200f\u202a-\u202e\u2066-\u2069\ufeff]/g, (character) => {
245
248
  var _a;
@@ -264,8 +267,8 @@ const ElementLibraryAddConfirmation = ({ displayName, origin, url }) => {
264
267
  };
265
268
  exports.ElementLibraryAddConfirmation = ElementLibraryAddConfirmation;
266
269
  const ElementInstallConfirmation = ({ state }) => {
267
- var _a, _b;
268
- const { currentPlan, dependenciesToReview, missingPackages, newPlan, onClose, request, sourceIsUnverified, sourceLabel, } = state;
270
+ var _a;
271
+ const { currentPlan, missingPackages, newPlan, onClose, request, sourceIsUnverified, sourceLabel, } = state;
269
272
  const config = remotion_1.Internals.useUnsafeVideoConfig();
270
273
  const { canvasContent, compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
271
274
  const currentCompositionMetadata = config === null ||
@@ -283,6 +286,8 @@ const ElementInstallConfirmation = ({ state }) => {
283
286
  const [mode, setMode] = (0, react_1.useState)(currentPlan === null ? 'new-composition' : 'current-composition');
284
287
  const [submitting, setSubmitting] = (0, react_1.useState)(false);
285
288
  const inputRef = (0, react_1.useRef)(null);
289
+ const currentDestinationRef = (0, react_1.useRef)(null);
290
+ const newDestinationRef = (0, react_1.useRef)(null);
286
291
  const [newCompositionValues, setNewCompositionValues] = (0, react_1.useState)(() => {
287
292
  var _a, _b, _c, _d, _e;
288
293
  const elementComponentName = (_a = studio_protocol_1.StudioProtocolInternals.getElementComponentNameFromSourceCode(request.element.sourceCode)) !== null && _a !== void 0 ? _a : 'Element';
@@ -400,6 +405,7 @@ const ElementInstallConfirmation = ({ state }) => {
400
405
  const selectedPlan = mode === 'current-composition' ? currentPlan : selectedNewCompositionPlan;
401
406
  const folderTargetIsReady = selectedFolderStack === null ||
402
407
  ((0, use_resolved_stack_1.hasResolvedStack)(selectedFolderStack) && folderCompositionFile !== null);
408
+ const title = `Install ${request.element.displayName}${request.element.displayName.endsWith(' Element') ? '' : ' Element'}`;
403
409
  const canSubmit = !submitting &&
404
410
  (mode === 'current-composition'
405
411
  ? currentPlan !== null
@@ -468,63 +474,67 @@ const ElementInstallConfirmation = ({ state }) => {
468
474
  onClose();
469
475
  }
470
476
  }, [onClose, submitting]);
477
+ const onDestinationKeyDown = (0, react_1.useCallback)((event) => {
478
+ if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown'].includes(event.key)) {
479
+ return;
480
+ }
481
+ event.preventDefault();
482
+ if (currentPlan === null) {
483
+ return;
484
+ }
485
+ const nextMode = mode === 'current-composition'
486
+ ? 'new-composition'
487
+ : 'current-composition';
488
+ setMode(nextMode);
489
+ requestAnimationFrame(() => {
490
+ var _a, _b;
491
+ if (nextMode === 'current-composition') {
492
+ (_a = currentDestinationRef.current) === null || _a === void 0 ? void 0 : _a.focus();
493
+ }
494
+ else {
495
+ (_b = newDestinationRef.current) === null || _b === void 0 ? void 0 : _b.focus();
496
+ }
497
+ });
498
+ }, [currentPlan, mode]);
471
499
  const onSubmit = (0, react_1.useCallback)((event) => {
472
500
  event.preventDefault();
473
501
  submit();
474
502
  }, [submit]);
475
- return (0, react_dom_1.createPortal)(jsx_runtime_1.jsxs(ModalContainer_1.ModalContainer, { onOutsideClick: cancel, onEscape: cancel, children: [
476
- jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "Install Element", onClose: cancel }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
503
+ return (0, react_dom_1.createPortal)(jsx_runtime_1.jsxs(ModalContainer_1.ModalContainer, { ariaLabelledBy: elementInstallTitleId, onOutsideClick: cancel, onEscape: cancel, children: [
504
+ jsx_runtime_1.jsx("div", { id: elementInstallTitleId, children: jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: title, onClose: cancel }) }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
477
505
  jsx_runtime_1.jsxs("div", { style: dialogContent, children: [
478
- jsx_runtime_1.jsxs("div", { style: destinationControlStyle, children: [
479
- jsx_runtime_1.jsx("div", { style: sectionTitleStyle, children: "Add to" }), jsx_runtime_1.jsxs("div", { "aria-label": "Installation destination", role: "group", style: destinationOptionsStyle, children: [
480
- jsx_runtime_1.jsx("button", { "aria-pressed": mode === 'current-composition', className: `${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME}`, disabled: currentPlan === null, onClick: () => setMode('current-composition'), style: getDestinationOptionStyle({
506
+ jsx_runtime_1.jsxs("dl", { style: requestSourceStyle, "aria-label": "Request source", children: [
507
+ jsx_runtime_1.jsx("dt", { style: sectionTitleStyle, children: "From" }), jsx_runtime_1.jsx("dd", { style: sourceIsUnverified
508
+ ? unverifiedRequestSourceStyle
509
+ : requestSourceDescriptionStyle, children: sourceLabel })
510
+ ] }), jsx_runtime_1.jsxs("div", { style: destinationControlStyle, children: [
511
+ jsx_runtime_1.jsx("div", { style: sectionTitleStyle, children: "Destination" }), jsx_runtime_1.jsxs("div", { "aria-label": "Installation destination", onKeyDown: onDestinationKeyDown, role: "radiogroup", style: destinationOptionsStyle, children: [
512
+ jsx_runtime_1.jsx("button", { ref: currentDestinationRef, "aria-checked": mode === 'current-composition', className: `${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME}`, disabled: currentPlan === null, onClick: () => setMode('current-composition'), role: "radio", style: getDestinationOptionStyle({
481
513
  disabled: currentPlan === null,
482
514
  selected: mode === 'current-composition',
483
- }), type: "button", children: "Current composition" }), jsx_runtime_1.jsx("button", { "aria-pressed": mode === 'new-composition', className: `${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME}`, onClick: () => {
515
+ }), tabIndex: mode === 'current-composition' ? 0 : -1, type: "button", children: "Current composition" }), jsx_runtime_1.jsx("button", { ref: newDestinationRef, "aria-checked": mode === 'new-composition', className: `${hoverable_1.HOVERABLE_CLASS_NAME} ${hoverable_1.FOCUS_VISIBLE_ONLY_CLASS_NAME}`, onClick: () => {
484
516
  setMode('new-composition');
485
517
  requestAnimationFrame(() => {
486
518
  var _a;
487
519
  return (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.select();
488
520
  });
489
- }, style: {
521
+ }, role: "radio", style: {
490
522
  ...getDestinationOptionStyle({
491
523
  disabled: false,
492
524
  selected: mode === 'new-composition',
493
525
  }),
494
526
  borderLeft: `1px solid ${colors_1.WHITE_ALPHA_12}`,
495
- }, type: "button", children: "New composition" })
527
+ }, tabIndex: mode === 'new-composition' ? 0 : -1, type: "button", children: "New composition" })
496
528
  ] })
497
529
  ] }), currentPlan === null ? (jsx_runtime_1.jsxs("div", { style: warningStyle, role: "status", children: [
498
- jsx_runtime_1.jsx(ValidationMessage_1.WarningTriangle, { style: warningIconStyle }), jsx_runtime_1.jsxs("p", { style: warningDescriptionStyle, children: ["Studio could not find a safe place in \u201C", request.compositionId, "\u201D to insert the Element. Install it into a new composition instead."] })
530
+ jsx_runtime_1.jsx(ValidationMessage_1.WarningTriangle, { style: warningIconStyle }), jsx_runtime_1.jsxs("p", { style: installWarningDescriptionStyle, children: ["Studio could not find a safe place in \u201C", request.compositionId, "\u201D to insert the Element. Install it into a new composition instead."] })
499
531
  ] })) : null, mode === 'new-composition' ? (jsx_runtime_1.jsxs("section", { style: sectionStyle, "aria-label": "New composition settings", children: [
500
- jsx_runtime_1.jsx(NewComposition_1.NewCompositionFields, { heightValidationMessage: heightValidationMessage, inputRef: inputRef, nameValidationMessage: nameValidationMessage, setValues: setNewCompositionValues, values: newCompositionValues, widthValidationMessage: widthValidationMessage }), (activeNewCompositionPlanState === null || activeNewCompositionPlanState === void 0 ? void 0 : activeNewCompositionPlanState.type) === 'error' ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: activeNewCompositionPlanState.reason, type: "error" })) : null] })) : null, jsx_runtime_1.jsxs("dl", { style: metadataStyle, "aria-label": "Installation details", children: [
501
- jsx_runtime_1.jsxs("div", { style: metadataRowStyle, children: [
502
- jsx_runtime_1.jsx("dt", { style: metadataTermStyle, children: "Element" }), jsx_runtime_1.jsx("dd", { style: metadataDescriptionStyle, children: request.element.displayName })
503
- ] }), jsx_runtime_1.jsxs("div", { style: metadataRowStyle, children: [
504
- jsx_runtime_1.jsx("dt", { style: metadataTermStyle, children: "Request source" }), jsx_runtime_1.jsx("dd", { style: sourceIsUnverified
505
- ? unverifiedSourceStyle
506
- : metadataDescriptionStyle, children: sourceLabel })
507
- ] }), jsx_runtime_1.jsxs("div", { style: metadataRowStyle, children: [
508
- jsx_runtime_1.jsx("dt", { style: metadataTermStyle, children: "Composition" }), jsx_runtime_1.jsx("dd", { style: metadataDescriptionStyle, children: jsx_runtime_1.jsx("code", { style: codeStyle, children: mode === 'current-composition'
509
- ? request.compositionId
510
- : newCompositionValues.id }) })
511
- ] }), jsx_runtime_1.jsxs("div", { style: metadataRowStyle, children: [
512
- jsx_runtime_1.jsx("dt", { style: metadataTermStyle, children: "Destination" }), jsx_runtime_1.jsx("dd", { style: metadataDescriptionStyle, children: jsx_runtime_1.jsx("code", { style: codeStyle, children: (_b = selectedPlan === null || selectedPlan === void 0 ? void 0 : selectedPlan.filePath) !== null && _b !== void 0 ? _b : 'Reviewing destination…' }) })
513
- ] }), (selectedPlan === null || selectedPlan === void 0 ? void 0 : selectedPlan.expectedFileState.exists) ? (jsx_runtime_1.jsxs("div", { style: metadataRowStyle, children: [
514
- jsx_runtime_1.jsx("dt", { style: metadataTermStyle, children: "File change" }), jsx_runtime_1.jsx("dd", { style: overwriteStyle, children: "Replace existing source file" })
515
- ] })) : null] }), dependenciesToReview.length > 0 ? (jsx_runtime_1.jsxs("section", { style: sectionStyle, "aria-labelledby": "element-install-dependencies", children: [
516
- jsx_runtime_1.jsx("h3", { id: "element-install-dependencies", style: sectionTitleStyle, children: "Dependencies" }), jsx_runtime_1.jsx("ul", { style: dependencyListStyle, role: "list", children: dependenciesToReview.map((packageName) => {
517
- const willInstall = missingPackages.includes(packageName);
518
- return (jsx_runtime_1.jsxs("li", { style: dependencyRowStyle, children: [
519
- jsx_runtime_1.jsx("div", { style: dependencyNameStyle, children: packageName }), jsx_runtime_1.jsx("div", { style: willInstall
520
- ? dependencyInstallStatusStyle
521
- : dependencyInstalledStatusStyle, children: willInstall ? 'Will be installed' : 'Installed' })
522
- ] }, packageName));
523
- }) })
532
+ jsx_runtime_1.jsx(NewComposition_1.NewCompositionFields, { heightValidationMessage: heightValidationMessage, inputRef: inputRef, nameValidationMessage: nameValidationMessage, setValues: setNewCompositionValues, values: newCompositionValues, widthValidationMessage: widthValidationMessage }), (activeNewCompositionPlanState === null || activeNewCompositionPlanState === void 0 ? void 0 : activeNewCompositionPlanState.type) === 'error' ? (jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: activeNewCompositionPlanState.reason, type: "error" })) : null] })) : null, (selectedPlan === null || selectedPlan === void 0 ? void 0 : selectedPlan.expectedFileState.exists) ? (jsx_runtime_1.jsx("p", { style: overwriteStyle, role: "status", children: "This will replace the existing Element source file." })) : null, missingPackages.length > 0 ? (jsx_runtime_1.jsxs("section", { style: sectionStyle, "aria-labelledby": "element-install-dependencies", children: [
533
+ jsx_runtime_1.jsx("h3", { id: "element-install-dependencies", style: sectionTitleStyle, children: "Packages to install" }), jsx_runtime_1.jsx("ul", { style: dependencyListStyle, role: "list", children: missingPackages.map((packageName) => (jsx_runtime_1.jsx("li", { style: dependencyNameStyle, children: packageName }, packageName))) })
524
534
  ] })) : null, jsx_runtime_1.jsxs("div", { style: warningStyle, children: [
525
- jsx_runtime_1.jsx(ValidationMessage_1.WarningTriangle, { style: warningIconStyle }), jsx_runtime_1.jsxs("p", { style: warningDescriptionStyle, children: ["This adds executable source code to your project.", usesBrowserDependencyResolution
535
+ jsx_runtime_1.jsx(ValidationMessage_1.WarningTriangle, { style: warningIconStyle }), jsx_runtime_1.jsxs("p", { style: installWarningDescriptionStyle, children: ["This adds executable source code to your project, with access to your files and the network.", usesBrowserDependencyResolution || missingPackages.length === 0
526
536
  ? null
527
- : ' Package lifecycle scripts may also run during installation, with access to your files and the network.'] })
537
+ : ' Package lifecycle scripts may also run during installation.'] })
528
538
  ] }), jsx_runtime_1.jsxs("details", { style: sourceDetailsStyle, children: [
529
539
  jsx_runtime_1.jsx("summary", { style: sourceSummaryStyle, children: "Source code" }), jsx_runtime_1.jsx("pre", { style: sourceCodeBlockStyle, children: jsx_runtime_1.jsx("code", { style: sourceCodeStyle, children: makeSourceControlsVisible(request.element.sourceCode) }) })
530
540
  ] })
@@ -15,6 +15,7 @@ const panelStyle = {
15
15
  };
16
16
  const iframeStyle = {
17
17
  border: 0,
18
+ colorScheme: 'dark',
18
19
  flex: 1,
19
20
  minHeight: 0,
20
21
  width: '100%',
@@ -31,10 +32,11 @@ const ElementLibraryModal = ({ name, url }) => {
31
32
  iframe.setAttribute('credentialless', '');
32
33
  const iframeUrl = new URL(url);
33
34
  iframeUrl.searchParams.set('remotion-studio', 'true');
35
+ iframeUrl.searchParams.set('docusaurus-theme', 'dark');
34
36
  iframe.src = iframeUrl.toString();
35
37
  }, [url]);
36
38
  return (jsx_runtime_1.jsxs(DismissableModal_1.DismissableModal, { panelStyle: panelStyle, children: [
37
- jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: name }), jsx_runtime_1.jsx("iframe", { ref: iframeRef, allow: "local-network-access; loopback-network", style: iframeStyle, title: `${name} library` })
39
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: name }), jsx_runtime_1.jsx("iframe", { ref: iframeRef, allow: "local-network-access; loopback-network", "data-remotion-element-library": "", style: iframeStyle, title: `${name} library` })
38
40
  ] }));
39
41
  };
40
42
  exports.ElementLibraryModal = ElementLibraryModal;
@@ -107,6 +107,42 @@ const InlineCaptionInspector = ({ captions, controls, expanded, nodePath, onTogg
107
107
  setPropStatuses,
108
108
  validatedLocation.source,
109
109
  ]);
110
+ const replaceCaptions = (0, react_1.useCallback)((nextCaptions) => {
111
+ if (!canSave || clientId === null) {
112
+ return;
113
+ }
114
+ setDraftCaptions(nextCaptions);
115
+ setDragOverrides(nodePath, 'captions', remotion_1.Internals.makeStaticDragOverride(nextCaptions));
116
+ savedCaptions.current = nextCaptions;
117
+ (0, save_sequence_prop_1.saveSequenceProps)({
118
+ changes: [
119
+ {
120
+ fileName: validatedLocation.source,
121
+ nodePath,
122
+ fieldKey: 'captions',
123
+ value: nextCaptions,
124
+ defaultValue: null,
125
+ schema: controls.schema,
126
+ },
127
+ ],
128
+ addedKeyframes: null,
129
+ movedKeyframes: null,
130
+ setPropStatuses,
131
+ clientId,
132
+ undoLabel: 'Import captions',
133
+ redoLabel: 'Import captions again',
134
+ });
135
+ clearDragOverrides(nodePath);
136
+ }, [
137
+ canSave,
138
+ clearDragOverrides,
139
+ clientId,
140
+ controls.schema,
141
+ nodePath,
142
+ setDragOverrides,
143
+ setPropStatuses,
144
+ validatedLocation.source,
145
+ ]);
110
146
  const readOnlyTitle = readOnlyStudio
111
147
  ? 'Caption editing is unavailable in read-only Studio'
112
148
  : clientId === null
@@ -114,6 +150,6 @@ const InlineCaptionInspector = ({ captions, controls, expanded, nodePath, onTogg
114
150
  : (captionStatus === null || captionStatus === void 0 ? void 0 : captionStatus.status) === 'computed'
115
151
  ? 'Captions must be a direct inline JSX array to edit them'
116
152
  : 'Captions are not ready for editing';
117
- return (jsx_runtime_1.jsx(CaptionInspector_1.CaptionInspector, { captions: draftCaptions, expanded: expanded, onTextChange: updateCaptions, onTextSave: saveCaptions, onTextCancel: cancelCaptions, onToggle: onToggle, readOnly: !canSave, readOnlyTitle: canSave ? null : readOnlyTitle }));
153
+ return (jsx_runtime_1.jsx(CaptionInspector_1.CaptionInspector, { captions: draftCaptions, expanded: expanded, onTextChange: updateCaptions, onTextSave: saveCaptions, onTextCancel: cancelCaptions, onToggle: onToggle, readOnly: !canSave, readOnlyTitle: canSave ? null : readOnlyTitle, onReplaceCaptions: canSave ? replaceCaptions : null }));
118
154
  };
119
155
  exports.InlineCaptionInspector = InlineCaptionInspector;
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ElementLibraryButton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const browser_studio_operations_1 = require("../../helpers/browser-studio-operations");
7
6
  const colors_1 = require("../../helpers/colors");
8
7
  const browse_elements_1 = require("../../icons/browse-elements");
9
8
  const caret_1 = require("../../icons/caret");
@@ -23,13 +22,6 @@ const browseElementsIconContainerStyle = {
23
22
  marginRight: -2,
24
23
  width: 22,
25
24
  };
26
- const browseElementsArrowStyle = {
27
- display: 'inline-block',
28
- height: 12,
29
- marginLeft: 4,
30
- verticalAlign: -2,
31
- width: 12,
32
- };
33
25
  const elementLibraryDropdownStyle = {
34
26
  borderRadius: 4,
35
27
  height: 28,
@@ -63,19 +55,14 @@ const ElementLibraryButton = () => {
63
55
  var _a;
64
56
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
65
57
  const { studioRuntimeConfig } = (0, SettingsContext_1.useSettings)();
66
- const isBrowserStudio = (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null;
67
58
  const elementLibraries = (_a = studioRuntimeConfig === null || studioRuntimeConfig === void 0 ? void 0 : studioRuntimeConfig.elementLibraries) !== null && _a !== void 0 ? _a : noElementLibraries;
68
59
  const openElementLibrary = (0, react_1.useCallback)((name, url) => {
69
- if (isBrowserStudio) {
70
- window.open(url, '_blank', 'noopener,noreferrer');
71
- return;
72
- }
73
60
  setSelectedModal({
74
61
  type: 'element-library',
75
62
  name,
76
63
  url,
77
64
  });
78
- }, [isBrowserStudio, setSelectedModal]);
65
+ }, [setSelectedModal]);
79
66
  const openElementsLibrary = (0, react_1.useCallback)(() => {
80
67
  openElementLibrary('Remotion Elements', 'https://www.remotion.dev/elements');
81
68
  }, [openElementLibrary]);
@@ -129,11 +116,9 @@ const ElementLibraryButton = () => {
129
116
  ],
130
117
  },
131
118
  ], [elementLibraries, openElementLibrary, openElementsLibrary]);
132
- if (elementLibraries.length > 0 && !isBrowserStudio) {
119
+ if (elementLibraries.length > 0) {
133
120
  return (jsx_runtime_1.jsx(SegmentedButton_1.SegmentedButton, { segments: elementLibraryDropdownSegments, style: elementLibraryDropdownStyle, title: null }));
134
121
  }
135
- return (jsx_runtime_1.jsxs(common_1.InspectorQuickAction, { disabled: false, iconContainerStyle: browseElementsIconContainerStyle, onClick: openElementsLibrary, renderIcon: (color) => (jsx_runtime_1.jsx(browse_elements_1.BrowseElementsIcon, { color: color, style: browseElementsIconStyle })), title: isBrowserStudio
136
- ? 'Open the Remotion Elements library in a new tab. Install an Element there to send it to this composition.'
137
- : 'Browse the Remotion Elements library inside Studio.', children: ["Browse Elements", isBrowserStudio ? (jsx_runtime_1.jsx("svg", { "aria-hidden": "true", viewBox: "0 0 16 16", style: browseElementsArrowStyle, children: jsx_runtime_1.jsx("path", { d: "M4 12 12 4M6 4h6v6", fill: "none", stroke: colors_1.CURRENT_COLOR, strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5" }) })) : null] }));
122
+ return (jsx_runtime_1.jsx(common_1.InspectorQuickAction, { disabled: false, iconContainerStyle: browseElementsIconContainerStyle, onClick: openElementsLibrary, renderIcon: (color) => (jsx_runtime_1.jsx(browse_elements_1.BrowseElementsIcon, { color: color, style: browseElementsIconStyle })), title: "Browse the Remotion Elements library inside Studio.", children: "Browse Elements" }));
138
123
  };
139
124
  exports.ElementLibraryButton = ElementLibraryButton;
@@ -22,7 +22,6 @@ const CollapsibleInspectorSectionHeader_1 = require("./InspectorPanel/Collapsibl
22
22
  const common_1 = require("./InspectorPanel/common");
23
23
  const inspector_section_collapse_1 = require("./InspectorPanel/inspector-section-collapse");
24
24
  const styles_1 = require("./InspectorPanel/styles");
25
- const asset_search_1 = require("./QuickSwitcher/asset-search");
26
25
  const border_radius_representation_1 = require("./Timeline/border-radius-representation");
27
26
  const save_sequence_prop_1 = require("./Timeline/save-sequence-prop");
28
27
  const timeline_asset_link_1 = require("./Timeline/timeline-asset-link");
@@ -226,7 +225,6 @@ const InspectorSequenceSection = ({ sequence, readOnlyStudio, validatedLocation,
226
225
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
227
226
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
228
227
  const mediaSrc = (0, timeline_asset_link_1.getTimelineAssetSrcFromSchema)(sequence.controls, runtimeValues);
229
- const assetSelectionInitialQuery = (0, asset_search_1.getAssetSearchQueryForComponent)(sequence.controls.componentIdentity);
230
228
  const getSourceAction = (0, react_1.useCallback)((src) => {
231
229
  var _a;
232
230
  const linkInfo = (0, timeline_asset_link_1.getTimelineAssetLinkInfo)(src);
@@ -258,9 +256,8 @@ const InspectorSequenceSection = ({ sequence, readOnlyStudio, validatedLocation,
258
256
  }, [getSourceAction, mediaSrc]);
259
257
  const assetSelectionContextValue = (0, react_1.useMemo)(() => ({
260
258
  getSourceAction,
261
- initialQuery: assetSelectionInitialQuery,
262
259
  sourceAction,
263
- }), [assetSelectionInitialQuery, getSourceAction, sourceAction]);
260
+ }), [getSourceAction, sourceAction]);
264
261
  const getIsExpanded = (0, react_1.useCallback)((candidate) => {
265
262
  return !collapsedKeys.has(getInspectorExpansionKey(candidate));
266
263
  }, [collapsedKeys]);
@@ -62,7 +62,7 @@ const MenuSubItem = ({ label, leaveLeftSpace, leftItem, onActionChosen, id, sele
62
62
  };
63
63
  }, [selected, disabled]);
64
64
  const onPointerUp = (0, react_1.useCallback)((e) => {
65
- if (disabled) {
65
+ if (disabled || e.button !== 0) {
66
66
  return;
67
67
  }
68
68
  if (subMenu) {
@@ -2,6 +2,7 @@ import React from 'react';
2
2
  export declare const getMaxModalWidth: (width: number) => string;
3
3
  export declare const getMaxModalHeight: (height: number) => string;
4
4
  export declare const ModalContainer: React.FC<{
5
+ readonly ariaLabelledBy?: string;
5
6
  readonly onEscape: () => void;
6
7
  readonly onOutsideClick: () => void;
7
8
  readonly children: React.ReactNode;
@@ -29,11 +29,11 @@ const panel = {
29
29
  color: colors_1.WHITE,
30
30
  margin: 'auto',
31
31
  };
32
- const ModalContainer = ({ children, onEscape, onOutsideClick, noZIndex, panelStyle }) => {
32
+ const ModalContainer = ({ ariaLabelledBy, children, onEscape, onOutsideClick, noZIndex, panelStyle, }) => {
33
33
  const onPointerDown = (0, react_1.useCallback)((e) => {
34
34
  // Prevent deselection of currently selected items
35
35
  e.stopPropagation();
36
36
  }, []);
37
- return (jsx_runtime_1.jsx("div", { className: "css-reset", style: backgroundOverlay, role: "dialog", "aria-modal": "true", onPointerDown: onPointerDown, children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { disabled: noZIndex, onOutsideClick: onOutsideClick, onEscape: onEscape, children: jsx_runtime_1.jsx("div", { style: { ...panel, ...panelStyle }, children: children }) }) }));
37
+ return (jsx_runtime_1.jsx("div", { "aria-labelledby": ariaLabelledBy !== null && ariaLabelledBy !== void 0 ? ariaLabelledBy : undefined, "aria-modal": "true", className: "css-reset", role: "dialog", style: backgroundOverlay, onPointerDown: onPointerDown, children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { disabled: noZIndex, onOutsideClick: onOutsideClick, onEscape: onEscape, children: jsx_runtime_1.jsx("div", { style: { ...panel, ...panelStyle }, children: children }) }) }));
38
38
  };
39
39
  exports.ModalContainer = ModalContainer;
@@ -16,8 +16,12 @@ const container = {
16
16
  borderBottom: colors_1.BORDER_BLACK,
17
17
  };
18
18
  const titleStyle = {
19
- fontSize: 14,
20
19
  color: colors_1.WHITE,
20
+ fontSize: 14,
21
+ minWidth: 0,
22
+ overflow: 'hidden',
23
+ textOverflow: 'ellipsis',
24
+ whiteSpace: 'nowrap',
21
25
  };
22
26
  const icon = {
23
27
  height: 20,
@@ -6,4 +6,3 @@ export declare const filterAssetsByType: ({ assets, query, }: {
6
6
  readonly assets: StaticFile[];
7
7
  readonly query: string;
8
8
  };
9
- export declare const getAssetSearchQueryForComponent: (componentIdentity: string | null) => string;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAssetSearchQueryForComponent = exports.filterAssetsByType = void 0;
3
+ exports.filterAssetsByType = void 0;
4
4
  const get_preview_file_type_1 = require("../../helpers/get-preview-file-type");
5
5
  const typeFilterRegex = /(^|\s)type:([^\s]+)/gi;
6
6
  const filterAssetsByType = ({ assets, query, }) => {
@@ -26,18 +26,3 @@ const filterAssetsByType = ({ assets, query, }) => {
26
26
  };
27
27
  };
28
28
  exports.filterAssetsByType = filterAssetsByType;
29
- const componentAssetTypes = {
30
- 'dev.remotion.media.Audio': 'audio',
31
- 'dev.remotion.media.Video': 'video',
32
- 'dev.remotion.remotion.AnimatedImage': 'image',
33
- 'dev.remotion.remotion.CanvasImage': 'image',
34
- 'dev.remotion.remotion.Img': 'image',
35
- };
36
- const getAssetSearchQueryForComponent = (componentIdentity) => {
37
- if (componentIdentity === null) {
38
- return '';
39
- }
40
- const assetType = componentAssetTypes[componentIdentity];
41
- return assetType ? `type:${assetType} ` : '';
42
- };
43
- exports.getAssetSearchQueryForComponent = getAssetSearchQueryForComponent;
@@ -282,7 +282,7 @@ const RenderButtonInner = ({ readOnlyStudio, size: controlSize = 'default', narr
282
282
  {
283
283
  type: 'item',
284
284
  id: 'client-render',
285
- label: 'Render on web',
285
+ label: 'Render in browser',
286
286
  value: 'client-render',
287
287
  onClick: () => handleRenderTypeChange('client-render'),
288
288
  keyHint: null,
@@ -336,7 +336,7 @@ const RenderButtonInner = ({ readOnlyStudio, size: controlSize = 'default', narr
336
336
  ? 'Render'
337
337
  : renderType === 'render-command'
338
338
  ? 'Render via CLI'
339
- : 'Render on web';
339
+ : 'Render in browser';
340
340
  const showRenderLabel = !narrow || renderType !== 'server-render';
341
341
  const segments = (0, react_1.useMemo)(() => {
342
342
  return [
@@ -41,6 +41,7 @@ const buttonRow = {
41
41
  justifyContent: 'flex-end',
42
42
  };
43
43
  const RenderStatusModal = ({ jobId, }) => {
44
+ var _a;
44
45
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.SetSelectedModalContext);
45
46
  const { jobs, removeClientJob, cancelClientJob } = (0, react_1.useContext)(context_1.RenderQueueContext);
46
47
  const job = jobs.find((j) => j.id === jobId);
@@ -88,9 +89,14 @@ const RenderStatusModal = ({ jobId, }) => {
88
89
  if (job.status === 'idle') {
89
90
  throw new Error('should not have rendered this modal');
90
91
  }
92
+ const errorDetails = job.status === 'failed'
93
+ ? ((_a = job.error.stack) === null || _a === void 0 ? void 0 : _a.split('\n')[0].includes(job.error.message))
94
+ ? job.error.stack
95
+ : [job.error.message, job.error.stack].filter(Boolean).join('\n')
96
+ : null;
91
97
  return (jsx_runtime_1.jsxs(ModalContainer_1.ModalContainer, { onOutsideClick: onQuit, onEscape: onQuit, children: [
92
98
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Render ${job.compositionId}` }), jsx_runtime_1.jsxs("div", { style: container, children: [job.status === 'failed' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
93
- jsx_runtime_1.jsx("p", { children: "The render failed because of the following error:" }), jsx_runtime_1.jsx("div", { className: is_menu_item_1.HORIZONTAL_SCROLLBAR_CLASSNAME, style: codeBlock, children: job.error.stack })
99
+ jsx_runtime_1.jsx("p", { children: "The render failed because of the following error:" }), jsx_runtime_1.jsx("div", { className: is_menu_item_1.HORIZONTAL_SCROLLBAR_CLASSNAME, style: codeBlock, children: errorDetails })
94
100
  ] })) : null, (job.status === 'done' || job.status === 'running') &&
95
101
  (isClientJob ? (jsx_runtime_1.jsx(ClientRenderProgress_1.ClientRenderProgress, { job: job })) : (jsx_runtime_1.jsx(GuiRenderStatus_1.GuiRenderStatus, { job: job }))), jsx_runtime_1.jsx("div", { style: spacer }), jsx_runtime_1.jsxs("div", { style: buttonRow, children: [job.status === 'running' ? (jsx_runtime_1.jsx(Button_1.Button, { onClick: onClickOnCancel, children: "Cancel render" })) : (jsx_runtime_1.jsx(Button_1.Button, { onClick: onClickOnRemove, children: "Remove render" })), jsx_runtime_1.jsx(layout_1.Flex, {}), job.status === 'failed' ? (jsx_runtime_1.jsx(Button_1.Button, { onClick: onRetry, children: "Retry" })) : null, jsx_runtime_1.jsx("div", { style: spacer }), jsx_runtime_1.jsx(Button_1.Button, { onClick: onQuit, children: "Close" })
96
102
  ] })
@@ -981,7 +981,7 @@ const RenderModal = ({ readOnlyStudio, initialFrame, initialVideoImageFormat, in
981
981
  });
982
982
  }, [availablePixelFormats, pixelFormat]);
983
983
  return (jsx_runtime_1.jsxs("div", { style: render_modals_1.outerModalStyle, children: [
984
- jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id}` }), jsx_runtime_1.jsxs("div", { style: render_modals_1.container, children: [
984
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id} ${readOnlyStudio ? 'via CLI' : 'on the server'}` }), jsx_runtime_1.jsxs("div", { style: render_modals_1.container, children: [
985
985
  jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: renderTabOptions, needsWrapping: false }), jsx_runtime_1.jsx("div", { style: render_modals_1.flexer }), jsx_runtime_1.jsxs(Button_1.Button, { autoFocus: true, onClick: trigger, disabled: renderDisabled, style: {
986
986
  ...render_modals_1.buttonStyle,
987
987
  backgroundColor: outnameValidation.valid ? colors_1.BLUE : colors_1.BLUE_DISABLED,
@@ -416,7 +416,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
416
416
  pageResponsiveness,
417
417
  ]);
418
418
  return (jsx_runtime_1.jsxs("div", { style: render_modals_1.outerModalStyle, children: [
419
- jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id}` }), jsx_runtime_1.jsxs("div", { style: render_modals_1.container, children: [
419
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id} in the browser` }), jsx_runtime_1.jsxs("div", { style: render_modals_1.container, children: [
420
420
  jsx_runtime_1.jsx(SegmentedControl_1.SegmentedControl, { items: renderTabOptions, needsWrapping: false }), jsx_runtime_1.jsx("div", { style: render_modals_1.flexer }), jsx_runtime_1.jsxs(Button_1.Button, { autoFocus: true, onClick: onAddToQueue, style: render_modals_1.buttonStyle, disabled: !outnameValidation.valid, children: ["Render ", renderMode, jsx_runtime_1.jsx(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: true })
421
421
  ] })
422
422
  ] }), jsx_runtime_1.jsxs("div", { style: render_modals_1.horizontalLayout, children: [
@@ -85,7 +85,7 @@ const ClientRenderQueueProcessor = () => {
85
85
  progress: progress.progress,
86
86
  });
87
87
  },
88
- outputTarget: 'web-fs',
88
+ outputTarget: null,
89
89
  licenseKey: (_c = job.licenseKey) !== null && _c !== void 0 ? _c : undefined,
90
90
  pageResponsiveness: job.pageResponsiveness,
91
91
  allowHtmlInCanvas: job.allowHtmlInCanvas,
@@ -30,6 +30,7 @@ const SkillsSettings_1 = require("./SkillsSettings");
30
30
  const StudioSettings_1 = require("./StudioSettings");
31
31
  const vertical_1 = require("./Tabs/vertical");
32
32
  const UpdatesSettings_1 = require("./UpdatesSettings");
33
+ const UpdateStatusContext_1 = require("./UpdateStatusContext");
33
34
  const hiddenPanel = {
34
35
  display: 'none',
35
36
  };
@@ -64,11 +65,13 @@ const SettingsModal = ({ initialPublicLicenseKey, initialTab }) => {
64
65
  const { setPublicLicenseKey } = (0, SettingsContext_1.useSettings)();
65
66
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
66
67
  const isBrowserStudio = (0, browser_studio_operations_1.getBrowserStudioOperations)() !== null;
67
- const showUpdates = (0, can_show_updates_1.canShowUpdates)({
68
- connectionStatus: previewServerState.type,
69
- isBrowserStudio,
70
- readOnlyStudio: window.remotion_isReadOnlyStudio,
71
- });
68
+ const { upgradeState } = (0, UpdateStatusContext_1.useUpdateStatus)();
69
+ const showUpdates = upgradeState !== 'idle' ||
70
+ (0, can_show_updates_1.canShowUpdates)({
71
+ connectionStatus: previewServerState.type,
72
+ isBrowserStudio,
73
+ readOnlyStudio: window.remotion_isReadOnlyStudio,
74
+ });
72
75
  const packageManager = window.remotion_packageManager === 'unknown'
73
76
  ? null
74
77
  : window.remotion_packageManager;