@remotion/studio 4.0.506 → 4.0.507

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 (119) hide show
  1. package/dist/api/copy-render-output-to-asset.d.ts +4 -0
  2. package/dist/api/copy-render-output-to-asset.js +11 -0
  3. package/dist/components/AssetSelector.js +19 -4
  4. package/dist/components/AssetSelectorItem.js +2 -2
  5. package/dist/components/CodingAgentIcon.d.ts +4 -0
  6. package/dist/components/CodingAgentIcon.js +17 -0
  7. package/dist/components/ConfigureDefaultEditorModal.d.ts +1 -3
  8. package/dist/components/ConfigureDefaultEditorModal.js +67 -77
  9. package/dist/components/ConfigureLicenseModal.d.ts +1 -4
  10. package/dist/components/ConfigureLicenseModal.js +89 -81
  11. package/dist/components/ContextMenu.js +10 -8
  12. package/dist/components/EditorContexts.js +6 -5
  13. package/dist/components/ExpandedTracksProvider.js +10 -53
  14. package/dist/components/InspectorLocationCopy.js +8 -8
  15. package/dist/components/InspectorOpenInEditor.d.ts +1 -0
  16. package/dist/components/InspectorOpenInEditor.js +39 -49
  17. package/dist/components/InspectorPanel/SequenceInspectorHeader.d.ts +3 -0
  18. package/dist/components/InspectorPanel/SequenceInspectorHeader.js +22 -4
  19. package/dist/components/InspectorPanel/SequenceSelectionInspector.js +1 -1
  20. package/dist/components/Menu/MenuSectionHeader.d.ts +4 -0
  21. package/dist/components/Menu/MenuSectionHeader.js +20 -0
  22. package/dist/components/Menu/SubMenu.js +13 -2
  23. package/dist/components/Menu/menu-tree-context.d.ts +3 -0
  24. package/dist/components/Menu/menu-tree-context.js +13 -0
  25. package/dist/components/NewComposition/ComboBox.d.ts +6 -1
  26. package/dist/components/NewComposition/MenuContent.js +27 -19
  27. package/dist/components/NewComposition/menu-typeahead.js +2 -2
  28. package/dist/components/Preview.js +29 -4
  29. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.d.ts +1 -0
  30. package/dist/components/RenderModal/SchemaEditor/ZodEnumEditor.js +2 -2
  31. package/dist/components/RenderModal/SchemaEditor/ZodOrNullishEditor.js +3 -3
  32. package/dist/components/RenderModal/SchemaEditor/ZodSwitch.js +1 -1
  33. package/dist/components/RenderModal/ServerRenderModal.js +4 -0
  34. package/dist/components/RenderQueue/RenderQueueItem.js +8 -2
  35. package/dist/components/RenderQueue/actions.d.ts +4 -2
  36. package/dist/components/RenderQueue/actions.js +4 -2
  37. package/dist/components/RenderQueue/index.js +3 -4
  38. package/dist/components/RenderQueue/use-render-output-file-drag.d.ts +8 -0
  39. package/dist/components/RenderQueue/use-render-output-file-drag.js +121 -0
  40. package/dist/components/SegmentedControl.js +0 -1
  41. package/dist/components/SelectedOutlineElement.d.ts +14 -17
  42. package/dist/components/SelectedOutlineElement.js +112 -930
  43. package/dist/components/SelectedOutlineKeyboardControls.d.ts +7 -0
  44. package/dist/components/SelectedOutlineKeyboardControls.js +261 -0
  45. package/dist/components/SelectedOutlineOverlay.d.ts +6 -13
  46. package/dist/components/SelectedOutlineOverlay.js +349 -864
  47. package/dist/components/SelectedOutlinePolygon.d.ts +25 -0
  48. package/dist/components/SelectedOutlinePolygon.js +359 -0
  49. package/dist/components/SelectedOutlineRenderer.d.ts +18 -0
  50. package/dist/components/SelectedOutlineRenderer.js +208 -0
  51. package/dist/components/SelectedOutlineRotationCornerHandle.d.ts +16 -0
  52. package/dist/components/SelectedOutlineRotationCornerHandle.js +269 -0
  53. package/dist/components/SelectedOutlineScaleEdgeLine.d.ts +16 -0
  54. package/dist/components/SelectedOutlineScaleEdgeLine.js +211 -0
  55. package/dist/components/SelectedOutlineSnapIndicators.d.ts +9 -0
  56. package/dist/components/SelectedOutlineSnapIndicators.js +29 -0
  57. package/dist/components/SelectedOutlineTransformOriginHandle.d.ts +9 -0
  58. package/dist/components/SelectedOutlineTransformOriginHandle.js +286 -0
  59. package/dist/components/SelectedOutlineUvControls.d.ts +3 -9
  60. package/dist/components/SelectedOutlineUvControls.js +57 -12
  61. package/dist/components/SettingsContext.d.ts +15 -0
  62. package/dist/components/SettingsContext.js +116 -0
  63. package/dist/components/SettingsModal.js +10 -4
  64. package/dist/components/SettingsModalFooter.d.ts +1 -3
  65. package/dist/components/SettingsModalFooter.js +4 -6
  66. package/dist/components/ShowOutlinesProvider.js +2 -3
  67. package/dist/components/Timeline/EasingEditorModal.js +66 -22
  68. package/dist/components/Timeline/Timeline.js +22 -5
  69. package/dist/components/Timeline/TimelineDuplicateCount.d.ts +4 -0
  70. package/dist/components/Timeline/TimelineDuplicateCount.js +28 -0
  71. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +3 -23
  72. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.d.ts +4 -2
  73. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +11 -1
  74. package/dist/components/Timeline/TimelineSequence.js +28 -25
  75. package/dist/components/Timeline/TimelineSequenceItem.js +49 -27
  76. package/dist/components/Timeline/TimelineTrack.js +2 -1
  77. package/dist/components/Timeline/get-sequence-context-menu-items.d.ts +6 -3
  78. package/dist/components/Timeline/get-sequence-context-menu-items.js +58 -53
  79. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +36 -4
  80. package/dist/components/Timeline/{use-open-sequence-in-editor.d.ts → use-open-sequence-in-apps.d.ts} +4 -1
  81. package/dist/components/Timeline/{use-open-sequence-in-editor.js → use-open-sequence-in-apps.js} +20 -4
  82. package/dist/components/Timeline/use-timeline-expanded-tree.d.ts +4 -0
  83. package/dist/components/Timeline/use-timeline-expanded-tree.js +45 -1
  84. package/dist/components/get-open-in-menu-items.d.ts +12 -0
  85. package/dist/components/get-open-in-menu-items.js +83 -0
  86. package/dist/components/selected-outline-measurement.d.ts +2 -2
  87. package/dist/components/selected-outline-order.d.ts +12 -0
  88. package/dist/components/selected-outline-order.js +251 -0
  89. package/dist/components/selected-outline-types.d.ts +9 -10
  90. package/dist/components/svg-point-to-client-point.d.ts +2 -0
  91. package/dist/components/svg-point-to-client-point.js +10 -0
  92. package/dist/components/use-auto-save-config.d.ts +8 -0
  93. package/dist/components/use-auto-save-config.js +74 -0
  94. package/dist/components/use-default-editor-info.d.ts +1 -0
  95. package/dist/components/use-default-editor-info.js +10 -30
  96. package/dist/esm/{chunk-jefhcs5z.js → chunk-fgedsvhb.js} +1 -2
  97. package/dist/esm/{chunk-b49ec3nz.js → chunk-ptnd65a9.js} +10602 -9364
  98. package/dist/esm/internals.mjs +10601 -9363
  99. package/dist/esm/previewEntry.mjs +10462 -9224
  100. package/dist/esm/renderEntry.mjs +2 -2
  101. package/dist/helpers/are-sequence-node-path-infos-equal.d.ts +2 -0
  102. package/dist/helpers/are-sequence-node-path-infos-equal.js +27 -0
  103. package/dist/helpers/calculate-timeline.js +3 -3
  104. package/dist/helpers/client-id.js +8 -1
  105. package/dist/helpers/format-file-location.d.ts +1 -1
  106. package/dist/helpers/format-file-location.js +3 -3
  107. package/dist/helpers/migrate-expanded-tracks-for-subscription-key.js +3 -3
  108. package/dist/helpers/open-in-editor.d.ts +1 -0
  109. package/dist/helpers/open-in-editor.js +5 -1
  110. package/dist/helpers/studio-runtime-config.js +3 -0
  111. package/dist/helpers/timeline-node-path-key.d.ts +2 -0
  112. package/dist/helpers/timeline-node-path-key.js +3 -1
  113. package/dist/helpers/use-asset-drag-events.d.ts +2 -1
  114. package/dist/helpers/use-asset-drag-events.js +14 -6
  115. package/dist/helpers/use-menu-structure.js +2 -2
  116. package/dist/helpers/use-runtime-values.d.ts +1 -3
  117. package/dist/state/timeline-sequence-hover.d.ts +9 -3
  118. package/dist/state/timeline-sequence-hover.js +63 -12
  119. package/package.json +12 -12
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useTimelineExpandedTree = void 0;
3
+ exports.useTimelineExpandedTree = exports.useTimelineSequenceHasExpandableContent = void 0;
4
4
  const react_1 = require("react");
5
5
  const remotion_1 = require("remotion");
6
6
  const timeline_layout_1 = require("../../helpers/timeline-layout");
@@ -9,6 +9,50 @@ const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
9
9
  const get_node_keyframes_1 = require("./get-node-keyframes");
10
10
  const timeline_expanded_filter_1 = require("./timeline-expanded-filter");
11
11
  const TimelineSelection_1 = require("./TimelineSelection");
12
+ const useTimelineSequenceHasExpandableContent = ({ sequence, nodePathInfo, }) => {
13
+ const { propStatuses: visualModePropStatuses } = (0, react_1.useContext)(remotion_1.Internals.VisualModePropStatusesContext);
14
+ const { getDragOverrides, getEffectDragOverrides } = (0, react_1.useContext)(remotion_1.Internals.VisualModeDragOverridesContext);
15
+ const { selectedItems } = (0, TimelineSelection_1.useTimelineSelection)();
16
+ const selectedRowKeys = (0, react_1.useMemo)(() => (0, timeline_expanded_filter_1.getSelectedTimelineExpandedRowKeys)(selectedItems), [selectedItems]);
17
+ const selectHasExpandableContent = (0, react_1.useCallback)((runtimeValues) => {
18
+ const tree = (0, timeline_layout_1.buildTimelineTree)({
19
+ sequence,
20
+ nodePathInfo,
21
+ getDragOverrides,
22
+ getEffectDragOverrides,
23
+ propStatuses: visualModePropStatuses,
24
+ includeTextContent: false,
25
+ includeSourceControls: false,
26
+ runtimeValues,
27
+ });
28
+ return ((0, timeline_expanded_filter_1.filterTimelineExpandedTree)({
29
+ nodes: tree,
30
+ shouldShowNode: (node) => (0, timeline_expanded_filter_1.isTimelineExpandedNodeSelected)({
31
+ nodePathInfo: node.nodePathInfo,
32
+ selectedRowKeys,
33
+ }) ||
34
+ (0, get_node_keyframes_1.getNodeHasKeyframes)({
35
+ node,
36
+ nodePath: nodePathInfo.sequenceSubscriptionKey,
37
+ propStatuses: visualModePropStatuses,
38
+ getDragOverrides,
39
+ getEffectDragOverrides,
40
+ }),
41
+ }).length > 0);
42
+ }, [
43
+ getDragOverrides,
44
+ getEffectDragOverrides,
45
+ nodePathInfo,
46
+ selectedRowKeys,
47
+ sequence,
48
+ visualModePropStatuses,
49
+ ]);
50
+ return (0, use_runtime_values_1.useRuntimeValueSelector)({
51
+ controls: sequence.controls,
52
+ selector: selectHasExpandableContent,
53
+ });
54
+ };
55
+ exports.useTimelineSequenceHasExpandableContent = useTimelineSequenceHasExpandableContent;
12
56
  const useTimelineExpandedTree = ({ sequence, nodePathInfo, includeTextContent, includeSourceControls, }) => {
13
57
  const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
14
58
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
@@ -0,0 +1,12 @@
1
+ import type { EditorPickerId, GetDefaultCodingAgentInfoResponse, GetDefaultEditorInfoResponse } from '@remotion/studio-shared';
2
+ import type { ComboboxValue } from './NewComposition/ComboBox';
3
+ export declare const getOpenInMenuItems: ({ codingAgentInfo, editorDisabled, editorInfo, excludeCodingAgentId, excludeEditorId, onConfigureApps, onOpenInCodingAgent, onOpenInEditor, }: {
4
+ readonly codingAgentInfo: GetDefaultCodingAgentInfoResponse | null;
5
+ readonly editorDisabled: boolean;
6
+ readonly editorInfo: GetDefaultEditorInfoResponse | null;
7
+ readonly excludeCodingAgentId: "claude-code" | "codex" | "copilot" | "cursor" | null;
8
+ readonly excludeEditorId: EditorPickerId | null;
9
+ readonly onConfigureApps: () => void;
10
+ readonly onOpenInCodingAgent: (codingAgentId: "claude-code" | "codex" | "copilot" | "cursor", codingAgentName: string) => void;
11
+ readonly onOpenInEditor: (editorId: EditorPickerId) => void;
12
+ }) => ComboboxValue[];
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOpenInMenuItems = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const editor_1 = require("../icons/editor");
6
+ const CodingAgentIcon_1 = require("./CodingAgentIcon");
7
+ const menuLabel = {
8
+ color: 'inherit',
9
+ fontFamily: 'sans-serif',
10
+ fontSize: 13,
11
+ lineHeight: '16px',
12
+ };
13
+ const getOpenInMenuItems = ({ codingAgentInfo, editorDisabled, editorInfo, excludeCodingAgentId, excludeEditorId, onConfigureApps, onOpenInCodingAgent, onOpenInEditor, }) => {
14
+ var _a, _b;
15
+ const editors = ((_a = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors) !== null && _a !== void 0 ? _a : [])
16
+ .filter((editor) => editor.id !== excludeEditorId)
17
+ .map((editor) => ({
18
+ disabled: editorDisabled,
19
+ id: `open-in-${editor.id}`,
20
+ keyHint: null,
21
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: editor.name }),
22
+ leftItem: jsx_runtime_1.jsx(editor_1.EditorIcon, { editorId: editor.id, size: 18 }),
23
+ onClick: () => {
24
+ if (!editorDisabled) {
25
+ onOpenInEditor(editor.id);
26
+ }
27
+ },
28
+ quickSwitcherLabel: null,
29
+ subMenu: null,
30
+ type: 'item',
31
+ value: editor.id,
32
+ }));
33
+ const codingAgents = ((_b = codingAgentInfo === null || codingAgentInfo === void 0 ? void 0 : codingAgentInfo.installedCodingAgents) !== null && _b !== void 0 ? _b : [])
34
+ .filter((codingAgent) => codingAgent.id !== excludeCodingAgentId)
35
+ .map((codingAgent) => ({
36
+ id: `open-in-coding-agent-${codingAgent.id}`,
37
+ keyHint: null,
38
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: codingAgent.name }),
39
+ leftItem: jsx_runtime_1.jsx(CodingAgentIcon_1.CodingAgentIcon, { iconDataUrl: codingAgent.iconDataUrl }),
40
+ onClick: () => onOpenInCodingAgent(codingAgent.id, codingAgent.nameWithType),
41
+ quickSwitcherLabel: null,
42
+ subMenu: null,
43
+ type: 'item',
44
+ value: `coding-agent-${codingAgent.id}`,
45
+ }));
46
+ return [
47
+ ...(editors.length > 0
48
+ ? [
49
+ {
50
+ type: 'section-header',
51
+ id: 'editors-header',
52
+ label: 'Editors',
53
+ },
54
+ ...editors,
55
+ ]
56
+ : []),
57
+ ...(codingAgents.length > 0
58
+ ? [
59
+ {
60
+ type: 'section-header',
61
+ id: 'agents-header',
62
+ label: 'Agents',
63
+ },
64
+ ...codingAgents,
65
+ ]
66
+ : []),
67
+ ...(editors.length > 0 || codingAgents.length > 0
68
+ ? [{ type: 'divider', id: 'open-in-settings-divider' }]
69
+ : []),
70
+ {
71
+ id: 'change-default-apps',
72
+ keyHint: null,
73
+ label: jsx_runtime_1.jsx("span", { style: menuLabel, children: "Change default apps..." }),
74
+ leftItem: null,
75
+ onClick: onConfigureApps,
76
+ quickSwitcherLabel: null,
77
+ subMenu: null,
78
+ type: 'item',
79
+ value: 'change-default-apps',
80
+ },
81
+ ];
82
+ };
83
+ exports.getOpenInMenuItems = getOpenInMenuItems;
@@ -1,6 +1,6 @@
1
1
  import type { OverrideIdToNodePaths, TSequence } from 'remotion';
2
2
  import type { OutlinePoint, SelectedOutline } from './selected-outline-geometry';
3
- import type { SelectedOutlineTarget, SequenceWithSelectedOutline } from './selected-outline-types';
3
+ import type { SelectedOutlineLayoutTarget, SequenceWithSelectedOutline } from './selected-outline-types';
4
4
  import { type TimelineSelection, type TimelineSelectionInteraction } from './Timeline/TimelineSelection';
5
5
  export declare const pointToString: (point: OutlinePoint) => string;
6
6
  export declare const midpoint: (from: OutlinePoint, to: OutlinePoint) => OutlinePoint;
@@ -75,6 +75,6 @@ export declare const getSequencesWithSelectableOutlines: ({ sequences, overrideI
75
75
  readonly compositions?: readonly import("remotion").AnyComposition[] | undefined;
76
76
  readonly timelinePosition: number;
77
77
  }) => SequenceWithSelectedOutline[];
78
- export declare const measureOutlines: (container: SVGSVGElement, targets: readonly SelectedOutlineTarget[]) => SelectedOutline[];
78
+ export declare const measureOutlines: (container: SVGSVGElement, targets: readonly SelectedOutlineLayoutTarget[]) => SelectedOutline[];
79
79
  export declare const outlinesAreEqual: (a: readonly SelectedOutline[], b: readonly SelectedOutline[]) => boolean;
80
80
  export {};
@@ -0,0 +1,12 @@
1
+ import type { SelectedOutline } from './selected-outline-geometry';
2
+ import type { SelectedOutlineLayoutTarget } from './selected-outline-types';
3
+ type OutlineSequenceParent = {
4
+ readonly id: string;
5
+ readonly parent: string | null;
6
+ };
7
+ export declare const orderOutlinesForRendering: ({ outlines, sequences, targetsByKey, }: {
8
+ readonly outlines: readonly SelectedOutline[];
9
+ readonly sequences: readonly OutlineSequenceParent[];
10
+ readonly targetsByKey: ReadonlyMap<string, SelectedOutlineLayoutTarget>;
11
+ }) => readonly SelectedOutline[];
12
+ export {};
@@ -0,0 +1,251 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.orderOutlinesForRendering = void 0;
4
+ const outlinePointEqualityTolerance = 0.5;
5
+ const outlineAreaEqualityTolerance = 0.5;
6
+ const outlineBoundsOverlapTolerance = 0.5;
7
+ const outlinePointsAreEquivalent = (a, b) => {
8
+ return (Math.abs(a.x - b.x) <= outlinePointEqualityTolerance &&
9
+ Math.abs(a.y - b.y) <= outlinePointEqualityTolerance);
10
+ };
11
+ const outlinesHaveEquivalentHitArea = (a, b) => {
12
+ if (a.points.length !== b.points.length) {
13
+ return false;
14
+ }
15
+ for (let startIndex = 0; startIndex < b.points.length; startIndex++) {
16
+ for (const direction of [1, -1]) {
17
+ const pointsMatch = a.points.every((point, index) => {
18
+ const bIndex = (startIndex + direction * index + b.points.length) % b.points.length;
19
+ return outlinePointsAreEquivalent(point, b.points[bIndex]);
20
+ });
21
+ if (pointsMatch) {
22
+ return true;
23
+ }
24
+ }
25
+ }
26
+ return false;
27
+ };
28
+ const getOutlineHitArea = (outline) => {
29
+ let area = 0;
30
+ for (let i = 0; i < outline.points.length; i++) {
31
+ const current = outline.points[i];
32
+ const next = outline.points[(i + 1) % outline.points.length];
33
+ area += current.x * next.y - next.x * current.y;
34
+ }
35
+ return Math.abs(area) / 2;
36
+ };
37
+ const getOutlineBounds = (outline) => {
38
+ const xs = outline.points.map((point) => point.x);
39
+ const ys = outline.points.map((point) => point.y);
40
+ return {
41
+ maxX: Math.max(...xs),
42
+ maxY: Math.max(...ys),
43
+ minX: Math.min(...xs),
44
+ minY: Math.min(...ys),
45
+ };
46
+ };
47
+ const outlineBoundsOverlap = (a, b) => {
48
+ const aBounds = getOutlineBounds(a);
49
+ const bBounds = getOutlineBounds(b);
50
+ return (aBounds.minX <= bBounds.maxX + outlineBoundsOverlapTolerance &&
51
+ aBounds.maxX + outlineBoundsOverlapTolerance >= bBounds.minX &&
52
+ aBounds.minY <= bBounds.maxY + outlineBoundsOverlapTolerance &&
53
+ aBounds.maxY + outlineBoundsOverlapTolerance >= bBounds.minY);
54
+ };
55
+ const getSequenceId = (target) => {
56
+ var _a;
57
+ var _b;
58
+ return (_b = (_a = target === null || target === void 0 ? void 0 : target.sequence) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null;
59
+ };
60
+ const getParentBySequenceId = ({ sequences, targetsByKey, }) => {
61
+ const parentBySequenceId = new Map();
62
+ for (const sequence of sequences) {
63
+ parentBySequenceId.set(sequence.id, sequence.parent);
64
+ }
65
+ for (const target of targetsByKey.values()) {
66
+ const sequenceId = getSequenceId(target);
67
+ if (sequenceId !== null && !parentBySequenceId.has(sequenceId)) {
68
+ parentBySequenceId.set(sequenceId, target.sequence.parent);
69
+ }
70
+ }
71
+ return parentBySequenceId;
72
+ };
73
+ const isAncestorTarget = ({ ancestor, descendant, parentBySequenceId, }) => {
74
+ var _a;
75
+ var _b, _c;
76
+ const ancestorId = getSequenceId(ancestor);
77
+ if (ancestorId === null) {
78
+ return false;
79
+ }
80
+ let parentId = (_b = (_a = descendant.sequence) === null || _a === void 0 ? void 0 : _a.parent) !== null && _b !== void 0 ? _b : null;
81
+ while (parentId !== null) {
82
+ if (parentId === ancestorId) {
83
+ return true;
84
+ }
85
+ parentId = (_c = parentBySequenceId.get(parentId)) !== null && _c !== void 0 ? _c : null;
86
+ }
87
+ return false;
88
+ };
89
+ const orderOutlineGroup = ({ outlines, parentBySequenceId, targetsByKey, }) => {
90
+ var _a;
91
+ var _b, _c, _d, _e;
92
+ const incomingEdges = new Map();
93
+ const outgoingEdges = new Map();
94
+ const outlinesByKey = new Map(outlines.map((outline) => [outline.key, outline]));
95
+ for (const outline of outlines) {
96
+ incomingEdges.set(outline.key, new Set());
97
+ outgoingEdges.set(outline.key, new Set());
98
+ }
99
+ const hasPath = ({ fromKey, seen, toKey, }) => {
100
+ var _a;
101
+ if (fromKey === toKey) {
102
+ return true;
103
+ }
104
+ if (seen.has(fromKey)) {
105
+ return false;
106
+ }
107
+ seen.add(fromKey);
108
+ for (const nextKey of (_a = outgoingEdges.get(fromKey)) !== null && _a !== void 0 ? _a : []) {
109
+ if (hasPath({ fromKey: nextKey, seen, toKey })) {
110
+ return true;
111
+ }
112
+ }
113
+ return false;
114
+ };
115
+ const addEdge = (before, after, options) => {
116
+ if (before.key === after.key) {
117
+ return;
118
+ }
119
+ const incoming = incomingEdges.get(after.key);
120
+ const outgoing = outgoingEdges.get(before.key);
121
+ if (incoming === undefined || outgoing === undefined) {
122
+ throw new Error('Expected outline to be registered before adding edge');
123
+ }
124
+ if (outgoing.has(after.key)) {
125
+ return;
126
+ }
127
+ if (hasPath({ fromKey: after.key, seen: new Set(), toKey: before.key })) {
128
+ if (options === null || options === void 0 ? void 0 : options.skipIfCycle) {
129
+ return;
130
+ }
131
+ throw new Error('Could not determine a stable outline rendering order');
132
+ }
133
+ incoming.add(before.key);
134
+ outgoing.add(after.key);
135
+ };
136
+ const addAncestorConstraint = ({ ancestor, descendant, descendantContainsSelection, equivalentHitArea, }) => {
137
+ // Usually, children should be above parents so nested elements are directly
138
+ // selectable. If an unselected child has the same hit area as its parent, put
139
+ // it below the parent so the wrapper can be selected. Once the child or
140
+ // one of its properties is selected, keep it above the parent so it remains
141
+ // directly draggable.
142
+ if (equivalentHitArea && !descendantContainsSelection) {
143
+ addEdge(descendant, ancestor);
144
+ }
145
+ else {
146
+ addEdge(ancestor, descendant);
147
+ }
148
+ };
149
+ const outlineBySequenceId = new Map();
150
+ for (const outline of outlines) {
151
+ const sequenceId = getSequenceId(targetsByKey.get(outline.key));
152
+ if (sequenceId !== null) {
153
+ outlineBySequenceId.set(sequenceId, outline);
154
+ }
155
+ }
156
+ // Only constrain each outline against its nearest rendered ancestor. The
157
+ // resulting graph follows the sequence tree, so pairwise subpixel equivalence
158
+ // cannot introduce contradictory edges across three nested outlines.
159
+ for (const descendant of outlines) {
160
+ const descendantTarget = targetsByKey.get(descendant.key);
161
+ let parentId = (_b = (_a = descendantTarget === null || descendantTarget === void 0 ? void 0 : descendantTarget.sequence) === null || _a === void 0 ? void 0 : _a.parent) !== null && _b !== void 0 ? _b : null;
162
+ while (parentId !== null) {
163
+ const ancestor = outlineBySequenceId.get(parentId);
164
+ if (ancestor !== undefined) {
165
+ addAncestorConstraint({
166
+ ancestor,
167
+ descendant,
168
+ descendantContainsSelection: ((_c = descendantTarget === null || descendantTarget === void 0 ? void 0 : descendantTarget.selected) !== null && _c !== void 0 ? _c : false) ||
169
+ ((_d = descendantTarget === null || descendantTarget === void 0 ? void 0 : descendantTarget.containsSelection) !== null && _d !== void 0 ? _d : false),
170
+ equivalentHitArea: outlinesHaveEquivalentHitArea(ancestor, descendant),
171
+ });
172
+ break;
173
+ }
174
+ parentId = (_e = parentBySequenceId.get(parentId)) !== null && _e !== void 0 ? _e : null;
175
+ }
176
+ }
177
+ // For unrelated overlapping outlines, put broader hit targets below
178
+ // smaller ones so a large selected sequence cannot swallow clicks on
179
+ // a more specific element in the same canvas area.
180
+ for (let i = 0; i < outlines.length; i++) {
181
+ for (let j = i + 1; j < outlines.length; j++) {
182
+ const a = outlines[i];
183
+ const b = outlines[j];
184
+ const aTarget = targetsByKey.get(a.key);
185
+ const bTarget = targetsByKey.get(b.key);
186
+ if (aTarget === undefined || bTarget === undefined) {
187
+ continue;
188
+ }
189
+ const aAncestorOfB = isAncestorTarget({
190
+ ancestor: aTarget,
191
+ descendant: bTarget,
192
+ parentBySequenceId,
193
+ });
194
+ const bAncestorOfA = isAncestorTarget({
195
+ ancestor: bTarget,
196
+ descendant: aTarget,
197
+ parentBySequenceId,
198
+ });
199
+ if (aAncestorOfB || bAncestorOfA || !outlineBoundsOverlap(a, b)) {
200
+ continue;
201
+ }
202
+ const aArea = getOutlineHitArea(a);
203
+ const bArea = getOutlineHitArea(b);
204
+ if (Math.abs(aArea - bArea) <= outlineAreaEqualityTolerance) {
205
+ continue;
206
+ }
207
+ if (aArea > bArea) {
208
+ addEdge(a, b, { skipIfCycle: true });
209
+ }
210
+ else {
211
+ addEdge(b, a, { skipIfCycle: true });
212
+ }
213
+ }
214
+ }
215
+ const emitted = new Set();
216
+ const visiting = new Set();
217
+ const ordered = [];
218
+ const visit = (outline) => {
219
+ var _a;
220
+ if (emitted.has(outline.key)) {
221
+ return;
222
+ }
223
+ if (visiting.has(outline.key)) {
224
+ throw new Error('Could not determine a stable outline rendering order');
225
+ }
226
+ visiting.add(outline.key);
227
+ for (const dependencyKey of (_a = incomingEdges.get(outline.key)) !== null && _a !== void 0 ? _a : []) {
228
+ const dependency = outlinesByKey.get(dependencyKey);
229
+ if (dependency === undefined) {
230
+ throw new Error('Expected outline dependency to exist');
231
+ }
232
+ visit(dependency);
233
+ }
234
+ visiting.delete(outline.key);
235
+ emitted.add(outline.key);
236
+ ordered.push(outline);
237
+ };
238
+ for (const outline of outlines) {
239
+ visit(outline);
240
+ }
241
+ return ordered;
242
+ };
243
+ const orderOutlinesForRendering = ({ outlines, sequences, targetsByKey, }) => {
244
+ const parentBySequenceId = getParentBySequenceId({ sequences, targetsByKey });
245
+ return orderOutlineGroup({
246
+ outlines,
247
+ parentBySequenceId,
248
+ targetsByKey,
249
+ });
250
+ };
251
+ exports.orderOutlinesForRendering = orderOutlinesForRendering;
@@ -1,18 +1,20 @@
1
1
  import type { CanUpdateSequencePropStatus, CanUpdateSequencePropStatusKeyframed, CanUpdateSequencePropStatusStatic, InteractivitySchema, InteractivitySchemaField, SequencePropsSubscriptionKey, TSequence } from 'remotion';
2
2
  import type { SequenceNodePathInfo } from '../helpers/get-timeline-sequence-sort-key';
3
3
  import type { ComboboxValue } from './NewComposition/ComboBox';
4
- import type { SelectedOutlineUvHandle } from './selected-outline-uv';
5
4
  import type { TimelineSelection } from './Timeline/TimelineSelection';
6
5
  export type SelectedOutlineContextMenuOpenResult = false | readonly ComboboxValue[];
7
6
  export type SelectedOutlineContextMenuOpenHandler = () => SelectedOutlineContextMenuOpenResult | Promise<SelectedOutlineContextMenuOpenResult>;
8
- export type SelectedOutlineTarget = {
7
+ export type SelectedOutlineLayoutTarget = {
9
8
  readonly key: string;
10
- readonly canCrop: boolean;
11
9
  readonly containsSelection: boolean;
12
- readonly effectDrop: SelectedOutlineEffectDropTarget | null;
10
+ readonly keyframeDisplayOffset: number;
13
11
  readonly nodePathInfo: SequenceNodePathInfo;
14
12
  readonly ref: React.RefObject<Element | null>;
15
13
  readonly selected: boolean;
14
+ readonly selectedForCrop: boolean;
15
+ readonly selectedForTransformOrigin: boolean;
16
+ readonly selectedForUvHandles: boolean;
17
+ readonly showSelectedOutline: boolean;
16
18
  readonly selection: TimelineSelection;
17
19
  readonly sequence: TSequence;
18
20
  readonly crop: {
@@ -21,12 +23,14 @@ export type SelectedOutlineTarget = {
21
23
  readonly top: number;
22
24
  readonly bottom: number;
23
25
  };
26
+ };
27
+ export type SelectedOutlineTarget = SelectedOutlineLayoutTarget & {
28
+ readonly canCrop: boolean;
24
29
  readonly cropDrag: SelectedOutlineCropDragTarget | null;
25
30
  readonly drag: SelectedOutlineDragTarget | null;
26
31
  readonly scaleDrag: SelectedOutlineScaleDragTarget | null;
27
32
  readonly rotationDrag: SelectedOutlineRotationDragTarget | null;
28
33
  readonly transformOriginDrag: SelectedOutlineTransformOriginDragTarget | null;
29
- readonly uvHandles: readonly SelectedOutlineUvHandle[];
30
34
  };
31
35
  export declare const cropFieldKeys: {
32
36
  readonly left: "cropLeft";
@@ -62,11 +66,6 @@ export type SelectedOutlineCropDragTarget = {
62
66
  readonly value: string;
63
67
  } | null;
64
68
  };
65
- export type SelectedOutlineEffectDropTarget = {
66
- readonly clientId: string;
67
- readonly fileName: string;
68
- readonly nodePath: SequencePropsSubscriptionKey;
69
- };
70
69
  export type SelectedOutlineDragTarget = {
71
70
  readonly propStatus: CanUpdateSequencePropStatusStatic | CanUpdateSequencePropStatusKeyframed;
72
71
  readonly clientId: string;
@@ -0,0 +1,2 @@
1
+ import type { OutlinePoint } from './selected-outline-geometry';
2
+ export declare const svgPointToClientPoint: (point: OutlinePoint, rect: DOMRect) => OutlinePoint;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.svgPointToClientPoint = void 0;
4
+ const svgPointToClientPoint = (point, rect) => {
5
+ return {
6
+ x: point.x + rect.left,
7
+ y: point.y + rect.top,
8
+ };
9
+ };
10
+ exports.svgPointToClientPoint = svgPointToClientPoint;
@@ -0,0 +1,8 @@
1
+ import type { ConfigUpdate } from '@remotion/studio-shared';
2
+ export declare const useAutoSaveConfig: ({ enabled, onError, ready, syncRevision, updates, }: {
3
+ readonly enabled: boolean;
4
+ readonly onError: (error: string | null) => void;
5
+ readonly ready: boolean;
6
+ readonly syncRevision: number;
7
+ readonly updates: ConfigUpdate[];
8
+ }) => void;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useAutoSaveConfig = void 0;
4
+ const react_1 = require("react");
5
+ const client_id_1 = require("../helpers/client-id");
6
+ const call_api_1 = require("./call-api");
7
+ const useAutoSaveConfig = ({ enabled, onError, ready, syncRevision, updates, }) => {
8
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
9
+ const serializedUpdates = (0, react_1.useMemo)(() => JSON.stringify(updates), [updates]);
10
+ const initialUpdates = (0, react_1.useRef)(null);
11
+ const lastQueuedUpdates = (0, react_1.useRef)(null);
12
+ const lastSyncRevision = (0, react_1.useRef)(null);
13
+ const syncGeneration = (0, react_1.useRef)(0);
14
+ const saveQueue = (0, react_1.useRef)(Promise.resolve());
15
+ const mounted = (0, react_1.useRef)(true);
16
+ (0, react_1.useEffect)(() => {
17
+ mounted.current = true;
18
+ return () => {
19
+ mounted.current = false;
20
+ };
21
+ }, []);
22
+ (0, react_1.useEffect)(() => {
23
+ if (!ready) {
24
+ return;
25
+ }
26
+ if (initialUpdates.current === null ||
27
+ lastSyncRevision.current !== syncRevision) {
28
+ initialUpdates.current = serializedUpdates;
29
+ lastQueuedUpdates.current = serializedUpdates;
30
+ lastSyncRevision.current = syncRevision;
31
+ syncGeneration.current++;
32
+ return;
33
+ }
34
+ if (!enabled ||
35
+ previewServerState.type !== 'connected' ||
36
+ lastQueuedUpdates.current === serializedUpdates) {
37
+ return;
38
+ }
39
+ lastQueuedUpdates.current = serializedUpdates;
40
+ onError(null);
41
+ const generation = syncGeneration.current;
42
+ saveQueue.current = saveQueue.current.then(async () => {
43
+ if (generation !== syncGeneration.current) {
44
+ return;
45
+ }
46
+ try {
47
+ const response = await (0, call_api_1.callApi)('/api/update-config', {
48
+ clientId: previewServerState.clientId,
49
+ updates,
50
+ });
51
+ if (!response.success &&
52
+ mounted.current &&
53
+ lastQueuedUpdates.current === serializedUpdates) {
54
+ onError(response.reason);
55
+ }
56
+ }
57
+ catch (err) {
58
+ if (mounted.current &&
59
+ lastQueuedUpdates.current === serializedUpdates) {
60
+ onError(err.message);
61
+ }
62
+ }
63
+ });
64
+ }, [
65
+ enabled,
66
+ onError,
67
+ previewServerState,
68
+ ready,
69
+ serializedUpdates,
70
+ syncRevision,
71
+ updates,
72
+ ]);
73
+ };
74
+ exports.useAutoSaveConfig = useAutoSaveConfig;
@@ -2,3 +2,4 @@ import type { EditorPickerId, GetDefaultEditorInfoResponse } from '@remotion/stu
2
2
  export declare const canUseEditorPicker: (previewServerConnected: boolean) => boolean;
3
3
  export declare const getPreferredEditorId: (editorInfo: GetDefaultEditorInfoResponse | null) => EditorPickerId | null;
4
4
  export declare const useDefaultEditorInfo: (enabled: boolean) => GetDefaultEditorInfoResponse | null;
5
+ export declare const useDefaultCodingAgentInfo: (enabled: boolean) => import("@remotion/studio-shared").GetDefaultCodingAgentInfoResponse | null;
@@ -1,17 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.useDefaultEditorInfo = exports.getPreferredEditorId = exports.canUseEditorPicker = void 0;
4
- const react_1 = require("react");
3
+ exports.useDefaultCodingAgentInfo = exports.useDefaultEditorInfo = exports.getPreferredEditorId = exports.canUseEditorPicker = void 0;
5
4
  const browser_studio_operations_1 = require("../helpers/browser-studio-operations");
6
- const call_api_1 = require("./call-api");
7
- let editorInfoPromise = null;
8
- const loadDefaultEditorInfo = () => {
9
- editorInfoPromise !== null && editorInfoPromise !== void 0 ? editorInfoPromise : (editorInfoPromise = (0, call_api_1.callApi)('/api/default-editor-info', {}).catch((err) => {
10
- editorInfoPromise = null;
11
- throw err;
12
- }));
13
- return editorInfoPromise;
14
- };
5
+ const SettingsContext_1 = require("./SettingsContext");
15
6
  const canUseEditorPicker = (previewServerConnected) => {
16
7
  return (previewServerConnected &&
17
8
  !window.remotion_isReadOnlyStudio &&
@@ -21,27 +12,16 @@ exports.canUseEditorPicker = canUseEditorPicker;
21
12
  const getPreferredEditorId = (editorInfo) => {
22
13
  var _a;
23
14
  var _b;
24
- return ((_b = (_a = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.find((editor) => editor.name === window.remotion_editorName)) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null);
15
+ return ((_b = (_a = editorInfo === null || editorInfo === void 0 ? void 0 : editorInfo.installedEditors.find((editor) => editor.nameWithType === window.remotion_editorName)) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : null);
25
16
  };
26
17
  exports.getPreferredEditorId = getPreferredEditorId;
27
18
  const useDefaultEditorInfo = (enabled) => {
28
- const [editorInfo, setEditorInfo] = (0, react_1.useState)(null);
29
- (0, react_1.useEffect)(() => {
30
- if (!enabled) {
31
- return;
32
- }
33
- let cancelled = false;
34
- loadDefaultEditorInfo()
35
- .then((response) => {
36
- if (!cancelled) {
37
- setEditorInfo(response);
38
- }
39
- })
40
- .catch(() => undefined);
41
- return () => {
42
- cancelled = true;
43
- };
44
- }, [enabled]);
45
- return editorInfo;
19
+ const { editorInfo } = (0, SettingsContext_1.useSettings)();
20
+ return enabled ? editorInfo : null;
46
21
  };
47
22
  exports.useDefaultEditorInfo = useDefaultEditorInfo;
23
+ const useDefaultCodingAgentInfo = (enabled) => {
24
+ const { codingAgentInfo } = (0, SettingsContext_1.useSettings)();
25
+ return enabled ? codingAgentInfo : null;
26
+ };
27
+ exports.useDefaultCodingAgentInfo = useDefaultCodingAgentInfo;