Add .gitignore to exclude all node packages and lock files

This commit is contained in:
Adolfo Reyna
2026-02-23 21:56:04 -05:00
parent faae96c9ed
commit dcc5c6c044
9747 changed files with 1555105 additions and 2 deletions
@@ -0,0 +1,6 @@
import type { TSequence } from 'remotion';
import type { TrackWithHash } from './get-timeline-sequence-sort-key';
export declare const calculateTimeline: ({ sequences, sequenceDuration, }: {
sequences: TSequence[];
sequenceDuration: number;
}) => TrackWithHash[];
@@ -0,0 +1,74 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.calculateTimeline = void 0;
const get_sequence_visible_range_1 = require("./get-sequence-visible-range");
const get_timeline_nestedness_1 = require("./get-timeline-nestedness");
const get_timeline_sequence_hash_1 = require("./get-timeline-sequence-hash");
const get_timeline_sequence_sort_key_1 = require("./get-timeline-sequence-sort-key");
const calculateTimeline = ({ sequences, sequenceDuration, }) => {
const tracks = [];
if (sequences.length === 0) {
return [
{
sequence: {
displayName: '',
duration: sequenceDuration,
from: 0,
id: 'seq',
parent: null,
type: 'sequence',
rootId: '-',
showInTimeline: true,
nonce: 0,
loopDisplay: undefined,
stack: null,
premountDisplay: null,
postmountDisplay: null,
},
depth: 0,
hash: '-',
},
];
}
const sameHashes = {};
const hashesUsedInRoot = {};
const cache = {};
for (let i = 0; i < sequences.length; i++) {
const sequence = sequences[i];
if (!hashesUsedInRoot[sequence.rootId]) {
hashesUsedInRoot[sequence.rootId] = [];
}
const actualHash = (0, get_timeline_sequence_hash_1.getTimelineSequenceHash)(sequence, sequences, hashesUsedInRoot, cache);
if (!sameHashes[actualHash]) {
sameHashes[actualHash] = [];
}
sameHashes[actualHash].push(sequence.id);
const cascadedStart = (0, get_sequence_visible_range_1.getCascadedStart)(sequence, sequences);
const visibleStart = (0, get_sequence_visible_range_1.getTimelineVisibleStart)(sequence, sequences);
const visibleDuration = (0, get_sequence_visible_range_1.getTimelineVisibleDuration)(sequence, sequences);
tracks.push({
sequence: {
...sequence,
from: visibleStart,
duration: visibleDuration,
},
depth: (0, get_timeline_nestedness_1.getTimelineNestedLevel)(sequence, sequences, 0),
hash: actualHash,
cascadedStart,
cascadedDuration: sequence.duration,
});
}
const uniqueTracks = [];
for (const track of tracks) {
if (!uniqueTracks.find((t) => t.hash === track.hash)) {
const { cascadedDuration, cascadedStart, ...cleanTrack } = track;
uniqueTracks.push(cleanTrack);
}
}
return uniqueTracks.sort((a, b) => {
const sortKeyA = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(a, tracks, sameHashes);
const sortKeyB = (0, get_timeline_sequence_sort_key_1.getTimelineSequenceSequenceSortKey)(b, tracks, sameHashes);
return sortKeyA.localeCompare(sortKeyB);
});
};
exports.calculateTimeline = calculateTimeline;
@@ -0,0 +1 @@
export declare const checkFullscreenSupport: () => any;
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkFullscreenSupport = void 0;
const checkFullscreenSupport = () => {
return (document.fullscreenEnabled ||
// @ts-expect-error Types not defined
document.webkitFullscreenEnabled);
};
exports.checkFullscreenSupport = checkFullscreenSupport;
@@ -0,0 +1,4 @@
export declare const getCheckerboardBackgroundSize: (size: number) => string;
export declare const getCheckerboardBackgroundPos: (size: number) => string;
export declare const checkerboardBackgroundColor: (checkerboard: boolean) => "black" | "white";
export declare const checkerboardBackgroundImage: (checkerboard: boolean) => "\n linear-gradient(\n 45deg,\n rgba(0, 0, 0, 0.1) 25%,\n transparent 25%\n ),\n linear-gradient(135deg, rgba(0, 0, 0, 0.1) 25%, transparent 25%),\n linear-gradient(45deg, transparent 75%, rgba(0, 0, 0, 0.1) 75%),\n linear-gradient(135deg, transparent 75%, rgba(0, 0, 0, 0.1) 75%)\n " | undefined;
@@ -0,0 +1,30 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.checkerboardBackgroundImage = exports.checkerboardBackgroundColor = exports.getCheckerboardBackgroundPos = exports.getCheckerboardBackgroundSize = void 0;
const getCheckerboardBackgroundSize = (size) => `${size}px ${size}px`;
exports.getCheckerboardBackgroundSize = getCheckerboardBackgroundSize;
const getCheckerboardBackgroundPos = (size) => `0 0, ${size / 2}px 0, ${size / 2}px -${size / 2}px, 0px ${size / 2}px`;
exports.getCheckerboardBackgroundPos = getCheckerboardBackgroundPos;
const checkerboardBackgroundColor = (checkerboard) => {
if (checkerboard) {
return 'white';
}
return 'black';
};
exports.checkerboardBackgroundColor = checkerboardBackgroundColor;
const checkerboardBackgroundImage = (checkerboard) => {
if (checkerboard) {
return `
linear-gradient(
45deg,
rgba(0, 0, 0, 0.1) 25%,
transparent 25%
),
linear-gradient(135deg, rgba(0, 0, 0, 0.1) 25%, transparent 25%),
linear-gradient(45deg, transparent 75%, rgba(0, 0, 0, 0.1) 75%),
linear-gradient(135deg, transparent 75%, rgba(0, 0, 0, 0.1) 75%)
`;
}
return undefined;
};
exports.checkerboardBackgroundImage = checkerboardBackgroundImage;
@@ -0,0 +1,20 @@
import type { EventSourceEvent } from '@remotion/studio-shared';
import React from 'react';
type PreviewServerState = {
type: 'init';
} | {
type: 'connected';
clientId: string;
} | {
type: 'disconnected';
};
type Context = {
previewServerState: PreviewServerState;
subscribeToEvent: (type: EventSourceEvent['type'], listener: (event: EventSourceEvent) => void) => () => void;
};
export declare const StudioServerConnectionCtx: React.Context<Context>;
export declare const PreviewServerConnection: React.FC<{
readonly children: React.ReactNode;
readonly readOnlyStudio: boolean;
}>;
export {};
@@ -0,0 +1,146 @@
"use strict";
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;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PreviewServerConnection = exports.StudioServerConnectionCtx = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = __importStar(require("react"));
const remotion_1 = require("remotion");
const NotificationCenter_1 = require("../components/Notifications/NotificationCenter");
const PlayBeepSound_1 = __importDefault(require("../components/PlayBeepSound"));
const context_1 = require("../components/RenderQueue/context");
const url_state_1 = require("./url-state");
exports.StudioServerConnectionCtx = react_1.default.createContext({
previewServerState: {
type: 'init',
},
subscribeToEvent: () => {
throw new Error('Context not initalized');
},
});
const PreviewServerConnection = ({ children, readOnlyStudio }) => {
const listeners = (0, react_1.useRef)([]);
const subscribeToEvent = (0, react_1.useCallback)((type, listener) => {
listeners.current.push({ type, listener });
return () => {
listeners.current = listeners.current.filter((l) => l.type !== type || l.listener !== listener);
};
}, []);
const openEventSource = (0, react_1.useCallback)(() => {
const source = new EventSource('/events');
source.addEventListener('message', (event) => {
var _a, _b;
const newEvent = JSON.parse(event.data);
if (newEvent.type === 'new-input-props' ||
newEvent.type === 'new-env-variables') {
(0, url_state_1.reloadUrl)();
}
if (newEvent.type === 'init') {
setState({
type: 'connected',
clientId: newEvent.clientId,
});
}
if (newEvent.type === 'render-queue-updated') {
(_a = context_1.renderJobsRef.current) === null || _a === void 0 ? void 0 : _a.updateRenderJobs(newEvent.queue);
for (const job of newEvent.queue) {
if (job.status === 'done' && job.beepOnFinish) {
(0, PlayBeepSound_1.default)(job.id);
}
}
}
if (newEvent.type === 'client-renders-updated') {
(_b = context_1.renderJobsRef.current) === null || _b === void 0 ? void 0 : _b.updateClientRenders(newEvent.renders);
}
if (newEvent.type === 'render-job-failed') {
(0, NotificationCenter_1.showNotification)(`Rendering "${newEvent.compositionId}" failed`, 2000);
}
if (newEvent.type === 'new-public-folder') {
const payload = {
files: newEvent.files,
};
window.remotion_staticFiles = newEvent.files;
window.remotion_publicFolderExists = newEvent.folderExists;
window.dispatchEvent(new CustomEvent(remotion_1.Internals.WATCH_REMOTION_STATIC_FILES, {
detail: payload,
}));
}
listeners.current.forEach((l) => {
if (l.type === newEvent.type) {
l.listener(newEvent);
}
});
});
source.addEventListener('open', () => {
source.addEventListener('error', () => {
setState({ type: 'disconnected' });
// Display an error message that the studio server has disconnected.
source === null || source === void 0 ? void 0 : source.close();
// Retry later
setTimeout(() => {
openEventSource();
}, 1000);
}, { once: true });
});
const close = () => {
source.close();
};
return {
close,
};
}, []);
(0, react_1.useEffect)(() => {
if (readOnlyStudio) {
return;
}
const { close } = openEventSource();
return () => {
close();
};
}, [openEventSource, readOnlyStudio]);
const [state, setState] = react_1.default.useState({
type: 'init',
});
const context = (0, react_1.useMemo)(() => {
return {
previewServerState: state,
subscribeToEvent,
};
}, [state, subscribeToEvent]);
return ((0, jsx_runtime_1.jsx)(exports.StudioServerConnectionCtx.Provider, { value: context, children: children }));
};
exports.PreviewServerConnection = PreviewServerConnection;
@@ -0,0 +1,2 @@
import type { ZodTypesType } from '../components/get-zod-if-possible';
export declare const colorWithNewOpacity: (color: string, opacity: number, zodTypes: ZodTypesType) => string;
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.colorWithNewOpacity = void 0;
const colorWithNewOpacity = (color, opacity, zodTypes) => {
const { r, g, b } = zodTypes.ZodZypesInternals.parseColor(color);
if (opacity >= 255) {
return `#${r.toString(16).padStart(2, '0')}${g
.toString(16)
.padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;
}
return `rgba(${r}, ${g}, ${b}, ${(opacity / 255).toFixed(2)})`;
};
exports.colorWithNewOpacity = colorWithNewOpacity;
@@ -0,0 +1,27 @@
export declare const BACKGROUND = "rgb(31,36,40)";
export declare const BACKGROUND__TRANSPARENT = "rgba(31,36,40, 0)";
export declare const INPUT_BACKGROUND = "#2f363d";
export declare const BORDER_COLOR = "#000";
export declare const LIGHT_COLOR = "#ddd";
export declare const SELECTED_BACKGROUND = "hsla(0, 0%, 100%, 0.15)";
export declare const LIGHT_TEXT = "#A6A7A9";
export declare const RULER_COLOR = "#808080";
export declare const VERY_LIGHT_TEXT = "rgba(255, 255, 255, 0.3)";
export declare const CLEAR_HOVER = "rgba(255, 255, 255, 0.06)";
export declare const INPUT_BORDER_COLOR_UNHOVERED = "rgba(0, 0, 0, 0.6)";
export declare const INPUT_BORDER_COLOR_HOVERED = "rgba(255, 255, 255, 0.05)";
export declare const TIMELINE_BACKGROUND = "#111";
export declare const FAIL_COLOR = "#ff3232";
export declare const TEXT_COLOR = "#fff";
export declare const WARNING_COLOR = "#f1c40f";
export declare const BLUE = "#0b84f3";
export declare const BLUE_DISABLED = "#284f73";
export declare const LIGHT_TRANSPARENT = "rgba(255, 255, 255, 0.7)";
export declare const UNSELECTED_GUIDE = "#7e1219";
export declare const SELECTED_GUIDE = "#d22d3a";
export declare const LINE_COLOR = "#363A3E";
export declare const TIMELINE_TRACK_SEPARATOR = "rgba(0, 0, 0, 0.3)";
export declare const getBackgroundFromHoverState: ({ selected, hovered, }: {
selected: boolean;
hovered: boolean;
}) => "hsla(0, 0%, 100%, 0.15)" | "hsla(0, 0%, 100%, 0.25)" | "rgba(255, 255, 255, 0.06)" | "transparent";
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getBackgroundFromHoverState = exports.TIMELINE_TRACK_SEPARATOR = exports.LINE_COLOR = exports.SELECTED_GUIDE = exports.UNSELECTED_GUIDE = exports.LIGHT_TRANSPARENT = exports.BLUE_DISABLED = exports.BLUE = exports.WARNING_COLOR = exports.TEXT_COLOR = exports.FAIL_COLOR = exports.TIMELINE_BACKGROUND = exports.INPUT_BORDER_COLOR_HOVERED = exports.INPUT_BORDER_COLOR_UNHOVERED = exports.CLEAR_HOVER = exports.VERY_LIGHT_TEXT = exports.RULER_COLOR = exports.LIGHT_TEXT = exports.SELECTED_BACKGROUND = exports.LIGHT_COLOR = exports.BORDER_COLOR = exports.INPUT_BACKGROUND = exports.BACKGROUND__TRANSPARENT = exports.BACKGROUND = void 0;
exports.BACKGROUND = 'rgb(31,36,40)';
exports.BACKGROUND__TRANSPARENT = 'rgba(31,36,40, 0)';
exports.INPUT_BACKGROUND = '#2f363d';
exports.BORDER_COLOR = '#000';
exports.LIGHT_COLOR = '#ddd';
exports.SELECTED_BACKGROUND = 'hsla(0, 0%, 100%, 0.15)';
exports.LIGHT_TEXT = '#A6A7A9';
exports.RULER_COLOR = '#808080';
exports.VERY_LIGHT_TEXT = 'rgba(255, 255, 255, 0.3)';
const SELECTED_HOVER_BACKGROUND = 'hsla(0, 0%, 100%, 0.25)';
exports.CLEAR_HOVER = 'rgba(255, 255, 255, 0.06)';
exports.INPUT_BORDER_COLOR_UNHOVERED = 'rgba(0, 0, 0, 0.6)';
exports.INPUT_BORDER_COLOR_HOVERED = 'rgba(255, 255, 255, 0.05)';
exports.TIMELINE_BACKGROUND = '#111';
exports.FAIL_COLOR = '#ff3232';
exports.TEXT_COLOR = '#fff';
exports.WARNING_COLOR = '#f1c40f';
exports.BLUE = '#0b84f3';
exports.BLUE_DISABLED = '#284f73';
exports.LIGHT_TRANSPARENT = 'rgba(255, 255, 255, 0.7)';
exports.UNSELECTED_GUIDE = '#7e1219';
exports.SELECTED_GUIDE = '#d22d3a';
exports.LINE_COLOR = '#363A3E';
exports.TIMELINE_TRACK_SEPARATOR = 'rgba(0, 0, 0, 0.3)';
const getBackgroundFromHoverState = ({ selected, hovered, }) => {
if (selected) {
if (hovered) {
return SELECTED_HOVER_BACKGROUND;
}
return exports.SELECTED_BACKGROUND;
}
if (hovered) {
return exports.CLEAR_HOVER;
}
return 'transparent';
};
exports.getBackgroundFromHoverState = getBackgroundFromHoverState;
@@ -0,0 +1,2 @@
export declare const envVariablesObjectToArray: (envVariables: Record<string, string>) => [string, string][];
export declare const envVariablesArrayToObject: (envVariables: [string, string][]) => Record<string, string>;
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.envVariablesArrayToObject = exports.envVariablesObjectToArray = void 0;
const envVariablesObjectToArray = (envVariables) => {
return Object.entries(envVariables).map(([key, one]) => [
key.trim().toUpperCase(),
one.trim(),
]);
};
exports.envVariablesObjectToArray = envVariablesObjectToArray;
const envVariablesArrayToObject = (envVariables) => {
return envVariables
.map(([key, val]) => [key.trim(), val.trim()])
.filter(([key, val]) => key && val)
.reduce((acc, [key, value]) => {
acc[key.toUpperCase()] = value;
return acc;
}, {});
};
exports.envVariablesArrayToObject = envVariablesArrayToObject;
@@ -0,0 +1 @@
export declare const copyText: (cmd: string) => Promise<void>;
@@ -0,0 +1,23 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.copyText = void 0;
const copyText = (cmd) => {
const permissionName = 'clipboard-write';
return new Promise((resolve, reject) => {
navigator.permissions
.query({ name: permissionName })
.then((result) => {
if (result.state === 'granted' || result.state === 'prompt') {
navigator.clipboard.writeText(cmd);
resolve();
}
else {
reject(new Error('Permission to copy not granted'));
}
})
.catch((err) => {
reject(err);
});
});
};
exports.copyText = copyText;
@@ -0,0 +1,17 @@
import type { _InternalTypes, StaticFile, TFolder } from 'remotion';
import type { CompositionSelectorItemType } from '../components/CompositionSelectorItem';
export type AssetFolder = {
name: string;
items: AssetStructure;
expanded: boolean;
};
export type AssetStructure = {
files: StaticFile[];
folders: AssetFolder[];
};
export declare const buildAssetFolderStructure: (files: StaticFile[], parentFolderName: string | null, foldersExpanded: Record<string, boolean>) => AssetStructure;
export declare const splitParentIntoNameAndParent: (name: string | null) => {
name: string | null;
parent: string | null;
};
export declare const createFolderTree: (comps: _InternalTypes["AnyComposition"][], folders: TFolder[], foldersExpanded: Record<string, boolean>) => CompositionSelectorItemType[];
@@ -0,0 +1,140 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.createFolderTree = exports.splitParentIntoNameAndParent = exports.buildAssetFolderStructure = void 0;
const persist_open_folders_1 = require("./persist-open-folders");
const buildAssetFolderStructure = (files, parentFolderName, foldersExpanded) => {
const notInFolder = files.filter((f) => !f.name.includes('/'));
const inFolder = files.filter((f) => f.name.includes('/'));
const groupedByFolder = {};
for (const item of inFolder) {
const folderName = item.name.split('/')[0];
if (!groupedByFolder[folderName]) {
groupedByFolder[folderName] = [];
}
groupedByFolder[folderName].push(item);
}
return {
files: notInFolder,
folders: Object.keys(groupedByFolder).map((folderName) => {
var _a;
const filesInFolder = groupedByFolder[folderName];
const filesWithoutFolderName = filesInFolder.map((f) => {
return {
...f,
name: f.name.substring(folderName.length + 1),
};
});
const key = [parentFolderName, folderName].filter(Boolean).join('/');
const isExpanded = (_a = foldersExpanded[key]) !== null && _a !== void 0 ? _a : false;
return {
name: folderName,
items: (0, exports.buildAssetFolderStructure)(filesWithoutFolderName, [parentFolderName, folderName].filter(Boolean).join('/'), foldersExpanded),
expanded: isExpanded,
};
}),
};
};
exports.buildAssetFolderStructure = buildAssetFolderStructure;
const splitParentIntoNameAndParent = (name) => {
if (name === null) {
return {
name: null,
parent: null,
};
}
const splitted = name.split('/');
const lastName = splitted[splitted.length - 1];
const parentParentArray = splitted.slice(0, splitted.length - 1);
const parentParent = parentParentArray.length === 0 ? null : parentParentArray.join('/');
return {
name: lastName,
parent: parentParent,
};
};
exports.splitParentIntoNameAndParent = splitParentIntoNameAndParent;
const doesFolderExist = (items, folderName, parentName) => {
for (const item of items) {
if (item.type === 'folder') {
if (item.folderName === folderName && item.parentName === parentName) {
return item.items;
}
const found = doesFolderExist(item.items, folderName, parentName);
if (found !== false) {
return found;
}
}
}
return false;
};
const findItemListToPush = (items, folderName, parentName) => {
if (folderName === null) {
return items;
}
const folder = doesFolderExist(items, folderName, parentName);
if (!folder) {
// eslint-disable-next-line no-console
console.log({ items, folderName, parentName });
throw new Error('did not find folder ' + folderName);
}
return folder;
};
const createFolderIfDoesNotExist = (items, availableFolders, folderItem, foldersExpanded) => {
var _a;
if (doesFolderExist(items, folderItem.name, folderItem.parent)) {
return;
}
const splitted = (0, exports.splitParentIntoNameAndParent)(folderItem.parent);
if (folderItem.parent) {
const parent = availableFolders.find((f) => f.name === splitted.name && f.parent === splitted.parent);
if (!parent) {
throw new Error('unexpectedly did not have parent');
}
createFolderIfDoesNotExist(items, availableFolders, parent, foldersExpanded);
}
const itemList = findItemListToPush(items, splitted.name, splitted.parent);
if (!itemList) {
throw new Error('why did folder not exist? ' + folderItem.name);
}
itemList.push({
type: 'folder',
folderName: folderItem.name,
items: [],
key: folderItem.name,
expanded: (_a = foldersExpanded[(0, persist_open_folders_1.openFolderKey)({
folderName: folderItem.name,
parentName: folderItem.parent,
})]) !== null && _a !== void 0 ? _a : false,
parentName: folderItem.parent,
});
};
const createFolderTree = (comps, folders, foldersExpanded) => {
const items = [];
const uniqueFolderKeys = [];
for (const folder of folders) {
const folderKey = (0, persist_open_folders_1.openFolderKey)({
folderName: folder.name,
parentName: folder.parent,
});
if (uniqueFolderKeys.includes(folderKey)) {
if (folder.parent) {
throw new Error(`Multiple folders with the name ${folder.name} inside the folder ${folder.parent} exist. Folder names must be unique.`);
}
throw new Error('Multiple folders with the name ' +
folder.name +
' exist. Folder names must be unique.');
}
uniqueFolderKeys.push(folderKey);
createFolderIfDoesNotExist(items, folders, folder, foldersExpanded);
}
for (const item of comps) {
const toPush = {
type: 'composition',
composition: item,
key: item.id,
};
const list = findItemListToPush(items, item.folderName, item.parentFolderName);
list.push(toPush);
}
return items;
};
exports.createFolderTree = createFolderTree;
@@ -0,0 +1,4 @@
import type { AnyRenderJob } from '../components/RenderQueue/context';
export declare const setCurrentCanvasContentId: (id: string | null) => void;
export declare const setUnsavedProps: (unsaved: boolean) => void;
export declare const setRenderJobs: (jobs: AnyRenderJob[]) => void;
@@ -0,0 +1,76 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.setRenderJobs = exports.setUnsavedProps = exports.setCurrentCanvasContentId = void 0;
const no_react_1 = require("remotion/no-react");
const context_1 = require("../components/RenderQueue/context");
let currentItemName = null;
let unsavedProps = false;
let tabInactive = false;
let renderJobs = [];
const setCurrentCanvasContentId = (id) => {
if (!id) {
currentItemName = id;
updateTitle();
return;
}
const idWithoutFolder = id.split('/').pop();
currentItemName = idWithoutFolder;
updateTitle();
};
exports.setCurrentCanvasContentId = setCurrentCanvasContentId;
const setUnsavedProps = (unsaved) => {
window.remotion_unsavedProps = unsaved;
unsavedProps = unsaved;
};
exports.setUnsavedProps = setUnsavedProps;
const setRenderJobs = (jobs) => {
renderJobs = jobs;
updateTitle();
};
exports.setRenderJobs = setRenderJobs;
document.addEventListener('visibilitychange', () => {
tabInactive = document.visibilityState === 'hidden';
updateTitle();
});
const productName = 'Remotion Studio';
const suffix = `- ${productName}`;
const updateTitle = () => {
if (!currentItemName) {
document.title = productName;
return;
}
const currentCompTitle = `${currentItemName} / ${window.remotion_projectName}`;
document.title = [
getProgressInBrackets(currentItemName, renderJobs),
unsavedProps && tabInactive ? '✏️' : null,
`${currentCompTitle} ${suffix}`,
]
.filter(no_react_1.NoReactInternals.truthy)
.join(' ');
};
const getProgressInBrackets = (selectedCompositionId, jobs) => {
const currentRender = jobs.find((job) => job.status === 'running');
if (!currentRender) {
return null;
}
if (currentRender.status !== 'running') {
throw new Error('expected running job');
}
let progInPercent;
if ((0, context_1.isClientRenderJob)(currentRender)) {
const { renderedFrames, totalFrames } = currentRender.progress;
progInPercent =
totalFrames > 0 ? Math.ceil((renderedFrames / totalFrames) * 100) : 0;
}
else {
progInPercent = Math.ceil(currentRender.progress.value * 100);
}
const progressInBrackets = currentRender.compositionId === selectedCompositionId
? `[${progInPercent}%]`
: `[${progInPercent}% ${currentRender.compositionId}]`;
return progressInBrackets;
};
document.addEventListener('visibilitychange', () => {
tabInactive = document.visibilityState === 'hidden';
updateTitle();
});
@@ -0,0 +1,39 @@
import type { Size } from '@remotion/player';
import type { Guide } from '../state/editor-guides';
export declare const drawMarkingOnRulerCanvas: ({ scale, points, startMarking, originOffset, markingGaps, orientation, rulerCanvasRef, selectedGuide, canvasHeight, canvasWidth, }: {
scale: number;
points: Array<{
position: number;
value: number;
}>;
startMarking: number;
originOffset: number;
markingGaps: number;
orientation: "horizontal" | "vertical";
rulerCanvasRef: React.RefObject<HTMLCanvasElement | null>;
selectedGuide: Guide | null;
canvasWidth: number;
canvasHeight: number;
}) => void;
export declare const getRulerPoints: ({ rulerScaleRange, rulerMarkingGaps, scale, }: {
rulerScaleRange: {
start: number;
end: number;
};
rulerMarkingGaps: number;
scale: number;
}) => {
points: {
value: number;
position: number;
}[];
startMarking: number;
};
export declare const getRulerScaleRange: ({ canvasLength, scale, canvasSize, }: {
canvasLength: number;
scale: number;
canvasSize: Size;
}) => {
start: number;
end: number;
};
@@ -0,0 +1,178 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRulerScaleRange = exports.getRulerPoints = exports.drawMarkingOnRulerCanvas = void 0;
const editor_rulers_1 = require("../state/editor-rulers");
const colors_1 = require("./colors");
const drawLabel = ({ orientation, context, label, originDistance, color, }) => {
context.fillStyle = color;
if (orientation === 'horizontal') {
context.fillText(label, originDistance + 4, 16);
}
else {
context.rotate(-Math.PI / 2);
context.fillText(label, -originDistance + 4, 16);
context.rotate(Math.PI / 2);
}
};
const drawGradient = ({ orientation, context, originDistance, canvasHeight, canvasWidth, }) => {
const size = 250;
const startX = orientation === 'horizontal' ? originDistance - size / 2 : 0;
const startY = orientation === 'horizontal' ? 0 : originDistance - size / 2;
const endX = orientation === 'horizontal' ? originDistance + size / 2 : canvasWidth;
const endY = orientation === 'horizontal' ? canvasHeight : originDistance + size / 2;
const grd = context.createLinearGradient(startX, startY, endX, endY);
grd.addColorStop(0, colors_1.BACKGROUND__TRANSPARENT);
grd.addColorStop(0.25, colors_1.BACKGROUND);
grd.addColorStop(0.75, colors_1.BACKGROUND);
grd.addColorStop(1, colors_1.BACKGROUND__TRANSPARENT);
context.fillStyle = grd;
context.fillRect(startX, startY, endX - startX, endY - startY);
};
const drawGuide = ({ selectedGuide, scale, startMarking, context, canvasHeight, canvasWidth, orientation, originOffset, }) => {
const originDistance = rulerValueToPosition({
value: selectedGuide.position,
startMarking,
scale,
}) +
originOffset -
startMarking * scale;
drawGradient({
canvasHeight,
context,
orientation,
originDistance,
canvasWidth,
});
context.strokeStyle = colors_1.SELECTED_GUIDE;
context.lineWidth = 1;
context.beginPath();
if (orientation === 'horizontal' &&
selectedGuide.orientation === 'horizontal') {
return;
}
if (orientation === 'vertical' && selectedGuide.orientation === 'vertical') {
return;
}
if (orientation === 'vertical' &&
selectedGuide.orientation === 'horizontal') {
context.moveTo(0, originDistance);
context.lineTo(canvasWidth, originDistance);
drawLabel({
context,
label: selectedGuide.position.toString(),
originDistance,
orientation,
color: colors_1.SELECTED_GUIDE,
});
}
else if (orientation === 'horizontal' &&
selectedGuide.orientation === 'vertical') {
context.moveTo(originDistance, 0);
context.lineTo(originDistance, canvasHeight);
drawLabel({
context,
label: selectedGuide.position.toString(),
originDistance,
orientation,
color: colors_1.SELECTED_GUIDE,
});
}
context.stroke();
};
const drawMarkingOnRulerCanvas = ({ scale, points, startMarking, originOffset, markingGaps, orientation, rulerCanvasRef, selectedGuide, canvasHeight, canvasWidth, }) => {
const canvas = rulerCanvasRef.current;
if (!canvas)
return;
const context = canvas.getContext('2d');
if (!context)
return;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
context.scale(window.devicePixelRatio, window.devicePixelRatio);
context.clearRect(0, 0, canvasWidth, canvasHeight);
context.strokeStyle = colors_1.RULER_COLOR;
context.lineWidth = 1;
context.beginPath();
points.forEach((point) => {
context.strokeStyle = colors_1.RULER_COLOR;
context.lineWidth = 1;
const originDistance = point.position + originOffset - startMarking * scale;
context.beginPath();
if (orientation === 'horizontal') {
context.moveTo(originDistance, 0);
context.lineTo(originDistance, canvasHeight);
}
else {
context.moveTo(0, originDistance);
context.lineTo(canvasWidth, originDistance);
}
for (let i = 1; i < 5; i++) {
const markingOffsetXY = i * markingGaps * scale;
if (orientation === 'horizontal') {
context.moveTo(originDistance + markingOffsetXY / 5, 0);
context.lineTo(originDistance + markingOffsetXY / 5, 4);
}
else {
context.moveTo(0, originDistance + markingOffsetXY / 5);
context.lineTo(4, originDistance + markingOffsetXY / 5);
}
}
context.stroke();
context.font = '10px Arial, Helvetica, sans-serif';
context.textAlign = 'left';
context.fillStyle = colors_1.RULER_COLOR;
drawLabel({
orientation,
context,
label: point.value.toString(),
originDistance,
color: colors_1.RULER_COLOR,
});
});
if (selectedGuide && orientation !== selectedGuide.orientation) {
drawGuide({
canvasHeight,
canvasWidth,
context,
orientation,
originOffset,
scale,
selectedGuide,
startMarking,
});
}
};
exports.drawMarkingOnRulerCanvas = drawMarkingOnRulerCanvas;
const getRulerPoints = ({ rulerScaleRange, rulerMarkingGaps, scale, }) => {
const points = [];
const startPoint = Math.ceil(rulerScaleRange.start / rulerMarkingGaps);
const endPoint = Math.floor(rulerScaleRange.end / rulerMarkingGaps);
const startMarking = startPoint * rulerMarkingGaps;
for (let i = startPoint; i <= endPoint; i++) {
points.push({
value: i * rulerMarkingGaps,
position: rulerValueToPosition({
scale,
startMarking,
value: i * rulerMarkingGaps,
}),
});
}
return {
points,
startMarking,
};
};
exports.getRulerPoints = getRulerPoints;
const rulerValueToPosition = ({ value, startMarking, scale, }) => {
return (value + startMarking) * scale;
};
const getRulerScaleRange = ({ canvasLength, scale, canvasSize, }) => {
const scaleRangeBeyondCanvas = (canvasSize.width ||
editor_rulers_1.MINIMUM_VISIBLE_CANVAS_SIZE - editor_rulers_1.MINIMUM_VISIBLE_CANVAS_SIZE) / scale;
return {
start: -scaleRangeBeyondCanvas,
end: scaleRangeBeyondCanvas + canvasLength,
};
};
exports.getRulerScaleRange = getRulerScaleRange;
@@ -0,0 +1,18 @@
import type { VideoSample } from 'mediabunny';
type Options = {
track: {
width: number;
height: number;
};
container: string;
durationInSeconds: number | null;
};
export type ExtractFramesTimestampsInSecondsFn = (options: Options) => Promise<number[]> | number[];
export type ExtractFramesProps = {
src: string;
timestampsInSeconds: number[] | ExtractFramesTimestampsInSecondsFn;
onVideoSample: (sample: VideoSample) => void;
signal?: AbortSignal;
};
export declare function extractFrames({ src, timestampsInSeconds, onVideoSample, signal, }: ExtractFramesProps): Promise<void>;
export {};
@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractFrames = extractFrames;
const mediabunny_1 = require("mediabunny");
async function extractFrames({ src, timestampsInSeconds, onVideoSample, signal, }) {
const input = new mediabunny_1.Input({
formats: mediabunny_1.ALL_FORMATS,
source: new mediabunny_1.UrlSource(src),
});
const dispose = () => {
input.dispose();
};
if (signal) {
signal.addEventListener('abort', dispose, { once: true });
}
try {
const [durationInSeconds, format, videoTrack] = await Promise.all([
input.computeDuration(),
input.getFormat(),
input.getPrimaryVideoTrack(),
]);
if (!videoTrack) {
throw new Error('No video track found in the input');
}
const timestamps = typeof timestampsInSeconds === 'function'
? await timestampsInSeconds({
track: {
width: videoTrack.displayWidth,
height: videoTrack.displayHeight,
},
container: format.name,
durationInSeconds,
})
: timestampsInSeconds;
if (timestamps.length === 0) {
return;
}
const sink = new mediabunny_1.VideoSampleSink(videoTrack);
for await (const videoSample of sink.samplesAtTimestamps(timestamps)) {
if (signal === null || signal === void 0 ? void 0 : signal.aborted) {
videoSample === null || videoSample === void 0 ? void 0 : videoSample.close();
break;
}
if (!videoSample) {
continue;
}
onVideoSample(videoSample);
}
}
catch (error) {
if (error instanceof mediabunny_1.InputDisposedError) {
return;
}
throw error;
}
finally {
dispose();
if (signal) {
signal.removeEventListener('abort', dispose);
}
}
}
@@ -0,0 +1,16 @@
export type FrameDatabaseKey = string & {
__brand: 'FrameDatabaseKey';
};
export declare const makeFrameDatabaseKey: (src: string, timestamp: number) => FrameDatabaseKey;
export declare const getFrameDatabaseKeyPrefix: (src: string) => string;
type VideoFrameAndLastUsed = {
frame: VideoFrame;
lastUsed: number;
};
export declare const frameDatabase: Map<FrameDatabaseKey, VideoFrameAndLastUsed>;
export declare const aspectRatioCache: Map<string, number>;
export declare const getTimestampFromFrameDatabaseKey: (key: FrameDatabaseKey) => number;
export declare const getAspectRatioFromCache: (src: string) => number | null;
export declare const clearOldFrames: () => void;
export declare const clearFramesForSrc: (src: string) => void;
export {};
@@ -0,0 +1,54 @@
"use strict";
// Cache the thumbnails of the timeline
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearFramesForSrc = exports.clearOldFrames = exports.getAspectRatioFromCache = exports.getTimestampFromFrameDatabaseKey = exports.aspectRatioCache = exports.frameDatabase = exports.getFrameDatabaseKeyPrefix = exports.makeFrameDatabaseKey = void 0;
const KEY_SEPARATOR = '|';
const makeFrameDatabaseKey = (src, timestamp) => `${src}${KEY_SEPARATOR}${timestamp}`;
exports.makeFrameDatabaseKey = makeFrameDatabaseKey;
const getFrameDatabaseKeyPrefix = (src) => {
return `${src}${KEY_SEPARATOR}`;
};
exports.getFrameDatabaseKeyPrefix = getFrameDatabaseKeyPrefix;
exports.frameDatabase = new Map();
exports.aspectRatioCache = new Map();
const getTimestampFromFrameDatabaseKey = (key) => {
const split = key.split(KEY_SEPARATOR);
return Number(split[split.length - 1]);
};
exports.getTimestampFromFrameDatabaseKey = getTimestampFromFrameDatabaseKey;
const getAspectRatioFromCache = (src) => {
const cached = exports.aspectRatioCache.get(src);
if (cached) {
return cached;
}
return null;
};
exports.getAspectRatioFromCache = getAspectRatioFromCache;
// a 16:9 thumbnail is 43x23px wide - 43 * 23 * 4 = 4052 bytes
// Our allowance is a 50MB frame cache, so we can store 12340 thumbnails
const MAX_FRAMES_IN_CACHE = 12340;
const clearOldFrames = () => {
if (exports.frameDatabase.size <= MAX_FRAMES_IN_CACHE) {
return;
}
const framesToRemove = Array.from(exports.frameDatabase.entries()).sort((a, b) => a[1].lastUsed - b[1].lastUsed);
for (const [key, frame] of framesToRemove.slice(0, framesToRemove.length - MAX_FRAMES_IN_CACHE)) {
frame.frame.close();
exports.frameDatabase.delete(key);
}
};
exports.clearOldFrames = clearOldFrames;
const clearFramesForSrc = (src) => {
const keysToRemove = [];
const prefix = (0, exports.getFrameDatabaseKeyPrefix)(src);
for (const [key, frame] of exports.frameDatabase.entries()) {
if (key.startsWith(prefix)) {
frame.frame.close();
keysToRemove.push(key);
}
}
for (const key of keysToRemove) {
exports.frameDatabase.delete(key);
}
};
exports.clearFramesForSrc = clearFramesForSrc;
@@ -0,0 +1,12 @@
import type { CanvasContent } from 'remotion';
import type { Dimensions } from './is-current-selected-still';
export declare const remotion_outputsBase: string;
export type AssetMetadata = {
type: 'not-found';
} | {
type: 'found';
size: number;
dimensions: Dimensions | 'none' | null;
fetchedAt: number;
};
export declare const getAssetMetadata: (canvasContent: CanvasContent, addTime: boolean) => Promise<AssetMetadata>;
@@ -0,0 +1,77 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getAssetMetadata = exports.remotion_outputsBase = void 0;
const media_utils_1 = require("@remotion/media-utils");
const remotion_1 = require("remotion");
const Preview_1 = require("../components/Preview");
exports.remotion_outputsBase = window.remotion_staticBase.replace('static', 'outputs');
const getSrcFromCanvasContent = (canvasContent) => {
if (canvasContent.type === 'asset') {
return (0, remotion_1.staticFile)(canvasContent.asset);
}
return exports.remotion_outputsBase + canvasContent.path;
};
const getAssetMetadata = async (canvasContent, addTime) => {
if (canvasContent.type === 'output-blob') {
return {
type: 'found',
size: canvasContent.sizeInBytes,
dimensions: { width: canvasContent.width, height: canvasContent.height },
fetchedAt: Date.now(),
};
}
if (canvasContent.type === 'composition') {
throw new Error('cannot get dimensions for composition');
}
const src = getSrcFromCanvasContent(canvasContent);
const file = await fetch(src, {
method: 'HEAD',
});
if (file.status === 404) {
return { type: 'not-found' };
}
if (file.status !== 200) {
throw new Error(`Expected status code 200 or 404 for file, got ${file.status}`);
}
const size = file.headers.get('content-length');
if (!size) {
throw new Error('Unexpected error: content-length is null');
}
const fetchedAt = Date.now();
const srcWithTime = addTime ? `${src}?date=${fetchedAt}` : src;
const fileType = (0, Preview_1.getPreviewFileType)(src);
if (fileType === 'video') {
const resolution = await (0, media_utils_1.getVideoMetadata)(srcWithTime);
return {
type: 'found',
size: Number(size),
dimensions: { width: resolution.width, height: resolution.height },
fetchedAt,
};
}
if (fileType === 'image') {
const resolution = await new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => {
resolve({
type: 'found',
size: Number(size),
dimensions: { width: img.width, height: img.height },
fetchedAt,
});
};
img.onerror = () => {
reject(new Error('Failed to load image'));
};
img.src = srcWithTime;
});
return resolution;
}
return {
type: 'found',
dimensions: 'none',
size: Number(size),
fetchedAt,
};
};
exports.getAssetMetadata = getAssetMetadata;
@@ -0,0 +1,27 @@
import type { Size } from '@remotion/player';
import type { Translation } from 'remotion';
export declare const getEffectiveTranslation: ({ canvasSize, scale, compositionHeight, compositionWidth, translation, }: {
canvasSize: Size;
scale: number;
compositionWidth: number;
compositionHeight: number;
translation: {
x: number;
y: number;
};
}) => {
x: number;
y: number;
};
export declare const getCenterPointWhileScrolling: ({ size, clientX, clientY, compositionWidth, compositionHeight, scale, translation, }: {
size: Size;
clientX: number;
clientY: number;
compositionWidth: number;
compositionHeight: number;
scale: number;
translation: Translation;
}) => {
centerX: number;
centerY: number;
};
@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getCenterPointWhileScrolling = exports.getEffectiveTranslation = void 0;
const getEffectiveXTranslation = ({ canvasSize, scale, compositionWidth, translation, }) => {
const maxTranslation = Math.abs(canvasSize.width / 2 +
(scale * compositionWidth) / 2 -
MUST_BE_INSIDE_CANVAS);
return Math.max(-maxTranslation, Math.min(translation.x, maxTranslation));
};
const MUST_BE_INSIDE_CANVAS = 50;
const getEffectiveYTranslation = ({ canvasSize, scale, compositionHeight, translation, }) => {
const maxTranslation = Math.abs(canvasSize.height / 2 + (scale * compositionHeight) / 2) -
MUST_BE_INSIDE_CANVAS;
return Math.max(-maxTranslation, Math.min(translation.y, maxTranslation));
};
const getEffectiveTranslation = ({ canvasSize, scale, compositionHeight, compositionWidth, translation, }) => {
return {
x: getEffectiveXTranslation({
canvasSize,
compositionWidth,
scale,
translation,
}),
y: getEffectiveYTranslation({
canvasSize,
compositionHeight,
scale,
translation,
}),
};
};
exports.getEffectiveTranslation = getEffectiveTranslation;
const getCenterPointWhileScrolling = ({ size, clientX, clientY, compositionWidth, compositionHeight, scale, translation, }) => {
const mouseLeft = clientX - size.left;
const mouseTop = clientY - size.top;
const contentLeftPoint = size.width / 2 - (compositionWidth * scale) / 2 - translation.x;
const contentTopPoint = size.height / 2 - (compositionHeight * scale) / 2 - translation.y;
const offsetFromVideoLeft = Math.min(compositionWidth, Math.max(0, (mouseLeft - contentLeftPoint) / scale));
const offsetFromVideoTop = Math.min(compositionHeight, Math.max(0, (mouseTop - contentTopPoint) / scale));
return {
centerX: offsetFromVideoLeft,
centerY: offsetFromVideoTop,
};
};
exports.getCenterPointWhileScrolling = getCenterPointWhileScrolling;
@@ -0,0 +1,7 @@
import type { GitSource } from '@remotion/studio-shared';
import type { ComboboxValue } from '../components/NewComposition/ComboBox';
import type { OriginalPosition } from '../error-overlay/react-overlay/utils/get-source-map';
export declare const getGitSourceName: (gitSource: GitSource) => string;
export declare const getGitSourceBranchUrl: (gitSource: GitSource) => string;
export declare const getGitRefUrl: (gitSource: GitSource, originalLocation: OriginalPosition) => string;
export declare const getGitMenuItem: () => ComboboxValue | null;
@@ -0,0 +1,43 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getGitMenuItem = exports.getGitRefUrl = exports.getGitSourceBranchUrl = exports.getGitSourceName = void 0;
const getGitSourceName = (gitSource) => {
if (gitSource.type === 'github') {
return 'GitHub';
}
throw new Error('Unknown git source type');
};
exports.getGitSourceName = getGitSourceName;
const getGitSourceBranchUrl = (gitSource) => {
if (gitSource.type === 'github') {
return `https://github.com/${gitSource.org}/${gitSource.name}/tree/${gitSource.ref}${gitSource.relativeFromGitRoot ? `/${gitSource.relativeFromGitRoot}` : ''}`;
}
throw new Error('Unknown git source type');
};
exports.getGitSourceBranchUrl = getGitSourceBranchUrl;
const getGitRefUrl = (gitSource, originalLocation) => {
if (gitSource.type === 'github') {
return `https://github.com/${gitSource.org}/${gitSource.name}/tree/${gitSource.ref}/${gitSource.relativeFromGitRoot ? `${gitSource.relativeFromGitRoot}/` : ''}${originalLocation.source}#L${originalLocation.line}`;
}
throw new Error('Unknown git source type');
};
exports.getGitRefUrl = getGitRefUrl;
const getGitMenuItem = () => {
if (!window.remotion_gitSource) {
return null;
}
return {
id: 'open-git-source',
value: 'open-git-source',
label: `Open ${(0, exports.getGitSourceName)(window.remotion_gitSource)} Repo`,
onClick: () => {
window.open((0, exports.getGitSourceBranchUrl)(window.remotion_gitSource), '_blank');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: `Open ${(0, exports.getGitSourceName)(window.remotion_gitSource)} repo`,
};
};
exports.getGitMenuItem = getGitMenuItem;
@@ -0,0 +1 @@
export declare const getXPositionOfItemInTimelineImperatively: (frame: number, duration: number, width: number) => number;
@@ -0,0 +1,9 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getXPositionOfItemInTimelineImperatively = void 0;
const timeline_layout_1 = require("./timeline-layout");
const getXPositionOfItemInTimelineImperatively = (frame, duration, width) => {
const proportion = frame / (duration - 1);
return proportion * (width - timeline_layout_1.TIMELINE_PADDING * 2) + timeline_layout_1.TIMELINE_PADDING;
};
exports.getXPositionOfItemInTimelineImperatively = getXPositionOfItemInTimelineImperatively;
@@ -0,0 +1,2 @@
export declare const getLocationOfSequence: (stack: string | null) => import("@remotion/studio-shared").StackFrame | null;
export declare const getLocationOfFunctionCall: (stack: string | null, functionName: string) => import("@remotion/studio-shared").StackFrame | null;
@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getLocationOfFunctionCall = exports.getLocationOfSequence = void 0;
const parser_1 = require("../error-overlay/react-overlay/utils/parser");
const getLocationOfSequence = (stack) => {
if (!stack) {
return null;
}
const parsed = (0, parser_1.parseStack)(stack.split('\n'));
let i = 0;
while (i < parsed.length) {
const frame = parsed[i];
if (frame.functionName === 'apply') {
i++;
continue;
}
return frame;
}
return null;
};
exports.getLocationOfSequence = getLocationOfSequence;
const getLocationOfFunctionCall = (stack, functionName) => {
if (!stack) {
return null;
}
const parsed = (0, parser_1.parseStack)(stack.split('\n'));
let i = 0;
while (i < parsed.length) {
const frame = parsed[i];
if (frame.functionName !== functionName) {
i++;
continue;
}
return parsed[i + 1];
}
return null;
};
exports.getLocationOfFunctionCall = getLocationOfFunctionCall;
@@ -0,0 +1,4 @@
import type { TSequence } from 'remotion';
export declare const getCascadedStart: (sequence: TSequence, sequences: TSequence[]) => number;
export declare const getTimelineVisibleStart: (sequence: TSequence, sequences: TSequence[]) => number;
export declare const getTimelineVisibleDuration: (sequence: TSequence, sequences: TSequence[]) => number;
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTimelineVisibleDuration = exports.getTimelineVisibleStart = exports.getCascadedStart = void 0;
const getCascadedStart = (sequence, sequences) => {
if (!sequence.parent) {
return sequence.from;
}
const parent = sequences.find((s) => s.id === sequence.parent);
if (!parent) {
throw new TypeError('Parent not found for sequence ' + sequence.id);
}
return (0, exports.getCascadedStart)(parent, sequences) + sequence.from;
};
exports.getCascadedStart = getCascadedStart;
const getTimelineVisibleStart = (sequence, sequences) => {
const cascadedStart = Math.max(0, (0, exports.getCascadedStart)(sequence, sequences));
if (!sequence.parent) {
return cascadedStart;
}
const parent = sequences.find((s) => s.id === sequence.parent);
if (!parent) {
throw new TypeError('Parent not found for sequence ' + sequence.id);
}
const timelineVisibleStart = (0, exports.getTimelineVisibleStart)(parent, sequences);
return Math.max(timelineVisibleStart, cascadedStart);
};
exports.getTimelineVisibleStart = getTimelineVisibleStart;
const getTimelineVisibleDuration = (sequence, sequences) => {
const visibleDuration = sequence.duration + Math.min(sequence.from, 0);
if (!sequence.parent) {
return visibleDuration;
}
const parent = sequences.find((s) => s.id === sequence.parent);
if (!parent) {
throw new TypeError('Parent not found for sequence ' + sequence.id);
}
return Math.min(visibleDuration, (0, exports.getTimelineVisibleDuration)(parent, sequences));
};
exports.getTimelineVisibleDuration = getTimelineVisibleDuration;
@@ -0,0 +1,2 @@
import type { TSequence } from 'remotion';
export declare const getTimelineNestedLevel: (sequence: TSequence, allSequences: TSequence[], depth: number) => number;
@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTimelineNestedLevel = void 0;
const getTimelineNestedLevel = (sequence, allSequences, depth) => {
if (!sequence.parent) {
return depth;
}
const parentSequence = allSequences.find((s) => s.id === sequence.parent);
if (!parentSequence) {
throw new Error('has parentId but no parent');
}
return (0, exports.getTimelineNestedLevel)(parentSequence, allSequences, depth + 1);
};
exports.getTimelineNestedLevel = getTimelineNestedLevel;
@@ -0,0 +1,6 @@
import type { TSequence } from 'remotion';
export declare const getTimelineSequenceHash: (sequence: TSequence, allSequences: TSequence[], hashesUsedInRoot: {
[rootId: string]: string[];
}, cache: {
[sequenceId: string]: string;
}) => string;
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTimelineSequenceHash = void 0;
// The goal for this function is to calculate an as unique as possible identifier
// for a sequence based on it's properties. A sequence can be registered multiple times
// from main preview and from thumbnails and we use this to deduplicate it.
// This is why we don't use `id` properties as they will
// differ as a hash.
const getTimelineSequenceHash = (sequence, allSequences, hashesUsedInRoot, cache) => {
if (cache[sequence.id]) {
return cache[sequence.id];
}
const parent = allSequences.find((a) => a.id === sequence.parent);
const baseHash = [
parent
? (0, exports.getTimelineSequenceHash)(parent, allSequences, hashesUsedInRoot, cache)
: null,
sequence.displayName,
sequence.duration,
sequence.from,
sequence.type,
sequence.type === 'audio' ? sequence.src : null,
sequence.type === 'audio' ? sequence.volume : null,
sequence.type === 'video' ? sequence.src : null,
sequence.type === 'video' ? sequence.volume : null,
].join('-');
const actualHash = baseHash +
hashesUsedInRoot[sequence.rootId].filter((h) => h === baseHash).length;
hashesUsedInRoot[sequence.rootId].push(baseHash);
cache[sequence.id] = actualHash;
return actualHash;
};
exports.getTimelineSequenceHash = getTimelineSequenceHash;
@@ -0,0 +1,18 @@
import type { VideoConfig } from 'remotion';
export declare const SEQUENCE_BORDER_WIDTH = 1;
export declare const getTimelineSequenceLayout: ({ durationInFrames, startFrom, maxMediaDuration, startFromMedia, video, windowWidth, premountDisplay, postmountDisplay, }: {
durationInFrames: number;
startFrom: number;
startFromMedia: number;
maxMediaDuration: number | null;
video: VideoConfig;
windowWidth: number;
premountDisplay: number | null;
postmountDisplay: number | null;
}) => {
marginLeft: number;
width: number;
naturalWidth: number;
premountWidth: number | null;
postmountWidth: number | null;
};
@@ -0,0 +1,78 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTimelineSequenceLayout = exports.SEQUENCE_BORDER_WIDTH = void 0;
const timeline_layout_1 = require("./timeline-layout");
exports.SEQUENCE_BORDER_WIDTH = 1;
const getWidthOfTrack = ({ durationInFrames, lastFrame, windowWidth, spatialDuration, nonNegativeMarginLeft, }) => {
const fullWidth = windowWidth - timeline_layout_1.TIMELINE_PADDING * 2;
const base = durationInFrames === Infinity || lastFrame === 0
? fullWidth
: (spatialDuration / lastFrame) * fullWidth;
return base - exports.SEQUENCE_BORDER_WIDTH + nonNegativeMarginLeft;
};
const getTimelineSequenceLayout = ({ durationInFrames, startFrom, maxMediaDuration, startFromMedia, video, windowWidth, premountDisplay, postmountDisplay, }) => {
var _a;
const maxMediaSequenceDuration = (maxMediaDuration !== null && maxMediaDuration !== void 0 ? maxMediaDuration : Infinity) - startFromMedia;
const lastFrame = ((_a = video.durationInFrames) !== null && _a !== void 0 ? _a : 1) - 1;
let spatialDuration = Math.min(maxMediaSequenceDuration, durationInFrames - 1, lastFrame - startFrom);
// Unclipped spatial duration: without the lastFrame - startFrom constraint
let naturalSpatialDuration = Math.min(maxMediaSequenceDuration, durationInFrames - 1);
const shouldAddHalfAFrameAtEnd = startFrom + durationInFrames < lastFrame;
const shouldAddHalfAFrameAtStart = startFrom > 0;
if (shouldAddHalfAFrameAtEnd) {
spatialDuration += 0.5;
naturalSpatialDuration += 0.5;
}
if (shouldAddHalfAFrameAtStart) {
spatialDuration += 0.5;
naturalSpatialDuration += 0.5;
}
const startFromWithOffset = shouldAddHalfAFrameAtStart
? startFrom - 0.5
: startFrom;
const marginLeft = lastFrame === 0
? 0
: (startFromWithOffset / lastFrame) *
(windowWidth - timeline_layout_1.TIMELINE_PADDING * 2);
const nonNegativeMarginLeft = Math.min(marginLeft, 0);
const width = getWidthOfTrack({
durationInFrames,
lastFrame,
nonNegativeMarginLeft,
spatialDuration,
windowWidth,
});
const naturalWidth = getWidthOfTrack({
durationInFrames,
lastFrame,
nonNegativeMarginLeft,
spatialDuration: naturalSpatialDuration,
windowWidth,
});
const premountWidth = premountDisplay
? getWidthOfTrack({
durationInFrames: premountDisplay,
lastFrame,
nonNegativeMarginLeft,
spatialDuration: premountDisplay,
windowWidth,
})
: null;
const postmountWidth = postmountDisplay
? getWidthOfTrack({
durationInFrames: postmountDisplay,
lastFrame,
nonNegativeMarginLeft,
spatialDuration: postmountDisplay,
windowWidth,
})
: null;
return {
marginLeft: Math.max(marginLeft, 0) - (premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0),
width: width + (premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0) + (postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0),
naturalWidth: naturalWidth + (premountWidth !== null && premountWidth !== void 0 ? premountWidth : 0) + (postmountWidth !== null && postmountWidth !== void 0 ? postmountWidth : 0),
premountWidth,
postmountWidth,
};
};
exports.getTimelineSequenceLayout = getTimelineSequenceLayout;
@@ -0,0 +1,17 @@
import type { TSequence } from 'remotion';
type Track = {
sequence: TSequence;
depth: number;
};
export type TrackWithHash = Track & {
hash: string;
};
export type TrackWithHashAndOriginalTimings = TrackWithHash & {
hash: string;
cascadedStart: number;
cascadedDuration: number;
};
export declare const getTimelineSequenceSequenceSortKey: (track: TrackWithHash, tracks: TrackWithHash[], sameHashes?: {
[hash: string]: string[];
}) => string;
export {};
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTimelineSequenceSequenceSortKey = void 0;
const getTimelineSequenceSequenceSortKey = (track, tracks, sameHashes = {}) => {
const firstSequenceWithSameHash = tracks.find((t) => sameHashes[track.hash].includes(t.sequence.id));
const id = String(firstSequenceWithSameHash.sequence.nonce).padStart(6, '0');
if (!track.sequence.parent) {
return id;
}
const parent = tracks.find((t) => t.sequence.id === track.sequence.parent);
if (!parent) {
// Due to effects and conditional `showInTimeline`, a parent
// may not exist in the `allTracks` array.
return id;
}
const firstParentWithSameHash = tracks.find((a) => {
return sameHashes[parent.hash].includes(a.sequence.id);
});
if (!firstParentWithSameHash) {
throw new Error('could not find parent: ' + track.sequence.parent);
}
return `${(0, exports.getTimelineSequenceSequenceSortKey)(firstParentWithSameHash, tracks, sameHashes)}-${id}`;
};
exports.getTimelineSequenceSequenceSortKey = getTimelineSequenceSequenceSortKey;
@@ -0,0 +1 @@
export declare const injectCSS: () => void;
@@ -0,0 +1,159 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.injectCSS = void 0;
const remotion_1 = require("remotion");
const scroll_to_default_props_path_1 = require("../components/RenderModal/SchemaEditor/scroll-to-default-props-path");
const makeDefaultGlobalCSS = () => {
const unhoveredDragAreaFactor = 2;
const fromMiddle = 50 / unhoveredDragAreaFactor;
const hoveredDragAreaFactor = 6;
const fromMiddleHovered = 50 / hoveredDragAreaFactor;
return `
html {
--remotion-cli-internals-blue: #0b84f3;
overscroll-behavior-y: none;
overscroll-behavior-x: none;
}
body {
overscroll-behavior-y: none;
overscroll-behavior-x: none;
/* Override Chakra UI position: relative on body */
position: static !important;
}
.remotion-splitter {
user-select: none;
}
.remotion-splitter-horizontal {
transform: scaleY(${unhoveredDragAreaFactor});
background: linear-gradient(
to bottom,
transparent ${50 - fromMiddle}%,
black ${50 - fromMiddle}%,
black ${50 + fromMiddle}%,
transparent ${50 + fromMiddle}%
);
}
.remotion-splitter-horizontal.remotion-splitter-active, .remotion-splitter-horizontal.remotion-splitter-hover {
background: linear-gradient(
to bottom,
transparent ${50 - fromMiddleHovered}%,
var(--remotion-cli-internals-blue) ${50 - fromMiddleHovered}%,
var(--remotion-cli-internals-blue) ${50 + fromMiddleHovered}%,
transparent ${50 + fromMiddleHovered}%
);
cursor: row-resize;
transform: scaleY(${hoveredDragAreaFactor});
z-index: 1000;
}
.remotion-splitter-vertical {
transform: scaleX(${unhoveredDragAreaFactor});
background: linear-gradient(
to right,
transparent ${50 - fromMiddle}%,
black ${50 - fromMiddle}%,
black ${50 + fromMiddle}%,
transparent ${50 + fromMiddle}%
);
}
.remotion-splitter-vertical.remotion-splitter-active, .remotion-splitter-vertical.remotion-splitter-hover {
background: linear-gradient(
to right,
transparent ${50 - fromMiddleHovered}%,
var(--remotion-cli-internals-blue) ${50 - fromMiddleHovered}%,
var(--remotion-cli-internals-blue) ${50 + fromMiddleHovered}%,
transparent ${50 + fromMiddleHovered}%
);
transform: scaleX(${hoveredDragAreaFactor});
cursor: col-resize;
z-index: 1000;
}
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
input:focus,
textarea:focus,
button:focus,
a:focus {
outline: none;
box-shadow:
inset 1px 1px #555,
inset -1px -1px #555,
inset 1px -1px #555,
inset -1px 1px #555;
}
input[type='color'].__remotion_color_picker::-webkit-color-swatch-wrapper {
padding: 0;
}
input[type='color'].__remotion_color_picker::-webkit-color-swatch {
border: none;
}
.__remotion_thumb,
.__remotion_thumb::-webkit-slider-thumb {
-webkit-appearance: none;
-webkit-tap-highlight-color: transparent;
}
.__remotion_thumb {
pointer-events: none;
position: absolute;
height: 0;
outline: none;
top: 15.5px;
width: 221px;
margin-left: -2px;
z-index: 2;
}
/* For Firefox browsers */
.__remotion_thumb::-moz-range-thumb {
border: 1px solid black;
border-radius: 2px;
cursor: pointer;
height: 37px;
width: 10px;
pointer-events: all;
border-color: black;
background-color: white;
position: relative;
}
/* For Chrome browsers */
.__remotion_thumb::-webkit-slider-thumb {
border: 1px solid black;
border-radius: 2px;
cursor: pointer;
height: 39px;
width: 10px;
pointer-events: all;
border-color: black;
background-color: white;
position: relative;
}
.${scroll_to_default_props_path_1.DEFAULT_PROPS_PATH_ACTIVE_CLASSNAME} span {
color: var(--remotion-cli-internals-blue) !important;
transition: color 0.2s ease-in-out;
}
`.trim();
};
let injected = false;
const injectCSS = () => {
if (injected) {
return;
}
remotion_1.Internals.CSSUtils.injectCSS(makeDefaultGlobalCSS());
injected = true;
};
exports.injectCSS = injectCSS;
@@ -0,0 +1,3 @@
export declare const isCompositionStill: (comp: {
durationInFrames: number | undefined;
} | null) => boolean;
@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isCompositionStill = void 0;
const isCompositionStill = (comp) => {
if (!comp) {
return false;
}
return comp.durationInFrames === 1;
};
exports.isCompositionStill = isCompositionStill;
@@ -0,0 +1,6 @@
export type Dimensions = {
width: number;
height: number;
};
export declare const useIsStill: () => boolean;
export declare const useIsVideoComposition: () => boolean;
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useIsVideoComposition = exports.useIsStill = void 0;
const react_1 = require("react");
const remotion_1 = require("remotion");
const is_composition_still_1 = require("./is-composition-still");
const useIsStill = () => {
const resolved = remotion_1.Internals.useResolvedVideoConfig(null);
if (!resolved || resolved.type !== 'success') {
return false;
}
return (0, is_composition_still_1.isCompositionStill)(resolved.result);
};
exports.useIsStill = useIsStill;
const useIsVideoComposition = () => {
const isStill = (0, exports.useIsStill)();
const { canvasContent } = (0, react_1.useContext)(remotion_1.Internals.CompositionManager);
if (canvasContent === null) {
return false;
}
if (isStill) {
return false;
}
return canvasContent.type === 'composition';
};
exports.useIsVideoComposition = useIsVideoComposition;
@@ -0,0 +1 @@
export declare const useMobileLayout: () => boolean;
@@ -0,0 +1,26 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useMobileLayout = void 0;
const react_1 = require("react");
const breakpoint = 900;
function getIsMobile() {
return window.innerWidth < breakpoint;
}
const useMobileLayout = () => {
const [isMobile, setIsMobile] = (0, react_1.useState)(getIsMobile());
const isMobileRef = (0, react_1.useRef)(isMobile);
(0, react_1.useEffect)(() => {
function handleResize() {
if (getIsMobile() !== isMobileRef.current) {
setIsMobile(getIsMobile());
}
isMobileRef.current = getIsMobile();
}
window.addEventListener('resize', handleResize);
return () => {
return window.removeEventListener('resize', handleResize);
};
}, []);
return isMobile;
};
exports.useMobileLayout = useMobileLayout;
@@ -0,0 +1 @@
export declare const noop: () => undefined;
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.noop = void 0;
const noop = () => undefined;
exports.noop = noop;
@@ -0,0 +1,4 @@
import type { SymbolicatedStackFrame } from '@remotion/studio-shared';
import type { OriginalPosition } from '../error-overlay/react-overlay/utils/get-source-map';
export declare const openInEditor: (stack: SymbolicatedStackFrame) => Promise<Response>;
export declare const openOriginalPositionInEditor: (originalPosition: OriginalPosition) => Promise<void>;
@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.openOriginalPositionInEditor = exports.openInEditor = void 0;
const openInEditor = (stack) => {
const { originalFileName, originalLineNumber, originalColumnNumber, originalFunctionName, originalScriptCode, } = stack;
return fetch(`/api/open-in-editor`, {
method: 'post',
headers: {
'content-type': 'application/json',
},
body: JSON.stringify({
stack: {
originalFileName,
originalLineNumber,
originalColumnNumber,
originalFunctionName,
originalScriptCode,
},
}),
});
};
exports.openInEditor = openInEditor;
const openOriginalPositionInEditor = async (originalPosition) => {
await (0, exports.openInEditor)({
originalColumnNumber: originalPosition.column,
originalFileName: originalPosition.source,
originalFunctionName: null,
originalLineNumber: originalPosition.line,
originalScriptCode: null,
});
};
exports.openOriginalPositionInEditor = openOriginalPositionInEditor;
@@ -0,0 +1,15 @@
export declare const openFolderKey: ({ folderName, parentName, }: {
folderName: string;
parentName: string | null;
}) => string;
export type ExpandedFoldersState = Record<string, boolean>;
type PersistanceType = 'assets' | 'compositions';
export declare const persistExpandedFolders: (type: PersistanceType, state: ExpandedFoldersState) => void;
export declare const loadExpandedFolders: (type: PersistanceType) => ExpandedFoldersState;
export type ExpandedFoldersRef = {
toggleFolder: (folderName: string, parentName: string | null) => void;
foldersExpanded: ExpandedFoldersState;
setFoldersExpanded: (foldersExpanded: ExpandedFoldersState) => void;
};
export declare const ExpandedFoldersContext: import("react").Context<ExpandedFoldersRef>;
export {};
@@ -0,0 +1,28 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ExpandedFoldersContext = exports.loadExpandedFolders = exports.persistExpandedFolders = exports.openFolderKey = void 0;
const react_1 = require("react");
const openFolderKey = ({ folderName, parentName, }) => {
return [parentName !== null && parentName !== void 0 ? parentName : 'no-parent', folderName].join('/');
};
exports.openFolderKey = openFolderKey;
const localStorageKey = (type) => type === 'compositions'
? 'remotion.expandedFolders'
: 'remotion.expandedAssetFolders';
const persistExpandedFolders = (type, state) => {
window.localStorage.setItem(localStorageKey(type), JSON.stringify(state));
};
exports.persistExpandedFolders = persistExpandedFolders;
const loadExpandedFolders = (type) => {
const item = window.localStorage.getItem(localStorageKey(type));
if (item === null) {
return {};
}
return JSON.parse(item);
};
exports.loadExpandedFolders = loadExpandedFolders;
exports.ExpandedFoldersContext = (0, react_1.createContext)({
toggleFolder: () => { },
foldersExpanded: {},
setFoldersExpanded: () => { },
});
@@ -0,0 +1 @@
export declare const pickColor: () => void;
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.pickColor = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const layout_1 = require("../components/layout");
const ColorDot_1 = require("../components/Notifications/ColorDot");
const NotificationCenter_1 = require("../components/Notifications/NotificationCenter");
const copy_text_1 = require("./copy-text");
const pickColor = () => {
// @ts-expect-error
const open = new EyeDropper().open();
open
.then((color) => {
(0, copy_text_1.copyText)(color.sRGBHex)
.then(() => {
(0, NotificationCenter_1.showNotification)((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(ColorDot_1.ColorDot, { color: color.sRGBHex }), " ", (0, jsx_runtime_1.jsx)(layout_1.Spacing, { x: 1 }), " Copied", ' ', color.sRGBHex] }), 2000);
})
.catch((err) => {
(0, NotificationCenter_1.showNotification)(`Could not copy: ${err.message}`, 2000);
});
})
.catch((err) => {
if (err.message.includes('canceled')) {
return;
}
(0, NotificationCenter_1.showNotification)(`Could not pick color.`, 2000);
});
};
exports.pickColor = pickColor;
@@ -0,0 +1,2 @@
import type { X264Preset } from '@remotion/renderer';
export declare const labelx264Preset: (profile: X264Preset) => "medium" | "ultrafast" | "superfast" | "veryfast" | "faster" | "fast" | "slow" | "slower" | "veryslow" | "placebo";
@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.labelx264Preset = void 0;
const labelx264Preset = (profile) => {
if (profile === 'ultrafast') {
return 'ultrafast';
}
if (profile === 'superfast') {
return 'superfast';
}
if (profile === 'veryfast') {
return 'veryfast';
}
if (profile === 'faster') {
return 'faster';
}
if (profile === 'fast') {
return 'fast';
}
if (profile === 'medium') {
return 'medium';
}
if (profile === 'slow') {
return 'slow';
}
if (profile === 'slower') {
return 'slower';
}
if (profile === 'veryslow') {
return 'veryslow';
}
if (profile === 'placebo') {
return 'placebo';
}
throw new TypeError(`Unknown x264 preset: ${profile}`);
};
exports.labelx264Preset = labelx264Preset;
@@ -0,0 +1,2 @@
import type { _InternalTypes } from 'remotion';
export declare const labelProResProfile: (profile: _InternalTypes["ProResProfile"]) => "4444" | "4444 XQ (Best)" | "HQ" | "Proxy (Worst)" | "Light" | "Standard";
@@ -0,0 +1,25 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.labelProResProfile = void 0;
const labelProResProfile = (profile) => {
if (profile === '4444') {
return '4444';
}
if (profile === '4444-xq') {
return '4444 XQ (Best)';
}
if (profile === 'hq') {
return 'HQ';
}
if (profile === 'proxy') {
return 'Proxy (Worst)';
}
if (profile === 'light') {
return 'Light';
}
if (profile === 'standard') {
return 'Standard';
}
throw new TypeError(`Unknown ProRes profile: ${profile}`);
};
exports.labelProResProfile = labelProResProfile;
@@ -0,0 +1,9 @@
import type { Codec } from '@remotion/renderer';
import type { RenderType } from '../components/RenderModal/RenderModalAdvanced';
type Section = 'general' | 'picture' | 'advanced' | 'data' | 'gif' | 'audio';
export declare const useRenderModalSections: (renderMode: RenderType, codec: Codec) => {
tab: Section;
setTab: import("react").Dispatch<import("react").SetStateAction<Section>>;
shownTabs: Section[];
};
export {};
@@ -0,0 +1,35 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useRenderModalSections = void 0;
const react_1 = require("react");
const useRenderModalSections = (renderMode, codec) => {
const [selectedTab, setTab] = (0, react_1.useState)('general');
const shownTabs = (0, react_1.useMemo)(() => {
if (renderMode === 'audio') {
return ['general', 'data', 'audio', 'advanced'];
}
if (renderMode === 'still') {
return ['general', 'data', 'picture', 'advanced'];
}
if (renderMode === 'sequence') {
return ['general', 'data', 'picture', 'advanced'];
}
if (renderMode === 'video') {
if (codec === 'gif') {
return ['general', 'data', 'picture', 'gif', 'advanced'];
}
return ['general', 'data', 'picture', 'audio', 'advanced'];
}
throw new TypeError('Unknown render mode');
}, [codec, renderMode]);
const tab = (0, react_1.useMemo)(() => {
if (!shownTabs.includes(selectedTab)) {
return shownTabs[0];
}
return selectedTab;
}, [selectedTab, shownTabs]);
return (0, react_1.useMemo)(() => {
return { tab, setTab, shownTabs };
}, [tab, shownTabs]);
};
exports.useRenderModalSections = useRenderModalSections;
@@ -0,0 +1,4 @@
export declare const resizeVideoFrame: ({ frame, scale, }: {
frame: VideoFrame;
scale: number;
}) => VideoFrame;
@@ -0,0 +1,39 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.resizeVideoFrame = void 0;
const calculateNewDimensionsFromScale = ({ width, height, scale, }) => {
const scaledWidth = Math.round(width * scale);
const scaledHeight = Math.round(height * scale);
return {
width: scaledWidth,
height: scaledHeight,
};
};
const resizeVideoFrame = ({ frame, scale, }) => {
var _a;
// No resize, no rotation
if (scale === 1) {
return frame;
}
const { width, height } = calculateNewDimensionsFromScale({
height: frame.displayHeight,
width: frame.displayWidth,
scale,
});
const canvas = new OffscreenCanvas(width, height);
const ctx = canvas.getContext('2d');
if (!ctx) {
throw new Error('Could not get 2d context');
}
canvas.width = width;
canvas.height = height;
ctx.scale(scale, scale);
ctx.drawImage(frame, 0, 0);
return new VideoFrame(canvas, {
displayHeight: height,
displayWidth: width,
duration: (_a = frame.duration) !== null && _a !== void 0 ? _a : undefined,
timestamp: frame.timestamp,
});
};
exports.resizeVideoFrame = resizeVideoFrame;
@@ -0,0 +1,5 @@
import type { RenderJob } from '@remotion/studio-shared';
import type { ClientStillRenderJob, ClientVideoRenderJob } from '../components/RenderQueue/client-side-render-types';
import type { RenderModalState, WebRenderModalState } from '../state/modals';
export declare const makeRetryPayload: (job: RenderJob) => RenderModalState;
export declare const makeClientRetryPayload: (job: ClientStillRenderJob | ClientVideoRenderJob) => WebRenderModalState;
@@ -0,0 +1,198 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeClientRetryPayload = exports.makeRetryPayload = void 0;
const no_react_1 = require("remotion/no-react");
const makeRetryPayload = (job) => {
var _a, _b, _c, _d, _e;
const defaults = window.remotion_renderDefaults;
if (!defaults) {
throw new Error('defaults not set');
}
if (job.type === 'still') {
return {
type: 'server-render',
compositionId: job.compositionId,
initialFrame: job.frame,
initialStillImageFormat: job.imageFormat,
initialVideoImageFormat: null,
initialJpegQuality: (_a = job.jpegQuality) !== null && _a !== void 0 ? _a : defaults.jpegQuality,
initialScale: job.scale,
initialLogLevel: job.logLevel,
initialConcurrency: defaults.concurrency,
maxConcurrency: defaults.maxConcurrency,
minConcurrency: defaults.minConcurrency,
initialMuted: defaults.muted,
initialEnforceAudioTrack: defaults.enforceAudioTrack,
initialProResProfile: null,
initialx264Preset: defaults.x264Preset,
initialPixelFormat: defaults.pixelFormat,
initialAudioBitrate: defaults.audioBitrate,
initialVideoBitrate: defaults.videoBitrate,
initialEveryNthFrame: defaults.everyNthFrame,
initialNumberOfGifLoops: defaults.numberOfGifLoops,
initialDelayRenderTimeout: job.delayRenderTimeout,
defaultConfigurationAudioCodec: defaults.audioCodec,
initialEnvVariables: job.envVariables,
initialDisableWebSecurity: job.chromiumOptions.disableWebSecurity,
initialOpenGlRenderer: job.chromiumOptions.gl,
initialHeadless: job.chromiumOptions.headless,
initialIgnoreCertificateErrors: job.chromiumOptions.ignoreCertificateErrors,
initialDarkMode: job.chromiumOptions.darkMode,
defaultProps: no_react_1.NoReactInternals.deserializeJSONWithSpecialTypes(job.serializedInputPropsWithCustomSchema),
inFrameMark: null,
outFrameMark: null,
initialOffthreadVideoCacheSizeInBytes: job.offthreadVideoCacheSizeInBytes,
initialOffthreadVideoThreads: job.offthreadVideoThreads,
initialColorSpace: defaults.colorSpace,
initialMultiProcessOnLinux: job.multiProcessOnLinux,
defaultConfigurationVideoCodec: defaults.codec,
initialEncodingBufferSize: defaults.encodingBufferSize,
initialEncodingMaxRate: defaults.encodingMaxRate,
initialUserAgent: job.chromiumOptions.userAgent,
initialBeep: job.beepOnFinish,
initialRepro: job.repro,
initialForSeamlessAacConcatenation: defaults.forSeamlessAacConcatenation,
defaulMetadata: job.metadata,
renderTypeOfLastRender: 'still',
initialHardwareAcceleration: defaults.hardwareAcceleration,
initialChromeMode: job.chromeMode,
initialMediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
renderDefaults: defaults,
};
}
if (job.type === 'sequence') {
return {
type: 'server-render',
initialFrame: 0,
compositionId: job.compositionId,
initialVideoImageFormat: null,
initialJpegQuality: (_b = job.jpegQuality) !== null && _b !== void 0 ? _b : defaults.jpegQuality,
initialScale: job.scale,
initialLogLevel: job.logLevel,
initialConcurrency: defaults.concurrency,
maxConcurrency: defaults.maxConcurrency,
minConcurrency: defaults.minConcurrency,
initialMuted: defaults.muted,
initialEnforceAudioTrack: defaults.enforceAudioTrack,
initialProResProfile: null,
initialx264Preset: defaults.x264Preset,
initialPixelFormat: defaults.pixelFormat,
initialAudioBitrate: defaults.audioBitrate,
initialVideoBitrate: defaults.videoBitrate,
initialEveryNthFrame: defaults.everyNthFrame,
initialNumberOfGifLoops: defaults.numberOfGifLoops,
initialDelayRenderTimeout: job.delayRenderTimeout,
initialEnvVariables: job.envVariables,
initialDisableWebSecurity: job.chromiumOptions.disableWebSecurity,
initialOpenGlRenderer: job.chromiumOptions.gl,
initialHeadless: job.chromiumOptions.headless,
initialIgnoreCertificateErrors: job.chromiumOptions.ignoreCertificateErrors,
initialDarkMode: job.chromiumOptions.darkMode,
defaultProps: no_react_1.NoReactInternals.deserializeJSONWithSpecialTypes(job.serializedInputPropsWithCustomSchema),
initialStillImageFormat: defaults.stillImageFormat,
inFrameMark: job.startFrame,
outFrameMark: job.endFrame,
initialOffthreadVideoCacheSizeInBytes: job.offthreadVideoCacheSizeInBytes,
initialOffthreadVideoThreads: job.offthreadVideoThreads,
initialColorSpace: defaults.colorSpace,
initialMultiProcessOnLinux: job.multiProcessOnLinux,
defaultConfigurationVideoCodec: defaults.codec,
defaultConfigurationAudioCodec: defaults.audioCodec,
initialEncodingBufferSize: defaults.encodingBufferSize,
initialEncodingMaxRate: defaults.encodingMaxRate,
initialUserAgent: job.chromiumOptions.userAgent,
initialBeep: job.beepOnFinish,
initialRepro: job.repro,
initialForSeamlessAacConcatenation: defaults.forSeamlessAacConcatenation,
defaulMetadata: job.metadata,
renderTypeOfLastRender: 'sequence',
initialHardwareAcceleration: defaults.hardwareAcceleration,
initialChromeMode: job.chromeMode,
initialMediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
renderDefaults: defaults,
};
}
if (job.type === 'video') {
return {
type: 'server-render',
compositionId: job.compositionId,
initialStillImageFormat: defaults.stillImageFormat,
initialVideoImageFormat: job.imageFormat,
initialJpegQuality: (_c = job.jpegQuality) !== null && _c !== void 0 ? _c : defaults.jpegQuality,
initialScale: job.scale,
initialLogLevel: job.logLevel,
initialFrame: 0,
initialConcurrency: job.concurrency,
maxConcurrency: defaults.maxConcurrency,
minConcurrency: defaults.minConcurrency,
initialMuted: job.muted,
initialEnforceAudioTrack: job.enforceAudioTrack,
initialProResProfile: (_d = job.proResProfile) !== null && _d !== void 0 ? _d : null,
initialx264Preset: (_e = job.x264Preset) !== null && _e !== void 0 ? _e : defaults.x264Preset,
initialPixelFormat: job.pixelFormat,
initialAudioBitrate: job.audioBitrate,
initialVideoBitrate: job.videoBitrate,
initialEveryNthFrame: job.everyNthFrame,
initialNumberOfGifLoops: job.numberOfGifLoops,
initialDelayRenderTimeout: job.delayRenderTimeout,
initialEnvVariables: job.envVariables,
initialDisableWebSecurity: job.chromiumOptions.disableWebSecurity,
initialOpenGlRenderer: job.chromiumOptions.gl,
initialHeadless: job.chromiumOptions.headless,
initialIgnoreCertificateErrors: job.chromiumOptions.ignoreCertificateErrors,
initialDarkMode: job.chromiumOptions.darkMode,
defaultProps: no_react_1.NoReactInternals.deserializeJSONWithSpecialTypes(job.serializedInputPropsWithCustomSchema),
inFrameMark: job.startFrame,
outFrameMark: job.endFrame,
initialOffthreadVideoCacheSizeInBytes: job.offthreadVideoCacheSizeInBytes,
initialOffthreadVideoThreads: job.offthreadVideoThreads,
initialColorSpace: job.colorSpace,
initialMultiProcessOnLinux: job.multiProcessOnLinux,
defaultConfigurationVideoCodec: job.codec,
defaultConfigurationAudioCodec: job.audioCodec,
initialEncodingBufferSize: job.encodingBufferSize,
initialEncodingMaxRate: job.encodingMaxRate,
initialUserAgent: job.chromiumOptions.userAgent,
initialBeep: job.beepOnFinish,
initialRepro: job.repro,
initialForSeamlessAacConcatenation: job.forSeamlessAacConcatenation,
defaulMetadata: job.metadata,
renderTypeOfLastRender: 'video',
initialHardwareAcceleration: job.hardwareAcceleration,
initialChromeMode: job.chromeMode,
initialMediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
renderDefaults: defaults,
};
}
throw new Error(`Job ${JSON.stringify(job)} Not implemented`);
};
exports.makeRetryPayload = makeRetryPayload;
const makeClientRetryPayload = (job) => {
return {
type: 'web-render',
compositionId: job.compositionId,
initialFrame: job.type === 'client-still' ? job.frame : 0,
initialLogLevel: job.logLevel,
initialLicenseKey: job.licenseKey,
defaultProps: job.inputProps,
inFrameMark: job.type === 'client-video' ? job.startFrame : null,
outFrameMark: job.type === 'client-video' ? job.endFrame : null,
initialDefaultOutName: job.outName,
initialScale: job.scale,
initialDelayRenderTimeout: job.delayRenderTimeout,
initialMediaCacheSizeInBytes: job.mediaCacheSizeInBytes,
initialAudioBitrate: job.type === 'client-video' ? job.audioBitrate : null,
initialAudioCodec: job.type === 'client-video' ? job.audioCodec : null,
initialContainer: job.type === 'client-video' ? job.container : null,
initialHardwareAcceleration: job.type === 'client-video'
? job.hardwareAcceleration
: null,
initialVideoBitrate: job.type === 'client-video' ? job.videoBitrate : null,
initialVideoCodec: job.type === 'client-video' ? job.videoCodec : null,
initialStillImageFormat: job.type === 'client-still' ? job.imageFormat : 'png',
initialKeyframeIntervalInSeconds: job.type === 'client-video' ? job.keyframeIntervalInSeconds : null,
initialMuted: job.type === 'client-video' ? job.muted : null,
initialTransparent: job.type === 'client-video' ? job.transparent : null,
};
};
exports.makeClientRetryPayload = makeClientRetryPayload;
@@ -0,0 +1 @@
export declare const shouldShowRenderButton: (readOnlyStudio: boolean) => boolean;
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.shouldShowRenderButton = void 0;
const show_browser_rendering_1 = require("./show-browser-rendering");
const shouldShowRenderButton = (readOnlyStudio) => {
if (readOnlyStudio) {
return show_browser_rendering_1.SHOW_BROWSER_RENDERING;
}
return true;
};
exports.shouldShowRenderButton = shouldShowRenderButton;
@@ -0,0 +1 @@
export declare const SHOW_BROWSER_RENDERING: boolean;
@@ -0,0 +1,4 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SHOW_BROWSER_RENDERING = void 0;
exports.SHOW_BROWSER_RENDERING = Boolean(process.env.EXPERIMENTAL_CLIENT_SIDE_RENDERING_ENABLED);
@@ -0,0 +1,4 @@
export declare const MIN_ZOOM = 0.05;
export declare const MAX_ZOOM = 10;
export declare const smoothenZoom: (input: number) => number;
export declare const unsmoothenZoom: (input: number) => number;
@@ -0,0 +1,20 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unsmoothenZoom = exports.smoothenZoom = exports.MAX_ZOOM = exports.MIN_ZOOM = void 0;
const BASE = Math.E / 4;
exports.MIN_ZOOM = 0.05;
exports.MAX_ZOOM = 10;
function logN(val) {
return Math.log(val) / Math.log(BASE);
}
const smoothenZoom = (input) => {
return BASE ** (input - 1);
};
exports.smoothenZoom = smoothenZoom;
const unsmoothenZoom = (input) => {
if (input < 0) {
return exports.MAX_ZOOM;
}
return Math.min(exports.MAX_ZOOM, Math.max(exports.MIN_ZOOM, logN(input) + 1));
};
exports.unsmoothenZoom = unsmoothenZoom;
@@ -0,0 +1,4 @@
export declare const TIMELINE_PADDING = 16;
export declare const TIMELINE_BORDER = 1;
export declare const TIMELINE_ITEM_BORDER_BOTTOM = 1;
export declare const getTimelineLayerHeight: (type: "video" | "other") => 50 | 25;
@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getTimelineLayerHeight = exports.TIMELINE_ITEM_BORDER_BOTTOM = exports.TIMELINE_BORDER = exports.TIMELINE_PADDING = void 0;
exports.TIMELINE_PADDING = 16;
exports.TIMELINE_BORDER = 1;
exports.TIMELINE_ITEM_BORDER_BOTTOM = 1;
const getTimelineLayerHeight = (type) => {
if (type === 'video') {
return 50;
}
return 25;
};
exports.getTimelineLayerHeight = getTimelineLayerHeight;
@@ -0,0 +1,4 @@
export declare const pushUrl: (url: string) => void;
export declare const clearUrl: () => void;
export declare const reloadUrl: () => void;
export declare const getRoute: () => string;
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getRoute = exports.reloadUrl = exports.clearUrl = exports.pushUrl = void 0;
const getUrlHandlingType = () => {
if (window.remotion_isReadOnlyStudio) {
return 'query-string';
}
return 'spa';
};
const pushUrl = (url) => {
if (getUrlHandlingType() === 'query-string') {
window.history.pushState({}, 'Studio', `${window.location.pathname}?${url}`);
}
else {
window.history.pushState({}, 'Studio', url);
}
};
exports.pushUrl = pushUrl;
const clearUrl = () => {
window.location.href = window.location.pathname;
};
exports.clearUrl = clearUrl;
const reloadUrl = () => {
window.location.reload();
};
exports.reloadUrl = reloadUrl;
const getRoute = () => {
if (getUrlHandlingType() === 'query-string') {
return window.location.search.substring(1);
}
return window.location.pathname;
};
exports.getRoute = getRoute;
@@ -0,0 +1,11 @@
declare function useAssetDragEvents({ name, parentFolder, dropLocation, setDropLocation, }: {
name: string | null;
parentFolder: string | null;
dropLocation: string | null;
setDropLocation: React.Dispatch<React.SetStateAction<string | null>>;
}): {
isDropDiv: boolean;
onDragEnter: () => void;
onDragLeave: () => void;
};
export default useAssetDragEvents;
@@ -0,0 +1,38 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const react_1 = require("react");
const no_react_1 = require("remotion/no-react");
function useAssetDragEvents({ name, parentFolder, dropLocation, setDropLocation, }) {
const dragDepthRef = (0, react_1.useRef)(0);
const combinedParents = (0, react_1.useMemo)(() => {
return [parentFolder, name].filter(no_react_1.NoReactInternals.truthy).join('/');
}, [name, parentFolder]);
const isDropDiv = (0, react_1.useMemo)(() => {
return dropLocation === combinedParents;
}, [combinedParents, dropLocation]);
const onDragEnter = (0, react_1.useCallback)(() => {
if (dragDepthRef.current === 0) {
setDropLocation((currentDropLocation) => (currentDropLocation === null || currentDropLocation === void 0 ? void 0 : currentDropLocation.includes(combinedParents))
? currentDropLocation
: combinedParents);
}
dragDepthRef.current++;
}, [combinedParents, dragDepthRef, setDropLocation]);
const onDragLeave = (0, react_1.useCallback)(() => {
dragDepthRef.current--;
if (dragDepthRef.current === 0) {
setDropLocation((currentPath) => currentPath === combinedParents ? parentFolder : currentPath);
}
}, [combinedParents, dragDepthRef, parentFolder, setDropLocation]);
(0, react_1.useEffect)(() => {
if (dropLocation === null) {
dragDepthRef.current = 0;
}
}, [dropLocation]);
return {
isDropDiv,
onDragEnter,
onDragLeave,
};
}
exports.default = useAssetDragEvents;
@@ -0,0 +1 @@
export declare function useBreakpoint(breakpoint: number): boolean;
@@ -0,0 +1,16 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useBreakpoint = useBreakpoint;
const react_1 = require("react");
function useBreakpoint(breakpoint) {
const [compactUI, setCompactUI] = (0, react_1.useState)(window.innerWidth < breakpoint);
(0, react_1.useEffect)(() => {
function handleResize() {
setCompactUI(window.innerWidth < breakpoint);
}
window.addEventListener('resize', handleResize);
handleResize();
return () => window.removeEventListener('resize', handleResize);
}, [breakpoint]);
return compactUI;
}
@@ -0,0 +1 @@
export declare const useFileExistence: (outName: string) => boolean;
@@ -0,0 +1,65 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useFileExistence = void 0;
const react_1 = require("react");
const actions_1 = require("../components/RenderQueue/actions");
const client_id_1 = require("./client-id");
const useFileExistence = (outName) => {
const [exists, setExists] = (0, react_1.useState)(false);
const { previewServerState: state, subscribeToEvent } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx);
const clientId = state.type === 'connected' ? state.clientId : undefined;
const currentOutName = (0, react_1.useRef)('');
currentOutName.current = outName;
(0, react_1.useEffect)(() => {
if (!clientId) {
return;
}
(0, actions_1.subscribeToFileExistenceWatcher)({
file: outName,
clientId,
}).then((_exists) => {
if (currentOutName.current === outName) {
setExists(_exists);
}
});
return () => {
(0, actions_1.unsubscribeFromFileExistenceWatcher)({ file: outName, clientId });
};
}, [clientId, outName]);
(0, react_1.useEffect)(() => {
const listener = (event) => {
if (event.type !== 'watched-file-deleted') {
return;
}
if (event.file !== currentOutName.current) {
return;
}
if (currentOutName.current === outName) {
setExists(false);
}
};
const unsub = subscribeToEvent('watched-file-deleted', listener);
return () => {
unsub();
};
}, [outName, subscribeToEvent]);
(0, react_1.useEffect)(() => {
const listener = (event) => {
if (event.type !== 'watched-file-undeleted') {
return;
}
if (event.file !== outName) {
return;
}
if (currentOutName.current === outName) {
setExists(true);
}
};
const unsub = subscribeToEvent('watched-file-undeleted', listener);
return () => {
unsub();
};
}, [outName, subscribeToEvent]);
return exists;
};
exports.useFileExistence = useFileExistence;
@@ -0,0 +1,16 @@
import type { KeyEventType } from '../state/keybindings';
export declare const areKeyboardShortcutsDisabled: () => boolean;
export declare const useKeybinding: () => {
registerKeybinding: (options: {
event: KeyEventType;
key: string;
commandCtrlKey: boolean;
callback: (e: KeyboardEvent) => void;
preventDefault: boolean;
triggerIfInputFieldFocused: boolean;
keepRegisteredWhenNotHighestContext: boolean;
}) => {
unregister: () => void;
};
isHighestContext: boolean;
};
@@ -0,0 +1,75 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useKeybinding = exports.areKeyboardShortcutsDisabled = void 0;
const react_1 = require("react");
const keybindings_1 = require("../state/keybindings");
const z_index_1 = require("../state/z-index");
if (!process.env.KEYBOARD_SHORTCUTS_ENABLED) {
// eslint-disable-next-line no-console
console.warn('Keyboard shortcuts disabled either due to: a) --disable-keyboard-shortcuts being passed b) Config.setKeyboardShortcutsEnabled(false) being set or c) a Remotion version mismatch.');
}
const areKeyboardShortcutsDisabled = () => {
return !process.env.KEYBOARD_SHORTCUTS_ENABLED;
};
exports.areKeyboardShortcutsDisabled = areKeyboardShortcutsDisabled;
const useKeybinding = () => {
const [paneId] = (0, react_1.useState)(() => String(Math.random()));
const context = (0, react_1.useContext)(keybindings_1.KeybindingContext);
const { isHighestContext } = (0, z_index_1.useZIndex)();
const registerKeybinding = (0, react_1.useCallback)((options) => {
if (!process.env.KEYBOARD_SHORTCUTS_ENABLED) {
return {
unregister: () => undefined,
};
}
if (!isHighestContext && !options.keepRegisteredWhenNotHighestContext) {
return {
unregister: () => undefined,
};
}
const listener = (e) => {
const commandKey = window.navigator.platform.startsWith('Mac')
? e.metaKey
: e.ctrlKey;
// Apparently, e.key can be undefined in Edge:
// https://github.com/remotion-dev/remotion/issues/5637
if (!e.key) {
return;
}
if (e.key.toLowerCase() === options.key.toLowerCase() &&
options.commandCtrlKey === commandKey) {
if (!options.triggerIfInputFieldFocused) {
const { activeElement } = document;
if (activeElement instanceof HTMLInputElement) {
return;
}
if (activeElement instanceof HTMLTextAreaElement) {
return;
}
}
options.callback(e);
if (options.preventDefault) {
e.preventDefault();
}
}
};
const toRegister = {
registeredFromPane: paneId,
event: options.event,
key: options.key,
callback: listener,
id: String(Math.random()),
};
context.registerKeybinding(toRegister);
return {
unregister: () => context.unregisterKeybinding(toRegister),
};
}, [context, isHighestContext, paneId]);
(0, react_1.useEffect)(() => {
return () => {
context.unregisterPane(paneId);
};
}, [context, paneId]);
return (0, react_1.useMemo)(() => ({ registerKeybinding, isHighestContext }), [registerKeybinding, isHighestContext]);
};
exports.useKeybinding = useKeybinding;
@@ -0,0 +1,2 @@
import { type TSequence } from 'remotion';
export declare const useMaxMediaDuration: (s: TSequence, fps: number) => number | null;
@@ -0,0 +1,60 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useMaxMediaDuration = void 0;
const media_utils_1 = require("@remotion/media-utils");
const mediabunny_1 = require("mediabunny");
const react_1 = require("react");
const cache = new Map();
const getSrc = (s) => {
if (s.type === 'video') {
return s.src;
}
if (s.type === 'audio') {
return s.src;
}
return null;
};
const useMaxMediaDuration = (s, fps) => {
var _a;
const src = getSrc(s);
const [maxMediaDuration, setMaxMediaDuration] = (0, react_1.useState)(src ? ((_a = cache.get(src)) !== null && _a !== void 0 ? _a : null) : Infinity);
(0, react_1.useEffect)(() => {
if (!src) {
return;
}
const input = new mediabunny_1.Input({
formats: mediabunny_1.ALL_FORMATS,
source: new mediabunny_1.UrlSource(src),
});
input
.computeDuration()
.then((duration) => {
cache.set(src, Math.floor(duration * fps));
setMaxMediaDuration(Math.floor(duration * fps));
})
.catch((e) => {
if (e instanceof mediabunny_1.InputDisposedError) {
return;
}
// In case of CORS errors, fall back to getVideoMetadata
return (0, media_utils_1.getVideoMetadata)(src)
.then((metadata) => {
var _a;
const durationOrInfinity = (_a = metadata.durationInSeconds) !== null && _a !== void 0 ? _a : Infinity;
cache.set(src, Math.floor(durationOrInfinity * fps));
setMaxMediaDuration(Math.floor(durationOrInfinity * fps));
})
.catch(() => {
// Silently handle getVideoMetadata failures to prevent unhandled rejections
});
});
return () => {
input.dispose();
};
}, [src, fps]);
if (maxMediaDuration !== null && (s.type === 'audio' || s.type === 'video')) {
return maxMediaDuration / s.playbackRate;
}
return maxMediaDuration;
};
exports.useMaxMediaDuration = useMaxMediaDuration;
@@ -0,0 +1,7 @@
import type { Menu } from '../components/Menu/MenuItem';
import type { TQuickSwitcherResult } from '../components/QuickSwitcher/QuickSwitcherResult';
import type { ModalState } from '../state/modals';
type Structure = Menu[];
export declare const useMenuStructure: (closeMenu: () => void, readOnlyStudio: boolean) => Structure;
export declare const makeSearchResults: (actions: Structure, setSelectedModal: (value: React.SetStateAction<ModalState | null>) => void) => TQuickSwitcherResult[];
export {};
@@ -0,0 +1,909 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.makeSearchResults = exports.useMenuStructure = void 0;
const jsx_runtime_1 = require("react/jsx-runtime");
const react_1 = require("react");
const remotion_1 = require("remotion");
const no_react_1 = require("remotion/no-react");
const restart_studio_1 = require("../api/restart-studio");
const AskAiModal_1 = require("../components/AskAiModal");
const NotificationCenter_1 = require("../components/Notifications/NotificationCenter");
const SizeSelector_1 = require("../components/SizeSelector");
const TimelineInOutToggle_1 = require("../components/TimelineInOutToggle");
const layout_1 = require("../components/layout");
const ShortcutHint_1 = require("../error-overlay/remotion-overlay/ShortcutHint");
const Checkmark_1 = require("../icons/Checkmark");
const canvas_ref_1 = require("../state/canvas-ref");
const checkerboard_1 = require("../state/checkerboard");
const editor_guides_1 = require("../state/editor-guides");
const editor_rulers_1 = require("../state/editor-rulers");
const editor_zoom_gestures_1 = require("../state/editor-zoom-gestures");
const modals_1 = require("../state/modals");
const sidebar_1 = require("../state/sidebar");
const check_fullscreen_support_1 = require("./check-fullscreen-support");
const client_id_1 = require("./client-id");
const get_git_menu_item_1 = require("./get-git-menu-item");
const mobile_layout_1 = require("./mobile-layout");
const open_in_editor_1 = require("./open-in-editor");
const pick_color_1 = require("./pick-color");
const show_browser_rendering_1 = require("./show-browser-rendering");
const use_keybinding_1 = require("./use-keybinding");
const openExternal = (link) => {
window.open(link, '_blank');
};
const rotate = {
transform: `rotate(90deg)`,
};
const ICON_SIZE = 16;
const getFileMenu = ({ readOnlyStudio, closeMenu, previewServerState, setSelectedModal, }) => {
const items = [
window.remotion_isReadOnlyStudio
? {
id: 'input-props-override',
value: 'input-props-override',
label: 'Set input props...',
onClick: () => {
closeMenu();
setSelectedModal({
type: 'input-props-override',
});
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Override input props',
}
: null,
readOnlyStudio
? null
: {
id: 'render',
value: 'render',
label: 'Render...',
onClick: () => {
closeMenu();
if (previewServerState !== 'connected') {
(0, NotificationCenter_1.showNotification)('Restart the studio to render', 2000);
return;
}
const renderButton = document.getElementById('render-modal-button-server');
renderButton.click();
},
type: 'item',
keyHint: 'R',
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Render...',
},
show_browser_rendering_1.SHOW_BROWSER_RENDERING && !readOnlyStudio
? {
id: 'render-on-web',
value: 'render-on-web',
label: 'Render on web...',
onClick: () => {
closeMenu();
const renderButton = document.getElementById('render-modal-button-client');
renderButton.click();
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Render on web...',
}
: null,
window.remotion_editorName && !readOnlyStudio
? {
type: 'divider',
id: 'open-in-editor-divider',
}
: null,
window.remotion_editorName && !readOnlyStudio
? {
id: 'open-in-editor',
value: 'open-in-editor',
label: `Open in ${window.remotion_editorName}`,
onClick: async () => {
await (0, open_in_editor_1.openInEditor)({
originalFileName: `${window.remotion_cwd}`,
originalLineNumber: 1,
originalColumnNumber: 1,
originalFunctionName: null,
originalScriptCode: null,
})
.then((res) => res.json())
.then(({ success }) => {
if (!success) {
(0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
}
})
.catch((err) => {
// eslint-disable-next-line no-console
console.error(err);
(0, NotificationCenter_1.showNotification)(`Could not open ${window.remotion_editorName}`, 2000);
});
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Open in editor...',
}
: null,
(0, get_git_menu_item_1.getGitMenuItem)(),
].filter(no_react_1.NoReactInternals.truthy);
if (items.length === 0) {
return null;
}
return {
id: 'file',
label: 'File',
leaveLeftPadding: false,
items,
quickSwitcherLabel: null,
};
};
const useMenuStructure = (closeMenu, readOnlyStudio) => {
const { setSelectedModal } = (0, react_1.useContext)(modals_1.ModalsContext);
const { checkerboard, setCheckerboard } = (0, react_1.useContext)(checkerboard_1.CheckerboardContext);
const { editorZoomGestures, setEditorZoomGestures } = (0, react_1.useContext)(editor_zoom_gestures_1.EditorZoomGesturesContext);
const { editorShowRulers, setEditorShowRulers } = (0, react_1.useContext)(editor_rulers_1.EditorShowRulersContext);
const { editorShowGuides, setEditorShowGuides } = (0, react_1.useContext)(editor_guides_1.EditorShowGuidesContext);
const { size, setSize } = (0, react_1.useContext)(remotion_1.Internals.PreviewSizeContext);
const { type } = (0, react_1.useContext)(client_id_1.StudioServerConnectionCtx).previewServerState;
const { setSidebarCollapsedState, sidebarCollapsedStateLeft, sidebarCollapsedStateRight, } = (0, react_1.useContext)(sidebar_1.SidebarContext);
const sizes = (0, react_1.useMemo)(() => (0, SizeSelector_1.getUniqueSizes)(size), [size]);
const isFullscreenSupported = (0, check_fullscreen_support_1.checkFullscreenSupport)();
const { remotion_packageManager } = window;
const sizePreselectIndex = sizes.findIndex((s) => String(size.size) === String(s.size));
const mobileLayout = (0, mobile_layout_1.useMobileLayout)();
const structure = (0, react_1.useMemo)(() => {
let struct = [
{
id: 'remotion',
label: ((0, jsx_runtime_1.jsx)(layout_1.Row, { align: "center", justify: "center", children: (0, jsx_runtime_1.jsx)("svg", { width: ICON_SIZE, height: ICON_SIZE, viewBox: "-100 -100 400 400", style: rotate, children: (0, jsx_runtime_1.jsx)("path", { fill: "#fff", stroke: "#fff", strokeWidth: "100", strokeLinejoin: "round", d: "M 2 172 a 196 100 0 0 0 195 5 A 196 240 0 0 0 100 2.259 A 196 240 0 0 0 2 172 z" }) }) })),
leaveLeftPadding: false,
items: [
{
id: 'about',
value: 'about',
label: 'About Remotion',
onClick: () => {
closeMenu();
openExternal('https://remotion.dev');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Help: About Remotion',
},
{
id: 'changelog',
value: 'changelog',
label: 'Changelog',
onClick: () => {
closeMenu();
openExternal('https://github.com/remotion-dev/remotion/releases');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Help: Changelog',
},
{
id: 'license',
value: 'license',
label: 'License',
onClick: () => {
closeMenu();
openExternal('https://github.com/remotion-dev/remotion/blob/main/LICENSE.md');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Help: License',
},
{
id: 'acknowledgements',
value: 'acknowledgements',
label: 'Acknowledgements',
onClick: () => {
closeMenu();
openExternal('https://remotion.dev/acknowledgements');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Help: Acknowledgements',
},
{
type: 'divider',
id: 'timeline-divider-1',
},
{
id: 'restart-studio',
value: 'restart-studio',
label: 'Restart Studio Server',
onClick: () => {
closeMenu();
(0, restart_studio_1.restartStudio)();
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Restart Studio Server',
},
],
quickSwitcherLabel: null,
},
getFileMenu({
readOnlyStudio,
closeMenu,
previewServerState: type,
setSelectedModal,
}),
{
id: 'view',
label: 'View',
leaveLeftPadding: true,
items: [
{
id: 'preview-size',
keyHint: null,
label: 'Preview size',
onClick: () => undefined,
type: 'item',
value: 'preview-size',
leftItem: null,
subMenu: {
leaveLeftSpace: true,
preselectIndex: sizePreselectIndex,
items: sizes.map((newSize) => ({
id: String(newSize.size),
keyHint: newSize.size === 1 ? '0' : null,
label: (0, SizeSelector_1.getPreviewSizeLabel)(newSize),
leftItem: String(newSize.size) === String(size.size) ? ((0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {})) : null,
onClick: () => {
closeMenu();
setSize(() => newSize);
},
subMenu: null,
type: 'item',
value: newSize.size,
quickSwitcherLabel: null,
})),
quickSwitcherLabel: null,
},
quickSwitcherLabel: null,
},
{
id: 'editor-zoom-gestures',
keyHint: null,
label: 'Zoom and Pan Gestures',
onClick: () => {
closeMenu();
setEditorZoomGestures((c) => !c);
},
type: 'item',
value: 'editor-zoom-gestures',
leftItem: editorZoomGestures ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
subMenu: null,
quickSwitcherLabel: editorZoomGestures
? 'Disable Zoom and Pan Gestures'
: 'Enable Zoom and Pan Gestures',
},
{
id: 'show-rulers',
keyHint: null,
label: 'Show Rulers',
onClick: () => {
closeMenu();
setEditorShowRulers((c) => !c);
},
type: 'item',
value: 'show-ruler',
leftItem: editorShowRulers ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
subMenu: null,
quickSwitcherLabel: editorShowRulers
? 'Hide Rulers'
: 'Show Rulers',
},
{
id: 'show-guides',
keyHint: null,
label: 'Show Guides',
onClick: () => {
closeMenu();
setEditorShowGuides((c) => !c);
},
type: 'item',
value: 'show-guides',
leftItem: editorShowGuides ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
subMenu: null,
quickSwitcherLabel: editorShowGuides
? 'Hide Guides'
: 'Show Guides',
},
{
id: 'timeline-divider-1',
type: 'divider',
},
{
id: 'left-sidebar',
label: 'Left Sidebar',
keyHint: null,
type: 'item',
value: 'preview-size',
leftItem: null,
quickSwitcherLabel: null,
subMenu: {
leaveLeftSpace: true,
preselectIndex: 0,
items: [
{
id: 'left-sidebar-responsive',
keyHint: null,
label: 'Responsive',
leftItem: sidebarCollapsedStateLeft === 'responsive' ? ((0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {})) : null,
onClick: () => {
closeMenu();
setSidebarCollapsedState({
left: 'responsive',
right: null,
});
},
subMenu: null,
type: 'item',
value: 'responsive',
quickSwitcherLabel: null,
},
{
id: 'left-sidebar-expanded',
keyHint: null,
label: 'Expanded',
leftItem: sidebarCollapsedStateLeft === 'expanded' ? ((0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {})) : null,
onClick: () => {
closeMenu();
setSidebarCollapsedState({ left: 'expanded', right: null });
},
subMenu: null,
type: 'item',
value: 'expanded',
quickSwitcherLabel: 'Expand',
},
{
id: 'left-sidebar-collapsed',
keyHint: null,
label: 'Collapsed',
leftItem: sidebarCollapsedStateLeft === 'collapsed' ? ((0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {})) : null,
onClick: () => {
closeMenu();
setSidebarCollapsedState({
left: 'collapsed',
right: null,
});
},
subMenu: null,
type: 'item',
value: 'collapsed',
quickSwitcherLabel: 'Collapse',
},
],
},
onClick: () => undefined,
},
{
id: 'right-sidebar',
label: 'Right Sidebar',
keyHint: null,
type: 'item',
value: 'preview-size',
leftItem: null,
quickSwitcherLabel: null,
subMenu: {
leaveLeftSpace: true,
preselectIndex: 0,
items: [
{
id: 'sidebar-expanded',
keyHint: null,
label: 'Expanded',
leftItem: sidebarCollapsedStateRight === 'expanded' ? ((0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {})) : null,
onClick: () => {
closeMenu();
setSidebarCollapsedState({ left: null, right: 'expanded' });
},
subMenu: null,
type: 'item',
value: 'expanded',
quickSwitcherLabel: 'Expand',
},
{
id: 'right-sidebar-collapsed',
keyHint: null,
label: 'Collapsed',
leftItem: sidebarCollapsedStateRight === 'collapsed' ? ((0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {})) : null,
onClick: () => {
closeMenu();
setSidebarCollapsedState({
left: null,
right: 'collapsed',
});
},
subMenu: null,
type: 'item',
value: 'collapsed',
quickSwitcherLabel: 'Collapse',
},
],
},
onClick: () => undefined,
},
{
id: 'timeline-divider-2',
type: 'divider',
},
{
id: 'checkerboard',
keyHint: 'T',
label: 'Transparency as checkerboard',
onClick: () => {
closeMenu();
setCheckerboard((c) => !c);
},
type: 'item',
value: 'checkerboard',
leftItem: checkerboard ? (0, jsx_runtime_1.jsx)(Checkmark_1.Checkmark, {}) : null,
subMenu: null,
quickSwitcherLabel: checkerboard
? 'Disable Checkerboard Transparency'
: 'Enable Checkerboard Transparency',
},
{
id: 'timeline-divider-3',
type: 'divider',
},
{
id: 'quick-switcher',
keyHint: `${ShortcutHint_1.cmdOrCtrlCharacter}+K`,
label: 'Quick Switcher',
onClick: () => {
closeMenu();
setSelectedModal({
type: 'quick-switcher',
mode: 'compositions',
invocationTimestamp: Date.now(),
});
},
type: 'item',
value: 'quick-switcher',
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Switch composition',
},
{
id: 'in-out-divider-5',
type: 'divider',
},
{
id: 'in-mark',
keyHint: 'I',
label: 'In Mark',
leftItem: null,
onClick: () => {
var _a;
closeMenu();
(_a = TimelineInOutToggle_1.inOutHandles.current) === null || _a === void 0 ? void 0 : _a.inMarkClick(null);
},
subMenu: null,
type: 'item',
value: 'in-mark',
quickSwitcherLabel: 'Timeline: Set In Mark',
},
{
id: 'out-mark',
keyHint: 'O',
label: 'Out Mark',
leftItem: null,
onClick: () => {
var _a;
closeMenu();
(_a = TimelineInOutToggle_1.inOutHandles.current) === null || _a === void 0 ? void 0 : _a.outMarkClick(null);
},
subMenu: null,
type: 'item',
value: 'out-mark',
quickSwitcherLabel: 'Timeline: Set Out Mark',
},
{
id: 'x-mark',
keyHint: 'X',
label: 'Clear In/Out Marks',
leftItem: null,
onClick: () => {
var _a;
closeMenu();
(_a = TimelineInOutToggle_1.inOutHandles.current) === null || _a === void 0 ? void 0 : _a.clearMarks();
},
subMenu: null,
type: 'item',
value: 'clear-marks',
quickSwitcherLabel: 'Timeline: Clear In and Out Mark',
},
{
id: 'goto-time',
keyHint: 'G',
label: 'Go to frame',
leftItem: null,
onClick: () => {
var _a;
closeMenu();
(_a = remotion_1.Internals.timeValueRef.current) === null || _a === void 0 ? void 0 : _a.goToFrame();
},
subMenu: null,
type: 'item',
value: 'clear-marks',
quickSwitcherLabel: 'Timeline: Go to frame',
},
{
id: 'fullscreen-divider',
type: 'divider',
},
isFullscreenSupported
? {
id: 'fullscreen',
keyHint: null,
label: 'Fullscreen',
leftItem: null,
onClick: () => {
var _a;
closeMenu();
(_a = canvas_ref_1.drawRef.current) === null || _a === void 0 ? void 0 : _a.requestFullscreen();
},
subMenu: null,
type: 'item',
value: 'fullscreen',
quickSwitcherLabel: 'Go Fullscreen',
}
: null,
].filter(remotion_1.Internals.truthy),
},
{
id: 'tools',
label: 'Tools',
leaveLeftPadding: false,
items: [
process.env.ASK_AI_ENABLED
? {
id: 'ask-ai',
value: 'ask-ai',
label: 'Ask AI',
onClick: () => {
var _a;
closeMenu();
(_a = AskAiModal_1.askAiModalRef.current) === null || _a === void 0 ? void 0 : _a.toggle();
},
leftItem: null,
keyHint: `${ShortcutHint_1.cmdOrCtrlCharacter}+I`,
subMenu: null,
type: 'item',
quickSwitcherLabel: 'Ask AI',
}
: null,
'EyeDropper' in window
? {
id: 'color-picker',
value: 'color-picker',
label: 'Color Picker',
onClick: () => {
closeMenu();
(0, pick_color_1.pickColor)();
},
leftItem: null,
keyHint: null,
subMenu: null,
type: 'item',
quickSwitcherLabel: 'Show Color Picker',
}
: null,
{
id: 'spring-editor',
value: 'spring-editor',
label: 'Timing Editor',
onClick: () => {
closeMenu();
window.open('https://www.remotion.dev/timing-editor', '_blank');
},
leftItem: null,
keyHint: null,
subMenu: null,
type: 'item',
quickSwitcherLabel: 'Open spring() Editor',
},
].filter(remotion_1.Internals.truthy),
quickSwitcherLabel: null,
},
readOnlyStudio || remotion_packageManager === 'unknown'
? null
: {
id: 'install',
label: 'Packages',
leaveLeftPadding: false,
items: [
{
id: 'install-packages',
value: 'install-packages',
label: 'Install...',
onClick: () => {
closeMenu();
setSelectedModal({
type: 'install-packages',
packageManager: remotion_packageManager,
});
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: `Install packages`,
},
],
},
{
id: 'help',
label: 'Help',
leaveLeftPadding: false,
items: [
{
id: 'shortcuts',
value: 'shortcuts',
label: (0, use_keybinding_1.areKeyboardShortcutsDisabled)()
? 'Shortcuts (disabled)'
: 'Shortcuts',
onClick: () => {
closeMenu();
setSelectedModal({
type: 'quick-switcher',
mode: 'docs',
invocationTimestamp: Date.now(),
});
},
keyHint: '?',
leftItem: null,
subMenu: null,
type: 'item',
quickSwitcherLabel: (0, use_keybinding_1.areKeyboardShortcutsDisabled)()
? 'Show all Keyboard Shortcuts (disabled)'
: 'Show all Keyboard Shortcuts',
},
{
id: 'docs',
value: 'docs',
label: 'Docs',
onClick: () => {
closeMenu();
openExternal('https://remotion.dev/docs');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Visit Documentation',
},
{
id: 'file-issue',
value: 'file-issue',
label: 'File an issue',
onClick: () => {
closeMenu();
openExternal('https://github.com/remotion-dev/remotion/issues/new/choose');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'File GitHub issue',
},
{
id: 'discord',
value: 'discord',
label: 'Join Discord community',
onClick: () => {
closeMenu();
openExternal('https://discord.com/invite/6VzzNDwUwV');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: null,
},
{
id: 'help-divider-6',
type: 'divider',
},
{
id: 'insta',
value: 'insta',
label: 'Instagram',
onClick: () => {
closeMenu();
openExternal('https://instagram.com/remotion');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Follow Remotion on Instagram',
},
{
id: 'x',
value: 'x',
label: 'X',
onClick: () => {
closeMenu();
openExternal('https://x.com/remotion');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Follow Remotion on X',
},
{
id: 'youtube',
value: 'youtube',
label: 'YouTube',
onClick: () => {
closeMenu();
openExternal('https://www.youtube.com/@remotion_dev');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Watch Remotion on YouTube',
},
{
id: 'linkedin',
value: 'linkedin',
label: 'LinkedIn',
onClick: () => {
closeMenu();
openExternal('https://www.linkedin.com/company/remotion-dev/');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Follow Remotion on LinkedIn',
},
{
id: 'tiktok',
value: 'tiktok',
label: 'TikTok',
onClick: () => {
closeMenu();
openExternal('https://www.tiktok.com/@remotion');
},
type: 'item',
keyHint: null,
leftItem: null,
subMenu: null,
quickSwitcherLabel: 'Follow Remotion on TikTok',
},
],
},
].filter(remotion_1.Internals.truthy);
if (mobileLayout) {
struct = [
{
...struct[0],
items: [
...struct.slice(1).map((s) => {
return {
...s,
keyHint: null,
onClick: () => undefined,
type: 'item',
value: s.id,
leftItem: null,
subMenu: {
items: s.items,
leaveLeftSpace: true,
preselectIndex: 0,
},
quickSwitcherLabel: null,
};
}),
...struct[0].items,
],
},
];
}
return struct;
}, [
readOnlyStudio,
closeMenu,
type,
sizePreselectIndex,
sizes,
editorZoomGestures,
editorShowRulers,
editorShowGuides,
sidebarCollapsedStateLeft,
sidebarCollapsedStateRight,
checkerboard,
isFullscreenSupported,
remotion_packageManager,
mobileLayout,
size.size,
setSize,
setEditorZoomGestures,
setEditorShowRulers,
setEditorShowGuides,
setSidebarCollapsedState,
setCheckerboard,
setSelectedModal,
]);
return structure;
};
exports.useMenuStructure = useMenuStructure;
const getItemLabel = (item) => {
var _a;
if (item.quickSwitcherLabel !== null) {
return item.quickSwitcherLabel;
}
if (typeof item.label === 'string') {
return item.label;
}
return (_a = item.label) === null || _a === void 0 ? void 0 : _a.toString();
};
const itemToSearchResult = (item, setSelectedModal, prefixes) => {
if (item.subMenu) {
return item.subMenu.items
.map((subItem) => {
if (subItem.type === 'divider') {
return null;
}
return itemToSearchResult(subItem, setSelectedModal, [
...prefixes,
getItemLabel(item),
]);
})
.flat(1)
.filter(no_react_1.NoReactInternals.truthy);
}
return [
{
type: 'menu-item',
id: item.id,
onSelected: () => {
setSelectedModal(null);
item.onClick(item.id, null);
},
title: [...prefixes, getItemLabel(item)].join(': '),
},
];
};
const makeSearchResults = (actions, setSelectedModal) => {
const items = actions
.map((menu) => {
return menu.items.map((item) => {
if (item.type === 'divider') {
return null;
}
return itemToSearchResult(item, setSelectedModal, []);
});
})
.flat(Infinity)
.filter(no_react_1.NoReactInternals.truthy);
return items;
};
exports.makeSearchResults = makeSearchResults;
@@ -0,0 +1,16 @@
import type { Size } from '@remotion/player';
import type { AssetMetadata } from './get-asset-metadata';
import type { Dimensions } from './is-current-selected-still';
export declare const useStudioCanvasDimensions: ({ canvasSize, contentDimensions, assetMetadata, }: {
canvasSize: Size | null;
contentDimensions: Dimensions | "none" | null;
assetMetadata: AssetMetadata | null;
}) => {
canvasPosition: {
left: number;
top: number;
width: number;
height: number;
};
scale: number;
};
@@ -0,0 +1,59 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.useStudioCanvasDimensions = void 0;
const player_1 = require("@remotion/player");
const react_1 = require("react");
const remotion_1 = require("remotion");
const useStudioCanvasDimensions = ({ canvasSize, contentDimensions, assetMetadata, }) => {
const { size: previewSize } = (0, react_1.useContext)(remotion_1.Internals.PreviewSizeContext);
const { centerX, centerY, scale } = (0, react_1.useMemo)(() => {
if (contentDimensions === 'none' ||
contentDimensions === null ||
(assetMetadata && assetMetadata.type === 'not-found') ||
!canvasSize) {
return {
centerX: previewSize.translation.x,
centerY: previewSize.translation.y,
scale: 1,
};
}
return player_1.PlayerInternals.calculateCanvasTransformation({
canvasSize,
compositionHeight: contentDimensions.height,
compositionWidth: contentDimensions.width,
previewSize: previewSize.size,
});
}, [
canvasSize,
contentDimensions,
previewSize.size,
previewSize.translation.y,
previewSize.translation.x,
assetMetadata,
]);
const canvasPosition = (0, react_1.useMemo)(() => {
return {
left: centerX - previewSize.translation.x,
top: centerY - previewSize.translation.y,
width: contentDimensions === 'none' || !contentDimensions
? (canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.width) || 0
: contentDimensions.width * scale,
height: contentDimensions === 'none' || !contentDimensions
? (canvasSize === null || canvasSize === void 0 ? void 0 : canvasSize.height) || 0
: contentDimensions.height * scale,
};
}, [
scale,
centerX,
previewSize.translation.x,
previewSize.translation.y,
centerY,
canvasSize,
contentDimensions,
]);
return {
canvasPosition,
scale,
};
};
exports.useStudioCanvasDimensions = useStudioCanvasDimensions;
@@ -0,0 +1,4 @@
import type { _InternalTypes } from 'remotion';
export declare const validateCompositionName: (compName: string, compositions: _InternalTypes["AnyComposition"][]) => string | null;
export declare const validateCompositionDimension: (dimension: "Width" | "Height", value: number) => string | null;
export declare const validateCompositionDuration: (value: number) => string | null;
@@ -0,0 +1,40 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateCompositionDuration = exports.validateCompositionDimension = exports.validateCompositionName = void 0;
const remotion_1 = require("remotion");
const validateCompositionName = (compName, compositions) => {
if (!remotion_1.Internals.isCompositionIdValid(compName)) {
return remotion_1.Internals.invalidCompositionErrorMessage;
}
if (compositions.find((c) => c.id === compName)) {
return `A composition with that name already exists.`;
}
return null;
};
exports.validateCompositionName = validateCompositionName;
const validateCompositionDimension = (dimension, value) => {
if (Number(value) % 2 !== 0) {
return `${dimension} should be divisible by 2, since H264 codec doesn't support odd dimensions.`;
}
if (Number.isNaN(Number(value))) {
return 'Invalid number.';
}
if (Number(value) === 0) {
return dimension + ' cannot be zero.';
}
return null;
};
exports.validateCompositionDimension = validateCompositionDimension;
const validateCompositionDuration = (value) => {
if (value % 1 !== 0) {
return `Duration must be an integer.`;
}
if (Number.isNaN(value)) {
return 'Invalid number.';
}
if (value === 0) {
return 'Duration cannot be zero.';
}
return null;
};
exports.validateCompositionDuration = validateCompositionDuration;