@remotion/studio
Version:
APIs for interacting with the Remotion Studio
210 lines (209 loc) • 12.6 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DuplicateComposition = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const url_state_1 = require("../../helpers/url-state");
const validate_new_comp_data_1 = require("../../helpers/validate-new-comp-data");
const layout_1 = require("../layout");
const ModalFooter_1 = require("../ModalFooter");
const ModalHeader_1 = require("../ModalHeader");
const layout_2 = require("../RenderModal/layout");
const ResolveCompositionBeforeModal_1 = require("../RenderModal/ResolveCompositionBeforeModal");
const CodemodFooter_1 = require("./CodemodFooter");
const ComboBox_1 = require("./ComboBox");
const DismissableModal_1 = require("./DismissableModal");
const InputDragger_1 = require("./InputDragger");
const NewCompDuration_1 = require("./NewCompDuration");
const RemInput_1 = require("./RemInput");
const ValidationMessage_1 = require("./ValidationMessage");
const content = {
padding: 12,
paddingRight: 12,
flex: 1,
fontSize: 13,
minWidth: 500,
};
const comboBoxStyle = {
width: 190,
};
const DuplicateCompositionLoaded = ({ initialType }) => {
const context = (0, react_1.useContext)(ResolveCompositionBeforeModal_1.ResolvedCompositionContext);
if (!context) {
throw new Error('Resolved composition context');
}
const { resolved, unresolved } = context;
const [initialCompType] = (0, react_1.useState)(initialType);
const hadDimensionsDefined = unresolved.width && unresolved.height;
const hadFpsDefined = unresolved.fps !== undefined;
const hadDurationDefined = unresolved.durationInFrames !== undefined;
const [selectedFrameRate, setFrameRate] = (0, react_1.useState)(resolved.result.fps);
const { compositions } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
const [type, setType] = (0, react_1.useState)(initialCompType);
const [newId, setName] = (0, react_1.useState)(() => {
var _a;
const numberAtEnd = (_a = resolved.result.id.match(/([0-9]+)$/)) === null || _a === void 0 ? void 0 : _a[0];
let prefix = numberAtEnd ? Number(numberAtEnd) : 1;
const initialName = resolved.result.id.replace(/([0-9]+)$/, '');
let currentName = initialName;
while (true) {
currentName = initialName + prefix;
const err = (0, validate_new_comp_data_1.validateCompositionName)(currentName, compositions);
if (!err) {
break;
}
prefix++;
}
return currentName;
});
const [size, setSize] = (0, react_1.useState)(() => ({
width: resolved.result.width,
height: resolved.result.height,
}));
const [durationInFrames, setDurationInFrames] = (0, react_1.useState)(resolved.result.durationInFrames);
const onTypeChanged = (0, react_1.useCallback)((newType) => {
setType(newType);
}, []);
const onWidthChanged = (0, react_1.useCallback)((newValue) => {
setSize((s) => {
const { height } = s;
const newWidth = Number(newValue);
return {
height,
width: newWidth,
};
});
}, []);
const onWidthDirectlyChanged = (0, react_1.useCallback)((newWidth) => {
setSize((s) => {
const { height } = s;
return {
height,
width: newWidth,
};
});
}, []);
const onHeightDirectlyChanged = (0, react_1.useCallback)((newHeight) => {
setSize((s) => {
const { width } = s;
return {
width,
height: newHeight,
};
});
}, []);
const onHeightChanged = (0, react_1.useCallback)((newValue) => {
setSize((s) => {
const { width } = s;
const newHeight = Number(newValue);
return {
width,
height: newHeight,
};
});
}, []);
const onNameChange = (0, react_1.useCallback)((e) => {
setName(e.target.value);
}, []);
const onTextFpsChange = (0, react_1.useCallback)((newFps) => {
setFrameRate(Number(newFps));
}, []);
const onFpsChange = (0, react_1.useCallback)((newFps) => {
setFrameRate(newFps);
}, []);
const compNameErrMessage = (0, validate_new_comp_data_1.validateCompositionName)(newId, compositions);
const compWidthErrMessage = (0, validate_new_comp_data_1.validateCompositionDimension)('Width', size.width);
const compHeightErrMessage = (0, validate_new_comp_data_1.validateCompositionDimension)('Height', size.height);
const typeValues = (0, react_1.useMemo)(() => {
return [
{
id: 'composition',
keyHint: null,
label: '<Composition />',
leftItem: null,
onClick: () => onTypeChanged('composition'),
subMenu: null,
type: 'item',
value: 'composition',
quickSwitcherLabel: null,
},
{
id: 'still',
keyHint: null,
label: '<Still />',
leftItem: null,
onClick: () => onTypeChanged('still'),
subMenu: null,
type: 'item',
value: 'still',
quickSwitcherLabel: null,
},
];
}, [onTypeChanged]);
const valid = compNameErrMessage === null &&
compWidthErrMessage === null &&
compHeightErrMessage === null;
const codemod = (0, react_1.useMemo)(() => {
return {
type: 'duplicate-composition',
idToDuplicate: resolved.result.id,
newDurationInFrames: hadDurationDefined ? Number(durationInFrames) : null,
newFps: hadFpsDefined ? Number(selectedFrameRate) : null,
newHeight: hadDimensionsDefined ? Number(size.height) : null,
newWidth: hadDimensionsDefined ? Number(size.width) : null,
newId,
tag: type === 'still' ? 'Still' : 'Composition',
};
}, [
durationInFrames,
hadDimensionsDefined,
hadDurationDefined,
hadFpsDefined,
newId,
resolved.result.id,
selectedFrameRate,
size.height,
size.width,
type,
]);
const onDuplicateSuccess = (0, react_1.useCallback)(() => {
(0, url_state_1.pushUrl)(`/${newId}`);
}, [newId]);
const onSubmit = (0, react_1.useCallback)((e) => {
e.preventDefault();
}, []);
return (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
jsx_runtime_1.jsx(ModalHeader_1.ModalHeader, { title: `Duplicate ${resolved.result.id}` }), jsx_runtime_1.jsxs("form", { onSubmit: onSubmit, children: [
jsx_runtime_1.jsxs("div", { style: content, children: [initialCompType === 'composition' ? (
// We allow converting from a composition to a still, but
// not the other way around
jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Type" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(ComboBox_1.Combobox, { title: "Type of composition", style: comboBoxStyle, values: typeValues, selectedId: type }) })
] })) : null, jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
jsx_runtime_1.jsx("div", { style: layout_2.label, children: "ID" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsxs("div", { children: [
jsx_runtime_1.jsx(RemInput_1.RemotionInput, { value: newId, onChange: onNameChange, type: "text", autoFocus: true, placeholder: "Composition ID", status: "ok", rightAlign: true }), compNameErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: compNameErrMessage, type: "error" })
] })) : null] }) })
] }), hadDimensionsDefined ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Width" }), jsx_runtime_1.jsxs("div", { style: layout_2.rightRow, children: [
jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: size.width, placeholder: "Width", onTextChange: onWidthChanged, name: "width", step: 2, min: 2, required: true, status: "ok", formatter: (w) => `${w}px`, max: 100000000, onValueChange: onWidthDirectlyChanged, rightAlign: false }), compWidthErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: compWidthErrMessage, type: "error" })
] })) : null] })
] }), jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
jsx_runtime_1.jsx("div", { style: layout_2.label, children: "Height" }), jsx_runtime_1.jsxs("div", { style: layout_2.rightRow, children: [
jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: size.height, onTextChange: onHeightChanged, placeholder: "Height", name: "height", step: 2, required: true, formatter: (h) => `${h}px`, min: 2, status: "ok", max: 100000000, onValueChange: onHeightDirectlyChanged, rightAlign: false }), compHeightErrMessage ? (jsx_runtime_1.jsxs(jsx_runtime_1.Fragment, { children: [
jsx_runtime_1.jsx(layout_1.Spacing, { y: 1, block: true }), jsx_runtime_1.jsx(ValidationMessage_1.ValidationMessage, { align: "flex-start", message: compHeightErrMessage, type: "error" })
] })) : null] })
] })
] })) : null, type === 'composition' && hadDurationDefined ? (jsx_runtime_1.jsx(NewCompDuration_1.NewCompDuration, { durationInFrames: durationInFrames, setDurationInFrames: setDurationInFrames })) : null, type === 'composition' && hadFpsDefined ? (jsx_runtime_1.jsxs("div", { style: layout_2.optionRow, children: [
jsx_runtime_1.jsx("div", { style: layout_2.label, children: "FPS" }), jsx_runtime_1.jsx("div", { style: layout_2.rightRow, children: jsx_runtime_1.jsx(InputDragger_1.InputDragger, { type: "number", value: selectedFrameRate, onTextChange: onTextFpsChange, placeholder: "Frame rate (fps)", name: "fps", min: 1, required: true, status: "ok", max: 240, step: 0.01, onValueChange: onFpsChange, rightAlign: false }) })
] })) : null] }), jsx_runtime_1.jsx(ModalFooter_1.ModalFooterContainer, { children: jsx_runtime_1.jsx(CodemodFooter_1.CodemodFooter, { loadingNotification: 'Duplicating...', errorNotification: 'Could not duplicate composition', successNotification: `Duplicated ${unresolved.id} as ${newId}`, genericSubmitLabel: 'Duplicate', submitLabel: ({ relativeRootPath }) => `Add to ${relativeRootPath}`, codemod: codemod, valid: valid, onSuccess: onDuplicateSuccess }) })
] })
] }));
};
const DuplicateComposition = ({ compositionId, compositionType }) => {
return (jsx_runtime_1.jsx(DismissableModal_1.DismissableModal, { children: jsx_runtime_1.jsx(ResolveCompositionBeforeModal_1.ResolveCompositionBeforeModal, { compositionId: compositionId, children: jsx_runtime_1.jsx(DuplicateCompositionLoaded, { initialType: compositionType }) }) }));
};
exports.DuplicateComposition = DuplicateComposition;