@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
@@ -4,23 +4,32 @@ exports.TimelineListItem = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const remotion_1 = require("remotion");
7
+ const no_react_1 = require("remotion/no-react");
7
8
  const client_id_1 = require("../../helpers/client-id");
8
- const colors_1 = require("../../helpers/colors");
9
9
  const timeline_layout_1 = require("../../helpers/timeline-layout");
10
10
  const call_api_1 = require("../call-api");
11
11
  const ContextMenu_1 = require("../ContextMenu");
12
12
  const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
13
13
  const NotificationCenter_1 = require("../Notifications/NotificationCenter");
14
14
  const save_sequence_prop_1 = require("./save-sequence-prop");
15
- const timeline_row_layout_1 = require("./timeline-row-layout");
16
15
  const TimelineExpandArrowButton_1 = require("./TimelineExpandArrowButton");
17
16
  const TimelineExpandedSection_1 = require("./TimelineExpandedSection");
17
+ const TimelineItemStack_1 = require("./TimelineItemStack");
18
18
  const TimelineLayerEye_1 = require("./TimelineLayerEye");
19
19
  const TimelineMediaInfo_1 = require("./TimelineMediaInfo");
20
20
  const TimelineRowChrome_1 = require("./TimelineRowChrome");
21
- const TimelineStack_1 = require("./TimelineStack");
22
- const use_resolved_stack_react_to_change_1 = require("./use-resolved-stack-react-to-change");
23
- const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) => {
21
+ const TimelineSelection_1 = require("./TimelineSelection");
22
+ const TimelineSequenceName_1 = require("./TimelineSequenceName");
23
+ const use_open_sequence_in_editor_1 = require("./use-open-sequence-in-editor");
24
+ const labelContainerStyle = {
25
+ alignItems: 'center',
26
+ alignSelf: 'stretch',
27
+ display: 'flex',
28
+ flexDirection: 'row',
29
+ minWidth: 0,
30
+ gap: 4,
31
+ };
32
+ const TimelineListItem = ({ nestedDepth, sequence, nodePathInfo }) => {
24
33
  var _a;
25
34
  var _b;
26
35
  const nodePath = (_b = nodePathInfo === null || nodePathInfo === void 0 ? void 0 : nodePathInfo.sequenceSubscriptionKey) !== null && _b !== void 0 ? _b : null;
@@ -30,7 +39,10 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
30
39
  const { toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksSetterContext);
31
40
  const { codeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeCodeValuesContext);
32
41
  const { setCodeValues } = (0, react_1.useContext)(remotion_1.Internals.VisualModeSettersContext);
33
- const originalLocation = (0, use_resolved_stack_react_to_change_1.useResolveStackAndReactToChange)(sequence.getStack);
42
+ const { setCanvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionSetters);
43
+ const { onSelect, selectable, selected } = (0, TimelineSelection_1.useTimelineRowSelection)(nodePathInfo);
44
+ const containsSelection = (0, TimelineSelection_1.useTimelineRowContainsSelection)(nodePathInfo);
45
+ const { canOpenInEditor, openInEditor, originalLocation } = (0, use_open_sequence_in_editor_1.useOpenSequenceInEditor)(sequence);
34
46
  const validatedLocation = (0, react_1.useMemo)(() => {
35
47
  var _a;
36
48
  if (!originalLocation ||
@@ -105,11 +117,73 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
105
117
  (0, NotificationCenter_1.showNotification)(err.message, 4000);
106
118
  }
107
119
  }, [nodePath, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source, nodePathInfo]);
120
+ const mediaSrc = sequence.type === 'audio' ||
121
+ sequence.type === 'video' ||
122
+ sequence.type === 'image'
123
+ ? sequence.src
124
+ : null;
125
+ const assetLinkInfo = (0, react_1.useMemo)(() => (mediaSrc ? (0, TimelineMediaInfo_1.getTimelineAssetLinkInfo)(mediaSrc) : null), [mediaSrc]);
108
126
  const contextMenuValues = (0, react_1.useMemo)(() => {
109
127
  if (!previewConnected) {
110
128
  return [];
111
129
  }
130
+ const editorName = window.remotion_editorName;
131
+ const { documentationLink } = sequence;
112
132
  return [
133
+ editorName
134
+ ? {
135
+ type: 'item',
136
+ id: 'show-in-editor',
137
+ keyHint: null,
138
+ label: `Show in ${editorName}`,
139
+ leftItem: null,
140
+ disabled: !canOpenInEditor,
141
+ onClick: () => {
142
+ openInEditor();
143
+ },
144
+ quickSwitcherLabel: null,
145
+ subMenu: null,
146
+ value: 'show-in-editor',
147
+ }
148
+ : null,
149
+ documentationLink
150
+ ? {
151
+ type: 'item',
152
+ id: 'open-component-docs',
153
+ keyHint: null,
154
+ label: 'Open component docs',
155
+ leftItem: null,
156
+ disabled: false,
157
+ onClick: () => {
158
+ window.open(documentationLink, '_blank', 'noopener,noreferrer');
159
+ },
160
+ quickSwitcherLabel: null,
161
+ subMenu: null,
162
+ value: 'open-component-docs',
163
+ }
164
+ : null,
165
+ assetLinkInfo
166
+ ? {
167
+ type: 'item',
168
+ id: 'show-asset',
169
+ keyHint: null,
170
+ label: 'Show asset',
171
+ leftItem: null,
172
+ disabled: false,
173
+ onClick: () => {
174
+ (0, TimelineMediaInfo_1.openTimelineAssetLink)(assetLinkInfo, setCanvasContent);
175
+ },
176
+ quickSwitcherLabel: null,
177
+ subMenu: null,
178
+ value: 'show-asset',
179
+ }
180
+ : null,
181
+ documentationLink
182
+ ? {
183
+ type: 'divider',
184
+ id: 'open-component-docs-divider',
185
+ }
186
+ : null,
113
187
  {
114
188
  type: 'item',
115
189
  id: 'duplicate-sequence',
@@ -144,13 +218,18 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
144
218
  subMenu: null,
145
219
  value: 'delete-sequence',
146
220
  },
147
- ];
221
+ ].filter(no_react_1.NoReactInternals.truthy);
148
222
  }, [
223
+ assetLinkInfo,
149
224
  deleteDisabled,
150
225
  duplicateDisabled,
151
226
  onDeleteSequenceFromSource,
152
227
  onDuplicateSequenceFromSource,
228
+ canOpenInEditor,
229
+ openInEditor,
153
230
  previewConnected,
231
+ sequence,
232
+ setCanvasContent,
154
233
  ]);
155
234
  const isExpanded = previewConnected && nodePathInfo !== null && getIsExpanded(nodePathInfo);
156
235
  const onToggleExpand = (0, react_1.useCallback)(() => {
@@ -159,6 +238,13 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
159
238
  }
160
239
  toggleTrack(nodePathInfo);
161
240
  }, [nodePathInfo, toggleTrack]);
241
+ const onShowInEditorDoubleClick = (0, react_1.useCallback)((e) => {
242
+ if (!TimelineSelection_1.SELECTION_ENABLED || !canOpenInEditor) {
243
+ return;
244
+ }
245
+ e.stopPropagation();
246
+ openInEditor();
247
+ }, [canOpenInEditor, openInEditor]);
162
248
  const codeValuesForOverride = (0, react_1.useMemo)(() => {
163
249
  return nodePath
164
250
  ? remotion_1.Internals.getCodeValuesCtx(codeValues, nodePath)
@@ -209,14 +295,7 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
209
295
  setCodeValues,
210
296
  validatedLocation,
211
297
  ]);
212
- const outer = (0, react_1.useMemo)(() => {
213
- return {
214
- height: (0, timeline_layout_1.getTimelineLayerHeight)(sequence.type) + timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
215
- borderBottom: `1px solid ${colors_1.TIMELINE_TRACK_SEPARATOR}`,
216
- display: 'flex',
217
- flexDirection: 'column',
218
- };
219
- }, [sequence.type]);
298
+ const outerHeight = (0, react_1.useMemo)(() => (0, timeline_layout_1.getTimelineLayerHeight)(sequence.type) + timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM, [sequence.type]);
220
299
  const inner = (0, react_1.useMemo)(() => {
221
300
  return {
222
301
  height: timeline_layout_1.TIMELINE_LIST_ITEM_ROW_HEIGHT,
@@ -227,20 +306,6 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
227
306
  flexShrink: 0,
228
307
  };
229
308
  }, []);
230
- const mediaInfoStyle = (0, react_1.useMemo)(() => {
231
- return {
232
- paddingLeft: (0, timeline_row_layout_1.getTimelineRowLeftChromeWidth)(nestedDepth),
233
- paddingRight: 8,
234
- marginTop: -6,
235
- overflow: 'hidden',
236
- minHeight: 0,
237
- };
238
- }, [nestedDepth]);
239
- const mediaSrc = sequence.type === 'audio' ||
240
- sequence.type === 'video' ||
241
- sequence.type === 'image'
242
- ? sequence.src
243
- : null;
244
309
  const hasExpandableContent = Boolean(sequence.controls) || sequence.effects.length > 0;
245
310
  const canToggleVisibility = previewConnected &&
246
311
  Boolean(sequence.controls) &&
@@ -249,8 +314,12 @@ const TimelineListItem = ({ nestedDepth, sequence, isCompact, nodePathInfo }) =>
249
314
  codeHiddenStatus !== undefined &&
250
315
  codeHiddenStatus !== null &&
251
316
  codeHiddenStatus.canUpdate;
252
- const trackRow = (jsx_runtime_1.jsxs("div", { style: outer, children: [jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent ? (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: !previewConnected || nodePathInfo === null })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: inner, children: jsx_runtime_1.jsx(TimelineStack_1.TimelineStack, { sequence: sequence, isCompact: isCompact, originalLocation: originalLocation }) }), mediaSrc ? (jsx_runtime_1.jsx("div", { style: mediaInfoStyle, children: jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc, type: sequence.type }) })) : null] }));
253
- return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, children: trackRow })) : (trackRow), previewConnected &&
317
+ const trackRow = (jsx_runtime_1.jsx(TimelineRowChrome_1.TimelineRowChrome, { depth: nestedDepth, eye: canToggleVisibility ? (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility })) : (jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEyeSpacer, {})), arrow: hasExpandableContent ? (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowButton, { isExpanded: isExpanded, onClick: onToggleExpand, label: "track properties", disabled: !previewConnected || nodePathInfo === null })) : (jsx_runtime_1.jsx(TimelineExpandArrowButton_1.TimelineExpandArrowSpacer, {})), style: inner, selected: selected, selectable: selectable, onSelect: onSelect, showSelectedBackground: true, containsSelection: containsSelection, outerHeight: outerHeight, onDoubleClick: TimelineSelection_1.SELECTION_ENABLED && canOpenInEditor
318
+ ? onShowInEditorDoubleClick
319
+ : undefined, children: jsx_runtime_1.jsxs("div", { style: labelContainerStyle, children: [
320
+ jsx_runtime_1.jsx(TimelineSequenceName_1.TimelineSequenceName, { sequence: sequence, selected: selected, containsSelection: containsSelection }), mediaSrc ? jsx_runtime_1.jsx(TimelineMediaInfo_1.TimelineMediaInfo, { src: mediaSrc }) : null, jsx_runtime_1.jsx(TimelineItemStack_1.TimelineItemStack, { originalLocation: originalLocation })
321
+ ] }) }));
322
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [previewConnected ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, onOpen: selectable ? onSelect : null, children: trackRow })) : (trackRow), previewConnected &&
254
323
  isExpanded &&
255
324
  hasExpandableContent &&
256
325
  nodePathInfo &&
@@ -1,5 +1,17 @@
1
1
  import React from 'react';
2
+ type LinkInfo = {
3
+ kind: 'local';
4
+ assetPath: string;
5
+ title: string;
6
+ } | {
7
+ kind: 'remote';
8
+ href: string;
9
+ title: string;
10
+ } | null;
11
+ export type TimelineAssetLinkInfo = Exclude<LinkInfo, null>;
12
+ export declare const getTimelineAssetLinkInfo: (src: string) => LinkInfo;
13
+ export declare const openTimelineAssetLink: (linkInfo: TimelineAssetLinkInfo, setCanvasContent: React.Dispatch<React.SetStateAction<import("remotion").CanvasContent | null>>) => void;
2
14
  export declare const TimelineMediaInfo: React.FC<{
3
15
  readonly src: string;
4
- readonly type: 'audio' | 'video' | 'image';
5
16
  }>;
17
+ export {};
@@ -33,25 +33,13 @@ var __importStar = (this && this.__importStar) || (function () {
33
33
  };
34
34
  })();
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.TimelineMediaInfo = void 0;
36
+ exports.TimelineMediaInfo = exports.openTimelineAssetLink = exports.getTimelineAssetLinkInfo = void 0;
37
37
  const jsx_runtime_1 = require("react/jsx-runtime");
38
- const media_utils_1 = require("@remotion/media-utils");
39
38
  const react_1 = __importStar(require("react"));
40
39
  const remotion_1 = require("remotion");
41
40
  const colors_1 = require("../../helpers/colors");
42
- const format_media_duration_1 = require("../../helpers/format-media-duration");
43
41
  const url_state_1 = require("../../helpers/url-state");
44
- const use_media_metadata_1 = require("../../helpers/use-media-metadata");
45
- const containerStyle = {
46
- fontFamily: 'Arial, Helvetica, sans-serif',
47
- fontSize: 12,
48
- lineHeight: 1,
49
- overflow: 'hidden',
50
- whiteSpace: 'nowrap',
51
- textOverflow: 'ellipsis',
52
- minWidth: 0,
53
- marginTop: 2,
54
- };
42
+ const TimelineSelection_1 = require("./TimelineSelection");
55
43
  const lineStyle = {
56
44
  whiteSpace: 'nowrap',
57
45
  overflow: 'hidden',
@@ -59,9 +47,9 @@ const lineStyle = {
59
47
  minWidth: 0,
60
48
  fontSize: 12,
61
49
  color: colors_1.VERY_LIGHT_TEXT,
62
- lineHeight: 1.3,
50
+ display: 'inline-block',
63
51
  };
64
- const getLinkInfo = (src) => {
52
+ const getTimelineAssetLinkInfo = (src) => {
65
53
  const staticBase = typeof window === 'undefined' ? null : window.remotion_staticBase;
66
54
  if (staticBase && src.startsWith(staticBase + '/')) {
67
55
  const assetPath = src.slice(staticBase.length + 1);
@@ -84,90 +72,55 @@ const getLinkInfo = (src) => {
84
72
  }
85
73
  return null;
86
74
  };
75
+ exports.getTimelineAssetLinkInfo = getTimelineAssetLinkInfo;
76
+ const openTimelineAssetLink = (linkInfo, setCanvasContent) => {
77
+ if (linkInfo.kind === 'local') {
78
+ setCanvasContent({ type: 'asset', asset: linkInfo.assetPath });
79
+ (0, url_state_1.pushUrl)(`/assets/${linkInfo.assetPath}`);
80
+ return;
81
+ }
82
+ window.open(linkInfo.href, '_blank', 'noopener,noreferrer');
83
+ };
84
+ exports.openTimelineAssetLink = openTimelineAssetLink;
87
85
  const useAssetLink = (src) => {
88
86
  const { setCanvasContent } = react_1.default.useContext(remotion_1.Internals.CompositionSetters);
89
87
  const [hovered, setHovered] = (0, react_1.useState)(false);
90
- const linkInfo = (0, react_1.useMemo)(() => getLinkInfo(src), [src]);
88
+ const linkInfo = (0, react_1.useMemo)(() => (0, exports.getTimelineAssetLinkInfo)(src), [src]);
89
+ const interactive = !TimelineSelection_1.SELECTION_ENABLED && linkInfo !== null;
91
90
  const onClick = (0, react_1.useCallback)((e) => {
92
91
  if (!linkInfo) {
93
92
  return;
94
93
  }
95
94
  e.preventDefault();
96
95
  e.stopPropagation();
97
- if (linkInfo.kind === 'local') {
98
- setCanvasContent({ type: 'asset', asset: linkInfo.assetPath });
99
- (0, url_state_1.pushUrl)(`/assets/${linkInfo.assetPath}`);
100
- return;
101
- }
102
- window.open(linkInfo.href, '_blank', 'noopener,noreferrer');
96
+ (0, exports.openTimelineAssetLink)(linkInfo, setCanvasContent);
103
97
  }, [linkInfo, setCanvasContent]);
104
98
  const onPointerEnter = (0, react_1.useCallback)(() => setHovered(true), []);
105
99
  const onPointerLeave = (0, react_1.useCallback)(() => setHovered(false), []);
106
100
  const fileNameStyle = (0, react_1.useMemo)(() => ({
107
101
  ...lineStyle,
108
- color: linkInfo && hovered ? colors_1.LIGHT_TEXT : colors_1.VERY_LIGHT_TEXT,
109
- cursor: linkInfo ? 'pointer' : undefined,
102
+ color: interactive && hovered ? colors_1.LIGHT_TEXT : colors_1.VERY_LIGHT_TEXT,
103
+ cursor: interactive ? 'pointer' : undefined,
110
104
  textDecoration: 'none',
111
105
  display: 'inline-block',
112
106
  overflow: 'hidden',
113
107
  whiteSpace: 'pre',
114
108
  textOverflow: 'ellipsis',
115
- }), [linkInfo, hovered]);
116
- return { linkInfo, onClick, onPointerEnter, onPointerLeave, fileNameStyle };
109
+ userSelect: 'none',
110
+ WebkitUserSelect: 'none',
111
+ }), [interactive, hovered]);
112
+ return {
113
+ linkInfo,
114
+ interactive,
115
+ onClick,
116
+ onPointerEnter,
117
+ onPointerLeave,
118
+ fileNameStyle,
119
+ };
117
120
  };
118
- const TimelineMediaInfo = ({ src, type }) => {
119
- // Images aren't supported by mediabunny, so don't even try.
120
- const metadata = (0, use_media_metadata_1.useMediaMetadata)(type === 'image' ? null : src);
121
+ const TimelineMediaInfo = ({ src }) => {
121
122
  const fileName = (0, react_1.useMemo)(() => remotion_1.Internals.getAssetDisplayName(src), [src]);
122
- const { linkInfo, onClick, onPointerEnter, onPointerLeave, fileNameStyle } = useAssetLink(src);
123
- const [imageDimensions, setImageDimensions] = (0, react_1.useState)(null);
124
- (0, react_1.useEffect)(() => {
125
- if (type !== 'image') {
126
- return;
127
- }
128
- let cancelled = false;
129
- setImageDimensions(null);
130
- (0, media_utils_1.getImageDimensions)(src)
131
- .then((dims) => {
132
- if (cancelled) {
133
- return;
134
- }
135
- setImageDimensions({ width: dims.width, height: dims.height });
136
- })
137
- .catch(() => {
138
- // Non-image or load failure — ignore silently.
139
- });
140
- return () => {
141
- cancelled = true;
142
- };
143
- }, [src, type]);
144
- const detailsLine = (0, react_1.useMemo)(() => {
145
- if (type === 'image') {
146
- if (!imageDimensions) {
147
- return null;
148
- }
149
- return `${imageDimensions.width}x${imageDimensions.height}`;
150
- }
151
- if (!metadata) {
152
- return null;
153
- }
154
- const parts = [];
155
- if (metadata.format) {
156
- parts.push(metadata.format);
157
- }
158
- if (type === 'video' && metadata.videoCodec) {
159
- parts.push(metadata.videoCodec);
160
- }
161
- if (metadata.audioCodec) {
162
- parts.push(metadata.audioCodec);
163
- }
164
- if (metadata.width !== null && metadata.height !== null) {
165
- parts.push(`${metadata.width}x${metadata.height}`);
166
- }
167
- parts.push((0, format_media_duration_1.formatMediaDuration)(metadata.duration));
168
- return parts.join(' · ');
169
- }, [imageDimensions, metadata, type]);
170
- return (jsx_runtime_1.jsxs("div", { style: containerStyle, children: [
171
- jsx_runtime_1.jsx("div", { style: fileNameStyle, title: linkInfo ? linkInfo.title : fileName, onClick: linkInfo ? onClick : undefined, onPointerEnter: linkInfo ? onPointerEnter : undefined, onPointerLeave: linkInfo ? onPointerLeave : undefined, children: fileName }), detailsLine ? (jsx_runtime_1.jsx("div", { style: lineStyle, title: detailsLine, children: detailsLine })) : null] }));
123
+ const { linkInfo, interactive, onClick, onPointerEnter, onPointerLeave, fileNameStyle, } = useAssetLink(src);
124
+ return (jsx_runtime_1.jsx("div", { style: fileNameStyle, title: linkInfo ? linkInfo.title : fileName, onClick: interactive ? onClick : undefined, onPointerEnter: interactive ? onPointerEnter : undefined, onPointerLeave: interactive ? onPointerLeave : undefined, children: fileName }));
172
125
  };
173
126
  exports.TimelineMediaInfo = TimelineMediaInfo;
@@ -4,5 +4,12 @@ export declare const TimelineRowChrome: React.FC<{
4
4
  readonly eye: React.ReactNode;
5
5
  readonly arrow: React.ReactNode;
6
6
  readonly children: React.ReactNode;
7
- readonly style?: React.CSSProperties;
7
+ readonly style: React.CSSProperties;
8
+ readonly selected: boolean;
9
+ readonly selectable: boolean;
10
+ readonly onSelect: () => void;
11
+ readonly showSelectedBackground: boolean;
12
+ readonly containsSelection: boolean;
13
+ readonly outerHeight: number | null;
14
+ readonly onDoubleClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
8
15
  }>;
@@ -3,19 +3,59 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.TimelineRowChrome = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
+ const colors_1 = require("../../helpers/colors");
6
7
  const Padder_1 = require("./Padder");
7
8
  const timeline_row_layout_1 = require("./timeline-row-layout");
9
+ const TimelineSelection_1 = require("./TimelineSelection");
8
10
  const rowBase = {
11
+ alignItems: 'stretch',
9
12
  display: 'flex',
13
+ };
14
+ const chromeColumnStyle = {
10
15
  alignItems: 'center',
16
+ alignSelf: 'stretch',
17
+ display: 'flex',
18
+ flexShrink: 0,
19
+ paddingLeft: timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING,
11
20
  };
12
- const TimelineRowChrome = ({ depth, eye, arrow, children, style }) => {
13
- const rowStyle = (0, react_1.useMemo)(() => ({
21
+ const TimelineRowChrome = ({ depth, eye, arrow, children, style, selected, selectable, onSelect, showSelectedBackground, containsSelection, outerHeight, onDoubleClick, }) => {
22
+ const indentWidth = (0, timeline_row_layout_1.getTimelineRowIndentWidth)(depth);
23
+ const onPointerDown = (0, react_1.useCallback)((e) => {
24
+ if (e.button === 0) {
25
+ e.stopPropagation();
26
+ onSelect();
27
+ }
28
+ }, [onSelect]);
29
+ const onContextMenu = (0, react_1.useCallback)((e) => {
30
+ e.stopPropagation();
31
+ onSelect();
32
+ }, [onSelect]);
33
+ const highlightBackground = showSelectedBackground && (selected || containsSelection)
34
+ ? TimelineSelection_1.TIMELINE_SELECTED_BACKGROUND
35
+ : undefined;
36
+ const innerRowStyle = (0, react_1.useMemo)(() => ({
14
37
  ...rowBase,
15
- paddingLeft: timeline_row_layout_1.TIMELINE_ROW_BASE_PADDING,
16
38
  ...style,
17
- }), [style]);
18
- const indentWidth = (0, timeline_row_layout_1.getTimelineRowIndentWidth)(depth);
19
- return (jsx_runtime_1.jsxs("div", { style: rowStyle, children: [eye, indentWidth > 0 ? jsx_runtime_1.jsx(Padder_1.Padder, { depth: depth }) : null, arrow, children] }));
39
+ backgroundColor: outerHeight === undefined ? highlightBackground : undefined,
40
+ }), [style, outerHeight, highlightBackground]);
41
+ const outerStyle = (0, react_1.useMemo)(() => {
42
+ if (outerHeight === null) {
43
+ return undefined;
44
+ }
45
+ return {
46
+ height: outerHeight,
47
+ borderBottom: `1px solid ${colors_1.TIMELINE_TRACK_SEPARATOR}`,
48
+ display: 'flex',
49
+ flexDirection: 'column',
50
+ justifyContent: 'center',
51
+ backgroundColor: highlightBackground,
52
+ };
53
+ }, [outerHeight, highlightBackground]);
54
+ 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] }));
56
+ if (outerStyle) {
57
+ 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
+ }
59
+ return (jsx_runtime_1.jsx("div", { onPointerDown: selectable ? onPointerDown : undefined, onContextMenu: selectable ? onContextMenu : undefined, onDoubleClick: onDoubleClick, style: innerRowStyle, children: chrome }));
20
60
  };
21
61
  exports.TimelineRowChrome = TimelineRowChrome;
@@ -9,10 +9,13 @@ const TimelineEnumField_1 = require("./TimelineEnumField");
9
9
  const TimelineNumberField_1 = require("./TimelineNumberField");
10
10
  const TimelineRotationField_1 = require("./TimelineRotationField");
11
11
  const TimelineTranslateField_1 = require("./TimelineTranslateField");
12
+ const TimelineUvCoordinateField_1 = require("./TimelineUvCoordinateField");
12
13
  const unsupportedLabel = {
13
14
  color: 'rgba(255, 255, 255, 0.4)',
14
15
  fontSize: 12,
15
16
  fontStyle: 'italic',
17
+ userSelect: 'none',
18
+ WebkitUserSelect: 'none',
16
19
  };
17
20
  const notEditableBackground = {
18
21
  backgroundColor: 'rgba(255, 0, 0, 0.2)',
@@ -30,10 +33,9 @@ const TimelineNonEditableStatus = ({ propStatus }) => {
30
33
  if (propStatus.canUpdate) {
31
34
  return null;
32
35
  }
33
- if (propStatus.reason === 'computed') {
36
+ if (propStatus.reason === 'computed' || propStatus.reason === 'keyframed') {
34
37
  return (jsx_runtime_1.jsx("span", { style: unsupportedLabel, children: (0, get_timeline_keyframes_1.getComputedStatusLabel)(propStatus) }));
35
38
  }
36
- throw new Error(`Unsupported prop status: ${propStatus.reason}`);
37
39
  };
38
40
  exports.TimelineNonEditableStatus = TimelineNonEditableStatus;
39
41
  const TimelineFieldValue = ({ field, onSave, onDragValueChange, onDragEnd, propStatus, effectiveValue, }) => {
@@ -49,6 +51,9 @@ const TimelineFieldValue = ({ field, onSave, onDragValueChange, onDragEnd, propS
49
51
  if (field.typeName === 'translate') {
50
52
  return (jsx_runtime_1.jsx("span", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineTranslateField_1.TimelineTranslateField, { field: field, effectiveValue: effectiveValue, propStatus: propStatus, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd }) }));
51
53
  }
54
+ if (field.typeName === 'uv-coordinate') {
55
+ return (jsx_runtime_1.jsx("span", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineUvCoordinateField_1.TimelineUvCoordinateField, { field: field, effectiveValue: effectiveValue, propStatus: propStatus, onSave: onSave, onDragValueChange: onDragValueChange, onDragEnd: onDragEnd }) }));
56
+ }
52
57
  if (field.typeName === 'boolean') {
53
58
  return (jsx_runtime_1.jsx("span", { style: wrapperStyle, children: jsx_runtime_1.jsx(TimelineBooleanField_1.TimelineBooleanField, { field: field, propStatus: propStatus, onSave: onSave, effectiveValue: effectiveValue }) }));
54
59
  }
@@ -0,0 +1,41 @@
1
+ import React, { type CSSProperties } from 'react';
2
+ import type { SequenceNodePathInfo } from '../../helpers/get-timeline-sequence-sort-key';
3
+ export declare const TIMELINE_SELECTED_BACKGROUND = "#3B3F42";
4
+ export declare const TIMELINE_SELECTED_LABEL_BACKGROUND = "#B0B0B0";
5
+ export declare const TIMELINE_SELECTED_LABEL_TEXT = "black";
6
+ export declare const TIMELINE_SELECTED_LABEL_HORIZONTAL_PADDING = 2;
7
+ export declare const getTimelineSelectedLabelStyle: (selected: boolean, subcategory: boolean) => CSSProperties;
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;
10
+ export declare const SELECTION_ENABLED = false;
11
+ export type TimelineSelection = {
12
+ readonly type: 'row';
13
+ readonly nodePathInfo: SequenceNodePathInfo;
14
+ } | {
15
+ readonly type: 'keyframe';
16
+ readonly nodePathInfo: SequenceNodePathInfo;
17
+ readonly frame: number;
18
+ };
19
+ type TimelineSelectionContextValue = {
20
+ readonly canSelect: boolean;
21
+ readonly isSelected: (item: TimelineSelection) => boolean;
22
+ readonly selectItem: (item: TimelineSelection) => void;
23
+ readonly containsSelection: (nodePathInfo: SequenceNodePathInfo) => boolean;
24
+ readonly clearSelection: () => void;
25
+ };
26
+ export declare const TimelineSelectionProvider: React.FC<{
27
+ readonly children: React.ReactNode;
28
+ }>;
29
+ export declare const useTimelineSelection: () => TimelineSelectionContextValue;
30
+ export declare const useTimelineRowSelection: (nodePathInfo: SequenceNodePathInfo | null) => {
31
+ onSelect: () => void;
32
+ selectable: boolean;
33
+ selected: boolean;
34
+ };
35
+ export declare const useTimelineKeyframeSelection: (nodePathInfo: SequenceNodePathInfo, frame: number) => {
36
+ onSelect: () => void;
37
+ selectable: boolean;
38
+ selected: boolean;
39
+ };
40
+ export declare const useTimelineRowContainsSelection: (nodePathInfo: SequenceNodePathInfo | null) => boolean;
41
+ export {};