@remotion/studio
Version:
APIs for interacting with the Remotion Studio
324 lines (323 loc) • 14.8 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DataEditor = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const remotion_1 = require("remotion");
const no_react_1 = require("remotion/no-react");
const client_id_1 = require("../../helpers/client-id");
const colors_1 = require("../../helpers/colors");
const ValidationMessage_1 = require("../NewComposition/ValidationMessage");
const NotificationCenter_1 = require("../Notifications/NotificationCenter");
const actions_1 = require("../RenderQueue/actions");
const SegmentedControl_1 = require("../SegmentedControl");
const get_zod_if_possible_1 = require("../get-zod-if-possible");
const layout_1 = require("../layout");
const RenderModalJSONPropsEditor_1 = require("./RenderModalJSONPropsEditor");
const SchemaEditor_1 = require("./SchemaEditor/SchemaEditor");
const SchemaErrorMessages_1 = require("./SchemaEditor/SchemaErrorMessages");
const extract_enum_json_paths_1 = require("./SchemaEditor/extract-enum-json-paths");
const WarningIndicatorButton_1 = require("./WarningIndicatorButton");
const get_render_modal_warnings_1 = require("./get-render-modal-warnings");
const errorExplanation = {
fontSize: 14,
color: colors_1.LIGHT_TEXT,
fontFamily: 'sans-serif',
lineHeight: 1.5,
};
const explainer = {
display: 'flex',
flex: 1,
flexDirection: 'column',
padding: '0 12px',
justifyContent: 'center',
alignItems: 'center',
textAlign: 'center',
};
const outer = {
display: 'flex',
flexDirection: 'column',
flex: 1,
overflow: 'hidden',
backgroundColor: colors_1.BACKGROUND,
};
const controlContainer = {
flexDirection: 'column',
display: 'flex',
padding: 12,
borderBottom: `1px solid ${colors_1.BORDER_COLOR}`,
};
const tabWrapper = {
display: 'flex',
marginBottom: '4px',
flexDirection: 'row',
alignItems: 'center',
};
const persistanceKey = 'remotion.show-render-modalwarning';
const getPersistedShowWarningState = () => {
const val = localStorage.getItem(persistanceKey);
if (!val) {
return true;
}
return val === 'true';
};
const setPersistedShowWarningState = (val) => {
localStorage.setItem(persistanceKey, String(Boolean(val)));
};
const DataEditor = ({ unresolvedComposition, defaultProps, setDefaultProps, mayShowSaveButton, propsEditType, saving, setSaving, readOnlyStudio, }) => {
const [mode, setMode] = (0, react_1.useState)('schema');
const [showWarning, setShowWarningWithoutPersistance] = (0, react_1.useState)(() => getPersistedShowWarningState());
const { updateCompositionDefaultProps } = (0, react_1.useContext)(remotion_1.Internals.CompositionSetters);
const inJSONEditor = mode === 'json';
const serializedJSON = (0, react_1.useMemo)(() => {
if (!inJSONEditor) {
return null;
}
const value = defaultProps;
return no_react_1.NoReactInternals.serializeJSONWithSpecialTypes({
data: value,
indent: 2,
staticBase: window.remotion_staticBase,
});
}, [inJSONEditor, defaultProps]);
const cliProps = (0, remotion_1.getInputProps)();
const [canSaveDefaultPropsObjectState, setCanSaveDefaultProps] = (0, react_1.useState)({
[unresolvedComposition.id]: get_render_modal_warnings_1.defaultTypeCanSaveState,
});
const z = (0, get_zod_if_possible_1.useZodIfPossible)();
const zodTypes = (0, get_zod_if_possible_1.useZodTypesIfPossible)();
const schema = (0, react_1.useMemo)(() => {
if (!z) {
return 'no-zod';
}
if (!unresolvedComposition.schema) {
return 'no-schema';
}
if (!(typeof unresolvedComposition.schema.safeParse === 'function')) {
throw new Error('A value which is not a Zod schema was passed to `schema`');
}
return unresolvedComposition.schema;
}, [unresolvedComposition.schema, z]);
const zodValidationResult = (0, react_1.useMemo)(() => {
if (schema === 'no-zod') {
return 'no-zod';
}
if (schema === 'no-schema') {
return 'no-schema';
}
return schema.safeParse(defaultProps);
}, [defaultProps, schema]);
const setShowWarning = (0, react_1.useCallback)((val) => {
setShowWarningWithoutPersistance((prevVal) => {
if (typeof val === 'boolean') {
setPersistedShowWarningState(val);
return val;
}
setPersistedShowWarningState(val(prevVal));
return val(prevVal);
});
}, []);
const canSaveDefaultProps = (0, react_1.useMemo)(() => {
return canSaveDefaultPropsObjectState[unresolvedComposition.id]
? canSaveDefaultPropsObjectState[unresolvedComposition.id]
: get_render_modal_warnings_1.defaultTypeCanSaveState;
}, [canSaveDefaultPropsObjectState, unresolvedComposition.id]);
const showSaveButton = mayShowSaveButton && canSaveDefaultProps.canUpdate;
const { fastRefreshes } = (0, react_1.useContext)(remotion_1.Internals.NonceContext);
const checkIfCanSaveDefaultProps = (0, react_1.useCallback)(async () => {
try {
const can = await (0, actions_1.canUpdateDefaultProps)(unresolvedComposition.id, readOnlyStudio);
if (can.canUpdate) {
setCanSaveDefaultProps((prevState) => ({
...prevState,
[unresolvedComposition.id]: {
canUpdate: true,
},
}));
}
else {
setCanSaveDefaultProps((prevState) => ({
...prevState,
[unresolvedComposition.id]: {
canUpdate: false,
reason: can.reason,
determined: true,
},
}));
}
}
catch (err) {
setCanSaveDefaultProps((prevState) => ({
...prevState,
[unresolvedComposition.id]: {
canUpdate: false,
reason: err.message,
determined: true,
},
}));
}
}, [readOnlyStudio, unresolvedComposition.id]);
(0, react_1.useEffect)(() => {
checkIfCanSaveDefaultProps();
}, [checkIfCanSaveDefaultProps]);
const { previewServerState, subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
(0, react_1.useEffect)(() => {
const unsub = subscribeToEvent('root-file-changed', checkIfCanSaveDefaultProps);
return () => {
unsub();
};
}, [checkIfCanSaveDefaultProps, subscribeToEvent]);
const modeItems = (0, react_1.useMemo)(() => {
return [
{
key: 'schema',
label: 'Schema',
onClick: () => {
setMode('schema');
},
selected: mode === 'schema',
},
{
key: 'json',
label: 'JSON',
onClick: () => {
setMode('json');
},
selected: mode === 'json',
},
];
}, [mode]);
const onUpdate = (0, react_1.useCallback)(() => {
if (schema === 'no-zod' || schema === 'no-schema' || z === null) {
(0, NotificationCenter_1.showNotification)('Cannot update default props: No Zod schema', 2000);
return;
}
(0, actions_1.callUpdateDefaultPropsApi)(unresolvedComposition.id, defaultProps, (0, extract_enum_json_paths_1.extractEnumJsonPaths)({ schema, zodRuntime: z, currentPath: [], zodTypes })).then((response) => {
if (!response.success) {
(0, NotificationCenter_1.showNotification)(`Cannot update default props: ${response.reason}`, 2000);
}
});
}, [schema, z, unresolvedComposition.id, defaultProps, zodTypes]);
const onSave = (0, react_1.useCallback)((updater) => {
var _a;
if (schema === 'no-zod' || schema === 'no-schema' || z === null) {
(0, NotificationCenter_1.showNotification)('Cannot update default props: No Zod schema', 2000);
return;
}
window.remotion_ignoreFastRefreshUpdate = fastRefreshes + 1;
setSaving(true);
const newDefaultProps = updater((_a = unresolvedComposition.defaultProps) !== null && _a !== void 0 ? _a : {});
(0, actions_1.callUpdateDefaultPropsApi)(unresolvedComposition.id, newDefaultProps, (0, extract_enum_json_paths_1.extractEnumJsonPaths)({
schema,
zodRuntime: z,
currentPath: [],
zodTypes,
}))
.then((response) => {
if (!response.success) {
// eslint-disable-next-line no-console
console.log(response.stack);
(0, NotificationCenter_1.showNotification)(`Cannot update default props: ${response.reason}. See console for more information.`, 2000);
}
updateCompositionDefaultProps(unresolvedComposition.id, newDefaultProps);
})
.catch((err) => {
(0, NotificationCenter_1.showNotification)(`Cannot update default props: ${err.message}`, 2000);
})
.finally(() => {
setSaving(false);
});
}, [
schema,
z,
zodTypes,
fastRefreshes,
setSaving,
unresolvedComposition.defaultProps,
unresolvedComposition.id,
updateCompositionDefaultProps,
]);
const connectionStatus = previewServerState.type;
const warnings = (0, react_1.useMemo)(() => {
return (0, get_render_modal_warnings_1.getRenderModalWarnings)({
canSaveDefaultProps,
cliProps,
isCustomDateUsed: serializedJSON ? serializedJSON.customDateUsed : false,
customFileUsed: serializedJSON ? serializedJSON.customFileUsed : false,
inJSONEditor,
propsEditType,
jsMapUsed: serializedJSON ? serializedJSON.mapUsed : false,
jsSetUsed: serializedJSON ? serializedJSON.setUsed : false,
});
}, [
cliProps,
canSaveDefaultProps,
inJSONEditor,
propsEditType,
serializedJSON,
]);
if (connectionStatus === 'disconnected') {
return ((0, jsx_runtime_1.jsxs)("div", { style: explainer, children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 5 }), (0, jsx_runtime_1.jsx)("div", { style: errorExplanation, children: "The studio server has disconnected. Reconnect to edit the schema." }), (0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 2, block: true })] }));
}
if (schema === 'no-zod') {
return (0, jsx_runtime_1.jsx)(SchemaErrorMessages_1.ZodNotInstalled, {});
}
if (schema === 'no-schema') {
return (0, jsx_runtime_1.jsx)(SchemaErrorMessages_1.NoSchemaDefined, {});
}
if (!z) {
throw new Error('expected zod');
}
if (zodValidationResult === 'no-zod') {
throw new Error('expected zod');
}
if (zodValidationResult === 'no-schema') {
throw new Error('expected schema');
}
const def = schema._def;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const typeName = def.typeName;
if (typeName === z.ZodFirstPartyTypeKind.ZodAny) {
return (0, jsx_runtime_1.jsx)(SchemaErrorMessages_1.NoSchemaDefined, {});
}
if (!unresolvedComposition.defaultProps) {
return (0, jsx_runtime_1.jsx)(SchemaErrorMessages_1.NoDefaultProps, {});
}
return ((0, jsx_runtime_1.jsxs)("div", { style: outer, children: [(0, jsx_runtime_1.jsxs)("div", { style: controlContainer, children: [(0, jsx_runtime_1.jsxs)("div", { style: tabWrapper, children: [(0, jsx_runtime_1.jsx)(SegmentedControl_1.SegmentedControl, { items: modeItems, needsWrapping: false }), (0, jsx_runtime_1.jsx)(layout_1.Flex, {}), warnings.length > 0 ? ((0, jsx_runtime_1.jsx)(WarningIndicatorButton_1.WarningIndicatorButton, { setShowWarning: setShowWarning, showWarning: showWarning, warningCount: warnings.length })) : null] }), showWarning && warnings.length > 0
? warnings.map((warning) => ((0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [(0, jsx_runtime_1.jsx)(layout_1.Spacing, { y: 1 }), (0, jsx_runtime_1.jsx)(ValidationMessage_1.ValidationMessage, { message: warning, align: "flex-start", type: "warning" })] }, warning)))
: null] }), mode === 'schema' ? ((0, jsx_runtime_1.jsx)(SchemaEditor_1.SchemaEditor, { unsavedDefaultProps: defaultProps, setValue: setDefaultProps, schema: schema, zodValidationResult: zodValidationResult, savedDefaultProps: unresolvedComposition.defaultProps, onSave: onSave, showSaveButton: showSaveButton, saving: saving, saveDisabledByParent: !zodValidationResult.success })) : ((0, jsx_runtime_1.jsx)(RenderModalJSONPropsEditor_1.RenderModalJSONPropsEditor, { value: defaultProps !== null && defaultProps !== void 0 ? defaultProps : {}, setValue: setDefaultProps, onSave: onUpdate, showSaveButton: showSaveButton, serializedJSON: serializedJSON, defaultProps: unresolvedComposition.defaultProps, schema: schema }))] }));
};
exports.DataEditor = DataEditor;