@remotion/studio 4.0.479 → 4.0.482

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 (75) hide show
  1. package/dist/components/AudioWaveform.js +19 -11
  2. package/dist/components/Button.d.ts +1 -0
  3. package/dist/components/Button.js +2 -2
  4. package/dist/components/CurrentCompositionSideEffects.d.ts +0 -3
  5. package/dist/components/CurrentCompositionSideEffects.js +1 -37
  6. package/dist/components/Editor.js +2 -5
  7. package/dist/components/EditorContent.js +2 -1
  8. package/dist/components/ExpandedTracksProvider.d.ts +1 -0
  9. package/dist/components/ExpandedTracksProvider.js +81 -7
  10. package/dist/components/GlobalKeybindings.d.ts +3 -1
  11. package/dist/components/GlobalKeybindings.js +104 -10
  12. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +7 -5
  13. package/dist/components/InspectorPanel/inspector-selection.d.ts +3 -3
  14. package/dist/components/InspectorPanel/inspector-selection.js +7 -6
  15. package/dist/components/InspectorPanel/styles.d.ts +1 -0
  16. package/dist/components/InspectorPanel/styles.js +19 -1
  17. package/dist/components/InspectorPanel.js +3 -3
  18. package/dist/components/InspectorSequenceSection.d.ts +3 -0
  19. package/dist/components/InspectorSequenceSection.js +12 -2
  20. package/dist/components/KeyboardShortcutsExplainer.js +10 -2
  21. package/dist/components/MediaVolumeProvider.js +4 -4
  22. package/dist/components/Modals.js +2 -1
  23. package/dist/components/NewComposition/CodemodFooter.d.ts +1 -0
  24. package/dist/components/NewComposition/CodemodFooter.js +25 -3
  25. package/dist/components/NewComposition/InputDragger.d.ts +4 -0
  26. package/dist/components/NewComposition/InputDragger.js +18 -2
  27. package/dist/components/NewComposition/NewComposition.d.ts +2 -0
  28. package/dist/components/NewComposition/NewComposition.js +178 -0
  29. package/dist/components/PreviewToolbar.js +3 -3
  30. package/dist/components/ResetZoomButton.d.ts +2 -1
  31. package/dist/components/ResetZoomButton.js +5 -1
  32. package/dist/components/SelectedOutlineElement.js +39 -0
  33. package/dist/components/SelectedOutlineOverlay.d.ts +6 -0
  34. package/dist/components/SelectedOutlineOverlay.js +21 -3
  35. package/dist/components/Timeline/Timeline.js +9 -9
  36. package/dist/components/Timeline/TimelineEffectItem.js +1 -1
  37. package/dist/components/Timeline/TimelineEffectPropItem.js +1 -1
  38. package/dist/components/Timeline/TimelineExpandArrowButton.js +42 -2
  39. package/dist/components/Timeline/TimelineExpandedRow.js +2 -2
  40. package/dist/components/Timeline/TimelineExpandedSection.js +8 -9
  41. package/dist/components/Timeline/TimelineRowChrome.d.ts +2 -0
  42. package/dist/components/Timeline/TimelineRowChrome.js +5 -3
  43. package/dist/components/Timeline/TimelineSelection.d.ts +26 -3
  44. package/dist/components/Timeline/TimelineSelection.js +322 -91
  45. package/dist/components/Timeline/TimelineSequenceItem.js +62 -5
  46. package/dist/components/Timeline/TimelineSequencePropItem.js +1 -1
  47. package/dist/components/Timeline/TimelineSequenceRightEdgeDragHandle.js +6 -4
  48. package/dist/components/Timeline/find-track-for-node-path-info.js +2 -2
  49. package/dist/components/Timeline/get-node-keyframes.d.ts +7 -0
  50. package/dist/components/Timeline/get-node-keyframes.js +26 -1
  51. package/dist/components/Timeline/reset-selected-timeline-props.js +15 -2
  52. package/dist/components/Timeline/timeline-expanded-filter.d.ts +12 -0
  53. package/dist/components/Timeline/timeline-expanded-filter.js +38 -0
  54. package/dist/components/Timeline/timeline-field-display-utils.js +3 -0
  55. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +50 -18
  56. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +1 -0
  57. package/dist/components/Timeline/use-timeline-expanded-tree.js +27 -0
  58. package/dist/components/Timeline/use-timeline-height.js +51 -7
  59. package/dist/components/Timeline/use-timeline-keyframe-drag.js +12 -6
  60. package/dist/components/TopPanel.js +1 -1
  61. package/dist/components/composition-menu-items.js +17 -0
  62. package/dist/components/selected-outline-measurement.js +48 -14
  63. package/dist/error-overlay/remotion-overlay/ErrorLoader.js +8 -1
  64. package/dist/esm/{chunk-fge2mq5p.js → chunk-nkqfa5bw.js} +17611 -16502
  65. package/dist/esm/internals.mjs +17611 -16502
  66. package/dist/esm/previewEntry.mjs +5179 -4068
  67. package/dist/esm/renderEntry.mjs +1 -1
  68. package/dist/helpers/calculate-timeline.js +6 -2
  69. package/dist/helpers/get-sequence-visible-range.d.ts +1 -0
  70. package/dist/helpers/get-sequence-visible-range.js +15 -1
  71. package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +3 -3
  72. package/dist/state/modals.d.ts +2 -0
  73. package/package.json +11 -11
  74. package/dist/components/Timeline/TimelineItemStack.d.ts +0 -5
  75. package/dist/components/Timeline/TimelineItemStack.js +0 -29
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.keyframeEditorValue = exports.keyframeEditorLabel = exports.keyframeEditorRow = exports.detailValue = exports.detailLabel = exports.detailRow = exports.guideDetailsContainer = exports.detailsContainer = exports.centeredMessage = exports.selectedContainer = exports.resolveLinkStyle = exports.defaultPropsWarningMessages = exports.defaultPropsWarningContainer = exports.sectionHeaderEnd = exports.sectionHeaderStart = exports.sectionHeaderTitle = exports.sectionHeaderRow = exports.sequenceHeaderTitle = exports.sequenceHeader = exports.sectionHeader = exports.inspectorSectionDivider = exports.compositionSection = exports.visualControlsSection = exports.defaultPropsSection = exports.scrollableContainer = exports.container = void 0;
3
+ exports.keyframeEditorValue = exports.keyframeEditorLabel = exports.keyframeEditorRow = exports.detailValue = exports.detailLabel = exports.detailRow = exports.guideDetailsContainer = exports.detailsContainer = exports.centeredMessage = exports.selectedContainer = exports.resolveLinkStyle = exports.defaultPropsWarningMessages = exports.defaultPropsWarningContainer = exports.sectionHeaderEnd = exports.sectionHeaderStart = exports.sectionHeaderTitle = exports.sectionHeaderRow = exports.sequenceHeaderSubtitle = exports.sequenceHeaderTitle = exports.sequenceHeader = exports.sectionHeader = exports.inspectorSectionDivider = exports.compositionSection = exports.visualControlsSection = exports.defaultPropsSection = exports.scrollableContainer = exports.container = void 0;
4
4
  const colors_1 = require("../../helpers/colors");
5
5
  const InspectorPanelLayout_1 = require("../InspectorPanelLayout");
6
6
  exports.container = {
@@ -62,6 +62,24 @@ exports.sequenceHeaderTitle = {
62
62
  textOverflow: 'ellipsis',
63
63
  whiteSpace: 'nowrap',
64
64
  };
65
+ exports.sequenceHeaderSubtitle = {
66
+ alignSelf: 'flex-start',
67
+ backgroundColor: colors_1.BACKGROUND,
68
+ border: 'none',
69
+ color: colors_1.LIGHT_TEXT,
70
+ display: 'inline-flex',
71
+ fontFamily: 'sans-serif',
72
+ fontSize: 12,
73
+ lineHeight: '18px',
74
+ margin: 0,
75
+ maxWidth: '100%',
76
+ minWidth: 0,
77
+ overflow: 'hidden',
78
+ padding: 0,
79
+ textAlign: 'left',
80
+ textOverflow: 'ellipsis',
81
+ whiteSpace: 'nowrap',
82
+ };
65
83
  exports.sectionHeaderRow = {
66
84
  alignItems: 'center',
67
85
  display: 'flex',
@@ -11,13 +11,13 @@ const styles_1 = require("./InspectorPanel/styles");
11
11
  const TimelineSelection_1 = require("./Timeline/TimelineSelection");
12
12
  const InspectorPanel = ({ composition, currentDefaultProps, setDefaultProps }) => {
13
13
  const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
14
- const sameSequencePropInspectorSelection = (0, react_1.useMemo)(() => (0, inspector_selection_1.getSameSequencePropInspectorSelection)(selectedItems), [selectedItems]);
14
+ const sameSequenceInspectorSelection = (0, react_1.useMemo)(() => (0, inspector_selection_1.getSameSequenceInspectorSelection)(selectedItems), [selectedItems]);
15
15
  if (selectedItems.length === 0) {
16
16
  return (jsx_runtime_1.jsx(DefaultInspector_1.DefaultInspector, { composition: composition, currentDefaultProps: currentDefaultProps, setDefaultProps: setDefaultProps }));
17
17
  }
18
18
  if (selectedItems.length > 1) {
19
- if (sameSequencePropInspectorSelection) {
20
- return (jsx_runtime_1.jsx("div", { style: styles_1.container, children: jsx_runtime_1.jsx(SelectedInspector_1.SelectedInspector, { selection: sameSequencePropInspectorSelection }) }));
19
+ if (sameSequenceInspectorSelection) {
20
+ return (jsx_runtime_1.jsx("div", { style: styles_1.container, children: jsx_runtime_1.jsx(SelectedInspector_1.SelectedInspector, { selection: sameSequenceInspectorSelection }) }));
21
21
  }
22
22
  return (jsx_runtime_1.jsx("div", { style: styles_1.container, children: jsx_runtime_1.jsxs(common_1.InspectorMessage, { children: [selectedItems.length, " items selected"] }) }));
23
23
  }
@@ -2,9 +2,12 @@ import React from 'react';
2
2
  import type { TSequence } from 'remotion';
3
3
  import type { CodePosition } from '../error-overlay/react-overlay/utils/get-source-map';
4
4
  import type { SequenceNodePathInfo } from '../helpers/get-timeline-sequence-sort-key';
5
+ import { type FlatTreeRow } from '../helpers/timeline-layout';
6
+ import { type TimelineSelection } from './Timeline/TimelineSelection';
5
7
  type SequenceWithControls = TSequence & {
6
8
  readonly controls: NonNullable<TSequence['controls']>;
7
9
  };
10
+ export declare const getInspectorSelectableItems: (rows: readonly FlatTreeRow[]) => TimelineSelection[];
8
11
  export declare const hasSequenceControls: (sequence: TSequence) => sequence is SequenceWithControls;
9
12
  export declare const InspectorSequenceSection: React.FC<{
10
13
  readonly sequence: SequenceWithControls;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.InspectorSequenceSection = exports.hasSequenceControls = void 0;
3
+ exports.InspectorSequenceSection = exports.hasSequenceControls = exports.getInspectorSelectableItems = 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");
@@ -11,6 +11,7 @@ const modals_1 = require("../state/modals");
11
11
  const InlineAction_1 = require("./InlineAction");
12
12
  const styles_1 = require("./InspectorPanel/styles");
13
13
  const TimelineExpandedRow_1 = require("./Timeline/TimelineExpandedRow");
14
+ const TimelineSelection_1 = require("./Timeline/TimelineSelection");
14
15
  const use_timeline_expanded_tree_1 = require("./Timeline/use-timeline-expanded-tree");
15
16
  const container = {
16
17
  color: 'white',
@@ -54,6 +55,13 @@ const isEffectsRoot = (node) => {
54
55
  const getInspectorExpansionKey = (nodePathInfo) => {
55
56
  return JSON.stringify(nodePathInfo);
56
57
  };
58
+ const getInspectorSelectableItems = (rows) => {
59
+ return rows.flatMap(({ node }) => {
60
+ const selection = (0, TimelineSelection_1.getTimelineSelectionFromNodePathInfo)(node.nodePathInfo);
61
+ return selection ? [selection] : [];
62
+ });
63
+ };
64
+ exports.getInspectorSelectableItems = getInspectorSelectableItems;
57
65
  const hasSequenceControls = (sequence) => {
58
66
  return sequence.controls !== null;
59
67
  };
@@ -106,6 +114,8 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
106
114
  }),
107
115
  };
108
116
  }, [getIsExpanded, tree]);
117
+ const controlSelectableItems = (0, react_1.useMemo)(() => (0, exports.getInspectorSelectableItems)(controlRows), [controlRows]);
118
+ const effectSelectableItems = (0, react_1.useMemo)(() => (0, exports.getInspectorSelectableItems)(effectRows), [effectRows]);
109
119
  const { schema } = sequence.controls;
110
120
  const showEffectsSection = nodePathInfo.supportsEffects || effectRows.length > 0;
111
121
  const showControlsEffectsDivider = controlRows.length > 0 && showEffectsSection;
@@ -142,6 +152,6 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
142
152
  ] }));
143
153
  }
144
154
  return (jsx_runtime_1.jsxs("div", { style: container, children: [
145
- jsx_runtime_1.jsx("div", { style: divider }), controlRows.length > 0 ? renderSectionHeader('Controls') : null, controlRows.map(renderRow), showEffectsSection ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showControlsEffectsDivider ? (jsx_runtime_1.jsx("div", { style: controlsEffectsDivider })) : null, renderEffectsHeader(), effectRows.length === 0 ? (jsx_runtime_1.jsx("div", { style: emptyState, children: "None" })) : (effectRows.map(renderRow))] })) : null] }));
155
+ jsx_runtime_1.jsx("div", { style: divider }), controlRows.length > 0 ? renderSectionHeader('Controls') : null, jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: controlSelectableItems, children: controlRows.map(renderRow) }), showEffectsSection ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [showControlsEffectsDivider ? (jsx_runtime_1.jsx("div", { style: controlsEffectsDivider })) : null, renderEffectsHeader(), effectRows.length === 0 ? (jsx_runtime_1.jsx("div", { style: emptyState, children: "None" })) : (jsx_runtime_1.jsx(TimelineSelection_1.TimelineSelectionOrderProvider, { items: effectSelectableItems, children: effectRows.map(renderRow) }))] })) : null] }));
146
156
  };
147
157
  exports.InspectorSequenceSection = InspectorSequenceSection;
@@ -109,9 +109,9 @@ const KeyboardShortcutsExplainer = () => {
109
109
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
110
110
  jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "PageDown" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Next composition" })
111
111
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
112
- jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "R" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Render composition" })
112
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "R" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Render, unless a sequence or prop is selected" })
113
113
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
114
- jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "T" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Toggle checkerboard background" })
114
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "T" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Checkerboard, unless a sequence or prop is selected" })
115
115
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
116
116
  jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "?" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Show keyboard shortcuts" })
117
117
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
@@ -146,6 +146,14 @@ const KeyboardShortcutsExplainer = () => {
146
146
  jsx_runtime_1.jsxs("div", { style: left, children: [
147
147
  jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "A" })
148
148
  ] }), jsx_runtime_1.jsx("div", { style: right, children: "Select sequence rows" })
149
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
150
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "P" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Select translate prop" })
151
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
152
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "T" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Select opacity prop" })
153
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
154
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "R" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Select rotate prop" })
155
+ ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
156
+ jsx_runtime_1.jsx("div", { style: left, children: jsx_runtime_1.jsx("kbd", { style: key, children: "S" }) }), jsx_runtime_1.jsx("div", { style: right, children: "Select scale prop" })
149
157
  ] }), jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
150
158
  jsx_runtime_1.jsxs("div", { style: left, children: [
151
159
  jsx_runtime_1.jsx("kbd", { style: key, children: ShortcutHint_1.cmdOrCtrlCharacter }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.3 }), jsx_runtime_1.jsx("kbd", { style: key, children: "D" })
@@ -6,17 +6,17 @@ const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
7
  const mute_1 = require("../state/mute");
8
8
  const MediaVolumeProvider = ({ children }) => {
9
- const [mediaMuted, setMediaMuted] = (0, react_1.useState)(() => (0, mute_1.loadMuteOption)());
9
+ const [playerMuted, setPlayerMuted] = (0, react_1.useState)(() => (0, mute_1.loadMuteOption)());
10
10
  const [mediaVolume, setMediaVolume] = (0, react_1.useState)(1);
11
11
  const mediaVolumeContextValue = (0, react_1.useMemo)(() => {
12
12
  return {
13
- mediaMuted,
13
+ playerMuted,
14
14
  mediaVolume,
15
15
  };
16
- }, [mediaMuted, mediaVolume]);
16
+ }, [playerMuted, mediaVolume]);
17
17
  const setMediaVolumeContextValue = (0, react_1.useMemo)(() => {
18
18
  return {
19
- setMediaMuted,
19
+ setPlayerMuted,
20
20
  setMediaVolume,
21
21
  };
22
22
  }, []);
@@ -15,6 +15,7 @@ const InstallPackage_1 = require("./InstallPackage");
15
15
  const DeleteComposition_1 = require("./NewComposition/DeleteComposition");
16
16
  const DeleteFolder_1 = require("./NewComposition/DeleteFolder");
17
17
  const DuplicateComposition_1 = require("./NewComposition/DuplicateComposition");
18
+ const NewComposition_1 = require("./NewComposition/NewComposition");
18
19
  const RenameComposition_1 = require("./NewComposition/RenameComposition");
19
20
  const RenameFolder_1 = require("./NewComposition/RenameFolder");
20
21
  const RenameStaticFile_1 = require("./NewComposition/RenameStaticFile");
@@ -30,7 +31,7 @@ const Modals = ({ readOnlyStudio }) => {
30
31
  const { selectedModal: modalContextType } = (0, react_1.useContext)(modals_1.ModalsContext);
31
32
  const canRender = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState.type ===
32
33
  'connected';
33
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'duplicate-comp' && (jsx_runtime_1.jsx(DuplicateComposition_1.DuplicateComposition, { compositionType: modalContextType.compositionType, compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-comp' && (jsx_runtime_1.jsx(DeleteComposition_1.DeleteComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'rename-comp' && (jsx_runtime_1.jsx(RenameComposition_1.RenameComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-folder' && (jsx_runtime_1.jsx(DeleteFolder_1.DeleteFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-folder' && (jsx_runtime_1.jsx(RenameFolder_1.RenameFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-static-file' && (jsx_runtime_1.jsx(RenameStaticFile_1.RenameStaticFileModal, { relativePath: modalContextType.relativePath })), modalContextType && modalContextType.type === 'input-props-override' && (jsx_runtime_1.jsx(OverrideInputProps_1.OverrideInputPropsModal, {})), modalContextType && modalContextType.type === 'keyframe-settings' && (jsx_runtime_1.jsx(KeyframeSettingsModal_1.KeyframeSettingsModal, { state: modalContextType })), modalContextType && modalContextType.type === 'web-render' && (jsx_runtime_1.jsx(WebRenderModal_1.WebRenderModalWithLoader, { ...modalContextType })), modalContextType &&
34
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'new-comp' && (jsx_runtime_1.jsx(NewComposition_1.NewComposition, {})), modalContextType && modalContextType.type === 'duplicate-comp' && (jsx_runtime_1.jsx(DuplicateComposition_1.DuplicateComposition, { compositionType: modalContextType.compositionType, compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-comp' && (jsx_runtime_1.jsx(DeleteComposition_1.DeleteComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'rename-comp' && (jsx_runtime_1.jsx(RenameComposition_1.RenameComposition, { compositionId: modalContextType.compositionId })), modalContextType && modalContextType.type === 'delete-folder' && (jsx_runtime_1.jsx(DeleteFolder_1.DeleteFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-folder' && (jsx_runtime_1.jsx(RenameFolder_1.RenameFolder, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), modalContextType && modalContextType.type === 'rename-static-file' && (jsx_runtime_1.jsx(RenameStaticFile_1.RenameStaticFileModal, { relativePath: modalContextType.relativePath })), modalContextType && modalContextType.type === 'input-props-override' && (jsx_runtime_1.jsx(OverrideInputProps_1.OverrideInputPropsModal, {})), modalContextType && modalContextType.type === 'keyframe-settings' && (jsx_runtime_1.jsx(KeyframeSettingsModal_1.KeyframeSettingsModal, { state: modalContextType })), modalContextType && modalContextType.type === 'web-render' && (jsx_runtime_1.jsx(WebRenderModal_1.WebRenderModalWithLoader, { ...modalContextType })), modalContextType &&
34
35
  modalContextType.type === 'server-render' &&
35
36
  (canRender || modalContextType.readOnlyStudio) ? (jsx_runtime_1.jsx(ServerRenderModal_1.RenderModalWithLoader, { readOnlyStudio: (_a = modalContextType.readOnlyStudio) !== null && _a !== void 0 ? _a : false, initialFrame: modalContextType.initialFrame, initialDarkMode: modalContextType.initialDarkMode, compositionId: modalContextType.compositionId, initialVideoImageFormat: modalContextType.initialVideoImageFormat, initialJpegQuality: modalContextType.initialJpegQuality, initialScale: modalContextType.initialScale, initialLogLevel: modalContextType.initialLogLevel, initialOffthreadVideoCacheSizeInBytes: modalContextType.initialOffthreadVideoCacheSizeInBytes, initialOffthreadVideoThreads: modalContextType.initialOffthreadVideoThreads, initialMediaCacheSizeInBytes: modalContextType.initialMediaCacheSizeInBytes, initialConcurrency: modalContextType.initialConcurrency, maxConcurrency: modalContextType.maxConcurrency, minConcurrency: modalContextType.minConcurrency, initialStillImageFormat: modalContextType.initialStillImageFormat, initialMuted: modalContextType.initialMuted, initialEnforceAudioTrack: modalContextType.initialEnforceAudioTrack, initialProResProfile: modalContextType.initialProResProfile, initialx264Preset: modalContextType.initialx264Preset, initialGopSize: modalContextType.initialGopSize, initialPixelFormat: modalContextType.initialPixelFormat, initialAudioBitrate: modalContextType.initialAudioBitrate, initialVideoBitrate: modalContextType.initialVideoBitrate, initialEveryNthFrame: modalContextType.initialEveryNthFrame, initialNumberOfGifLoops: modalContextType.initialNumberOfGifLoops, initialDelayRenderTimeout: modalContextType.initialDelayRenderTimeout, initialEnvVariables: modalContextType.initialEnvVariables, initialDisableWebSecurity: modalContextType.initialDisableWebSecurity, initialGl: modalContextType.initialOpenGlRenderer, initialHeadless: modalContextType.initialHeadless, initialIgnoreCertificateErrors: modalContextType.initialIgnoreCertificateErrors, initialEncodingBufferSize: modalContextType.initialEncodingBufferSize, initialEncodingMaxRate: modalContextType.initialEncodingMaxRate, initialUserAgent: modalContextType.initialUserAgent, initialColorSpace: modalContextType.initialColorSpace, initialMultiProcessOnLinux: modalContextType.initialMultiProcessOnLinux, initialRepro: modalContextType.initialRepro, initialBeep: modalContextType.initialBeep, initialForSeamlessAacConcatenation: modalContextType.initialForSeamlessAacConcatenation, defaultProps: modalContextType.defaultProps, inFrameMark: modalContextType.inFrameMark, outFrameMark: modalContextType.outFrameMark, defaultConfigurationAudioCodec: modalContextType.defaultConfigurationAudioCodec, defaultConfigurationVideoCodec: modalContextType.defaultConfigurationVideoCodec, renderTypeOfLastRender: modalContextType.renderTypeOfLastRender, defaultMetadata: modalContextType.defaulMetadata, initialHardwareAcceleration: modalContextType.initialHardwareAcceleration, initialSampleRate: modalContextType.initialSampleRate, initialChromeMode: modalContextType.initialChromeMode, renderDefaults: modalContextType.renderDefaults })) : null, modalContextType && modalContextType.type === 'render-progress' && (jsx_runtime_1.jsx(RenderStatusModal_1.RenderStatusModal, { jobId: modalContextType.jobId })), modalContextType && modalContextType.type === 'update' && (jsx_runtime_1.jsx(UpdateModal_1.UpdateModal, { info: modalContextType.info, knownBugs: modalContextType.knownBugs })), modalContextType && modalContextType.type === 'install-packages' && (jsx_runtime_1.jsx(InstallPackage_1.InstallPackageModal, { packageManager: modalContextType.packageManager })), modalContextType && modalContextType.type === 'quick-switcher' && (jsx_runtime_1.jsx(QuickSwitcher_1.default, { readOnlyStudio: readOnlyStudio, invocationTimestamp: modalContextType.invocationTimestamp, initialMode: modalContextType.mode })), modalContextType && modalContextType.type === 'add-effect' && (jsx_runtime_1.jsx(EffectPickerModal_1.EffectPickerModal, { state: modalContextType })), modalContextType && modalContextType.type === 'confirmation-dialog' && (jsx_runtime_1.jsx(ConfirmationDialog_1.ConfirmationDialog, { state: modalContextType })), process.env.ASK_AI_ENABLED && jsx_runtime_1.jsx(AskAiModal_1.AskAiModal, {})] }));
36
37
  };
@@ -12,4 +12,5 @@ export declare const CodemodFooter: React.FC<{
12
12
  relativeRootPath: string;
13
13
  }) => string;
14
14
  readonly onSuccess: (() => void) | null;
15
+ readonly fallbackToRootFile?: boolean;
15
16
  }>;
@@ -13,7 +13,7 @@ const NotificationCenter_1 = require("../Notifications/NotificationCenter");
13
13
  const actions_1 = require("../RenderQueue/actions");
14
14
  const use_resolved_stack_1 = require("../Timeline/use-resolved-stack");
15
15
  const DiffPreview_1 = require("./DiffPreview");
16
- const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNotification, errorNotification, genericSubmitLabel, submitLabel, onSuccess, }) => {
16
+ const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNotification, errorNotification, genericSubmitLabel, submitLabel, onSuccess, fallbackToRootFile = false, }) => {
17
17
  var _a;
18
18
  const [submitting, setSubmitting] = (0, react_1.useState)(false);
19
19
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
@@ -68,6 +68,22 @@ const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNoti
68
68
  }, [codemod, symbolicatedStack]);
69
69
  (0, react_1.useEffect)(() => {
70
70
  if (!stack) {
71
+ if (fallbackToRootFile) {
72
+ const rootFileAbortController = new AbortController();
73
+ let rootFileAborted = false;
74
+ getCanApplyCodemod(rootFileAbortController.signal)
75
+ .then(() => undefined)
76
+ .catch((err) => {
77
+ if (rootFileAborted) {
78
+ return;
79
+ }
80
+ (0, NotificationCenter_1.showNotification)(`${errorNotification}: ${err.message}`, 3000);
81
+ });
82
+ return () => {
83
+ rootFileAborted = true;
84
+ rootFileAbortController.abort();
85
+ };
86
+ }
71
87
  setCanApplyCodemod({
72
88
  type: 'fail',
73
89
  error: 'Could not determine where this item is defined',
@@ -98,10 +114,16 @@ const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNoti
98
114
  aborted = true;
99
115
  abortController.abort();
100
116
  };
101
- }, [errorNotification, getCanApplyCodemod, stack, symbolicatedStack]);
117
+ }, [
118
+ errorNotification,
119
+ fallbackToRootFile,
120
+ getCanApplyCodemod,
121
+ stack,
122
+ symbolicatedStack,
123
+ ]);
102
124
  const disabled = !valid ||
103
125
  submitting ||
104
- symbolicatedStack === null ||
126
+ (symbolicatedStack === null && !fallbackToRootFile) ||
105
127
  codemodStatus.type !== 'success';
106
128
  const { registerKeybinding } = (0, use_keybinding_1.useKeybinding)();
107
129
  (0, react_1.useEffect)(() => {
@@ -6,6 +6,10 @@ export declare const deriveInputDraggerStep: ({ min, snapToStep, step, }: {
6
6
  readonly snapToStep: boolean;
7
7
  readonly step: string | number | undefined;
8
8
  }) => string | number;
9
+ export declare const deriveInputDraggerDragStartValue: ({ min, value, }: {
10
+ readonly min: string | number | undefined;
11
+ readonly value: string | number | readonly string[] | undefined;
12
+ }) => number;
9
13
  export declare const InputDragger: React.ForwardRefExoticComponent<InputHTMLAttributes<HTMLInputElement> & {
10
14
  readonly onValueChange: (newVal: number) => void;
11
15
  readonly onValueChangeEnd?: ((newVal: number) => void) | undefined;
@@ -33,7 +33,7 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.InputDragger = exports.deriveInputDraggerStep = void 0;
36
+ exports.InputDragger = exports.deriveInputDraggerDragStartValue = exports.deriveInputDraggerStep = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const remotion_1 = require("remotion");
@@ -64,6 +64,18 @@ const deriveInputDraggerStep = ({ min, snapToStep, step, }) => {
64
64
  return 0.0001;
65
65
  };
66
66
  exports.deriveInputDraggerStep = deriveInputDraggerStep;
67
+ const deriveInputDraggerDragStartValue = ({ min, value, }) => {
68
+ const numericValue = Number(value);
69
+ if (Number.isFinite(numericValue)) {
70
+ return numericValue;
71
+ }
72
+ const numericMin = Number(min);
73
+ if (Number.isFinite(numericMin)) {
74
+ return numericMin;
75
+ }
76
+ return 0;
77
+ };
78
+ exports.deriveInputDraggerDragStartValue = deriveInputDraggerDragStartValue;
67
79
  const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min, max: _max, step: _step, value, onTextChange, formatter = (q) => String(q), status, rightAlign, small, snapToStep = true, dragDecimalPlaces, ...props }, ref) => {
68
80
  const [inputFallback, setInputFallback] = (0, react_1.useState)(false);
69
81
  const [dragging, setDragging] = (0, react_1.useState)(false);
@@ -152,6 +164,10 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
152
164
  const step = Number(_step !== null && _step !== void 0 ? _step : 1);
153
165
  const min = Number(_min !== null && _min !== void 0 ? _min : 0);
154
166
  const max = Number(_max !== null && _max !== void 0 ? _max : Infinity);
167
+ const dragStartValue = (0, exports.deriveInputDraggerDragStartValue)({
168
+ min: _min,
169
+ value,
170
+ });
155
171
  if (distanceFromStart > 4) {
156
172
  (0, input_dragger_click_lock_1.setClickLock)(true);
157
173
  setDragging(true);
@@ -159,7 +175,7 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
159
175
  target.blur();
160
176
  }
161
177
  const diff = (0, remotion_1.interpolate)(xDistance, [-5, -4, 0, 4, 5], [-step, 0, 0, 0, step]);
162
- const newValue = Math.min(max, Math.max(min, Number(value) + diff));
178
+ const newValue = Math.min(max, Math.max(min, dragStartValue + diff));
163
179
  const nextValue = snapToStep
164
180
  ? roundToStep(newValue, step)
165
181
  : dragDecimalPlaces === undefined
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const NewComposition: React.FC;
@@ -0,0 +1,178 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.NewComposition = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const url_state_1 = require("../../helpers/url-state");
8
+ const validate_new_comp_data_1 = require("../../helpers/validate-new-comp-data");
9
+ const layout_1 = require("../layout");
10
+ const ModalFooter_1 = require("../ModalFooter");
11
+ const ModalHeader_1 = require("../ModalHeader");
12
+ const layout_2 = require("../RenderModal/layout");
13
+ const CodemodFooter_1 = require("./CodemodFooter");
14
+ const DismissableModal_1 = require("./DismissableModal");
15
+ const InputDragger_1 = require("./InputDragger");
16
+ const NewCompDuration_1 = require("./NewCompDuration");
17
+ const RemInput_1 = require("./RemInput");
18
+ const ValidationMessage_1 = require("./ValidationMessage");
19
+ const content = {
20
+ padding: 12,
21
+ paddingRight: 12,
22
+ flex: 1,
23
+ fontSize: 13,
24
+ minWidth: 500,
25
+ };
26
+ const toPascalCase = (value) => {
27
+ var _a;
28
+ const words = (_a = value.match(/[a-zA-Z0-9]+/g)) !== null && _a !== void 0 ? _a : [];
29
+ const candidate = words
30
+ .map((word) => `${word.charAt(0).toUpperCase()}${word.slice(1)}`)
31
+ .join('');
32
+ if (!candidate) {
33
+ return 'NewComposition';
34
+ }
35
+ if (/^[0-9]/.test(candidate)) {
36
+ return `Composition${candidate}`;
37
+ }
38
+ return candidate;
39
+ };
40
+ const waitForComposition = (compositionId) => {
41
+ return new Promise((resolve) => {
42
+ const started = Date.now();
43
+ const interval = window.setInterval(() => {
44
+ var _a;
45
+ var _b;
46
+ const compositionNames = (_b = (_a = window.remotion_getCompositionNames) === null || _a === void 0 ? void 0 : _a.call(window)) !== null && _b !== void 0 ? _b : [];
47
+ if (compositionNames.includes(compositionId) ||
48
+ Date.now() - started > 10000) {
49
+ window.clearInterval(interval);
50
+ resolve();
51
+ }
52
+ }, 100);
53
+ });
54
+ };
55
+ const getUniqueCompositionName = (compositions) => {
56
+ let counter = 1;
57
+ while (true) {
58
+ const name = counter === 1 ? 'NewComposition' : `NewComposition${counter}`;
59
+ const err = (0, validate_new_comp_data_1.validateCompositionName)(name, compositions);
60
+ if (!err) {
61
+ return name;
62
+ }
63
+ counter++;
64
+ }
65
+ };
66
+ const NewCompositionLoaded = () => {
67
+ const { compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
68
+ const [newId, setName] = (0, react_1.useState)(() => getUniqueCompositionName(compositions));
69
+ const [selectedFrameRate, setFrameRate] = (0, react_1.useState)(30);
70
+ const [size, setSize] = (0, react_1.useState)(() => ({
71
+ width: 1920,
72
+ height: 1080,
73
+ }));
74
+ const [durationInFrames, setDurationInFrames] = (0, react_1.useState)(150);
75
+ const onWidthChanged = (0, react_1.useCallback)((newValue) => {
76
+ setSize((s) => {
77
+ return {
78
+ height: s.height,
79
+ width: Number(newValue),
80
+ };
81
+ });
82
+ }, []);
83
+ const onWidthDirectlyChanged = (0, react_1.useCallback)((newWidth) => {
84
+ setSize((s) => {
85
+ return {
86
+ height: s.height,
87
+ width: newWidth,
88
+ };
89
+ });
90
+ }, []);
91
+ const onHeightDirectlyChanged = (0, react_1.useCallback)((newHeight) => {
92
+ setSize((s) => {
93
+ return {
94
+ width: s.width,
95
+ height: newHeight,
96
+ };
97
+ });
98
+ }, []);
99
+ const onHeightChanged = (0, react_1.useCallback)((newValue) => {
100
+ setSize((s) => {
101
+ return {
102
+ width: s.width,
103
+ height: Number(newValue),
104
+ };
105
+ });
106
+ }, []);
107
+ const onNameChange = (0, react_1.useCallback)((e) => {
108
+ setName(e.target.value);
109
+ }, []);
110
+ const onTextFpsChange = (0, react_1.useCallback)((newFps) => {
111
+ setFrameRate(Number(newFps));
112
+ }, []);
113
+ const onFpsChange = (0, react_1.useCallback)((newFps) => {
114
+ setFrameRate(newFps);
115
+ }, []);
116
+ const compNameErrMessage = (0, validate_new_comp_data_1.validateCompositionName)(newId, compositions);
117
+ const compWidthErrMessage = (0, validate_new_comp_data_1.validateCompositionDimension)('Width', size.width);
118
+ const compHeightErrMessage = (0, validate_new_comp_data_1.validateCompositionDimension)('Height', size.height);
119
+ const componentName = toPascalCase(newId);
120
+ const valid = compNameErrMessage === null &&
121
+ compWidthErrMessage === null &&
122
+ compHeightErrMessage === null;
123
+ const codemod = (0, react_1.useMemo)(() => {
124
+ return {
125
+ type: 'new-composition',
126
+ newDurationInFrames: Number(durationInFrames),
127
+ newFps: Number(selectedFrameRate),
128
+ newHeight: Number(size.height),
129
+ newWidth: Number(size.width),
130
+ newId,
131
+ componentName,
132
+ componentImportPath: `./${componentName}`,
133
+ };
134
+ }, [
135
+ componentName,
136
+ durationInFrames,
137
+ newId,
138
+ selectedFrameRate,
139
+ size.height,
140
+ size.width,
141
+ ]);
142
+ const onSuccess = (0, react_1.useCallback)(() => {
143
+ waitForComposition(newId).then(() => {
144
+ (0, url_state_1.pushUrl)(`/${newId}`);
145
+ });
146
+ }, [newId]);
147
+ const onSubmit = (0, react_1.useCallback)((e) => {
148
+ e.preventDefault();
149
+ }, []);
150
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
151
+ jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: "New composition" }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
152
+ jsx_runtime_1.jsxs("div", { style: content, children: [
153
+ jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
154
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: "ID" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsxs("div", { children: [
155
+ jsx_runtime_1.jsx(RemInput_1.RemotionInput, { value: newId, onChange: onNameChange, type: "text", autoFocus: true, placeholder: "Composition ID", status: "ok", rightAlign: true }), compNameErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
156
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: compNameErrMessage, type: "error" })
157
+ ] })) : null] }) })
158
+ ] }), jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
159
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Width" }), jsx_runtime_1.jsxs("div", { style: layout_2.rightRow, children: [
160
+ jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: size.width, placeholder: "Width", onTextChange: onWidthChanged, name: "width", step: 2, min: 2, required: true, status: "ok", formatter: (w) => `${w}px`, max: 100000000, onValueChange: onWidthDirectlyChanged, rightAlign: false }), compWidthErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
161
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: compWidthErrMessage, type: "error" })
162
+ ] })) : null] })
163
+ ] }), jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
164
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Height" }), jsx_runtime_1.jsxs("div", { style: layout_2.rightRow, children: [
165
+ jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: size.height, onTextChange: onHeightChanged, placeholder: "Height", name: "height", step: 2, required: true, formatter: (h) => `${h}px`, min: 2, status: "ok", max: 100000000, onValueChange: onHeightDirectlyChanged, rightAlign: false }), compHeightErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
166
+ jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: compHeightErrMessage, type: "error" })
167
+ ] })) : null] })
168
+ ] }), jsx_runtime_1.jsx(NewCompDuration_1.NewCompDuration, { durationInFrames: durationInFrames, setDurationInFrames: setDurationInFrames }), jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
169
+ jsx_runtime_1.jsx("div", { style: layout_2.label, children: "FPS" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: selectedFrameRate, onTextChange: onTextFpsChange, placeholder: "Frame rate (fps)", name: "fps", min: 1, required: true, status: "ok", max: 240, step: 0.01, onValueChange: onFpsChange, rightAlign: false }) })
170
+ ] })
171
+ ] }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsx(CodemodFooter_1.CodemodFooter, { loadingNotification: "Creating composition...", errorNotification: "Could not create composition", successNotification: `Created ${newId}`, genericSubmitLabel: "Add to root file", submitLabel: ({ relativeRootPath }) => `Add to ${relativeRootPath}`, codemod: codemod, stack: null, valid: valid, onSuccess: onSuccess, fallbackToRootFile: true }) })
172
+ ] })
173
+ ] }));
174
+ };
175
+ const NewComposition = () => {
176
+ return (jsx_runtime_1.jsx(DismissableModal_1.DismissableModal, { children: jsx_runtime_1.jsx(NewCompositionLoaded, {}) }));
177
+ };
178
+ exports.NewComposition = NewComposition;
@@ -83,8 +83,8 @@ const PreviewToolbarControl = ({ children }) => {
83
83
  };
84
84
  const PreviewToolbar = ({ readOnlyStudio, bufferStateDelayInMilliseconds }) => {
85
85
  const { playbackRate, setPlaybackRate } = remotion_1.Internals.usePlaybackRate();
86
- const { mediaMuted } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
87
- const { setMediaMuted } = (0, react_1.useContext)(remotion_1.Internals.SetMediaVolumeContext);
86
+ const { playerMuted } = (0, react_1.useContext)(remotion_1.Internals.MediaVolumeContext);
87
+ const { setPlayerMuted } = (0, react_1.useContext)(remotion_1.Internals.SetMediaVolumeContext);
88
88
  const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
89
89
  const isVideoComposition = (0, is_current_selected_still_1.useIsVideoComposition)();
90
90
  const previewToolbarRef = (0, react_1.useRef)(null);
@@ -163,7 +163,7 @@ const PreviewToolbar = ({ readOnlyStudio, bufferStateDelayInMilliseconds }) => {
163
163
  jsx_runtime_1.jsxs("div", { style: sideContainer, children: [
164
164
  jsx_runtime_1.jsx("div", { style: padding }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(TimelineZoomControls_1.TimelineZoomControls, {}) })
165
165
  ] }), jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(SizeSelector_1.SizeSelector, {}) }), isStill || isVideoComposition ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlaybackRateSelector_1.PlaybackRateSelector, { setPlaybackRate: setPlaybackRate, playbackRate: playbackRate }) })) : null] })), isVideoComposition ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
166
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlayPause_1.PlayPause, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, loop: loop, playbackRate: playbackRate, muted: mediaMuted }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }) }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(MuteToggle_1.MuteToggle, { muted: mediaMuted, setMuted: setMediaMuted }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(TimelineInOutToggle_1.TimelineInOutPointToggle, {}) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 })
166
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(PlayPause_1.PlayPause, { bufferStateDelayInMilliseconds: bufferStateDelayInMilliseconds, loop: loop, playbackRate: playbackRate, muted: playerMuted }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(LoopToggle_1.LoopToggle, { loop: loop, setLoop: setLoop }) }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(MuteToggle_1.MuteToggle, { muted: playerMuted, setMuted: setPlayerMuted }) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(TimelineInOutToggle_1.TimelineInOutPointToggle, {}) }), jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 })
167
167
  ] })) : null, (canvasContent === null || canvasContent === void 0 ? void 0 : canvasContent.type) === 'composition' ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
168
168
  jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(CheckboardToggle_1.CheckboardToggle, {}) }), jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(OutlineToggle_1.OutlineToggle, {}) })
169
169
  ] })) : null, jsx_runtime_1.jsx(layout_1.Spacing, { x: 1 }), canvasContent && isFullscreenSupported ? (jsx_runtime_1.jsx(PreviewToolbarControl, { children: jsx_runtime_1.jsx(FullscreenToggle_1.FullScreenToggle, {}) })) : null, jsx_runtime_1.jsx(layout_1.Flex, {}), isMobileLayout && (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
@@ -1,3 +1,4 @@
1
+ import React from 'react';
1
2
  export declare const ResetZoomButton: React.FC<{
2
- onClick: () => void;
3
+ readonly onClick: () => void;
3
4
  }>;
@@ -2,8 +2,12 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ResetZoomButton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
5
6
  const Button_1 = require("./Button");
6
7
  const ResetZoomButton = ({ onClick }) => {
7
- return jsx_runtime_1.jsx(Button_1.Button, { onClick: onClick, children: "Reset zoom" });
8
+ const onPointerDown = (0, react_1.useCallback)((event) => {
9
+ event.stopPropagation();
10
+ }, []);
11
+ return (jsx_runtime_1.jsx(Button_1.Button, { onClick: onClick, onPointerDown: onPointerDown, children: "Reset zoom" }));
8
12
  };
9
13
  exports.ResetZoomButton = ResetZoomButton;
@@ -42,6 +42,7 @@ const client_id_1 = require("../helpers/client-id");
42
42
  const colors_1 = require("../helpers/colors");
43
43
  const format_file_location_1 = require("../helpers/format-file-location");
44
44
  const open_in_editor_1 = require("../helpers/open-in-editor");
45
+ const modals_1 = require("../state/modals");
45
46
  const call_api_1 = require("./call-api");
46
47
  const ConfirmationDialog_1 = require("./ConfirmationDialog");
47
48
  const ContextMenu_1 = require("./ContextMenu");
@@ -914,6 +915,7 @@ const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allSca
914
915
  const updateResolvedStackTrace = (0, react_1.useContext)(remotion_1.Internals.SequenceStackTracesUpdateContext);
915
916
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
916
917
  const selectAsset = (0, use_select_asset_1.useSelectAsset)();
918
+ const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
917
919
  const onContextMenuOpen = react_1.default.useCallback(async () => {
918
920
  if (target === undefined || previewServerState.type !== 'connected') {
919
921
  return false;
@@ -948,6 +950,9 @@ const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allSca
948
950
  const canOpenInEditor = Boolean(window.remotion_editorName && originalLocation);
949
951
  const disableInteractivityDisabled = !target.sequence.showInTimeline;
950
952
  const sourceEditDisabled = !target.sequence.controls || !nodePath.absolutePath;
953
+ const canAddEffect = target.nodePathInfo.supportsEffects &&
954
+ !sourceEditDisabled &&
955
+ previewServerState.type === 'connected';
951
956
  return (0, get_sequence_context_menu_items_1.getSequenceContextMenuItems)({
952
957
  assetLinkInfo,
953
958
  canOpenInEditor,
@@ -1021,12 +1026,46 @@ const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allSca
1021
1026
  originalLocation,
1022
1027
  selectAsset,
1023
1028
  sequence: target.sequence,
1029
+ sourceActions: [
1030
+ ...(target.nodePathInfo.supportsEffects
1031
+ ? [
1032
+ {
1033
+ type: 'item',
1034
+ id: 'add-effect',
1035
+ keyHint: null,
1036
+ label: 'Add effect...',
1037
+ leftItem: null,
1038
+ disabled: !canAddEffect,
1039
+ onClick: () => {
1040
+ if (!canAddEffect ||
1041
+ previewServerState.type !== 'connected') {
1042
+ return;
1043
+ }
1044
+ setSelectedModal({
1045
+ type: 'add-effect',
1046
+ clientId: previewServerState.clientId,
1047
+ fileName: nodePath.absolutePath,
1048
+ nodePath,
1049
+ });
1050
+ },
1051
+ quickSwitcherLabel: null,
1052
+ subMenu: null,
1053
+ value: 'add-effect',
1054
+ },
1055
+ {
1056
+ type: 'divider',
1057
+ id: 'add-effect-divider',
1058
+ },
1059
+ ]
1060
+ : []),
1061
+ ],
1024
1062
  });
1025
1063
  }, [
1026
1064
  confirm,
1027
1065
  onSelect,
1028
1066
  previewServerState,
1029
1067
  selectAsset,
1068
+ setSelectedModal,
1030
1069
  setPropStatuses,
1031
1070
  target,
1032
1071
  updateResolvedStackTrace,