@remotion/studio 4.0.468 → 4.0.469

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 (71) hide show
  1. package/dist/components/AudioWaveform.d.ts +1 -0
  2. package/dist/components/AudioWaveform.js +23 -22
  3. package/dist/components/CompositionSelectorItem.js +1 -1
  4. package/dist/components/ContextMenu.d.ts +1 -0
  5. package/dist/components/ContextMenu.js +3 -2
  6. package/dist/components/EditorGuides/Guide.js +1 -1
  7. package/dist/components/ExpandedTracksProvider.js +3 -8
  8. package/dist/components/Menu/MenuItem.js +2 -2
  9. package/dist/components/Menu/MenuSubItem.js +5 -5
  10. package/dist/components/PreviewToolbar.js +2 -4
  11. package/dist/components/Timeline/Timeline.js +14 -13
  12. package/dist/components/Timeline/TimelineDragHandler.js +1 -1
  13. package/dist/components/Timeline/TimelineEffectFieldRow.d.ts +2 -0
  14. package/dist/components/Timeline/TimelineEffectFieldRow.js +9 -14
  15. package/dist/components/Timeline/TimelineEffectGroupRow.js +13 -4
  16. package/dist/components/Timeline/TimelineExpandedKeyframeRow.d.ts +11 -0
  17. package/dist/components/Timeline/TimelineExpandedKeyframeRow.js +23 -0
  18. package/dist/components/Timeline/TimelineExpandedRow.js +22 -6
  19. package/dist/components/Timeline/TimelineExpandedSection.js +2 -2
  20. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.d.ts +1 -1
  21. package/dist/components/Timeline/TimelineExpandedTrackKeyframes.js +9 -120
  22. package/dist/components/Timeline/TimelineFieldLabel.d.ts +6 -0
  23. package/dist/components/Timeline/TimelineFieldLabel.js +30 -0
  24. package/dist/components/Timeline/TimelineFieldRow.d.ts +3 -2
  25. package/dist/components/Timeline/TimelineFieldRow.js +7 -13
  26. package/dist/components/Timeline/TimelineItemStack.d.ts +5 -0
  27. package/dist/components/Timeline/TimelineItemStack.js +82 -0
  28. package/dist/components/Timeline/TimelineKeyframeDiamond.d.ts +7 -0
  29. package/dist/components/Timeline/TimelineKeyframeDiamond.js +87 -0
  30. package/dist/components/Timeline/TimelineLayerEye.js +1 -0
  31. package/dist/components/Timeline/TimelineList.js +13 -9
  32. package/dist/components/Timeline/TimelineListItem.d.ts +0 -1
  33. package/dist/components/Timeline/TimelineListItem.js +100 -31
  34. package/dist/components/Timeline/TimelineMediaInfo.d.ts +13 -1
  35. package/dist/components/Timeline/TimelineMediaInfo.js +33 -80
  36. package/dist/components/Timeline/TimelineRowChrome.d.ts +8 -1
  37. package/dist/components/Timeline/TimelineRowChrome.js +46 -6
  38. package/dist/components/Timeline/TimelineSchemaField.js +7 -2
  39. package/dist/components/Timeline/TimelineSelection.d.ts +41 -0
  40. package/dist/components/Timeline/TimelineSelection.js +160 -0
  41. package/dist/components/Timeline/TimelineSequence.js +1 -1
  42. package/dist/components/Timeline/TimelineSequenceName.d.ts +7 -0
  43. package/dist/components/Timeline/TimelineSequenceName.js +50 -0
  44. package/dist/components/Timeline/TimelineTrack.d.ts +5 -0
  45. package/dist/components/Timeline/TimelineTrack.js +64 -0
  46. package/dist/components/Timeline/TimelineTracks.js +2 -16
  47. package/dist/components/Timeline/TimelineUvCoordinateField.d.ts +11 -0
  48. package/dist/components/Timeline/TimelineUvCoordinateField.js +126 -0
  49. package/dist/components/Timeline/TimelineVideoInfo.js +11 -12
  50. package/dist/components/Timeline/get-node-keyframes.d.ts +11 -0
  51. package/dist/components/Timeline/get-node-keyframes.js +23 -0
  52. package/dist/components/Timeline/get-timeline-keyframes.js +6 -8
  53. package/dist/components/Timeline/timeline-field-row-layout.d.ts +1 -0
  54. package/dist/components/Timeline/timeline-field-row-layout.js +11 -1
  55. package/dist/components/Timeline/use-expanded-track-keyframe-rows.d.ts +17 -0
  56. package/dist/components/Timeline/use-expanded-track-keyframe-rows.js +45 -0
  57. package/dist/components/Timeline/use-open-sequence-in-editor.d.ts +6 -0
  58. package/dist/components/Timeline/use-open-sequence-in-editor.js +31 -0
  59. package/dist/esm/{chunk-8q828zk7.js → chunk-1mp51e0w.js} +3328 -2705
  60. package/dist/esm/internals.mjs +3328 -2705
  61. package/dist/esm/previewEntry.mjs +3338 -2715
  62. package/dist/esm/renderEntry.mjs +1 -1
  63. package/dist/helpers/colors.d.ts +1 -1
  64. package/dist/helpers/colors.js +1 -1
  65. package/dist/helpers/timeline-layout.d.ts +8 -7
  66. package/dist/helpers/timeline-layout.js +9 -8
  67. package/dist/helpers/timeline-node-path-key.d.ts +2 -0
  68. package/dist/helpers/timeline-node-path-key.js +10 -0
  69. package/package.json +10 -10
  70. package/dist/components/Timeline/TimelineStack/index.d.ts +0 -8
  71. package/dist/components/Timeline/TimelineStack/index.js +0 -119
@@ -0,0 +1,160 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useTimelineRowContainsSelection = exports.useTimelineKeyframeSelection = exports.useTimelineRowSelection = exports.useTimelineSelection = exports.TimelineSelectionProvider = exports.SELECTION_ENABLED = exports.TIMELINE_SELECTED_TRACK_HIGHLIGHT_STYLE = exports.getTimelineColor = exports.getTimelineSelectedLabelStyle = exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = exports.TIMELINE_SELECTED_LABEL_TEXT = exports.TIMELINE_SELECTED_LABEL_BACKGROUND = exports.TIMELINE_SELECTED_BACKGROUND = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const studio_shared_1 = require("@remotion/studio-shared");
6
+ const react_1 = require("react");
7
+ const client_id_1 = require("../../helpers/client-id");
8
+ const timeline_layout_1 = require("../../helpers/timeline-layout");
9
+ const timeline_node_path_key_1 = require("../../helpers/timeline-node-path-key");
10
+ exports.TIMELINE_SELECTED_BACKGROUND = '#3B3F42';
11
+ exports.TIMELINE_SELECTED_LABEL_BACKGROUND = '#B0B0B0';
12
+ exports.TIMELINE_SELECTED_LABEL_TEXT = 'black';
13
+ exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = 2;
14
+ const getTimelineSelectedLabelStyle = (selected, subcategory) => {
15
+ return {
16
+ paddingLeft: exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING,
17
+ paddingRight: exports.TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING,
18
+ ...(selected
19
+ ? {
20
+ backgroundColor: subcategory
21
+ ? 'rgba(255, 255, 255, 0.1)'
22
+ : exports.TIMELINE_SELECTED_LABEL_BACKGROUND,
23
+ }
24
+ : {}),
25
+ };
26
+ };
27
+ exports.getTimelineSelectedLabelStyle = getTimelineSelectedLabelStyle;
28
+ const getTimelineColor = (selected, subcategory) => {
29
+ return selected && !subcategory
30
+ ? exports.TIMELINE_SELECTED_LABEL_TEXT
31
+ : 'rgba(255, 255, 255, 0.8)';
32
+ };
33
+ exports.getTimelineColor = getTimelineColor;
34
+ exports.TIMELINE_SELECTED_TRACK_HIGHLIGHT_STYLE = {
35
+ backgroundColor: exports.TIMELINE_SELECTED_BACKGROUND,
36
+ bottom: 0,
37
+ left: -timeline_layout_1.TIMELINE_PADDING,
38
+ pointerEvents: 'none',
39
+ position: 'absolute',
40
+ right: -timeline_layout_1.TIMELINE_PADDING,
41
+ top: 0,
42
+ };
43
+ exports.SELECTION_ENABLED = false;
44
+ const TimelineSelectionContext = (0, react_1.createContext)({
45
+ canSelect: false,
46
+ isSelected: () => false,
47
+ selectItem: () => undefined,
48
+ containsSelection: () => false,
49
+ clearSelection: () => undefined,
50
+ });
51
+ const getTimelineSelectionKey = (item) => {
52
+ const rowKey = (0, timeline_node_path_key_1.timelineNodePathInfoToKey)(item.nodePathInfo);
53
+ if (item.type === 'row') {
54
+ return rowKey;
55
+ }
56
+ return `${rowKey}.keyframe.${item.frame}`;
57
+ };
58
+ const TimelineSelectionProvider = ({ children }) => {
59
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
60
+ const canSelect = exports.SELECTION_ENABLED &&
61
+ previewServerState.type === 'connected' &&
62
+ !window.remotion_isReadOnlyStudio;
63
+ const [selectedItem, setSelectedItem] = (0, react_1.useState)(null);
64
+ (0, react_1.useEffect)(() => {
65
+ if (!canSelect) {
66
+ setSelectedItem(null);
67
+ }
68
+ }, [canSelect]);
69
+ const isSelected = (0, react_1.useCallback)((item) => {
70
+ return selectedItem === null
71
+ ? false
72
+ : getTimelineSelectionKey(selectedItem) ===
73
+ getTimelineSelectionKey(item);
74
+ }, [selectedItem]);
75
+ const selectItem = (0, react_1.useCallback)((item) => {
76
+ if (!canSelect) {
77
+ return;
78
+ }
79
+ setSelectedItem(item);
80
+ }, [canSelect]);
81
+ const clearSelection = (0, react_1.useCallback)(() => {
82
+ setSelectedItem(null);
83
+ }, []);
84
+ const containsSelection = (0, react_1.useCallback)((nodePathInfo) => {
85
+ if (selectedItem === null) {
86
+ return false;
87
+ }
88
+ const selectedNodePath = selectedItem.nodePathInfo;
89
+ if ((0, studio_shared_1.stringifySequenceExpandedRowKey)(selectedNodePath.sequenceSubscriptionKey) !==
90
+ (0, studio_shared_1.stringifySequenceExpandedRowKey)(nodePathInfo.sequenceSubscriptionKey)) {
91
+ return false;
92
+ }
93
+ if (selectedNodePath.index !== nodePathInfo.index) {
94
+ return false;
95
+ }
96
+ // Selection must be strictly deeper than this node (i.e. a descendant),
97
+ // not the same row.
98
+ if (selectedNodePath.auxiliaryKeys.length <=
99
+ nodePathInfo.auxiliaryKeys.length) {
100
+ return false;
101
+ }
102
+ return nodePathInfo.auxiliaryKeys.every((key, i) => selectedNodePath.auxiliaryKeys[i] === key);
103
+ }, [selectedItem]);
104
+ const value = (0, react_1.useMemo)(() => ({
105
+ canSelect,
106
+ isSelected,
107
+ selectItem,
108
+ containsSelection,
109
+ clearSelection,
110
+ }), [canSelect, isSelected, selectItem, containsSelection, clearSelection]);
111
+ return (jsx_runtime_1.jsx(TimelineSelectionContext.Provider, { value: value, children: children }));
112
+ };
113
+ exports.TimelineSelectionProvider = TimelineSelectionProvider;
114
+ const useTimelineSelection = () => {
115
+ return (0, react_1.useContext)(TimelineSelectionContext);
116
+ };
117
+ exports.useTimelineSelection = useTimelineSelection;
118
+ const useTimelineRowSelection = (nodePathInfo) => {
119
+ const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
120
+ const selectionItem = (0, react_1.useMemo)(() => nodePathInfo === null ? null : { type: 'row', nodePathInfo }, [nodePathInfo]);
121
+ const selected = selectionItem === null ? false : isSelected(selectionItem);
122
+ const onSelect = (0, react_1.useCallback)(() => {
123
+ if (selectionItem === null) {
124
+ return;
125
+ }
126
+ selectItem(selectionItem);
127
+ }, [selectItem, selectionItem]);
128
+ return {
129
+ onSelect,
130
+ selectable: canSelect && selectionItem !== null,
131
+ selected,
132
+ };
133
+ };
134
+ exports.useTimelineRowSelection = useTimelineRowSelection;
135
+ const useTimelineKeyframeSelection = (nodePathInfo, frame) => {
136
+ const { canSelect, isSelected, selectItem } = (0, exports.useTimelineSelection)();
137
+ const selectionItem = (0, react_1.useMemo)(() => ({
138
+ type: 'keyframe',
139
+ nodePathInfo,
140
+ frame,
141
+ }), [nodePathInfo, frame]);
142
+ const selected = isSelected(selectionItem);
143
+ const onSelect = (0, react_1.useCallback)(() => {
144
+ selectItem(selectionItem);
145
+ }, [selectItem, selectionItem]);
146
+ return {
147
+ onSelect,
148
+ selectable: canSelect,
149
+ selected,
150
+ };
151
+ };
152
+ exports.useTimelineKeyframeSelection = useTimelineKeyframeSelection;
153
+ const useTimelineRowContainsSelection = (nodePathInfo) => {
154
+ const { containsSelection } = (0, exports.useTimelineSelection)();
155
+ if (nodePathInfo === null) {
156
+ return false;
157
+ }
158
+ return containsSelection(nodePathInfo);
159
+ };
160
+ exports.useTimelineRowContainsSelection = useTimelineRowContainsSelection;
@@ -165,6 +165,6 @@ const TimelineSequenceInner = ({ s, windowWidth }) => {
165
165
  if (maxMediaDuration === null && !s.loopDisplay) {
166
166
  return null;
167
167
  }
168
- return (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, children: [s.type === 'audio' ? (jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, doesVolumeChange: s.doesVolumeChange, visualizationWidth: width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, trimBefore: s.startMediaFrom, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay })) : null, s.type === 'image' ? (jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: width })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes }))] }));
168
+ return (jsx_runtime_1.jsxs(TimelineSequenceCurrentFrame, { s: s, displayDurationInFrames: displayDurationInFrames, premountWidth: premountWidth, postmountWidth: postmountWidth, style: style, children: [s.type === 'audio' ? (jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: s.src, height: timeline_layout_1.TIMELINE_LAYER_HEIGHT_AUDIO, doesVolumeChange: s.doesVolumeChange, visualizationWidth: width, startFrom: s.startMediaFrom, durationInFrames: s.duration, volume: s.volume, playbackRate: s.playbackRate, loopDisplay: s.loopDisplay })) : null, s.type === 'video' ? (jsx_runtime_1.jsx(TimelineVideoInfo_1.TimelineVideoInfo, { src: s.src, visualizationWidth: width, naturalWidth: naturalWidth, trimBefore: s.startMediaFrom, durationInFrames: s.duration, playbackRate: s.playbackRate, volume: s.volume, doesVolumeChange: s.doesVolumeChange, premountWidth: premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0, postmountWidth: postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0, loopDisplay: s.loopDisplay })) : null, s.type === 'image' ? (jsx_runtime_1.jsx(TimelineImageInfo_1.TimelineImageInfo, { src: s.src, visualizationWidth: width })) : null, s.loopDisplay === undefined ? null : (jsx_runtime_1.jsx(LoopedTimelineIndicators_1.LoopedTimelineIndicator, { loops: s.loopDisplay.numberOfTimes }))] }));
169
169
  };
170
170
  exports.TimelineSequence = react_1.default.memo(TimelineSequenceFn);
@@ -0,0 +1,7 @@
1
+ import React from 'react';
2
+ import type { TSequence } from 'remotion';
3
+ export declare const TimelineSequenceName: React.FC<{
4
+ readonly sequence: TSequence;
5
+ readonly selected: boolean;
6
+ readonly containsSelection: boolean;
7
+ }>;
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineSequenceName = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const TimelineSelection_1 = require("./TimelineSelection");
7
+ const MAX_DISPLAY_NAME_LENGTH = 1000;
8
+ const getTruncatedDisplayName = (displayName) => {
9
+ if (displayName.length > MAX_DISPLAY_NAME_LENGTH) {
10
+ return displayName.slice(0, MAX_DISPLAY_NAME_LENGTH) + '...';
11
+ }
12
+ return displayName;
13
+ };
14
+ const TimelineSequenceName = ({ sequence, selected, containsSelection }) => {
15
+ const [hovered, setHovered] = (0, react_1.useState)(false);
16
+ const { documentationLink } = sequence;
17
+ const hoverable = !TimelineSelection_1.SELECTION_ENABLED && documentationLink !== null;
18
+ const onClick = (0, react_1.useCallback)(() => {
19
+ if (documentationLink === null) {
20
+ return;
21
+ }
22
+ window.open(documentationLink, '_blank', 'noopener,noreferrer');
23
+ }, [documentationLink]);
24
+ const onPointerEnter = (0, react_1.useCallback)(() => setHovered(true), []);
25
+ const onPointerLeave = (0, react_1.useCallback)(() => setHovered(false), []);
26
+ const style = (0, react_1.useMemo)(() => {
27
+ const hoverEffect = hovered && hoverable;
28
+ return {
29
+ alignItems: 'center',
30
+ alignSelf: 'stretch',
31
+ ...(0, TimelineSelection_1.getTimelineSelectedLabelStyle)(selected, false),
32
+ display: 'inline-flex',
33
+ fontSize: 12,
34
+ whiteSpace: 'nowrap',
35
+ textOverflow: 'ellipsis',
36
+ overflow: 'hidden',
37
+ color: (0, TimelineSelection_1.getTimelineColor)(selected, false),
38
+ userSelect: 'none',
39
+ WebkitUserSelect: 'none',
40
+ textDecoration: hoverEffect ? 'underline' : 'none',
41
+ cursor: hoverEffect ? 'pointer' : undefined,
42
+ boxShadow: containsSelection && !selected
43
+ ? `inset 0 0 0 2px ${TimelineSelection_1.TIMELINE_SELECTED_LABEL_BACKGROUND}`
44
+ : undefined,
45
+ };
46
+ }, [hovered, hoverable, selected, containsSelection]);
47
+ const text = getTruncatedDisplayName(sequence.displayName) || '<Sequence>';
48
+ return (jsx_runtime_1.jsx("div", { onPointerEnter: hoverable ? onPointerEnter : undefined, onPointerLeave: hoverable ? onPointerLeave : undefined, title: documentationLink ? `Open documentation: ${documentationLink}` : text, style: style, onClick: hoverable ? onClick : undefined, children: text }));
49
+ };
50
+ exports.TimelineSequenceName = TimelineSequenceName;
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ import type { TrackWithHash } from '../../helpers/get-timeline-sequence-sort-key';
3
+ export declare const TimelineTrack: React.NamedExoticComponent<{
4
+ readonly track: TrackWithHash;
5
+ }>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TimelineTrack = void 0;
37
+ const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const react_1 = __importStar(require("react"));
39
+ const client_id_1 = require("../../helpers/client-id");
40
+ const timeline_layout_1 = require("../../helpers/timeline-layout");
41
+ const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
42
+ const TimelineExpandedTrackKeyframes_1 = require("./TimelineExpandedTrackKeyframes");
43
+ const TimelineSelection_1 = require("./TimelineSelection");
44
+ const TimelineSequence_1 = require("./TimelineSequence");
45
+ const TimelineTrackUnmemoized = ({ track }) => {
46
+ const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
47
+ const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
48
+ const previewServerConnected = previewServerState.type === 'connected';
49
+ const { selected: rowSelected } = (0, TimelineSelection_1.useTimelineRowSelection)(track.nodePathInfo);
50
+ const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(track.nodePathInfo);
51
+ const layerStyle = (0, react_1.useMemo)(() => ({
52
+ height: (0, timeline_layout_1.getTimelineLayerHeight)(track.sequence.type),
53
+ marginBottom: timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
54
+ position: 'relative',
55
+ }), [track.sequence.type]);
56
+ const showExpandedKeyframes = track.nodePathInfo !== null &&
57
+ previewServerConnected &&
58
+ getIsExpanded(track.nodePathInfo);
59
+ const showRowHighlight = track.nodePathInfo !== null && (rowSelected || containsSelection);
60
+ return (jsx_runtime_1.jsxs("div", { children: [
61
+ jsx_runtime_1.jsxs("div", { style: layerStyle, children: [showRowHighlight ? (jsx_runtime_1.jsx("div", { style: TimelineSelection_1.TIMELINE_SELECTED_TRACK_HIGHLIGHT_STYLE })) : null, jsx_runtime_1.jsx(TimelineSequence_1.TimelineSequence, { s: track.sequence })
62
+ ] }), showExpandedKeyframes && track.nodePathInfo ? (jsx_runtime_1.jsx(TimelineExpandedTrackKeyframes_1.TimelineExpandedTrackKeyframes, { sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset })) : null] }));
63
+ };
64
+ exports.TimelineTrack = react_1.default.memo(TimelineTrackUnmemoized);
@@ -36,25 +36,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.TimelineTracks = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
38
  const react_1 = __importStar(require("react"));
39
- const client_id_1 = require("../../helpers/client-id");
40
39
  const timeline_layout_1 = require("../../helpers/timeline-layout");
41
- const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
42
40
  const MaxTimelineTracks_1 = require("./MaxTimelineTracks");
43
- const TimelineExpandedTrackKeyframes_1 = require("./TimelineExpandedTrackKeyframes");
44
- const TimelineSequence_1 = require("./TimelineSequence");
45
41
  const TimelineTimeIndicators_1 = require("./TimelineTimeIndicators");
42
+ const TimelineTrack_1 = require("./TimelineTrack");
46
43
  const content = {
47
44
  paddingLeft: timeline_layout_1.TIMELINE_PADDING,
48
45
  paddingRight: timeline_layout_1.TIMELINE_PADDING,
49
- paddingTop: 1,
50
46
  };
51
47
  const timelineContent = {
52
48
  minHeight: '100%',
53
49
  };
54
50
  const TimelineTracksInner = ({ timeline, hasBeenCut }) => {
55
- const { getIsExpanded } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksGetterContext);
56
- const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
57
- const previewServerConnected = previewServerState.type === 'connected';
58
51
  const timelineStyle = (0, react_1.useMemo)(() => {
59
52
  return {
60
53
  ...timelineContent,
@@ -63,13 +56,6 @@ const TimelineTracksInner = ({ timeline, hasBeenCut }) => {
63
56
  }, []);
64
57
  return (jsx_runtime_1.jsxs("div", { style: timelineStyle, children: [
65
58
  jsx_runtime_1.jsxs("div", { style: content, children: [
66
- jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePadding, {}), timeline.map((track) => {
67
- const isExpanded = track.nodePathInfo !== null && getIsExpanded(track.nodePathInfo);
68
- return (jsx_runtime_1.jsxs("div", { children: [
69
- jsx_runtime_1.jsx("div", { style: {
70
- height: (0, timeline_layout_1.getTimelineLayerHeight)(track.sequence.type),
71
- marginBottom: timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
72
- }, children: jsx_runtime_1.jsx(TimelineSequence_1.TimelineSequence, { s: track.sequence }) }), isExpanded && track.nodePathInfo && previewServerConnected ? (jsx_runtime_1.jsx(TimelineExpandedTrackKeyframes_1.TimelineExpandedTrackKeyframes, { sequence: track.sequence, nodePathInfo: track.nodePathInfo, keyframeDisplayOffset: track.keyframeDisplayOffset })) : null] }, track.sequence.id));
73
- })] }), hasBeenCut ? jsx_runtime_1.jsx(MaxTimelineTracks_1.MaxTimelineTracksReached, {}) : null] }));
59
+ jsx_runtime_1.jsx(TimelineTimeIndicators_1.TimelineTimePadding, {}), timeline.map((track) => (jsx_runtime_1.jsx(TimelineTrack_1.TimelineTrack, { track: track }, track.sequence.id)))] }), hasBeenCut ? jsx_runtime_1.jsx(MaxTimelineTracks_1.MaxTimelineTracksReached, {}) : null] }));
74
60
  };
75
61
  exports.TimelineTracks = react_1.default.memo(TimelineTracksInner);
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { CanUpdateSequencePropStatus } from 'remotion';
3
+ import type { SchemaFieldInfo, TimelineFieldOnDragValueChange, TimelineFieldOnSave } from '../../helpers/timeline-layout';
4
+ export declare const TimelineUvCoordinateField: React.FC<{
5
+ readonly field: SchemaFieldInfo;
6
+ readonly propStatus: CanUpdateSequencePropStatus;
7
+ readonly effectiveValue: unknown;
8
+ readonly onSave: TimelineFieldOnSave;
9
+ readonly onDragValueChange: TimelineFieldOnDragValueChange;
10
+ readonly onDragEnd: () => void;
11
+ }>;
@@ -0,0 +1,126 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimelineUvCoordinateField = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
6
+ const InputDragger_1 = require("../NewComposition/InputDragger");
7
+ const timeline_field_utils_1 = require("./timeline-field-utils");
8
+ const leftDraggerStyle = {
9
+ paddingLeft: 0,
10
+ };
11
+ const rightDraggerStyle = {
12
+ paddingRight: 0,
13
+ };
14
+ const containerStyle = {
15
+ display: 'flex',
16
+ gap: 4,
17
+ };
18
+ const parseUvCoordinate = (value) => {
19
+ if (Array.isArray(value) &&
20
+ value.length === 2 &&
21
+ value.every((item) => typeof item === 'number' && Number.isFinite(item))) {
22
+ return [value[0], value[1]];
23
+ }
24
+ return [0, 0];
25
+ };
26
+ const tuplesEqual = (left, right) => {
27
+ if (!Array.isArray(left) || left.length !== 2) {
28
+ return false;
29
+ }
30
+ return left[0] === right[0] && left[1] === right[1];
31
+ };
32
+ const TimelineUvCoordinateField = ({ field, propStatus, effectiveValue, onSave, onDragValueChange, onDragEnd, }) => {
33
+ var _a, _b, _c;
34
+ const [dragX, setDragX] = (0, react_1.useState)(null);
35
+ const [dragY, setDragY] = (0, react_1.useState)(null);
36
+ const [codeX, codeY] = (0, react_1.useMemo)(() => parseUvCoordinate(effectiveValue), [effectiveValue]);
37
+ const step = field.fieldSchema.type === 'uv-coordinate'
38
+ ? ((_a = field.fieldSchema.step) !== null && _a !== void 0 ? _a : 0.01)
39
+ : 0.01;
40
+ const min = field.fieldSchema.type === 'uv-coordinate'
41
+ ? ((_b = field.fieldSchema.min) !== null && _b !== void 0 ? _b : -Infinity)
42
+ : -Infinity;
43
+ const max = field.fieldSchema.type === 'uv-coordinate'
44
+ ? ((_c = field.fieldSchema.max) !== null && _c !== void 0 ? _c : Infinity)
45
+ : Infinity;
46
+ const stepDecimals = (0, react_1.useMemo)(() => (0, timeline_field_utils_1.getDecimalPlaces)(step), [step]);
47
+ const formatter = (0, react_1.useCallback)((v) => {
48
+ const num = Number(v);
49
+ const digits = Math.max(stepDecimals, (0, timeline_field_utils_1.getDecimalPlaces)(num));
50
+ return digits === 0 ? String(num) : num.toFixed(digits);
51
+ }, [stepDecimals]);
52
+ const onXChange = (0, react_1.useCallback)((newVal) => {
53
+ setDragX(newVal);
54
+ const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
55
+ onDragValueChange([newVal, currentY]);
56
+ }, [onDragValueChange, dragY, codeY]);
57
+ const onXChangeEnd = (0, react_1.useCallback)((newVal) => {
58
+ const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
59
+ const newTuple = [newVal, currentY];
60
+ if (propStatus.canUpdate &&
61
+ !tuplesEqual(propStatus.codeValue, newTuple)) {
62
+ onSave(newTuple).finally(() => {
63
+ setDragX(null);
64
+ onDragEnd();
65
+ });
66
+ }
67
+ else {
68
+ setDragX(null);
69
+ onDragEnd();
70
+ }
71
+ }, [dragY, codeY, propStatus, onSave, onDragEnd]);
72
+ const onXTextChange = (0, react_1.useCallback)((newVal) => {
73
+ if (propStatus.canUpdate) {
74
+ const parsed = Number(newVal);
75
+ if (!Number.isNaN(parsed)) {
76
+ const currentY = dragY !== null && dragY !== void 0 ? dragY : codeY;
77
+ const newTuple = [parsed, currentY];
78
+ if (!tuplesEqual(propStatus.codeValue, newTuple)) {
79
+ setDragX(parsed);
80
+ onSave(newTuple).finally(() => {
81
+ setDragX(null);
82
+ });
83
+ }
84
+ }
85
+ }
86
+ }, [propStatus, dragY, codeY, onSave]);
87
+ const onYChange = (0, react_1.useCallback)((newVal) => {
88
+ setDragY(newVal);
89
+ const currentX = dragX !== null && dragX !== void 0 ? dragX : codeX;
90
+ onDragValueChange([currentX, newVal]);
91
+ }, [onDragValueChange, dragX, codeX]);
92
+ const onYChangeEnd = (0, react_1.useCallback)((newVal) => {
93
+ const currentX = dragX !== null && dragX !== void 0 ? dragX : codeX;
94
+ const newTuple = [currentX, newVal];
95
+ if (propStatus.canUpdate &&
96
+ !tuplesEqual(propStatus.codeValue, newTuple)) {
97
+ onSave(newTuple).finally(() => {
98
+ setDragY(null);
99
+ onDragEnd();
100
+ });
101
+ }
102
+ else {
103
+ setDragY(null);
104
+ onDragEnd();
105
+ }
106
+ }, [dragX, codeX, propStatus, onSave, onDragEnd]);
107
+ const onYTextChange = (0, react_1.useCallback)((newVal) => {
108
+ if (propStatus.canUpdate) {
109
+ const parsed = Number(newVal);
110
+ if (!Number.isNaN(parsed)) {
111
+ const currentX = dragX !== null && dragX !== void 0 ? dragX : codeX;
112
+ const newTuple = [currentX, parsed];
113
+ if (!tuplesEqual(propStatus.codeValue, newTuple)) {
114
+ setDragY(parsed);
115
+ onSave(newTuple).finally(() => {
116
+ setDragY(null);
117
+ });
118
+ }
119
+ }
120
+ }
121
+ }, [propStatus, onSave, dragX, codeX]);
122
+ return (jsx_runtime_1.jsxs("span", { style: containerStyle, children: [
123
+ jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragX !== null && dragX !== void 0 ? dragX : codeX, style: leftDraggerStyle, status: "ok", small: true, onValueChange: onXChange, onValueChangeEnd: onXChangeEnd, onTextChange: onXTextChange, min: min, max: max, step: step, formatter: formatter, rightAlign: false }), jsx_runtime_1.jsx("div", { style: { marginLeft: -6, marginRight: -6 } }), jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: dragY !== null && dragY !== void 0 ? dragY : codeY, style: rightDraggerStyle, status: "ok", small: true, onValueChange: onYChange, onValueChangeEnd: onYChangeEnd, onTextChange: onYTextChange, min: min, max: max, step: step, formatter: formatter, rightAlign: false })
124
+ ] }));
125
+ };
126
+ exports.TimelineUvCoordinateField = TimelineUvCoordinateField;
@@ -8,7 +8,6 @@ const remotion_1 = require("remotion");
8
8
  const timeline_layout_1 = require("../../helpers/timeline-layout");
9
9
  const AudioWaveform_1 = require("../AudioWaveform");
10
10
  const get_timeline_video_info_widths_1 = require("./get-timeline-video-info-widths");
11
- const FILMSTRIP_HEIGHT = 48;
12
11
  const outerStyle = {
13
12
  width: '100%',
14
13
  height: '100%',
@@ -16,7 +15,7 @@ const outerStyle = {
16
15
  flexDirection: 'column',
17
16
  };
18
17
  const filmstripContainerStyle = {
19
- height: FILMSTRIP_HEIGHT,
18
+ height: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
20
19
  backgroundColor: 'rgba(0, 0, 0, 0.3)',
21
20
  display: 'flex',
22
21
  borderTopLeftRadius: 2,
@@ -48,7 +47,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
48
47
  const controller = new AbortController();
49
48
  const canvas = document.createElement('canvas');
50
49
  canvas.width = mediaVisualizationWidth;
51
- canvas.height = FILMSTRIP_HEIGHT;
50
+ canvas.height = timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT;
52
51
  const ctx = canvas.getContext('2d');
53
52
  if (!ctx) {
54
53
  return;
@@ -103,7 +102,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
103
102
  fromSeconds,
104
103
  toSeconds,
105
104
  aspectRatio: aspectRatio.current,
106
- frameHeight: FILMSTRIP_HEIGHT,
105
+ frameHeight: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
107
106
  });
108
107
  (0, timeline_utils_1.fillWithCachedFrames)({
109
108
  ctx: targetCtx,
@@ -113,7 +112,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
113
112
  segmentDuration: toSeconds - fromSeconds,
114
113
  fromSeconds,
115
114
  devicePixelRatio: window.devicePixelRatio,
116
- frameHeight: FILMSTRIP_HEIGHT,
115
+ frameHeight: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
117
116
  });
118
117
  repeatTarget();
119
118
  const unfilled = Array.from(filledSlots.keys()).filter((timestamp) => !filledSlots.get(timestamp));
@@ -134,7 +133,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
134
133
  toSeconds,
135
134
  naturalWidth: targetWidth,
136
135
  aspectRatio: aspectRatio.current,
137
- frameHeight: FILMSTRIP_HEIGHT,
136
+ frameHeight: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
138
137
  });
139
138
  return Array.from(filledSlots.keys()).map((timestamp) => timestamp / timeline_utils_1.WEBCODECS_TIMESCALE);
140
139
  },
@@ -143,7 +142,8 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
143
142
  let frame;
144
143
  try {
145
144
  frame = sample.toVideoFrame();
146
- const scale = (FILMSTRIP_HEIGHT / frame.displayHeight) * window.devicePixelRatio;
145
+ const scale = (timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT / frame.displayHeight) *
146
+ window.devicePixelRatio;
147
147
  const transformed = (0, timeline_utils_1.resizeVideoFrame)({
148
148
  frame,
149
149
  scale,
@@ -163,7 +163,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
163
163
  toSeconds,
164
164
  naturalWidth: targetWidth,
165
165
  aspectRatio: aspectRatio.current,
166
- frameHeight: FILMSTRIP_HEIGHT,
166
+ frameHeight: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
167
167
  });
168
168
  (0, timeline_utils_1.fillFrameWhereItFits)({
169
169
  ctx: targetCtx,
@@ -173,7 +173,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
173
173
  segmentDuration: toSeconds - fromSeconds,
174
174
  fromSeconds,
175
175
  devicePixelRatio: window.devicePixelRatio,
176
- frameHeight: FILMSTRIP_HEIGHT,
176
+ frameHeight: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
177
177
  });
178
178
  repeatTarget();
179
179
  }
@@ -201,7 +201,7 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
201
201
  segmentDuration: toSeconds - fromSeconds,
202
202
  fromSeconds,
203
203
  devicePixelRatio: window.devicePixelRatio,
204
- frameHeight: FILMSTRIP_HEIGHT,
204
+ frameHeight: timeline_layout_1.TIMELINE_LAYER_FILMSTRIP_HEIGHT,
205
205
  });
206
206
  repeatTarget();
207
207
  })
@@ -233,14 +233,13 @@ const TimelineVideoInfo = ({ src, visualizationWidth, naturalWidth, trimBefore,
233
233
  }, [mediaVisualizationWidth, premountWidth]);
234
234
  const audioStyle = (0, react_1.useMemo)(() => {
235
235
  return {
236
- height: timeline_layout_1.TIMELINE_VIDEO_INFO_WAVEFORM_HEIGHT,
237
236
  width: audioWidth,
238
237
  position: 'relative',
239
238
  marginLeft: premountWidth,
240
239
  };
241
240
  }, [audioWidth, premountWidth]);
242
241
  return (jsx_runtime_1.jsxs("div", { style: outerStyle, children: [
243
- jsx_runtime_1.jsx("div", { ref: ref, style: filmstripStyle }), jsx_runtime_1.jsx("div", { style: audioStyle, children: jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: src, visualizationWidth: audioWidth, startFrom: trimBefore, durationInFrames: durationInFrames, volume: volume, doesVolumeChange: doesVolumeChange, playbackRate: playbackRate, loopDisplay: loopDisplay }) })
242
+ jsx_runtime_1.jsx("div", { ref: ref, style: filmstripStyle }), jsx_runtime_1.jsx("div", { style: audioStyle, children: jsx_runtime_1.jsx(AudioWaveform_1.AudioWaveform, { src: src, height: timeline_layout_1.TIMELINE_VIDEO_INFO_WAVEFORM_HEIGHT, visualizationWidth: audioWidth, startFrom: trimBefore, durationInFrames: durationInFrames, volume: volume, doesVolumeChange: doesVolumeChange, playbackRate: playbackRate, loopDisplay: loopDisplay }) })
244
243
  ] }));
245
244
  };
246
245
  exports.TimelineVideoInfo = TimelineVideoInfo;
@@ -0,0 +1,11 @@
1
+ import { type CodeValues, type SequencePropsSubscriptionKey } from 'remotion';
2
+ import type { TimelineTreeNode } from '../../helpers/timeline-layout';
3
+ export declare const getNodeKeyframes: ({ node, nodePath, codeValues, keyframeDisplayOffset, }: {
4
+ node: TimelineTreeNode;
5
+ nodePath: SequencePropsSubscriptionKey;
6
+ codeValues: CodeValues;
7
+ keyframeDisplayOffset: number;
8
+ }) => {
9
+ frame: number;
10
+ value: unknown;
11
+ }[];
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getNodeKeyframes = void 0;
4
+ const remotion_1 = require("remotion");
5
+ const get_timeline_keyframes_1 = require("./get-timeline-keyframes");
6
+ const getNodeKeyframes = ({ node, nodePath, codeValues, keyframeDisplayOffset, }) => {
7
+ var _a, _b;
8
+ if (node.kind !== 'field' || node.field === null) {
9
+ return [];
10
+ }
11
+ if (node.field.kind === 'sequence-field') {
12
+ return (0, get_timeline_keyframes_1.getTimelineKeyframes)((_a = remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)) === null || _a === void 0 ? void 0 : _a[node.field.key], keyframeDisplayOffset);
13
+ }
14
+ const effectStatus = remotion_1.Internals.getEffectCodeValuesCtx({
15
+ codeValues,
16
+ nodePath,
17
+ effectIndex: node.field.effectIndex,
18
+ });
19
+ return (0, get_timeline_keyframes_1.getTimelineKeyframes)(effectStatus.type === 'can-update-effect'
20
+ ? (_b = effectStatus.props) === null || _b === void 0 ? void 0 : _b[node.field.key]
21
+ : null, keyframeDisplayOffset);
22
+ };
23
+ exports.getNodeKeyframes = getNodeKeyframes;
@@ -2,22 +2,20 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getTimelineKeyframes = exports.getComputedStatusLabel = void 0;
4
4
  const getComputedStatusLabel = (propStatus) => {
5
- var _a;
6
- if (propStatus.reason !== 'computed') {
7
- throw new Error(`Unsupported prop status: ${propStatus.reason}`);
5
+ if (propStatus.reason === 'computed') {
6
+ return 'computed';
8
7
  }
9
- return ((_a = propStatus.keyframes) === null || _a === void 0 ? void 0 : _a.length) ? 'keyframed' : 'computed';
8
+ return 'keyframed';
10
9
  };
11
10
  exports.getComputedStatusLabel = getComputedStatusLabel;
12
11
  const getTimelineKeyframes = (propStatus, keyframeDisplayOffset = 0) => {
13
- var _a;
14
12
  if (!propStatus || propStatus.canUpdate) {
15
13
  return [];
16
14
  }
17
- if (propStatus.reason !== 'computed') {
18
- throw new Error(`Unsupported prop status: ${propStatus.reason}`);
15
+ if (propStatus.reason === 'computed') {
16
+ return [];
19
17
  }
20
- const keyframes = (_a = propStatus.keyframes) !== null && _a !== void 0 ? _a : [];
18
+ const { keyframes } = propStatus;
21
19
  if (keyframeDisplayOffset === 0) {
22
20
  return keyframes;
23
21
  }