@remotion/studio
Version:
APIs for interacting with the Remotion Studio
159 lines (158 loc) • 8.02 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimelineListItem = exports.SPACING = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const client_id_1 = require("../../helpers/client-id");
const colors_1 = require("../../helpers/colors");
const timeline_layout_1 = require("../../helpers/timeline-layout");
const call_api_1 = require("../call-api");
const ContextMenu_1 = require("../ContextMenu");
const ExpandedTracksProvider_1 = require("../ExpandedTracksProvider");
const NotificationCenter_1 = require("../Notifications/NotificationCenter");
const TimelineExpandedSection_1 = require("./TimelineExpandedSection");
const TimelineLayerEye_1 = require("./TimelineLayerEye");
const TimelineStack_1 = require("./TimelineStack");
const use_resolved_stack_1 = require("./use-resolved-stack");
const use_sequence_props_subscription_1 = require("./use-sequence-props-subscription");
exports.SPACING = 5;
const space = {
width: exports.SPACING,
flexShrink: 0,
};
const arrowButton = {
background: 'none',
border: 'none',
color: 'white',
cursor: 'pointer',
padding: 0,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 12,
height: 12,
flexShrink: 0,
fontSize: 8,
marginRight: 4,
userSelect: 'none',
outline: 'none',
lineHeight: 1,
};
const TimelineListItem = ({ nestedDepth, sequence, isCompact }) => {
var _a, _b;
const { previewServerState } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
const visualModeEnvEnabled = Boolean(process.env.EXPERIMENTAL_VISUAL_MODE_ENABLED);
const previewConnected = previewServerState.type === 'connected';
const visualModeActive = visualModeEnvEnabled && previewConnected;
const { hidden, setHidden } = (0, react_1.useContext)(remotion_1.Internals.SequenceVisibilityToggleContext);
const { expandedTracks, toggleTrack } = (0, react_1.useContext)(ExpandedTracksProvider_1.ExpandedTracksContext);
const originalLocation = (0, use_resolved_stack_1.useResolvedStack)((_a = sequence.stack) !== null && _a !== void 0 ? _a : null);
const nodePath = (0, use_sequence_props_subscription_1.useSequencePropsSubscription)(sequence, originalLocation, visualModeActive);
const validatedLocation = (0, react_1.useMemo)(() => {
var _a;
if (!originalLocation ||
!originalLocation.source ||
!originalLocation.line) {
return null;
}
return {
source: originalLocation.source,
line: originalLocation.line,
column: (_a = originalLocation.column) !== null && _a !== void 0 ? _a : 0,
};
}, [originalLocation]);
const canDeleteFromSource = Boolean(nodePath && (validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source));
const deleteDisabled = (0, react_1.useMemo)(() => !previewConnected || !sequence.controls || !canDeleteFromSource, [previewConnected, sequence.controls, canDeleteFromSource]);
const onDeleteSequenceFromSource = (0, react_1.useCallback)(async () => {
if (!(validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source) || !nodePath) {
return;
}
try {
const result = await (0, call_api_1.callApi)('/api/delete-jsx-node', {
fileName: validatedLocation.source,
nodePath,
});
if (result.success) {
(0, NotificationCenter_1.showNotification)('Removed sequence from source file', 2000);
}
else {
(0, NotificationCenter_1.showNotification)(result.reason, 4000);
}
}
catch (err) {
(0, NotificationCenter_1.showNotification)(err.message, 4000);
}
}, [nodePath, validatedLocation === null || validatedLocation === void 0 ? void 0 : validatedLocation.source]);
const contextMenuValues = (0, react_1.useMemo)(() => {
if (!visualModeEnvEnabled) {
return [];
}
return [
{
type: 'item',
id: 'delete-sequence',
keyHint: null,
label: 'Delete',
leftItem: null,
disabled: deleteDisabled,
onClick: () => {
if (deleteDisabled) {
return;
}
onDeleteSequenceFromSource();
},
quickSwitcherLabel: null,
subMenu: null,
value: 'delete-sequence',
},
];
}, [deleteDisabled, onDeleteSequenceFromSource, visualModeEnvEnabled]);
const isExpanded = visualModeActive && ((_b = expandedTracks[sequence.id]) !== null && _b !== void 0 ? _b : false);
const onToggleExpand = (0, react_1.useCallback)(() => {
toggleTrack(sequence.id);
}, [sequence.id, toggleTrack]);
const padder = (0, react_1.useMemo)(() => {
return {
width: Number(exports.SPACING * 3) * nestedDepth,
flexShrink: 0,
};
}, [nestedDepth]);
const isItemHidden = (0, react_1.useMemo)(() => {
var _a;
return (_a = hidden[sequence.id]) !== null && _a !== void 0 ? _a : false;
}, [hidden, sequence.id]);
const onToggleVisibility = (0, react_1.useCallback)((type) => {
setHidden((prev) => {
return {
...prev,
[sequence.id]: type !== 'enable',
};
});
}, [sequence.id, setHidden]);
const outer = (0, react_1.useMemo)(() => {
return {
height: (0, timeline_layout_1.getTimelineLayerHeight)(sequence.type) + timeline_layout_1.TIMELINE_ITEM_BORDER_BOTTOM,
color: 'white',
fontFamily: 'Arial, Helvetica, sans-serif',
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
wordBreak: 'break-all',
textAlign: 'left',
paddingLeft: exports.SPACING,
borderBottom: `1px solid ${colors_1.TIMELINE_TRACK_SEPARATOR}`,
};
}, [sequence.type]);
const arrowStyle = (0, react_1.useMemo)(() => {
return {
...arrowButton,
transform: isExpanded ? 'rotate(90deg)' : 'rotate(0deg)',
};
}, [isExpanded]);
const trackRow = (jsx_runtime_1.jsxs("div", { style: outer, children: [
jsx_runtime_1.jsx(TimelineLayerEye_1.TimelineLayerEye, { type: sequence.type === 'audio' ? 'speaker' : 'eye', hidden: isItemHidden, onInvoked: onToggleVisibility }), jsx_runtime_1.jsx("div", { style: padder }), sequence.parent && nestedDepth > 0 ? jsx_runtime_1.jsx("div", { style: space }) : null, visualModeActive ? (sequence.controls ? (jsx_runtime_1.jsx("button", { type: "button", style: arrowStyle, onClick: onToggleExpand, "aria-expanded": isExpanded, "aria-label": `${isExpanded ? 'Collapse' : 'Expand'} track`, children: jsx_runtime_1.jsx("svg", { width: "12", height: "12", viewBox: "0 0 8 8", style: { display: 'block' }, children: jsx_runtime_1.jsx("path", { d: "M2 1L6 4L2 7Z", fill: "white" }) }) })) : (jsx_runtime_1.jsx("div", { style: arrowButton }))) : null, jsx_runtime_1.jsx(TimelineStack_1.TimelineStack, { sequence: sequence, isCompact: isCompact, originalLocation: originalLocation })
] }));
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [visualModeEnvEnabled ? (jsx_runtime_1.jsx(ContextMenu_1.ContextMenu, { values: contextMenuValues, children: trackRow })) : (trackRow), visualModeActive && isExpanded && sequence.controls ? (jsx_runtime_1.jsx(TimelineExpandedSection_1.TimelineExpandedSection, { sequence: sequence, originalLocation: originalLocation, nestedDepth: nestedDepth, nodePath: nodePath })) : null] }));
};
exports.TimelineListItem = TimelineListItem;