@remotion/studio 4.0.469 → 4.0.470

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 (90) hide show
  1. package/dist/Studio.js +1 -1
  2. package/dist/api/save-render-output.js +3 -12
  3. package/dist/components/AudioWaveform.js +19 -2
  4. package/dist/components/ContextMenu.js +5 -1
  5. package/dist/components/EditorContent.js +5 -4
  6. package/dist/components/Menu/MenuItem.d.ts +1 -1
  7. package/dist/components/MenuBuildIndicator.js +0 -1
  8. package/dist/components/NewComposition/InputDragger.js +1 -0
  9. package/dist/components/Preview.js +4 -1
  10. package/dist/components/SelectedOutlineOverlay.d.ts +18 -0
  11. package/dist/components/SelectedOutlineOverlay.js +645 -0
  12. package/dist/components/Timeline/Timeline.js +27 -13
  13. package/dist/components/Timeline/TimelineDeleteKeybindings.d.ts +2 -0
  14. package/dist/components/Timeline/TimelineDeleteKeybindings.js +86 -0
  15. package/dist/components/Timeline/TimelineDragHandler.js +19 -244
  16. package/dist/components/Timeline/{TimelineEffectGroupRow.d.ts → TimelineEffectItem.d.ts} +1 -1
  17. package/dist/components/Timeline/{TimelineEffectGroupRow.js → TimelineEffectItem.js} +50 -33
  18. package/dist/components/Timeline/{TimelineEffectFieldRow.d.ts → TimelineEffectPropItem.d.ts} +2 -1
  19. package/dist/components/Timeline/{TimelineEffectFieldRow.js → TimelineEffectPropItem.js} +97 -8
  20. package/dist/components/Timeline/TimelineExpandArrowButton.js +5 -1
  21. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +37 -5
  22. package/dist/components/Timeline/TimelineExpandedRow.d.ts +1 -0
  23. package/dist/components/Timeline/TimelineExpandedRow.js +9 -7
  24. package/dist/components/Timeline/TimelineExpandedSection.d.ts +1 -0
  25. package/dist/components/Timeline/TimelineExpandedSection.js +2 -2
  26. package/dist/components/Timeline/TimelineInOutDragHandler.d.ts +2 -0
  27. package/dist/components/Timeline/TimelineInOutDragHandler.js +324 -0
  28. package/dist/components/Timeline/TimelineInOutPointer.js +3 -1
  29. package/dist/components/Timeline/TimelineInOutPointerHandle.d.ts +1 -0
  30. package/dist/components/Timeline/TimelineInOutPointerHandle.js +5 -4
  31. package/dist/components/Timeline/TimelineKeyframeControls.d.ts +17 -0
  32. package/dist/components/Timeline/TimelineKeyframeControls.js +217 -0
  33. package/dist/components/Timeline/TimelineKeyframeDiamond.js +7 -6
  34. package/dist/components/Timeline/TimelineKeyframedValue.d.ts +8 -0
  35. package/dist/components/Timeline/TimelineKeyframedValue.js +36 -0
  36. package/dist/components/Timeline/TimelineList.js +3 -15
  37. package/dist/components/Timeline/TimelineRowChrome.d.ts +3 -1
  38. package/dist/components/Timeline/TimelineRowChrome.js +23 -5
  39. package/dist/components/Timeline/TimelineSelection.d.ts +53 -9
  40. package/dist/components/Timeline/TimelineSelection.js +305 -48
  41. package/dist/components/Timeline/TimelineSequence.d.ts +2 -0
  42. package/dist/components/Timeline/TimelineSequence.js +18 -6
  43. package/dist/components/Timeline/TimelineSequenceFrame.js +1 -0
  44. package/dist/components/Timeline/{TimelineListItem.d.ts → TimelineSequenceItem.d.ts} +2 -1
  45. package/dist/components/Timeline/{TimelineListItem.js → TimelineSequenceItem.js} +49 -33
  46. package/dist/components/Timeline/{TimelineFieldRow.d.ts → TimelineSequencePropItem.d.ts} +2 -1
  47. package/dist/components/Timeline/{TimelineFieldRow.js → TimelineSequencePropItem.js} +81 -5
  48. package/dist/components/Timeline/TimelineTimeIndicators.js +0 -1
  49. package/dist/components/Timeline/TimelineTrack.js +3 -1
  50. package/dist/components/Timeline/TimelineTranslateField.js +14 -22
  51. package/dist/components/Timeline/call-add-keyframe.d.ts +23 -0
  52. package/dist/components/Timeline/call-add-keyframe.js +54 -0
  53. package/dist/components/Timeline/call-delete-keyframe.d.ts +21 -0
  54. package/dist/components/Timeline/call-delete-keyframe.js +50 -0
  55. package/dist/components/Timeline/delete-selected-keyframe.d.ts +11 -0
  56. package/dist/components/Timeline/delete-selected-keyframe.js +51 -0
  57. package/dist/components/Timeline/delete-selected-timeline-item.d.ts +17 -0
  58. package/dist/components/Timeline/delete-selected-timeline-item.js +183 -0
  59. package/dist/components/Timeline/duplicate-selected-timeline-item.d.ts +13 -0
  60. package/dist/components/Timeline/duplicate-selected-timeline-item.js +66 -0
  61. package/dist/components/Timeline/find-track-for-node-path-info.d.ts +7 -0
  62. package/dist/components/Timeline/find-track-for-node-path-info.js +13 -0
  63. package/dist/components/Timeline/get-keyframe-navigation.d.ts +9 -0
  64. package/dist/components/Timeline/get-keyframe-navigation.js +26 -0
  65. package/dist/components/Timeline/parse-keyframe-field-from-node-path.d.ts +8 -0
  66. package/dist/components/Timeline/parse-keyframe-field-from-node-path.js +26 -0
  67. package/dist/components/Timeline/save-sequence-prop.d.ts +14 -2
  68. package/dist/components/Timeline/save-sequence-prop.js +42 -7
  69. package/dist/components/Timeline/timeline-row-layout.d.ts +1 -0
  70. package/dist/components/Timeline/timeline-row-layout.js +2 -1
  71. package/dist/components/Timeline/timeline-translate-utils.d.ts +2 -0
  72. package/dist/components/Timeline/timeline-translate-utils.js +20 -0
  73. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +10 -3
  74. package/dist/components/composition-menu-items.js +32 -1
  75. package/dist/error-overlay/remotion-overlay/OpenInEditor.js +0 -1
  76. package/dist/esm/{chunk-1mp51e0w.js → chunk-dny42qnq.js} +9896 -6174
  77. package/dist/esm/internals.mjs +9896 -6174
  78. package/dist/esm/previewEntry.mjs +9870 -6148
  79. package/dist/esm/renderEntry.mjs +3 -1
  80. package/dist/helpers/format-file-location.d.ts +9 -0
  81. package/dist/helpers/format-file-location.js +27 -0
  82. package/dist/helpers/get-box-quads-polyfill-internals.d.ts +82 -0
  83. package/dist/helpers/get-box-quads-polyfill-internals.js +2395 -0
  84. package/dist/helpers/get-box-quads-ponyfill.d.ts +10 -0
  85. package/dist/helpers/get-box-quads-ponyfill.js +23 -0
  86. package/dist/helpers/open-in-editor.d.ts +1 -1
  87. package/dist/helpers/open-in-editor.js +11 -26
  88. package/dist/helpers/use-menu-structure.js +8 -16
  89. package/dist/renderEntry.js +2 -2
  90. package/package.json +10 -10
@@ -5,6 +5,7 @@ type Props = {
5
5
  readonly dragging: boolean;
6
6
  readonly type: 'in' | 'out';
7
7
  readonly atFrame: number;
8
+ readonly onPointerDown?: (e: React.PointerEvent<HTMLDivElement>) => void;
8
9
  };
9
10
  export declare const TimelineInOutPointerHandle: React.FC<Props>;
10
11
  export {};
@@ -18,7 +18,7 @@ const line = {
18
18
  };
19
19
  exports.inPointerHandle = (0, react_1.createRef)();
20
20
  exports.outPointerHandle = (0, react_1.createRef)();
21
- const InnerTimelineInOutPointerHandle = ({ atFrame, dragging, timelineWidth, type }) => {
21
+ const InnerTimelineInOutPointerHandle = ({ atFrame, dragging, onPointerDown, timelineWidth, type }) => {
22
22
  const videoConfig = (0, remotion_1.useVideoConfig)();
23
23
  const style = (0, react_1.useMemo)(() => {
24
24
  return {
@@ -27,17 +27,18 @@ const InnerTimelineInOutPointerHandle = ({ atFrame, dragging, timelineWidth, typ
27
27
  ? colors_1.LIGHT_TRANSPARENT
28
28
  : 'rgba(255, 255, 255, 0.1)',
29
29
  transform: `translateX(${(0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(atFrame, videoConfig.durationInFrames, timelineWidth)}px)`,
30
+ top: 0,
30
31
  };
31
32
  }, [atFrame, dragging, timelineWidth, videoConfig.durationInFrames]);
32
- return (jsx_runtime_1.jsx("div", { ref: type === 'in' ? exports.inPointerHandle : exports.outPointerHandle, style: style }));
33
+ return (jsx_runtime_1.jsx("div", { ref: type === 'in' ? exports.inPointerHandle : exports.outPointerHandle, style: style, onPointerDown: onPointerDown }));
33
34
  };
34
- const TimelineInOutPointerHandle = ({ dragging, type, atFrame, }) => {
35
+ const TimelineInOutPointerHandle = ({ dragging, onPointerDown, type, atFrame, }) => {
35
36
  const timelineWidth = (0, react_1.useContext)(TimelineWidthProvider_1.TimelineWidthContext);
36
37
  // When switching from a content which has no timeline (still or asset preview)
37
38
  // the timeline first needs to mount, so we need to wait for the timeline width
38
39
  if (timelineWidth === null) {
39
40
  return null;
40
41
  }
41
- return (jsx_runtime_1.jsx(InnerTimelineInOutPointerHandle, { atFrame: atFrame, dragging: dragging, timelineWidth: timelineWidth, type: type }));
42
+ return (jsx_runtime_1.jsx(InnerTimelineInOutPointerHandle, { atFrame: atFrame, dragging: dragging, onPointerDown: onPointerDown, timelineWidth: timelineWidth, type: type }));
42
43
  };
43
44
  exports.TimelineInOutPointerHandle = TimelineInOutPointerHandle;
@@ -0,0 +1,17 @@
1
+ import React from 'react';
2
+ import type { CanUpdateSequencePropStatus, SequencePropsSubscriptionKey, SequenceSchema } from 'remotion';
3
+ export declare const shouldShowTimelineKeyframeControls: ({ propStatus, selected, }: {
4
+ propStatus: CanUpdateSequencePropStatus | null;
5
+ selected: boolean;
6
+ }) => boolean;
7
+ export declare const TimelineKeyframeControls: React.FC<{
8
+ readonly fieldKey: string;
9
+ readonly propStatus: CanUpdateSequencePropStatus;
10
+ readonly nodePath: SequencePropsSubscriptionKey;
11
+ readonly fileName: string;
12
+ readonly keyframeDisplayOffset: number;
13
+ readonly defaultValue: unknown;
14
+ readonly dragOverrideValue: unknown | undefined;
15
+ readonly schema: SequenceSchema;
16
+ readonly effectIndex: number | null;
17
+ }>;
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineKeyframeControls = exports.shouldShowTimelineKeyframeControls = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const client_id_1 = require("../../helpers/client-id");
8
+ const colors_1 = require("../../helpers/colors");
9
+ const call_add_keyframe_1 = require("./call-add-keyframe");
10
+ const call_delete_keyframe_1 = require("./call-delete-keyframe");
11
+ const get_keyframe_navigation_1 = require("./get-keyframe-navigation");
12
+ const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
13
+ const TimelineSelection_1 = require("./TimelineSelection");
14
+ const controlsContainerStyle = {
15
+ alignItems: 'center',
16
+ display: 'flex',
17
+ flexShrink: 0,
18
+ gap: 2,
19
+ marginRight: 4,
20
+ };
21
+ const navButtonStyle = {
22
+ alignItems: 'center',
23
+ background: 'none',
24
+ border: 'none',
25
+ color: 'white',
26
+ cursor: 'pointer',
27
+ display: 'flex',
28
+ flexShrink: 0,
29
+ fontSize: 8,
30
+ height: 12,
31
+ justifyContent: 'center',
32
+ lineHeight: 1,
33
+ outline: 'none',
34
+ padding: 0,
35
+ userSelect: 'none',
36
+ width: 10,
37
+ };
38
+ const diamondButtonStyle = {
39
+ ...navButtonStyle,
40
+ height: 10,
41
+ width: 10,
42
+ };
43
+ const svgStyle = { display: 'block' };
44
+ const getCurrentKeyframeValue = ({ propStatus, jsxFrame, defaultValue, dragOverrideValue, }) => {
45
+ if (propStatus.canUpdate) {
46
+ return remotion_1.Internals.getEffectiveVisualModeValue({
47
+ codeValue: propStatus,
48
+ dragOverrideValue,
49
+ defaultValue,
50
+ shouldResortToDefaultValueIfUndefined: true,
51
+ });
52
+ }
53
+ if (propStatus.reason === 'keyframed') {
54
+ return remotion_1.Internals.interpolateKeyframedStatus({
55
+ frame: jsxFrame,
56
+ status: propStatus,
57
+ });
58
+ }
59
+ return null;
60
+ };
61
+ const shouldShowTimelineKeyframeControls = ({ propStatus, selected, }) => {
62
+ if (propStatus === null) {
63
+ return false;
64
+ }
65
+ if (selected) {
66
+ return true;
67
+ }
68
+ return (TimelineSelection_1.SELECTION_ENABLED &&
69
+ !propStatus.canUpdate &&
70
+ propStatus.reason === 'keyframed');
71
+ };
72
+ exports.shouldShowTimelineKeyframeControls = shouldShowTimelineKeyframeControls;
73
+ const TimelineKeyframeControls = ({ fieldKey, propStatus, nodePath, fileName, keyframeDisplayOffset, defaultValue, dragOverrideValue, schema, effectIndex, }) => {
74
+ const videoConfig = (0, remotion_1.useVideoConfig)();
75
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
76
+ const setFrame = remotion_1.Internals.useTimelineSetFrame();
77
+ const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
78
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
79
+ const clientId = previewServerState.type === 'connected'
80
+ ? previewServerState.clientId
81
+ : null;
82
+ const jsxFrame = timelinePosition - keyframeDisplayOffset;
83
+ const keyframes = (0, react_1.useMemo)(() => (0, get_timeline_keyframes_1.getTimelineKeyframes)(propStatus, keyframeDisplayOffset), [propStatus, keyframeDisplayOffset]);
84
+ const hasKeyframeAtCurrentFrame = (0, react_1.useMemo)(() => {
85
+ if (propStatus.canUpdate || propStatus.reason === 'computed') {
86
+ return false;
87
+ }
88
+ return (0, get_keyframe_navigation_1.hasKeyframeAtSourceFrame)(propStatus.keyframes, jsxFrame);
89
+ }, [jsxFrame, propStatus]);
90
+ const previousDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getPreviousKeyframeDisplayFrame)(keyframes, timelinePosition), [keyframes, timelinePosition]);
91
+ const nextDisplayFrame = (0, react_1.useMemo)(() => (0, get_keyframe_navigation_1.getNextKeyframeDisplayFrame)(keyframes, timelinePosition), [keyframes, timelinePosition]);
92
+ const canToggleKeyframe = propStatus.canUpdate || propStatus.reason === 'keyframed';
93
+ const seekToDisplayFrame = (0, react_1.useCallback)((frame) => {
94
+ setFrame((current) => {
95
+ const next = { ...current, [videoConfig.id]: frame };
96
+ remotion_1.Internals.persistCurrentFrame(next);
97
+ return next;
98
+ });
99
+ }, [setFrame, videoConfig.id]);
100
+ const onPrevious = (0, react_1.useCallback)((e) => {
101
+ e.stopPropagation();
102
+ if (previousDisplayFrame !== null) {
103
+ seekToDisplayFrame(previousDisplayFrame);
104
+ }
105
+ }, [previousDisplayFrame, seekToDisplayFrame]);
106
+ const onNext = (0, react_1.useCallback)((e) => {
107
+ e.stopPropagation();
108
+ if (nextDisplayFrame !== null) {
109
+ seekToDisplayFrame(nextDisplayFrame);
110
+ }
111
+ }, [nextDisplayFrame, seekToDisplayFrame]);
112
+ const onToggleKeyframe = (0, react_1.useCallback)(async (e) => {
113
+ e.stopPropagation();
114
+ if (!clientId || !canToggleKeyframe) {
115
+ return;
116
+ }
117
+ if (hasKeyframeAtCurrentFrame &&
118
+ !propStatus.canUpdate &&
119
+ propStatus.reason === 'keyframed') {
120
+ if (effectIndex === null) {
121
+ await (0, call_delete_keyframe_1.callDeleteSequenceKeyframe)({
122
+ fileName,
123
+ nodePath,
124
+ fieldKey,
125
+ sourceFrame: jsxFrame,
126
+ schema,
127
+ setCodeValues,
128
+ clientId,
129
+ });
130
+ return;
131
+ }
132
+ await (0, call_delete_keyframe_1.callDeleteEffectKeyframe)({
133
+ fileName,
134
+ nodePath,
135
+ effectIndex,
136
+ fieldKey,
137
+ sourceFrame: jsxFrame,
138
+ schema,
139
+ setCodeValues,
140
+ clientId,
141
+ });
142
+ return;
143
+ }
144
+ const value = getCurrentKeyframeValue({
145
+ propStatus,
146
+ jsxFrame,
147
+ defaultValue,
148
+ dragOverrideValue,
149
+ });
150
+ if (value === null) {
151
+ return;
152
+ }
153
+ if (effectIndex === null) {
154
+ await (0, call_add_keyframe_1.callAddSequenceKeyframe)({
155
+ fileName,
156
+ nodePath,
157
+ fieldKey,
158
+ sourceFrame: jsxFrame,
159
+ value,
160
+ schema,
161
+ setCodeValues,
162
+ clientId,
163
+ });
164
+ return;
165
+ }
166
+ await (0, call_add_keyframe_1.callAddEffectKeyframe)({
167
+ fileName,
168
+ nodePath,
169
+ effectIndex,
170
+ fieldKey,
171
+ sourceFrame: jsxFrame,
172
+ value,
173
+ schema,
174
+ setCodeValues,
175
+ clientId,
176
+ });
177
+ }, [
178
+ canToggleKeyframe,
179
+ clientId,
180
+ defaultValue,
181
+ dragOverrideValue,
182
+ effectIndex,
183
+ fieldKey,
184
+ fileName,
185
+ hasKeyframeAtCurrentFrame,
186
+ jsxFrame,
187
+ nodePath,
188
+ propStatus,
189
+ schema,
190
+ setCodeValues,
191
+ ]);
192
+ const previousDisabled = previousDisplayFrame === null;
193
+ const nextDisabled = nextDisplayFrame === null;
194
+ const previousStyle = (0, react_1.useMemo)(() => ({
195
+ ...navButtonStyle,
196
+ cursor: previousDisabled ? 'default' : 'pointer',
197
+ opacity: previousDisabled ? 0.35 : 1,
198
+ }), [previousDisabled]);
199
+ const nextStyle = (0, react_1.useMemo)(() => ({
200
+ ...navButtonStyle,
201
+ cursor: nextDisabled ? 'default' : 'pointer',
202
+ opacity: nextDisabled ? 0.35 : 1,
203
+ }), [nextDisabled]);
204
+ const diamondStyle = (0, react_1.useMemo)(() => ({
205
+ ...diamondButtonStyle,
206
+ backgroundColor: hasKeyframeAtCurrentFrame ? colors_1.BLUE : colors_1.LIGHT_TEXT,
207
+ borderRadius: 1,
208
+ boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.4)',
209
+ cursor: canToggleKeyframe && clientId ? 'pointer' : 'default',
210
+ opacity: canToggleKeyframe && clientId ? 1 : 0.35,
211
+ transform: 'rotate(45deg)',
212
+ }), [canToggleKeyframe, clientId, hasKeyframeAtCurrentFrame]);
213
+ return (jsx_runtime_1.jsxs("div", { style: controlsContainerStyle, children: [
214
+ jsx_runtime_1.jsx("button", { type: "button", style: previousStyle, disabled: previousDisabled, onPointerDown: previousDisabled ? undefined : onPrevious, "aria-label": "Go to previous keyframe", title: "Previous keyframe", children: jsx_runtime_1.jsx("svg", { width: "8", height: "8", viewBox: "0 0 8 8", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M5 1L2 4L5 7Z", fill: "#ccc" }) }) }), jsx_runtime_1.jsx("button", { type: "button", style: diamondStyle, disabled: !canToggleKeyframe || !clientId, onPointerDown: canToggleKeyframe && clientId ? onToggleKeyframe : undefined, "aria-label": hasKeyframeAtCurrentFrame ? 'Remove keyframe' : 'Add keyframe', title: hasKeyframeAtCurrentFrame ? 'Remove keyframe' : 'Add keyframe' }), jsx_runtime_1.jsx("button", { type: "button", style: nextStyle, disabled: nextDisabled, onPointerDown: nextDisabled ? undefined : onNext, "aria-label": "Go to next keyframe", title: "Next keyframe", children: jsx_runtime_1.jsx("svg", { width: "8", height: "8", viewBox: "0 0 8 8", style: svgStyle, children: jsx_runtime_1.jsx("path", { d: "M3 1L6 4L3 7Z", fill: "#ccc" }) }) })
215
+ ] }));
216
+ };
217
+ exports.TimelineKeyframeControls = TimelineKeyframeControls;
@@ -49,7 +49,6 @@ const diamondBase = {
49
49
  backgroundColor: colors_1.LIGHT_TEXT,
50
50
  borderRadius: 1,
51
51
  boxShadow: '0 0 0 1px rgba(0, 0, 0, 0.4)',
52
- pointerEvents: 'none',
53
52
  };
54
53
  const TimelineKeyframeDiamondUnmemoized = ({ frame, rowHeight, nodePathInfo }) => {
55
54
  const videoConfig = (0, remotion_1.useVideoConfig)();
@@ -61,11 +60,10 @@ const TimelineKeyframeDiamondUnmemoized = ({ frame, rowHeight, nodePathInfo }) =
61
60
  }
62
61
  return {
63
62
  ...diamondBase,
64
- backgroundColor: selected
65
- ? TimelineSelection_1.TIMELINE_SELECTED_LABEL_BACKGROUND
66
- : colors_1.LIGHT_TEXT,
63
+ backgroundColor: colors_1.LIGHT_TEXT,
64
+ outline: selected ? '2px solid ' + colors_1.BLUE : 'none',
67
65
  border: 'none',
68
- cursor: 'default',
66
+ cursor: 'pointer',
69
67
  left: (0, get_left_of_timeline_slider_1.getXPositionOfItemInTimelineImperatively)(frame, videoConfig.durationInFrames, timelineWidth) - timeline_layout_1.TIMELINE_PADDING,
70
68
  padding: 0,
71
69
  pointerEvents: 'auto',
@@ -76,7 +74,10 @@ const TimelineKeyframeDiamondUnmemoized = ({ frame, rowHeight, nodePathInfo }) =
76
74
  const onPointerDown = (0, react_1.useCallback)((e) => {
77
75
  if (e.button === 0) {
78
76
  e.stopPropagation();
79
- onSelect();
77
+ onSelect({
78
+ shiftKey: e.shiftKey,
79
+ toggleKey: e.metaKey || e.ctrlKey,
80
+ });
80
81
  }
81
82
  }, [onSelect]);
82
83
  if (style === null) {
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import type { CanUpdateSequencePropStatusKeyframed } from 'remotion';
3
+ import type { SchemaFieldInfo } from '../../helpers/timeline-layout';
4
+ export declare const TimelineKeyframedValue: React.FC<{
5
+ readonly field: SchemaFieldInfo;
6
+ readonly propStatus: CanUpdateSequencePropStatusKeyframed;
7
+ readonly keyframeDisplayOffset: number;
8
+ }>;
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineKeyframedValue = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const remotion_1 = require("remotion");
7
+ const TimelineSchemaField_1 = require("./TimelineSchemaField");
8
+ const wrapperStyle = {
9
+ opacity: 0.5,
10
+ pointerEvents: 'none',
11
+ };
12
+ const noop = () => undefined;
13
+ const noopAsync = () => Promise.resolve();
14
+ const TimelineKeyframedValue = ({ field, propStatus, keyframeDisplayOffset }) => {
15
+ const timelinePosition = remotion_1.Internals.Timeline.useTimelinePosition();
16
+ const jsxFrame = timelinePosition - keyframeDisplayOffset;
17
+ const computedValue = (0, react_1.useMemo)(() => {
18
+ const raw = remotion_1.Internals.interpolateKeyframedStatus({
19
+ frame: jsxFrame,
20
+ status: propStatus,
21
+ });
22
+ if (typeof raw === 'number') {
23
+ return Math.round(raw * 100) / 100;
24
+ }
25
+ return raw;
26
+ }, [jsxFrame, propStatus]);
27
+ const fakeStatus = (0, react_1.useMemo)(() => ({
28
+ canUpdate: true,
29
+ codeValue: computedValue,
30
+ }), [computedValue]);
31
+ if (computedValue === null) {
32
+ return null;
33
+ }
34
+ return (jsx_runtime_1.jsx("div", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineSchemaField_1.TimelineFieldValue, { field: field, propStatus: fakeStatus, effectiveValue: computedValue, onSave: noopAsync, onDragValueChange: noop, onDragEnd: noop }) }));
35
+ };
36
+ exports.TimelineKeyframedValue = TimelineKeyframedValue;
@@ -2,29 +2,17 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineList = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("react");
6
5
  const colors_1 = require("../../helpers/colors");
7
- const TimelineListItem_1 = require("./TimelineListItem");
8
- const TimelineSelection_1 = require("./TimelineSelection");
6
+ const TimelineSequenceItem_1 = require("./TimelineSequenceItem");
9
7
  const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
10
8
  const container = {
11
9
  flex: 1,
12
10
  background: colors_1.BACKGROUND,
13
11
  };
14
12
  const TimelineList = ({ timeline }) => {
15
- const { clearSelection } = (0, TimelineSelection_1.useTimelineSelection)();
16
- // Selection-triggering click handlers in children call e.stopPropagation(),
17
- // so any pointerdown that bubbles up here is by definition on empty space
18
- // and should clear the current selection.
19
- const onPointerDown = (0, react_1.useCallback)((e) => {
20
- if (e.button !== 0) {
21
- return;
22
- }
23
- clearSelection();
24
- }, [clearSelection]);
25
- return (jsx_runtime_1.jsxs("div", { style: container, onPointerDown: onPointerDown, children: [
13
+ return (jsx_runtime_1.jsxs("div", { style: container, children: [
26
14
  jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePadding, {}), timeline.map((track) => {
27
- return (jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(TimelineListItem_1.TimelineListItem, { nestedDepth: track.depth, sequence: track.sequence, nodePathInfo: track.nodePathInfo }, track.sequence.id) }, track.sequence.id));
15
+ return (jsx_runtime_1.jsx("div", { children: jsx_runtime_1.jsx(TimelineSequenceItem_1.TimelineSequenceItem, { nestedDepth: track.depth, sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset }, track.sequence.id) }, track.sequence.id));
28
16
  })] }));
29
17
  };
30
18
  exports.TimelineList = TimelineList;
@@ -1,13 +1,15 @@
1
1
  import React from 'react';
2
+ import type { TimelineSelectionInteraction } from './TimelineSelection';
2
3
  export declare const TimelineRowChrome: React.FC<{
3
4
  readonly depth: number;
4
5
  readonly eye: React.ReactNode;
6
+ readonly keyframeControls?: React.ReactNode;
5
7
  readonly arrow: React.ReactNode;
6
8
  readonly children: React.ReactNode;
7
9
  readonly style: React.CSSProperties;
8
10
  readonly selected: boolean;
9
11
  readonly selectable: boolean;
10
- readonly onSelect: () => void;
12
+ readonly onSelect: (interaction?: TimelineSelectionInteraction) => void;
11
13
  readonly showSelectedBackground: boolean;
12
14
  readonly containsSelection: boolean;
13
15
  readonly outerHeight: number | null;
@@ -11,19 +11,36 @@ const rowBase = {
11
11
  alignItems: 'stretch',
12
12
  display: 'flex',
13
13
  };
14
- const chromeColumnStyle = {
14
+ const leftChromeStyle = {
15
15
  alignItems: 'center',
16
16
  alignSelf: 'stretch',
17
17
  display: 'flex',
18
18
  flexShrink: 0,
19
- paddingLeft: timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING,
20
19
  };
21
- const TimelineRowChrome = ({ depth, eye, arrow, children, style, selected, selectable, onSelect, showSelectedBackground, containsSelection, outerHeight, onDoubleClick, }) => {
20
+ const keyframeControlsColumnStyle = {
21
+ alignItems: 'center',
22
+ display: 'flex',
23
+ flexShrink: 0,
24
+ justifyContent: 'flex-start',
25
+ marginRight: -(timeline_row_layout_1.TIMELINE_KEYFRAME_CONTROLS_WIDTH - timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING),
26
+ width: timeline_row_layout_1.TIMELINE_KEYFRAME_CONTROLS_WIDTH,
27
+ };
28
+ const TimelineRowChrome = ({ depth, eye, keyframeControls, arrow, children, style, selected, selectable, onSelect, showSelectedBackground, containsSelection, outerHeight, onDoubleClick, }) => {
22
29
  const indentWidth = (0, timeline_row_layout_1.getTimelineRowIndentWidth)(depth);
30
+ const chromeColumnStyle = (0, react_1.useMemo)(() => ({
31
+ alignItems: 'center',
32
+ alignSelf: 'stretch',
33
+ display: 'flex',
34
+ flexShrink: 0,
35
+ paddingLeft: keyframeControls ? 0 : timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING,
36
+ }), [keyframeControls]);
23
37
  const onPointerDown = (0, react_1.useCallback)((e) => {
24
38
  if (e.button === 0) {
25
39
  e.stopPropagation();
26
- onSelect();
40
+ onSelect({
41
+ shiftKey: e.shiftKey,
42
+ toggleKey: e.metaKey || e.ctrlKey,
43
+ });
27
44
  }
28
45
  }, [onSelect]);
29
46
  const onContextMenu = (0, react_1.useCallback)((e) => {
@@ -52,7 +69,8 @@ const TimelineRowChrome = ({ depth, eye, arrow, children, style, selected, selec
52
69
  };
53
70
  }, [outerHeight, highlightBackground]);
54
71
  const chrome = (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
55
- jsx_runtime_1.jsxs("div", { style: chromeColumnStyle, children: [eye, indentWidth > 0 ? jsx_runtime_1.jsx(Padder_1.Padder, { depth: depth }) : null, arrow] }), children] }));
72
+ jsx_runtime_1.jsxs("div", { style: leftChromeStyle, children: [keyframeControls ? (jsx_runtime_1.jsx("div", { style: keyframeControlsColumnStyle, children: keyframeControls })) : null, jsx_runtime_1.jsxs("div", { style: chromeColumnStyle, children: [eye, indentWidth > 0 ? jsx_runtime_1.jsx(Padder_1.Padder, { depth: depth }) : null, arrow] })
73
+ ] }), children] }));
56
74
  if (outerStyle) {
57
75
  return (jsx_runtime_1.jsx("div", { style: outerStyle, onPointerDown: selectable ? onPointerDown : undefined, onContextMenu: selectable ? onContextMenu : undefined, onDoubleClick: onDoubleClick, children: jsx_runtime_1.jsx("div", { style: innerRowStyle, children: chrome }) }));
58
76
  }
@@ -1,39 +1,83 @@
1
1
  import React, { type CSSProperties } from 'react';
2
- import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
2
+ import type { SequenceNodePathInfo, TrackWithHash } from '../../helpers/get-timeline-sequence-sort-key';
3
3
  export declare const TIMELINE_SELECTED_BACKGROUND = "#3B3F42";
4
4
  export declare const TIMELINE_SELECTED_LABEL_BACKGROUND = "#B0B0B0";
5
5
  export declare const TIMELINE_SELECTED_LABEL_TEXT = "black";
6
6
  export declare const TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = 2;
7
7
  export declare const getTimelineSelectedLabelStyle: (selected: boolean, subcategory: boolean) => CSSProperties;
8
8
  export declare const getTimelineColor: (selected: boolean, subcategory: boolean) => "black" | "rgba(255, 255, 255, 0.8)";
9
- export declare const TIMELINE_SELECTED_TRACK_HIGHLIGHT_STYLE: CSSProperties;
9
+ export declare const getTimelineSelectedTrackHighlightStyle: (timelineWidth: number) => CSSProperties;
10
10
  export declare const SELECTION_ENABLED = false;
11
- export type TimelineSelection = {
12
- readonly type: 'row';
11
+ export declare const TIMELINE_TOP_DRAG = false;
12
+ export declare const ENABLE_OUTLINES = false;
13
+ type TimelineSelectionBase = {
13
14
  readonly nodePathInfo: SequenceNodePathInfo;
14
- } | {
15
+ };
16
+ export type TimelineSelection = (TimelineSelectionBase & {
17
+ readonly type: 'sequence';
18
+ }) | (TimelineSelectionBase & {
19
+ readonly type: 'sequence-prop';
20
+ readonly key: string;
21
+ }) | (TimelineSelectionBase & {
22
+ readonly type: 'sequence-all-effects';
23
+ }) | (TimelineSelectionBase & {
24
+ readonly type: 'sequence-effect';
25
+ readonly i: number;
26
+ }) | (TimelineSelectionBase & {
27
+ readonly type: 'sequence-effect-prop';
28
+ readonly i: number;
29
+ readonly key: string;
30
+ }) | (TimelineSelectionBase & {
15
31
  readonly type: 'keyframe';
16
- readonly nodePathInfo: SequenceNodePathInfo;
17
32
  readonly frame: number;
33
+ });
34
+ export type TimelineSelectionInteraction = {
35
+ readonly shiftKey: boolean;
36
+ readonly toggleKey: boolean;
18
37
  };
38
+ export declare const isTimelineSelectionModifierEvent: ({ shiftKey, metaKey, ctrlKey, }: {
39
+ readonly shiftKey: boolean;
40
+ readonly metaKey: boolean;
41
+ readonly ctrlKey: boolean;
42
+ }) => boolean;
43
+ export type TimelineSelectionState = {
44
+ readonly selectedItems: readonly TimelineSelection[];
45
+ readonly anchor: TimelineSelection | null;
46
+ };
47
+ export declare const getTimelineSelectionAfterInteraction: ({ currentState, clickedItem, interaction, allSelectableItems, }: {
48
+ readonly currentState: TimelineSelectionState;
49
+ readonly clickedItem: TimelineSelection;
50
+ readonly interaction: TimelineSelectionInteraction;
51
+ readonly allSelectableItems: readonly TimelineSelection[];
52
+ }) => TimelineSelectionState;
19
53
  type TimelineSelectionContextValue = {
20
54
  readonly canSelect: boolean;
55
+ readonly selectedItems: readonly TimelineSelection[];
21
56
  readonly isSelected: (item: TimelineSelection) => boolean;
22
- readonly selectItem: (item: TimelineSelection) => void;
57
+ readonly selectItem: (item: TimelineSelection, interaction?: TimelineSelectionInteraction) => void;
58
+ readonly selectItems: (items: readonly TimelineSelection[]) => void;
59
+ readonly registerSelectableItem: (item: TimelineSelection) => () => void;
23
60
  readonly containsSelection: (nodePathInfo: SequenceNodePathInfo) => boolean;
24
61
  readonly clearSelection: () => void;
25
62
  };
63
+ export declare const getTimelineSelectionFromNodePathInfo: (nodePathInfo: SequenceNodePathInfo | null) => TimelineSelection | null;
64
+ export declare const getSelectableTimelineSequenceSelections: (tracks: readonly Pick<TrackWithHash, "nodePathInfo">[]) => TimelineSelection[];
65
+ export declare const getTimelineSequenceSelectionKey: (nodePathInfo: SequenceNodePathInfo) => string;
66
+ export declare const TimelineSelectAllKeybindings: React.FC<{
67
+ readonly timeline: readonly TrackWithHash[];
68
+ }>;
26
69
  export declare const TimelineSelectionProvider: React.FC<{
27
70
  readonly children: React.ReactNode;
28
71
  }>;
29
72
  export declare const useTimelineSelection: () => TimelineSelectionContextValue;
73
+ export declare const useCurrentTimelineSelectionStateAsRef: () => React.RefObject<TimelineSelectionContextValue>;
30
74
  export declare const useTimelineRowSelection: (nodePathInfo: SequenceNodePathInfo | null) => {
31
- onSelect: () => void;
75
+ onSelect: (interaction?: TimelineSelectionInteraction | undefined) => void;
32
76
  selectable: boolean;
33
77
  selected: boolean;
34
78
  };
35
79
  export declare const useTimelineKeyframeSelection: (nodePathInfo: SequenceNodePathInfo, frame: number) => {
36
- onSelect: () => void;
80
+ onSelect: (interaction?: TimelineSelectionInteraction | undefined) => void;
37
81
  selectable: boolean;
38
82
  selected: boolean;
39
83
  };