@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
@@ -40,6 +40,7 @@ const remotion_1 = require("remotion");
40
40
  const client_id_1 = require("../../helpers/client-id");
41
41
  const colors_1 = require("../../helpers/colors");
42
42
  const format_file_location_1 = require("../../helpers/format-file-location");
43
+ const interactivity_enabled_1 = require("../../helpers/interactivity-enabled");
43
44
  const timeline_layout_1 = require("../../helpers/timeline-layout");
44
45
  const use_keybinding_1 = require("../../helpers/use-keybinding");
45
46
  const modals_1 = require("../../state/modals");
@@ -158,6 +159,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
158
159
  const nodePath = (_d = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _d !== void 0 ? _d : null;
159
160
  const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
160
161
  const previewConnected = previewServerState.type === 'connected';
162
+ const previewInteractive = previewConnected && interactivity_enabled_1.studioInteractivityEnabled;
161
163
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
162
164
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
163
165
  const { setPropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
@@ -191,7 +193,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
191
193
  };
192
194
  }, [originalLocation]);
193
195
  const { canRename: canRenameThisSequence, displayName, fallbackDisplayName, propStatusesForOverride, saveName, } = (0, use_rename_sequence_1.useRenameSequence)({
194
- clientId: previewServerState.type === 'connected'
196
+ clientId: previewInteractive && previewServerState.type === 'connected'
195
197
  ? previewServerState.clientId
196
198
  : null,
197
199
  nodePathInfo,
@@ -201,25 +203,25 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
201
203
  const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
202
204
  const nodePathKey = (0, react_1.useMemo)(() => nodePath ? remotion_1.Internals.makeSequencePropsSubscriptionKey(nodePath) : null, [nodePath]);
203
205
  const parentId = (_e = sequence.parent) !== null && _e !== void 0 ? _e : null;
204
- const canReorderSequence = previewConnected &&
206
+ const canReorderSequence = previewInteractive &&
205
207
  Boolean(nodePath && nodePathKey && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source)) &&
206
208
  (nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.numberOfSequencesWithThisNodePath) === 1;
207
- const canHandleSequenceDrag = previewConnected;
209
+ const canHandleSequenceDrag = previewInteractive;
208
210
  const confirm = (0, ConfirmationDialog_1.useConfirmationDialog)();
209
- const deleteDisabled = (0, react_1.useMemo)(() => !previewConnected || !sequence.controls || !canDeleteFromSource, [previewConnected, sequence.controls, canDeleteFromSource]);
211
+ const deleteDisabled = (0, react_1.useMemo)(() => !previewInteractive || !sequence.controls || !canDeleteFromSource, [previewInteractive, sequence.controls, canDeleteFromSource]);
210
212
  const duplicateDisabled = deleteDisabled;
211
- const disableInteractivityDisabled = !previewConnected ||
213
+ const disableInteractivityDisabled = !previewInteractive ||
212
214
  !sequence.showInTimeline ||
213
215
  !nodePath ||
214
216
  !(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source);
215
217
  const onDuplicateSequenceFromSource = (0, react_1.useCallback)(() => {
216
- if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePathInfo) {
218
+ if (duplicateDisabled || !(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePathInfo) {
217
219
  return;
218
220
  }
219
221
  (0, duplicate_selected_timeline_item_1.duplicateSequencesFromSource)([nodePathInfo], confirm).catch(() => undefined);
220
- }, [confirm, nodePathInfo, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source]);
222
+ }, [confirm, duplicateDisabled, nodePathInfo, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source]);
221
223
  const onDeleteSequenceFromSource = (0, react_1.useCallback)(async () => {
222
- if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath) {
224
+ if (deleteDisabled || !(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath) {
223
225
  return;
224
226
  }
225
227
  if (nodePathInfo && nodePathInfo.numberOfSequencesWithThisNodePath > 1) {
@@ -253,7 +255,13 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
253
255
  catch (err) {
254
256
  (0, NotificationCenter_1.showNotification)(err.message, 4000);
255
257
  }
256
- }, [confirm, nodePath, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source, nodePathInfo]);
258
+ }, [
259
+ confirm,
260
+ deleteDisabled,
261
+ nodePath,
262
+ validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source,
263
+ nodePathInfo,
264
+ ]);
257
265
  const onDisableSequenceInteractivity = (0, react_1.useCallback)(() => {
258
266
  if (disableInteractivityDisabled ||
259
267
  !nodePath ||
@@ -517,8 +525,9 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
517
525
  }
518
526
  : inner;
519
527
  }, [effectDropHovered, inner]);
520
- const hasExpandableContent = Boolean(sequence.controls) || sequence.effects.length > 0;
521
- const canToggleVisibility = previewConnected &&
528
+ const hasExpandableContent = interactivity_enabled_1.studioInteractivityEnabled &&
529
+ (Boolean(sequence.controls) || sequence.effects.length > 0);
530
+ const canToggleVisibility = previewInteractive &&
522
531
  Boolean(sequence.controls) &&
523
532
  nodePath !== null &&
524
533
  validatedLocation !== null &&
@@ -583,7 +592,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
583
592
  setIsRenaming(true);
584
593
  }, [canRenameThisSequence]);
585
594
  const freezeFrameMenuItem = (0, use_sequence_freeze_frame_menu_item_1.useSequenceFreezeFrameMenuItem)({
586
- clientId: previewServerState.type === 'connected'
595
+ clientId: previewInteractive && previewServerState.type === 'connected'
587
596
  ? previewServerState.clientId
588
597
  : null,
589
598
  nodePath,
@@ -595,7 +604,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
595
604
  validatedSource: (_f = validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) !== null && _f !== void 0 ? _f : null,
596
605
  });
597
606
  const canAddEffect = (nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects) === true &&
598
- previewServerState.type === 'connected' &&
607
+ previewInteractive &&
599
608
  Boolean(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source);
600
609
  const onAddEffect = (0, react_1.useCallback)(() => {
601
610
  if (!canAddEffect ||
@@ -628,7 +637,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
628
637
  disableInteractivityDisabled,
629
638
  duplicateDisabled,
630
639
  fileLocation,
631
- includeSourceEditItems: true,
640
+ includeSourceEditItems: interactivity_enabled_1.studioInteractivityEnabled,
632
641
  onDeleteSequenceFromSource,
633
642
  onDisableSequenceInteractivity,
634
643
  onDuplicateSequenceFromSource,
@@ -636,43 +645,45 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
636
645
  originalLocation,
637
646
  selectAsset,
638
647
  sequence,
639
- sourceActions: [
640
- ...((nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects)
641
- ? [
642
- {
643
- type: 'item',
644
- id: 'add-effect',
645
- keyHint: null,
646
- label: 'Add effect...',
647
- leftItem: null,
648
- disabled: !canAddEffect,
649
- onClick: onAddEffect,
650
- quickSwitcherLabel: null,
651
- subMenu: null,
652
- value: 'add-effect',
653
- },
654
- {
655
- type: 'divider',
656
- id: 'add-effect-divider',
648
+ sourceActions: interactivity_enabled_1.studioInteractivityEnabled
649
+ ? [
650
+ ...((nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.supportsEffects)
651
+ ? [
652
+ {
653
+ type: 'item',
654
+ id: 'add-effect',
655
+ keyHint: null,
656
+ label: 'Add effect...',
657
+ leftItem: null,
658
+ disabled: !canAddEffect,
659
+ onClick: onAddEffect,
660
+ quickSwitcherLabel: null,
661
+ subMenu: null,
662
+ value: 'add-effect',
663
+ },
664
+ {
665
+ type: 'divider',
666
+ id: 'add-effect-divider',
667
+ },
668
+ ]
669
+ : []),
670
+ {
671
+ type: 'item',
672
+ id: 'rename-sequence',
673
+ keyHint: null,
674
+ label: 'Rename...',
675
+ leftItem: null,
676
+ disabled: !canRenameThisSequence,
677
+ onClick: () => {
678
+ onRenameSequence();
657
679
  },
658
- ]
659
- : []),
660
- {
661
- type: 'item',
662
- id: 'rename-sequence',
663
- keyHint: null,
664
- label: 'Rename...',
665
- leftItem: null,
666
- disabled: !canRenameThisSequence,
667
- onClick: () => {
668
- onRenameSequence();
680
+ quickSwitcherLabel: null,
681
+ subMenu: null,
682
+ value: 'rename-sequence',
669
683
  },
670
- quickSwitcherLabel: null,
671
- subMenu: null,
672
- value: 'rename-sequence',
673
- },
674
- ...(freezeFrameMenuItem ? [freezeFrameMenuItem] : []),
675
- ],
684
+ ...(freezeFrameMenuItem ? [freezeFrameMenuItem] : []),
685
+ ]
686
+ : [],
676
687
  });
677
688
  }, [
678
689
  assetLinkInfo,
@@ -696,7 +707,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
696
707
  selectAsset,
697
708
  sequence,
698
709
  ]);
699
- const canDropEffect = previewServerState.type === 'connected' &&
710
+ const canDropEffect = previewInteractive &&
700
711
  nodePath !== null &&
701
712
  validatedLocation !== null &&
702
713
  ((_c = sequence.controls) === null || _c === void 0 ? void 0 : _c.supportsEffects) === true;
@@ -754,7 +765,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
754
765
  clientId: previewServerState.clientId,
755
766
  });
756
767
  }, [canDropEffect, nodePath, previewServerState, validatedLocation]);
757
- const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewConnected, isExpanded: isExpanded, nodePathInfo: nodePathInfo, onToggleExpand: onToggleExpand, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, selectionItem: selectionItem, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canRenameThisSequence || canOpenInEditor
768
+ const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent && nodePathInfo !== null ? (jsx_runtime_1.jsx(TimelineSequenceExpandArrow, { disabled: !previewInteractive, isExpanded: isExpanded, nodePathInfo: nodePathInfo, onToggleExpand: onToggleExpand, sequence: sequence })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: rowStyle, selected: selected, selectable: selectable, selectionItem: selectionItem, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDragLeave: canDropEffect ? onEffectDragLeave : undefined, onDragOver: canDropEffect ? onEffectDragOver : undefined, onDrop: canDropEffect ? onEffectDrop : undefined, onDoubleClick: canRenameThisSequence || canOpenInEditor
758
769
  ? onSequenceDoubleClick
759
770
  : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
760
771
  jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { displayName: displayName, fallbackDisplayName: fallbackDisplayName, selected: selected, containsSelection: containsSelection, editing: isRenaming, onCancelEditing: onCancelRenaming, onSaveName: onSaveName }), mediaSrc ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
@@ -764,6 +775,7 @@ const TimelineSequenceItem = ({ nestedDepth, sequence, nodePathInfo, keyframeDis
764
775
  ] })) : null] }) }));
765
776
  const draggableTrackRow = canHandleSequenceDrag ? (jsx_runtime_1.jsxs("div", { draggable: canReorderSequence, onDragStart: onSequenceDragStart, onDragEnd: onSequenceDragEnd, onDragOver: onSequenceDragOver, onDragLeave: onSequenceDragLeave, onDrop: onSequenceDrop, style: sequenceReorderWrapper, children: [sequenceReorderLineStyle ? (jsx_runtime_1.jsx("div", { style: sequenceReorderLineStyle })) : null, sequenceDropRejection ? (jsx_runtime_1.jsx("div", { style: sequenceReorderRejectionStyle, children: sequenceDropRejection })) : null, trackRow] })) : (trackRow);
766
777
  return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selectable ? onSelect : null, children: draggableTrackRow })) : (draggableTrackRow), previewConnected &&
778
+ interactivity_enabled_1.studioInteractivityEnabled &&
767
779
  isExpanded &&
768
780
  hasExpandableContent &&
769
781
  nodePathInfo &&
@@ -8,8 +8,8 @@ const open_in_editor_1 = require("../../helpers/open-in-editor");
8
8
  const Fieldset_1 = require("../RenderModal/SchemaEditor/Fieldset");
9
9
  const source_attribution_1 = require("../Timeline/TimelineStack/source-attribution");
10
10
  const container = {
11
- paddingLeft: Fieldset_1.SCHEMA_EDITOR_FIELDSET_PADDING,
12
- paddingTop: Fieldset_1.SCHEMA_EDITOR_FIELDSET_PADDING / 2,
11
+ paddingLeft: (0, Fieldset_1.getSchemaEditorFieldsetPadding)(),
12
+ paddingTop: (0, Fieldset_1.getSchemaEditorFieldsetPadding)() / 2,
13
13
  };
14
14
  const ClickableFileName = ({ originalFileName, }) => {
15
15
  const [titleHovered, setTitleHovered] = (0, react_1.useState)(false);
@@ -37,15 +37,23 @@ exports.VisualControlsContent = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
39
  const VisualControls_1 = require("../../visual-controls/VisualControls");
40
+ const InspectorPanelLayout_1 = require("../InspectorPanelLayout");
41
+ const Fieldset_1 = require("../RenderModal/SchemaEditor/Fieldset");
40
42
  const SchemaSeparationLine_1 = require("../RenderModal/SchemaEditor/SchemaSeparationLine");
41
43
  const VisualControlHandle_1 = require("./VisualControlHandle");
44
+ const rootInset = (0, Fieldset_1.getSchemaEditorRootInset)(InspectorPanelLayout_1.INSPECTOR_PANEL_HORIZONTAL_PADDING);
45
+ const container = {
46
+ boxSizing: 'border-box',
47
+ paddingLeft: rootInset,
48
+ paddingRight: rootInset,
49
+ };
42
50
  const VisualControlsContent = () => {
43
51
  const { handles } = (0, react_1.useContext)(VisualControls_1.VisualControlsContext);
44
52
  const entries = Object.entries(handles);
45
53
  if (entries.length === 0) {
46
54
  return null;
47
55
  }
48
- return (jsx_runtime_1.jsx("div", { children: entries.map(([key, value], i) => {
56
+ return (jsx_runtime_1.jsx("div", { style: container, children: entries.map(([key, value], i) => {
49
57
  return (jsx_runtime_1.jsxs(react_1.default.Fragment, { children: [
50
58
  jsx_runtime_1.jsx(VisualControlHandle_1.VisualControlHandle, { keyName: key, value: value }), i === entries.length - 1 ? null : jsx_runtime_1.jsx(SchemaSeparationLine_1.SchemaSeparationLine, {})] }, key));
51
59
  }) }));
@@ -8,7 +8,9 @@ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
8
8
  const hasEffectDragType = (dataTransfer) => {
9
9
  const types = Array.from(dataTransfer.types);
10
10
  const hasExplicitEffectType = types.includes(studio_shared_1.EFFECT_DRAG_MIME_TYPE);
11
- if (!hasExplicitEffectType && hasImportableAssetDragType(dataTransfer)) {
11
+ if (!hasExplicitEffectType &&
12
+ (hasNonEffectRemotionDragType(dataTransfer) ||
13
+ hasNonRemotionImportableAssetDragType(dataTransfer))) {
12
14
  return false;
13
15
  }
14
16
  return types.some((type) => type === studio_shared_1.EFFECT_DRAG_MIME_TYPE || isGenericDragType(type));
@@ -21,14 +23,33 @@ exports.hasExplicitEffectDragType = hasExplicitEffectDragType;
21
23
  const isGenericDragType = (type) => {
22
24
  return type === 'application/json' || type === 'text/plain';
23
25
  };
24
- const hasImportableAssetDragType = (dataTransfer) => {
25
- return Array.from(dataTransfer.types).some((type) => type === 'Files' ||
26
- type === studio_shared_1.ASSET_DRAG_MIME_TYPE ||
27
- type === studio_shared_1.COMPOSITION_DRAG_MIME_TYPE ||
28
- type === studio_shared_1.COMPONENT_DRAG_MIME_TYPE ||
29
- type === studio_shared_1.SFX_DRAG_MIME_TYPE ||
30
- type === 'text/uri-list' ||
31
- type === 'text/html');
26
+ const isNonEffectRemotionDragType = (mimeType) => {
27
+ switch (mimeType) {
28
+ case studio_shared_1.EFFECT_DRAG_MIME_TYPE:
29
+ return false;
30
+ case studio_shared_1.ASSET_DRAG_MIME_TYPE:
31
+ case studio_shared_1.COMPOSITION_DRAG_MIME_TYPE:
32
+ case studio_shared_1.COMPONENT_DRAG_MIME_TYPE:
33
+ case studio_shared_1.ELEMENT_DRAG_MIME_TYPE:
34
+ case studio_shared_1.SFX_DRAG_MIME_TYPE:
35
+ return true;
36
+ default:
37
+ mimeType;
38
+ throw new Error(`Unhandled Remotion drag MIME type: ${mimeType}`);
39
+ }
40
+ };
41
+ const hasNonEffectRemotionDragType = (dataTransfer) => {
42
+ return Array.from(dataTransfer.types).some((type) => {
43
+ if (!(0, studio_shared_1.isRemotionDragMimeType)(type)) {
44
+ return false;
45
+ }
46
+ return isNonEffectRemotionDragType(type);
47
+ });
48
+ };
49
+ const hasNonRemotionImportableAssetDragType = (dataTransfer) => {
50
+ return Array.from(dataTransfer.types).some((type) => {
51
+ return type === 'Files' || type === 'text/uri-list' || type === 'text/html';
52
+ });
32
53
  };
33
54
  const getEffectDragData = (dataTransfer) => {
34
55
  for (const type of [
@@ -86,6 +86,6 @@ export declare const insertElement: ({ compositionFile, compositionId, dropPosit
86
86
  slug: string;
87
87
  displayName: string;
88
88
  sourceCode: string;
89
- dimensions: import("@remotion/studio-shared").ComponentDimensions;
89
+ dimensions: import("@remotion/studio-shared").ComponentDimensions | null;
90
90
  };
91
91
  }) => Promise<void>;
@@ -2,3 +2,4 @@ export declare const optionsSidebarTabs: import("react").RefObject<{
2
2
  selectInspectorPanel: () => void;
3
3
  selectRendersPanel: () => void;
4
4
  } | null>;
5
+ export declare const selectOptionsSidebarInspectorPanel: () => void;
@@ -1,5 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.optionsSidebarTabs = void 0;
3
+ exports.selectOptionsSidebarInspectorPanel = exports.optionsSidebarTabs = void 0;
4
4
  const react_1 = require("react");
5
5
  exports.optionsSidebarTabs = (0, react_1.createRef)();
6
+ const selectOptionsSidebarInspectorPanel = () => {
7
+ var _a;
8
+ (_a = exports.optionsSidebarTabs.current) === null || _a === void 0 ? void 0 : _a.selectInspectorPanel();
9
+ };
10
+ exports.selectOptionsSidebarInspectorPanel = selectOptionsSidebarInspectorPanel;
@@ -0,0 +1,36 @@
1
+ import type { Guide } from '../state/editor-guides';
2
+ import type { SelectedOutline } from './selected-outline-geometry';
3
+ export declare const selectedOutlineSnapThresholdPx = 10;
4
+ export declare const selectedOutlineSnapIndicatorColor = "#ff00ff";
5
+ export type SelectedOutlineSnapAxis = 'x' | 'y';
6
+ export type SelectedOutlineSnapTargetType = 'canvas-left' | 'canvas-right' | 'canvas-top' | 'canvas-bottom' | 'canvas-horizontal-center' | 'canvas-vertical-center' | 'guide-vertical' | 'guide-horizontal';
7
+ export type SelectedOutlineSnapTarget = {
8
+ readonly axis: SelectedOutlineSnapAxis;
9
+ readonly position: number;
10
+ readonly type: SelectedOutlineSnapTargetType;
11
+ };
12
+ export type SelectedOutlineSnapEdge = 'left' | 'right' | 'center-x' | 'top' | 'bottom' | 'center-y';
13
+ export type SelectedOutlineSnapPoint = {
14
+ readonly distance: number;
15
+ readonly edge: SelectedOutlineSnapEdge;
16
+ readonly target: SelectedOutlineSnapTarget;
17
+ };
18
+ export type SelectedOutlineSnapResult = {
19
+ readonly activeSnapPoints: readonly SelectedOutlineSnapPoint[];
20
+ readonly snapOffsetX: number | null;
21
+ readonly snapOffsetY: number | null;
22
+ };
23
+ export declare const getSelectedOutlineSnapTargets: ({ compositionHeight, compositionWidth, guides, }: {
24
+ readonly compositionHeight: number;
25
+ readonly compositionWidth: number;
26
+ readonly guides: readonly Guide[];
27
+ }) => readonly SelectedOutlineSnapTarget[];
28
+ export declare const findSelectedOutlineSnap: ({ allowX, allowY, deltaX, deltaY, outlines, scale, targets, }: {
29
+ readonly allowX: boolean;
30
+ readonly allowY: boolean;
31
+ readonly deltaX: number;
32
+ readonly deltaY: number;
33
+ readonly outlines: readonly SelectedOutline[];
34
+ readonly scale: number;
35
+ readonly targets: readonly SelectedOutlineSnapTarget[];
36
+ }) => SelectedOutlineSnapResult;
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.findSelectedOutlineSnap = exports.getSelectedOutlineSnapTargets = exports.selectedOutlineSnapIndicatorColor = exports.selectedOutlineSnapThresholdPx = void 0;
4
+ exports.selectedOutlineSnapThresholdPx = 10;
5
+ exports.selectedOutlineSnapIndicatorColor = '#ff00ff';
6
+ const EPSILON = 0.000001;
7
+ const getSelectedOutlineSnapTargets = ({ compositionHeight, compositionWidth, guides, }) => {
8
+ return [
9
+ { axis: 'x', position: 0, type: 'canvas-left' },
10
+ {
11
+ axis: 'x',
12
+ position: compositionWidth / 2,
13
+ type: 'canvas-horizontal-center',
14
+ },
15
+ { axis: 'x', position: compositionWidth, type: 'canvas-right' },
16
+ { axis: 'y', position: 0, type: 'canvas-top' },
17
+ {
18
+ axis: 'y',
19
+ position: compositionHeight / 2,
20
+ type: 'canvas-vertical-center',
21
+ },
22
+ { axis: 'y', position: compositionHeight, type: 'canvas-bottom' },
23
+ ...guides.flatMap((guide) => {
24
+ if (!guide.show) {
25
+ return [];
26
+ }
27
+ return [
28
+ guide.orientation === 'vertical'
29
+ ? {
30
+ axis: 'x',
31
+ position: guide.position,
32
+ type: 'guide-vertical',
33
+ }
34
+ : {
35
+ axis: 'y',
36
+ position: guide.position,
37
+ type: 'guide-horizontal',
38
+ },
39
+ ];
40
+ }),
41
+ ];
42
+ };
43
+ exports.getSelectedOutlineSnapTargets = getSelectedOutlineSnapTargets;
44
+ const getSelectedOutlineBounds = ({ deltaX, deltaY, outlines, scale, }) => {
45
+ if (outlines.length === 0) {
46
+ return null;
47
+ }
48
+ const points = outlines.flatMap((outline) => outline.points);
49
+ const left = Math.min(...points.map((point) => point.x)) / scale + deltaX;
50
+ const right = Math.max(...points.map((point) => point.x)) / scale + deltaX;
51
+ const top = Math.min(...points.map((point) => point.y)) / scale + deltaY;
52
+ const bottom = Math.max(...points.map((point) => point.y)) / scale + deltaY;
53
+ return {
54
+ left,
55
+ right,
56
+ top,
57
+ bottom,
58
+ centerX: left + (right - left) / 2,
59
+ centerY: top + (bottom - top) / 2,
60
+ };
61
+ };
62
+ const canSnapEdgeToTarget = (edge, target) => {
63
+ if (target.type === 'canvas-horizontal-center') {
64
+ return edge === 'center-x';
65
+ }
66
+ if (target.type === 'canvas-vertical-center') {
67
+ return edge === 'center-y';
68
+ }
69
+ if (target.type === 'canvas-left' || target.type === 'canvas-right') {
70
+ return edge === 'left' || edge === 'right';
71
+ }
72
+ if (target.type === 'guide-vertical') {
73
+ return edge === 'left' || edge === 'right' || edge === 'center-x';
74
+ }
75
+ if (target.type === 'canvas-top' || target.type === 'canvas-bottom') {
76
+ return edge === 'top' || edge === 'bottom';
77
+ }
78
+ return edge === 'top' || edge === 'bottom' || edge === 'center-y';
79
+ };
80
+ const findBestSnapForAxis = ({ edges, targets, threshold, }) => {
81
+ var _a;
82
+ let bestDistance = Infinity;
83
+ let bestSnaps = [];
84
+ for (const target of targets) {
85
+ for (const edge of edges) {
86
+ if (!canSnapEdgeToTarget(edge.edge, target)) {
87
+ continue;
88
+ }
89
+ const distance = Math.abs(edge.position - target.position);
90
+ if (distance > threshold || distance > bestDistance + EPSILON) {
91
+ continue;
92
+ }
93
+ if (distance < bestDistance - EPSILON) {
94
+ bestSnaps = [];
95
+ bestDistance = distance;
96
+ }
97
+ bestSnaps.push({
98
+ offset: target.position - edge.position,
99
+ snapPoint: {
100
+ distance,
101
+ edge: edge.edge,
102
+ target,
103
+ },
104
+ });
105
+ }
106
+ }
107
+ if (bestSnaps.length > 1) {
108
+ const centerSnap = bestSnaps.find((snap) => snap.snapPoint.target.type === 'canvas-horizontal-center' ||
109
+ snap.snapPoint.target.type === 'canvas-vertical-center');
110
+ if (centerSnap) {
111
+ return centerSnap;
112
+ }
113
+ }
114
+ return (_a = bestSnaps[0]) !== null && _a !== void 0 ? _a : null;
115
+ };
116
+ const findSelectedOutlineSnap = ({ allowX, allowY, deltaX, deltaY, outlines, scale, targets, }) => {
117
+ var _a, _b, _c, _d;
118
+ const bounds = getSelectedOutlineBounds({ deltaX, deltaY, outlines, scale });
119
+ if (bounds === null) {
120
+ return {
121
+ activeSnapPoints: [],
122
+ snapOffsetX: null,
123
+ snapOffsetY: null,
124
+ };
125
+ }
126
+ const threshold = exports.selectedOutlineSnapThresholdPx / scale;
127
+ const snapX = allowX
128
+ ? findBestSnapForAxis({
129
+ edges: [
130
+ { edge: 'left', position: bounds.left },
131
+ { edge: 'center-x', position: bounds.centerX },
132
+ { edge: 'right', position: bounds.right },
133
+ ],
134
+ targets: targets.filter((target) => target.axis === 'x'),
135
+ threshold,
136
+ })
137
+ : null;
138
+ const snapY = allowY
139
+ ? findBestSnapForAxis({
140
+ edges: [
141
+ { edge: 'top', position: bounds.top },
142
+ { edge: 'center-y', position: bounds.centerY },
143
+ { edge: 'bottom', position: bounds.bottom },
144
+ ],
145
+ targets: targets.filter((target) => target.axis === 'y'),
146
+ threshold,
147
+ })
148
+ : null;
149
+ return {
150
+ activeSnapPoints: [
151
+ (_a = snapX === null || snapX === void 0 ? void 0 : snapX.snapPoint) !== null && _a !== void 0 ? _a : null,
152
+ (_b = snapY === null || snapY === void 0 ? void 0 : snapY.snapPoint) !== null && _b !== void 0 ? _b : null,
153
+ ].filter((snapPoint) => snapPoint !== null),
154
+ snapOffsetX: (_c = snapX === null || snapX === void 0 ? void 0 : snapX.offset) !== null && _c !== void 0 ? _c : null,
155
+ snapOffsetY: (_d = snapY === null || snapY === void 0 ? void 0 : snapY.offset) !== null && _d !== void 0 ? _d : null,
156
+ };
157
+ };
158
+ exports.findSelectedOutlineSnap = findSelectedOutlineSnap;