@remotion/studio 4.0.484 → 4.0.485

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 (76) hide show
  1. package/dist/components/ContextMenu.js +75 -1
  2. package/dist/components/CurrentComposition.js +3 -2
  3. package/dist/components/InlineCompositionName.d.ts +7 -0
  4. package/dist/components/InlineCompositionName.js +58 -0
  5. package/dist/components/InlineEditableTitle.d.ts +7 -0
  6. package/dist/components/InlineEditableTitle.js +129 -0
  7. package/dist/components/InspectorPanel/KeyframeInspector.js +1 -0
  8. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +17 -30
  9. package/dist/components/InspectorPanel/styles.js +2 -2
  10. package/dist/components/InspectorSequenceSection.js +34 -1
  11. package/dist/components/Modals.js +1 -1
  12. package/dist/components/NewComposition/CodemodFooter.d.ts +7 -1
  13. package/dist/components/NewComposition/CodemodFooter.js +17 -12
  14. package/dist/components/NewComposition/DeleteComposition.js +7 -1
  15. package/dist/components/NewComposition/DeleteFolder.js +7 -1
  16. package/dist/components/NewComposition/DuplicateComposition.js +17 -10
  17. package/dist/components/NewComposition/InputAndValidationContainer.d.ts +3 -0
  18. package/dist/components/NewComposition/InputAndValidationContainer.js +15 -0
  19. package/dist/components/NewComposition/NewCompDuration.js +7 -6
  20. package/dist/components/NewComposition/NewComposition.d.ts +5 -1
  21. package/dist/components/NewComposition/NewComposition.js +29 -86
  22. package/dist/components/NewComposition/RenameComposition.js +13 -14
  23. package/dist/components/NewComposition/RenameFolder.js +9 -2
  24. package/dist/components/NewComposition/RenameStaticFile.js +2 -1
  25. package/dist/components/NewComposition/ValidationMessage.js +9 -1
  26. package/dist/components/OptionsPanel.d.ts +0 -3
  27. package/dist/components/OptionsPanel.js +7 -3
  28. package/dist/components/RenderModal/ServerRenderModal.js +4 -3
  29. package/dist/components/RenderModal/WebRenderModal.js +2 -1
  30. package/dist/components/SelectedOutlineElement.js +45 -3
  31. package/dist/components/SelectedOutlineOverlay.d.ts +1 -1
  32. package/dist/components/SelectedOutlineOverlay.js +15 -3
  33. package/dist/components/Timeline/TimelineDeleteKeybindings.js +34 -1
  34. package/dist/components/Timeline/TimelineExpandedSection.js +1 -0
  35. package/dist/components/Timeline/TimelineInOutPointerHandle.js +2 -1
  36. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +1 -1
  37. package/dist/components/Timeline/TimelineKeyframeControls.js +1 -0
  38. package/dist/components/Timeline/TimelinePrimitiveFieldValue.js +4 -0
  39. package/dist/components/Timeline/TimelineSelection.js +1 -0
  40. package/dist/components/Timeline/TimelineSequenceItem.js +19 -101
  41. package/dist/components/Timeline/TimelineSequencePropItem.js +6 -3
  42. package/dist/components/Timeline/TimelineTextContentField.d.ts +12 -0
  43. package/dist/components/Timeline/TimelineTextContentField.js +100 -0
  44. package/dist/components/Timeline/TimelineWidthProvider.js +18 -3
  45. package/dist/components/Timeline/focus-inspector-field.d.ts +16 -0
  46. package/dist/components/Timeline/focus-inspector-field.js +49 -0
  47. package/dist/components/Timeline/split-selected-timeline-item.d.ts +38 -0
  48. package/dist/components/Timeline/split-selected-timeline-item.js +156 -0
  49. package/dist/components/Timeline/timeline-field-display-utils.js +2 -0
  50. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +1 -0
  51. package/dist/components/Timeline/use-rename-sequence.d.ts +30 -0
  52. package/dist/components/Timeline/use-rename-sequence.js +115 -0
  53. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +2 -1
  54. package/dist/components/Timeline/use-timeline-expanded-tree.js +3 -1
  55. package/dist/components/Timeline/use-timeline-height.js +1 -0
  56. package/dist/components/composition-menu-items.js +3 -0
  57. package/dist/components/folder-menu-items.js +20 -0
  58. package/dist/components/options-sidebar-tabs.d.ts +4 -0
  59. package/dist/components/options-sidebar-tabs.js +5 -0
  60. package/dist/components/selected-outline-types.d.ts +6 -1
  61. package/dist/esm/{chunk-9erwh79m.js → chunk-103pp4n7.js} +6734 -5683
  62. package/dist/esm/internals.mjs +6734 -5683
  63. package/dist/esm/previewEntry.mjs +6649 -5598
  64. package/dist/esm/renderEntry.mjs +1 -1
  65. package/dist/helpers/render-codec-label.d.ts +1 -1
  66. package/dist/helpers/timeline-layout.d.ts +4 -3
  67. package/dist/helpers/timeline-layout.js +3 -1
  68. package/dist/helpers/use-create-composition.d.ts +35 -0
  69. package/dist/helpers/use-create-composition.js +111 -0
  70. package/dist/helpers/use-rename-composition.d.ts +16 -0
  71. package/dist/helpers/use-rename-composition.js +49 -0
  72. package/dist/state/modals.d.ts +3 -0
  73. package/dist/state/timeline-zoom.js +17 -14
  74. package/dist/state/z-index.d.ts +1 -0
  75. package/dist/state/z-index.js +11 -2
  76. package/package.json +12 -12
@@ -47,7 +47,25 @@ const z_index_1 = require("../state/z-index");
47
47
  const portals_1 = require("./Menu/portals");
48
48
  const styles_1 = require("./Menu/styles");
49
49
  const MenuContent_1 = require("./NewComposition/MenuContent");
50
+ const CONTEXT_MENU_Z_INDEX = 1001;
51
+ const contextMenuFullScreenOverlay = {
52
+ ...styles_1.fullScreenOverlay,
53
+ pointerEvents: 'none',
54
+ zIndex: CONTEXT_MENU_Z_INDEX,
55
+ };
56
+ const contextMenuOuterPortal = {
57
+ ...styles_1.outerPortal,
58
+ pointerEvents: 'auto',
59
+ };
60
+ const contextMenuOpenedEvent = 'remotion-context-menu-opened';
61
+ let nextContextMenuId = 0;
62
+ const notifyContextMenuOpened = (id) => {
63
+ window.dispatchEvent(new CustomEvent(contextMenuOpenedEvent, {
64
+ detail: id,
65
+ }));
66
+ };
50
67
  const ContextMenuPortal = ({ sizeSource, currentZIndex, onHide, opened, values }) => {
68
+ const menuRef = (0, react_1.useRef)(null);
51
69
  const size = player_1.PlayerInternals.useElementSize(sizeSource, {
52
70
  triggerOnWindowResize: true,
53
71
  shouldApplyCssTransforms: true,
@@ -103,6 +121,34 @@ const ContextMenuPortal = ({ sizeSource, currentZIndex, onHide, opened, values }
103
121
  spaceToTop,
104
122
  spaceToBottom,
105
123
  ]);
124
+ (0, react_1.useEffect)(() => {
125
+ const preventNativeContextMenu = (event) => {
126
+ event.preventDefault();
127
+ };
128
+ window.addEventListener('contextmenu', preventNativeContextMenu, true);
129
+ return () => {
130
+ window.removeEventListener('contextmenu', preventNativeContextMenu, true);
131
+ };
132
+ }, []);
133
+ (0, react_1.useEffect)(() => {
134
+ const dismissWithoutClickThrough = (event) => {
135
+ var _a;
136
+ if (event.button !== 0) {
137
+ return;
138
+ }
139
+ if ((_a = menuRef.current) === null || _a === void 0 ? void 0 : _a.contains(event.target)) {
140
+ return;
141
+ }
142
+ event.preventDefault();
143
+ event.stopPropagation();
144
+ event.stopImmediatePropagation();
145
+ onHide();
146
+ };
147
+ window.addEventListener('pointerdown', dismissWithoutClickThrough, true);
148
+ return () => {
149
+ window.removeEventListener('pointerdown', dismissWithoutClickThrough, true);
150
+ };
151
+ }, [onHide]);
106
152
  // Prevent deselection of a selected item
107
153
  const onMenuPointerDown = (0, react_1.useCallback)((e) => {
108
154
  e.stopPropagation();
@@ -110,10 +156,11 @@ const ContextMenuPortal = ({ sizeSource, currentZIndex, onHide, opened, values }
110
156
  if (!portalStyle) {
111
157
  return null;
112
158
  }
113
- return react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { style: styles_1.fullScreenOverlay, children: jsx_runtime_1.jsx("div", { style: styles_1.outerPortal, className: "css-reset", children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onOutsideClick: onHide, onEscape: onHide, children: jsx_runtime_1.jsx("div", { style: portalStyle, onPointerDown: onMenuPointerDown, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: noop_1.noop, values: values, onHide: onHide, leaveLeftSpace: true, preselectIndex: false, topItemCanBeUnselected: false, fixedHeight: null }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex));
159
+ return react_dom_1.default.createPortal(jsx_runtime_1.jsx("div", { style: contextMenuFullScreenOverlay, children: jsx_runtime_1.jsx("div", { style: contextMenuOuterPortal, className: "css-reset", children: jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onOutsideClick: onHide, onEscape: onHide, outsideClickButton: "primary", children: jsx_runtime_1.jsx("div", { ref: menuRef, style: portalStyle, onPointerDown: onMenuPointerDown, children: jsx_runtime_1.jsx(MenuContent_1.MenuContent, { onNextMenu: noop_1.noop, onPreviousMenu: noop_1.noop, values: values, onHide: onHide, leaveLeftSpace: true, preselectIndex: false, topItemCanBeUnselected: false, fixedHeight: null }) }) }) }) }), (0, portals_1.getPortal)(currentZIndex));
114
160
  };
115
161
  exports.ContextMenu = react_1.default.forwardRef(({ children, values, onOpen, style = undefined, className = undefined, onPointerDown = undefined, }, forwardedRef) => {
116
162
  const ref = (0, react_1.useRef)(null);
163
+ const idRef = (0, react_1.useRef)(nextContextMenuId++);
117
164
  const [opened, setOpened] = (0, react_1.useState)({ type: 'not-open' });
118
165
  const { currentZIndex } = (0, z_index_1.useZIndex)();
119
166
  const setRef = (0, react_1.useCallback)((node) => {
@@ -137,6 +184,7 @@ exports.ContextMenu = react_1.default.forwardRef(({ children, values, onOpen, st
137
184
  if ((onOpen === null || onOpen === void 0 ? void 0 : onOpen()) === false) {
138
185
  return false;
139
186
  }
187
+ notifyContextMenuOpened(idRef.current);
140
188
  setOpened({ type: 'open', left: e.clientX, top: e.clientY });
141
189
  return false;
142
190
  };
@@ -148,11 +196,24 @@ exports.ContextMenu = react_1.default.forwardRef(({ children, values, onOpen, st
148
196
  const onHide = (0, react_1.useCallback)(() => {
149
197
  setOpened({ type: 'not-open' });
150
198
  }, []);
199
+ (0, react_1.useEffect)(() => {
200
+ const onOtherContextMenuOpened = (event) => {
201
+ if (event.detail === idRef.current) {
202
+ return;
203
+ }
204
+ onHide();
205
+ };
206
+ window.addEventListener(contextMenuOpenedEvent, onOtherContextMenuOpened);
207
+ return () => {
208
+ window.removeEventListener(contextMenuOpenedEvent, onOtherContextMenuOpened);
209
+ };
210
+ }, [onHide]);
151
211
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
152
212
  jsx_runtime_1.jsx("div", { ref: setRef, onContextMenu: () => false, style: style, className: className, onPointerDown: onPointerDown, children: children }), opened.type === 'open' ? (jsx_runtime_1.jsx(ContextMenuPortal, { sizeSource: ref, currentZIndex: currentZIndex, onHide: onHide, opened: opened, values: values })) : null] }));
153
213
  });
154
214
  exports.ContextMenu.displayName = 'ContextMenu';
155
215
  const ContextMenuForTarget = ({ triggerRef, values, onOpen }) => {
216
+ const idRef = (0, react_1.useRef)(nextContextMenuId++);
156
217
  const [opened, setOpened] = (0, react_1.useState)({ type: 'not-open' });
157
218
  const [openedValues, setOpenedValues] = (0, react_1.useState)(values);
158
219
  const [body, setBody] = (0, react_1.useState)(null);
@@ -179,6 +240,7 @@ const ContextMenuForTarget = ({ triggerRef, values, onOpen }) => {
179
240
  if (nextValues.length === 0) {
180
241
  return false;
181
242
  }
243
+ notifyContextMenuOpened(idRef.current);
182
244
  setOpenedValues(nextValues);
183
245
  setOpened({ type: 'open', left: e.clientX, top: e.clientY });
184
246
  return false;
@@ -191,6 +253,18 @@ const ContextMenuForTarget = ({ triggerRef, values, onOpen }) => {
191
253
  const onHide = (0, react_1.useCallback)(() => {
192
254
  setOpened({ type: 'not-open' });
193
255
  }, []);
256
+ (0, react_1.useEffect)(() => {
257
+ const onOtherContextMenuOpened = (event) => {
258
+ if (event.detail === idRef.current) {
259
+ return;
260
+ }
261
+ onHide();
262
+ };
263
+ window.addEventListener(contextMenuOpenedEvent, onOtherContextMenuOpened);
264
+ return () => {
265
+ window.removeEventListener(contextMenuOpenedEvent, onOtherContextMenuOpened);
266
+ };
267
+ }, [onHide]);
194
268
  return opened.type === 'open' ? (jsx_runtime_1.jsx(ContextMenuPortal, { sizeSource: body, currentZIndex: currentZIndex, onHide: onHide, opened: opened, values: [...openedValues] })) : null;
195
269
  };
196
270
  exports.ContextMenuForTarget = ContextMenuForTarget;
@@ -7,13 +7,14 @@ const remotion_1 = require("remotion");
7
7
  const is_composition_still_1 = require("../helpers/is-composition-still");
8
8
  const open_in_editor_1 = require("../helpers/open-in-editor");
9
9
  const render_frame_1 = require("../state/render-frame");
10
+ const InlineCompositionName_1 = require("./InlineCompositionName");
10
11
  const InspectorInfoHeader_1 = require("./InspectorInfoHeader");
11
12
  const InspectorSourceLocation_1 = require("./InspectorSourceLocation");
12
13
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
13
14
  const use_resolved_stack_1 = require("./Timeline/use-resolved-stack");
14
15
  exports.CURRENT_COMPOSITION_HEIGHT = InspectorInfoHeader_1.INSPECTOR_INFO_HEADER_MIN_HEIGHT;
15
16
  const CurrentComposition = () => {
16
- var _a;
17
+ var _a, _b;
17
18
  const video = remotion_1.Internals.useVideo();
18
19
  const { compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
19
20
  const currentComposition = (0, react_1.useMemo)(() => {
@@ -44,6 +45,6 @@ const CurrentComposition = () => {
44
45
  });
45
46
  }, [validatedLocation]);
46
47
  return (jsx_runtime_1.jsx(InspectorInfoHeader_1.InspectorInfoHeader, { children: video ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
47
- jsx_runtime_1.jsx(InspectorInfoHeader_1.InspectorInfoTitle, { children: video.id }), jsx_runtime_1.jsx(InspectorSourceLocation_1.InspectorSourceLocation, { location: validatedLocation, canOpen: validatedLocation !== null, onOpen: openFileLocation }), jsx_runtime_1.jsxs(InspectorInfoHeader_1.InspectorInfoSubtitle, { children: [video.width, "x", video.height, (0, is_composition_still_1.isCompositionStill)(video) ? null : `, ${video.fps} FPS`] }), (0, is_composition_still_1.isCompositionStill)(video) ? (jsx_runtime_1.jsx(InspectorInfoHeader_1.InspectorInfoSubtitle, { children: "Still" })) : (jsx_runtime_1.jsxs(InspectorInfoHeader_1.InspectorInfoSubtitle, { children: ["Duration ", (0, render_frame_1.renderFrame)(video.durationInFrames, video.fps)] }))] })) : null }));
48
+ jsx_runtime_1.jsx(InlineCompositionName_1.InlineCompositionName, { compositionId: video.id, stack: (_b = currentComposition === null || currentComposition === void 0 ? void 0 : currentComposition.stack) !== null && _b !== void 0 ? _b : null, compositions: compositions }, video.id), jsx_runtime_1.jsx(InspectorSourceLocation_1.InspectorSourceLocation, { location: validatedLocation, canOpen: validatedLocation !== null, onOpen: openFileLocation }), jsx_runtime_1.jsxs(InspectorInfoHeader_1.InspectorInfoSubtitle, { children: [video.width, "x", video.height, (0, is_composition_still_1.isCompositionStill)(video) ? null : `, ${video.fps} FPS`] }), (0, is_composition_still_1.isCompositionStill)(video) ? (jsx_runtime_1.jsx(InspectorInfoHeader_1.InspectorInfoSubtitle, { children: "Still" })) : (jsx_runtime_1.jsxs(InspectorInfoHeader_1.InspectorInfoSubtitle, { children: ["Duration ", (0, render_frame_1.renderFrame)(video.durationInFrames, video.fps)] }))] })) : null }));
48
49
  };
49
50
  exports.CurrentComposition = CurrentComposition;
@@ -0,0 +1,7 @@
1
+ import type * as React from 'react';
2
+ import type { _InternalTypes } from 'remotion';
3
+ export declare const InlineCompositionName: React.FC<{
4
+ readonly compositionId: string;
5
+ readonly stack: string | null;
6
+ readonly compositions: _InternalTypes['AnyComposition'][];
7
+ }>;
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InlineCompositionName = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const resolved_stack_to_symbolicated_1 = require("../helpers/resolved-stack-to-symbolicated");
7
+ const use_rename_composition_1 = require("../helpers/use-rename-composition");
8
+ const InlineEditableTitle_1 = require("./InlineEditableTitle");
9
+ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
10
+ const use_resolved_stack_1 = require("./Timeline/use-resolved-stack");
11
+ const InlineCompositionName = ({ compositionId, stack, compositions }) => {
12
+ const canRename = !window.remotion_isReadOnlyStudio;
13
+ const resolvedLocation = (0, use_resolved_stack_1.useResolvedStack)(stack);
14
+ const symbolicatedStack = (0, react_1.useMemo)(() => (0, resolved_stack_to_symbolicated_1.resolvedStackToSymbolicated)(resolvedLocation), [resolvedLocation]);
15
+ const { getValidationMessage, renameComposition } = (0, use_rename_composition_1.useRenameComposition)({
16
+ compositions,
17
+ currentId: compositionId,
18
+ newId: compositionId,
19
+ });
20
+ const commit = (0, react_1.useCallback)((newId) => {
21
+ if (newId === compositionId) {
22
+ return;
23
+ }
24
+ const compNameErrMessage = getValidationMessage(newId);
25
+ if (compNameErrMessage) {
26
+ (0, NotificationCenter_1.showNotification)(compNameErrMessage, 2000);
27
+ return;
28
+ }
29
+ if (!stack || !symbolicatedStack) {
30
+ (0, NotificationCenter_1.showNotification)('Could not determine where this composition is defined', 2000);
31
+ return;
32
+ }
33
+ const notification = (0, NotificationCenter_1.showNotification)('Renaming...', null);
34
+ renameComposition({
35
+ newCompositionId: newId,
36
+ signal: new AbortController().signal,
37
+ symbolicatedStack,
38
+ })
39
+ .then((result) => {
40
+ if (!result.success) {
41
+ notification.replaceContent(`Could not rename composition: ${result.reason}`, 2000);
42
+ return;
43
+ }
44
+ notification.replaceContent(`Renamed to ${newId}`, 2000);
45
+ })
46
+ .catch((err) => {
47
+ notification.replaceContent(`Could not rename composition: ${err.message}`, 2000);
48
+ });
49
+ }, [
50
+ compositionId,
51
+ getValidationMessage,
52
+ renameComposition,
53
+ stack,
54
+ symbolicatedStack,
55
+ ]);
56
+ return (jsx_runtime_1.jsx(InlineEditableTitle_1.InlineEditableTitle, { value: compositionId, canRename: canRename, onCommit: commit }));
57
+ };
58
+ exports.InlineCompositionName = InlineCompositionName;
@@ -0,0 +1,7 @@
1
+ import type * as React from 'react';
2
+ export declare const InlineEditableTitle: React.FC<{
3
+ readonly value: string;
4
+ readonly canRename: boolean;
5
+ readonly onCommit: (newValue: string) => void;
6
+ readonly title?: string;
7
+ }>;
@@ -0,0 +1,129 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InlineEditableTitle = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const colors_1 = require("../helpers/colors");
7
+ const titleWrapper = {
8
+ boxSizing: 'border-box',
9
+ color: 'white',
10
+ fontSize: 12,
11
+ height: 18,
12
+ lineHeight: '18px',
13
+ marginLeft: -4,
14
+ overflow: 'hidden',
15
+ textOverflow: 'ellipsis',
16
+ whiteSpace: 'nowrap',
17
+ width: 'calc(100% + 4px)',
18
+ };
19
+ const titleInner = {
20
+ borderRadius: 4,
21
+ boxSizing: 'border-box',
22
+ display: 'inline-grid',
23
+ fontSize: 12,
24
+ lineHeight: '18px',
25
+ maxWidth: '100%',
26
+ paddingLeft: 4,
27
+ paddingRight: 4,
28
+ verticalAlign: 'top',
29
+ };
30
+ const titleGridItem = {
31
+ fontSize: 12,
32
+ gridArea: '1 / 1',
33
+ minWidth: 0,
34
+ overflow: 'hidden',
35
+ textOverflow: 'ellipsis',
36
+ whiteSpace: 'nowrap',
37
+ };
38
+ const titleInput = {
39
+ appearance: 'none',
40
+ backgroundColor: 'transparent',
41
+ border: 'none',
42
+ boxShadow: 'none',
43
+ color: 'white',
44
+ fontFamily: 'inherit',
45
+ fontSize: 12,
46
+ height: 18,
47
+ lineHeight: '18px',
48
+ margin: 0,
49
+ minWidth: 0,
50
+ outline: 'none',
51
+ overflow: 'hidden',
52
+ padding: 0,
53
+ WebkitAppearance: 'none',
54
+ width: '100%',
55
+ };
56
+ const InlineEditableTitle = ({ value, canRename, onCommit, title }) => {
57
+ const [isEditing, setIsEditing] = (0, react_1.useState)(false);
58
+ const [isHovered, setIsHovered] = (0, react_1.useState)(false);
59
+ const [draftValue, setDraftValue] = (0, react_1.useState)(value);
60
+ const inputRef = (0, react_1.useRef)(null);
61
+ const cancelledRef = (0, react_1.useRef)(false);
62
+ (0, react_1.useEffect)(() => {
63
+ if (!isEditing) {
64
+ setDraftValue(value);
65
+ }
66
+ }, [isEditing, value]);
67
+ const focusInput = (0, react_1.useCallback)((input) => {
68
+ inputRef.current = input;
69
+ if (!input) {
70
+ return;
71
+ }
72
+ input.focus();
73
+ input.select();
74
+ }, []);
75
+ const commit = (0, react_1.useCallback)((newValue) => {
76
+ if (cancelledRef.current) {
77
+ return;
78
+ }
79
+ setIsEditing(false);
80
+ onCommit(newValue);
81
+ }, [onCommit]);
82
+ const startEditing = (0, react_1.useCallback)(() => {
83
+ if (!canRename) {
84
+ return;
85
+ }
86
+ cancelledRef.current = false;
87
+ setDraftValue(value);
88
+ setIsEditing(true);
89
+ }, [canRename, value]);
90
+ const onChange = (0, react_1.useCallback)((e) => {
91
+ setDraftValue(e.target.value);
92
+ }, []);
93
+ const onBlur = (0, react_1.useCallback)((e) => {
94
+ commit(e.currentTarget.value);
95
+ }, [commit]);
96
+ const onKeyDown = (0, react_1.useCallback)((e) => {
97
+ var _a;
98
+ if (e.key === 'Enter') {
99
+ e.preventDefault();
100
+ (_a = inputRef.current) === null || _a === void 0 ? void 0 : _a.blur();
101
+ }
102
+ if (e.key === 'Escape') {
103
+ e.preventDefault();
104
+ cancelledRef.current = true;
105
+ setDraftValue(value);
106
+ setIsEditing(false);
107
+ }
108
+ }, [value]);
109
+ const backgroundColor = isEditing
110
+ ? colors_1.INPUT_BACKGROUND
111
+ : isHovered && canRename
112
+ ? colors_1.CLEAR_HOVER
113
+ : 'transparent';
114
+ const innerStyle = (0, react_1.useMemo)(() => {
115
+ return {
116
+ ...titleInner,
117
+ backgroundColor,
118
+ cursor: isEditing ? 'text' : canRename ? 'pointer' : 'default',
119
+ userSelect: isEditing ? 'text' : 'none',
120
+ width: isEditing ? '100%' : undefined,
121
+ };
122
+ }, [backgroundColor, canRename, isEditing]);
123
+ return (jsx_runtime_1.jsx("div", { style: titleWrapper, title: title !== null && title !== void 0 ? title : value, children: jsx_runtime_1.jsxs("span", { style: innerStyle, onMouseEnter: () => setIsHovered(true), onMouseLeave: () => setIsHovered(false), onClick: isEditing || !canRename ? undefined : startEditing, children: [
124
+ jsx_runtime_1.jsx("span", { "aria-hidden": isEditing, style: {
125
+ ...titleGridItem,
126
+ visibility: isEditing ? 'hidden' : 'visible',
127
+ }, children: value }), isEditing ? (jsx_runtime_1.jsx("input", { ref: focusInput, style: { ...titleGridItem, ...titleInput }, value: draftValue, onChange: onChange, onBlur: onBlur, onKeyDown: onKeyDown })) : null] }) }));
128
+ };
129
+ exports.InlineEditableTitle = InlineEditableTitle;
@@ -85,6 +85,7 @@ const KeyframeInspector = ({ selection }) => {
85
85
  getDragOverrides,
86
86
  propStatuses,
87
87
  nodePath,
88
+ includeTextContent: false,
88
89
  });
89
90
  const sequenceField = (_b = sequenceFields === null || sequenceFields === void 0 ? void 0 : sequenceFields.find((candidate) => candidate.key === keyframeField.fieldKey)) !== null && _b !== void 0 ? _b : null;
90
91
  const sequencePropStatus = (_c = (_a = remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)) === null || _a === void 0 ? void 0 : _a[keyframeField.fieldKey]) !== null && _c !== void 0 ? _c : null;
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SequenceInspectorHeaderWithDivider = exports.SequenceInspectorHeader = exports.useSequenceInspectorSourceLocation = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
- const remotion_1 = require("remotion");
6
+ const client_id_1 = require("../../helpers/client-id");
7
+ const InlineEditableTitle_1 = require("../InlineEditableTitle");
7
8
  const InspectorSourceLocation_1 = require("../InspectorSourceLocation");
8
9
  const use_open_sequence_in_editor_1 = require("../Timeline/use-open-sequence-in-editor");
10
+ const use_rename_sequence_1 = require("../Timeline/use-rename-sequence");
9
11
  const styles_1 = require("./styles");
10
12
  const useSequenceInspectorSourceLocation = (sequence) => {
11
13
  const { canOpenInEditor, openInEditor, originalLocation } = (0, use_open_sequence_in_editor_1.useOpenSequenceInEditor)(sequence);
@@ -35,36 +37,18 @@ const useSequenceInspectorSourceLocation = (sequence) => {
35
37
  };
36
38
  };
37
39
  exports.useSequenceInspectorSourceLocation = useSequenceInspectorSourceLocation;
38
- const useSequenceDisplayName = (track) => {
39
- var _a, _b;
40
- var _c;
41
- const { propStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
42
- const nodePath = (_c = (_a = track.nodePathInfo) === null || _a === void 0 ? void 0 : _a.sequenceSubscriptionKey) !== null && _c !== void 0 ? _c : null;
43
- return (0, react_1.useMemo)(() => {
44
- var _a;
45
- const propStatusesForOverride = nodePath
46
- ? remotion_1.Internals.getPropStatusesCtx(propStatuses, nodePath)
47
- : undefined;
48
- const codeNameStatus = propStatusesForOverride === null || propStatusesForOverride === void 0 ? void 0 : propStatusesForOverride.name;
49
- const fallbackDisplayName = ((_a = track.sequence.controls) === null || _a === void 0 ? void 0 : _a.componentName) || '<Sequence>';
50
- if ((codeNameStatus === null || codeNameStatus === void 0 ? void 0 : codeNameStatus.status) === 'static' &&
51
- typeof codeNameStatus.codeValue === 'string') {
52
- return codeNameStatus.codeValue;
53
- }
54
- if ((codeNameStatus === null || codeNameStatus === void 0 ? void 0 : codeNameStatus.status) === 'static') {
55
- return fallbackDisplayName;
56
- }
57
- return track.sequence.displayName || fallbackDisplayName;
58
- }, [
59
- nodePath,
60
- propStatuses,
61
- (_b = track.sequence.controls) === null || _b === void 0 ? void 0 : _b.componentName,
62
- track.sequence.displayName,
63
- ]);
64
- };
65
40
  const SequenceInspectorHeader = ({ sourceLocation, track }) => {
66
41
  var _a;
67
- const sequenceDisplayName = useSequenceDisplayName(track);
42
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
43
+ const { canRename, displayName, fallbackDisplayName, saveName } = (0, use_rename_sequence_1.useRenameSequence)({
44
+ clientId: previewServerState.type === 'connected'
45
+ ? previewServerState.clientId
46
+ : null,
47
+ nodePathInfo: track.nodePathInfo,
48
+ sequence: track.sequence,
49
+ validatedLocation: sourceLocation.validatedLocation,
50
+ });
51
+ const sequenceDisplayName = displayName || fallbackDisplayName;
68
52
  const { documentationLink } = track.sequence;
69
53
  const openDocumentationLink = (0, react_1.useCallback)(() => {
70
54
  if (!documentationLink) {
@@ -79,8 +63,11 @@ const SequenceInspectorHeader = ({ sourceLocation, track }) => {
79
63
  };
80
64
  }, [documentationLink]);
81
65
  const componentName = (_a = track.sequence.controls) === null || _a === void 0 ? void 0 : _a.componentName;
66
+ const onRename = (0, react_1.useCallback)((newName) => {
67
+ saveName(newName).catch(() => undefined);
68
+ }, [saveName]);
82
69
  return (jsx_runtime_1.jsxs("div", { style: styles_1.sequenceHeader, children: [
83
- jsx_runtime_1.jsx("div", { style: styles_1.sequenceHeaderTitle, children: sequenceDisplayName }), documentationLink ? (jsx_runtime_1.jsx("button", { type: "button", style: subtitleStyle, title: "Open component docs", onClick: openDocumentationLink, children: componentName })) : (jsx_runtime_1.jsx("div", { style: subtitleStyle, children: componentName })), jsx_runtime_1.jsx(InspectorSourceLocation_1.InspectorSourceLocation, { location: sourceLocation.validatedLocation, canOpen: sourceLocation.canOpenInEditor, onOpen: sourceLocation.openFileLocation })
70
+ jsx_runtime_1.jsx("div", { style: styles_1.sequenceHeaderTitle, children: jsx_runtime_1.jsx(InlineEditableTitle_1.InlineEditableTitle, { value: sequenceDisplayName, canRename: canRename, onCommit: onRename }) }), documentationLink ? (jsx_runtime_1.jsx("button", { type: "button", style: subtitleStyle, title: "Open component docs", onClick: openDocumentationLink, children: componentName })) : (jsx_runtime_1.jsx("div", { style: subtitleStyle, children: componentName })), jsx_runtime_1.jsx(InspectorSourceLocation_1.InspectorSourceLocation, { location: sourceLocation.validatedLocation, canOpen: sourceLocation.canOpenInEditor, onOpen: sourceLocation.openFileLocation })
84
71
  ] }));
85
72
  };
86
73
  exports.SequenceInspectorHeader = SequenceInspectorHeader;
@@ -52,11 +52,11 @@ exports.sequenceHeader = {
52
52
  padding: `6px ${InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING}px 4px`,
53
53
  };
54
54
  exports.sequenceHeaderTitle = {
55
- alignSelf: 'flex-start',
55
+ alignSelf: 'stretch',
56
56
  backgroundColor: colors_1.BACKGROUND,
57
57
  border: 'none',
58
58
  color: 'white',
59
- display: 'inline-flex',
59
+ display: 'flex',
60
60
  fontFamily: 'sans-serif',
61
61
  fontSize: 12,
62
62
  lineHeight: '18px',
@@ -79,9 +79,40 @@ const isEffectsRoot = (node) => {
79
79
  const { auxiliaryKeys } = node.nodePathInfo;
80
80
  return auxiliaryKeys[auxiliaryKeys.length - 1] === 'effects';
81
81
  };
82
+ const INSPECTOR_COLLAPSED_ROWS_SESSION_STORAGE_KEY = 'remotion.editor.inspectorCollapsedRows';
82
83
  const getInspectorExpansionKey = (nodePathInfo) => {
83
84
  return JSON.stringify(nodePathInfo);
84
85
  };
86
+ const loadInspectorCollapsedKeys = () => {
87
+ if (typeof window === 'undefined') {
88
+ return new Set();
89
+ }
90
+ try {
91
+ const raw = window.sessionStorage.getItem(INSPECTOR_COLLAPSED_ROWS_SESSION_STORAGE_KEY);
92
+ if (raw === null) {
93
+ return new Set();
94
+ }
95
+ const parsed = JSON.parse(raw);
96
+ if (!Array.isArray(parsed)) {
97
+ return new Set();
98
+ }
99
+ return new Set(parsed.filter((key) => typeof key === 'string'));
100
+ }
101
+ catch (_a) {
102
+ return new Set();
103
+ }
104
+ };
105
+ const persistInspectorCollapsedKeys = (keys) => {
106
+ if (typeof window === 'undefined') {
107
+ return;
108
+ }
109
+ try {
110
+ window.sessionStorage.setItem(INSPECTOR_COLLAPSED_ROWS_SESSION_STORAGE_KEY, JSON.stringify([...keys]));
111
+ }
112
+ catch (_a) {
113
+ // Ignore quota errors or disabled storage.
114
+ }
115
+ };
85
116
  const getInspectorControlGroups = (rows) => {
86
117
  return timeline_layout_1.SCHEMA_FIELD_GROUPS.map((group) => ({
87
118
  ...group,
@@ -106,8 +137,9 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
106
137
  const { tree } = (0, use_timeline_expanded_tree_1.useTimelineExpandedTree)({
107
138
  sequence,
108
139
  nodePathInfo,
140
+ includeTextContent: true,
109
141
  });
110
- const [collapsedKeys, setCollapsedKeys] = (0, react_1.useState)(() => new Set());
142
+ const [collapsedKeys, setCollapsedKeys] = (0, react_1.useState)(loadInspectorCollapsedKeys);
111
143
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
112
144
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
113
145
  const getIsExpanded = (0, react_1.useCallback)((candidate) => {
@@ -123,6 +155,7 @@ const InspectorSequenceSection = ({ sequence, validatedLocation, nodePathInfo, k
123
155
  else {
124
156
  next.add(key);
125
157
  }
158
+ persistInspectorCollapsedKeys(next);
126
159
  return next;
127
160
  });
128
161
  }, []);
@@ -31,7 +31,7 @@ const Modals = ({ readOnlyStudio }) => {
31
31
  const { selectedModal: modalContextType } = (0, react_1.useContext)(modals_1.ModalsContext);
32
32
  const canRender = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState.type ===
33
33
  'connected';
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
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [modalContextType && modalContextType.type === 'new-comp' && (jsx_runtime_1.jsx(NewComposition_1.NewComposition, { folderName: modalContextType.folderName, parentName: modalContextType.parentName, stack: modalContextType.stack })), 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 &&
35
35
  modalContextType.type === 'server-render' &&
36
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, {})] }));
37
37
  };
@@ -1,5 +1,9 @@
1
- import type { RecastCodemod } from '@remotion/studio-shared';
1
+ import type { ApplyCodemodResponse, RecastCodemod, SymbolicatedStackFrame } from '@remotion/studio-shared';
2
2
  import React from 'react';
3
+ type ApplyCodemodAction = (options: {
4
+ signal: AbortSignal;
5
+ symbolicatedStack: SymbolicatedStackFrame | null;
6
+ }) => Promise<ApplyCodemodResponse>;
3
7
  export declare const CodemodFooter: React.FC<{
4
8
  readonly valid: boolean;
5
9
  readonly codemod: RecastCodemod;
@@ -13,4 +17,6 @@ export declare const CodemodFooter: React.FC<{
13
17
  }) => string;
14
18
  readonly onSuccess: (() => void) | null;
15
19
  readonly fallbackToRootFile?: boolean;
20
+ readonly applyCodemod: ApplyCodemodAction;
16
21
  }>;
22
+ export {};
@@ -13,7 +13,15 @@ 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, fallbackToRootFile = false, }) => {
16
+ const CodemodFooterPresentation = ({ codemodStatus, disabled, genericSubmitLabel, relativeFilePath, submitLabel, trigger, }) => {
17
+ return (jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
18
+ jsx_runtime_1.jsx(DiffPreview_1.CodemodDiffPreview, { status: codemodStatus }), jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(layout_1.Spacing, { block: true, x: 2 }), jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: trigger, disabled: disabled, children: [relativeFilePath
19
+ ? submitLabel({ relativeRootPath: relativeFilePath })
20
+ : genericSubmitLabel, jsx_runtime_1.jsx(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: false })
21
+ ] })
22
+ ] }));
23
+ };
24
+ const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNotification, errorNotification, genericSubmitLabel, submitLabel, onSuccess, fallbackToRootFile = false, applyCodemod, }) => {
17
25
  var _a;
18
26
  const [submitting, setSubmitting] = (0, react_1.useState)(false);
19
27
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
@@ -27,13 +35,15 @@ const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNoti
27
35
  setSubmitting(true);
28
36
  setSelectedModal(null);
29
37
  const notification = (0, NotificationCenter_1.showNotification)(loadingNotification, null);
30
- (0, actions_1.applyCodemod)({
31
- codemod,
32
- dryRun: false,
38
+ applyCodemod({
33
39
  symbolicatedStack,
34
40
  signal: new AbortController().signal,
35
41
  })
36
- .then(() => {
42
+ .then((result) => {
43
+ if (!result.success) {
44
+ notification.replaceContent(`${errorNotification}: ${result.reason}`, 2000);
45
+ return;
46
+ }
37
47
  notification.replaceContent(successNotification, 2000);
38
48
  onSuccess === null || onSuccess === void 0 ? void 0 : onSuccess();
39
49
  })
@@ -41,7 +51,7 @@ const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNoti
41
51
  notification.replaceContent(`${errorNotification}: ${err.message}`, 2000);
42
52
  });
43
53
  }, [
44
- codemod,
54
+ applyCodemod,
45
55
  errorNotification,
46
56
  loadingNotification,
47
57
  onSuccess,
@@ -145,11 +155,6 @@ const CodemodFooter = ({ codemod, stack, valid, loadingNotification, successNoti
145
155
  enter.unregister();
146
156
  };
147
157
  }, [disabled, registerKeybinding, trigger, valid]);
148
- return (jsx_runtime_1.jsxs(layout_1.Row, { align: "center", children: [
149
- jsx_runtime_1.jsx(DiffPreview_1.CodemodDiffPreview, { status: codemodStatus }), jsx_runtime_1.jsx(layout_1.Flex, {}), jsx_runtime_1.jsx(layout_1.Spacing, { block: true, x: 2 }), jsx_runtime_1.jsxs(ModalButton_1.ModalButton, { onClick: trigger, disabled: disabled, children: [relativeFilePath
150
- ? submitLabel({ relativeRootPath: relativeFilePath })
151
- : genericSubmitLabel, jsx_runtime_1.jsx(ShortcutHint_1.ShortcutHint, { keyToPress: "\u21B5", cmdOrCtrl: false })
152
- ] })
153
- ] }));
158
+ return (jsx_runtime_1.jsx(CodemodFooterPresentation, { codemodStatus: codemodStatus, disabled: disabled, genericSubmitLabel: genericSubmitLabel, relativeFilePath: relativeFilePath, submitLabel: submitLabel, trigger: trigger }));
154
159
  };
155
160
  exports.CodemodFooter = CodemodFooter;
@@ -7,6 +7,7 @@ const styles_1 = require("../Menu/styles");
7
7
  const ModalFooter_1 = require("../ModalFooter");
8
8
  const ModalHeader_1 = require("../ModalHeader");
9
9
  const ResolveCompositionBeforeModal_1 = require("../RenderModal/ResolveCompositionBeforeModal");
10
+ const actions_1 = require("../RenderQueue/actions");
10
11
  const CodemodFooter_1 = require("./CodemodFooter");
11
12
  const DismissableModal_1 = require("./DismissableModal");
12
13
  const content = {
@@ -38,7 +39,12 @@ const DeleteCompositionLoaded = ({ compositionId }) => {
38
39
  jsx_runtime_1.jsx("br", {}),
39
40
  "The associated ",
40
41
  jsx_runtime_1.jsx("code", { style: styles_1.inlineCodeSnippet, children: "component" }),
41
- " will remain in your code."] }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsx(CodemodFooter_1.CodemodFooter, { errorNotification: `Could not delete composition`, loadingNotification: 'Deleting', successNotification: `Deleted ${unresolved.id}`, genericSubmitLabel: `Delete`, submitLabel: ({ relativeRootPath }) => `Delete from ${relativeRootPath}`, codemod: codemod, stack: compositionStack, valid: true, onSuccess: null }) })
42
+ " will remain in your code."] }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsx(CodemodFooter_1.CodemodFooter, { errorNotification: `Could not delete composition`, loadingNotification: 'Deleting', successNotification: `Deleted ${unresolved.id}`, genericSubmitLabel: `Delete`, submitLabel: ({ relativeRootPath }) => `Delete from ${relativeRootPath}`, codemod: codemod, stack: compositionStack, valid: true, onSuccess: null, applyCodemod: ({ signal, symbolicatedStack }) => (0, actions_1.applyCodemod)({
43
+ codemod,
44
+ dryRun: false,
45
+ signal,
46
+ symbolicatedStack,
47
+ }) }) })
42
48
  ] })
43
49
  ] }));
44
50
  };