@remotion/studio 4.0.441 → 4.0.443

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 (40) hide show
  1. package/dist/components/AudioWaveform.js +67 -61
  2. package/dist/components/Editor.js +7 -4
  3. package/dist/components/EditorGuides/Guide.js +2 -1
  4. package/dist/components/EditorRuler/Ruler.js +2 -1
  5. package/dist/components/EditorRuler/index.js +4 -7
  6. package/dist/components/ForceSpecificCursor.d.ts +3 -0
  7. package/dist/components/ForceSpecificCursor.js +68 -0
  8. package/dist/components/MenuBuildIndicator.js +58 -3
  9. package/dist/components/MenuCompositionName.d.ts +2 -0
  10. package/dist/components/MenuCompositionName.js +80 -0
  11. package/dist/components/NewComposition/InputDragger.js +3 -0
  12. package/dist/components/RenderModal/RenderModalJSONPropsEditor.js +10 -3
  13. package/dist/components/Splitter/SplitterHandle.js +3 -0
  14. package/dist/components/Timeline/Timeline.js +3 -3
  15. package/dist/components/Timeline/TimelineDragHandler.js +4 -0
  16. package/dist/components/Timeline/TimelineRotationField.js +11 -0
  17. package/dist/components/Timeline/TimelineSequence.js +1 -1
  18. package/dist/components/Timeline/TimelineStack/index.js +2 -1
  19. package/dist/components/Timeline/TimelineVideoInfo.d.ts +4 -0
  20. package/dist/components/Timeline/TimelineVideoInfo.js +31 -12
  21. package/dist/components/Timeline/TimelineWidthProvider.js +16 -1
  22. package/dist/components/draw-peaks.d.ts +1 -0
  23. package/dist/components/draw-peaks.js +61 -0
  24. package/dist/components/load-waveform-peaks.d.ts +3 -0
  25. package/dist/components/load-waveform-peaks.js +67 -0
  26. package/dist/components/parse-color.d.ts +1 -0
  27. package/dist/components/parse-color.js +17 -0
  28. package/dist/esm/{chunk-1x2ychmc.js → chunk-cpv44d93.js} +3613 -3340
  29. package/dist/esm/internals.mjs +3613 -3340
  30. package/dist/esm/previewEntry.mjs +3405 -3132
  31. package/dist/esm/renderEntry.mjs +1 -1
  32. package/dist/helpers/calculate-timeline.d.ts +1 -2
  33. package/dist/helpers/calculate-timeline.js +2 -23
  34. package/dist/helpers/timeline-layout.d.ts +4 -1
  35. package/dist/helpers/timeline-layout.js +10 -4
  36. package/package.json +9 -9
  37. package/dist/components/AudioWaveformBar.d.ts +0 -14
  38. package/dist/components/AudioWaveformBar.js +0 -33
  39. package/dist/components/OpenEditorButton.d.ts +0 -3
  40. package/dist/components/OpenEditorButton.js +0 -67
@@ -2,18 +2,18 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AudioWaveform = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const media_utils_1 = require("@remotion/media-utils");
6
5
  const react_1 = require("react");
7
6
  const remotion_1 = require("remotion");
8
7
  const colors_1 = require("../helpers/colors");
9
8
  const timeline_layout_1 = require("../helpers/timeline-layout");
10
- const AudioWaveformBar_1 = require("./AudioWaveformBar");
9
+ const draw_peaks_1 = require("./draw-peaks");
10
+ const load_waveform_peaks_1 = require("./load-waveform-peaks");
11
11
  const container = {
12
12
  display: 'flex',
13
13
  flexDirection: 'row',
14
- alignItems: 'flex-end',
14
+ alignItems: 'center',
15
15
  position: 'absolute',
16
- height: (0, timeline_layout_1.getTimelineLayerHeight)('other'),
16
+ inset: 0,
17
17
  };
18
18
  const errorMessage = {
19
19
  fontSize: 13,
@@ -25,46 +25,87 @@ const errorMessage = {
25
25
  maxWidth: 450,
26
26
  opacity: 0.75,
27
27
  };
28
- const canvasStyle = {
28
+ const waveformCanvasStyle = {
29
+ pointerEvents: 'none',
30
+ };
31
+ const volumeCanvasStyle = {
29
32
  position: 'absolute',
30
33
  };
31
34
  const AudioWaveform = ({ src, startFrom, durationInFrames, visualizationWidth, volume, doesVolumeChange, playbackRate, }) => {
32
- const [metadata, setMetadata] = (0, react_1.useState)(null);
35
+ const [peaks, setPeaks] = (0, react_1.useState)(null);
33
36
  const [error, setError] = (0, react_1.useState)(null);
34
- const mountState = (0, react_1.useRef)({ isMounted: true });
35
37
  const vidConf = remotion_1.Internals.useUnsafeVideoConfig();
36
38
  if (vidConf === null) {
37
39
  throw new Error('Expected video config');
38
40
  }
39
- const canvas = (0, react_1.useRef)(null);
41
+ const containerRef = (0, react_1.useRef)(null);
42
+ const waveformCanvas = (0, react_1.useRef)(null);
43
+ const volumeCanvas = (0, react_1.useRef)(null);
40
44
  (0, react_1.useEffect)(() => {
41
- const { current } = mountState;
42
- current.isMounted = true;
43
- return () => {
44
- current.isMounted = false;
45
- };
46
- }, []);
45
+ const controller = new AbortController();
46
+ setError(null);
47
+ (0, load_waveform_peaks_1.loadWaveformPeaks)(src, controller.signal)
48
+ .then((p) => {
49
+ if (!controller.signal.aborted) {
50
+ setPeaks(p);
51
+ }
52
+ })
53
+ .catch((err) => {
54
+ if (!controller.signal.aborted) {
55
+ setError(err);
56
+ }
57
+ });
58
+ return () => controller.abort();
59
+ }, [src]);
60
+ const portionPeaks = (0, react_1.useMemo)(() => {
61
+ if (!peaks || peaks.length === 0) {
62
+ return null;
63
+ }
64
+ const startTimeInSeconds = startFrom / vidConf.fps;
65
+ const durationInSeconds = (durationInFrames / vidConf.fps) * playbackRate;
66
+ const startPeakIndex = Math.floor(startTimeInSeconds * load_waveform_peaks_1.TARGET_SAMPLE_RATE);
67
+ const endPeakIndex = Math.ceil((startTimeInSeconds + durationInSeconds) * load_waveform_peaks_1.TARGET_SAMPLE_RATE);
68
+ return peaks.slice(Math.max(0, startPeakIndex), Math.min(peaks.length, endPeakIndex));
69
+ }, [peaks, startFrom, durationInFrames, vidConf.fps, playbackRate]);
70
+ (0, react_1.useEffect)(() => {
71
+ const { current: canvasElement } = waveformCanvas;
72
+ const { current: containerElement } = containerRef;
73
+ if (!canvasElement ||
74
+ !containerElement ||
75
+ !portionPeaks ||
76
+ portionPeaks.length === 0) {
77
+ return;
78
+ }
79
+ const h = containerElement.clientHeight;
80
+ const w = Math.ceil(visualizationWidth);
81
+ canvasElement.width = w;
82
+ canvasElement.height = h;
83
+ const vol = typeof volume === 'number' ? volume : 1;
84
+ (0, draw_peaks_1.drawBars)(canvasElement, portionPeaks, 'rgba(255, 255, 255, 0.6)', vol, w);
85
+ }, [portionPeaks, visualizationWidth, volume]);
47
86
  (0, react_1.useEffect)(() => {
48
- if (!canvas.current) {
87
+ const { current: volumeCanvasElement } = volumeCanvas;
88
+ const { current: containerElement } = containerRef;
89
+ if (!volumeCanvasElement || !containerElement) {
49
90
  return;
50
91
  }
51
- const context = canvas.current.getContext('2d');
92
+ const h = containerElement.clientHeight;
93
+ const context = volumeCanvasElement.getContext('2d');
52
94
  if (!context) {
53
95
  return;
54
96
  }
55
- context.clearRect(0, 0, visualizationWidth, (0, timeline_layout_1.getTimelineLayerHeight)('other'));
97
+ volumeCanvasElement.width = Math.ceil(visualizationWidth);
98
+ volumeCanvasElement.height = h;
99
+ context.clearRect(0, 0, visualizationWidth, h);
56
100
  if (!doesVolumeChange || typeof volume === 'number') {
57
- // The volume is a number, meaning it could change on each frame-
58
- // User did not use the (f: number) => number syntax, so we can't draw
59
- // a visualization.
60
101
  return;
61
102
  }
62
103
  const volumes = volume.split(',').map((v) => Number(v));
63
104
  context.beginPath();
64
- context.moveTo(0, (0, timeline_layout_1.getTimelineLayerHeight)('other'));
105
+ context.moveTo(0, h);
65
106
  volumes.forEach((v, index) => {
66
107
  const x = (index / (volumes.length - 1)) * visualizationWidth;
67
- const y = (1 - v) * ((0, timeline_layout_1.getTimelineLayerHeight)('other') - timeline_layout_1.TIMELINE_BORDER * 2) + 1;
108
+ const y = (1 - v) * (h - timeline_layout_1.TIMELINE_BORDER * 2) + 1;
68
109
  if (index === 0) {
69
110
  context.moveTo(x, y);
70
111
  }
@@ -74,50 +115,15 @@ const AudioWaveform = ({ src, startFrom, durationInFrames, visualizationWidth, v
74
115
  });
75
116
  context.strokeStyle = colors_1.LIGHT_TRANSPARENT;
76
117
  context.stroke();
77
- }, [visualizationWidth, metadata, startFrom, volume, doesVolumeChange]);
78
- (0, react_1.useEffect)(() => {
79
- setError(null);
80
- (0, media_utils_1.getAudioData)(src)
81
- .then((data) => {
82
- if (mountState.current.isMounted) {
83
- setMetadata(data);
84
- }
85
- })
86
- .catch((err) => {
87
- if (mountState.current.isMounted) {
88
- setError(err);
89
- }
90
- });
91
- }, [src, vidConf.fps]);
92
- const normalized = (0, react_1.useMemo)(() => {
93
- if (!metadata || metadata.numberOfChannels === 0) {
94
- return [];
95
- }
96
- const numberOfSamples = Math.floor(visualizationWidth / (AudioWaveformBar_1.WAVEFORM_BAR_LENGTH + AudioWaveformBar_1.WAVEFORM_BAR_MARGIN));
97
- return (0, media_utils_1.getWaveformPortion)({
98
- audioData: metadata,
99
- startTimeInSeconds: startFrom / vidConf.fps,
100
- durationInSeconds: Math.min((durationInFrames / vidConf.fps) * playbackRate, metadata.durationInSeconds),
101
- numberOfSamples,
102
- normalize: false,
103
- });
104
- }, [
105
- durationInFrames,
106
- vidConf.fps,
107
- metadata,
108
- playbackRate,
109
- startFrom,
110
- visualizationWidth,
111
- ]);
118
+ }, [visualizationWidth, volume, doesVolumeChange]);
112
119
  if (error) {
113
120
  return (jsx_runtime_1.jsx("div", { style: container, children: jsx_runtime_1.jsx("div", { style: errorMessage, children: "No waveform available. Audio might not support CORS." }) }));
114
121
  }
115
- if (!metadata) {
122
+ if (!peaks) {
116
123
  return null;
117
124
  }
118
- return (jsx_runtime_1.jsxs("div", { style: container, children: [normalized.map((w) => {
119
- return (jsx_runtime_1.jsx(AudioWaveformBar_1.AudioWaveformBar, { amplitude: w.amplitude * (typeof volume === 'number' ? volume : 1) }, w.index));
120
- }), jsx_runtime_1.jsx("canvas", { ref: canvas, style: canvasStyle, width: visualizationWidth, height: (0, timeline_layout_1.getTimelineLayerHeight)('other') })
125
+ return (jsx_runtime_1.jsxs("div", { ref: containerRef, style: container, children: [
126
+ jsx_runtime_1.jsx("canvas", { ref: waveformCanvas, style: waveformCanvasStyle }), jsx_runtime_1.jsx("canvas", { ref: volumeCanvas, style: volumeCanvasStyle })
121
127
  ] }));
122
128
  };
123
129
  exports.AudioWaveform = AudioWaveform;
@@ -44,6 +44,7 @@ const canvas_ref_1 = require("../state/canvas-ref");
44
44
  const timeline_zoom_1 = require("../state/timeline-zoom");
45
45
  const z_index_1 = require("../state/z-index");
46
46
  const EditorContent_1 = require("./EditorContent");
47
+ const ForceSpecificCursor_1 = require("./ForceSpecificCursor");
47
48
  const GlobalKeybindings_1 = require("./GlobalKeybindings");
48
49
  const Modals_1 = require("./Modals");
49
50
  const NotificationCenter_1 = require("./Notifications/NotificationCenter");
@@ -83,10 +84,12 @@ const Editor = ({ Root, readOnlyStudio }) => {
83
84
  return react_1.default.memo(Root);
84
85
  }, [Root]);
85
86
  return (jsx_runtime_1.jsx(z_index_1.HigherZIndex, { onEscape: noop_1.noop, onOutsideClick: noop_1.noop, children: jsx_runtime_1.jsxs(timeline_zoom_1.TimelineZoomContext, { children: [
86
- jsx_runtime_1.jsx(remotion_1.Internals.CurrentScaleContext.Provider, { value: value, children: jsx_runtime_1.jsxs("div", { style: background, children: [canvasMounted ? jsx_runtime_1.jsx(MemoRoot, {}) : null, jsx_runtime_1.jsxs(remotion_1.Internals.CanUseRemotionHooksProvider, { children: [
87
- jsx_runtime_1.jsx(EditorContent_1.EditorContent, { readOnlyStudio: readOnlyStudio, children: jsx_runtime_1.jsx(TopPanel_1.TopPanel, { drawRef: canvas_ref_1.drawRef, bufferStateDelayInMilliseconds: exports.BUFFER_STATE_DELAY_IN_MILLISECONDS, onMounted: onMounted, readOnlyStudio: readOnlyStudio }) }), jsx_runtime_1.jsx(GlobalKeybindings_1.GlobalKeybindings, {})
88
- ] })
89
- ] }) }), jsx_runtime_1.jsx(Modals_1.Modals, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(NotificationCenter_1.NotificationCenter, {})
87
+ jsx_runtime_1.jsxs(remotion_1.Internals.CurrentScaleContext.Provider, { value: value, children: [
88
+ jsx_runtime_1.jsx(ForceSpecificCursor_1.ForceSpecificCursor, {}), jsx_runtime_1.jsxs("div", { style: background, children: [canvasMounted ? jsx_runtime_1.jsx(MemoRoot, {}) : null, jsx_runtime_1.jsxs(remotion_1.Internals.CanUseRemotionHooksProvider, { children: [
89
+ jsx_runtime_1.jsx(EditorContent_1.EditorContent, { readOnlyStudio: readOnlyStudio, children: jsx_runtime_1.jsx(TopPanel_1.TopPanel, { drawRef: canvas_ref_1.drawRef, bufferStateDelayInMilliseconds: exports.BUFFER_STATE_DELAY_IN_MILLISECONDS, onMounted: onMounted, readOnlyStudio: readOnlyStudio }) }), jsx_runtime_1.jsx(GlobalKeybindings_1.GlobalKeybindings, {})
90
+ ] })
91
+ ] })
92
+ ] }), jsx_runtime_1.jsx(Modals_1.Modals, { readOnlyStudio: readOnlyStudio }), jsx_runtime_1.jsx(NotificationCenter_1.NotificationCenter, {})
90
93
  ] }) }));
91
94
  };
92
95
  exports.Editor = Editor;
@@ -7,6 +7,7 @@ const colors_1 = require("../../helpers/colors");
7
7
  const editor_guides_1 = require("../../state/editor-guides");
8
8
  const editor_rulers_1 = require("../../state/editor-rulers");
9
9
  const ContextMenu_1 = require("../ContextMenu");
10
+ const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
10
11
  const PADDING_FOR_EASY_DRAG = 4;
11
12
  const GuideComp = ({ guide, canvasDimensions, scale }) => {
12
13
  const { shouldCreateGuideRef, setGuidesList, setSelectedGuideId, selectedGuideId, setHoveredGuideId, hoveredGuideId, } = (0, react_1.useContext)(editor_guides_1.EditorShowGuidesContext);
@@ -53,7 +54,7 @@ const GuideComp = ({ guide, canvasDimensions, scale }) => {
53
54
  return;
54
55
  }
55
56
  shouldCreateGuideRef.current = true;
56
- document.body.style.cursor = 'no-drop';
57
+ (0, ForceSpecificCursor_1.forceSpecificCursor)('no-drop');
57
58
  setSelectedGuideId(() => guide.id);
58
59
  }, [shouldCreateGuideRef, setSelectedGuideId, guide.id]);
59
60
  const values = (0, react_1.useMemo)(() => {
@@ -7,6 +7,7 @@ const colors_1 = require("../../helpers/colors");
7
7
  const editor_ruler_1 = require("../../helpers/editor-ruler");
8
8
  const editor_guides_1 = require("../../state/editor-guides");
9
9
  const editor_rulers_1 = require("../../state/editor-rulers");
10
+ const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
10
11
  const makeGuideId = () => {
11
12
  return Math.random().toString(36).substring(7);
12
13
  };
@@ -67,7 +68,7 @@ const Ruler = ({ scale, points, originOffset, startMarking, size, markingGaps, o
67
68
  }
68
69
  e.preventDefault();
69
70
  shouldCreateGuideRef.current = true;
70
- document.body.style.cursor = 'no-drop';
71
+ (0, ForceSpecificCursor_1.forceSpecificCursor)('no-drop');
71
72
  const guideId = makeGuideId();
72
73
  setEditorShowGuides(() => true);
73
74
  setSelectedGuideId(() => guideId);
@@ -11,6 +11,7 @@ const editor_ruler_1 = require("../../helpers/editor-ruler");
11
11
  const use_studio_canvas_dimensions_1 = require("../../helpers/use-studio-canvas-dimensions");
12
12
  const editor_guides_1 = require("../../state/editor-guides");
13
13
  const editor_rulers_1 = require("../../state/editor-rulers");
14
+ const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
14
15
  const Ruler_1 = __importDefault(require("./Ruler"));
15
16
  const originBlockStyles = {
16
17
  position: 'absolute',
@@ -70,9 +71,7 @@ const EditorRulers = ({ contentDimensions, canvasSize, assetMetadata, containerR
70
71
  if (!shouldDeleteGuideRef.current) {
71
72
  shouldDeleteGuideRef.current = true;
72
73
  }
73
- if (document.body.style.cursor !== 'no-drop') {
74
- document.body.style.cursor = 'no-drop';
75
- }
74
+ (0, ForceSpecificCursor_1.forceSpecificCursor)('no-drop');
76
75
  setGuidesList((prevState) => {
77
76
  const newGuides = prevState.map((guide) => {
78
77
  if (guide.id !== selectedGuideId) {
@@ -103,9 +102,7 @@ const EditorRulers = ({ contentDimensions, canvasSize, assetMetadata, containerR
103
102
  : (mouseY - containerTop) / scale -
104
103
  canvasPosition.top / scale;
105
104
  const desiredCursor = guide.orientation === 'vertical' ? 'ew-resize' : 'ns-resize';
106
- if (document.body.style.cursor !== desiredCursor) {
107
- document.body.style.cursor = desiredCursor;
108
- }
105
+ (0, ForceSpecificCursor_1.forceSpecificCursor)(desiredCursor);
109
106
  return {
110
107
  ...guide,
111
108
  position: Math.floor(position / 1.0),
@@ -136,7 +133,7 @@ const EditorRulers = ({ contentDimensions, canvasSize, assetMetadata, containerR
136
133
  return newGuides;
137
134
  });
138
135
  shouldDeleteGuideRef.current = false;
139
- document.body.style.cursor = 'auto';
136
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
140
137
  shouldCreateGuideRef.current = false;
141
138
  setSelectedGuideId(() => null);
142
139
  document.removeEventListener('pointerup', onMouseUp);
@@ -0,0 +1,3 @@
1
+ export declare const forceSpecificCursor: (cursor: string) => void;
2
+ export declare const stopForcingSpecificCursor: () => void;
3
+ export declare const ForceSpecificCursor: () => import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,68 @@
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.ForceSpecificCursor = exports.stopForcingSpecificCursor = exports.forceSpecificCursor = void 0;
37
+ const jsx_runtime_1 = require("react/jsx-runtime");
38
+ const react_1 = __importStar(require("react"));
39
+ const ref = react_1.default.createRef();
40
+ const forceSpecificCursor = (cursor) => {
41
+ if (!ref.current) {
42
+ throw new Error('ForceSpecificCursor is not mounted');
43
+ }
44
+ ref.current.style.cursor = cursor;
45
+ ref.current.style.pointerEvents = 'auto';
46
+ };
47
+ exports.forceSpecificCursor = forceSpecificCursor;
48
+ const stopForcingSpecificCursor = () => {
49
+ if (!ref.current) {
50
+ throw new Error('ForceSpecificCursor is not mounted');
51
+ }
52
+ ref.current.style.cursor = '';
53
+ ref.current.style.pointerEvents = 'none';
54
+ };
55
+ exports.stopForcingSpecificCursor = stopForcingSpecificCursor;
56
+ const Z_INDEX_FORCE_SPECIFIC_CURSOR = 100;
57
+ const ForceSpecificCursor = () => {
58
+ const style = (0, react_1.useMemo)(() => {
59
+ return {
60
+ position: 'fixed',
61
+ inset: 0,
62
+ zIndex: Z_INDEX_FORCE_SPECIFIC_CURSOR,
63
+ pointerEvents: 'none',
64
+ };
65
+ }, []);
66
+ return jsx_runtime_1.jsx("div", { ref: ref, style: style });
67
+ };
68
+ exports.ForceSpecificCursor = ForceSpecificCursor;
@@ -4,8 +4,11 @@ exports.MenuBuildIndicator = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const react_1 = require("react");
6
6
  const client_id_1 = require("../helpers/client-id");
7
+ const get_git_menu_item_1 = require("../helpers/get-git-menu-item");
8
+ const open_in_editor_1 = require("../helpers/open-in-editor");
7
9
  const layout_1 = require("./layout");
8
- const OpenEditorButton_1 = require("./OpenEditorButton");
10
+ const MenuCompositionName_1 = require("./MenuCompositionName");
11
+ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
9
12
  const Spinner_1 = require("./Spinner");
10
13
  const cwd = {
11
14
  fontSize: 13,
@@ -25,10 +28,61 @@ const noSpinner = {
25
28
  position: 'relative',
26
29
  width: spinnerSize,
27
30
  };
31
+ const projectNameLinkBase = {
32
+ color: 'inherit',
33
+ textDecoration: 'none',
34
+ cursor: 'pointer',
35
+ fontSize: 'inherit',
36
+ textUnderlineOffset: 2,
37
+ };
38
+ const projectNameLink = {
39
+ ...projectNameLinkBase,
40
+ };
41
+ const projectNameLinkHovered = {
42
+ ...projectNameLinkBase,
43
+ textDecoration: 'underline',
44
+ };
28
45
  const MenuBuildIndicator = () => {
29
46
  const [isBuilding, setIsBuilding] = (0, react_1.useState)(false);
47
+ const [projectNameHovered, setProjectNameHovered] = (0, react_1.useState)(false);
30
48
  const ctx = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState;
31
- const showButton = window.remotion_editorName && ctx.type === 'connected';
49
+ const showEditorLink = window.remotion_editorName && ctx.type === 'connected';
50
+ const showGitLink = !showEditorLink && Boolean(window.remotion_gitSource);
51
+ const handleProjectNameClick = (0, react_1.useCallback)(async () => {
52
+ if (showEditorLink) {
53
+ await (0, open_in_editor_1.openInEditor)({
54
+ originalFileName: `${window.remotion_cwd}`,
55
+ originalLineNumber: 1,
56
+ originalColumnNumber: 1,
57
+ originalFunctionName: null,
58
+ originalScriptCode: null,
59
+ })
60
+ .then((res) => res.json())
61
+ .then(({ success }) => {
62
+ if (!success) {
63
+ (0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
64
+ }
65
+ })
66
+ .catch((err) => {
67
+ // eslint-disable-next-line no-console
68
+ console.error(err);
69
+ (0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
70
+ });
71
+ }
72
+ else if (showGitLink) {
73
+ window.open((0, get_git_menu_item_1.getGitSourceBranchUrl)(window.remotion_gitSource), '_blank');
74
+ }
75
+ }, [showEditorLink, showGitLink]);
76
+ const projectNameTitle = (0, react_1.useMemo)(() => {
77
+ if (showEditorLink) {
78
+ return `Open in ${window.remotion_editorName}`;
79
+ }
80
+ if (showGitLink) {
81
+ return `Open ${(0, get_git_menu_item_1.getGitSourceName)(window.remotion_gitSource)} Repo`;
82
+ }
83
+ return undefined;
84
+ }, [showEditorLink, showGitLink]);
85
+ const isClickable = showEditorLink || showGitLink;
32
86
  (0, react_1.useEffect)(() => {
33
87
  window.remotion_isBuilding = () => {
34
88
  setIsBuilding(true);
@@ -41,6 +95,7 @@ const MenuBuildIndicator = () => {
41
95
  window.remotion_finishedBuilding = undefined;
42
96
  };
43
97
  }, []);
44
- return (jsx_runtime_1.jsxs("div", { style: cwd, title: window.remotion_cwd, children: [showButton ? jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }) : null, isBuilding ? (jsx_runtime_1.jsx("div", { style: spinner, children: jsx_runtime_1.jsx(Spinner_1.Spinner, { duration: 0.5, size: spinnerSize }) })) : (jsx_runtime_1.jsx("div", { style: noSpinner })), showButton ? jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }) : null, window.remotion_projectName, showButton ? jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.25 }) : null, showButton ? (jsx_runtime_1.jsx(OpenEditorButton_1.OpenEditorButton, { type: "editor" })) : window.remotion_gitSource ? (jsx_runtime_1.jsx(OpenEditorButton_1.OpenEditorButton, { type: "git" })) : null] }));
98
+ return (jsx_runtime_1.jsxs("div", { style: cwd, title: window.remotion_cwd, children: [isClickable ? jsx_runtime_1.jsx(layout_1.Spacing, { x: 2 }) : null, isBuilding ? (jsx_runtime_1.jsx("div", { style: spinner, children: jsx_runtime_1.jsx(Spinner_1.Spinner, { duration: 0.5, size: spinnerSize }) })) : (jsx_runtime_1.jsx("div", { style: noSpinner })), isClickable ? jsx_runtime_1.jsx(layout_1.Spacing, { x: 0.5 }) : null, isClickable ? (jsx_runtime_1.jsx("a", { style: projectNameHovered ? projectNameLinkHovered : projectNameLink, title: projectNameTitle, onClick: handleProjectNameClick, onPointerEnter: () => setProjectNameHovered(true), onPointerLeave: () => setProjectNameHovered(false), children: window.remotion_projectName })) : (window.remotion_projectName), jsx_runtime_1.jsx(MenuCompositionName_1.MenuCompositionName, {})
99
+ ] }));
45
100
  };
46
101
  exports.MenuBuildIndicator = MenuBuildIndicator;
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const MenuCompositionName: React.FC;
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MenuCompositionName = 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 open_in_editor_1 = require("../helpers/open-in-editor");
10
+ const NotificationCenter_1 = require("./Notifications/NotificationCenter");
11
+ const use_resolved_stack_1 = require("./Timeline/use-resolved-stack");
12
+ const baseStyle = {
13
+ color: 'inherit',
14
+ textDecoration: 'none',
15
+ fontSize: 'inherit',
16
+ textUnderlineOffset: 2,
17
+ };
18
+ const compositionNameStyle = {
19
+ ...baseStyle,
20
+ cursor: 'default',
21
+ };
22
+ const clickableStyle = {
23
+ ...baseStyle,
24
+ cursor: 'pointer',
25
+ };
26
+ const clickableHoveredStyle = {
27
+ ...clickableStyle,
28
+ textDecoration: 'underline',
29
+ };
30
+ const slashStyle = {
31
+ color: colors_1.LIGHT_TEXT,
32
+ marginInline: 4,
33
+ position: 'relative',
34
+ top: 1,
35
+ };
36
+ const MenuCompositionName = () => {
37
+ var _a;
38
+ const { canvasContent, compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
39
+ const connectionStatus = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx)
40
+ .previewServerState.type;
41
+ const [opening, setOpening] = (0, react_1.useState)(false);
42
+ const [hovered, setHovered] = (0, react_1.useState)(false);
43
+ const composition = (0, react_1.useMemo)(() => {
44
+ var _a;
45
+ if (canvasContent === null || canvasContent.type !== 'composition') {
46
+ return null;
47
+ }
48
+ return ((_a = compositions.find((c) => c.id === canvasContent.compositionId)) !== null && _a !== void 0 ? _a : null);
49
+ }, [canvasContent, compositions]);
50
+ const resolvedLocation = (0, use_resolved_stack_1.useResolvedStack)((_a = composition === null || composition === void 0 ? void 0 : composition.stack) !== null && _a !== void 0 ? _a : null);
51
+ const canOpen = resolvedLocation &&
52
+ window.remotion_editorName &&
53
+ connectionStatus === 'connected';
54
+ const handleClick = (0, react_1.useCallback)(async () => {
55
+ if (!canOpen || !resolvedLocation) {
56
+ return;
57
+ }
58
+ setOpening(true);
59
+ try {
60
+ await (0, open_in_editor_1.openOriginalPositionInEditor)(resolvedLocation);
61
+ }
62
+ catch (err) {
63
+ (0, NotificationCenter_1.showNotification)(err.message, 2000);
64
+ }
65
+ finally {
66
+ setOpening(false);
67
+ }
68
+ }, [canOpen, resolvedLocation]);
69
+ if (!composition) {
70
+ return null;
71
+ }
72
+ return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
73
+ jsx_runtime_1.jsx("span", { style: slashStyle, children: "/" }), jsx_runtime_1.jsx("a", { style: canOpen && !opening
74
+ ? hovered
75
+ ? clickableHoveredStyle
76
+ : clickableStyle
77
+ : compositionNameStyle, title: canOpen ? `Open in ${window.remotion_editorName}` : composition.id, onClick: handleClick, onPointerEnter: () => setHovered(true), onPointerLeave: () => setHovered(false), children: composition.id })
78
+ ] }));
79
+ };
80
+ exports.MenuCompositionName = MenuCompositionName;
@@ -41,6 +41,7 @@ const colors_1 = require("../../helpers/colors");
41
41
  const noop_1 = require("../../helpers/noop");
42
42
  const input_dragger_click_lock_1 = require("../../state/input-dragger-click-lock");
43
43
  const z_index_1 = require("../../state/z-index");
44
+ const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
44
45
  const RemInput_1 = require("./RemInput");
45
46
  const isInt = (num) => {
46
47
  return num % 1 === 0;
@@ -135,6 +136,7 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
135
136
  if (distanceFromStart > 4) {
136
137
  (0, input_dragger_click_lock_1.setClickLock)(true);
137
138
  setDragging(true);
139
+ (0, ForceSpecificCursor_1.forceSpecificCursor)('ew-resize');
138
140
  target.blur();
139
141
  }
140
142
  const diff = (0, remotion_1.interpolate)(xDistance, [-5, -4, 0, 4, 5], [-step, 0, 0, 0, step]);
@@ -148,6 +150,7 @@ const InputDraggerForwardRefFn = ({ onValueChange, onValueChangeEnd, min: _min,
148
150
  window.removeEventListener('mousemove', moveListener);
149
151
  pointerDownRef.current = false;
150
152
  setDragging(false);
153
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
151
154
  if (lastDragValue !== null && onValueChangeEnd) {
152
155
  onValueChangeEnd(lastDragValue);
153
156
  }
@@ -103,13 +103,20 @@ const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, ser
103
103
  }
104
104
  const { result } = e;
105
105
  if (result.canUpdate) {
106
- setLocalValue(parseJS(result.currentDefaultProps, schema));
106
+ const nextState = parseJS(result.currentDefaultProps, schema);
107
+ setLocalValue(nextState);
107
108
  }
108
109
  });
109
110
  return () => {
110
111
  unsub();
111
112
  };
112
113
  }, [subscribeToEvent, compositionId, schema]);
114
+ (0, react_1.useEffect)(() => {
115
+ if (localValue.validJSON && (0, deep_equal_1.deepEqual)(value, localValue.value)) {
116
+ return;
117
+ }
118
+ setLocalValue(parseJS(value, schema));
119
+ }, [value, schema, localValue]);
113
120
  const onPretty = (0, react_1.useCallback)(() => {
114
121
  if (!localValue.validJSON) {
115
122
  return;
@@ -137,8 +144,8 @@ const RenderModalJSONPropsEditor = ({ setValue, value, defaultProps, onSave, ser
137
144
  }, [hasChanged, hasError, onSave]);
138
145
  // If schema is changed in code
139
146
  (0, react_1.useEffect)(() => {
140
- setLocalValue(parseJSON(localValue.str, schema));
141
- }, [localValue.str, schema]);
147
+ setLocalValue((v) => parseJSON(v.str, schema));
148
+ }, [schema]);
142
149
  const reset = (0, react_1.useCallback)(() => {
143
150
  setValue(defaultProps);
144
151
  setLocalValue(parseJSON(JSON.stringify(defaultProps, null, 2), schema));
@@ -4,6 +4,7 @@ exports.SplitterHandle = exports.SPLITTER_HANDLE_SIZE = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const player_1 = require("@remotion/player");
6
6
  const react_1 = require("react");
7
+ const ForceSpecificCursor_1 = require("../ForceSpecificCursor");
7
8
  const SplitterContext_1 = require("./SplitterContext");
8
9
  exports.SPLITTER_HANDLE_SIZE = 3;
9
10
  const containerRow = {
@@ -58,6 +59,7 @@ const SplitterHandle = ({ allowToCollapse, onCollapse }) => {
58
59
  x: e.clientX,
59
60
  y: e.clientY,
60
61
  };
62
+ (0, ForceSpecificCursor_1.forceSpecificCursor)(context.orientation === 'horizontal' ? 'row-resize' : 'col-resize');
61
63
  (_a = ref.current) === null || _a === void 0 ? void 0 : _a.classList.add('remotion-splitter-active');
62
64
  window.addEventListener('pointerup', (ev) => {
63
65
  if (!context.isDragging.current) {
@@ -94,6 +96,7 @@ const SplitterHandle = ({ allowToCollapse, onCollapse }) => {
94
96
  const cleanup = () => {
95
97
  var _a;
96
98
  context.isDragging.current = false;
99
+ (0, ForceSpecificCursor_1.stopForcingSpecificCursor)();
97
100
  (_a = ref.current) === null || _a === void 0 ? void 0 : _a.classList.remove('remotion-splitter-active');
98
101
  current.removeEventListener('pointerdown', onPointerDown);
99
102
  window.removeEventListener('pointermove', onPointerMove);
@@ -75,15 +75,15 @@ const TimelineInner = () => {
75
75
  const visualModeEnabled = Boolean(process.env.EXPERIMENTAL_VISUAL_MODE_ENABLED) &&
76
76
  previewServerState.type === 'connected';
77
77
  const videoConfig = remotion_1.Internals.useUnsafeVideoConfig();
78
+ const videoConfigIsNull = videoConfig === null;
78
79
  const timeline = (0, react_1.useMemo)(() => {
79
- if (!videoConfig) {
80
+ if (videoConfigIsNull) {
80
81
  return [];
81
82
  }
82
83
  return (0, calculate_timeline_1.calculateTimeline)({
83
84
  sequences,
84
- sequenceDuration: videoConfig.durationInFrames,
85
85
  });
86
- }, [sequences, videoConfig]);
86
+ }, [sequences, videoConfigIsNull]);
87
87
  const durationInFrames = (_a = videoConfig === null || videoConfig === void 0 ? void 0 : videoConfig.durationInFrames) !== null && _a !== void 0 ? _a : 0;
88
88
  const filtered = (0, react_1.useMemo)(() => {
89
89
  const withoutHidden = timeline.filter((t) => !(0, is_collapsed_1.isTrackHidden)(t));