@remotion/studio 4.0.486 → 4.0.488

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 (67) hide show
  1. package/dist/components/Canvas.js +156 -4
  2. package/dist/components/ContextMenu.js +2 -1
  3. package/dist/components/CurrentComposition.js +43 -2
  4. package/dist/components/EditorContexts.js +2 -1
  5. package/dist/components/GlobalKeybindings.js +19 -0
  6. package/dist/components/InspectorPanel/DefaultInspector.js +2 -1
  7. package/dist/components/InspectorSourceLocation.d.ts +1 -0
  8. package/dist/components/InspectorSourceLocation.js +18 -3
  9. package/dist/components/KeyboardShortcutsExplainer.js +4 -0
  10. package/dist/components/Preview.js +1 -1
  11. package/dist/components/PreviewToolbar.js +2 -1
  12. package/dist/components/RenderButton.js +1 -0
  13. package/dist/components/RenderModal/OptionExplainer.d.ts +11 -1
  14. package/dist/components/RenderModal/OptionExplainer.js +31 -11
  15. package/dist/components/RenderModal/OptionExplainerBubble.d.ts +15 -1
  16. package/dist/components/RenderModal/OptionExplainerBubble.js +17 -3
  17. package/dist/components/RenderModal/SchemaEditor/Fieldset.d.ts +1 -0
  18. package/dist/components/RenderModal/SchemaEditor/Fieldset.js +6 -1
  19. package/dist/components/RenderModal/SchemaEditor/SchemaEditor.js +1 -2
  20. package/dist/components/RenderModal/WebRenderModal.js +5 -2
  21. package/dist/components/RenderModal/WebRenderModalAdvanced.d.ts +3 -0
  22. package/dist/components/RenderModal/WebRenderModalAdvanced.js +92 -5
  23. package/dist/components/RenderModal/WebRenderModalBasic.js +2 -2
  24. package/dist/components/RenderQueue/ClientRenderQueueProcessor.js +1 -0
  25. package/dist/components/RenderQueue/client-side-render-types.d.ts +2 -1
  26. package/dist/components/SelectedOutlineElement.d.ts +4 -0
  27. package/dist/components/SelectedOutlineElement.js +56 -11
  28. package/dist/components/SelectedOutlineOverlay.d.ts +2 -0
  29. package/dist/components/SelectedOutlineOverlay.js +55 -3
  30. package/dist/components/SelectedOutlineUvControls.js +13 -6
  31. package/dist/components/SnappingProvider.d.ts +4 -0
  32. package/dist/components/SnappingProvider.js +24 -0
  33. package/dist/components/SnappingToggle.d.ts +2 -0
  34. package/dist/components/SnappingToggle.js +26 -0
  35. package/dist/components/Splitter/SplitterContext.d.ts +1 -1
  36. package/dist/components/Timeline/Timeline.js +8 -6
  37. package/dist/components/Timeline/TimelineDragHandler.js +2 -1
  38. package/dist/components/Timeline/TimelineSelection.js +8 -1
  39. package/dist/components/Timeline/TimelineSequence.js +15 -8
  40. package/dist/components/Timeline/TimelineSequenceItem.js +63 -51
  41. package/dist/components/VisualControls/ClickableFileName.js +2 -2
  42. package/dist/components/VisualControls/VisualControlsContent.js +9 -1
  43. package/dist/components/effect-drag-and-drop.js +30 -9
  44. package/dist/components/import-assets.d.ts +1 -1
  45. package/dist/components/options-sidebar-tabs.d.ts +1 -0
  46. package/dist/components/options-sidebar-tabs.js +6 -1
  47. package/dist/components/selected-outline-snap.d.ts +36 -0
  48. package/dist/components/selected-outline-snap.js +158 -0
  49. package/dist/esm/{chunk-975rp13y.js → chunk-nn36hyt1.js} +5001 -3970
  50. package/dist/esm/index.mjs +3 -0
  51. package/dist/esm/internals.mjs +5001 -3970
  52. package/dist/esm/previewEntry.mjs +5544 -4513
  53. package/dist/esm/renderEntry.mjs +1 -1
  54. package/dist/helpers/interactivity-enabled.d.ts +1 -0
  55. package/dist/helpers/interactivity-enabled.js +7 -0
  56. package/dist/helpers/retry-payload.js +1 -0
  57. package/dist/helpers/use-menu-structure.js +43 -2
  58. package/dist/icons/magnet.d.ts +3 -0
  59. package/dist/icons/magnet.js +8 -0
  60. package/dist/icons/react.d.ts +5 -0
  61. package/dist/icons/react.js +8 -0
  62. package/dist/state/editor-guides.d.ts +2 -2
  63. package/dist/state/editor-snapping.d.ts +8 -0
  64. package/dist/state/editor-snapping.js +18 -0
  65. package/dist/state/modals.d.ts +2 -1
  66. package/dist/visual-controls/VisualControls.js +4 -0
  67. package/package.json +12 -12
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  export declare const SCHEMA_EDITOR_FIELDSET_PADDING = 6;
3
3
  export declare const getSchemaEditorFieldsetPadding: () => number;
4
+ export declare const getSchemaEditorRootInset: (contentInset: number) => number;
4
5
  export declare const Fieldset: React.FC<{
5
6
  readonly children: React.ReactNode;
6
7
  readonly shouldPad: boolean;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Fieldset = exports.getSchemaEditorFieldsetPadding = exports.SCHEMA_EDITOR_FIELDSET_PADDING = void 0;
3
+ exports.Fieldset = exports.getSchemaEditorRootInset = exports.getSchemaEditorFieldsetPadding = exports.SCHEMA_EDITOR_FIELDSET_PADDING = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  exports.SCHEMA_EDITOR_FIELDSET_PADDING = 6;
@@ -8,6 +8,11 @@ const getSchemaEditorFieldsetPadding = () => {
8
8
  return exports.SCHEMA_EDITOR_FIELDSET_PADDING;
9
9
  };
10
10
  exports.getSchemaEditorFieldsetPadding = getSchemaEditorFieldsetPadding;
11
+ const getSchemaEditorRootInset = (contentInset) => {
12
+ const fieldsetPadding = (0, exports.getSchemaEditorFieldsetPadding)();
13
+ return Math.max(0, contentInset - fieldsetPadding);
14
+ };
15
+ exports.getSchemaEditorRootInset = getSchemaEditorRootInset;
11
16
  const AlreadyPaddedRightContext = (0, react_1.createContext)(false);
12
17
  const Fieldset = ({ children, shouldPad }) => {
13
18
  const alreadyPadded = (0, react_1.useContext)(AlreadyPaddedRightContext);
@@ -24,8 +24,7 @@ const getContainerStyle = ({ contentInset, scrollableContainer, }) => {
24
24
  if (contentInset === undefined) {
25
25
  return base;
26
26
  }
27
- const fieldsetPadding = (0, Fieldset_1.getSchemaEditorFieldsetPadding)();
28
- const rootInset = Math.max(0, contentInset - fieldsetPadding);
27
+ const rootInset = (0, Fieldset_1.getSchemaEditorRootInset)(contentInset);
29
28
  return {
30
29
  ...base,
31
30
  boxSizing: 'border-box',
@@ -81,7 +81,7 @@ const validateOutnameForStill = ({ outName, stillImageFormat, }) => {
81
81
  // TODO: Shortcut: Shift + R
82
82
  // TODO: Apply defaultCodec
83
83
  // TODO: Apply defaultOutName
84
- const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, initialLogLevel, initialLicenseKey, initialStillImageFormat, initialDefaultOutName, initialScale, initialDelayRenderTimeout, initialMediaCacheSizeInBytes, initialContainer, initialVideoCodec, initialAudioCodec, initialAudioBitrate, initialVideoBitrate, initialHardwareAcceleration, initialKeyframeIntervalInSeconds, initialTransparent, initialMuted, initialAllowHtmlInCanvas, }) => {
84
+ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark, initialLogLevel, initialLicenseKey, initialStillImageFormat, initialDefaultOutName, initialScale, initialDelayRenderTimeout, initialMediaCacheSizeInBytes, initialContainer, initialVideoCodec, initialAudioCodec, initialAudioBitrate, initialVideoBitrate, initialHardwareAcceleration, initialKeyframeIntervalInSeconds, initialTransparent, initialMuted, initialAllowHtmlInCanvas, initialPageResponsiveness, }) => {
85
85
  var _a;
86
86
  const context = (0, react_1.useContext)(ResolveCompositionBeforeModal_1.ResolvedCompositionContext);
87
87
  const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
@@ -126,6 +126,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
126
126
  const [scale, setScale] = (0, react_1.useState)(initialScale !== null && initialScale !== void 0 ? initialScale : 1);
127
127
  const [licenseKey, setLicenseKey] = (0, react_1.useState)(initialLicenseKey);
128
128
  const [allowHtmlInCanvas, setAllowHtmlInCanvas] = (0, react_1.useState)(initialAllowHtmlInCanvas !== null && initialAllowHtmlInCanvas !== void 0 ? initialAllowHtmlInCanvas : false);
129
+ const [pageResponsiveness, setPageResponsiveness] = (0, react_1.useState)(initialPageResponsiveness !== null && initialPageResponsiveness !== void 0 ? initialPageResponsiveness : 'medium');
129
130
  const encodableAudioCodecs = (0, use_encodable_audio_codecs_1.useEncodableAudioCodecs)(container);
130
131
  const encodableVideoCodecs = (0, use_encodable_video_codecs_1.useEncodableVideoCodecs)(container);
131
132
  const effectiveAudioCodec = (0, react_1.useMemo)(() => {
@@ -366,6 +367,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
366
367
  licenseKey,
367
368
  scale,
368
369
  allowHtmlInCanvas,
370
+ pageResponsiveness,
369
371
  }, compositionRef);
370
372
  }
371
373
  setSidebarCollapsedState({ left: null, right: 'expanded' });
@@ -407,6 +409,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
407
409
  addClientVideoJob,
408
410
  scale,
409
411
  allowHtmlInCanvas,
412
+ pageResponsiveness,
410
413
  ]);
411
414
  return (jsx_runtime_1.jsxs("div", { style: render_modals_1.outerModalStyle, children: [
412
415
  jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Render ${resolvedComposition.id}` }), jsx_runtime_1.jsxs("div", { style: render_modals_1.container, children: [
@@ -431,7 +434,7 @@ const WebRenderModal = ({ initialFrame, defaultProps, inFrameMark, outFrameMark,
431
434
  canUpdate: false,
432
435
  reason: 'render dialogue',
433
436
  determined: false,
434
- } })) : tab === 'picture' ? (jsx_runtime_1.jsx(WebRenderModalPicture_1.WebRenderModalPicture, { renderMode: renderMode, videoBitrate: videoBitrate, setVideoBitrate: setVideoBitrate, keyframeIntervalInSeconds: keyframeIntervalInSeconds, setKeyframeIntervalInSeconds: setKeyframeIntervalInSeconds, transparent: transparent, setTransparent: setTransparent, scale: scale, setScale: setScale, compositionWidth: resolvedComposition.width, compositionHeight: resolvedComposition.height })) : tab === 'audio' ? (jsx_runtime_1.jsx(WebRenderModalAudio_1.WebRenderModalAudio, { renderMode: renderMode, muted: muted, setMuted: setMuted, audioCodec: audioCodec, setAudioCodec: setAudioCodec, audioBitrate: audioBitrate, setAudioBitrate: setAudioBitrate, container: container, encodableCodecs: encodableAudioCodecs, effectiveAudioCodec: effectiveAudioCodec })) : tab === 'advanced' ? (jsx_runtime_1.jsx(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration, allowHtmlInCanvas: allowHtmlInCanvas, setAllowHtmlInCanvas: setAllowHtmlInCanvas })) : (jsx_runtime_1.jsx(WebRenderModalLicense_1.WebRenderModalLicense, { licenseKey: licenseKey, setLicenseKey: setLicenseKey, initialPublicLicenseKey: initialLicenseKey })) })
437
+ } })) : tab === 'picture' ? (jsx_runtime_1.jsx(WebRenderModalPicture_1.WebRenderModalPicture, { renderMode: renderMode, videoBitrate: videoBitrate, setVideoBitrate: setVideoBitrate, keyframeIntervalInSeconds: keyframeIntervalInSeconds, setKeyframeIntervalInSeconds: setKeyframeIntervalInSeconds, transparent: transparent, setTransparent: setTransparent, scale: scale, setScale: setScale, compositionWidth: resolvedComposition.width, compositionHeight: resolvedComposition.height })) : tab === 'audio' ? (jsx_runtime_1.jsx(WebRenderModalAudio_1.WebRenderModalAudio, { renderMode: renderMode, muted: muted, setMuted: setMuted, audioCodec: audioCodec, setAudioCodec: setAudioCodec, audioBitrate: audioBitrate, setAudioBitrate: setAudioBitrate, container: container, encodableCodecs: encodableAudioCodecs, effectiveAudioCodec: effectiveAudioCodec })) : tab === 'advanced' ? (jsx_runtime_1.jsx(WebRenderModalAdvanced_1.WebRenderModalAdvanced, { renderMode: renderMode, delayRenderTimeout: delayRenderTimeout, setDelayRenderTimeout: setDelayRenderTimeout, mediaCacheSizeInBytes: mediaCacheSizeInBytes, setMediaCacheSizeInBytes: setMediaCacheSizeInBytes, hardwareAcceleration: hardwareAcceleration, setHardwareAcceleration: setHardwareAcceleration, allowHtmlInCanvas: allowHtmlInCanvas, setAllowHtmlInCanvas: setAllowHtmlInCanvas, pageResponsiveness: pageResponsiveness, setPageResponsiveness: setPageResponsiveness })) : (jsx_runtime_1.jsx(WebRenderModalLicense_1.WebRenderModalLicense, { licenseKey: licenseKey, setLicenseKey: setLicenseKey, initialPublicLicenseKey: initialLicenseKey })) })
435
438
  ] })
436
439
  ] }));
437
440
  };
@@ -1,3 +1,4 @@
1
+ import type { WebRendererPageResponsiveness } from '@remotion/web-renderer';
1
2
  import type React from 'react';
2
3
  import type { RenderType } from './WebRenderModal';
3
4
  type WebRenderModalAdvancedProps = {
@@ -10,6 +11,8 @@ type WebRenderModalAdvancedProps = {
10
11
  readonly setHardwareAcceleration: (value: 'no-preference' | 'prefer-hardware' | 'prefer-software') => void;
11
12
  readonly allowHtmlInCanvas: boolean;
12
13
  readonly setAllowHtmlInCanvas: React.Dispatch<React.SetStateAction<boolean>>;
14
+ readonly pageResponsiveness: WebRendererPageResponsiveness;
15
+ readonly setPageResponsiveness: React.Dispatch<React.SetStateAction<WebRendererPageResponsiveness>>;
13
16
  };
14
17
  export declare const WebRenderModalAdvanced: React.FC<WebRenderModalAdvancedProps>;
15
18
  export {};
@@ -13,7 +13,24 @@ const OptionExplainerBubble_1 = require("./OptionExplainerBubble");
13
13
  const tabContainer = {
14
14
  flex: 1,
15
15
  };
16
- const WebRenderModalAdvanced = ({ renderMode, delayRenderTimeout, setDelayRenderTimeout, mediaCacheSizeInBytes, setMediaCacheSizeInBytes, hardwareAcceleration, setHardwareAcceleration, allowHtmlInCanvas, setAllowHtmlInCanvas, }) => {
16
+ const paragraph = {
17
+ margin: 0,
18
+ marginBottom: 8,
19
+ };
20
+ const lastParagraph = {
21
+ margin: 0,
22
+ };
23
+ const PageResponsivenessDescription = () => {
24
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
25
+ jsx_runtime_1.jsx("p", { style: paragraph, children: "The Web Renderer runs in the same browser tab as the Studio. Rendering can block the tab while Remotion captures frames." }), jsx_runtime_1.jsxs("p", { style: paragraph, children: ["The default is ",
26
+ jsx_runtime_1.jsx("code", { children: "Medium" }),
27
+ ", which tries to free the event loop every 33ms of rendering work so progress updates and UI interactions can stay responsive."] }), jsx_runtime_1.jsxs("p", { style: lastParagraph, children: ["Choose ",
28
+ jsx_runtime_1.jsx("code", { children: "Disabled" }),
29
+ " to prioritize render speed, or", ' ', jsx_runtime_1.jsx("code", { children: "High" }),
30
+ " to give the browser more chances to update."] })
31
+ ] }));
32
+ };
33
+ const WebRenderModalAdvanced = ({ renderMode, delayRenderTimeout, setDelayRenderTimeout, mediaCacheSizeInBytes, setMediaCacheSizeInBytes, hardwareAcceleration, setHardwareAcceleration, allowHtmlInCanvas, setAllowHtmlInCanvas, pageResponsiveness, setPageResponsiveness, }) => {
17
34
  const toggleCustomMediaCacheSizeInBytes = (0, react_1.useCallback)(() => {
18
35
  setMediaCacheSizeInBytes((previous) => {
19
36
  if (previous === null) {
@@ -73,18 +90,88 @@ const WebRenderModalAdvanced = ({ renderMode, delayRenderTimeout, setDelayRender
73
90
  },
74
91
  ];
75
92
  }, [hardwareAcceleration, setHardwareAcceleration]);
93
+ const selectedPageResponsiveness = typeof pageResponsiveness === 'number' ? 'custom' : pageResponsiveness;
94
+ const pageResponsivenessOptions = (0, react_1.useMemo)(() => {
95
+ return [
96
+ {
97
+ label: 'Disabled',
98
+ onClick: () => setPageResponsiveness('disabled'),
99
+ leftItem: selectedPageResponsiveness === 'disabled' ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
100
+ id: 'disabled',
101
+ keyHint: null,
102
+ quickSwitcherLabel: null,
103
+ subMenu: null,
104
+ type: 'item',
105
+ value: 'disabled',
106
+ },
107
+ {
108
+ label: 'Low (100ms)',
109
+ onClick: () => setPageResponsiveness('low'),
110
+ leftItem: selectedPageResponsiveness === 'low' ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
111
+ id: 'low',
112
+ keyHint: null,
113
+ quickSwitcherLabel: null,
114
+ subMenu: null,
115
+ type: 'item',
116
+ value: 'low',
117
+ },
118
+ {
119
+ label: 'Medium (33ms)',
120
+ onClick: () => setPageResponsiveness('medium'),
121
+ leftItem: selectedPageResponsiveness === 'medium' ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
122
+ id: 'medium',
123
+ keyHint: null,
124
+ quickSwitcherLabel: null,
125
+ subMenu: null,
126
+ type: 'item',
127
+ value: 'medium',
128
+ },
129
+ {
130
+ label: 'High (16ms)',
131
+ onClick: () => setPageResponsiveness('high'),
132
+ leftItem: selectedPageResponsiveness === 'high' ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
133
+ id: 'high',
134
+ keyHint: null,
135
+ quickSwitcherLabel: null,
136
+ subMenu: null,
137
+ type: 'item',
138
+ value: 'high',
139
+ },
140
+ {
141
+ label: 'Custom',
142
+ onClick: () => setPageResponsiveness((previous) => typeof previous === 'number' ? previous : 33),
143
+ leftItem: selectedPageResponsiveness === 'custom' ? jsx_runtime_1.jsx(Checkmark_1.Checkmark, {}) : null,
144
+ id: 'custom',
145
+ keyHint: null,
146
+ quickSwitcherLabel: null,
147
+ subMenu: null,
148
+ type: 'item',
149
+ value: 'custom',
150
+ },
151
+ ];
152
+ }, [selectedPageResponsiveness, setPageResponsiveness]);
153
+ const setCustomPageResponsiveness = (0, react_1.useCallback)((value) => {
154
+ setPageResponsiveness((previous) => {
155
+ const currentValue = typeof previous === 'number' ? previous : 33;
156
+ return typeof value === 'function' ? value(currentValue) : value;
157
+ });
158
+ }, [setPageResponsiveness]);
76
159
  return (jsx_runtime_1.jsxs("div", { style: tabContainer, children: [
77
160
  jsx_runtime_1.jsx(NumberSetting_1.NumberSetting, { name: "Delay Render Timeout", formatter: (v) => `${v}ms`, min: 0, max: 1000000000, step: 1000, value: delayRenderTimeout, onValueChanged: setDelayRenderTimeout, hint: "delayRenderTimeoutInMillisecondsOption" }), jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
78
161
  jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Custom @remotion/media cache size ",
79
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "mediaCacheSizeInBytesOption" })
162
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.WebRendererOptionExplainerBubble, { apiName: "mediaCacheSizeInBytes", id: "mediaCacheSizeInBytesOption" })
80
163
  ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: mediaCacheSizeInBytes !== null, onChange: toggleCustomMediaCacheSizeInBytes, name: "media-cache-size" }) })
81
164
  ] }), mediaCacheSizeInBytes === null ? null : (jsx_runtime_1.jsx(NumberSetting_1.NumberSetting, { name: "@remotion/media cache size", formatter: (w) => `${w} bytes`, min: 0, max: 10000000000, step: 10 * 1024 * 1024, value: mediaCacheSizeInBytes, onValueChanged: changeMediaCacheSizeInBytes })), renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
82
165
  jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Hardware Acceleration" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: hardwareAccelerationOptions, selectedId: hardwareAcceleration, title: "Hardware Acceleration" }) })
83
166
  ] })) : null, jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
84
167
  jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Allow HTML-in-canvas ",
85
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "allowHtmlInCanvasOption" })
168
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.WebRendererOptionExplainerBubble, { apiName: "allowHtmlInCanvas", id: "allowHtmlInCanvasOption" })
86
169
  ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(Checkbox_1.Checkbox, { checked: allowHtmlInCanvas, onChange: toggleAllowHtmlInCanvas, name: "allow-html-in-canvas" }) })
87
- ] })
88
- ] }));
170
+ ] }), renderMode === 'still' ? null : (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
171
+ jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
172
+ jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Page Responsiveness ",
173
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.WebRendererCustomOptionExplainerBubble, { apiName: "pageResponsiveness", description: jsx_runtime_1.jsx(PageResponsivenessDescription, {}), docLink: "https://www.remotion.dev/docs/client-side-rendering/page-responsiveness", name: "Page responsiveness" })
174
+ ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: pageResponsivenessOptions, selectedId: selectedPageResponsiveness, title: "Page Responsiveness" }) })
175
+ ] }), typeof pageResponsiveness === 'number' ? (jsx_runtime_1.jsx(NumberSetting_1.NumberSetting, { name: "Responsiveness Interval", formatter: (v) => `${v}ms`, min: 1, max: 1000000000, step: 1, value: pageResponsiveness, onValueChanged: setCustomPageResponsiveness })) : null] }))] }));
89
176
  };
90
177
  exports.WebRenderModalAdvanced = WebRenderModalAdvanced;
@@ -118,12 +118,12 @@ const WebRenderModalBasic = ({ renderMode, resolvedComposition, imageFormat, set
118
118
  jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Container" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: containerOptions, selectedId: container, title: "Container" }) })
119
119
  ] }), renderMode === 'video' ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
120
120
  jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Codec",
121
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "videoCodecOption" })
121
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.WebRendererOptionExplainerBubble, { apiName: "codec", id: "videoCodecOption" })
122
122
  ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: codecOptions, selectedId: effectiveVideoCodec, title: "Codec" }) })
123
123
  ] })) : null, jsx_runtime_1.jsx(FrameRangeSetting_1.FrameRangeSetting, { durationInFrames: resolvedComposition.durationInFrames, startFrame: startFrame !== null && startFrame !== void 0 ? startFrame : 0, endFrame: endFrame !== null && endFrame !== void 0 ? endFrame : resolvedComposition.durationInFrames - 1, setStartFrame: setStartFrame, setEndFrame: setEndFrame })
124
124
  ] })), jsx_runtime_1.jsx(RenderModalOutputName_1.RenderModalOutputName, { existence: false, inputStyle: layout_2.input, outName: outName, onValueChange: onOutNameChange, validationMessage: validationMessage, label: window.remotion_isReadOnlyStudio ? 'Download name' : 'Output name' }), jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
125
125
  jsx_runtime_1.jsxs("div", { style: layout_2.label, children: ["Log Level ",
126
- jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.OptionExplainerBubble, { id: "logLevelOption" })
126
+ jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }), jsx_runtime_1.jsx(OptionExplainerBubble_1.WebRendererOptionExplainerBubble, { apiName: "logLevel", id: "logLevelOption" })
127
127
  ] }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { values: logLevelOptions, selectedId: logLevel, title: "Log Level" }) })
128
128
  ] })
129
129
  ] }));
@@ -98,6 +98,7 @@ const ClientRenderQueueProcessor = () => {
98
98
  outputTarget: 'web-fs',
99
99
  licenseKey: (_c = job.licenseKey) !== null && _c !== void 0 ? _c : undefined,
100
100
  allowHtmlInCanvas: job.allowHtmlInCanvas,
101
+ pageResponsiveness: job.pageResponsiveness,
101
102
  });
102
103
  return {
103
104
  getBlob,
@@ -1,5 +1,5 @@
1
1
  import type { CompletedClientRender } from '@remotion/studio-shared';
2
- import type { RenderStillOnWebImageFormat, WebRendererAudioCodec, WebRendererContainer, WebRendererQuality, WebRendererVideoCodec } from '@remotion/web-renderer';
2
+ import type { RenderStillOnWebImageFormat, WebRendererAudioCodec, WebRendererContainer, WebRendererPageResponsiveness, WebRendererQuality, WebRendererVideoCodec } from '@remotion/web-renderer';
3
3
  import type { LogLevel } from 'remotion';
4
4
  export type ClientRenderJobProgress = {
5
5
  encodedFrames: number;
@@ -60,6 +60,7 @@ export type ClientVideoRenderJob = ClientRenderJobBase & {
60
60
  keyframeIntervalInSeconds: number;
61
61
  transparent: boolean;
62
62
  muted: boolean;
63
+ pageResponsiveness: WebRendererPageResponsiveness;
63
64
  } & ClientRenderJobDynamicStatus;
64
65
  export type RestoredClientRenderJob = CompletedClientRender & {
65
66
  status: 'done';
@@ -1,5 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { SelectedOutline } from './selected-outline-geometry';
3
+ import { type SelectedOutlineSnapPoint, type SelectedOutlineSnapTarget } from './selected-outline-snap';
3
4
  import { type SelectedOutlineDragTarget, type SelectedOutlineRotationDragTarget, type SelectedOutlineScaleDragTarget, type SelectedOutlineTarget } from './selected-outline-types';
4
5
  import type { TimelineSelection, TimelineSelectionInteraction } from './Timeline/TimelineSelection';
5
6
  export declare const SelectedOutlineTransformOriginHandle: React.FC<{
@@ -9,6 +10,7 @@ export declare const SelectedOutlineTransformOriginHandle: React.FC<{
9
10
  }>;
10
11
  export declare const SelectedOutlineElement: React.FC<{
11
12
  readonly allDragTargets: readonly SelectedOutlineDragTarget[];
13
+ readonly allDragOutlines: readonly SelectedOutline[];
12
14
  readonly allRotationDragTargets: readonly SelectedOutlineRotationDragTarget[];
13
15
  readonly allScaleDragTargets: readonly SelectedOutlineScaleDragTarget[];
14
16
  readonly dragging: boolean;
@@ -16,7 +18,9 @@ export declare const SelectedOutlineElement: React.FC<{
16
18
  readonly outline: SelectedOutline;
17
19
  readonly onDraggingChange: (dragging: boolean) => void;
18
20
  readonly onHoverChange: (key: string | null) => void;
21
+ readonly onSnapPointsChange: (snapPoints: readonly SelectedOutlineSnapPoint[]) => void;
19
22
  readonly onSelect: (item: TimelineSelection, interaction: TimelineSelectionInteraction) => void;
20
23
  readonly scale: number;
24
+ readonly snapTargets: readonly SelectedOutlineSnapTarget[];
21
25
  readonly target: SelectedOutlineTarget | undefined;
22
26
  }>;
@@ -43,6 +43,7 @@ const client_id_1 = require("../helpers/client-id");
43
43
  const colors_1 = require("../helpers/colors");
44
44
  const format_file_location_1 = require("../helpers/format-file-location");
45
45
  const open_in_editor_1 = require("../helpers/open-in-editor");
46
+ const editor_snapping_1 = require("../state/editor-snapping");
46
47
  const modals_1 = require("../state/modals");
47
48
  const call_api_1 = require("./call-api");
48
49
  const ConfirmationDialog_1 = require("./ConfirmationDialog");
@@ -53,6 +54,7 @@ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
53
54
  const options_sidebar_tabs_1 = require("./options-sidebar-tabs");
54
55
  const selected_outline_drag_1 = require("./selected-outline-drag");
55
56
  const selected_outline_measurement_1 = require("./selected-outline-measurement");
57
+ const selected_outline_snap_1 = require("./selected-outline-snap");
56
58
  const selected_outline_types_1 = require("./selected-outline-types");
57
59
  const selected_outline_uv_1 = require("./selected-outline-uv");
58
60
  const call_add_keyframe_1 = require("./Timeline/call-add-keyframe");
@@ -70,6 +72,7 @@ const emptyContextMenuValues = [];
70
72
  const SelectedOutlineTransformOriginHandle = ({ outline, onDraggingChange, target }) => {
71
73
  var _a;
72
74
  const { setDragOverrides, clearDragOverrides, setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
75
+ const { editorSnapping } = (0, react_1.useContext)(editor_snapping_1.EditorSnappingContext);
73
76
  const transformOriginDrag = (_a = target === null || target === void 0 ? void 0 : target.transformOriginDrag) !== null && _a !== void 0 ? _a : null;
74
77
  const parsed = (0, react_1.useMemo)(() => transformOriginDrag === null
75
78
  ? null
@@ -142,11 +145,13 @@ const SelectedOutlineTransformOriginHandle = ({ outline, onDraggingChange, targe
142
145
  const snapPoint = lockedAxis === null
143
146
  ? point
144
147
  : (0, selected_outline_uv_1.getUvHandlePosition)(outline.points, axisLockedUv);
145
- const snappedUv = (0, selected_outline_drag_1.snapSelectedOutlineTransformOriginUv)({
146
- point: snapPoint,
147
- points: outline.points,
148
- uv: axisLockedUv,
149
- });
148
+ const snappedUv = editorSnapping
149
+ ? (0, selected_outline_drag_1.snapSelectedOutlineTransformOriginUv)({
150
+ point: snapPoint,
151
+ points: outline.points,
152
+ uv: axisLockedUv,
153
+ })
154
+ : axisLockedUv;
150
155
  const nextUv = (0, selected_outline_drag_1.applySelectedOutlineTransformOriginAxisLock)({
151
156
  lockedAxis,
152
157
  startUv: uv,
@@ -293,6 +298,7 @@ const SelectedOutlineTransformOriginHandle = ({ outline, onDraggingChange, targe
293
298
  window.addEventListener('keyup', onKeyChange);
294
299
  }, [
295
300
  clearDragOverrides,
301
+ editorSnapping,
296
302
  onDraggingChange,
297
303
  outline,
298
304
  parsed,
@@ -314,10 +320,11 @@ const SelectedOutlineTransformOriginHandle = ({ outline, onDraggingChange, targe
314
320
  ] }));
315
321
  };
316
322
  exports.SelectedOutlineTransformOriginHandle = SelectedOutlineTransformOriginHandle;
317
- const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, hovered, onContextMenuOpen, outline, onDraggingChange, onHoverChange, onSelect, onTextEditStart, scale, target, }) => {
323
+ const SelectedOutlinePolygon = ({ allDragTargets, allDragOutlines, contextMenuValues, dragging, hovered, onContextMenuOpen, outline, onDraggingChange, onHoverChange, onSnapPointsChange, onSelect, onTextEditStart, scale, snapTargets, target, }) => {
318
324
  var _a, _b, _c, _d;
319
325
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
320
326
  const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
327
+ const { editorSnapping } = (0, react_1.useContext)(editor_snapping_1.EditorSnappingContext);
321
328
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
322
329
  const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
323
330
  timelinePositionRef.current = timelinePosition;
@@ -358,6 +365,7 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
358
365
  let currentPointerY = startPointerY;
359
366
  let axisLocked = false;
360
367
  let dragStarted = false;
368
+ let snappingDisabled = event.metaKey || event.ctrlKey;
361
369
  const updateDragOverrides = () => {
362
370
  const screenDeltaX = currentPointerX - startPointerX;
363
371
  const screenDeltaY = currentPointerY - startPointerY;
@@ -370,16 +378,44 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
370
378
  }
371
379
  dragStarted = true;
372
380
  onDraggingChange(true);
381
+ (0, ForceSpecificCursor_1.forceSpecificCursor)('default');
373
382
  }
383
+ const axisLockedDirection = axisLocked
384
+ ? Math.abs(screenDeltaX) >= Math.abs(screenDeltaY)
385
+ ? 'horizontal'
386
+ : 'vertical'
387
+ : null;
374
388
  const dragDelta = (0, selected_outline_drag_1.applySelectedOutlineDragAxisLock)({
375
389
  deltaX: screenDeltaX / scale,
376
390
  deltaY: screenDeltaY / scale,
377
391
  axisLocked,
378
392
  });
393
+ let { deltaX, deltaY } = dragDelta;
394
+ if (editorSnapping && !snappingDisabled) {
395
+ const snapResult = (0, selected_outline_snap_1.findSelectedOutlineSnap)({
396
+ allowX: axisLockedDirection !== 'vertical',
397
+ allowY: axisLockedDirection !== 'horizontal',
398
+ deltaX,
399
+ deltaY,
400
+ outlines: selected ? allDragOutlines : [outline],
401
+ scale,
402
+ targets: snapTargets,
403
+ });
404
+ if (snapResult.snapOffsetX !== null) {
405
+ deltaX += snapResult.snapOffsetX;
406
+ }
407
+ if (snapResult.snapOffsetY !== null) {
408
+ deltaY += snapResult.snapOffsetY;
409
+ }
410
+ onSnapPointsChange(snapResult.activeSnapPoints);
411
+ }
412
+ else {
413
+ onSnapPointsChange([]);
414
+ }
379
415
  lastValues = (0, selected_outline_drag_1.getSelectedOutlineDragValues)({
380
416
  dragStates,
381
- deltaX: dragDelta.deltaX,
382
- deltaY: dragDelta.deltaY,
417
+ deltaX,
418
+ deltaY,
383
419
  });
384
420
  for (const dragState of dragStates) {
385
421
  const value = lastValues.get(dragState.key);
@@ -403,6 +439,7 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
403
439
  currentPointerX = moveEvent.clientX;
404
440
  currentPointerY = moveEvent.clientY;
405
441
  axisLocked = moveEvent.shiftKey;
442
+ snappingDisabled = moveEvent.metaKey || moveEvent.ctrlKey;
406
443
  updateDragOverrides();
407
444
  };
408
445
  const onKeyChange = (keyEvent) => {
@@ -423,6 +460,7 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
423
460
  window.removeEventListener('keydown', onKeyChange);
424
461
  window.removeEventListener('keyup', onKeyChange);
425
462
  if (dragStarted) {
463
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
426
464
  onDraggingChange(false);
427
465
  }
428
466
  const changes = (0, selected_outline_drag_1.getSelectedOutlineDragChanges)({
@@ -474,15 +512,20 @@ const SelectedOutlinePolygon = ({ allDragTargets, contextMenuValues, dragging, h
474
512
  window.addEventListener('keyup', onKeyChange);
475
513
  }, [
476
514
  allDragTargets,
515
+ allDragOutlines,
477
516
  clearDragOverrides,
478
517
  drag,
518
+ editorSnapping,
479
519
  getDragOverrides,
480
520
  onDraggingChange,
481
521
  onSelect,
522
+ onSnapPointsChange,
523
+ outline,
482
524
  scale,
483
525
  selected,
484
526
  setPropStatuses,
485
527
  setDragOverrides,
528
+ snapTargets,
486
529
  target,
487
530
  ]);
488
531
  const onDoubleClick = react_1.default.useCallback((event) => {
@@ -718,6 +761,7 @@ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMe
718
761
  var _a, _b;
719
762
  const { getDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
720
763
  const { setPropStatuses, setDragOverrides, clearDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
764
+ const { editorSnapping } = (0, react_1.useContext)(editor_snapping_1.EditorSnappingContext);
721
765
  const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
722
766
  const timelinePositionRef = (0, react_1.useRef)(timelinePosition);
723
767
  timelinePositionRef.current = timelinePosition;
@@ -770,7 +814,7 @@ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMe
770
814
  let lastValues = new Map();
771
815
  let dragStarted = false;
772
816
  const updateRotationDragOverrides = () => {
773
- const rotationDeltaDegrees = rotationLocked
817
+ const rotationDeltaDegrees = rotationLocked && editorSnapping
774
818
  ? (0, selected_outline_drag_1.snapSelectedOutlineRotationDeltaDegrees)({
775
819
  dragStates,
776
820
  rotationDeltaDegrees: accumulatedDelta,
@@ -904,6 +948,7 @@ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMe
904
948
  allRotationDragTargets,
905
949
  clearDragOverrides,
906
950
  cornerInfo,
951
+ editorSnapping,
907
952
  getDragOverrides,
908
953
  onDraggingChange,
909
954
  outline.dimensions,
@@ -930,7 +975,7 @@ const SelectedOutlineRotationCornerHandle = ({ allRotationDragTargets, contextMe
930
975
  }, onPointerDown: onPointerDown }), jsx_runtime_1.jsx(ContextMenu_1.ContextMenuForTarget, { triggerRef: circleRef, values: [...contextMenuValues], onOpen: onContextMenuOpen })
931
976
  ] }));
932
977
  };
933
- const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allScaleDragTargets, dragging, hovered, outline, onDraggingChange, onHoverChange, onSelect, scale, target, }) => {
978
+ const SelectedOutlineElement = ({ allDragTargets, allDragOutlines, allRotationDragTargets, allScaleDragTargets, dragging, hovered, outline, onDraggingChange, onHoverChange, onSnapPointsChange, onSelect, scale, snapTargets, target, }) => {
934
979
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
935
980
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
936
981
  const updateResolvedStackTrace = (0, react_1.useContext)(remotion_1.Internals.SequenceStackTracesUpdateContext);
@@ -1114,7 +1159,7 @@ const SelectedOutlineElement = ({ allDragTargets, allRotationDragTargets, allSca
1114
1159
  updateResolvedStackTrace,
1115
1160
  ]);
1116
1161
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
1117
- jsx_runtime_1.jsx(SelectedOutlinePolygon, { allDragTargets: allDragTargets, contextMenuValues: emptyContextMenuValues, dragging: dragging, hovered: hovered, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, onTextEditStart: onTextEditStart, scale: scale, target: target }), (target === null || target === void 0 ? void 0 : target.containsSelection) || hovered
1162
+ jsx_runtime_1.jsx(SelectedOutlinePolygon, { allDragTargets: allDragTargets, allDragOutlines: allDragOutlines, contextMenuValues: emptyContextMenuValues, dragging: dragging, hovered: hovered, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSnapPointsChange: onSnapPointsChange, onSelect: onSelect, onTextEditStart: onTextEditStart, scale: scale, snapTargets: snapTargets, target: target }), (target === null || target === void 0 ? void 0 : target.containsSelection) || hovered
1118
1163
  ? ['top', 'right', 'bottom', 'left'].map((edge) => (jsx_runtime_1.jsx(SelectedOutlineScaleEdgeLine, { allScaleDragTargets: allScaleDragTargets, contextMenuValues: emptyContextMenuValues, dragging: dragging, edge: edge, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, target: target }, edge)))
1119
1164
  : null, (target === null || target === void 0 ? void 0 : target.containsSelection) || hovered
1120
1165
  ? ['top-left', 'top-right', 'bottom-right', 'bottom-left'].map((corner) => (jsx_runtime_1.jsx(SelectedOutlineRotationCornerHandle, { allRotationDragTargets: allRotationDragTargets, contextMenuValues: emptyContextMenuValues, corner: corner, dragging: dragging, outline: outline, onContextMenuOpen: onContextMenuOpen, onDraggingChange: onDraggingChange, onHoverChange: onHoverChange, onSelect: onSelect, target: target }, corner)))
@@ -10,6 +10,8 @@ export declare const orderOutlinesForRendering: ({ outlines, targetsByKey, }: {
10
10
  readonly targetsByKey: ReadonlyMap<string, SelectedOutlineTarget>;
11
11
  }) => readonly SelectedOutline[];
12
12
  export declare const SelectedOutlineOverlay: React.FC<{
13
+ readonly compositionHeight: number;
14
+ readonly compositionWidth: number;
13
15
  readonly scale: number;
14
16
  readonly translationX: number;
15
17
  readonly translationY: number;