From 162ed90d780914034ac934d0ccd93b6fdf642bbc Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 11:07:14 +0100 Subject: [PATCH 01/30] Force bt601 color space for GIF codec GIFs don't support bt709/bt2020, so always use bt601 regardless of the user-specified color space setting. Co-Authored-By: Claude Opus 4.6 --- packages/renderer/src/ffmpeg-args.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/renderer/src/ffmpeg-args.ts b/packages/renderer/src/ffmpeg-args.ts index 209ebc0c4d2..81b3657ad19 100644 --- a/packages/renderer/src/ffmpeg-args.ts +++ b/packages/renderer/src/ffmpeg-args.ts @@ -115,7 +115,8 @@ export const generateFfmpegArgs = ({ `Encoder: ${encoderName}, hardware accelerated: ${hardwareAccelerated}`, ); - const resolvedColorSpace = colorSpace ?? DEFAULT_COLOR_SPACE; + const resolvedColorSpace: ColorSpace = + codec === 'gif' ? 'bt601' : (colorSpace ?? DEFAULT_COLOR_SPACE); const colorSpaceOptions: string[][] = resolvedColorSpace === 'bt709' From 9ad4fe43bdbca4e1a1765ee6c3805be3d0a8e03d Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 11:17:41 +0100 Subject: [PATCH 02/30] Add bt601 color space option for v4 (same as default) Co-Authored-By: Claude Opus 4.6 --- packages/renderer/src/options/color-space.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/renderer/src/options/color-space.tsx b/packages/renderer/src/options/color-space.tsx index 3d7addee5ca..5289144b479 100644 --- a/packages/renderer/src/options/color-space.tsx +++ b/packages/renderer/src/options/color-space.tsx @@ -1,7 +1,7 @@ import {NoReactInternals} from 'remotion/no-react'; import type {AnyRemotionOption} from './option'; -const validV4ColorSpaces = ['default', 'bt709', 'bt2020-ncl'] as const; +const validV4ColorSpaces = ['default', 'bt601', 'bt709', 'bt2020-ncl'] as const; const validV5ColorSpaces = ['bt601', 'bt709', 'bt2020-ncl'] as const; export const validColorSpaces = ( @@ -43,6 +43,14 @@ export const colorSpaceOption = { ) : ( <> + + {'"'}bt601{'"'} + {' '} + (same as{' '} + + {'"'}default{'"'} + + , since v4.0.424),{' '} {'"'}bt709{'"'} {' '} From 32198be9de7793ff0f149a7b79e3a6672b2c9d6c Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 12:51:51 +0100 Subject: [PATCH 03/30] @remotion/renderer: Fix numberOfGifLoops being ignored on Lambda The muxVideoAndAudio step was re-muxing the GIF with -c:v copy without passing the -loop flag, causing FFmpeg's GIF muxer to use its default (infinite loop) and overriding the correct loop count. Co-Authored-By: Claude Opus 4.6 --- packages/renderer/src/combine-chunks.ts | 1 + packages/renderer/src/mux-video-and-audio.ts | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/packages/renderer/src/combine-chunks.ts b/packages/renderer/src/combine-chunks.ts index 8b57e06efbd..1e53c40d26a 100644 --- a/packages/renderer/src/combine-chunks.ts +++ b/packages/renderer/src/combine-chunks.ts @@ -246,6 +246,7 @@ export const internalCombineChunks = async ({ cancelSignal, addFaststart: codecSupportsFastStart[codec], metadata, + numberOfGifLoops, }); onProgress({totalProgress: 1, frames: numberOfFrames}); rmSync(filelistDir, {recursive: true}); diff --git a/packages/renderer/src/mux-video-and-audio.ts b/packages/renderer/src/mux-video-and-audio.ts index dfb36c80da8..5cbce21df8b 100644 --- a/packages/renderer/src/mux-video-and-audio.ts +++ b/packages/renderer/src/mux-video-and-audio.ts @@ -1,4 +1,5 @@ import {callFf} from './call-ffmpeg'; +import {convertNumberOfGifLoopsToFfmpegSyntax} from './convert-number-of-gif-loops-to-ffmpeg'; import type {LogLevel} from './log-level'; import {Log} from './logger'; import type {CancelSignal} from './make-cancel-signal'; @@ -18,6 +19,7 @@ export const muxVideoAndAudio = async ({ cancelSignal, addFaststart, metadata, + numberOfGifLoops, }: { videoOutput: string | null; audioOutput: string | null; @@ -30,6 +32,7 @@ export const muxVideoAndAudio = async ({ cancelSignal: CancelSignal | undefined; addFaststart: boolean; metadata?: Record | null; + numberOfGifLoops: number | null; }) => { const startTime = Date.now(); Log.verbose({indent, logLevel}, 'Muxing video and audio together'); @@ -44,6 +47,10 @@ export const muxVideoAndAudio = async ({ videoOutput ? 'copy' : null, audioOutput ? '-c:a' : null, audioOutput ? 'copy' : null, + numberOfGifLoops === null ? null : '-loop', + numberOfGifLoops === null + ? null + : convertNumberOfGifLoopsToFfmpegSyntax(numberOfGifLoops), addFaststart ? '-movflags' : null, addFaststart ? 'faststart' : null, ...makeMetadataArgs(metadata ?? {}), From c2daf14e427ea805071616ecf9c33edcc0f7f7f9 Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 12:52:14 +0100 Subject: [PATCH 04/30] @remotion/serverless: Retry on socket hang up and ECONNRESET errors Co-Authored-By: Claude Opus 4.6 --- packages/serverless/src/stream-renderer.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/serverless/src/stream-renderer.ts b/packages/serverless/src/stream-renderer.ts index 311c3dd6a67..f37071b3ffc 100644 --- a/packages/serverless/src/stream-renderer.ts +++ b/packages/serverless/src/stream-renderer.ts @@ -185,6 +185,8 @@ const streamRenderer = ({ const shouldRetry = (err as Error).stack?.includes('Error: aborted') || (err as Error).stack?.includes('ETIMEDOUT') || + (err as Error).stack?.includes('socket hang up') || + (err as Error).stack?.includes('ECONNRESET') || false; resolve({ From 35e20b6ba16d65246e7d06b6ad2242adb8bb49ae Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 13:06:11 +0100 Subject: [PATCH 05/30] `@remotion/media`: Upgrade Mediabunny to 1.34.4, register AC3 decoder Co-Authored-By: Claude Opus 4.6 --- bun.lock | 31 ++++++------------- package.json | 6 ++-- packages/cli/src/extra-packages.ts | 2 +- packages/docs/docs/mediabunny/version.mdx | 4 +-- packages/media/bundle.ts | 1 + packages/media/src/index.ts | 3 ++ packages/studio-shared/src/package-info.ts | 2 +- .../template-music-visualization/package.json | 2 +- packages/template-recorder/package.json | 2 +- packages/template-three/package.json | 2 +- packages/web-renderer/bundle.ts | 2 +- packages/web-renderer/package.json | 3 +- 12 files changed, 25 insertions(+), 35 deletions(-) diff --git a/bun.lock b/bun.lock index fdaea9ed43f..0c691270741 100644 --- a/bun.lock +++ b/bun.lock @@ -1599,7 +1599,7 @@ "@remotion/media": "workspace:*", "@remotion/media-utils": "workspace:*", "@remotion/zod-types": "workspace:*", - "mediabunny": "1.34.2", + "mediabunny": "1.34.4", "react": "19.2.3", "react-dom": "19.2.3", "remotion": "workspace:*", @@ -1923,7 +1923,7 @@ "connect": "3.7.0", "eslint": "9.19.0", "lucide-react": "0.516.0", - "mediabunny": "1.34.2", + "mediabunny": "1.34.4", "react": "19.2.3", "react-dom": "19.2.3", "remotion": "workspace:*", @@ -2059,7 +2059,7 @@ "@remotion/media": "workspace:*", "@remotion/three": "workspace:*", "@remotion/zod-types": "workspace:*", - "mediabunny": "1.34.2", + "mediabunny": "1.34.4", "react": "19.2.3", "react-dom": "19.2.3", "remotion": "workspace:*", @@ -2275,7 +2275,6 @@ "name": "@remotion/web-renderer", "version": "4.0.423", "dependencies": { - "@mediabunny/ac3": "catalog:", "@remotion/licensing": "workspace:*", "mediabunny": "catalog:", "remotion": "workspace:*", @@ -2365,8 +2364,8 @@ "@aws-sdk/lib-storage": "3.986.0", "@aws-sdk/middleware-flexible-checksums": "3.972.5", "@aws-sdk/s3-request-presigner": "3.986.0", - "@mediabunny/ac3": "1.34.3", - "@mediabunny/mp3-encoder": "1.34.3", + "@mediabunny/ac3": "1.34.4", + "@mediabunny/mp3-encoder": "1.34.4", "@react-three/fiber": "9.2.0", "@types/bun": "1.3.3", "@types/dom-webcodecs": "0.1.11", @@ -2379,7 +2378,7 @@ "@vitejs/plugin-react": "4.1.0", "@vitest/browser-playwright": "4.0.9", "eslint": "9.19.0", - "mediabunny": "1.34.3", + "mediabunny": "1.34.4", "next": "16.1.5", "openai": "4.67.1", "playwright": "1.55.1", @@ -3304,9 +3303,9 @@ "@mdx-js/react": ["@mdx-js/react@2.3.0", "", { "dependencies": { "@types/mdx": "2.0.5", "@types/react": "19.0.0" }, "peerDependencies": { "react": "19.0.0" } }, "sha512-zQH//gdOmuu7nt2oJR29vFhDv88oGPmVw6BggmrHeMI+xgEkp1B2dX9/bMBSYtK0dyLX/aOmesKS09g222K1/g=="], - "@mediabunny/ac3": ["@mediabunny/ac3@1.34.3", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-YpQN7dOQHbA3DX7Qt5DoWLcf8LDIHzO3i5jrl++GoCCbQQykS7L3Ea66oCKZCqlX42kLZhavPOgd0OXGFf+dEQ=="], + "@mediabunny/ac3": ["@mediabunny/ac3@1.34.4", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-x8mt6jbBl5iEIPPrKdhV9Ui3PnSv+jrtRekbWjdh4FYGwlqvLxko1HQgCSg8sCt/5da0A4XsfYI3X/CpL0heCg=="], - "@mediabunny/mp3-encoder": ["@mediabunny/mp3-encoder@1.34.3", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-be3vYjGKSWRzKMfajGbdej6IjEE7fLHIONbOy9jhUO+57OF8ZCVH3SpG6zEuyZdnsJonEVqnyBkQkchHB2Q+Fg=="], + "@mediabunny/mp3-encoder": ["@mediabunny/mp3-encoder@1.34.4", "", { "peerDependencies": { "mediabunny": "^1.0.0" } }, "sha512-k3DiqwSfjsX5WKqNgiGSqF90HPbHQ4qt8vaFRQloVwzIpvV+q5ivXpq0TEFMAzsRJKSKrRPYDiSJu7EdRui09g=="], "@mediafox/core": ["@mediafox/core@1.0.4", "", { "peerDependencies": { "mediabunny": "^1.23.0", "typescript": ">=5.0.0" } }, "sha512-1j8PKp835RUVzZt1vcymrgZqhaMobfP7SswbTisusvTgIZL8y5n2QFhSCnn7dze+a53VgnWyzkHOYdtVR1Gdew=="], @@ -6218,7 +6217,7 @@ "media-typer": ["media-typer@0.3.0", "", {}, "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="], - "mediabunny": ["mediabunny@1.34.3", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-Jb0x3jyvadGVpo8aZSn53NZduPbPdbx9foQsAGOmKBz7Hai9B38Kf+7eXbxXFcXoXxcTyNaZeDhoA0agoBQldA=="], + "mediabunny": ["mediabunny@1.34.4", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-f1B95A60YoCsZQO/JQYxPDorybEz2Sjasf4RrpwGSMmJW6JVyhI/iJDri9LF6kk5WwUovF8oiTvRNM6xGjWo5w=="], "memfs": ["memfs@3.4.3", "", { "dependencies": { "fs-monkey": "1.0.3" } }, "sha512-eivjfi7Ahr6eQTn44nvTnR60e4a1Fs1Via2kCR5lHo/kyNoiMWaXCNJ/GpSd0ilXas2JSOl9B5FTIhflXu0hlg=="], @@ -10446,8 +10445,6 @@ "template-ai-video/uuid": ["uuid@13.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="], - "template-music-visualization/mediabunny": ["mediabunny@1.34.2", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-Mr9VhiqH2RRwc3vR6rk8ca/58HhstP+c25PjtZmZvmCw21ibWSNqpinvBREfJmY+hpNGnG9dUmbJ4WqLMDWO0g=="], - "template-next-app/@eslint/js": ["@eslint/js@9.38.0", "", {}, "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A=="], "template-next-app/@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@8.46.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "8.46.0", "@typescript-eslint/type-utils": "8.46.0", "@typescript-eslint/utils": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0", "graphemer": "^1.4.0", "ignore": "^7.0.0", "natural-compare": "^1.4.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "@typescript-eslint/parser": "^8.46.0", "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-hA8gxBq4ukonVXPy0OKhiaUh/68D0E88GSmtC1iAEnGaieuDi38LhS7jdCHRLi6ErJBNDGCzvh5EnzdPwUc0DA=="], @@ -10526,8 +10523,6 @@ "template-recorder/lucide-react": ["lucide-react@0.516.0", "", { "peerDependencies": { "react": "19.0.0" } }, "sha512-aybBJzLHcw1CIn3rUcRkztB37dsJATtpffLNX+0/w+ws2p21nYIlOwX/B5fqxq8F/BjqVemnJX8chKwRidvROg=="], - "template-recorder/mediabunny": ["mediabunny@1.34.2", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-Mr9VhiqH2RRwc3vR6rk8ca/58HhstP+c25PjtZmZvmCw21ibWSNqpinvBREfJmY+hpNGnG9dUmbJ4WqLMDWO0g=="], - "template-recorder/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "3.3.11", "picocolors": "1.1.1", "source-map-js": "1.2.1" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], "template-recorder/prettier-plugin-organize-imports": ["prettier-plugin-organize-imports@3.2.3", "", { "peerDependencies": { "prettier": "3.6.0", "typescript": "5.8.2" } }, "sha512-KFvk8C/zGyvUaE3RvxN2MhCLwzV6OBbFSkwZ2OamCrs9ZY4i5L77jQ/w4UmUr+lqX8qbaqVq6bZZkApn+IgJSg=="], @@ -10546,8 +10541,6 @@ "template-still/p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], - "template-three/mediabunny": ["mediabunny@1.34.2", "", { "dependencies": { "@types/dom-mediacapture-transform": "^0.1.11", "@types/dom-webcodecs": "0.1.13" } }, "sha512-Mr9VhiqH2RRwc3vR6rk8ca/58HhstP+c25PjtZmZvmCw21ibWSNqpinvBREfJmY+hpNGnG9dUmbJ4WqLMDWO0g=="], - "template-tts-azure/tsx": ["tsx@4.19.3", "", { "dependencies": { "esbuild": "0.25.0", "get-tsconfig": "4.8.1" }, "optionalDependencies": { "fsevents": "2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ=="], "template-tts-google/@types/express": ["@types/express@4.17.13", "", { "dependencies": { "@types/body-parser": "1.19.1", "@types/express-serve-static-core": "4.17.35", "@types/qs": "6.9.7", "@types/serve-static": "1.13.10" } }, "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA=="], @@ -13432,8 +13425,6 @@ "teeny-request/https-proxy-agent/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], - "template-music-visualization/mediabunny/@types/dom-webcodecs": ["@types/dom-webcodecs@0.1.13", "", {}, "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="], - "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.0", "", { "dependencies": { "@typescript-eslint/types": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0" } }, "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw=="], "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@8.46.0", "", { "dependencies": { "@typescript-eslint/types": "8.46.0", "@typescript-eslint/typescript-estree": "8.46.0", "@typescript-eslint/utils": "8.46.0", "debug": "^4.3.4", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-hy+lvYV1lZpVs2jRaEYvgCblZxUoJiPyCemwbQZ+NGulWkQRy0HRPYAoef/CNSzaLt+MLvMptZsHXHlkEilaeg=="], @@ -13644,8 +13635,6 @@ "template-recorder/lucide-react/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], - "template-recorder/mediabunny/@types/dom-webcodecs": ["@types/dom-webcodecs@0.1.13", "", {}, "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="], - "template-recorder/tailwindcss/postcss": ["postcss@8.5.1", "", { "dependencies": { "nanoid": "3.3.11", "picocolors": "1.1.1", "source-map-js": "1.2.1" } }, "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ=="], "template-recorder/tailwindcss/resolve": ["resolve@1.22.8", "", { "dependencies": { "is-core-module": "2.15.1", "path-parse": "1.0.7", "supports-preserve-symlinks-flag": "1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw=="], @@ -13682,8 +13671,6 @@ "template-still/p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], - "template-three/mediabunny/@types/dom-webcodecs": ["@types/dom-webcodecs@0.1.13", "", {}, "sha512-O5hkiFIcjjszPIYyUSyvScyvrBoV3NOEEZx/pMlsu44TKzWNkLVBBxnxJz42in5n3QIolYOcBYFCPZZ0h8SkwQ=="], - "template-tts-google/@types/express/@types/serve-static": ["@types/serve-static@1.13.10", "", { "dependencies": { "@types/mime": "1.3.2", "@types/node": "20.12.14" } }, "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ=="], "template-vercel/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@8.46.0", "", { "dependencies": { "@typescript-eslint/types": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0" } }, "sha512-lWETPa9XGcBes4jqAMYD9fW0j4n6hrPtTJwWDmtqgFO/4HF4jmdH/Q6wggTw5qIT5TXjKzbt7GsZUBnWoO3dqw=="], diff --git a/package.json b/package.json index c4b50a24d23..0b5bdaeb4a4 100644 --- a/package.json +++ b/package.json @@ -101,9 +101,9 @@ "@types/node": "20.12.14", "@types/web": "0.0.166", "@types/bun": "1.3.3", - "mediabunny": "1.34.3", - "@mediabunny/mp3-encoder": "1.34.3", - "@mediabunny/ac3": "1.34.3", + "mediabunny": "1.34.4", + "@mediabunny/mp3-encoder": "1.34.4", + "@mediabunny/ac3": "1.34.4", "next": "16.1.5", "three": "0.178.0", "sharp": "0.34.5", diff --git a/packages/cli/src/extra-packages.ts b/packages/cli/src/extra-packages.ts index 6d0e839a152..66b29897bd5 100644 --- a/packages/cli/src/extra-packages.ts +++ b/packages/cli/src/extra-packages.ts @@ -1,6 +1,6 @@ export const EXTRA_PACKAGES: Record = { zod: '3.22.3', - mediabunny: '1.34.3', + mediabunny: '1.34.4', }; export const EXTRA_PACKAGES_DOCS: Record = { diff --git a/packages/docs/docs/mediabunny/version.mdx b/packages/docs/docs/mediabunny/version.mdx index 9862f36bb51..3cf1ef15c5f 100644 --- a/packages/docs/docs/mediabunny/version.mdx +++ b/packages/docs/docs/mediabunny/version.mdx @@ -10,7 +10,7 @@ The following package of Remotion is using [Mediabunny](https://mediabunny.dev): - [`@remotion/media`](/docs/media) - [`@remotion/media-utils`](/docs/media-utils) -The current version of Remotion uses version [`1.34.3`](https://github.com/Vanilagy/mediabunny/releases/tag/v1.34.3) of Mediabunny. +The current version of Remotion uses version [`1.34.4`](https://github.com/Vanilagy/mediabunny/releases/tag/v1.34.4) of Mediabunny. If you use Mediabunny as a direct dependency in your project, you can install it with the correct version using: @@ -25,7 +25,7 @@ Note that only from 4.0.355, Mediabunny is not bundled in with Remotion but load | Remotion Version | Mediabunny Version | | ---------------- | ------------------ | -| 4.0.424 | 1.34.3 | +| 4.0.424 | 1.34.4 | | 4.0.423 | 1.34.2 | | 4.0.408 | 1.29.0 | | 4.0.399 | 1.27.3 | diff --git a/packages/media/bundle.ts b/packages/media/bundle.ts index e8e1604e133..1e3c593af14 100644 --- a/packages/media/bundle.ts +++ b/packages/media/bundle.ts @@ -17,6 +17,7 @@ const output = await build({ 'react/jsx-dev-runtime', 'react-dom', 'mediabunny', + '@mediabunny/ac3', ], }); diff --git a/packages/media/src/index.ts b/packages/media/src/index.ts index 6bc908ec34d..71f3c206b20 100644 --- a/packages/media/src/index.ts +++ b/packages/media/src/index.ts @@ -1,3 +1,4 @@ +import {registerAc3Decoder} from '@mediabunny/ac3'; import {Audio} from './audio/audio'; import {Video} from './video/video'; /** @@ -15,3 +16,5 @@ export {AudioProps, FallbackHtml5AudioProps} from './audio/props'; export {MediaErrorAction} from './on-error'; export {FallbackOffthreadVideoProps, VideoProps} from './video/props'; export {Audio, Video}; + +registerAc3Decoder(); diff --git a/packages/studio-shared/src/package-info.ts b/packages/studio-shared/src/package-info.ts index b21576ded0f..407bf1bdc14 100644 --- a/packages/studio-shared/src/package-info.ts +++ b/packages/studio-shared/src/package-info.ts @@ -102,7 +102,7 @@ export const extraPackages: ExtraPackage[] = [ }, { name: 'mediabunny', - version: '1.34.3', + version: '1.34.4', description: 'Multimedia library used by Remotion', docsUrl: 'https://www.remotion.dev/docs/mediabunny/version', }, diff --git a/packages/template-music-visualization/package.json b/packages/template-music-visualization/package.json index 5f234874d9d..ce5c2dedbc0 100644 --- a/packages/template-music-visualization/package.json +++ b/packages/template-music-visualization/package.json @@ -17,7 +17,7 @@ "@remotion/media-utils": "workspace:*", "@remotion/google-fonts": "workspace:*", "@remotion/zod-types": "workspace:*", - "mediabunny": "1.34.2", + "mediabunny": "1.34.4", "react": "19.2.3", "react-dom": "19.2.3", "remotion": "workspace:*", diff --git a/packages/template-recorder/package.json b/packages/template-recorder/package.json index 5dcc2134a26..385524e1902 100644 --- a/packages/template-recorder/package.json +++ b/packages/template-recorder/package.json @@ -39,7 +39,7 @@ "connect": "3.7.0", "eslint": "9.19.0", "lucide-react": "0.516.0", - "mediabunny": "1.34.2", + "mediabunny": "1.34.4", "react": "19.2.3", "react-dom": "19.2.3", "tailwind-merge": "1.14.0", diff --git a/packages/template-three/package.json b/packages/template-three/package.json index 15921ba08ed..ea493d67c97 100644 --- a/packages/template-three/package.json +++ b/packages/template-three/package.json @@ -21,7 +21,7 @@ "remotion": "workspace:*", "three": "0.178.0", "zod": "3.22.3", - "mediabunny": "1.34.2" + "mediabunny": "1.34.4" }, "devDependencies": { "@remotion/eslint-config-flat": "workspace:*", diff --git a/packages/web-renderer/bundle.ts b/packages/web-renderer/bundle.ts index de96a11f743..ed054fb537d 100644 --- a/packages/web-renderer/bundle.ts +++ b/packages/web-renderer/bundle.ts @@ -5,6 +5,6 @@ await buildPackage({ cjs: 'do-nothing', esm: 'build', }, - external: ['remotion', 'react', 'react-dom', 'mediabunny', '@mediabunny/ac3'], + external: ['remotion', 'react', 'react-dom', 'mediabunny'], entrypoints: [{path: 'src/index.ts', target: 'browser'}], }); diff --git a/packages/web-renderer/package.json b/packages/web-renderer/package.json index 00c5f4b2c34..f70f19f2884 100644 --- a/packages/web-renderer/package.json +++ b/packages/web-renderer/package.json @@ -21,8 +21,7 @@ "dependencies": { "@remotion/licensing": "workspace:*", "remotion": "workspace:*", - "mediabunny": "catalog:", - "@mediabunny/ac3": "catalog:" + "mediabunny": "catalog:" }, "devDependencies": { "@react-three/fiber": "catalog:", From ef784d3f4749d9eeb111ecf9e5841adf873490b7 Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 13:08:56 +0100 Subject: [PATCH 06/30] `@remotion/media`: Document AC3 and EAC3 decoding support Co-Authored-By: Claude Opus 4.6 --- packages/docs/docs/mediabunny/formats.mdx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/docs/docs/mediabunny/formats.mdx b/packages/docs/docs/mediabunny/formats.mdx index 5aff063cc1b..a10b66b4c62 100644 --- a/packages/docs/docs/mediabunny/formats.mdx +++ b/packages/docs/docs/mediabunny/formats.mdx @@ -61,6 +61,13 @@ This means that during rendering of Remotion videos server-side, HEVC videos can - `'pcm-f64be'` - 64-bit big-endian float PCM - `'ulaw'` - μ-law PCM - `'alaw'` - A-law PCM +- `'ac3'` - Dolby Digital (AC-3) +- `'eac3'` - Dolby Digital Plus (E-AC-3) + +:::note +AC-3 and E-AC-3 are not natively supported by WebCodecs. +Remotion registers a software decoder from [`@mediabunny/ac3`](https://www.npmjs.com/package/@mediabunny/ac3) to enable decoding of these codecs. +::: ## Compatibility table @@ -92,6 +99,8 @@ Not all codecs can be used with all containers. The following table specifies th | `'pcm-f64be'` | ✓ | ✓ | | | | | | | | | | `'ulaw'` | | ✓ | | | | | ✓ | | | | | `'alaw'` | | ✓ | | | | | ✓ | | | | +| `'ac3'` | ✓ | ✓ | ✓ | | | | | | | ✓ | +| `'eac3'` | ✓ | ✓ | ✓ | | | | | | | ✓ | ## CORS From ff8b3b1b648b1b0a80c822a772626cb0c466b5e9 Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 13:25:09 +0100 Subject: [PATCH 07/30] Upgrade Prettier from 3.6.0 to 3.8.1 Update workspace catalog, all 23 template package.json files, and reformat codebase with new Prettier version. Add prettier-ignore to webcodecs stbl.test.ts where new await-import line breaking conflicts with ts-expect-error. Co-Authored-By: Claude Opus 4.6 --- bun.lock | 50 ++--- package.json | 2 +- packages/cloudrun/src/shared/read-dir.ts | 1 - packages/create-video/src/pkg-managers.ts | 2 +- packages/docusaurus-plugin/src/shiki.ts | 2 +- packages/gif/src/lru/index.ts | 6 +- packages/lambda-client/src/is-in-lambda.ts | 2 +- packages/lambda-go-example/go.mod | 2 + packages/player/src/PlayerUI.tsx | 4 +- .../promo-pages/src/components/experts.tsx | 2 +- .../src/components/experts/experts-data.tsx | 9 +- .../src/components/homepage/FreePricing.tsx | 9 +- .../src/components/homepage/InfoTooltip.tsx | 6 +- .../components/homepage/VideoAppsShowcase.tsx | 42 ++-- packages/skia/src/enable.ts | 5 +- packages/skills/src/Root.tsx | 72 +++---- packages/skills/src/index.ts | 4 +- .../src/components/Menu/is-menu-item.tsx | 6 +- packages/tailwind-v4/src/enable.ts | 4 +- packages/tailwind/src/enable.ts | 4 +- packages/template-audiogram/package.json | 2 +- .../src/Audiogram/AudioVizContainer.tsx | 12 +- .../src/Audiogram/Captions.tsx | 26 +-- .../template-audiogram/src/Audiogram/Main.tsx | 56 +++--- .../src/Audiogram/Oscilloscope.tsx | 8 +- .../src/Audiogram/Spectrum.tsx | 10 +- .../src/Audiogram/WaitForFonts.tsx | 8 +- .../template-audiogram/src/Audiogram/Word.tsx | 21 +- .../template-audiogram/src/Audiogram/font.ts | 6 +- .../Audiogram/get-number-of-lines-for-text.ts | 10 +- .../src/Audiogram/schema.ts | 18 +- .../src/Audiogram/sentence-to-display.ts | 10 +- packages/template-audiogram/src/Root.tsx | 30 +-- .../src/helpers/fetch-captions.ts | 8 +- packages/template-audiogram/src/index.ts | 4 +- packages/template-blank/package.json | 2 +- packages/template-blank/src/Root.tsx | 4 +- packages/template-blank/src/index.ts | 4 +- packages/template-code-hike/package.json | 2 +- .../template-code-hike/src/CodeTransition.tsx | 25 ++- packages/template-code-hike/src/Main.tsx | 24 +-- .../template-code-hike/src/ProgressBar.tsx | 21 +- .../src/ReloadOnCodeChange.tsx | 16 +- packages/template-code-hike/src/Root.tsx | 12 +- .../src/annotations/Callout.tsx | 38 ++-- .../src/annotations/Error.tsx | 32 +-- .../src/annotations/InlineToken.tsx | 6 +- .../calculate-metadata/calculate-metadata.tsx | 30 +-- .../src/calculate-metadata/get-files.ts | 4 +- .../src/calculate-metadata/process-snippet.ts | 24 +-- .../src/calculate-metadata/schema.ts | 10 +- .../src/calculate-metadata/theme.tsx | 52 ++--- packages/template-code-hike/src/font.ts | 8 +- packages/template-code-hike/src/index.ts | 4 +- packages/template-code-hike/src/utils.ts | 6 +- packages/template-helloworld/package.json | 2 +- .../template-helloworld/src/HelloWorld.tsx | 20 +- .../src/HelloWorld/Arc.tsx | 6 +- .../src/HelloWorld/Atom.tsx | 6 +- .../src/HelloWorld/Logo.tsx | 10 +- .../src/HelloWorld/Subtitle.tsx | 12 +- .../src/HelloWorld/Title.tsx | 18 +- .../src/HelloWorld/constants.ts | 4 +- packages/template-helloworld/src/Root.tsx | 18 +- packages/template-helloworld/src/index.ts | 4 +- packages/template-javascript/package.json | 2 +- .../src/HelloWorld/Arc.jsx | 8 +- .../src/HelloWorld/Atom.jsx | 8 +- .../src/HelloWorld/Logo.jsx | 6 +- .../src/HelloWorld/Subtitle.jsx | 11 +- .../src/HelloWorld/Title.jsx | 17 +- .../src/HelloWorld/constants.js | 6 +- .../src/HelloWorld/index.jsx | 16 +- packages/template-javascript/src/Root.jsx | 10 +- packages/template-javascript/src/index.js | 4 +- .../template-music-visualization/package.json | 2 +- .../template-music-visualization/src/Root.tsx | 24 +-- .../src/Visualizer/BassOverlay.tsx | 6 +- .../src/Visualizer/Main.tsx | 36 ++-- .../src/Visualizer/SongInfo.tsx | 30 +-- .../src/Visualizer/Spectrum.tsx | 30 +-- .../src/Visualizer/Waveform.tsx | 6 +- .../src/helpers/WaitForFonts.tsx | 8 +- .../src/helpers/font.ts | 8 +- .../src/helpers/schema.ts | 16 +- .../template-music-visualization/src/index.ts | 4 +- .../template-next-app-tailwind/package.json | 2 +- .../src/app/api/lambda/progress/route.ts | 16 +- .../src/app/api/lambda/render/route.ts | 21 +- .../src/app/layout.tsx | 10 +- .../src/app/page.tsx | 24 +-- .../src/components/AlignEnd.tsx | 2 +- .../src/components/Button.tsx | 12 +- .../src/components/Container.tsx | 2 +- .../src/components/DownloadButton.tsx | 24 +-- .../src/components/Error.tsx | 2 +- .../src/components/Input.tsx | 2 +- .../src/components/ProgressBar.tsx | 2 +- .../src/components/RenderControls.tsx | 40 ++-- .../src/components/Spacing.tsx | 2 +- .../src/components/Spinner.tsx | 8 +- .../src/components/Tips.tsx | 2 +- .../src/helpers/api-response.ts | 12 +- .../src/helpers/use-rendering.ts | 40 ++-- .../src/lambda/api.ts | 20 +- .../src/lib/utils.ts | 4 +- .../src/remotion/MyComp/Main.tsx | 20 +- .../src/remotion/MyComp/NextLogo.tsx | 8 +- .../src/remotion/MyComp/Rings.tsx | 10 +- .../src/remotion/MyComp/TextFade.tsx | 4 +- .../src/remotion/Root.tsx | 8 +- .../src/remotion/index.ts | 6 +- packages/template-next-app/package.json | 2 +- .../src/app/api/lambda/progress/route.ts | 16 +- .../src/app/api/lambda/render/route.ts | 21 +- packages/template-next-app/src/app/layout.tsx | 10 +- packages/template-next-app/src/app/page.tsx | 30 +-- .../src/components/AlignEnd.tsx | 4 +- .../src/components/Button/Button.tsx | 10 +- .../src/components/Container.tsx | 14 +- .../src/components/DownloadButton.tsx | 30 +-- .../src/components/Error.tsx | 12 +- .../src/components/Input.tsx | 16 +- .../src/components/ProgressBar.tsx | 12 +- .../src/components/RenderControls.tsx | 40 ++-- .../src/components/Spacing.tsx | 6 +- .../src/components/Spinner/Spinner.tsx | 10 +- .../src/components/Tips/Tips.tsx | 22 +-- .../src/helpers/api-response.ts | 12 +- .../src/helpers/use-rendering.ts | 40 ++-- packages/template-next-app/src/lambda/api.ts | 20 +- .../src/remotion/MyComp/Main.tsx | 28 +-- .../src/remotion/MyComp/NextLogo.tsx | 10 +- .../src/remotion/MyComp/Rings.tsx | 16 +- .../src/remotion/MyComp/TextFade.tsx | 8 +- .../template-next-app/src/remotion/Root.tsx | 8 +- .../template-next-app/src/remotion/index.ts | 4 +- .../template-next-app/src/types/constants.ts | 6 +- .../template-next-app/src/types/schema.ts | 10 +- packages/template-next-pages/package.json | 2 +- .../src/components/AlignEnd.tsx | 4 +- .../src/components/Button/Button.tsx | 10 +- .../src/components/Container.tsx | 14 +- .../src/components/DownloadButton.tsx | 32 +-- .../src/components/Error.tsx | 12 +- .../src/components/Input.tsx | 16 +- .../src/components/ProgressBar.tsx | 12 +- .../src/components/RenderControls.tsx | 40 ++-- .../src/components/Spacing.tsx | 6 +- .../src/components/Spinner/Spinner.tsx | 10 +- .../src/components/Tips/Tips.tsx | 22 +-- .../src/helpers/api-response.ts | 12 +- .../src/helpers/use-rendering.ts | 40 ++-- .../template-next-pages/src/lambda/api.ts | 22 +-- .../template-next-pages/src/pages/_app.tsx | 4 +- .../src/pages/api/lambda/progress.ts | 20 +- .../src/pages/api/lambda/render.ts | 25 +-- .../template-next-pages/src/pages/index.tsx | 30 +-- .../src/remotion/MyComp/Main.tsx | 28 +-- .../src/remotion/MyComp/NextLogo.tsx | 10 +- .../src/remotion/MyComp/Rings.tsx | 16 +- .../src/remotion/MyComp/TextFade.tsx | 8 +- .../template-next-pages/src/remotion/Root.tsx | 8 +- .../template-next-pages/src/remotion/index.ts | 4 +- packages/template-overlay/package.json | 2 +- packages/template-overlay/src/Overlay.tsx | 22 +-- packages/template-overlay/src/Root.tsx | 4 +- packages/template-overlay/src/index.ts | 4 +- .../package.json | 2 +- .../src/app/api/generate/route.ts | 183 ++++++++++-------- .../src/app/api/lambda/progress/route.ts | 16 +- .../src/app/api/lambda/render/route.ts | 23 +-- .../src/app/code-examples/page.tsx | 50 ++--- .../src/app/generate/page.tsx | 112 ++++++----- .../src/app/layout.tsx | 10 +- .../src/app/page.tsx | 27 ++- .../RenderControls/DownloadButton.tsx | 22 +-- .../AnimationPlayer/RenderControls/Error.tsx | 15 +- .../RenderControls/ProgressBar.tsx | 2 +- .../AnimationPlayer/RenderControls/index.tsx | 40 ++-- .../AnimationPlayer/SettingsModal.tsx | 17 +- .../src/components/AnimationPlayer/index.tsx | 50 ++--- .../components/ChatSidebar/ChatHistory.tsx | 43 ++-- .../src/components/ChatSidebar/ChatInput.tsx | 30 +-- .../components/ChatSidebar/ChatSidebar.tsx | 65 +++---- .../src/components/ChatSidebar/index.ts | 2 +- .../src/components/CodeEditor/CodeEditor.tsx | 52 ++--- .../src/components/CodeEditor/CopyButton.tsx | 8 +- .../components/CodeEditor/EditorHeader.tsx | 10 +- .../CodeEditor/StreamingOverlay.tsx | 6 +- .../src/components/CodeEditor/index.ts | 2 +- .../src/components/ErrorDisplay.tsx | 67 ++++--- .../src/components/Header.tsx | 2 +- .../src/components/LandingPageInput.tsx | 70 ++++--- .../src/components/PageLayout.tsx | 4 +- .../src/components/TabPanel.tsx | 26 +-- .../src/components/ui/alert.tsx | 40 ++-- .../src/components/ui/button.tsx | 55 +++--- .../src/components/ui/dialog.tsx | 56 +++--- .../src/components/ui/select.tsx | 70 +++---- .../src/components/ui/spinner.tsx | 12 +- .../src/components/ui/tooltip.tsx | 22 +-- .../src/examples/code/animated-shapes.ts | 10 +- .../src/examples/code/falling-spheres.ts | 10 +- .../src/examples/code/gold-price-chart.ts | 11 +- .../src/examples/code/histogram.ts | 10 +- .../src/examples/code/index.ts | 22 +-- .../src/examples/code/lottie-animation.ts | 10 +- .../src/examples/code/progress-bar.ts | 10 +- .../src/examples/code/text-rotation.ts | 10 +- .../src/examples/code/typewriter-highlight.ts | 11 +- .../src/examples/code/word-carousel.ts | 10 +- .../src/examples/prompts.ts | 40 ++-- .../src/helpers/api-response.ts | 12 +- .../src/helpers/capture-frame.ts | 10 +- .../src/helpers/sanitize-response.ts | 14 +- .../src/helpers/use-rendering.ts | 44 ++--- .../src/hooks/useAnimationState.ts | 8 +- .../src/hooks/useAutoCorrection.ts | 42 ++-- .../src/hooks/useConversationState.ts | 67 ++++--- .../src/hooks/useGenerationApi.ts | 96 ++++----- .../src/hooks/useImageAttachments.ts | 92 +++++---- .../src/lambda/api.ts | 20 +- .../src/lib/utils.ts | 6 +- .../src/markdown.d.ts | 2 +- .../src/remotion/DynamicComp.tsx | 40 ++-- .../src/remotion/Root.tsx | 6 +- .../src/remotion/compiler.ts | 149 +++++++------- .../src/remotion/index.ts | 4 +- .../src/skills/index.ts | 86 ++++---- .../src/types/conversation.ts | 8 +- .../src/types/generation.ts | 20 +- .../template-prompt-to-video/package.json | 2 +- .../template-prompt-to-video/src/Root.tsx | 12 +- .../src/components/AIVideo.tsx | 42 ++-- .../src/components/Background.tsx | 12 +- .../src/components/Subtitle.tsx | 6 +- .../src/components/Word.tsx | 22 +-- .../template-prompt-to-video/src/index.ts | 4 +- .../template-prompt-to-video/src/lib/types.ts | 24 +-- .../template-prompt-to-video/src/lib/utils.ts | 10 +- packages/template-react-router/package.json | 2 +- packages/template-recorder/package.json | 2 +- packages/template-recorder/src/App.tsx | 56 +++--- .../template-recorder/src/BlinkingCircle.tsx | 4 +- .../template-recorder/src/CropIndicator.tsx | 12 +- packages/template-recorder/src/DeviceItem.tsx | 30 +-- .../src/DevicePermission.tsx | 126 ++++++------ packages/template-recorder/src/Logo.tsx | 2 +- .../template-recorder/src/PermissionError.tsx | 18 +- .../src/PrefixAndResolution.tsx | 18 +- .../template-recorder/src/RecordButton.tsx | 72 +++---- .../template-recorder/src/RecordingView.tsx | 140 +++++++------- .../src/ResolutionLimiter.tsx | 44 ++--- packages/template-recorder/src/Rotate.tsx | 4 +- packages/template-recorder/src/Stream.tsx | 70 +++---- packages/template-recorder/src/Timer.tsx | 4 +- packages/template-recorder/src/ToggleCrop.tsx | 4 +- .../template-recorder/src/ToggleMirror.tsx | 4 +- packages/template-recorder/src/TopBar.tsx | 48 ++--- .../src/WaitingForDevices.tsx | 6 +- .../src/actions/create-folder.ts | 8 +- .../src/actions/fetch-project-folders.ts | 8 +- .../src/components/ClearCurrentVideo.tsx | 16 +- .../src/components/CurrentAudio.tsx | 16 +- .../src/components/CurrentVideo.tsx | 30 +-- .../src/components/Divider.tsx | 4 +- .../src/components/EnsureBrowserSupport.tsx | 22 +-- .../src/components/NewFolderDialog.tsx | 22 +-- .../src/components/ProcessingStatus.tsx | 12 +- .../src/components/RescanDevices.tsx | 6 +- .../src/components/SelectedFolder.tsx | 20 +- .../src/components/Spinner.tsx | 2 +- .../src/components/StreamPicker.tsx | 42 ++-- .../src/components/UseThisTake.tsx | 80 ++++---- .../src/components/VolumeMeter.tsx | 36 ++-- .../src/components/theme-provider.tsx | 20 +- .../src/components/ui/button.tsx | 41 ++-- .../src/components/ui/dialog.tsx | 28 +-- .../src/components/ui/dropdown-menu.tsx | 36 ++-- .../src/components/ui/input.tsx | 8 +- .../src/components/ui/label.tsx | 10 +- .../src/components/ui/select.tsx | 34 ++-- .../src/components/ui/toggle.tsx | 24 +-- .../src/helpers/browser-support.ts | 6 +- .../src/helpers/can-rotate-camera.ts | 6 +- .../src/helpers/cancel-transcribe.ts | 4 +- .../src/helpers/convert-in-browser.ts | 8 +- .../src/helpers/download-video.ts | 10 +- .../helpers/enumerate-devices-or-time-out.ts | 2 +- .../src/helpers/find-good-supported-codec.ts | 30 +-- .../src/helpers/format-device-label.ts | 14 +- .../src/helpers/format-time.ts | 8 +- .../src/helpers/get-devices.ts | 14 +- .../src/helpers/get-folders.ts | 8 +- .../helpers/get-max-resolution-of-device.ts | 2 +- .../src/helpers/get-selected-video-source.ts | 26 +-- .../src/helpers/get-video-stream.ts | 26 +-- .../template-recorder/src/helpers/prefixes.ts | 2 +- .../src/helpers/start-media-recorder.ts | 22 +-- .../src/helpers/store-file.ts | 2 +- .../src/helpers/transcribe-video.ts | 26 +-- .../src/helpers/upload-file.ts | 10 +- .../src/helpers/use-element-size.ts | 10 +- .../src/helpers/use-key-press.ts | 6 +- .../template-recorder/src/helpers/utils.ts | 4 +- packages/template-recorder/src/main.tsx | 12 +- .../src/preferred-device-localstorage.ts | 10 +- .../src/preferred-resolution.ts | 4 +- .../src/state/media-sources.tsx | 32 +-- .../src/state/visible-views.ts | 2 +- packages/template-render-server/package.json | 2 +- packages/template-skia/package.json | 2 +- packages/template-skia/src/AssetManager.tsx | 18 +- packages/template-skia/src/Drawing.tsx | 10 +- packages/template-skia/src/HelloSkia.tsx | 16 +- packages/template-skia/src/Root.tsx | 6 +- packages/template-skia/src/SkiaNeon.tsx | 29 ++- packages/template-skia/src/index.ts | 6 +- packages/template-stargazer/package.json | 2 +- packages/template-stargazer/src/Content.tsx | 66 +++---- packages/template-stargazer/src/Main.tsx | 10 +- packages/template-stargazer/src/Root.tsx | 14 +- packages/template-stargazer/src/cache.ts | 4 +- .../src/fetch/fetch-data.ts | 10 +- .../src/fetch/via-graphql.ts | 18 +- .../template-stargazer/src/fetch/via-rest.ts | 6 +- packages/template-stargazer/src/index.ts | 4 +- .../template-stargazer/src/repo-header.tsx | 38 ++-- .../src/wait-for-no-input.ts | 6 +- packages/template-still/package.json | 2 +- packages/template-still/src/PreviewCard.tsx | 42 ++-- packages/template-still/src/Root.tsx | 11 +- packages/template-still/src/Swirl.tsx | 6 +- packages/template-still/src/index.ts | 4 +- packages/template-still/src/server/cache.ts | 28 +-- packages/template-still/src/server/config.ts | 8 +- packages/template-still/src/server/handler.ts | 6 +- .../template-still/src/server/image-types.ts | 22 +-- packages/template-still/src/server/index.ts | 38 ++-- .../template-still/src/server/make-hash.ts | 4 +- packages/template-still/src/server/s3.ts | 6 +- .../template-still/src/server/send-file.ts | 8 +- packages/template-three/package.json | 2 +- packages/template-three/src/Phone.tsx | 22 +-- packages/template-three/src/Root.tsx | 16 +- packages/template-three/src/RoundedBox.tsx | 6 +- packages/template-three/src/Scene.tsx | 24 +-- .../src/helpers/get-media-metadata.ts | 2 +- packages/template-three/src/helpers/layout.ts | 2 +- .../src/helpers/rounded-rectangle.ts | 2 +- packages/template-three/src/index.ts | 4 +- packages/template-tiktok/package.json | 2 +- .../src/CaptionedVideo/NoCaptionFile.tsx | 12 +- .../src/CaptionedVideo/Page.tsx | 34 ++-- .../src/CaptionedVideo/SubtitlePage.tsx | 8 +- .../src/CaptionedVideo/index.tsx | 28 +-- packages/template-tiktok/src/Root.tsx | 6 +- packages/template-tiktok/src/index.ts | 4 +- packages/template-tiktok/src/load-font.ts | 4 +- packages/template-tts-azure/package.json | 2 +- .../template-tts-azure/src/HelloWorld.tsx | 18 +- .../src/HelloWorld/Title.tsx | 16 +- packages/template-tts-azure/src/Root.tsx | 18 +- packages/template-tts-azure/src/debounce.ts | 6 +- packages/template-tts-azure/src/index.ts | 4 +- packages/template-tts-azure/src/tts.ts | 26 +-- packages/template-tts-azure/src/types.ts | 6 +- packages/template-tts-google/package.json | 2 +- .../template-tts-google/src/HelloWorld.tsx | 18 +- .../src/HelloWorld/Title.tsx | 30 +-- packages/template-tts-google/src/Root.tsx | 32 +-- packages/template-tts-google/src/debounce.ts | 6 +- packages/template-tts-google/src/index.ts | 4 +- .../src/lib/client-utils.ts | 10 +- .../src/lib/firebase/index.ts | 8 +- .../src/lib/firebase/utils.ts | 4 +- .../template-tts-google/src/lib/interfaces.ts | 10 +- packages/template-tts-google/src/render.ts | 16 +- .../src/server/TextToSpeech/constants.ts | 12 +- .../src/server/TextToSpeech/index.ts | 18 +- .../template-tts-google/src/server/server.ts | 18 +- packages/template-tts-google/src/studio.ts | 10 +- packages/template-vercel/package.json | 2 +- .../src/app/api/render/helpers.ts | 14 +- .../src/app/api/render/render.ts | 36 ++-- .../src/app/api/render/route.ts | 36 ++-- .../src/app/api/render/sandbox/add-bundle.ts | 24 +-- .../app/api/render/sandbox/create-sandbox.ts | 40 ++-- .../app/api/render/sandbox/install-browser.ts | 18 +- .../render/sandbox/install-js-dependencies.ts | 6 +- .../sandbox/install-system-dependencies.ts | 40 ++-- .../api/render/sandbox/patch-compositor.ts | 10 +- .../render/sandbox/reuse-or-create-sandbox.ts | 14 +- .../src/app/api/render/sandbox/snapshots.ts | 8 +- packages/template-vercel/src/app/layout.tsx | 10 +- packages/template-vercel/src/app/page.tsx | 22 +-- .../src/components/AlignEnd.tsx | 4 +- .../template-vercel/src/components/Button.tsx | 12 +- .../src/components/Container.tsx | 2 +- .../src/components/DownloadButton.tsx | 22 +-- .../template-vercel/src/components/Error.tsx | 2 +- .../template-vercel/src/components/Input.tsx | 2 +- .../src/components/ProgressBar.tsx | 2 +- .../src/components/RenderControls.tsx | 50 ++--- .../src/components/Spacing.tsx | 2 +- .../src/components/Spinner.tsx | 8 +- .../template-vercel/src/components/Tips.tsx | 2 +- .../src/helpers/api-response.ts | 12 +- .../src/helpers/use-rendering.ts | 54 +++--- packages/template-vercel/src/lib/utils.ts | 4 +- .../src/remotion/MyComp/Main.tsx | 20 +- .../src/remotion/MyComp/NextLogo.tsx | 8 +- .../src/remotion/MyComp/Rings.tsx | 10 +- .../src/remotion/MyComp/TextFade.tsx | 4 +- .../template-vercel/src/remotion/Root.tsx | 8 +- .../template-vercel/src/remotion/index.ts | 6 +- packages/webcodecs/src/test/stbl.test.ts | 29 +-- 418 files changed, 3800 insertions(+), 3693 deletions(-) diff --git a/bun.lock b/bun.lock index fdaea9ed43f..2ad7d1c1623 100644 --- a/bun.lock +++ b/bun.lock @@ -1506,7 +1506,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -1524,7 +1524,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -1550,7 +1550,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -1570,7 +1570,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -1587,7 +1587,7 @@ "devDependencies": { "@remotion/eslint-config-flat": "workspace:*", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", }, }, "packages/template-music-visualization": { @@ -1610,7 +1610,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -1646,7 +1646,7 @@ "dotenv": "17.3.1", "eslint": "9.19.0", "eslint-config-next": "15.1.6", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", "typescript-eslint": "8.46.0", }, @@ -1688,7 +1688,7 @@ "eslint": "9.19.0", "eslint-config-next": "15.1.6", "postcss": "8.4.47", - "prettier": "3.6.0", + "prettier": "3.8.1", "tailwindcss": "4.0.3", "typescript": "5.9.3", "typescript-eslint": "8.46.0", @@ -1725,7 +1725,7 @@ "dotenv": "17.3.1", "eslint": "9.19.0", "eslint-config-next": "15.1.6", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", "typescript-eslint": "8.46.0", }, @@ -1745,7 +1745,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -1808,7 +1808,7 @@ "eslint": "9.19.0", "eslint-config-next": "15.1.6", "postcss": "8.4.47", - "prettier": "3.6.0", + "prettier": "3.8.1", "raw-loader": "^4.0.2", "tailwindcss": "4.0.3", "tw-animate-css": "1.4.0", @@ -1843,7 +1843,7 @@ "dotenv": "17.3.1", "eslint": "9.19.0", "ora": "^9.0.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "prompts": "^2.4.2", "tsx": "^4.20.6", "typescript": "5.9.3", @@ -1887,7 +1887,7 @@ "@types/react-dom": "19.2.3", "dotenv": "17.3.1", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "tsx": "4.19.3", "typescript": "5.9.3", }, @@ -1944,7 +1944,7 @@ "@vitejs/plugin-react-swc": "3.0.0", "autoprefixer": "10.4.16", "postcss": "8.4.31", - "prettier": "3.6.0", + "prettier": "3.8.1", "prettier-plugin-organize-imports": "3.2.3", "tailwindcss": "3.3.5", "typescript": "5.9.3", @@ -1972,7 +1972,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "tsx": "4.19.3", "typescript": "5.9.3", }, @@ -1995,7 +1995,7 @@ "@types/dom-webcodecs": "0.1.11", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -2015,7 +2015,7 @@ "@remotion/eslint-config-flat": "workspace:*", "@types/react": "19.2.7", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -2046,7 +2046,7 @@ "@remotion/eslint-config-flat": "workspace:*", "bun": "1.3.3", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -2072,7 +2072,7 @@ "@types/three": "0.170.0", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -2097,7 +2097,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", }, }, @@ -2122,7 +2122,7 @@ "@types/node": "20.12.14", "@types/react": "19.2.7", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "tsx": "4.19.3", "typescript": "5.9.3", "zod": "3.22.3", @@ -2156,7 +2156,7 @@ "@types/node": "20.12.14", "@types/react": "19.2.7", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "tsx": "4.19.3", "typescript": "5.9.3", }, @@ -2201,7 +2201,7 @@ "eslint": "9.19.0", "eslint-config-next": "15.1.6", "postcss": "8.4.47", - "prettier": "3.6.0", + "prettier": "3.8.1", "tailwindcss": "4.0.3", "turbo": "2.8.6", "typescript": "5.9.3", @@ -2383,7 +2383,7 @@ "next": "16.1.5", "openai": "4.67.1", "playwright": "1.55.1", - "prettier": "3.6.0", + "prettier": "3.8.1", "react": "19.2.3", "react-dom": "19.2.3", "sharp": "0.34.5", @@ -6762,7 +6762,7 @@ "prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="], - "prettier": ["prettier@3.6.0", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw=="], + "prettier": ["prettier@3.8.1", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg=="], "prettier-plugin-organize-imports": ["prettier-plugin-organize-imports@3.2.4", "", { "peerDependencies": { "prettier": "3.6.0", "typescript": "5.8.2" } }, "sha512-6m8WBhIp0dfwu0SkgfOxJqh+HpdyfqSSLfKKRZSFbDuEQXDDndb8fTpRWkUrX/uBenkex3MgnVk0J3b3Y5byog=="], diff --git a/package.json b/package.json index c4b50a24d23..cbdbc17de20 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "react": "19.2.3", "react-dom": "19.2.3", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "zod": "3.22.3", "@types/react": "19.2.7", "@types/react-dom": "19.2.3", diff --git a/packages/cloudrun/src/shared/read-dir.ts b/packages/cloudrun/src/shared/read-dir.ts index 45e6bd4af82..35100a96aad 100644 --- a/packages/cloudrun/src/shared/read-dir.ts +++ b/packages/cloudrun/src/shared/read-dir.ts @@ -28,7 +28,6 @@ export async function readDirectory({ continue; } - if (fs.lstatSync(filePath).isSymbolicLink()) { const realPath = fs.realpathSync(filePath); diff --git a/packages/create-video/src/pkg-managers.ts b/packages/create-video/src/pkg-managers.ts index 7b5fc2b5108..a74045692eb 100644 --- a/packages/create-video/src/pkg-managers.ts +++ b/packages/create-video/src/pkg-managers.ts @@ -19,7 +19,7 @@ const shouldUseBun = (): boolean => { const shouldUseYarn = (): boolean => { return Boolean( process.env.npm_execpath?.includes('yarn.js') || - process.env.npm_config_user_agent?.includes('yarn'), + process.env.npm_config_user_agent?.includes('yarn'), ); }; diff --git a/packages/docusaurus-plugin/src/shiki.ts b/packages/docusaurus-plugin/src/shiki.ts index cc74667ff2b..35cf5652a6d 100644 --- a/packages/docusaurus-plugin/src/shiki.ts +++ b/packages/docusaurus-plugin/src/shiki.ts @@ -5,8 +5,8 @@ import type {Highlighter} from 'shiki'; import {getHighlighter} from 'shiki'; import type {UserConfigSettings} from 'shiki-twoslash'; import {renderCodeToHTML} from 'shiki-twoslash'; -import {visit} from 'unist-util-visit'; import type {BuildVisitor} from 'unist-util-visit'; +import {visit} from 'unist-util-visit'; import {cachedTwoslashCall} from './caching'; import {setupNodeForTwoslashException} from './exceptionMessageDOM'; diff --git a/packages/gif/src/lru/index.ts b/packages/gif/src/lru/index.ts index b9e684d27a2..72cb6a8c9a2 100644 --- a/packages/gif/src/lru/index.ts +++ b/packages/gif/src/lru/index.ts @@ -29,9 +29,9 @@ type MapValue = { expiry?: number; }; -export class QuickLRU - implements Iterable<[KeyType, ValueType]> -{ +export class QuickLRU implements Iterable< + [KeyType, ValueType] +> { /** The maximum number of milliseconds an item should remain in the cache. diff --git a/packages/lambda-client/src/is-in-lambda.ts b/packages/lambda-client/src/is-in-lambda.ts index c2901d5467b..c0889148316 100644 --- a/packages/lambda-client/src/is-in-lambda.ts +++ b/packages/lambda-client/src/is-in-lambda.ts @@ -1,5 +1,5 @@ export const isInsideLambda = () => Boolean( typeof process !== 'undefined' && - process?.env?.__RESERVED_IS_INSIDE_REMOTION_LAMBDA, + process?.env?.__RESERVED_IS_INSIDE_REMOTION_LAMBDA, ); diff --git a/packages/lambda-go-example/go.mod b/packages/lambda-go-example/go.mod index d361c0f6d19..b5e343e1d0e 100644 --- a/packages/lambda-go-example/go.mod +++ b/packages/lambda-go-example/go.mod @@ -1,5 +1,7 @@ module main.go +go 1.24.3 + require ( github.com/go-playground/validator/v10 v10.13.0 github.com/joho/godotenv v1.5.1 diff --git a/packages/player/src/PlayerUI.tsx b/packages/player/src/PlayerUI.tsx index c21e18d52ab..04a967d93fc 100644 --- a/packages/player/src/PlayerUI.tsx +++ b/packages/player/src/PlayerUI.tsx @@ -162,8 +162,8 @@ const PlayerUI: React.ForwardRefRenderFunction< return Boolean( document.fullscreenEnabled || - // @ts-expect-error Types not defined - document.webkitFullscreenEnabled, + // @ts-expect-error Types not defined + document.webkitFullscreenEnabled, ); }, []); diff --git a/packages/promo-pages/src/components/experts.tsx b/packages/promo-pages/src/components/experts.tsx index bb40a05f8c5..f9c9d805b52 100644 --- a/packages/promo-pages/src/components/experts.tsx +++ b/packages/promo-pages/src/components/experts.tsx @@ -1,3 +1,3 @@ -export {ExpertsPageContent} from './experts/ExpertsPage'; export {experts} from './experts/experts-data'; export type {Expert} from './experts/experts-data'; +export {ExpertsPageContent} from './experts/ExpertsPage'; diff --git a/packages/promo-pages/src/components/experts/experts-data.tsx b/packages/promo-pages/src/components/experts/experts-data.tsx index 28f463d5637..f14fad2108f 100644 --- a/packages/promo-pages/src/components/experts/experts-data.tsx +++ b/packages/promo-pages/src/components/experts/experts-data.tsx @@ -585,11 +585,10 @@ export const experts: Expert[] = [ Pablituuu Studio , a premium AI-powered video editor. -
- I specialize in building complex Remotion applications integrated with AI - services like Gemini (for video analysis and highlights) and Deepgram - (for automated captions). I also focus on high-performance canvas - interactions using Fabric.js and cost-effective AI workflows. +
I specialize in building complex Remotion applications integrated + with AI services like Gemini (for video analysis and highlights) and + Deepgram (for automated captions). I also focus on high-performance + canvas interactions using Fabric.js and cost-effective AI workflows. ), }, diff --git a/packages/promo-pages/src/components/homepage/FreePricing.tsx b/packages/promo-pages/src/components/homepage/FreePricing.tsx index 23f6d9df65a..5331922d19d 100644 --- a/packages/promo-pages/src/components/homepage/FreePricing.tsx +++ b/packages/promo-pages/src/components/homepage/FreePricing.tsx @@ -383,8 +383,7 @@ export const CompanyPricing: React.FC = () => {
A $100/mo Minimum Spend applies.

- Developers working on automation projects do not require a - Seat. + Developers working on automation projects do not require a Seat.
{ > At this spend, you are eligible for the Enterprise License.
You can select it when setting up your license, or{' '} - + contact us . diff --git a/packages/promo-pages/src/components/homepage/InfoTooltip.tsx b/packages/promo-pages/src/components/homepage/InfoTooltip.tsx index 38a79ed96d2..6cc382504a9 100644 --- a/packages/promo-pages/src/components/homepage/InfoTooltip.tsx +++ b/packages/promo-pages/src/components/homepage/InfoTooltip.tsx @@ -17,9 +17,9 @@ export const InfoTooltip: React.FC = ({children}) => { ⓘ {isVisible && ( - - {children} - + + {children} + )} diff --git a/packages/promo-pages/src/components/homepage/VideoAppsShowcase.tsx b/packages/promo-pages/src/components/homepage/VideoAppsShowcase.tsx index 12cfed656ec..790d404699c 100644 --- a/packages/promo-pages/src/components/homepage/VideoAppsShowcase.tsx +++ b/packages/promo-pages/src/components/homepage/VideoAppsShowcase.tsx @@ -152,27 +152,27 @@ const VideoAppsShowcase: React.FC = () => { onClick={handlePlayPause} > {videoLoaded ? ( - setIsPlaying(true)} - /> - ) : ( - {videoApps[activeTab].title} - )} + setIsPlaying(true)} + /> + ) : ( + {videoApps[activeTab].title} + )} {/* Play/Pause Button - bottom left corner */} ; } - if (state.status !== "done") { - throw new Error("Download button should not be rendered when not done"); + if (state.status !== 'done') { + throw new Error('Download button should not be rendered when not done'); } return ( diff --git a/packages/template-next-app-tailwind/src/components/Error.tsx b/packages/template-next-app-tailwind/src/components/Error.tsx index 28020e53c2a..2df268555ad 100644 --- a/packages/template-next-app-tailwind/src/components/Error.tsx +++ b/packages/template-next-app-tailwind/src/components/Error.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; export const ErrorComp: React.FC<{ message: string; diff --git a/packages/template-next-app-tailwind/src/components/Input.tsx b/packages/template-next-app-tailwind/src/components/Input.tsx index d6dcc0434d6..1a6e3699226 100644 --- a/packages/template-next-app-tailwind/src/components/Input.tsx +++ b/packages/template-next-app-tailwind/src/components/Input.tsx @@ -1,4 +1,4 @@ -import React, { useCallback } from "react"; +import React, { useCallback } from 'react'; export const Input: React.FC<{ text: string; diff --git a/packages/template-next-app-tailwind/src/components/ProgressBar.tsx b/packages/template-next-app-tailwind/src/components/ProgressBar.tsx index a4c5886df74..e0dd16b7214 100644 --- a/packages/template-next-app-tailwind/src/components/ProgressBar.tsx +++ b/packages/template-next-app-tailwind/src/components/ProgressBar.tsx @@ -1,4 +1,4 @@ -import React, { useMemo } from "react"; +import React, { useMemo } from 'react'; export const ProgressBar: React.FC<{ progress: number; diff --git a/packages/template-next-app-tailwind/src/components/RenderControls.tsx b/packages/template-next-app-tailwind/src/components/RenderControls.tsx index 37113100954..59aca180dfd 100644 --- a/packages/template-next-app-tailwind/src/components/RenderControls.tsx +++ b/packages/template-next-app-tailwind/src/components/RenderControls.tsx @@ -1,14 +1,14 @@ -import { z } from "zod"; -import { AlignEnd } from "./AlignEnd"; -import { Button } from "./Button"; -import { InputContainer } from "./Container"; -import { DownloadButton } from "./DownloadButton"; -import { ErrorComp } from "./Error"; -import { Input } from "./Input"; -import { ProgressBar } from "./ProgressBar"; -import { Spacing } from "./Spacing"; -import { COMP_NAME, CompositionProps } from "../../types/constants"; -import { useRendering } from "../helpers/use-rendering"; +import { z } from 'zod'; +import { COMP_NAME, CompositionProps } from '../../types/constants'; +import { useRendering } from '../helpers/use-rendering'; +import { AlignEnd } from './AlignEnd'; +import { Button } from './Button'; +import { InputContainer } from './Container'; +import { DownloadButton } from './DownloadButton'; +import { ErrorComp } from './Error'; +import { Input } from './Input'; +import { ProgressBar } from './ProgressBar'; +import { Spacing } from './Spacing'; export const RenderControls: React.FC<{ text: string; @@ -19,34 +19,34 @@ export const RenderControls: React.FC<{ return ( - {state.status === "init" || - state.status === "invoking" || - state.status === "error" ? ( + {state.status === 'init' || + state.status === 'invoking' || + state.status === 'error' ? ( <> - {state.status === "error" ? ( + {state.status === 'error' ? ( ) : null} ) : null} - {state.status === "rendering" || state.status === "done" ? ( + {state.status === 'rendering' || state.status === 'done' ? ( <> diff --git a/packages/template-next-app-tailwind/src/components/Spacing.tsx b/packages/template-next-app-tailwind/src/components/Spacing.tsx index c901cfdadb6..742905d320b 100644 --- a/packages/template-next-app-tailwind/src/components/Spacing.tsx +++ b/packages/template-next-app-tailwind/src/components/Spacing.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; export const Spacing: React.FC = () => { return
; diff --git a/packages/template-next-app-tailwind/src/components/Spinner.tsx b/packages/template-next-app-tailwind/src/components/Spinner.tsx index 405f2260c1a..e1cae300fab 100644 --- a/packages/template-next-app-tailwind/src/components/Spinner.tsx +++ b/packages/template-next-app-tailwind/src/components/Spinner.tsx @@ -1,6 +1,6 @@ -import React, { useMemo } from "react"; -import { makeRect } from "@remotion/shapes"; -import { translatePath } from "@remotion/paths"; +import { translatePath } from '@remotion/paths'; +import { makeRect } from '@remotion/shapes'; +import React, { useMemo } from 'react'; const viewBox = 100; const lines = 12; @@ -32,7 +32,7 @@ export const Spinner: React.FC<{ className="animate-spinner" style={{ rotate: `${(index * Math.PI * 2) / lines}rad`, - transformOrigin: "center center", + transformOrigin: 'center center', animationDelay: `${index * 0.1 - lines * 0.1}s`, }} key={index} diff --git a/packages/template-next-app-tailwind/src/components/Tips.tsx b/packages/template-next-app-tailwind/src/components/Tips.tsx index 4e0d16cf4eb..2ada6b91071 100644 --- a/packages/template-next-app-tailwind/src/components/Tips.tsx +++ b/packages/template-next-app-tailwind/src/components/Tips.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; const Tip: React.FC<{ title: React.ReactNode; diff --git a/packages/template-next-app-tailwind/src/helpers/api-response.ts b/packages/template-next-app-tailwind/src/helpers/api-response.ts index d4da4ce7862..574a3134aec 100644 --- a/packages/template-next-app-tailwind/src/helpers/api-response.ts +++ b/packages/template-next-app-tailwind/src/helpers/api-response.ts @@ -1,13 +1,13 @@ -import { NextResponse } from "next/server"; -import { z, ZodType } from "zod"; +import { NextResponse } from 'next/server'; +import { z, ZodType } from 'zod'; export type ApiResponse = | { - type: "error"; + type: 'error'; message: string; } | { - type: "success"; + type: 'success'; data: Res; }; @@ -22,12 +22,12 @@ export const executeApi = const parsed = schema.parse(payload); const data = await handler(req, parsed); return NextResponse.json({ - type: "success", + type: 'success', data: data, }); } catch (err) { return NextResponse.json( - { type: "error", message: (err as Error).message }, + { type: 'error', message: (err as Error).message }, { status: 500, }, diff --git a/packages/template-next-app-tailwind/src/helpers/use-rendering.ts b/packages/template-next-app-tailwind/src/helpers/use-rendering.ts index ff7c29efdb0..c871bfc6f2a 100644 --- a/packages/template-next-app-tailwind/src/helpers/use-rendering.ts +++ b/packages/template-next-app-tailwind/src/helpers/use-rendering.ts @@ -1,30 +1,30 @@ -import { z } from "zod"; -import { useCallback, useMemo, useState } from "react"; -import { getProgress, renderVideo } from "../lambda/api"; -import { CompositionProps } from "../../types/constants"; +import { useCallback, useMemo, useState } from 'react'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; +import { getProgress, renderVideo } from '../lambda/api'; export type State = | { - status: "init"; + status: 'init'; } | { - status: "invoking"; + status: 'invoking'; } | { renderId: string; bucketName: string; progress: number; - status: "rendering"; + status: 'rendering'; } | { renderId: string | null; - status: "error"; + status: 'error'; error: Error; } | { url: string; size: number; - status: "done"; + status: 'done'; }; const wait = async (milliSeconds: number) => { @@ -40,17 +40,17 @@ export const useRendering = ( inputProps: z.infer, ) => { const [state, setState] = useState({ - status: "init", + status: 'init', }); const renderMedia = useCallback(async () => { setState({ - status: "invoking", + status: 'invoking', }); try { const { renderId, bucketName } = await renderVideo({ id, inputProps }); setState({ - status: "rendering", + status: 'rendering', progress: 0, renderId: renderId, bucketName: bucketName, @@ -64,27 +64,27 @@ export const useRendering = ( bucketName: bucketName, }); switch (result.type) { - case "error": { + case 'error': { setState({ - status: "error", + status: 'error', renderId: renderId, error: new Error(result.message), }); pending = false; break; } - case "done": { + case 'done': { setState({ size: result.size, url: result.url, - status: "done", + status: 'done', }); pending = false; break; } - case "progress": { + case 'progress': { setState({ - status: "rendering", + status: 'rendering', bucketName: bucketName, progress: result.progress, renderId: renderId, @@ -95,7 +95,7 @@ export const useRendering = ( } } catch (err) { setState({ - status: "error", + status: 'error', error: err as Error, renderId: null, }); @@ -103,7 +103,7 @@ export const useRendering = ( }, [id, inputProps]); const undo = useCallback(() => { - setState({ status: "init" }); + setState({ status: 'init' }); }, []); return useMemo(() => { diff --git a/packages/template-next-app-tailwind/src/lambda/api.ts b/packages/template-next-app-tailwind/src/lambda/api.ts index f1182d95777..44de9effdbb 100644 --- a/packages/template-next-app-tailwind/src/lambda/api.ts +++ b/packages/template-next-app-tailwind/src/lambda/api.ts @@ -1,26 +1,26 @@ -import { z } from "zod"; -import type { RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; +import type { RenderMediaOnLambdaOutput } from '@remotion/lambda/client'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; import { ProgressRequest, ProgressResponse, RenderRequest, -} from "../../types/schema"; -import { CompositionProps } from "../../types/constants"; -import { ApiResponse } from "../helpers/api-response"; +} from '../../types/schema'; +import { ApiResponse } from '../helpers/api-response'; const makeRequest = async ( endpoint: string, body: unknown, ): Promise => { const result = await fetch(endpoint, { - method: "post", + method: 'post', body: JSON.stringify(body), headers: { - "content-type": "application/json", + 'content-type': 'application/json', }, }); const json = (await result.json()) as ApiResponse; - if (json.type === "error") { + if (json.type === 'error') { throw new Error(json.message); } @@ -39,7 +39,7 @@ export const renderVideo = async ({ inputProps, }; - return makeRequest("/api/lambda/render", body); + return makeRequest('/api/lambda/render', body); }; export const getProgress = async ({ @@ -54,5 +54,5 @@ export const getProgress = async ({ bucketName, }; - return makeRequest("/api/lambda/progress", body); + return makeRequest('/api/lambda/progress', body); }; diff --git a/packages/template-next-app-tailwind/src/lib/utils.ts b/packages/template-next-app-tailwind/src/lib/utils.ts index a5ef193506d..2819a830d24 100644 --- a/packages/template-next-app-tailwind/src/lib/utils.ts +++ b/packages/template-next-app-tailwind/src/lib/utils.ts @@ -1,5 +1,5 @@ -import { clsx, type ClassValue } from "clsx"; -import { twMerge } from "tailwind-merge"; +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); diff --git a/packages/template-next-app-tailwind/src/remotion/MyComp/Main.tsx b/packages/template-next-app-tailwind/src/remotion/MyComp/Main.tsx index cf23037a594..10a75830723 100644 --- a/packages/template-next-app-tailwind/src/remotion/MyComp/Main.tsx +++ b/packages/template-next-app-tailwind/src/remotion/MyComp/Main.tsx @@ -1,20 +1,20 @@ -import { z } from "zod"; +import { fontFamily, loadFont } from '@remotion/google-fonts/Inter'; import { AbsoluteFill, Sequence, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; -import { CompositionProps } from "../../../types/constants"; -import { NextLogo } from "./NextLogo"; -import { loadFont, fontFamily } from "@remotion/google-fonts/Inter"; -import { Rings } from "./Rings"; -import { TextFade } from "./TextFade"; +} from 'remotion'; +import { z } from 'zod'; +import { CompositionProps } from '../../../types/constants'; +import { NextLogo } from './NextLogo'; +import { Rings } from './Rings'; +import { TextFade } from './TextFade'; -loadFont("normal", { - subsets: ["latin"], - weights: ["400", "700"], +loadFont('normal', { + subsets: ['latin'], + weights: ['400', '700'], }); export const Main = ({ title }: z.infer) => { const frame = useCurrentFrame(); diff --git a/packages/template-next-app-tailwind/src/remotion/MyComp/NextLogo.tsx b/packages/template-next-app-tailwind/src/remotion/MyComp/NextLogo.tsx index b7f87f6bf29..f5aacd6d5e5 100644 --- a/packages/template-next-app-tailwind/src/remotion/MyComp/NextLogo.tsx +++ b/packages/template-next-app-tailwind/src/remotion/MyComp/NextLogo.tsx @@ -1,9 +1,9 @@ -import { evolvePath } from "@remotion/paths"; -import React, { useMemo } from "react"; -import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"; +import { evolvePath } from '@remotion/paths'; +import React, { useMemo } from 'react'; +import { interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'; const nStroke = - "M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z"; + 'M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z'; export const NextLogo: React.FC<{ outProgress: number; diff --git a/packages/template-next-app-tailwind/src/remotion/MyComp/Rings.tsx b/packages/template-next-app-tailwind/src/remotion/MyComp/Rings.tsx index 8e27bae8569..d4aa3ce0122 100644 --- a/packages/template-next-app-tailwind/src/remotion/MyComp/Rings.tsx +++ b/packages/template-next-app-tailwind/src/remotion/MyComp/Rings.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { AbsoluteFill, interpolateColors, useVideoConfig } from "remotion"; +import React from 'react'; +import { AbsoluteFill, interpolateColors, useVideoConfig } from 'remotion'; const RadialGradient: React.FC<{ radius: number; @@ -11,8 +11,8 @@ const RadialGradient: React.FC<{ return (
); }) diff --git a/packages/template-next-app-tailwind/src/remotion/MyComp/TextFade.tsx b/packages/template-next-app-tailwind/src/remotion/MyComp/TextFade.tsx index 1b71930a0b9..09ddcd20be8 100644 --- a/packages/template-next-app-tailwind/src/remotion/MyComp/TextFade.tsx +++ b/packages/template-next-app-tailwind/src/remotion/MyComp/TextFade.tsx @@ -1,11 +1,11 @@ -import React, { useMemo } from "react"; +import React, { useMemo } from 'react'; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; +} from 'remotion'; export const TextFade: React.FC<{ children: React.ReactNode; diff --git a/packages/template-next-app-tailwind/src/remotion/Root.tsx b/packages/template-next-app-tailwind/src/remotion/Root.tsx index 83276274db8..284b680e91d 100644 --- a/packages/template-next-app-tailwind/src/remotion/Root.tsx +++ b/packages/template-next-app-tailwind/src/remotion/Root.tsx @@ -1,5 +1,4 @@ -import { Composition } from "remotion"; -import { Main } from "./MyComp/Main"; +import { Composition } from 'remotion'; import { COMP_NAME, defaultMyCompProps, @@ -7,8 +6,9 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from "../../types/constants"; -import { NextLogo } from "./MyComp/NextLogo"; +} from '../../types/constants'; +import { Main } from './MyComp/Main'; +import { NextLogo } from './MyComp/NextLogo'; export const RemotionRoot: React.FC = () => { return ( diff --git a/packages/template-next-app-tailwind/src/remotion/index.ts b/packages/template-next-app-tailwind/src/remotion/index.ts index 23d7a0fb208..092fe6e97d3 100644 --- a/packages/template-next-app-tailwind/src/remotion/index.ts +++ b/packages/template-next-app-tailwind/src/remotion/index.ts @@ -1,5 +1,5 @@ -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; -import "../../styles/global.css"; +import { registerRoot } from 'remotion'; +import '../../styles/global.css'; +import { RemotionRoot } from './Root'; registerRoot(RemotionRoot); diff --git a/packages/template-next-app/package.json b/packages/template-next-app/package.json index 5cea1b45a0d..da3af7ab855 100644 --- a/packages/template-next-app/package.json +++ b/packages/template-next-app/package.json @@ -41,7 +41,7 @@ "eslint-config-next": "15.1.6", "typescript": "5.9.3", "typescript-eslint": "8.46.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "@eslint/eslintrc": "3.1.0" } } diff --git a/packages/template-next-app/src/app/api/lambda/progress/route.ts b/packages/template-next-app/src/app/api/lambda/progress/route.ts index 1a7e3bf69fb..67699b80cba 100644 --- a/packages/template-next-app/src/app/api/lambda/progress/route.ts +++ b/packages/template-next-app/src/app/api/lambda/progress/route.ts @@ -1,11 +1,11 @@ import { - speculateFunctionName, AwsRegion, getRenderProgress, -} from "@remotion/lambda/client"; -import { DISK, RAM, REGION, TIMEOUT } from "../../../../../config.mjs"; -import { executeApi } from "../../../../helpers/api-response"; -import { ProgressRequest, ProgressResponse } from "../../../../types/schema"; + speculateFunctionName, +} from '@remotion/lambda/client'; +import { DISK, RAM, REGION, TIMEOUT } from '../../../../../config.mjs'; +import { executeApi } from '../../../../helpers/api-response'; +import { ProgressRequest, ProgressResponse } from '../../../../types/schema'; export const POST = executeApi( ProgressRequest, @@ -23,21 +23,21 @@ export const POST = executeApi( if (renderProgress.fatalErrorEncountered) { return { - type: "error", + type: 'error', message: renderProgress.errors[0].message, }; } if (renderProgress.done) { return { - type: "done", + type: 'done', url: renderProgress.outputFile as string, size: renderProgress.outputSizeInBytes as number, }; } return { - type: "progress", + type: 'progress', progress: Math.max(0.03, renderProgress.overallProgress), }; }, diff --git a/packages/template-next-app/src/app/api/lambda/render/route.ts b/packages/template-next-app/src/app/api/lambda/render/route.ts index 11ef8eef693..13a322d1423 100644 --- a/packages/template-next-app/src/app/api/lambda/render/route.ts +++ b/packages/template-next-app/src/app/api/lambda/render/route.ts @@ -1,17 +1,18 @@ -import { AwsRegion, RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; import { + AwsRegion, renderMediaOnLambda, + RenderMediaOnLambdaOutput, speculateFunctionName, -} from "@remotion/lambda/client"; -import { executeApi } from "../../../../helpers/api-response"; +} from '@remotion/lambda/client'; import { DISK, RAM, REGION, SITE_NAME, TIMEOUT, -} from "../../../../../config.mjs"; -import { RenderRequest } from "../../../../types/schema"; +} from '../../../../../config.mjs'; +import { executeApi } from '../../../../helpers/api-response'; +import { RenderRequest } from '../../../../types/schema'; export const POST = executeApi( RenderRequest, @@ -21,7 +22,7 @@ export const POST = executeApi( !process.env.REMOTION_AWS_ACCESS_KEY_ID ) { throw new TypeError( - "Set up Remotion Lambda to render videos. See the README.md for how to do so.", + 'Set up Remotion Lambda to render videos. See the README.md for how to do so.', ); } if ( @@ -29,12 +30,12 @@ export const POST = executeApi( !process.env.REMOTION_AWS_SECRET_ACCESS_KEY ) { throw new TypeError( - "The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.", + 'The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.', ); } const result = await renderMediaOnLambda({ - codec: "h264", + codec: 'h264', functionName: speculateFunctionName({ diskSizeInMb: DISK, memorySizeInMb: RAM, @@ -46,8 +47,8 @@ export const POST = executeApi( inputProps: body.inputProps, framesPerLambda: 10, downloadBehavior: { - type: "download", - fileName: "video.mp4", + type: 'download', + fileName: 'video.mp4', }, }); diff --git a/packages/template-next-app/src/app/layout.tsx b/packages/template-next-app/src/app/layout.tsx index ff7ba433853..93a4fc8efae 100644 --- a/packages/template-next-app/src/app/layout.tsx +++ b/packages/template-next-app/src/app/layout.tsx @@ -1,13 +1,13 @@ -import "../../styles/global.css"; -import { Metadata, Viewport } from "next"; +import { Metadata, Viewport } from 'next'; +import '../../styles/global.css'; export const metadata: Metadata = { - title: "Remotion and Next.js", - description: "Remotion and Next.js", + title: 'Remotion and Next.js', + description: 'Remotion and Next.js', }; export const viewport: Viewport = { - width: "device-width", + width: 'device-width', initialScale: 1, maximumScale: 1, }; diff --git a/packages/template-next-app/src/app/page.tsx b/packages/template-next-app/src/app/page.tsx index 6a2a9c04fc9..ca2c18b96de 100644 --- a/packages/template-next-app/src/app/page.tsx +++ b/packages/template-next-app/src/app/page.tsx @@ -1,9 +1,13 @@ -"use client"; +'use client'; -import { Player } from "@remotion/player"; -import type { NextPage } from "next"; -import React, { useMemo, useState } from "react"; -import { Main } from "../remotion/MyComp/Main"; +import { Player } from '@remotion/player'; +import type { NextPage } from 'next'; +import React, { useMemo, useState } from 'react'; +import { z } from 'zod'; +import { RenderControls } from '../components/RenderControls'; +import { Spacing } from '../components/Spacing'; +import { Tips } from '../components/Tips/Tips'; +import { Main } from '../remotion/MyComp/Main'; import { CompositionProps, defaultMyCompProps, @@ -11,30 +15,26 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from "../types/constants"; -import { z } from "zod"; -import { RenderControls } from "../components/RenderControls"; -import { Tips } from "../components/Tips/Tips"; -import { Spacing } from "../components/Spacing"; +} from '../types/constants'; const container: React.CSSProperties = { maxWidth: 768, - margin: "auto", + margin: 'auto', marginBottom: 20, paddingLeft: 16, paddingRight: 16, }; const outer: React.CSSProperties = { - borderRadius: "var(--geist-border-radius)", - overflow: "hidden", - boxShadow: "0 0 200px rgba(0, 0, 0, 0.15)", + borderRadius: 'var(--geist-border-radius)', + overflow: 'hidden', + boxShadow: '0 0 200px rgba(0, 0, 0, 0.15)', marginBottom: 40, marginTop: 60, }; const player: React.CSSProperties = { - width: "100%", + width: '100%', }; const Home: NextPage = () => { diff --git a/packages/template-next-app/src/components/AlignEnd.tsx b/packages/template-next-app/src/components/AlignEnd.tsx index f08aa29ad5f..f7e736314bd 100644 --- a/packages/template-next-app/src/components/AlignEnd.tsx +++ b/packages/template-next-app/src/components/AlignEnd.tsx @@ -1,7 +1,7 @@ -import React from "react"; +import React from 'react'; const container: React.CSSProperties = { - alignSelf: "flex-end", + alignSelf: 'flex-end', }; export const AlignEnd: React.FC<{ diff --git a/packages/template-next-app/src/components/Button/Button.tsx b/packages/template-next-app/src/components/Button/Button.tsx index b697c903144..8041ae33b2e 100644 --- a/packages/template-next-app/src/components/Button/Button.tsx +++ b/packages/template-next-app/src/components/Button/Button.tsx @@ -1,7 +1,7 @@ -import React, { forwardRef } from "react"; -import { Spacing } from "../Spacing"; -import { Spinner } from "../Spinner/Spinner"; -import styles from "./styles.module.css"; +import React, { forwardRef } from 'react'; +import { Spacing } from '../Spacing'; +import { Spinner } from '../Spinner/Spinner'; +import styles from './styles.module.css'; const ButtonForward: React.ForwardRefRenderFunction< HTMLButtonElement, @@ -19,7 +19,7 @@ const ButtonForward: React.ForwardRefRenderFunction< className={[ styles.button, secondary ? styles.secondarybutton : undefined, - ].join(" ")} + ].join(' ')} onClick={onClick} disabled={disabled} > diff --git a/packages/template-next-app/src/components/Container.tsx b/packages/template-next-app/src/components/Container.tsx index 71fe2f9b7ea..4ad9da288f8 100644 --- a/packages/template-next-app/src/components/Container.tsx +++ b/packages/template-next-app/src/components/Container.tsx @@ -1,12 +1,12 @@ -import React from "react"; +import React from 'react'; const inputContainer: React.CSSProperties = { - border: "1px solid var(--unfocused-border-color)", - padding: "var(--geist-pad)", - borderRadius: "var(--geist-border-radius)", - backgroundColor: "var(--background)", - display: "flex", - flexDirection: "column", + border: '1px solid var(--unfocused-border-color)', + padding: 'var(--geist-pad)', + borderRadius: 'var(--geist-border-radius)', + backgroundColor: 'var(--background)', + display: 'flex', + flexDirection: 'column', }; export const InputContainer: React.FC<{ diff --git a/packages/template-next-app/src/components/DownloadButton.tsx b/packages/template-next-app/src/components/DownloadButton.tsx index 5e60c49486f..35fac296ec5 100644 --- a/packages/template-next-app/src/components/DownloadButton.tsx +++ b/packages/template-next-app/src/components/DownloadButton.tsx @@ -1,29 +1,29 @@ -import React from "react"; -import { State } from "../helpers/use-rendering"; -import { Button } from "./Button/Button"; -import { Spacing } from "./Spacing"; +import React from 'react'; +import { State } from '../helpers/use-rendering'; +import { Button } from './Button/Button'; +import { Spacing } from './Spacing'; const light: React.CSSProperties = { opacity: 0.6, }; const link: React.CSSProperties = { - textDecoration: "none", + textDecoration: 'none', }; const row: React.CSSProperties = { - display: "flex", - flexDirection: "row", + display: 'flex', + flexDirection: 'row', }; const Megabytes: React.FC<{ sizeInBytes: number; }> = ({ sizeInBytes }) => { - const megabytes = Intl.NumberFormat("en", { - notation: "compact", - style: "unit", - unit: "byte", - unitDisplay: "narrow", + const megabytes = Intl.NumberFormat('en', { + notation: 'compact', + style: 'unit', + unit: 'byte', + unitDisplay: 'narrow', }).format(sizeInBytes); return {megabytes}; }; @@ -32,12 +32,12 @@ export const DownloadButton: React.FC<{ state: State; undo: () => void; }> = ({ state, undo }) => { - if (state.status === "rendering") { + if (state.status === 'rendering') { return ; } - if (state.status !== "done") { - throw new Error("Download button should not be rendered when not done"); + if (state.status !== 'done') { + throw new Error('Download button should not be rendered when not done'); } return ( diff --git a/packages/template-next-app/src/components/Error.tsx b/packages/template-next-app/src/components/Error.tsx index 7fa5d80fb3b..05db53a70fe 100644 --- a/packages/template-next-app/src/components/Error.tsx +++ b/packages/template-next-app/src/components/Error.tsx @@ -1,15 +1,15 @@ -import React from "react"; +import React from 'react'; const container: React.CSSProperties = { - color: "var(--geist-error)", - fontFamily: "var(--geist-font)", - paddingTop: "var(--geist-half-pad)", - paddingBottom: "var(--geist-half-pad)", + color: 'var(--geist-error)', + fontFamily: 'var(--geist-font)', + paddingTop: 'var(--geist-half-pad)', + paddingBottom: 'var(--geist-half-pad)', }; const icon: React.CSSProperties = { height: 20, - verticalAlign: "text-bottom", + verticalAlign: 'text-bottom', marginRight: 6, }; diff --git a/packages/template-next-app/src/components/Input.tsx b/packages/template-next-app/src/components/Input.tsx index 40b32dd4705..454c033c5c0 100644 --- a/packages/template-next-app/src/components/Input.tsx +++ b/packages/template-next-app/src/components/Input.tsx @@ -1,14 +1,14 @@ -import React, { useCallback } from "react"; +import React, { useCallback } from 'react'; const textarea: React.CSSProperties = { - resize: "none", + resize: 'none', lineHeight: 1.7, - display: "block", - width: "100%", - borderRadius: "var(--geist-border-radius)", - backgroundColor: "var(--background)", - padding: "var(--geist-half-pad)", - color: "var(--foreground)", + display: 'block', + width: '100%', + borderRadius: 'var(--geist-border-radius)', + backgroundColor: 'var(--background)', + padding: 'var(--geist-half-pad)', + color: 'var(--foreground)', fontSize: 14, }; diff --git a/packages/template-next-app/src/components/ProgressBar.tsx b/packages/template-next-app/src/components/ProgressBar.tsx index f383f994cd5..011cf3196ac 100644 --- a/packages/template-next-app/src/components/ProgressBar.tsx +++ b/packages/template-next-app/src/components/ProgressBar.tsx @@ -1,15 +1,15 @@ -import React, { useMemo } from "react"; +import React, { useMemo } from 'react'; export const ProgressBar: React.FC<{ progress: number; }> = ({ progress }) => { const style: React.CSSProperties = useMemo(() => { return { - width: "100%", + width: '100%', height: 10, borderRadius: 5, - appearance: "none", - backgroundColor: "var(--unfocused-border-color)", + appearance: 'none', + backgroundColor: 'var(--unfocused-border-color)', marginTop: 10, marginBottom: 25, }; @@ -17,10 +17,10 @@ export const ProgressBar: React.FC<{ const fill: React.CSSProperties = useMemo(() => { return { - backgroundColor: "var(--foreground)", + backgroundColor: 'var(--foreground)', height: 10, borderRadius: 5, - transition: "width 0.1s ease-in-out", + transition: 'width 0.1s ease-in-out', width: `${progress * 100}%`, }; }, [progress]); diff --git a/packages/template-next-app/src/components/RenderControls.tsx b/packages/template-next-app/src/components/RenderControls.tsx index 9cb56cc1484..7fceca34af9 100644 --- a/packages/template-next-app/src/components/RenderControls.tsx +++ b/packages/template-next-app/src/components/RenderControls.tsx @@ -1,14 +1,14 @@ -import { z } from "zod"; -import { useRendering } from "../helpers/use-rendering"; -import { CompositionProps, COMP_NAME } from "../types/constants"; -import { AlignEnd } from "./AlignEnd"; -import { Button } from "./Button/Button"; -import { InputContainer } from "./Container"; -import { DownloadButton } from "./DownloadButton"; -import { ErrorComp } from "./Error"; -import { Input } from "./Input"; -import { ProgressBar } from "./ProgressBar"; -import { Spacing } from "./Spacing"; +import { z } from 'zod'; +import { useRendering } from '../helpers/use-rendering'; +import { COMP_NAME, CompositionProps } from '../types/constants'; +import { AlignEnd } from './AlignEnd'; +import { Button } from './Button/Button'; +import { InputContainer } from './Container'; +import { DownloadButton } from './DownloadButton'; +import { ErrorComp } from './Error'; +import { Input } from './Input'; +import { ProgressBar } from './ProgressBar'; +import { Spacing } from './Spacing'; export const RenderControls: React.FC<{ text: string; @@ -19,34 +19,34 @@ export const RenderControls: React.FC<{ return ( - {state.status === "init" || - state.status === "invoking" || - state.status === "error" ? ( + {state.status === 'init' || + state.status === 'invoking' || + state.status === 'error' ? ( <> - {state.status === "error" ? ( + {state.status === 'error' ? ( ) : null} ) : null} - {state.status === "rendering" || state.status === "done" ? ( + {state.status === 'rendering' || state.status === 'done' ? ( <> diff --git a/packages/template-next-app/src/components/Spacing.tsx b/packages/template-next-app/src/components/Spacing.tsx index 31965a480c4..8bb0b451b6d 100644 --- a/packages/template-next-app/src/components/Spacing.tsx +++ b/packages/template-next-app/src/components/Spacing.tsx @@ -1,11 +1,11 @@ -import React from "react"; +import React from 'react'; export const Spacing: React.FC = () => { return (
); diff --git a/packages/template-next-app/src/components/Spinner/Spinner.tsx b/packages/template-next-app/src/components/Spinner/Spinner.tsx index ee0ce8f05b0..098d16fd2ea 100644 --- a/packages/template-next-app/src/components/Spinner/Spinner.tsx +++ b/packages/template-next-app/src/components/Spinner/Spinner.tsx @@ -1,7 +1,7 @@ -import React, { useMemo } from "react"; -import { makeRect } from "@remotion/shapes"; -import { translatePath } from "@remotion/paths"; -import styles from "./styles.module.css"; +import { translatePath } from '@remotion/paths'; +import { makeRect } from '@remotion/shapes'; +import React, { useMemo } from 'react'; +import styles from './styles.module.css'; const viewBox = 100; const lines = 12; @@ -33,7 +33,7 @@ export const Spinner: React.FC<{ className={styles.line} style={{ rotate: `${(index * Math.PI * 2) / lines}rad`, - transformOrigin: "center center", + transformOrigin: 'center center', animationDelay: `${index * 0.1 - lines * 0.1}s`, }} key={index} diff --git a/packages/template-next-app/src/components/Tips/Tips.tsx b/packages/template-next-app/src/components/Tips/Tips.tsx index a6cea969b35..9b1c0a0d7bb 100644 --- a/packages/template-next-app/src/components/Tips/Tips.tsx +++ b/packages/template-next-app/src/components/Tips/Tips.tsx @@ -1,22 +1,22 @@ -import React from "react"; -import styles from "./styles.module.css"; +import React from 'react'; +import styles from './styles.module.css'; const titlerow: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "center", - justifyContent: "flex-start", + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-start', }; const titlestyle: React.CSSProperties = { - marginBottom: "0.75em", - marginTop: "0.75em", - color: "var(--foreground)", + marginBottom: '0.75em', + marginTop: '0.75em', + color: 'var(--foreground)', }; const a: React.CSSProperties = { - textDecoration: "none", - color: "inherit", + textDecoration: 'none', + color: 'inherit', flex: 1, }; diff --git a/packages/template-next-app/src/helpers/api-response.ts b/packages/template-next-app/src/helpers/api-response.ts index d4da4ce7862..574a3134aec 100644 --- a/packages/template-next-app/src/helpers/api-response.ts +++ b/packages/template-next-app/src/helpers/api-response.ts @@ -1,13 +1,13 @@ -import { NextResponse } from "next/server"; -import { z, ZodType } from "zod"; +import { NextResponse } from 'next/server'; +import { z, ZodType } from 'zod'; export type ApiResponse = | { - type: "error"; + type: 'error'; message: string; } | { - type: "success"; + type: 'success'; data: Res; }; @@ -22,12 +22,12 @@ export const executeApi = const parsed = schema.parse(payload); const data = await handler(req, parsed); return NextResponse.json({ - type: "success", + type: 'success', data: data, }); } catch (err) { return NextResponse.json( - { type: "error", message: (err as Error).message }, + { type: 'error', message: (err as Error).message }, { status: 500, }, diff --git a/packages/template-next-app/src/helpers/use-rendering.ts b/packages/template-next-app/src/helpers/use-rendering.ts index a7f549d24f2..3ec5a484603 100644 --- a/packages/template-next-app/src/helpers/use-rendering.ts +++ b/packages/template-next-app/src/helpers/use-rendering.ts @@ -1,30 +1,30 @@ -import { z } from "zod"; -import { useCallback, useMemo, useState } from "react"; -import { getProgress, renderVideo } from "../lambda/api"; -import { CompositionProps } from "../types/constants"; +import { useCallback, useMemo, useState } from 'react'; +import { z } from 'zod'; +import { getProgress, renderVideo } from '../lambda/api'; +import { CompositionProps } from '../types/constants'; export type State = | { - status: "init"; + status: 'init'; } | { - status: "invoking"; + status: 'invoking'; } | { renderId: string; bucketName: string; progress: number; - status: "rendering"; + status: 'rendering'; } | { renderId: string | null; - status: "error"; + status: 'error'; error: Error; } | { url: string; size: number; - status: "done"; + status: 'done'; }; const wait = async (milliSeconds: number) => { @@ -40,17 +40,17 @@ export const useRendering = ( inputProps: z.infer, ) => { const [state, setState] = useState({ - status: "init", + status: 'init', }); const renderMedia = useCallback(async () => { setState({ - status: "invoking", + status: 'invoking', }); try { const { renderId, bucketName } = await renderVideo({ id, inputProps }); setState({ - status: "rendering", + status: 'rendering', progress: 0, renderId: renderId, bucketName: bucketName, @@ -64,27 +64,27 @@ export const useRendering = ( bucketName: bucketName, }); switch (result.type) { - case "error": { + case 'error': { setState({ - status: "error", + status: 'error', renderId: renderId, error: new Error(result.message), }); pending = false; break; } - case "done": { + case 'done': { setState({ size: result.size, url: result.url, - status: "done", + status: 'done', }); pending = false; break; } - case "progress": { + case 'progress': { setState({ - status: "rendering", + status: 'rendering', bucketName: bucketName, progress: result.progress, renderId: renderId, @@ -95,7 +95,7 @@ export const useRendering = ( } } catch (err) { setState({ - status: "error", + status: 'error', error: err as Error, renderId: null, }); @@ -103,7 +103,7 @@ export const useRendering = ( }, [id, inputProps]); const undo = useCallback(() => { - setState({ status: "init" }); + setState({ status: 'init' }); }, []); return useMemo(() => { diff --git a/packages/template-next-app/src/lambda/api.ts b/packages/template-next-app/src/lambda/api.ts index a01d801ed55..8509aabd384 100644 --- a/packages/template-next-app/src/lambda/api.ts +++ b/packages/template-next-app/src/lambda/api.ts @@ -1,26 +1,26 @@ -import { z } from "zod"; -import type { RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; +import type { RenderMediaOnLambdaOutput } from '@remotion/lambda/client'; +import { z } from 'zod'; +import { ApiResponse } from '../helpers/api-response'; +import { CompositionProps } from '../types/constants'; import { ProgressRequest, ProgressResponse, RenderRequest, -} from "../types/schema"; -import { CompositionProps } from "../types/constants"; -import { ApiResponse } from "../helpers/api-response"; +} from '../types/schema'; const makeRequest = async ( endpoint: string, body: unknown, ): Promise => { const result = await fetch(endpoint, { - method: "post", + method: 'post', body: JSON.stringify(body), headers: { - "content-type": "application/json", + 'content-type': 'application/json', }, }); const json = (await result.json()) as ApiResponse; - if (json.type === "error") { + if (json.type === 'error') { throw new Error(json.message); } @@ -39,7 +39,7 @@ export const renderVideo = async ({ inputProps, }; - return makeRequest("/api/lambda/render", body); + return makeRequest('/api/lambda/render', body); }; export const getProgress = async ({ @@ -54,5 +54,5 @@ export const getProgress = async ({ bucketName, }; - return makeRequest("/api/lambda/progress", body); + return makeRequest('/api/lambda/progress', body); }; diff --git a/packages/template-next-app/src/remotion/MyComp/Main.tsx b/packages/template-next-app/src/remotion/MyComp/Main.tsx index dfc1b51472c..29f33546fee 100644 --- a/packages/template-next-app/src/remotion/MyComp/Main.tsx +++ b/packages/template-next-app/src/remotion/MyComp/Main.tsx @@ -1,30 +1,30 @@ -import { z } from "zod"; +import { fontFamily, loadFont } from '@remotion/google-fonts/Inter'; +import React, { useMemo } from 'react'; import { AbsoluteFill, Sequence, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; -import { NextLogo } from "./NextLogo"; -import { loadFont, fontFamily } from "@remotion/google-fonts/Inter"; -import React, { useMemo } from "react"; -import { Rings } from "./Rings"; -import { TextFade } from "./TextFade"; -import { CompositionProps } from "../../types/constants"; +} from 'remotion'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; +import { NextLogo } from './NextLogo'; +import { Rings } from './Rings'; +import { TextFade } from './TextFade'; -loadFont("normal", { - subsets: ["latin"], - weights: ["400", "700"], +loadFont('normal', { + subsets: ['latin'], + weights: ['400', '700'], }); const container: React.CSSProperties = { - backgroundColor: "white", + backgroundColor: 'white', }; const logo: React.CSSProperties = { - justifyContent: "center", - alignItems: "center", + justifyContent: 'center', + alignItems: 'center', }; export const Main = ({ title }: z.infer) => { diff --git a/packages/template-next-app/src/remotion/MyComp/NextLogo.tsx b/packages/template-next-app/src/remotion/MyComp/NextLogo.tsx index 5d0f03ab6aa..f2b477e1735 100644 --- a/packages/template-next-app/src/remotion/MyComp/NextLogo.tsx +++ b/packages/template-next-app/src/remotion/MyComp/NextLogo.tsx @@ -1,13 +1,13 @@ -import { evolvePath } from "@remotion/paths"; -import React, { useMemo } from "react"; -import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"; +import { evolvePath } from '@remotion/paths'; +import React, { useMemo } from 'react'; +import { interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'; const mask: React.CSSProperties = { - maskType: "alpha", + maskType: 'alpha', }; const nStroke = - "M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z"; + 'M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z'; export const NextLogo: React.FC<{ outProgress: number; diff --git a/packages/template-next-app/src/remotion/MyComp/Rings.tsx b/packages/template-next-app/src/remotion/MyComp/Rings.tsx index 68adad54296..20801ee15f2 100644 --- a/packages/template-next-app/src/remotion/MyComp/Rings.tsx +++ b/packages/template-next-app/src/remotion/MyComp/Rings.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { AbsoluteFill, interpolateColors, useVideoConfig } from "remotion"; +import React from 'react'; +import { AbsoluteFill, interpolateColors, useVideoConfig } from 'remotion'; const RadialGradient: React.FC<{ radius: number; @@ -11,19 +11,19 @@ const RadialGradient: React.FC<{ return (
@@ -49,7 +49,7 @@ export const Rings: React.FC<{ ); }) diff --git a/packages/template-next-app/src/remotion/MyComp/TextFade.tsx b/packages/template-next-app/src/remotion/MyComp/TextFade.tsx index a9a0891aaad..1f3869b46f4 100644 --- a/packages/template-next-app/src/remotion/MyComp/TextFade.tsx +++ b/packages/template-next-app/src/remotion/MyComp/TextFade.tsx @@ -1,11 +1,11 @@ -import React, { useMemo } from "react"; +import React, { useMemo } from 'react'; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; +} from 'remotion'; const outer: React.CSSProperties = {}; @@ -32,8 +32,8 @@ export const TextFade: React.FC<{ const container: React.CSSProperties = useMemo(() => { return { - justifyContent: "center", - alignItems: "center", + justifyContent: 'center', + alignItems: 'center', }; }, []); diff --git a/packages/template-next-app/src/remotion/Root.tsx b/packages/template-next-app/src/remotion/Root.tsx index 92de0800a68..69ce84dc6d7 100644 --- a/packages/template-next-app/src/remotion/Root.tsx +++ b/packages/template-next-app/src/remotion/Root.tsx @@ -1,5 +1,4 @@ -import { Composition } from "remotion"; -import { Main } from "./MyComp/Main"; +import { Composition } from 'remotion'; import { COMP_NAME, defaultMyCompProps, @@ -7,8 +6,9 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from "../types/constants"; -import { NextLogo } from "./MyComp/NextLogo"; +} from '../types/constants'; +import { Main } from './MyComp/Main'; +import { NextLogo } from './MyComp/NextLogo'; export const RemotionRoot: React.FC = () => { return ( diff --git a/packages/template-next-app/src/remotion/index.ts b/packages/template-next-app/src/remotion/index.ts index f31c790edb3..91fa0f3468e 100644 --- a/packages/template-next-app/src/remotion/index.ts +++ b/packages/template-next-app/src/remotion/index.ts @@ -1,4 +1,4 @@ -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; +import { registerRoot } from 'remotion'; +import { RemotionRoot } from './Root'; registerRoot(RemotionRoot); diff --git a/packages/template-next-app/src/types/constants.ts b/packages/template-next-app/src/types/constants.ts index 4767c5e80f7..fb98be2ae32 100644 --- a/packages/template-next-app/src/types/constants.ts +++ b/packages/template-next-app/src/types/constants.ts @@ -1,12 +1,12 @@ -import { z } from "zod"; -export const COMP_NAME = "MyComp"; +import { z } from 'zod'; +export const COMP_NAME = 'MyComp'; export const CompositionProps = z.object({ title: z.string(), }); export const defaultMyCompProps: z.infer = { - title: "Next.js and Remotion", + title: 'Next.js and Remotion', }; export const DURATION_IN_FRAMES = 200; diff --git a/packages/template-next-app/src/types/schema.ts b/packages/template-next-app/src/types/schema.ts index da1562f334d..715ce685b74 100644 --- a/packages/template-next-app/src/types/schema.ts +++ b/packages/template-next-app/src/types/schema.ts @@ -1,5 +1,5 @@ -import { z } from "zod"; -import { CompositionProps } from "./constants"; +import { z } from 'zod'; +import { CompositionProps } from './constants'; export const RenderRequest = z.object({ id: z.string(), @@ -13,15 +13,15 @@ export const ProgressRequest = z.object({ export type ProgressResponse = | { - type: "error"; + type: 'error'; message: string; } | { - type: "progress"; + type: 'progress'; progress: number; } | { - type: "done"; + type: 'done'; url: string; size: number; }; diff --git a/packages/template-next-pages/package.json b/packages/template-next-pages/package.json index 127594e436d..a05c53f2a44 100644 --- a/packages/template-next-pages/package.json +++ b/packages/template-next-pages/package.json @@ -39,7 +39,7 @@ "dotenv": "17.3.1", "eslint": "9.19.0", "eslint-config-next": "15.1.6", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3", "typescript-eslint": "8.46.0" } diff --git a/packages/template-next-pages/src/components/AlignEnd.tsx b/packages/template-next-pages/src/components/AlignEnd.tsx index f08aa29ad5f..f7e736314bd 100644 --- a/packages/template-next-pages/src/components/AlignEnd.tsx +++ b/packages/template-next-pages/src/components/AlignEnd.tsx @@ -1,7 +1,7 @@ -import React from "react"; +import React from 'react'; const container: React.CSSProperties = { - alignSelf: "flex-end", + alignSelf: 'flex-end', }; export const AlignEnd: React.FC<{ diff --git a/packages/template-next-pages/src/components/Button/Button.tsx b/packages/template-next-pages/src/components/Button/Button.tsx index b697c903144..8041ae33b2e 100644 --- a/packages/template-next-pages/src/components/Button/Button.tsx +++ b/packages/template-next-pages/src/components/Button/Button.tsx @@ -1,7 +1,7 @@ -import React, { forwardRef } from "react"; -import { Spacing } from "../Spacing"; -import { Spinner } from "../Spinner/Spinner"; -import styles from "./styles.module.css"; +import React, { forwardRef } from 'react'; +import { Spacing } from '../Spacing'; +import { Spinner } from '../Spinner/Spinner'; +import styles from './styles.module.css'; const ButtonForward: React.ForwardRefRenderFunction< HTMLButtonElement, @@ -19,7 +19,7 @@ const ButtonForward: React.ForwardRefRenderFunction< className={[ styles.button, secondary ? styles.secondarybutton : undefined, - ].join(" ")} + ].join(' ')} onClick={onClick} disabled={disabled} > diff --git a/packages/template-next-pages/src/components/Container.tsx b/packages/template-next-pages/src/components/Container.tsx index 71fe2f9b7ea..4ad9da288f8 100644 --- a/packages/template-next-pages/src/components/Container.tsx +++ b/packages/template-next-pages/src/components/Container.tsx @@ -1,12 +1,12 @@ -import React from "react"; +import React from 'react'; const inputContainer: React.CSSProperties = { - border: "1px solid var(--unfocused-border-color)", - padding: "var(--geist-pad)", - borderRadius: "var(--geist-border-radius)", - backgroundColor: "var(--background)", - display: "flex", - flexDirection: "column", + border: '1px solid var(--unfocused-border-color)', + padding: 'var(--geist-pad)', + borderRadius: 'var(--geist-border-radius)', + backgroundColor: 'var(--background)', + display: 'flex', + flexDirection: 'column', }; export const InputContainer: React.FC<{ diff --git a/packages/template-next-pages/src/components/DownloadButton.tsx b/packages/template-next-pages/src/components/DownloadButton.tsx index ac1b8fd5a73..6ba33109202 100644 --- a/packages/template-next-pages/src/components/DownloadButton.tsx +++ b/packages/template-next-pages/src/components/DownloadButton.tsx @@ -1,30 +1,30 @@ -import Link from "next/link"; -import React from "react"; -import { State } from "../helpers/use-rendering"; -import { Button } from "./Button/Button"; -import { Spacing } from "./Spacing"; +import Link from 'next/link'; +import React from 'react'; +import { State } from '../helpers/use-rendering'; +import { Button } from './Button/Button'; +import { Spacing } from './Spacing'; const light: React.CSSProperties = { opacity: 0.6, }; const link: React.CSSProperties = { - textDecoration: "none", + textDecoration: 'none', }; const row: React.CSSProperties = { - display: "flex", - flexDirection: "row", + display: 'flex', + flexDirection: 'row', }; const Megabytes: React.FC<{ sizeInBytes: number; }> = ({ sizeInBytes }) => { - const megabytes = Intl.NumberFormat("en", { - notation: "compact", - style: "unit", - unit: "byte", - unitDisplay: "narrow", + const megabytes = Intl.NumberFormat('en', { + notation: 'compact', + style: 'unit', + unit: 'byte', + unitDisplay: 'narrow', }).format(sizeInBytes); return {megabytes}; }; @@ -33,12 +33,12 @@ export const DownloadButton: React.FC<{ state: State; undo: () => void; }> = ({ state, undo }) => { - if (state.status === "rendering") { + if (state.status === 'rendering') { return ; } - if (state.status !== "done") { - throw new Error("Download button should not be rendered when not done"); + if (state.status !== 'done') { + throw new Error('Download button should not be rendered when not done'); } return ( diff --git a/packages/template-next-pages/src/components/Error.tsx b/packages/template-next-pages/src/components/Error.tsx index 7fa5d80fb3b..05db53a70fe 100644 --- a/packages/template-next-pages/src/components/Error.tsx +++ b/packages/template-next-pages/src/components/Error.tsx @@ -1,15 +1,15 @@ -import React from "react"; +import React from 'react'; const container: React.CSSProperties = { - color: "var(--geist-error)", - fontFamily: "var(--geist-font)", - paddingTop: "var(--geist-half-pad)", - paddingBottom: "var(--geist-half-pad)", + color: 'var(--geist-error)', + fontFamily: 'var(--geist-font)', + paddingTop: 'var(--geist-half-pad)', + paddingBottom: 'var(--geist-half-pad)', }; const icon: React.CSSProperties = { height: 20, - verticalAlign: "text-bottom", + verticalAlign: 'text-bottom', marginRight: 6, }; diff --git a/packages/template-next-pages/src/components/Input.tsx b/packages/template-next-pages/src/components/Input.tsx index 40b32dd4705..454c033c5c0 100644 --- a/packages/template-next-pages/src/components/Input.tsx +++ b/packages/template-next-pages/src/components/Input.tsx @@ -1,14 +1,14 @@ -import React, { useCallback } from "react"; +import React, { useCallback } from 'react'; const textarea: React.CSSProperties = { - resize: "none", + resize: 'none', lineHeight: 1.7, - display: "block", - width: "100%", - borderRadius: "var(--geist-border-radius)", - backgroundColor: "var(--background)", - padding: "var(--geist-half-pad)", - color: "var(--foreground)", + display: 'block', + width: '100%', + borderRadius: 'var(--geist-border-radius)', + backgroundColor: 'var(--background)', + padding: 'var(--geist-half-pad)', + color: 'var(--foreground)', fontSize: 14, }; diff --git a/packages/template-next-pages/src/components/ProgressBar.tsx b/packages/template-next-pages/src/components/ProgressBar.tsx index f383f994cd5..011cf3196ac 100644 --- a/packages/template-next-pages/src/components/ProgressBar.tsx +++ b/packages/template-next-pages/src/components/ProgressBar.tsx @@ -1,15 +1,15 @@ -import React, { useMemo } from "react"; +import React, { useMemo } from 'react'; export const ProgressBar: React.FC<{ progress: number; }> = ({ progress }) => { const style: React.CSSProperties = useMemo(() => { return { - width: "100%", + width: '100%', height: 10, borderRadius: 5, - appearance: "none", - backgroundColor: "var(--unfocused-border-color)", + appearance: 'none', + backgroundColor: 'var(--unfocused-border-color)', marginTop: 10, marginBottom: 25, }; @@ -17,10 +17,10 @@ export const ProgressBar: React.FC<{ const fill: React.CSSProperties = useMemo(() => { return { - backgroundColor: "var(--foreground)", + backgroundColor: 'var(--foreground)', height: 10, borderRadius: 5, - transition: "width 0.1s ease-in-out", + transition: 'width 0.1s ease-in-out', width: `${progress * 100}%`, }; }, [progress]); diff --git a/packages/template-next-pages/src/components/RenderControls.tsx b/packages/template-next-pages/src/components/RenderControls.tsx index 3ed5b70a21b..c81f470a9ab 100644 --- a/packages/template-next-pages/src/components/RenderControls.tsx +++ b/packages/template-next-pages/src/components/RenderControls.tsx @@ -1,14 +1,14 @@ -import { z } from "zod"; -import { useRendering } from "../helpers/use-rendering"; -import { AlignEnd } from "./AlignEnd"; -import { Button } from "./Button/Button"; -import { InputContainer } from "./Container"; -import { DownloadButton } from "./DownloadButton"; -import { ErrorComp } from "./Error"; -import { Input } from "./Input"; -import { ProgressBar } from "./ProgressBar"; -import { Spacing } from "./Spacing"; -import { COMP_NAME, CompositionProps } from "../../types/constants"; +import { z } from 'zod'; +import { COMP_NAME, CompositionProps } from '../../types/constants'; +import { useRendering } from '../helpers/use-rendering'; +import { AlignEnd } from './AlignEnd'; +import { Button } from './Button/Button'; +import { InputContainer } from './Container'; +import { DownloadButton } from './DownloadButton'; +import { ErrorComp } from './Error'; +import { Input } from './Input'; +import { ProgressBar } from './ProgressBar'; +import { Spacing } from './Spacing'; export const RenderControls: React.FC<{ text: string; @@ -19,34 +19,34 @@ export const RenderControls: React.FC<{ return ( - {state.status === "init" || - state.status === "invoking" || - state.status === "error" ? ( + {state.status === 'init' || + state.status === 'invoking' || + state.status === 'error' ? ( <> - {state.status === "error" ? ( + {state.status === 'error' ? ( ) : null} ) : null} - {state.status === "rendering" || state.status === "done" ? ( + {state.status === 'rendering' || state.status === 'done' ? ( <> diff --git a/packages/template-next-pages/src/components/Spacing.tsx b/packages/template-next-pages/src/components/Spacing.tsx index 31965a480c4..8bb0b451b6d 100644 --- a/packages/template-next-pages/src/components/Spacing.tsx +++ b/packages/template-next-pages/src/components/Spacing.tsx @@ -1,11 +1,11 @@ -import React from "react"; +import React from 'react'; export const Spacing: React.FC = () => { return (
); diff --git a/packages/template-next-pages/src/components/Spinner/Spinner.tsx b/packages/template-next-pages/src/components/Spinner/Spinner.tsx index ee0ce8f05b0..098d16fd2ea 100644 --- a/packages/template-next-pages/src/components/Spinner/Spinner.tsx +++ b/packages/template-next-pages/src/components/Spinner/Spinner.tsx @@ -1,7 +1,7 @@ -import React, { useMemo } from "react"; -import { makeRect } from "@remotion/shapes"; -import { translatePath } from "@remotion/paths"; -import styles from "./styles.module.css"; +import { translatePath } from '@remotion/paths'; +import { makeRect } from '@remotion/shapes'; +import React, { useMemo } from 'react'; +import styles from './styles.module.css'; const viewBox = 100; const lines = 12; @@ -33,7 +33,7 @@ export const Spinner: React.FC<{ className={styles.line} style={{ rotate: `${(index * Math.PI * 2) / lines}rad`, - transformOrigin: "center center", + transformOrigin: 'center center', animationDelay: `${index * 0.1 - lines * 0.1}s`, }} key={index} diff --git a/packages/template-next-pages/src/components/Tips/Tips.tsx b/packages/template-next-pages/src/components/Tips/Tips.tsx index 3b26ca9c0b8..d8f5498bf7a 100644 --- a/packages/template-next-pages/src/components/Tips/Tips.tsx +++ b/packages/template-next-pages/src/components/Tips/Tips.tsx @@ -1,22 +1,22 @@ -import React from "react"; -import styles from "./styles.module.css"; +import React from 'react'; +import styles from './styles.module.css'; const titlerow: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "center", - justifyContent: "flex-start", + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + justifyContent: 'flex-start', }; const titlestyle: React.CSSProperties = { - marginBottom: "0.75em", - marginTop: "0.75em", - color: "var(--foreground)", + marginBottom: '0.75em', + marginTop: '0.75em', + color: 'var(--foreground)', }; const a: React.CSSProperties = { - textDecoration: "none", - color: "inherit", + textDecoration: 'none', + color: 'inherit', flex: 1, }; diff --git a/packages/template-next-pages/src/helpers/api-response.ts b/packages/template-next-pages/src/helpers/api-response.ts index 33a9cb8afde..cc2fbf8c2ea 100644 --- a/packages/template-next-pages/src/helpers/api-response.ts +++ b/packages/template-next-pages/src/helpers/api-response.ts @@ -1,13 +1,13 @@ -import { NextApiRequest, NextApiResponse } from "next"; -import { z, ZodType } from "zod"; +import { NextApiRequest, NextApiResponse } from 'next'; +import { z, ZodType } from 'zod'; export type ApiResponse = | { - type: "error"; + type: 'error'; message: string; } | { - type: "success"; + type: 'success'; data: Res; }; @@ -25,10 +25,10 @@ export const executeApi = const parsed = schema.parse(req.body); const data = await handler(req, parsed, res); res.status(200).json({ - type: "success", + type: 'success', data: data, }); } catch (err) { - res.status(500).json({ type: "error", message: (err as Error).message }); + res.status(500).json({ type: 'error', message: (err as Error).message }); } }; diff --git a/packages/template-next-pages/src/helpers/use-rendering.ts b/packages/template-next-pages/src/helpers/use-rendering.ts index ff7c29efdb0..c871bfc6f2a 100644 --- a/packages/template-next-pages/src/helpers/use-rendering.ts +++ b/packages/template-next-pages/src/helpers/use-rendering.ts @@ -1,30 +1,30 @@ -import { z } from "zod"; -import { useCallback, useMemo, useState } from "react"; -import { getProgress, renderVideo } from "../lambda/api"; -import { CompositionProps } from "../../types/constants"; +import { useCallback, useMemo, useState } from 'react'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; +import { getProgress, renderVideo } from '../lambda/api'; export type State = | { - status: "init"; + status: 'init'; } | { - status: "invoking"; + status: 'invoking'; } | { renderId: string; bucketName: string; progress: number; - status: "rendering"; + status: 'rendering'; } | { renderId: string | null; - status: "error"; + status: 'error'; error: Error; } | { url: string; size: number; - status: "done"; + status: 'done'; }; const wait = async (milliSeconds: number) => { @@ -40,17 +40,17 @@ export const useRendering = ( inputProps: z.infer, ) => { const [state, setState] = useState({ - status: "init", + status: 'init', }); const renderMedia = useCallback(async () => { setState({ - status: "invoking", + status: 'invoking', }); try { const { renderId, bucketName } = await renderVideo({ id, inputProps }); setState({ - status: "rendering", + status: 'rendering', progress: 0, renderId: renderId, bucketName: bucketName, @@ -64,27 +64,27 @@ export const useRendering = ( bucketName: bucketName, }); switch (result.type) { - case "error": { + case 'error': { setState({ - status: "error", + status: 'error', renderId: renderId, error: new Error(result.message), }); pending = false; break; } - case "done": { + case 'done': { setState({ size: result.size, url: result.url, - status: "done", + status: 'done', }); pending = false; break; } - case "progress": { + case 'progress': { setState({ - status: "rendering", + status: 'rendering', bucketName: bucketName, progress: result.progress, renderId: renderId, @@ -95,7 +95,7 @@ export const useRendering = ( } } catch (err) { setState({ - status: "error", + status: 'error', error: err as Error, renderId: null, }); @@ -103,7 +103,7 @@ export const useRendering = ( }, [id, inputProps]); const undo = useCallback(() => { - setState({ status: "init" }); + setState({ status: 'init' }); }, []); return useMemo(() => { diff --git a/packages/template-next-pages/src/lambda/api.ts b/packages/template-next-pages/src/lambda/api.ts index 95f0613d9d8..44de9effdbb 100644 --- a/packages/template-next-pages/src/lambda/api.ts +++ b/packages/template-next-pages/src/lambda/api.ts @@ -1,26 +1,26 @@ -import { z } from "zod"; -import type { RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; -import { ApiResponse } from "../helpers/api-response"; -import { CompositionProps } from "../../types/constants"; +import type { RenderMediaOnLambdaOutput } from '@remotion/lambda/client'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; import { - RenderRequest, ProgressRequest, ProgressResponse, -} from "../../types/schema"; + RenderRequest, +} from '../../types/schema'; +import { ApiResponse } from '../helpers/api-response'; const makeRequest = async ( endpoint: string, body: unknown, ): Promise => { const result = await fetch(endpoint, { - method: "post", + method: 'post', body: JSON.stringify(body), headers: { - "content-type": "application/json", + 'content-type': 'application/json', }, }); const json = (await result.json()) as ApiResponse; - if (json.type === "error") { + if (json.type === 'error') { throw new Error(json.message); } @@ -39,7 +39,7 @@ export const renderVideo = async ({ inputProps, }; - return makeRequest("/api/lambda/render", body); + return makeRequest('/api/lambda/render', body); }; export const getProgress = async ({ @@ -54,5 +54,5 @@ export const getProgress = async ({ bucketName, }; - return makeRequest("/api/lambda/progress", body); + return makeRequest('/api/lambda/progress', body); }; diff --git a/packages/template-next-pages/src/pages/_app.tsx b/packages/template-next-pages/src/pages/_app.tsx index 9c00895b0ff..762bde25b83 100644 --- a/packages/template-next-pages/src/pages/_app.tsx +++ b/packages/template-next-pages/src/pages/_app.tsx @@ -1,5 +1,5 @@ -import "../../styles/global.css"; -import type { AppProps } from "next/app"; +import type { AppProps } from 'next/app'; +import '../../styles/global.css'; function MyApp({ Component, pageProps }: AppProps) { return ; diff --git a/packages/template-next-pages/src/pages/api/lambda/progress.ts b/packages/template-next-pages/src/pages/api/lambda/progress.ts index 19cc6b73586..1c8bce8424f 100644 --- a/packages/template-next-pages/src/pages/api/lambda/progress.ts +++ b/packages/template-next-pages/src/pages/api/lambda/progress.ts @@ -1,17 +1,17 @@ import { - speculateFunctionName, AwsRegion, getRenderProgress, -} from "@remotion/lambda/client"; -import { DISK, RAM, REGION, TIMEOUT } from "../../../../config.mjs"; -import { executeApi } from "../../../helpers/api-response"; -import { ProgressResponse, ProgressRequest } from "../../../../types/schema"; + speculateFunctionName, +} from '@remotion/lambda/client'; +import { DISK, RAM, REGION, TIMEOUT } from '../../../../config.mjs'; +import { ProgressRequest, ProgressResponse } from '../../../../types/schema'; +import { executeApi } from '../../../helpers/api-response'; const progress = executeApi( ProgressRequest, async (req, body) => { - if (req.method !== "POST") { - throw new Error("Only POST requests are allowed"); + if (req.method !== 'POST') { + throw new Error('Only POST requests are allowed'); } const renderProgress = await getRenderProgress({ @@ -27,21 +27,21 @@ const progress = executeApi( if (renderProgress.fatalErrorEncountered) { return { - type: "error", + type: 'error', message: renderProgress.errors[0].message, }; } if (renderProgress.done) { return { - type: "done", + type: 'done', url: renderProgress.outputFile as string, size: renderProgress.outputSizeInBytes as number, }; } return { - type: "progress", + type: 'progress', progress: Math.max(0.03, renderProgress.overallProgress), }; }, diff --git a/packages/template-next-pages/src/pages/api/lambda/render.ts b/packages/template-next-pages/src/pages/api/lambda/render.ts index 28b7e4e0b45..eaa48168af3 100644 --- a/packages/template-next-pages/src/pages/api/lambda/render.ts +++ b/packages/template-next-pages/src/pages/api/lambda/render.ts @@ -1,17 +1,18 @@ -import { AwsRegion, RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; import { + AwsRegion, renderMediaOnLambda, + RenderMediaOnLambdaOutput, speculateFunctionName, -} from "@remotion/lambda/client"; -import { DISK, RAM, REGION, SITE_NAME, TIMEOUT } from "../../../../config.mjs"; -import { executeApi } from "../../../helpers/api-response"; -import { RenderRequest } from "../../../../types/schema"; +} from '@remotion/lambda/client'; +import { DISK, RAM, REGION, SITE_NAME, TIMEOUT } from '../../../../config.mjs'; +import { RenderRequest } from '../../../../types/schema'; +import { executeApi } from '../../../helpers/api-response'; const render = executeApi( RenderRequest, async (req, body) => { - if (req.method !== "POST") { - throw new Error("Only POST requests are allowed"); + if (req.method !== 'POST') { + throw new Error('Only POST requests are allowed'); } if ( @@ -19,7 +20,7 @@ const render = executeApi( !process.env.REMOTION_AWS_ACCESS_KEY_ID ) { throw new TypeError( - "Set up Remotion Lambda to render videos. See the README.md for how to do so.", + 'Set up Remotion Lambda to render videos. See the README.md for how to do so.', ); } if ( @@ -27,12 +28,12 @@ const render = executeApi( !process.env.REMOTION_AWS_SECRET_ACCESS_KEY ) { throw new TypeError( - "The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.", + 'The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.', ); } const result = await renderMediaOnLambda({ - codec: "h264", + codec: 'h264', functionName: speculateFunctionName({ diskSizeInMb: DISK, memorySizeInMb: RAM, @@ -44,8 +45,8 @@ const render = executeApi( inputProps: body.inputProps, framesPerLambda: 10, downloadBehavior: { - type: "download", - fileName: "video.mp4", + type: 'download', + fileName: 'video.mp4', }, }); diff --git a/packages/template-next-pages/src/pages/index.tsx b/packages/template-next-pages/src/pages/index.tsx index 31904266676..78845e8a7b9 100644 --- a/packages/template-next-pages/src/pages/index.tsx +++ b/packages/template-next-pages/src/pages/index.tsx @@ -1,8 +1,8 @@ -import { Player } from "@remotion/player"; -import type { NextPage } from "next"; -import Head from "next/head"; -import React, { useMemo, useState } from "react"; -import { Main } from "../remotion/MyComp/Main"; +import { Player } from '@remotion/player'; +import type { NextPage } from 'next'; +import Head from 'next/head'; +import React, { useMemo, useState } from 'react'; +import { z } from 'zod'; import { CompositionProps, defaultMyCompProps, @@ -10,30 +10,30 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from "../../types/constants"; -import { z } from "zod"; -import { RenderControls } from "../components/RenderControls"; -import { Tips } from "../components/Tips/Tips"; -import { Spacing } from "../components/Spacing"; +} from '../../types/constants'; +import { RenderControls } from '../components/RenderControls'; +import { Spacing } from '../components/Spacing'; +import { Tips } from '../components/Tips/Tips'; +import { Main } from '../remotion/MyComp/Main'; const container: React.CSSProperties = { maxWidth: 768, - margin: "auto", + margin: 'auto', marginBottom: 20, paddingLeft: 16, paddingRight: 16, }; const outer: React.CSSProperties = { - borderRadius: "var(--geist-border-radius)", - overflow: "hidden", - boxShadow: "0 0 200px rgba(0, 0, 0, 0.15)", + borderRadius: 'var(--geist-border-radius)', + overflow: 'hidden', + boxShadow: '0 0 200px rgba(0, 0, 0, 0.15)', marginBottom: 40, marginTop: 60, }; const player: React.CSSProperties = { - width: "100%", + width: '100%', }; const Home: NextPage = () => { diff --git a/packages/template-next-pages/src/remotion/MyComp/Main.tsx b/packages/template-next-pages/src/remotion/MyComp/Main.tsx index 73b31927c17..dfaa1239ca8 100644 --- a/packages/template-next-pages/src/remotion/MyComp/Main.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/Main.tsx @@ -1,30 +1,30 @@ -import { z } from "zod"; +import { fontFamily, loadFont } from '@remotion/google-fonts/Inter'; +import React, { useMemo } from 'react'; import { AbsoluteFill, Sequence, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; -import { NextLogo } from "./NextLogo"; -import { loadFont, fontFamily } from "@remotion/google-fonts/Inter"; -import React, { useMemo } from "react"; -import { Rings } from "./Rings"; -import { TextFade } from "./TextFade"; -import { CompositionProps } from "../../../types/constants"; +} from 'remotion'; +import { z } from 'zod'; +import { CompositionProps } from '../../../types/constants'; +import { NextLogo } from './NextLogo'; +import { Rings } from './Rings'; +import { TextFade } from './TextFade'; -loadFont("normal", { - subsets: ["latin"], - weights: ["400", "700"], +loadFont('normal', { + subsets: ['latin'], + weights: ['400', '700'], }); const container: React.CSSProperties = { - backgroundColor: "white", + backgroundColor: 'white', }; const logo: React.CSSProperties = { - justifyContent: "center", - alignItems: "center", + justifyContent: 'center', + alignItems: 'center', }; export const Main = ({ title }: z.infer) => { diff --git a/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx b/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx index 5d0f03ab6aa..f2b477e1735 100644 --- a/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx @@ -1,13 +1,13 @@ -import { evolvePath } from "@remotion/paths"; -import React, { useMemo } from "react"; -import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"; +import { evolvePath } from '@remotion/paths'; +import React, { useMemo } from 'react'; +import { interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'; const mask: React.CSSProperties = { - maskType: "alpha", + maskType: 'alpha', }; const nStroke = - "M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z"; + 'M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z'; export const NextLogo: React.FC<{ outProgress: number; diff --git a/packages/template-next-pages/src/remotion/MyComp/Rings.tsx b/packages/template-next-pages/src/remotion/MyComp/Rings.tsx index 68adad54296..20801ee15f2 100644 --- a/packages/template-next-pages/src/remotion/MyComp/Rings.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/Rings.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { AbsoluteFill, interpolateColors, useVideoConfig } from "remotion"; +import React from 'react'; +import { AbsoluteFill, interpolateColors, useVideoConfig } from 'remotion'; const RadialGradient: React.FC<{ radius: number; @@ -11,19 +11,19 @@ const RadialGradient: React.FC<{ return (
@@ -49,7 +49,7 @@ export const Rings: React.FC<{ ); }) diff --git a/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx b/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx index a9a0891aaad..1f3869b46f4 100644 --- a/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx @@ -1,11 +1,11 @@ -import React, { useMemo } from "react"; +import React, { useMemo } from 'react'; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; +} from 'remotion'; const outer: React.CSSProperties = {}; @@ -32,8 +32,8 @@ export const TextFade: React.FC<{ const container: React.CSSProperties = useMemo(() => { return { - justifyContent: "center", - alignItems: "center", + justifyContent: 'center', + alignItems: 'center', }; }, []); diff --git a/packages/template-next-pages/src/remotion/Root.tsx b/packages/template-next-pages/src/remotion/Root.tsx index 83276274db8..284b680e91d 100644 --- a/packages/template-next-pages/src/remotion/Root.tsx +++ b/packages/template-next-pages/src/remotion/Root.tsx @@ -1,5 +1,4 @@ -import { Composition } from "remotion"; -import { Main } from "./MyComp/Main"; +import { Composition } from 'remotion'; import { COMP_NAME, defaultMyCompProps, @@ -7,8 +6,9 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from "../../types/constants"; -import { NextLogo } from "./MyComp/NextLogo"; +} from '../../types/constants'; +import { Main } from './MyComp/Main'; +import { NextLogo } from './MyComp/NextLogo'; export const RemotionRoot: React.FC = () => { return ( diff --git a/packages/template-next-pages/src/remotion/index.ts b/packages/template-next-pages/src/remotion/index.ts index f31c790edb3..91fa0f3468e 100644 --- a/packages/template-next-pages/src/remotion/index.ts +++ b/packages/template-next-pages/src/remotion/index.ts @@ -1,4 +1,4 @@ -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; +import { registerRoot } from 'remotion'; +import { RemotionRoot } from './Root'; registerRoot(RemotionRoot); diff --git a/packages/template-overlay/package.json b/packages/template-overlay/package.json index a978d156110..2341cf1e914 100644 --- a/packages/template-overlay/package.json +++ b/packages/template-overlay/package.json @@ -15,7 +15,7 @@ "@types/react": "19.2.7", "@types/web": "0.0.166", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "typescript": "5.9.3" }, "dependencies": { diff --git a/packages/template-overlay/src/Overlay.tsx b/packages/template-overlay/src/Overlay.tsx index 1930ec23682..310384ca904 100644 --- a/packages/template-overlay/src/Overlay.tsx +++ b/packages/template-overlay/src/Overlay.tsx @@ -1,29 +1,29 @@ +import { loadFont } from '@remotion/google-fonts/Roboto'; +import React, { useMemo } from 'react'; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; -import React, { useMemo } from "react"; -import { loadFont } from "@remotion/google-fonts/Roboto"; +} from 'remotion'; -const { fontFamily } = loadFont("normal", { - subsets: ["latin"], - weights: ["400", "700"], +const { fontFamily } = loadFont('normal', { + subsets: ['latin'], + weights: ['400', '700'], }); const title: React.CSSProperties = { fontFamily, fontSize: 80, - fontWeight: "bold", + fontWeight: 'bold', }; const text: React.CSSProperties = { - fontWeight: "bold", + fontWeight: 'bold', fontFamily, fontSize: 40, - color: "#4290F5", + color: '#4290F5', }; const disappearBeforeEnd = 20; @@ -54,8 +54,8 @@ export const Overlay: React.FC = () => { const container: React.CSSProperties = useMemo(() => { return { - position: "absolute", - backgroundColor: "white", + position: 'absolute', + backgroundColor: 'white', borderRadius: 25, right: 90, top: 90, diff --git a/packages/template-overlay/src/Root.tsx b/packages/template-overlay/src/Root.tsx index 984bc727ccb..8b8961d2919 100644 --- a/packages/template-overlay/src/Root.tsx +++ b/packages/template-overlay/src/Root.tsx @@ -1,5 +1,5 @@ -import { Composition } from "remotion"; -import { Overlay } from "./Overlay"; +import { Composition } from 'remotion'; +import { Overlay } from './Overlay'; export const RemotionRoot: React.FC = () => { return ( diff --git a/packages/template-overlay/src/index.ts b/packages/template-overlay/src/index.ts index f31c790edb3..91fa0f3468e 100644 --- a/packages/template-overlay/src/index.ts +++ b/packages/template-overlay/src/index.ts @@ -1,4 +1,4 @@ -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; +import { registerRoot } from 'remotion'; +import { RemotionRoot } from './Root'; registerRoot(RemotionRoot); diff --git a/packages/template-prompt-to-motion-graphics/package.json b/packages/template-prompt-to-motion-graphics/package.json index 0ddedad9287..de46719e996 100644 --- a/packages/template-prompt-to-motion-graphics/package.json +++ b/packages/template-prompt-to-motion-graphics/package.json @@ -72,7 +72,7 @@ "eslint": "9.19.0", "eslint-config-next": "15.1.6", "postcss": "8.4.47", - "prettier": "3.6.0", + "prettier": "3.8.1", "raw-loader": "^4.0.2", "tailwindcss": "4.0.3", "tw-animate-css": "1.4.0", diff --git a/packages/template-prompt-to-motion-graphics/src/app/api/generate/route.ts b/packages/template-prompt-to-motion-graphics/src/app/api/generate/route.ts index 679a5c78e7b..99e0257d8cb 100644 --- a/packages/template-prompt-to-motion-graphics/src/app/api/generate/route.ts +++ b/packages/template-prompt-to-motion-graphics/src/app/api/generate/route.ts @@ -1,12 +1,12 @@ -import { streamText, generateObject } from "ai"; -import { createOpenAI } from "@ai-sdk/openai"; -import { z } from "zod"; import { getCombinedSkillContent, SKILL_DETECTION_PROMPT, SKILL_NAMES, type SkillName, -} from "@/skills"; +} from '@/skills'; +import { createOpenAI } from '@ai-sdk/openai'; +import { generateObject, streamText } from 'ai'; +import { z } from 'zod'; const VALIDATION_PROMPT = `You are a prompt classifier for a motion graphics generation tool. @@ -144,12 +144,14 @@ If the user has made manual edits, preserve them unless explicitly asked to chan // Note: Using a flat object schema because OpenAI doesn't support discriminated unions const FollowUpResponseSchema = z.object({ type: z - .enum(["edit", "full"]) - .describe('Use "edit" for small targeted changes, "full" for major restructuring'), + .enum(['edit', 'full']) + .describe( + 'Use "edit" for small targeted changes, "full" for major restructuring', + ), summary: z .string() .describe( - "A brief 1-sentence summary of what changes were made, e.g. 'Changed background color to blue and increased font size'" + "A brief 1-sentence summary of what changes were made, e.g. 'Changed background color to blue and increased font size'", ), edits: z .array( @@ -157,21 +159,23 @@ const FollowUpResponseSchema = z.object({ description: z .string() .describe( - "Brief description of this edit, e.g. 'Update background color', 'Increase animation duration'" + "Brief description of this edit, e.g. 'Update background color', 'Increase animation duration'", ), old_string: z .string() - .describe("The exact string to find (must match exactly)"), - new_string: z.string().describe("The replacement string"), - }) + .describe('The exact string to find (must match exactly)'), + new_string: z.string().describe('The replacement string'), + }), ) .optional() - .describe("Required when type is 'edit': array of search-replace operations"), + .describe( + "Required when type is 'edit': array of search-replace operations", + ), code: z .string() .optional() .describe( - "Required when type is 'full': the complete replacement code starting with imports" + "Required when type is 'full': the complete replacement code starting with imports", ), }); @@ -186,13 +190,13 @@ type EditOperation = { function getLineNumber(code: string, searchString: string): number { const index = code.indexOf(searchString); if (index === -1) return -1; - return code.substring(0, index).split("\n").length; + return code.substring(0, index).split('\n').length; } // Apply edit operations to code and enrich with line numbers function applyEdits( code: string, - edits: EditOperation[] + edits: EditOperation[], ): { success: boolean; result: string; @@ -247,7 +251,7 @@ function applyEdits( } interface ConversationContextMessage { - role: "user" | "assistant"; + role: 'user' | 'assistant'; content: string; /** For user messages, attached images as base64 data URLs */ attachedImages?: string[]; @@ -284,7 +288,7 @@ interface GenerateResponse { summary: string; metadata: { skills: string[]; - editType: "tool_edit" | "full_replacement"; + editType: 'tool_edit' | 'full_replacement'; edits?: EditOperation[]; model: string; }; @@ -293,7 +297,7 @@ interface GenerateResponse { export async function POST(req: Request) { const { prompt, - model = "gpt-5.2", + model = 'gpt-5.2', currentCode, conversationHistory = [], isFollowUp = false, @@ -313,13 +317,13 @@ export async function POST(req: Request) { }), { status: 400, - headers: { "Content-Type": "application/json" }, + headers: { 'Content-Type': 'application/json' }, }, ); } // Parse model ID - format can be "model-name" or "model-name:reasoning_effort" - const [modelName, reasoningEffort] = model.split(":"); + const [modelName, reasoningEffort] = model.split(':'); const openai = createOpenAI({ apiKey }); @@ -327,7 +331,7 @@ export async function POST(req: Request) { if (!isFollowUp) { try { const validationResult = await generateObject({ - model: openai("gpt-5.2"), + model: openai('gpt-5.2'), system: VALIDATION_PROMPT, prompt: `User prompt: "${prompt}"`, schema: z.object({ valid: z.boolean() }), @@ -338,14 +342,14 @@ export async function POST(req: Request) { JSON.stringify({ error: "No valid motion graphics prompt. Please describe an animation or visual content you'd like to create.", - type: "validation", + type: 'validation', }), - { status: 400, headers: { "Content-Type": "application/json" } }, + { status: 400, headers: { 'Content-Type': 'application/json' } }, ); } } catch (validationError) { // On validation error, allow through rather than blocking - console.error("Validation error:", validationError); + console.error('Validation error:', validationError); } } @@ -353,7 +357,7 @@ export async function POST(req: Request) { let detectedSkills: SkillName[] = []; try { const skillResult = await generateObject({ - model: openai("gpt-5.2"), + model: openai('gpt-5.2'), system: SKILL_DETECTION_PROMPT, prompt: `User prompt: "${prompt}"`, schema: z.object({ @@ -361,16 +365,19 @@ export async function POST(req: Request) { }), }); detectedSkills = skillResult.object.skills; - console.log("Detected skills:", detectedSkills); + console.log('Detected skills:', detectedSkills); } catch (skillError) { - console.error("Skill detection error:", skillError); + console.error('Skill detection error:', skillError); } // Filter out skills that were already used in the conversation to avoid redundant context const newSkills = detectedSkills.filter( (skill) => !previouslyUsedSkills.includes(skill), ); - if (previouslyUsedSkills.length > 0 && newSkills.length < detectedSkills.length) { + if ( + previouslyUsedSkills.length > 0 && + newSkills.length < detectedSkills.length + ) { console.log( `Skipping ${detectedSkills.length - newSkills.length} previously used skills:`, detectedSkills.filter((s) => previouslyUsedSkills.includes(s)), @@ -388,27 +395,27 @@ export async function POST(req: Request) { try { // Build context for the edit request const contextMessages = conversationHistory.slice(-6); - let conversationContext = ""; + let conversationContext = ''; if (contextMessages.length > 0) { conversationContext = - "\n\n## RECENT CONVERSATION:\n" + + '\n\n## RECENT CONVERSATION:\n' + contextMessages .map((m) => { const imageNote = m.attachedImages && m.attachedImages.length > 0 - ? ` [with ${m.attachedImages.length} attached image${m.attachedImages.length > 1 ? "s" : ""}]` - : ""; + ? ` [with ${m.attachedImages.length} attached image${m.attachedImages.length > 1 ? 's' : ''}]` + : ''; return `${m.role.toUpperCase()}: ${m.content}${imageNote}`; }) - .join("\n"); + .join('\n'); } const manualEditNotice = hasManualEdits - ? "\n\nNOTE: The user has made manual edits to the code. Preserve these changes." - : ""; + ? '\n\nNOTE: The user has made manual edits to the code. Preserve these changes.' + : ''; // Error correction context for self-healing - let errorCorrectionNotice = ""; + let errorCorrectionNotice = ''; if (errorCorrection) { const failedEditInfo = errorCorrection.failedEdit ? ` @@ -419,9 +426,11 @@ The previous edit attempt failed. Here's what was tried: - Wanted to replace with: \`${errorCorrection.failedEdit.new_string}\` The old_string was either not found or matched multiple locations. You MUST include more surrounding context to make the match unique.` - : ""; + : ''; - const isEditFailure = errorCorrection.error.includes("Edit") && errorCorrection.error.includes("failed"); + const isEditFailure = + errorCorrection.error.includes('Edit') && + errorCorrection.error.includes('failed'); if (isEditFailure) { errorCorrectionNotice = ` @@ -463,35 +472,39 @@ ${errorCorrectionNotice} ## USER REQUEST: ${prompt} -${frameImages && frameImages.length > 0 ? `\n(See the attached ${frameImages.length === 1 ? "image" : "images"} for visual reference)` : ""} +${frameImages && frameImages.length > 0 ? `\n(See the attached ${frameImages.length === 1 ? 'image' : 'images'} for visual reference)` : ''} Analyze the request and decide: use targeted edits (type: "edit") for small changes, or full replacement (type: "full") for major restructuring.`; console.log( - "Follow-up edit with prompt:", + 'Follow-up edit with prompt:', prompt, - "model:", + 'model:', modelName, - "skills:", - detectedSkills.length > 0 ? detectedSkills.join(", ") : "general", - frameImages && frameImages.length > 0 ? `(with ${frameImages.length} image(s))` : "" + 'skills:', + detectedSkills.length > 0 ? detectedSkills.join(', ') : 'general', + frameImages && frameImages.length > 0 + ? `(with ${frameImages.length} image(s))` + : '', ); // Build messages array - include images if provided - const editMessageContent: Array<{ type: "text"; text: string } | { type: "image"; image: string }> = [ - { type: "text" as const, text: editPromptText }, - ]; + const editMessageContent: Array< + { type: 'text'; text: string } | { type: 'image'; image: string } + > = [{ type: 'text' as const, text: editPromptText }]; if (frameImages && frameImages.length > 0) { for (const img of frameImages) { - editMessageContent.push({ type: "image" as const, image: img }); + editMessageContent.push({ type: 'image' as const, image: img }); } } const editMessages: Array<{ - role: "user"; - content: Array<{ type: "text"; text: string } | { type: "image"; image: string }>; + role: 'user'; + content: Array< + { type: 'text'; text: string } | { type: 'image'; image: string } + >; }> = [ { - role: "user" as const, + role: 'user' as const, content: editMessageContent, }, ]; @@ -505,10 +518,10 @@ Analyze the request and decide: use targeted edits (type: "edit") for small chan const response = editResult.object; let finalCode: string; - let editType: "tool_edit" | "full_replacement"; + let editType: 'tool_edit' | 'full_replacement'; let appliedEdits: EditOperation[] | undefined; - if (response.type === "edit" && response.edits) { + if (response.type === 'edit' && response.edits) { // Apply the edits to the current code const result = applyEdits(currentCode, response.edits); if (!result.success) { @@ -516,30 +529,30 @@ Analyze the request and decide: use targeted edits (type: "edit") for small chan return new Response( JSON.stringify({ error: result.error, - type: "edit_failed", + type: 'edit_failed', failedEdit: result.failedEdit, }), - { status: 400, headers: { "Content-Type": "application/json" } } + { status: 400, headers: { 'Content-Type': 'application/json' } }, ); } finalCode = result.result; - editType = "tool_edit"; + editType = 'tool_edit'; // Use enriched edits with line numbers appliedEdits = result.enrichedEdits; console.log(`Applied ${response.edits.length} edit(s) successfully`); - } else if (response.type === "full" && response.code) { + } else if (response.type === 'full' && response.code) { // Full replacement finalCode = response.code; - editType = "full_replacement"; - console.log("Using full code replacement"); + editType = 'full_replacement'; + console.log('Using full code replacement'); } else { // Invalid response - missing required fields return new Response( JSON.stringify({ - error: "Invalid AI response: missing required fields", - type: "edit_failed", + error: 'Invalid AI response: missing required fields', + type: 'edit_failed', }), - { status: 400, headers: { "Content-Type": "application/json" } } + { status: 400, headers: { 'Content-Type': 'application/json' } }, ); } @@ -557,15 +570,15 @@ Analyze the request and decide: use targeted edits (type: "edit") for small chan return new Response(JSON.stringify(responseData), { status: 200, - headers: { "Content-Type": "application/json" }, + headers: { 'Content-Type': 'application/json' }, }); } catch (error) { - console.error("Error in follow-up edit:", error); + console.error('Error in follow-up edit:', error); return new Response( JSON.stringify({ - error: "Something went wrong while processing the edit request.", + error: 'Something went wrong while processing the edit request.', }), - { status: 500, headers: { "Content-Type": "application/json" } } + { status: 500, headers: { 'Content-Type': 'application/json' } }, ); } } @@ -575,24 +588,26 @@ Analyze the request and decide: use targeted edits (type: "edit") for small chan // Build messages for initial generation (supports image references) const hasImages = frameImages && frameImages.length > 0; const initialPromptText = hasImages - ? `${prompt}\n\n(See the attached ${frameImages.length === 1 ? "image" : "images"} for visual reference)` + ? `${prompt}\n\n(See the attached ${frameImages.length === 1 ? 'image' : 'images'} for visual reference)` : prompt; - const initialMessageContent: Array<{ type: "text"; text: string } | { type: "image"; image: string }> = [ - { type: "text" as const, text: initialPromptText }, - ]; + const initialMessageContent: Array< + { type: 'text'; text: string } | { type: 'image'; image: string } + > = [{ type: 'text' as const, text: initialPromptText }]; if (hasImages) { for (const img of frameImages) { - initialMessageContent.push({ type: "image" as const, image: img }); + initialMessageContent.push({ type: 'image' as const, image: img }); } } const initialMessages: Array<{ - role: "user"; - content: Array<{ type: "text"; text: string } | { type: "image"; image: string }>; + role: 'user'; + content: Array< + { type: 'text'; text: string } | { type: 'image'; image: string } + >; }> = [ { - role: "user" as const, + role: 'user' as const, content: initialMessageContent, }, ]; @@ -611,14 +626,14 @@ Analyze the request and decide: use targeted edits (type: "edit") for small chan }); console.log( - "Generating React component with prompt:", + 'Generating React component with prompt:', prompt, - "model:", + 'model:', modelName, - "skills:", - detectedSkills.length > 0 ? detectedSkills.join(", ") : "general", - reasoningEffort ? `reasoning_effort: ${reasoningEffort}` : "", - hasImages ? `(with ${frameImages.length} image(s))` : "" + 'skills:', + detectedSkills.length > 0 ? detectedSkills.join(', ') : 'general', + reasoningEffort ? `reasoning_effort: ${reasoningEffort}` : '', + hasImages ? `(with ${frameImages.length} image(s))` : '', ); // Get the original stream response @@ -628,7 +643,7 @@ Analyze the request and decide: use targeted edits (type: "edit") for small chan // Create metadata event to prepend const metadataEvent = `data: ${JSON.stringify({ - type: "metadata", + type: 'metadata', skills: detectedSkills, })}\n\n`; @@ -660,12 +675,12 @@ Analyze the request and decide: use targeted edits (type: "edit") for small chan headers: originalResponse.headers, }); } catch (error) { - console.error("Error generating code:", error); + console.error('Error generating code:', error); return new Response( JSON.stringify({ - error: "Something went wrong while trying to reach OpenAI APIs.", + error: 'Something went wrong while trying to reach OpenAI APIs.', }), - { status: 500, headers: { "Content-Type": "application/json" } } + { status: 500, headers: { 'Content-Type': 'application/json' } }, ); } } diff --git a/packages/template-prompt-to-motion-graphics/src/app/api/lambda/progress/route.ts b/packages/template-prompt-to-motion-graphics/src/app/api/lambda/progress/route.ts index 7f6fbcfcba4..91331ea7c05 100644 --- a/packages/template-prompt-to-motion-graphics/src/app/api/lambda/progress/route.ts +++ b/packages/template-prompt-to-motion-graphics/src/app/api/lambda/progress/route.ts @@ -1,11 +1,11 @@ import { - speculateFunctionName, AwsRegion, getRenderProgress, -} from "@remotion/lambda/client"; -import { DISK, RAM, REGION, TIMEOUT } from "../../../../../config.mjs"; -import { ProgressResponse, ProgressRequest } from "../../../../../types/schema"; -import { executeApi } from "../../../../helpers/api-response"; + speculateFunctionName, +} from '@remotion/lambda/client'; +import { DISK, RAM, REGION, TIMEOUT } from '../../../../../config.mjs'; +import { ProgressRequest, ProgressResponse } from '../../../../../types/schema'; +import { executeApi } from '../../../../helpers/api-response'; export const POST = executeApi( ProgressRequest, @@ -23,21 +23,21 @@ export const POST = executeApi( if (renderProgress.fatalErrorEncountered) { return { - type: "error", + type: 'error', message: renderProgress.errors[0].message, }; } if (renderProgress.done) { return { - type: "done", + type: 'done', url: renderProgress.outputFile as string, size: renderProgress.outputSizeInBytes as number, }; } return { - type: "progress", + type: 'progress', progress: Math.max(0.03, renderProgress.overallProgress), }; }, diff --git a/packages/template-prompt-to-motion-graphics/src/app/api/lambda/render/route.ts b/packages/template-prompt-to-motion-graphics/src/app/api/lambda/render/route.ts index f811700d134..a55e44be216 100644 --- a/packages/template-prompt-to-motion-graphics/src/app/api/lambda/render/route.ts +++ b/packages/template-prompt-to-motion-graphics/src/app/api/lambda/render/route.ts @@ -1,18 +1,19 @@ -import { AwsRegion, RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; import { + AwsRegion, renderMediaOnLambda, + RenderMediaOnLambdaOutput, speculateFunctionName, -} from "@remotion/lambda/client"; +} from '@remotion/lambda/client'; import { DISK, RAM, REGION, SITE_NAME, TIMEOUT, -} from "../../../../../config.mjs"; -import { COMP_NAME } from "../../../../../types/constants"; -import { RenderRequest } from "../../../../../types/schema"; -import { executeApi } from "../../../../helpers/api-response"; +} from '../../../../../config.mjs'; +import { COMP_NAME } from '../../../../../types/constants'; +import { RenderRequest } from '../../../../../types/schema'; +import { executeApi } from '../../../../helpers/api-response'; export const POST = executeApi( RenderRequest, @@ -22,7 +23,7 @@ export const POST = executeApi( !process.env.REMOTION_AWS_ACCESS_KEY_ID ) { throw new TypeError( - "Set up Remotion Lambda to render videos. See the README.md for how to do so.", + 'Set up Remotion Lambda to render videos. See the README.md for how to do so.', ); } if ( @@ -30,12 +31,12 @@ export const POST = executeApi( !process.env.REMOTION_AWS_SECRET_ACCESS_KEY ) { throw new TypeError( - "The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.", + 'The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.', ); } const result = await renderMediaOnLambda({ - codec: "h264", + codec: 'h264', functionName: speculateFunctionName({ diskSizeInMb: DISK, memorySizeInMb: RAM, @@ -47,8 +48,8 @@ export const POST = executeApi( inputProps: body.inputProps, framesPerLambda: 60, downloadBehavior: { - type: "download", - fileName: "video.mp4", + type: 'download', + fileName: 'video.mp4', }, }); diff --git a/packages/template-prompt-to-motion-graphics/src/app/code-examples/page.tsx b/packages/template-prompt-to-motion-graphics/src/app/code-examples/page.tsx index ff632082229..f6b5054f8a4 100644 --- a/packages/template-prompt-to-motion-graphics/src/app/code-examples/page.tsx +++ b/packages/template-prompt-to-motion-graphics/src/app/code-examples/page.tsx @@ -1,21 +1,21 @@ -"use client"; +'use client'; +import { ArrowLeft, PanelLeft, PanelLeftClose } from 'lucide-react'; +import Link from 'next/link'; +import { useRouter, useSearchParams } from 'next/navigation'; import { - useState, - useCallback, - useMemo, Suspense, + useCallback, useEffect, + useMemo, useRef, -} from "react"; -import Link from "next/link"; -import { useSearchParams, useRouter } from "next/navigation"; -import { ArrowLeft, PanelLeftClose, PanelLeft } from "lucide-react"; -import { examples, getExampleById } from "../../examples/code"; -import { useAnimationState } from "../../hooks/useAnimationState"; -import { CodeEditor } from "../../components/CodeEditor"; -import { AnimationPlayer } from "../../components/AnimationPlayer"; -import { Header } from "../../components/Header"; + useState, +} from 'react'; +import { AnimationPlayer } from '../../components/AnimationPlayer'; +import { CodeEditor } from '../../components/CodeEditor'; +import { Header } from '../../components/Header'; +import { examples, getExampleById } from '../../examples/code'; +import { useAnimationState } from '../../hooks/useAnimationState'; function DemoPageContent() { const searchParams = useSearchParams(); @@ -23,7 +23,7 @@ function DemoPageContent() { // Derive selected example directly from URL (single source of truth) const selectedExample = useMemo(() => { - const exampleId = searchParams.get("example"); + const exampleId = searchParams.get('example'); if (exampleId) { return getExampleById(exampleId) ?? examples[0]!; } @@ -31,7 +31,9 @@ function DemoPageContent() { }, [searchParams]); const [sidebarOpen, setSidebarOpen] = useState(true); - const [durationInFrames, setDurationInFrames] = useState(selectedExample.durationInFrames); + const [durationInFrames, setDurationInFrames] = useState( + selectedExample.durationInFrames, + ); const [fps, setFps] = useState(selectedExample.fps); const selectedButtonRef = useRef(null); @@ -42,8 +44,8 @@ function DemoPageContent() { useEffect(() => { if (selectedButtonRef.current) { selectedButtonRef.current.scrollIntoView({ - behavior: "smooth", - block: "nearest", + behavior: 'smooth', + block: 'nearest', }); } }, [selectedExample.id]); @@ -89,7 +91,9 @@ function DemoPageContent() {
-

Example Gallery

+

+ Example Gallery +

{/* Main content with sidebar */} @@ -97,11 +101,11 @@ function DemoPageContent() { {/* Sidebar */}
{categories.map((category) => (
@@ -122,8 +126,8 @@ function DemoPageContent() { onClick={() => handleExampleSelect(example.id)} className={`w-full text-left p-3 rounded-lg border transition-all ${ selectedExample.id === example.id - ? "border-primary bg-primary/10 text-foreground" - : "border-border-dim bg-muted text-gray-400 hover:border-border hover:bg-background-elevated" + ? 'border-primary bg-primary/10 text-foreground' + : 'border-border-dim bg-muted text-gray-400 hover:border-border hover:bg-background-elevated' }`} >
@@ -146,7 +150,7 @@ function DemoPageContent() { ; } - if (state.status !== "done") { - throw new Error("Download button should not be rendered when not done"); + if (state.status !== 'done') { + throw new Error('Download button should not be rendered when not done'); } return ( diff --git a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/Error.tsx b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/Error.tsx index 1eb512da59e..799fd7c23c3 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/Error.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/Error.tsx @@ -1,10 +1,10 @@ -import React from "react"; -import { ErrorDisplay } from "@/components/ErrorDisplay"; +import { ErrorDisplay } from '@/components/ErrorDisplay'; +import React from 'react'; const isLambdaNotConfiguredError = (message: string): boolean => { return ( - message.includes("Set up Remotion Lambda") || - message.includes("Function not found:") + message.includes('Set up Remotion Lambda') || + message.includes('Function not found:') ); }; @@ -34,11 +34,6 @@ export const ErrorComp: React.FC<{ } return ( - + ); }; diff --git a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/ProgressBar.tsx b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/ProgressBar.tsx index 2b1a06d3924..b476292d3dd 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/ProgressBar.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/ProgressBar.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; export const ProgressBar: React.FC<{ progress: number; diff --git a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/index.tsx b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/index.tsx index c8aa0ca11af..1b40b5e949f 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/index.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/RenderControls/index.tsx @@ -1,12 +1,12 @@ -"use client"; +'use client'; -import { useEffect, useRef } from "react"; -import { Download } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { ErrorComp } from "./Error"; -import { ProgressBar } from "./ProgressBar"; -import { DownloadButton } from "./DownloadButton"; -import { useRendering } from "../../../helpers/use-rendering"; +import { Button } from '@/components/ui/button'; +import { Download } from 'lucide-react'; +import { useEffect, useRef } from 'react'; +import { useRendering } from '../../../helpers/use-rendering'; +import { DownloadButton } from './DownloadButton'; +import { ErrorComp } from './Error'; +import { ProgressBar } from './ProgressBar'; export const RenderControls: React.FC<{ code: string; @@ -28,41 +28,41 @@ export const RenderControls: React.FC<{ prev.durationInFrames !== durationInFrames || prev.fps !== fps; - if (hasChanged && state.status !== "init") { + if (hasChanged && state.status !== 'init') { undo(); } previousPropsRef.current = { code, durationInFrames, fps }; }, [code, durationInFrames, fps, state.status, undo]); if ( - state.status === "init" || - state.status === "invoking" || - state.status === "error" + state.status === 'init' || + state.status === 'invoking' || + state.status === 'error' ) { return (
- {state.status === "error" && ( + {state.status === 'error' && ( )}
); } - if (state.status === "rendering") { + if (state.status === 'rendering') { return ; } - if (state.status === "done") { + if (state.status === 'done') { return ; } diff --git a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/SettingsModal.tsx b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/SettingsModal.tsx index 9e04ca8744e..11832ac599d 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/SettingsModal.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/AnimationPlayer/SettingsModal.tsx @@ -1,17 +1,17 @@ -"use client"; +'use client'; -import { useState, useEffect } from "react"; +import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, + DialogFooter, DialogHeader, DialogTitle, DialogTrigger, - DialogFooter, -} from "@/components/ui/dialog"; -import { Settings } from "lucide-react"; -import { Button } from "@/components/ui/button"; +} from '@/components/ui/dialog'; +import { Settings } from 'lucide-react'; +import { useEffect, useState } from 'react'; interface SettingsModalProps { durationInFrames: number; @@ -78,7 +78,10 @@ export function SettingsModal({

Animation

-
- + = ({ return (
-
- {renderContent()} -
+
{renderContent()}
); }; diff --git a/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatHistory.tsx b/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatHistory.tsx index ee1466566dc..645b6d99edf 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatHistory.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatHistory.tsx @@ -1,13 +1,13 @@ -"use client"; +'use client'; -import { useRef, useEffect } from "react"; -import { AlertTriangle, FileCode, PenLine, BookOpen } from "lucide-react"; import { Tooltip, TooltipContent, TooltipTrigger, -} from "@/components/ui/tooltip"; -import type { ConversationMessage } from "@/types/conversation"; +} from '@/components/ui/tooltip'; +import type { ConversationMessage } from '@/types/conversation'; +import { AlertTriangle, BookOpen, FileCode, PenLine } from 'lucide-react'; +import { useEffect, useRef } from 'react'; interface ChatHistoryProps { messages: ConversationMessage[]; @@ -17,15 +17,12 @@ interface ChatHistoryProps { }; } -export function ChatHistory({ - messages, - pendingMessage, -}: ChatHistoryProps) { +export function ChatHistory({ messages, pendingMessage }: ChatHistoryProps) { const messagesEndRef = useRef(null); // Auto-scroll to bottom when messages change useEffect(() => { - messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }); + messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }); }, [messages]); return ( @@ -40,13 +37,13 @@ export function ChatHistory({ } function ChatMessage({ message }: { message: ConversationMessage }) { - const isUser = message.role === "user"; - const isError = message.role === "error"; + const isUser = message.role === 'user'; + const isError = message.role === 'error'; const metadata = message.metadata; const time = new Date(message.timestamp).toLocaleTimeString([], { - hour: "numeric", - minute: "2-digit", + hour: 'numeric', + minute: '2-digit', }); if (isUser) { @@ -78,11 +75,11 @@ function ChatMessage({ message }: { message: ConversationMessage }) { if (isError) { const errorLabel = - message.errorType === "api" - ? "API Error" - : message.errorType === "validation" - ? "Validation Error" - : "Edit Failed"; + message.errorType === 'api' + ? 'API Error' + : message.errorType === 'validation' + ? 'Validation Error' + : 'Edit Failed'; return (
@@ -115,13 +112,13 @@ function ChatMessage({ message }: { message: ConversationMessage }) { - Skills used: {metadata.skills.join(", ")} + Skills used: {metadata.skills.join(', ')} )}
- {metadata?.editType === "tool_edit" && metadata.edits && ( + {metadata?.editType === 'tool_edit' && metadata.edits && (
{metadata.edits.map((edit, i) => (
@@ -141,7 +138,7 @@ function ChatMessage({ message }: { message: ConversationMessage }) {
)} - {metadata?.editType === "full_replacement" && ( + {metadata?.editType === 'full_replacement' && (
Full code rewrite @@ -170,7 +167,7 @@ function PendingMessage({ skills }: { skills?: string[] }) { - Skills used: {skills.join(", ")} + Skills used: {skills.join(', ')} )} diff --git a/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatInput.tsx b/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatInput.tsx index dba0ddbf50a..c3a7545386f 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatInput.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatInput.tsx @@ -1,19 +1,19 @@ -"use client"; +'use client'; -import { useState, useEffect, type ComponentType } from "react"; -import { ArrowUp, Camera, X, Paperclip } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { ErrorDisplay } from "@/components/ErrorDisplay"; +import { ErrorDisplay } from '@/components/ErrorDisplay'; +import { Button } from '@/components/ui/button'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from "@/components/ui/select"; -import { type ModelId, MODELS } from "@/types/generation"; -import { captureFrame } from "@/helpers/capture-frame"; -import { useImageAttachments } from "@/hooks/useImageAttachments"; +} from '@/components/ui/select'; +import { captureFrame } from '@/helpers/capture-frame'; +import { useImageAttachments } from '@/hooks/useImageAttachments'; +import { MODELS, type ModelId } from '@/types/generation'; +import { ArrowUp, Camera, Paperclip, X } from 'lucide-react'; +import { useEffect, useState, type ComponentType } from 'react'; interface ChatInputProps { prompt: string; @@ -76,7 +76,7 @@ export function ChatInput({ const handleKeyDown = (e: React.KeyboardEvent) => { // Submit on Enter (Shift+Enter for new line) - if (e.key === "Enter" && !e.shiftKey) { + if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit(e); } @@ -95,7 +95,7 @@ export function ChatInput({ }); addImages([base64]); } catch (error) { - console.error("Failed to capture frame:", error); + console.error('Failed to capture frame:', error); } finally { setIsCapturing(false); } @@ -108,7 +108,7 @@ export function ChatInput({
{/* Hidden file input */} diff --git a/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatSidebar.tsx b/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatSidebar.tsx index 1d2e3866394..465344fb055 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatSidebar.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ChatSidebar/ChatSidebar.tsx @@ -1,32 +1,32 @@ -"use client"; +'use client'; -import { - useState, - forwardRef, - useImperativeHandle, - useRef, - useEffect, - type ComponentType, -} from "react"; -import { PanelLeftClose, PanelLeftOpen, RotateCcw } from "lucide-react"; -import { Button } from "@/components/ui/button"; -import { cn } from "@/lib/utils"; +import { Button } from '@/components/ui/button'; +import { useGenerationApi } from '@/hooks/useGenerationApi'; +import { cn } from '@/lib/utils'; import type { - ConversationMessage, - ConversationContextMessage, AssistantMetadata, - ErrorCorrectionContext, + ConversationContextMessage, + ConversationMessage, EditOperation, -} from "@/types/conversation"; + ErrorCorrectionContext, +} from '@/types/conversation'; import { - type StreamPhase, + MODELS, type GenerationErrorType, type ModelId, - MODELS, -} from "@/types/generation"; -import { ChatInput } from "./ChatInput"; -import { ChatHistory } from "./ChatHistory"; -import { useGenerationApi } from "@/hooks/useGenerationApi"; + type StreamPhase, +} from '@/types/generation'; +import { PanelLeftClose, PanelLeftOpen, RotateCcw } from 'lucide-react'; +import { + forwardRef, + useEffect, + useImperativeHandle, + useRef, + useState, + type ComponentType, +} from 'react'; +import { ChatHistory } from './ChatHistory'; +import { ChatInput } from './ChatInput'; export interface ChatSidebarRef { triggerGeneration: (options?: { @@ -67,7 +67,7 @@ interface ChatSidebarProps { ) => void; onErrorMessage?: ( message: string, - errorType: "edit_failed" | "api" | "validation", + errorType: 'edit_failed' | 'api' | 'validation', ) => void; errorCorrection?: ErrorCorrectionContext; onPendingMessage?: (skills?: string[]) => void; @@ -111,7 +111,7 @@ export const ChatSidebar = forwardRef( ref, ) { const [model, setModel] = useState(MODELS[1].id); - const promptRef = useRef(""); + const promptRef = useRef(''); const { isLoading, runGeneration } = useGenerationApi(); @@ -127,7 +127,7 @@ export const ChatSidebar = forwardRef( const currentPrompt = promptRef.current; if (!currentPrompt.trim()) return; - onPromptChange(""); // Clear input immediately + onPromptChange(''); // Clear input immediately await runGeneration( currentPrompt, @@ -164,10 +164,10 @@ export const ChatSidebar = forwardRef( return (
{isCollapsed ? ( @@ -196,10 +196,10 @@ export const ChatSidebar = forwardRef( onClick={() => { if ( window.confirm( - "Start over? This will reset your animation.", + 'Start over? This will reset your animation.', ) ) { - window.location.href = "/"; + window.location.href = '/'; } }} title="Start over" @@ -220,10 +220,7 @@ export const ChatSidebar = forwardRef(
{/* Messages */} - + {/* Input */} import("@monaco-editor/react"), { +const MonacoEditor = dynamic(() => import('@monaco-editor/react'), { ssr: false, loading: () => (
@@ -22,7 +22,7 @@ const MonacoEditor = dynamic(() => import("@monaco-editor/react"), { ), }); -type StreamPhase = "idle" | "reasoning" | "generating"; +type StreamPhase = 'idle' | 'reasoning' | 'generating'; interface CodeEditorProps { code: string; @@ -35,7 +35,7 @@ export const CodeEditor: React.FC = ({ code, onChange, isStreaming = false, - streamPhase = "idle", + streamPhase = 'idle', }) => { const monacoRef = useRef(null); const editorRef = useRef(null); @@ -47,7 +47,7 @@ export const CodeEditor: React.FC = ({ }, [isStreaming]); // Use typescript for semantic checking, plaintext during streaming - const editorLanguage = isStreaming ? "plaintext" : "typescript"; + const editorLanguage = isStreaming ? 'plaintext' : 'typescript'; // Continuously clear markers while streaming useEffect(() => { @@ -55,9 +55,9 @@ export const CodeEditor: React.FC = ({ const clearAllMarkers = () => { monacoRef.current?.editor.getModels().forEach((model) => { - monacoRef.current?.editor.setModelMarkers(model, "javascript", []); - monacoRef.current?.editor.setModelMarkers(model, "typescript", []); - monacoRef.current?.editor.setModelMarkers(model, "owner", []); + monacoRef.current?.editor.setModelMarkers(model, 'javascript', []); + monacoRef.current?.editor.setModelMarkers(model, 'typescript', []); + monacoRef.current?.editor.setModelMarkers(model, 'owner', []); }); }; @@ -158,7 +158,7 @@ export const CodeEditor: React.FC = ({ } } `, - "react.d.ts", + 'react.d.ts', ); // Add module declaration for 'react' to allow imports @@ -171,7 +171,7 @@ export const CodeEditor: React.FC = ({ export const useRef: typeof React.useRef; export default React; }`, - "react-module.d.ts", + 'react-module.d.ts', ); // Add type declarations for all whitelisted libraries @@ -184,7 +184,7 @@ export const CodeEditor: React.FC = ({ export function spring(options: { frame: number; fps: number; config?: any; durationInFrames?: number }): number; export const Sequence: React.FC<{ from?: number; durationInFrames?: number; children: React.ReactNode }>; }`, - "remotion.d.ts", + 'remotion.d.ts', ); ts?.typescriptDefaults?.addExtraLib( @@ -202,14 +202,14 @@ export const CodeEditor: React.FC = ({ export const Polygon: React.FC; export const Ellipse: React.FC; }`, - "remotion-shapes.d.ts", + 'remotion-shapes.d.ts', ); ts?.typescriptDefaults?.addExtraLib( `declare module '@remotion/lottie' { export const Lottie: React.FC<{ animationData?: any; src?: string; playbackRate?: number; style?: React.CSSProperties }>; }`, - "remotion-lottie.d.ts", + 'remotion-lottie.d.ts', ); ts?.typescriptDefaults?.addExtraLib( @@ -224,7 +224,7 @@ export const CodeEditor: React.FC = ({ [key: string]: any; }>; }`, - "remotion-three.d.ts", + 'remotion-three.d.ts', ); ts?.typescriptDefaults?.addExtraLib( @@ -237,7 +237,7 @@ export const CodeEditor: React.FC = ({ export class Mesh { constructor(geometry?: any, material?: any); position: Vector3; rotation: Vector3; } export const DoubleSide: number; }`, - "three.d.ts", + 'three.d.ts', ); // Override marker setting to suppress during streaming @@ -265,7 +265,7 @@ export const CodeEditor: React.FC = ({ // Simple pass-through: code is displayed and edited as-is const handleChange = (value: string | undefined) => { - onChange(value || ""); + onChange(value || ''); }; return ( @@ -276,7 +276,7 @@ export const CodeEditor: React.FC = ({ = ({ options={{ minimap: { enabled: false }, fontSize: 14, - lineNumbers: "on", + lineNumbers: 'on', scrollBeyondLastLine: false, automaticLayout: true, tabSize: 2, - wordWrap: "on", + wordWrap: 'on', padding: { top: 16 }, glyphMargin: false, lineNumbersMinChars: 3, diff --git a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/CopyButton.tsx b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/CopyButton.tsx index 97d1e6c5895..9c46f768c72 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/CopyButton.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/CopyButton.tsx @@ -1,7 +1,7 @@ -"use client"; +'use client'; -import React, { useState } from "react"; -import { Copy, Check } from "lucide-react"; +import { Check, Copy } from 'lucide-react'; +import React, { useState } from 'react'; interface CopyButtonProps { text: string; @@ -22,7 +22,7 @@ export const CopyButton: React.FC = ({ text, className }) => { onClick={handleCopy} className={ className ?? - "flex items-center gap-1.5 px-2 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-accent rounded transition-colors" + 'flex items-center gap-1.5 px-2 py-1 text-xs text-muted-foreground hover:text-foreground hover:bg-accent rounded transition-colors' } > {copied ? ( diff --git a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/EditorHeader.tsx b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/EditorHeader.tsx index 053e91f1965..bb6eb19cf94 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/EditorHeader.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/EditorHeader.tsx @@ -1,7 +1,7 @@ -"use client"; +'use client'; -import React from "react"; -import { CopyButton } from "./CopyButton"; +import React from 'react'; +import { CopyButton } from './CopyButton'; interface EditorHeaderProps { filename: string; @@ -14,7 +14,9 @@ export const EditorHeader: React.FC = ({ }) => { return (
- {filename} + + {filename} +
); diff --git a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/StreamingOverlay.tsx b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/StreamingOverlay.tsx index adb97fbf263..78a164d7859 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/StreamingOverlay.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/StreamingOverlay.tsx @@ -1,6 +1,6 @@ -"use client"; +'use client'; -import React from "react"; +import React from 'react'; interface StreamingOverlayProps { visible: boolean; @@ -9,7 +9,7 @@ interface StreamingOverlayProps { export const StreamingOverlay: React.FC = ({ visible, - message = "Generating code...", + message = 'Generating code...', }) => { if (!visible) return null; diff --git a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/index.ts b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/index.ts index a2fc417c8b4..9f6648589e9 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/index.ts +++ b/packages/template-prompt-to-motion-graphics/src/components/CodeEditor/index.ts @@ -1 +1 @@ -export { CodeEditor } from "./CodeEditor"; +export { CodeEditor } from './CodeEditor'; diff --git a/packages/template-prompt-to-motion-graphics/src/components/ErrorDisplay.tsx b/packages/template-prompt-to-motion-graphics/src/components/ErrorDisplay.tsx index 001a1820e15..d9daf05df2b 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ErrorDisplay.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ErrorDisplay.tsx @@ -1,13 +1,13 @@ -"use client"; +'use client'; -import React from "react"; -import { Alert, AlertTitle, AlertDescription } from "@/components/ui/alert"; -import { Button } from "@/components/ui/button"; -import { AlertCircle, X } from "lucide-react"; -import { cn } from "@/lib/utils"; +import { Alert, AlertDescription, AlertTitle } from '@/components/ui/alert'; +import { Button } from '@/components/ui/button'; +import { cn } from '@/lib/utils'; +import { AlertCircle, X } from 'lucide-react'; +import React from 'react'; -export type ErrorVariant = "inline" | "card" | "fullscreen"; -export type ErrorSize = "sm" | "md" | "lg"; +export type ErrorVariant = 'inline' | 'card' | 'fullscreen'; +export type ErrorSize = 'sm' | 'md' | 'lg'; interface ErrorDisplayProps { error: string; @@ -19,24 +19,35 @@ interface ErrorDisplayProps { className?: string; } -const sizeStyles: Record = { - sm: { icon: "h-3 w-3", title: "text-xs", description: "text-xs" }, - md: { icon: "h-4 w-4", title: "text-sm font-semibold", description: "text-sm" }, - lg: { icon: "h-5 w-5", title: "text-base font-semibold", description: "text-base" }, +const sizeStyles: Record< + ErrorSize, + { icon: string; title: string; description: string } +> = { + sm: { icon: 'h-3 w-3', title: 'text-xs', description: 'text-xs' }, + md: { + icon: 'h-4 w-4', + title: 'text-sm font-semibold', + description: 'text-sm', + }, + lg: { + icon: 'h-5 w-5', + title: 'text-base font-semibold', + description: 'text-base', + }, }; export const ErrorDisplay: React.FC = ({ error, title, - variant = "card", - size = "md", + variant = 'card', + size = 'md', onDismiss, children, className, }) => { const styles = sizeStyles[size]; - if (variant === "fullscreen") { + if (variant === 'fullscreen') { return (
@@ -57,10 +68,15 @@ export const ErrorDisplay: React.FC = ({ ); } - if (variant === "inline") { + if (variant === 'inline') { return ( - - {error} + + + {error} + {onDismiss && (
); diff --git a/packages/template-prompt-to-motion-graphics/src/components/ui/alert.tsx b/packages/template-prompt-to-motion-graphics/src/components/ui/alert.tsx index 0dfb59c616f..1a23c56a1cc 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ui/alert.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ui/alert.tsx @@ -1,29 +1,29 @@ -import * as React from "react" -import { cva, type VariantProps } from "class-variance-authority" +import { cva, type VariantProps } from 'class-variance-authority'; +import * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; const alertVariants = cva( - "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", + 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current', { variants: { variant: { - default: "bg-card text-card-foreground", + default: 'bg-card text-card-foreground', destructive: - "text-destructive bg-destructive/10 border-destructive/50 [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90", + 'text-destructive bg-destructive/10 border-destructive/50 [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90', }, }, defaultVariants: { - variant: "default", + variant: 'default', }, - } -) + }, +); function Alert({ className, variant, ...props -}: React.ComponentProps<"div"> & VariantProps) { +}: React.ComponentProps<'div'> & VariantProps) { return (
- ) + ); } -function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { +function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { return (
- ) + ); } function AlertDescription({ className, ...props -}: React.ComponentProps<"div">) { +}: React.ComponentProps<'div'>) { return (
- ) + ); } -export { Alert, AlertTitle, AlertDescription } +export { Alert, AlertDescription, AlertTitle }; diff --git a/packages/template-prompt-to-motion-graphics/src/components/ui/button.tsx b/packages/template-prompt-to-motion-graphics/src/components/ui/button.tsx index 25c404885d3..be050c997bc 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ui/button.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ui/button.tsx @@ -1,38 +1,39 @@ -import * as React from "react" -import { Slot } from "@radix-ui/react-slot" -import { cva, type VariantProps } from "class-variance-authority" +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; +import * as React from 'react'; -import { cn } from "@/lib/utils" -import { Spinner } from "./spinner" +import { cn } from '@/lib/utils'; +import { Spinner } from './spinner'; const buttonVariants = cva( "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all cursor-pointer disabled:pointer-events-none disabled:opacity-50 disabled:cursor-not-allowed [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 aria-invalid:border-destructive", { variants: { variant: { - default: "bg-primary text-primary-foreground hover:bg-primary-hover", - destructive: "bg-destructive text-foreground hover:bg-destructive/90", + default: 'bg-primary text-primary-foreground hover:bg-primary-hover', + destructive: 'bg-destructive text-foreground hover:bg-destructive/90', outline: - "border border-border bg-transparent text-foreground hover:bg-accent", - secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80", - ghost: "text-foreground hover:bg-accent", - link: "text-primary underline-offset-4 hover:underline", + 'border border-border bg-transparent text-foreground hover:bg-accent', + secondary: + 'bg-secondary text-secondary-foreground hover:bg-secondary/80', + ghost: 'text-foreground hover:bg-accent', + link: 'text-primary underline-offset-4 hover:underline', }, size: { - default: "h-10 px-4 py-2", - sm: "h-8 rounded-md gap-1.5 px-3", - lg: "h-11 rounded-md px-6", - icon: "size-10", - "icon-sm": "size-8", - "icon-lg": "size-11", + default: 'h-10 px-4 py-2', + sm: 'h-8 rounded-md gap-1.5 px-3', + lg: 'h-11 rounded-md px-6', + icon: 'size-10', + 'icon-sm': 'size-8', + 'icon-lg': 'size-11', }, }, defaultVariants: { - variant: "default", - size: "default", + variant: 'default', + size: 'default', }, - } -) + }, +); function Button({ className, @@ -42,12 +43,12 @@ function Button({ loading = false, children, ...props -}: React.ComponentProps<"button"> & +}: React.ComponentProps<'button'> & VariantProps & { - asChild?: boolean - loading?: boolean + asChild?: boolean; + loading?: boolean; }) { - const Comp = asChild ? Slot : "button" + const Comp = asChild ? Slot : 'button'; return ( {loading ? : children} - ) + ); } -export { Button, buttonVariants } +export { Button, buttonVariants }; diff --git a/packages/template-prompt-to-motion-graphics/src/components/ui/dialog.tsx b/packages/template-prompt-to-motion-graphics/src/components/ui/dialog.tsx index d9ccec91d22..485db538a93 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ui/dialog.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ui/dialog.tsx @@ -1,33 +1,33 @@ -"use client" +'use client'; -import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { XIcon } from "lucide-react" +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { XIcon } from 'lucide-react'; +import * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; function Dialog({ ...props }: React.ComponentProps) { - return + return ; } function DialogTrigger({ ...props }: React.ComponentProps) { - return + return ; } function DialogPortal({ ...props }: React.ComponentProps) { - return + return ; } function DialogClose({ ...props }: React.ComponentProps) { - return + return ; } function DialogOverlay({ @@ -38,12 +38,12 @@ function DialogOverlay({ - ) + ); } function DialogContent({ @@ -52,7 +52,7 @@ function DialogContent({ showCloseButton = true, ...props }: React.ComponentProps & { - showCloseButton?: boolean + showCloseButton?: boolean; }) { return ( @@ -60,8 +60,8 @@ function DialogContent({ @@ -77,30 +77,30 @@ function DialogContent({ )} - ) + ); } -function DialogHeader({ className, ...props }: React.ComponentProps<"div">) { +function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) { return (
- ) + ); } -function DialogFooter({ className, ...props }: React.ComponentProps<"div">) { +function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) { return (
- ) + ); } function DialogTitle({ @@ -110,10 +110,10 @@ function DialogTitle({ return ( - ) + ); } function DialogDescription({ @@ -123,10 +123,10 @@ function DialogDescription({ return ( - ) + ); } export { @@ -140,4 +140,4 @@ export { DialogPortal, DialogTitle, DialogTrigger, -} +}; diff --git a/packages/template-prompt-to-motion-graphics/src/components/ui/select.tsx b/packages/template-prompt-to-motion-graphics/src/components/ui/select.tsx index a1405e916b5..39a9dc4bac2 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ui/select.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ui/select.tsx @@ -1,36 +1,36 @@ -"use client" +'use client'; -import * as React from "react" -import * as SelectPrimitive from "@radix-ui/react-select" -import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react" +import * as SelectPrimitive from '@radix-ui/react-select'; +import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react'; +import * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; function Select({ ...props }: React.ComponentProps) { - return + return ; } function SelectGroup({ ...props }: React.ComponentProps) { - return + return ; } function SelectValue({ ...props }: React.ComponentProps) { - return + return ; } function SelectTrigger({ className, - size = "default", + size = 'default', children, ...props }: React.ComponentProps & { - size?: "sm" | "default" + size?: 'sm' | 'default'; }) { return ( @@ -47,14 +47,14 @@ function SelectTrigger({ - ) + ); } function SelectContent({ className, children, - position = "popper", - align = "center", + position = 'popper', + align = 'center', ...props }: React.ComponentProps) { return ( @@ -62,10 +62,10 @@ function SelectContent({ {children} @@ -84,7 +84,7 @@ function SelectContent({ - ) + ); } function SelectLabel({ @@ -94,10 +94,10 @@ function SelectLabel({ return ( - ) + ); } function SelectItem({ @@ -110,7 +110,7 @@ function SelectItem({ data-slot="select-item" className={cn( "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2", - className + className, )} {...props} > @@ -121,7 +121,7 @@ function SelectItem({ {children} - ) + ); } function SelectSeparator({ @@ -131,10 +131,10 @@ function SelectSeparator({ return ( - ) + ); } function SelectScrollUpButton({ @@ -145,14 +145,14 @@ function SelectScrollUpButton({ - ) + ); } function SelectScrollDownButton({ @@ -163,14 +163,14 @@ function SelectScrollDownButton({ - ) + ); } export { @@ -184,4 +184,4 @@ export { SelectSeparator, SelectTrigger, SelectValue, -} +}; diff --git a/packages/template-prompt-to-motion-graphics/src/components/ui/spinner.tsx b/packages/template-prompt-to-motion-graphics/src/components/ui/spinner.tsx index a70e713c5b4..178210cd5ce 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ui/spinner.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ui/spinner.tsx @@ -1,16 +1,16 @@ -import { Loader2Icon } from "lucide-react" +import { Loader2Icon } from 'lucide-react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -function Spinner({ className, ...props }: React.ComponentProps<"svg">) { +function Spinner({ className, ...props }: React.ComponentProps<'svg'>) { return ( - ) + ); } -export { Spinner } +export { Spinner }; diff --git a/packages/template-prompt-to-motion-graphics/src/components/ui/tooltip.tsx b/packages/template-prompt-to-motion-graphics/src/components/ui/tooltip.tsx index a4e90d4e9af..f36e6fa5501 100644 --- a/packages/template-prompt-to-motion-graphics/src/components/ui/tooltip.tsx +++ b/packages/template-prompt-to-motion-graphics/src/components/ui/tooltip.tsx @@ -1,9 +1,9 @@ -"use client" +'use client'; -import * as React from "react" -import * as TooltipPrimitive from "@radix-ui/react-tooltip" +import * as TooltipPrimitive from '@radix-ui/react-tooltip'; +import * as React from 'react'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; function TooltipProvider({ delayDuration = 0, @@ -15,7 +15,7 @@ function TooltipProvider({ delayDuration={delayDuration} {...props} /> - ) + ); } function Tooltip({ @@ -25,13 +25,13 @@ function Tooltip({ - ) + ); } function TooltipTrigger({ ...props }: React.ComponentProps) { - return + return ; } function TooltipContent({ @@ -46,8 +46,8 @@ function TooltipContent({ data-slot="tooltip-content" sideOffset={sideOffset} className={cn( - "bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", - className + 'bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance', + className, )} {...props} > @@ -55,7 +55,7 @@ function TooltipContent({ - ) + ); } -export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } +export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger }; diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/animated-shapes.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/animated-shapes.ts index a56046d805e..70a770f6eab 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/animated-shapes.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/animated-shapes.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const animatedShapesCode = `import { AbsoluteFill, useCurrentFrame, useVideoConfig, spring, interpolate } from "remotion"; import { Circle, Triangle, Rect, Star } from "@remotion/shapes"; @@ -83,10 +83,10 @@ export const MyAnimation = () => { };`; export const animatedShapesExample: RemotionExample = { - id: "animated-shapes", - name: "Animated Shapes", - description: "Bouncing and rotating SVG shapes with spring animations", - category: "Other", + id: 'animated-shapes', + name: 'Animated Shapes', + description: 'Bouncing and rotating SVG shapes with spring animations', + category: 'Other', durationInFrames: 180, fps: 30, code: animatedShapesCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/falling-spheres.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/falling-spheres.ts index 0abe54873e6..b954d528aef 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/falling-spheres.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/falling-spheres.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const fallingSpheresCode = `import { AbsoluteFill, useCurrentFrame, useVideoConfig } from "remotion"; import { ThreeCanvas } from "@remotion/three"; @@ -106,10 +106,10 @@ export const MyAnimation = () => { };`; export const fallingSpheresExample: RemotionExample = { - id: "falling-spheres", - name: "Golden Bouncing Spheres", - description: "Glowing golden spheres with physics and orbiting camera", - category: "3D", + id: 'falling-spheres', + name: 'Golden Bouncing Spheres', + description: 'Glowing golden spheres with physics and orbiting camera', + category: '3D', durationInFrames: 450, fps: 60, code: fallingSpheresCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/gold-price-chart.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/gold-price-chart.ts index 5f114149b79..ba58ae84de8 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/gold-price-chart.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/gold-price-chart.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const goldPriceChartCode = `import { useCurrentFrame, useVideoConfig, AbsoluteFill, spring } from "remotion"; @@ -185,10 +185,11 @@ export const MyAnimation = () => { };`; export const goldPriceChartExample: RemotionExample = { - id: "gold-price-chart", - name: "Gold Price Chart", - description: "Animated bar chart with Y-axis labels and staggered spring animations", - category: "Charts", + id: 'gold-price-chart', + name: 'Gold Price Chart', + description: + 'Animated bar chart with Y-axis labels and staggered spring animations', + category: 'Charts', durationInFrames: 150, fps: 30, code: goldPriceChartCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/histogram.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/histogram.ts index 0f855cef1af..a9ec45b3683 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/histogram.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/histogram.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const histogramCode = `import { AbsoluteFill, useCurrentFrame, useVideoConfig, spring } from "remotion"; import { Rect } from "@remotion/shapes"; @@ -93,10 +93,10 @@ export const MyAnimation = () => { };`; export const histogramExample: RemotionExample = { - id: "histogram", - name: "Histogram", - description: "Animated bar chart using @remotion/shapes", - category: "Charts", + id: 'histogram', + name: 'Histogram', + description: 'Animated bar chart using @remotion/shapes', + category: 'Charts', durationInFrames: 120, fps: 30, code: histogramCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/index.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/index.ts index 24e9353fbd4..2af4a3e105c 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/index.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/index.ts @@ -1,12 +1,12 @@ -import { textRotationExample } from "./text-rotation"; -import { histogramExample } from "./histogram"; -import { progressBarExample } from "./progress-bar"; -import { animatedShapesExample } from "./animated-shapes"; -import { lottieAnimationExample } from "./lottie-animation"; -import { fallingSpheresExample } from "./falling-spheres"; -import { goldPriceChartExample } from "./gold-price-chart"; -import { typewriterHighlightExample } from "./typewriter-highlight"; -import { wordCarouselExample } from "./word-carousel"; +import { animatedShapesExample } from './animated-shapes'; +import { fallingSpheresExample } from './falling-spheres'; +import { goldPriceChartExample } from './gold-price-chart'; +import { histogramExample } from './histogram'; +import { lottieAnimationExample } from './lottie-animation'; +import { progressBarExample } from './progress-bar'; +import { textRotationExample } from './text-rotation'; +import { typewriterHighlightExample } from './typewriter-highlight'; +import { wordCarouselExample } from './word-carousel'; export interface RemotionExample { id: string; @@ -15,7 +15,7 @@ export interface RemotionExample { code: string; durationInFrames: number; fps: number; - category: "Text" | "Charts" | "Animation" | "3D" | "Other"; + category: 'Text' | 'Charts' | 'Animation' | '3D' | 'Other'; } export const examples: RemotionExample[] = [ @@ -35,7 +35,7 @@ export function getExampleById(id: string): RemotionExample | undefined { } export function getExamplesByCategory( - category: RemotionExample["category"], + category: RemotionExample['category'], ): RemotionExample[] { return examples.filter((e) => e.category === category); } diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/lottie-animation.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/lottie-animation.ts index f33aa912b1f..a21d891fc09 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/lottie-animation.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/lottie-animation.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const lottieAnimationCode = `import { AbsoluteFill, useCurrentFrame, useVideoConfig, spring, interpolate } from "remotion"; import { Lottie } from "@remotion/lottie"; @@ -79,10 +79,10 @@ export const MyAnimation = () => { };`; export const lottieAnimationExample: RemotionExample = { - id: "lottie-animation", - name: "Lottie Fish Loader", - description: "Glowing fish loader animation from LottieFiles", - category: "Animation", + id: 'lottie-animation', + name: 'Lottie Fish Loader', + description: 'Glowing fish loader animation from LottieFiles', + category: 'Animation', durationInFrames: 180, fps: 60, code: lottieAnimationCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/progress-bar.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/progress-bar.ts index e9f5900770c..a1f63f4b7ab 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/progress-bar.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/progress-bar.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const progressBarCode = `import { AbsoluteFill, useCurrentFrame, useVideoConfig, interpolate } from "remotion"; @@ -82,10 +82,10 @@ export const MyAnimation = () => { };`; export const progressBarExample: RemotionExample = { - id: "progress-bar", - name: "Progress Bar", - description: "Animated progress bar from 0 to 100%", - category: "Other", + id: 'progress-bar', + name: 'Progress Bar', + description: 'Animated progress bar from 0 to 100%', + category: 'Other', durationInFrames: 180, fps: 30, code: progressBarCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/text-rotation.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/text-rotation.ts index 926f624eaee..4a87d518b61 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/text-rotation.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/text-rotation.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const textRotationCode = `import { useCurrentFrame, AbsoluteFill, interpolate } from "remotion"; @@ -73,10 +73,10 @@ export const MyAnimation = () => { };`; export const textRotationExample: RemotionExample = { - id: "text-rotation", - name: "Text Rotation", - description: "Rotating words with dissolve and blur effects", - category: "Text", + id: 'text-rotation', + name: 'Text Rotation', + description: 'Rotating words with dissolve and blur effects', + category: 'Text', durationInFrames: 240, fps: 30, code: textRotationCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/typewriter-highlight.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/typewriter-highlight.ts index 14917e6bfac..73b30cfc1c3 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/typewriter-highlight.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/typewriter-highlight.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const typewriterHighlightCode = `import React from "react"; import { @@ -189,10 +189,11 @@ export const MyAnimation = () => { };`; export const typewriterHighlightExample: RemotionExample = { - id: "typewriter-highlight", - name: "Typewriter with Highlight", - description: "Typewriter effect with blinking cursor and spring-animated word highlight", - category: "Text", + id: 'typewriter-highlight', + name: 'Typewriter with Highlight', + description: + 'Typewriter effect with blinking cursor and spring-animated word highlight', + category: 'Text', durationInFrames: 90, fps: 30, code: typewriterHighlightCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/code/word-carousel.ts b/packages/template-prompt-to-motion-graphics/src/examples/code/word-carousel.ts index 831dfd6e69a..aed8d1ee1d2 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/code/word-carousel.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/code/word-carousel.ts @@ -1,4 +1,4 @@ -import { RemotionExample } from "./index"; +import { RemotionExample } from './index'; export const wordCarouselCode = `import { useCurrentFrame, AbsoluteFill, interpolate } from "remotion"; @@ -120,10 +120,10 @@ export const MyAnimation = () => { };`; export const wordCarouselExample: RemotionExample = { - id: "word-carousel", - name: "Word Carousel", - description: "Rotating words with crossfade and blur transitions", - category: "Text", + id: 'word-carousel', + name: 'Word Carousel', + description: 'Rotating words with crossfade and blur transitions', + category: 'Text', durationInFrames: 200, fps: 30, code: wordCarouselCode, diff --git a/packages/template-prompt-to-motion-graphics/src/examples/prompts.ts b/packages/template-prompt-to-motion-graphics/src/examples/prompts.ts index f624966197f..3e8844850ff 100644 --- a/packages/template-prompt-to-motion-graphics/src/examples/prompts.ts +++ b/packages/template-prompt-to-motion-graphics/src/examples/prompts.ts @@ -1,34 +1,34 @@ export const examplePrompts = [ { - id: "text-typewriter", - headline: "Typewriter text", - icon: "Type", + id: 'text-typewriter', + headline: 'Typewriter text', + icon: 'Type', prompt: `Generate the text "Hello world" with world in yellow highlighting. Black text, white background. That words should be shown next to each other in the center of the screen. Animation: Let the words fade in from left to right and then highlight "world" yellow. Mimic a typewriter effect for the text appearance with a blinking cursor at the end of the text.`, - color: "#fdba74", + color: '#fdba74', }, { - id: "chat-bubbles", - headline: "Chat messages", - icon: "MessageCircle", + id: 'chat-bubbles', + headline: 'Chat messages', + icon: 'MessageCircle', prompt: `WhatsApp-style chat bubbles that appear one by one with a bouncy spring animation, alternating between sent and received messages. Use green for sent messages and gray for received messages. Position them on left and right sides respectively.`, - color: "#86efac", + color: '#86efac', }, { - id: "counter", - headline: "Metric counters", - icon: "Hash", + id: 'counter', + headline: 'Metric counters', + icon: 'Hash', prompt: `Three animated number counters showing Users (10,000), Revenue ($50,000), and Growth (127%) that count up from zero with staggered timing. Show all metrics at the same time, use this color #fde047. Focus on no overlaps and no flickering. Show the metrics in the center.`, - color: "#fde047", + color: '#fde047', }, { - id: "bar-chart", - headline: "Bar chart", - icon: "BarChart3", + id: 'bar-chart', + headline: 'Bar chart', + icon: 'BarChart3', prompt: `An animated histogram with the gold price for the following data: { "title": "Gold Price 2024", @@ -48,17 +48,17 @@ Show all metrics at the same time, use this color #fde047. Focus on no overlaps { "month": "Dec", "price": 2650 } ] }`, - color: "#a5b4fc", + color: '#a5b4fc', }, { - id: "doge-dvd", - headline: "Doge screensaver", - icon: "Disc", + id: 'doge-dvd', + headline: 'Doge screensaver', + icon: 'Disc', prompt: `Create a DVD-Rom Style animation of this image https://i.pinimg.com/600x/ac/82/57/ac8257e1cfc4e63f5c63f3d4869eb7c4.jpg The graphic moves smoothly across the screen in a straight line, bouncing off the edges of the screen whenever it hits a border. Each time it hits a corner or side, it changes direction, creating a continuous floating, ricocheting motion. The speed is steady, the movement is linear, and the object keeps rotating around the screen endlessly, just like the classic DVD logo screensaver. Change the color on every bounce, no rotation, Make the animation speed fast.`, - color: "#f9a8d4", + color: '#f9a8d4', }, ] as const; diff --git a/packages/template-prompt-to-motion-graphics/src/helpers/api-response.ts b/packages/template-prompt-to-motion-graphics/src/helpers/api-response.ts index d4da4ce7862..574a3134aec 100644 --- a/packages/template-prompt-to-motion-graphics/src/helpers/api-response.ts +++ b/packages/template-prompt-to-motion-graphics/src/helpers/api-response.ts @@ -1,13 +1,13 @@ -import { NextResponse } from "next/server"; -import { z, ZodType } from "zod"; +import { NextResponse } from 'next/server'; +import { z, ZodType } from 'zod'; export type ApiResponse = | { - type: "error"; + type: 'error'; message: string; } | { - type: "success"; + type: 'success'; data: Res; }; @@ -22,12 +22,12 @@ export const executeApi = const parsed = schema.parse(payload); const data = await handler(req, parsed); return NextResponse.json({ - type: "success", + type: 'success', data: data, }); } catch (err) { return NextResponse.json( - { type: "error", message: (err as Error).message }, + { type: 'error', message: (err as Error).message }, { status: 500, }, diff --git a/packages/template-prompt-to-motion-graphics/src/helpers/capture-frame.ts b/packages/template-prompt-to-motion-graphics/src/helpers/capture-frame.ts index 1a69148eae6..b84c85761a4 100644 --- a/packages/template-prompt-to-motion-graphics/src/helpers/capture-frame.ts +++ b/packages/template-prompt-to-motion-graphics/src/helpers/capture-frame.ts @@ -1,5 +1,5 @@ -import { renderStillOnWeb } from "@remotion/web-renderer"; -import type { ComponentType } from "react"; +import { renderStillOnWeb } from '@remotion/web-renderer'; +import type { ComponentType } from 'react'; interface CaptureConfig { width: number; @@ -19,14 +19,14 @@ export async function captureFrame( const { blob } = await renderStillOnWeb({ composition: { component: Component, - id: "frame-capture", + id: 'frame-capture', width: config.width, height: config.height, fps: config.fps, durationInFrames: config.durationInFrames, }, frame, - imageFormat: "jpeg", + imageFormat: 'jpeg', scale: 0.5, // 960x540 - good enough for AI context inputProps: {}, }); @@ -34,7 +34,7 @@ export async function captureFrame( // Convert blob to base64 data URL const buffer = await blob.arrayBuffer(); const bytes = new Uint8Array(buffer); - let binary = ""; + let binary = ''; for (let i = 0; i < bytes.length; i++) { binary += String.fromCharCode(bytes[i]); } diff --git a/packages/template-prompt-to-motion-graphics/src/helpers/sanitize-response.ts b/packages/template-prompt-to-motion-graphics/src/helpers/sanitize-response.ts index a9fa9a1f0d0..1d514bc99d2 100644 --- a/packages/template-prompt-to-motion-graphics/src/helpers/sanitize-response.ts +++ b/packages/template-prompt-to-motion-graphics/src/helpers/sanitize-response.ts @@ -9,8 +9,8 @@ export interface ValidationResult { */ export function stripMarkdownFences(code: string): string { let result = code; - result = result.replace(/^```(?:tsx?|jsx?)?\n?/, ""); - result = result.replace(/\n?```\s*$/, ""); + result = result.replace(/^```(?:tsx?|jsx?)?\n?/, ''); + result = result.replace(/\n?```\s*$/, ''); return result.trim(); } @@ -28,7 +28,7 @@ export function validateGptResponse(response: string): ValidationResult { return { isValid: false, error: - "The response was not a valid motion graphics component. Please try a different prompt.", + 'The response was not a valid motion graphics component. Please try a different prompt.', }; } @@ -58,9 +58,9 @@ export function extractComponentCode(code: string): string { for (let i = bodyStart; i < code.length; i++) { const char = code[i]; - if (char === "{") { + if (char === '{') { braceCount++; - } else if (char === "}") { + } else if (char === '}') { braceCount--; if (braceCount === 0) { endIndex = i; @@ -73,8 +73,8 @@ export function extractComponentCode(code: string): string { // Return everything from start of code to end of component (including closing brace and semicolon) let result = code.slice(0, endIndex + 1); // Add semicolon if not present - if (!result.trim().endsWith(";")) { - result = result.trimEnd() + ";"; + if (!result.trim().endsWith(';')) { + result = result.trimEnd() + ';'; } return result.trim(); } diff --git a/packages/template-prompt-to-motion-graphics/src/helpers/use-rendering.ts b/packages/template-prompt-to-motion-graphics/src/helpers/use-rendering.ts index ace2b96c2fc..113921af74e 100644 --- a/packages/template-prompt-to-motion-graphics/src/helpers/use-rendering.ts +++ b/packages/template-prompt-to-motion-graphics/src/helpers/use-rendering.ts @@ -1,30 +1,30 @@ -import { z } from "zod"; -import { useCallback, useMemo, useState } from "react"; -import { getProgress, renderVideo } from "../lambda/api"; -import { CompositionProps } from "../../types/constants"; +import { useCallback, useMemo, useState } from 'react'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; +import { getProgress, renderVideo } from '../lambda/api'; export type State = | { - status: "init"; + status: 'init'; } | { - status: "invoking"; + status: 'invoking'; } | { renderId: string; bucketName: string; progress: number; - status: "rendering"; + status: 'rendering'; } | { renderId: string | null; - status: "error"; + status: 'error'; error: Error; } | { url: string; size: number; - status: "done"; + status: 'done'; }; const wait = async (milliSeconds: number) => { @@ -35,21 +35,19 @@ const wait = async (milliSeconds: number) => { }); }; -export const useRendering = ( - inputProps: z.infer, -) => { +export const useRendering = (inputProps: z.infer) => { const [state, setState] = useState({ - status: "init", + status: 'init', }); const renderMedia = useCallback(async () => { setState({ - status: "invoking", + status: 'invoking', }); try { const { renderId, bucketName } = await renderVideo({ inputProps }); setState({ - status: "rendering", + status: 'rendering', progress: 0, renderId: renderId, bucketName: bucketName, @@ -63,27 +61,27 @@ export const useRendering = ( bucketName: bucketName, }); switch (result.type) { - case "error": { + case 'error': { setState({ - status: "error", + status: 'error', renderId: renderId, error: new Error(result.message), }); pending = false; break; } - case "done": { + case 'done': { setState({ size: result.size, url: result.url, - status: "done", + status: 'done', }); pending = false; break; } - case "progress": { + case 'progress': { setState({ - status: "rendering", + status: 'rendering', bucketName: bucketName, progress: result.progress, renderId: renderId, @@ -94,7 +92,7 @@ export const useRendering = ( } } catch (err) { setState({ - status: "error", + status: 'error', error: err as Error, renderId: null, }); @@ -102,7 +100,7 @@ export const useRendering = ( }, [inputProps]); const undo = useCallback(() => { - setState({ status: "init" }); + setState({ status: 'init' }); }, []); return useMemo(() => { diff --git a/packages/template-prompt-to-motion-graphics/src/hooks/useAnimationState.ts b/packages/template-prompt-to-motion-graphics/src/hooks/useAnimationState.ts index 60b8c8103ab..c18ed58ec57 100644 --- a/packages/template-prompt-to-motion-graphics/src/hooks/useAnimationState.ts +++ b/packages/template-prompt-to-motion-graphics/src/hooks/useAnimationState.ts @@ -1,10 +1,10 @@ -"use client"; +'use client'; -import { useState, useEffect, useCallback } from "react"; +import { useCallback, useEffect, useState } from 'react'; import { compileCode as compile, type CompilationResult, -} from "../remotion/compiler"; +} from '../remotion/compiler'; export interface AnimationState { code: string; @@ -13,7 +13,7 @@ export interface AnimationState { isCompiling: boolean; } -export function useAnimationState(initialCode: string = "") { +export function useAnimationState(initialCode: string = '') { const [state, setState] = useState({ code: initialCode, Component: null, diff --git a/packages/template-prompt-to-motion-graphics/src/hooks/useAutoCorrection.ts b/packages/template-prompt-to-motion-graphics/src/hooks/useAutoCorrection.ts index 03dbabad4c1..b7c0416becf 100644 --- a/packages/template-prompt-to-motion-graphics/src/hooks/useAutoCorrection.ts +++ b/packages/template-prompt-to-motion-graphics/src/hooks/useAutoCorrection.ts @@ -1,12 +1,19 @@ -import { useEffect, useRef, useCallback } from "react"; -import type { ErrorCorrectionContext, EditOperation } from "@/types/conversation"; +import type { + EditOperation, + ErrorCorrectionContext, +} from '@/types/conversation'; +import { useCallback, useEffect, useRef } from 'react'; interface AutoCorrectionConfig { maxAttempts: number; /** Compilation error from useAnimationState */ compilationError: string | null; /** Generation/API error */ - generationError: { message: string; type: string; failedEdit?: EditOperation } | null; + generationError: { + message: string; + type: string; + failedEdit?: EditOperation; + } | null; /** Whether code is currently being generated */ isStreaming: boolean; /** Whether code is currently being compiled */ @@ -18,8 +25,15 @@ interface AutoCorrectionConfig { /** Current error correction context */ errorCorrection: ErrorCorrectionContext | null; /** Callbacks */ - onTriggerCorrection: (prompt: string, errorContext: ErrorCorrectionContext) => void; - onAddErrorMessage: (message: string, type: "edit_failed" | "api" | "validation", failedEdit?: EditOperation) => void; + onTriggerCorrection: ( + prompt: string, + errorContext: ErrorCorrectionContext, + ) => void; + onAddErrorMessage: ( + message: string, + type: 'edit_failed' | 'api' | 'validation', + failedEdit?: EditOperation, + ) => void; onClearGenerationError: () => void; onClearErrorCorrection: () => void; } @@ -43,16 +57,16 @@ export function useAutoCorrection({ onClearErrorCorrection, }: AutoCorrectionConfig) { // Track whether last code change was from AI or user - const lastChangeSourceRef = useRef<"ai" | "user">("ai"); + const lastChangeSourceRef = useRef<'ai' | 'user'>('ai'); // Mark code as AI-generated const markAsAiGenerated = useCallback(() => { - lastChangeSourceRef.current = "ai"; + lastChangeSourceRef.current = 'ai'; }, []); // Mark code as user-edited const markAsUserEdited = useCallback(() => { - lastChangeSourceRef.current = "user"; + lastChangeSourceRef.current = 'user'; }, []); // Check if we should attempt auto-correction @@ -60,7 +74,7 @@ export function useAutoCorrection({ return ( hasGeneratedOnce && !isStreaming && - lastChangeSourceRef.current === "ai" && + lastChangeSourceRef.current === 'ai' && (errorCorrection?.attemptNumber ?? 0) < maxAttempts ); }, [hasGeneratedOnce, isStreaming, errorCorrection, maxAttempts]); @@ -77,11 +91,11 @@ export function useAutoCorrection({ const nextAttempt = (errorCorrection?.attemptNumber ?? 0) + 1; console.log( `Auto-correction attempt ${nextAttempt}/${maxAttempts} for compilation error:`, - compilationError + compilationError, ); - onAddErrorMessage(`Compilation error: ${compilationError}`, "validation"); - onTriggerCorrection("Fix the compilation error", { + onAddErrorMessage(`Compilation error: ${compilationError}`, 'validation'); + onTriggerCorrection('Fix the compilation error', { error: compilationError, attemptNumber: nextAttempt, maxAttempts, @@ -111,11 +125,11 @@ export function useAutoCorrection({ const nextAttempt = (errorCorrection?.attemptNumber ?? 0) + 1; console.log( `Auto-retry attempt ${nextAttempt}/${maxAttempts} for generation error:`, - generationError.message + generationError.message, ); onClearGenerationError(); - onTriggerCorrection("Retry the previous request", { + onTriggerCorrection('Retry the previous request', { error: generationError.message, attemptNumber: nextAttempt, maxAttempts, diff --git a/packages/template-prompt-to-motion-graphics/src/hooks/useConversationState.ts b/packages/template-prompt-to-motion-graphics/src/hooks/useConversationState.ts index e71304dd241..27fd1b90cff 100644 --- a/packages/template-prompt-to-motion-graphics/src/hooks/useConversationState.ts +++ b/packages/template-prompt-to-motion-graphics/src/hooks/useConversationState.ts @@ -1,11 +1,11 @@ -import { useState, useCallback, useRef } from "react"; import type { + AssistantMetadata, + ConversationContextMessage, ConversationMessage, ConversationState, - ConversationContextMessage, - AssistantMetadata, EditOperation, -} from "@/types/conversation"; +} from '@/types/conversation'; +import { useCallback, useRef, useState } from 'react'; export function useConversationState() { const [state, setState] = useState({ @@ -16,28 +16,31 @@ export function useConversationState() { }); // Track the last AI-generated code to detect manual edits - const lastAiCodeRef = useRef(""); + const lastAiCodeRef = useRef(''); - const addUserMessage = useCallback((content: string, attachedImages?: string[]) => { - const message: ConversationMessage = { - id: `user-${Date.now()}`, - role: "user", - content, - timestamp: Date.now(), - attachedImages, - }; - setState((prev) => ({ - ...prev, - messages: [...prev.messages, message], - })); - return message.id; - }, []); + const addUserMessage = useCallback( + (content: string, attachedImages?: string[]) => { + const message: ConversationMessage = { + id: `user-${Date.now()}`, + role: 'user', + content, + timestamp: Date.now(), + attachedImages, + }; + setState((prev) => ({ + ...prev, + messages: [...prev.messages, message], + })); + return message.id; + }, + [], + ); const addAssistantMessage = useCallback( (content: string, codeSnapshot: string, metadata?: AssistantMetadata) => { const message: ConversationMessage = { id: `assistant-${Date.now()}`, - role: "assistant", + role: 'assistant', content, timestamp: Date.now(), codeSnapshot, @@ -58,12 +61,12 @@ export function useConversationState() { const addErrorMessage = useCallback( ( content: string, - errorType: "edit_failed" | "api" | "validation", + errorType: 'edit_failed' | 'api' | 'validation', failedEdit?: EditOperation, ) => { const message: ConversationMessage = { id: `error-${Date.now()}`, - role: "error", + role: 'error', content, timestamp: Date.now(), errorType, @@ -80,7 +83,7 @@ export function useConversationState() { const markManualEdit = useCallback((currentCode: string) => { // Only mark as manual edit if code differs from last AI generation - if (currentCode !== lastAiCodeRef.current && lastAiCodeRef.current !== "") { + if (currentCode !== lastAiCodeRef.current && lastAiCodeRef.current !== '') { setState((prev) => ({ ...prev, hasManualEdits: true, @@ -89,7 +92,7 @@ export function useConversationState() { }, []); const clearConversation = useCallback(() => { - lastAiCodeRef.current = ""; + lastAiCodeRef.current = ''; setState({ messages: [], hasManualEdits: false, @@ -119,12 +122,12 @@ export function useConversationState() { const getFullContext = useCallback((): ConversationContextMessage[] => { // Filter out error messages - they're not part of the conversation context for the AI return state.messages - .filter((m) => m.role === "user" || m.role === "assistant") + .filter((m) => m.role === 'user' || m.role === 'assistant') .map((m) => ({ - role: m.role as "user" | "assistant", - content: m.role === "user" ? m.content : "[Generated Code]", + role: m.role as 'user' | 'assistant', + content: m.role === 'user' ? m.content : '[Generated Code]', // Include attached images for user messages so the AI remembers what was shared - ...(m.role === "user" && m.attachedImages && m.attachedImages.length > 0 + ...(m.role === 'user' && m.attachedImages && m.attachedImages.length > 0 ? { attachedImages: m.attachedImages } : {}), })); @@ -134,7 +137,7 @@ export function useConversationState() { const getPreviouslyUsedSkills = useCallback((): string[] => { const allSkills = new Set(); state.messages.forEach((m) => { - if (m.role === "assistant" && m.metadata?.skills) { + if (m.role === 'assistant' && m.metadata?.skills) { m.metadata.skills.forEach((skill) => allSkills.add(skill)); } }); @@ -145,7 +148,11 @@ export function useConversationState() { const getLastUserAttachedImages = useCallback((): string[] | undefined => { for (let i = state.messages.length - 1; i >= 0; i--) { const msg = state.messages[i]; - if (msg.role === "user" && msg.attachedImages && msg.attachedImages.length > 0) { + if ( + msg.role === 'user' && + msg.attachedImages && + msg.attachedImages.length > 0 + ) { return msg.attachedImages; } } diff --git a/packages/template-prompt-to-motion-graphics/src/hooks/useGenerationApi.ts b/packages/template-prompt-to-motion-graphics/src/hooks/useGenerationApi.ts index d5731901c29..6836da2b84a 100644 --- a/packages/template-prompt-to-motion-graphics/src/hooks/useGenerationApi.ts +++ b/packages/template-prompt-to-motion-graphics/src/hooks/useGenerationApi.ts @@ -1,15 +1,19 @@ -import { useState, useCallback } from "react"; -import type { - ConversationContextMessage, - AssistantMetadata, - ErrorCorrectionContext, -} from "@/types/conversation"; -import type { StreamPhase, GenerationErrorType, ModelId } from "@/types/generation"; import { - validateGptResponse, extractComponentCode, stripMarkdownFences, -} from "@/helpers/sanitize-response"; + validateGptResponse, +} from '@/helpers/sanitize-response'; +import type { + AssistantMetadata, + ConversationContextMessage, + ErrorCorrectionContext, +} from '@/types/conversation'; +import type { + GenerationErrorType, + ModelId, + StreamPhase, +} from '@/types/generation'; +import { useCallback, useState } from 'react'; interface FailedEditInfo { description: string; @@ -21,7 +25,11 @@ interface GenerationCallbacks { onCodeGenerated?: (code: string) => void; onStreamingChange?: (isStreaming: boolean) => void; onStreamPhaseChange?: (phase: StreamPhase) => void; - onError?: (error: string, type: GenerationErrorType, failedEdit?: FailedEditInfo) => void; + onError?: ( + error: string, + type: GenerationErrorType, + failedEdit?: FailedEditInfo, + ) => void; onMessageSent?: (prompt: string, attachedImages?: string[]) => void; onGenerationComplete?: ( code: string, @@ -30,7 +38,7 @@ interface GenerationCallbacks { ) => void; onErrorMessage?: ( message: string, - errorType: "edit_failed" | "api" | "validation", + errorType: 'edit_failed' | 'api' | 'validation', failedEdit?: FailedEditInfo, ) => void; onPendingMessage?: (skills?: string[]) => void; @@ -95,7 +103,7 @@ export function useGenerationApi(): UseGenerationApiReturn { setIsLoading(true); onStreamingChange?.(true); - onStreamPhaseChange?.("reasoning"); + onStreamPhaseChange?.('reasoning'); // Only add user message if not a silent retry if (!options?.silent) { @@ -103,9 +111,9 @@ export function useGenerationApi(): UseGenerationApiReturn { } try { - const response = await fetch("/api/generate", { - method: "POST", - headers: { "Content-Type": "application/json" }, + const response = await fetch('/api/generate', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ prompt, model, @@ -123,41 +131,41 @@ export function useGenerationApi(): UseGenerationApiReturn { const errorData = await response.json().catch(() => ({})); const errorMessage = errorData.error || `API error: ${response.status}`; - if (errorData.type === "edit_failed") { - onError?.(errorMessage, "validation", errorData.failedEdit); - onErrorMessage?.(errorMessage, "edit_failed", errorData.failedEdit); + if (errorData.type === 'edit_failed') { + onError?.(errorMessage, 'validation', errorData.failedEdit); + onErrorMessage?.(errorMessage, 'edit_failed', errorData.failedEdit); return; } - if (errorData.type === "validation") { - onError?.(errorMessage, "validation"); - onErrorMessage?.(errorMessage, "validation"); + if (errorData.type === 'validation') { + onError?.(errorMessage, 'validation'); + onErrorMessage?.(errorMessage, 'validation'); return; } throw new Error(errorMessage); } - const contentType = response.headers.get("content-type") || ""; + const contentType = response.headers.get('content-type') || ''; // Handle JSON response (non-streaming, for follow-up edits) - if (contentType.includes("application/json")) { + if (contentType.includes('application/json')) { const data = await response.json(); const { code, summary, metadata } = data; onCodeGenerated?.(code); onGenerationComplete?.(code, summary, metadata); const validation = validateGptResponse(code); if (!validation.isValid && validation.error) { - onError?.(validation.error, "validation"); + onError?.(validation.error, 'validation'); } return; } // Handle SSE stream response const reader = response.body?.getReader(); - if (!reader) throw new Error("No response body"); + if (!reader) throw new Error('No response body'); const decoder = new TextDecoder(); - let accumulatedText = ""; - let buffer = ""; + let accumulatedText = ''; + let buffer = ''; let streamMetadata: AssistantMetadata = {}; while (true) { @@ -165,37 +173,37 @@ export function useGenerationApi(): UseGenerationApiReturn { if (done) break; buffer += decoder.decode(value, { stream: true }); - const lines = buffer.split("\n"); - buffer = lines.pop() || ""; + const lines = buffer.split('\n'); + buffer = lines.pop() || ''; for (const line of lines) { - if (!line.startsWith("data: ")) continue; + if (!line.startsWith('data: ')) continue; const data = line.slice(6); - if (data === "[DONE]") continue; + if (data === '[DONE]') continue; try { const event = JSON.parse(data); - if (event.type === "metadata") { + if (event.type === 'metadata') { streamMetadata = { ...streamMetadata, skills: event.skills, }; onPendingMessage?.(event.skills); - } else if (event.type === "reasoning-start") { - onStreamPhaseChange?.("reasoning"); - } else if (event.type === "text-start") { - onStreamPhaseChange?.("generating"); - } else if (event.type === "text-delta") { + } else if (event.type === 'reasoning-start') { + onStreamPhaseChange?.('reasoning'); + } else if (event.type === 'text-start') { + onStreamPhaseChange?.('generating'); + } else if (event.type === 'text-delta') { accumulatedText += event.delta; const codeToShow = stripMarkdownFences(accumulatedText); onCodeGenerated?.(codeToShow); - } else if (event.type === "error") { + } else if (event.type === 'error') { throw new Error(event.error); } } catch (parseError) { if ( parseError instanceof Error && - parseError.message !== "Unexpected token" + parseError.message !== 'Unexpected token' ) { throw parseError; } @@ -215,19 +223,19 @@ export function useGenerationApi(): UseGenerationApiReturn { const validation = validateGptResponse(finalCode); if (!validation.isValid && validation.error) { - onError?.(validation.error, "validation"); + onError?.(validation.error, 'validation'); } } catch (error) { - console.error("Error generating code:", error); + console.error('Error generating code:', error); const errorMessage = error instanceof Error ? error.message - : "An unexpected error occurred"; - onError?.(errorMessage, "api"); + : 'An unexpected error occurred'; + onError?.(errorMessage, 'api'); } finally { setIsLoading(false); onStreamingChange?.(false); - onStreamPhaseChange?.("idle"); + onStreamPhaseChange?.('idle'); onClearPendingMessage?.(); } }, diff --git a/packages/template-prompt-to-motion-graphics/src/hooks/useImageAttachments.ts b/packages/template-prompt-to-motion-graphics/src/hooks/useImageAttachments.ts index a8e8130f8de..199baf97793 100644 --- a/packages/template-prompt-to-motion-graphics/src/hooks/useImageAttachments.ts +++ b/packages/template-prompt-to-motion-graphics/src/hooks/useImageAttachments.ts @@ -1,5 +1,12 @@ -import { useState, useRef, useCallback, type ChangeEvent, type DragEvent, type ClipboardEvent } from "react"; -import { fileToBase64 } from "@/helpers/capture-frame"; +import { fileToBase64 } from '@/helpers/capture-frame'; +import { + useCallback, + useRef, + useState, + type ChangeEvent, + type ClipboardEvent, + type DragEvent, +} from 'react'; const MAX_ATTACHED_IMAGES = 4; const MAX_FILE_SIZE_BYTES = 10 * 1024 * 1024; // 10MB per image @@ -45,9 +52,9 @@ export function useImageAttachments(): UseImageAttachmentsReturn { } if (oversizedFiles.length > 0) { - const fileNames = oversizedFiles.map((f) => f.name).join(", "); + const fileNames = oversizedFiles.map((f) => f.name).join(', '); setError( - `${oversizedFiles.length === 1 ? "File" : "Files"} too large (max ${MAX_FILE_SIZE_MB}MB): ${fileNames}` + `${oversizedFiles.length === 1 ? 'File' : 'Files'} too large (max ${MAX_FILE_SIZE_MB}MB): ${fileNames}`, ); } @@ -69,33 +76,39 @@ export function useImageAttachments(): UseImageAttachmentsReturn { setAttachedImages([]); }, []); - const handleFileSelect = useCallback(async (e: ChangeEvent) => { - const files = Array.from(e.target.files || []); - const imageFiles = files.filter((f) => f.type.startsWith("image/")); - const validFiles = filterValidFiles(imageFiles); - if (validFiles.length > 0) { - const base64Images = await Promise.all(validFiles.map(fileToBase64)); - addImages(base64Images); - } - // Reset input so same file can be selected again - e.target.value = ""; - }, [addImages, filterValidFiles]); - - const handlePaste = useCallback(async (e: ClipboardEvent) => { - const items = Array.from(e.clipboardData.items); - const imageItems = items.filter((item) => item.type.startsWith("image/")); - if (imageItems.length > 0) { - e.preventDefault(); - const files = imageItems - .map((item) => item.getAsFile()) - .filter((f): f is File => f !== null); - const validFiles = filterValidFiles(files); + const handleFileSelect = useCallback( + async (e: ChangeEvent) => { + const files = Array.from(e.target.files || []); + const imageFiles = files.filter((f) => f.type.startsWith('image/')); + const validFiles = filterValidFiles(imageFiles); if (validFiles.length > 0) { const base64Images = await Promise.all(validFiles.map(fileToBase64)); addImages(base64Images); } - } - }, [addImages, filterValidFiles]); + // Reset input so same file can be selected again + e.target.value = ''; + }, + [addImages, filterValidFiles], + ); + + const handlePaste = useCallback( + async (e: ClipboardEvent) => { + const items = Array.from(e.clipboardData.items); + const imageItems = items.filter((item) => item.type.startsWith('image/')); + if (imageItems.length > 0) { + e.preventDefault(); + const files = imageItems + .map((item) => item.getAsFile()) + .filter((f): f is File => f !== null); + const validFiles = filterValidFiles(files); + if (validFiles.length > 0) { + const base64Images = await Promise.all(validFiles.map(fileToBase64)); + addImages(base64Images); + } + } + }, + [addImages, filterValidFiles], + ); const handleDragOver = useCallback((e: DragEvent) => { e.preventDefault(); @@ -107,18 +120,21 @@ export function useImageAttachments(): UseImageAttachmentsReturn { setIsDragging(false); }, []); - const handleDrop = useCallback(async (e: DragEvent) => { - e.preventDefault(); - setIsDragging(false); + const handleDrop = useCallback( + async (e: DragEvent) => { + e.preventDefault(); + setIsDragging(false); - const files = Array.from(e.dataTransfer.files); - const imageFiles = files.filter((f) => f.type.startsWith("image/")); - const validFiles = filterValidFiles(imageFiles); - if (validFiles.length > 0) { - const base64Images = await Promise.all(validFiles.map(fileToBase64)); - addImages(base64Images); - } - }, [addImages, filterValidFiles]); + const files = Array.from(e.dataTransfer.files); + const imageFiles = files.filter((f) => f.type.startsWith('image/')); + const validFiles = filterValidFiles(imageFiles); + if (validFiles.length > 0) { + const base64Images = await Promise.all(validFiles.map(fileToBase64)); + addImages(base64Images); + } + }, + [addImages, filterValidFiles], + ); return { attachedImages, diff --git a/packages/template-prompt-to-motion-graphics/src/lambda/api.ts b/packages/template-prompt-to-motion-graphics/src/lambda/api.ts index ab9a12c87f9..78460fc2c56 100644 --- a/packages/template-prompt-to-motion-graphics/src/lambda/api.ts +++ b/packages/template-prompt-to-motion-graphics/src/lambda/api.ts @@ -1,26 +1,26 @@ -import { z } from "zod"; -import type { RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; +import type { RenderMediaOnLambdaOutput } from '@remotion/lambda/client'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; import { ProgressRequest, ProgressResponse, RenderRequest, -} from "../../types/schema"; -import { CompositionProps } from "../../types/constants"; -import { ApiResponse } from "../helpers/api-response"; +} from '../../types/schema'; +import { ApiResponse } from '../helpers/api-response'; const makeRequest = async ( endpoint: string, body: unknown, ): Promise => { const result = await fetch(endpoint, { - method: "post", + method: 'post', body: JSON.stringify(body), headers: { - "content-type": "application/json", + 'content-type': 'application/json', }, }); const json = (await result.json()) as ApiResponse; - if (json.type === "error") { + if (json.type === 'error') { throw new Error(json.message); } @@ -36,7 +36,7 @@ export const renderVideo = async ({ inputProps, }; - return makeRequest("/api/lambda/render", body); + return makeRequest('/api/lambda/render', body); }; export const getProgress = async ({ @@ -51,5 +51,5 @@ export const getProgress = async ({ bucketName, }; - return makeRequest("/api/lambda/progress", body); + return makeRequest('/api/lambda/progress', body); }; diff --git a/packages/template-prompt-to-motion-graphics/src/lib/utils.ts b/packages/template-prompt-to-motion-graphics/src/lib/utils.ts index bd0c391ddd1..2819a830d24 100644 --- a/packages/template-prompt-to-motion-graphics/src/lib/utils.ts +++ b/packages/template-prompt-to-motion-graphics/src/lib/utils.ts @@ -1,6 +1,6 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); } diff --git a/packages/template-prompt-to-motion-graphics/src/markdown.d.ts b/packages/template-prompt-to-motion-graphics/src/markdown.d.ts index c94d67b1a26..f73d61b396c 100644 --- a/packages/template-prompt-to-motion-graphics/src/markdown.d.ts +++ b/packages/template-prompt-to-motion-graphics/src/markdown.d.ts @@ -1,4 +1,4 @@ -declare module "*.md" { +declare module '*.md' { const content: string; export default content; } diff --git a/packages/template-prompt-to-motion-graphics/src/remotion/DynamicComp.tsx b/packages/template-prompt-to-motion-graphics/src/remotion/DynamicComp.tsx index fbc65394028..9eb5c513331 100644 --- a/packages/template-prompt-to-motion-graphics/src/remotion/DynamicComp.tsx +++ b/packages/template-prompt-to-motion-graphics/src/remotion/DynamicComp.tsx @@ -1,11 +1,11 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState } from 'react'; import { - getInputProps, - delayRender, - continueRender, AbsoluteFill, -} from "remotion"; -import { compileCode } from "./compiler"; + continueRender, + delayRender, + getInputProps, +} from 'remotion'; +import { compileCode } from './compiler'; interface DynamicCompProps { code: string; @@ -15,7 +15,7 @@ interface DynamicCompProps { export const DynamicComp: React.FC = () => { const { code } = getInputProps() as DynamicCompProps; - const [handle] = useState(() => delayRender("Compiling code...")); + const [handle] = useState(() => delayRender('Compiling code...')); const [Component, setComponent] = useState(null); const [error, setError] = useState(null); @@ -29,7 +29,7 @@ export const DynamicComp: React.FC = () => { setComponent(() => result.Component); } } catch (e) { - setError(e instanceof Error ? e.message : "Unknown error"); + setError(e instanceof Error ? e.message : 'Unknown error'); } finally { continueRender(handle); } @@ -39,32 +39,32 @@ export const DynamicComp: React.FC = () => { return (
Compilation Error
{error} diff --git a/packages/template-prompt-to-motion-graphics/src/remotion/Root.tsx b/packages/template-prompt-to-motion-graphics/src/remotion/Root.tsx index b4a00e9a886..3e2ec039497 100644 --- a/packages/template-prompt-to-motion-graphics/src/remotion/Root.tsx +++ b/packages/template-prompt-to-motion-graphics/src/remotion/Root.tsx @@ -1,6 +1,6 @@ -import React from "react"; -import { Composition } from "remotion"; -import { DynamicComp } from "./DynamicComp"; +import React from 'react'; +import { Composition } from 'remotion'; +import { DynamicComp } from './DynamicComp'; const defaultCode = `import { AbsoluteFill } from "remotion"; export const MyAnimation = () => ;`; diff --git a/packages/template-prompt-to-motion-graphics/src/remotion/compiler.ts b/packages/template-prompt-to-motion-graphics/src/remotion/compiler.ts index b8a39134446..51145412f44 100644 --- a/packages/template-prompt-to-motion-graphics/src/remotion/compiler.ts +++ b/packages/template-prompt-to-motion-graphics/src/remotion/compiler.ts @@ -1,29 +1,28 @@ -import { useState, useEffect, useMemo, useRef } from "react"; -import * as Babel from "@babel/standalone"; -import React from "react"; +import * as Babel from '@babel/standalone'; +import { Lottie } from '@remotion/lottie'; +import * as RemotionShapes from '@remotion/shapes'; +import { ThreeCanvas } from '@remotion/three'; +import { + TransitionSeries, + linearTiming, + springTiming, +} from '@remotion/transitions'; +import { clockWipe } from '@remotion/transitions/clock-wipe'; +import { fade } from '@remotion/transitions/fade'; +import { flip } from '@remotion/transitions/flip'; +import { slide } from '@remotion/transitions/slide'; +import { wipe } from '@remotion/transitions/wipe'; +import React, { useEffect, useMemo, useRef, useState } from 'react'; import { AbsoluteFill, + Img, + Sequence, interpolate, + spring, useCurrentFrame, useVideoConfig, - spring, - Sequence, - Img, -} from "remotion"; -import * as RemotionShapes from "@remotion/shapes"; -import { Lottie } from "@remotion/lottie"; -import { ThreeCanvas } from "@remotion/three"; -import * as THREE from "three"; -import { - TransitionSeries, - linearTiming, - springTiming, -} from "@remotion/transitions"; -import { fade } from "@remotion/transitions/fade"; -import { slide } from "@remotion/transitions/slide"; -import { wipe } from "@remotion/transitions/wipe"; -import { flip } from "@remotion/transitions/flip"; -import { clockWipe } from "@remotion/transitions/clock-wipe"; +} from 'remotion'; +import * as THREE from 'three'; export interface CompilationResult { Component: React.ComponentType | null; @@ -39,27 +38,27 @@ function extractComponentBody(code: string): string { // Remove type imports: import type { ... } from "..."; cleaned = cleaned.replace( /import\s+type\s*\{[\s\S]*?\}\s*from\s*["'][^"']+["'];?/g, - "", + '', ); // Remove combined default + named imports: import X, { ... } from "..."; cleaned = cleaned.replace( /import\s+\w+\s*,\s*\{[\s\S]*?\}\s*from\s*["'][^"']+["'];?/g, - "", + '', ); // Remove multi-line named imports: import { ... } from "..."; cleaned = cleaned.replace( /import\s*\{[\s\S]*?\}\s*from\s*["'][^"']+["'];?/g, - "", + '', ); // Remove namespace imports: import * as X from "..."; cleaned = cleaned.replace( /import\s+\*\s+as\s+\w+\s+from\s*["'][^"']+["'];?/g, - "", + '', ); // Remove default imports: import X from "..."; - cleaned = cleaned.replace(/import\s+\w+\s+from\s*["'][^"']+["'];?/g, ""); + cleaned = cleaned.replace(/import\s+\w+\s+from\s*["'][^"']+["'];?/g, ''); // Remove side-effect imports: import "..."; - cleaned = cleaned.replace(/import\s*["'][^"']+["'];?/g, ""); + cleaned = cleaned.replace(/import\s*["'][^"']+["'];?/g, ''); cleaned = cleaned.trim(); @@ -80,7 +79,7 @@ function extractComponentBody(code: string): string { // Standalone compile function for use outside React components export function compileCode(code: string): CompilationResult { if (!code?.trim()) { - return { Component: null, error: "No code provided" }; + return { Component: null, error: 'No code provided' }; } try { @@ -88,12 +87,12 @@ export function compileCode(code: string): CompilationResult { const wrappedSource = `const DynamicAnimation = () => {\n${componentBody}\n};`; const transpiled = Babel.transform(wrappedSource, { - presets: ["react", "typescript"], - filename: "dynamic-animation.tsx", + presets: ['react', 'typescript'], + filename: 'dynamic-animation.tsx', }); if (!transpiled.code) { - return { Component: null, error: "Transpilation failed" }; + return { Component: null, error: 'Transpilation failed' }; } const Remotion = { @@ -109,48 +108,48 @@ export function compileCode(code: string): CompilationResult { const wrappedCode = `${transpiled.code}\nreturn DynamicAnimation;`; const createComponent = new Function( - "React", - "Remotion", - "RemotionShapes", - "Lottie", - "ThreeCanvas", - "THREE", - "AbsoluteFill", - "interpolate", - "useCurrentFrame", - "useVideoConfig", - "spring", - "Sequence", - "Img", - "useState", - "useEffect", - "useMemo", - "useRef", - "Rect", - "Circle", - "Triangle", - "Star", - "Polygon", - "Ellipse", - "Heart", - "Pie", - "makeRect", - "makeCircle", - "makeTriangle", - "makeStar", - "makePolygon", - "makeEllipse", - "makeHeart", - "makePie", + 'React', + 'Remotion', + 'RemotionShapes', + 'Lottie', + 'ThreeCanvas', + 'THREE', + 'AbsoluteFill', + 'interpolate', + 'useCurrentFrame', + 'useVideoConfig', + 'spring', + 'Sequence', + 'Img', + 'useState', + 'useEffect', + 'useMemo', + 'useRef', + 'Rect', + 'Circle', + 'Triangle', + 'Star', + 'Polygon', + 'Ellipse', + 'Heart', + 'Pie', + 'makeRect', + 'makeCircle', + 'makeTriangle', + 'makeStar', + 'makePolygon', + 'makeEllipse', + 'makeHeart', + 'makePie', // Transitions - "TransitionSeries", - "linearTiming", - "springTiming", - "fade", - "slide", - "wipe", - "flip", - "clockWipe", + 'TransitionSeries', + 'linearTiming', + 'springTiming', + 'fade', + 'slide', + 'wipe', + 'flip', + 'clockWipe', wrappedCode, ); @@ -199,17 +198,17 @@ export function compileCode(code: string): CompilationResult { clockWipe, ); - if (typeof Component !== "function") { + if (typeof Component !== 'function') { return { Component: null, - error: "Code must be a function that returns a React component", + error: 'Code must be a function that returns a React component', }; } return { Component, error: null }; } catch (error) { const errorMessage = - error instanceof Error ? error.message : "Unknown compilation error"; + error instanceof Error ? error.message : 'Unknown compilation error'; return { Component: null, error: errorMessage }; } } diff --git a/packages/template-prompt-to-motion-graphics/src/remotion/index.ts b/packages/template-prompt-to-motion-graphics/src/remotion/index.ts index f31c790edb3..91fa0f3468e 100644 --- a/packages/template-prompt-to-motion-graphics/src/remotion/index.ts +++ b/packages/template-prompt-to-motion-graphics/src/remotion/index.ts @@ -1,4 +1,4 @@ -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; +import { registerRoot } from 'remotion'; +import { RemotionRoot } from './Root'; registerRoot(RemotionRoot); diff --git a/packages/template-prompt-to-motion-graphics/src/skills/index.ts b/packages/template-prompt-to-motion-graphics/src/skills/index.ts index 6b81cff1b70..94b32293b6e 100644 --- a/packages/template-prompt-to-motion-graphics/src/skills/index.ts +++ b/packages/template-prompt-to-motion-graphics/src/skills/index.ts @@ -1,38 +1,38 @@ -import { examples } from "@/examples/code"; +import { examples } from '@/examples/code'; // Import markdown files at build time -import chartsSkill from "./charts.md"; -import typographySkill from "./typography.md"; -import socialMediaSkill from "./social-media.md"; -import messagingSkill from "./messaging.md"; -import threeDSkill from "./3d.md"; -import transitionsSkill from "./transitions.md"; -import sequencingSkill from "./sequencing.md"; -import springPhysicsSkill from "./spring-physics.md"; +import threeDSkill from './3d.md'; +import chartsSkill from './charts.md'; +import messagingSkill from './messaging.md'; +import sequencingSkill from './sequencing.md'; +import socialMediaSkill from './social-media.md'; +import springPhysicsSkill from './spring-physics.md'; +import transitionsSkill from './transitions.md'; +import typographySkill from './typography.md'; // Guidance skills (markdown files with patterns/rules) const GUIDANCE_SKILLS = [ - "charts", - "typography", - "social-media", - "messaging", - "3d", - "transitions", - "sequencing", - "spring-physics", + 'charts', + 'typography', + 'social-media', + 'messaging', + '3d', + 'transitions', + 'sequencing', + 'spring-physics', ] as const; // Example skills (complete working code references) const EXAMPLE_SKILLS = [ - "example-histogram", - "example-progress-bar", - "example-text-rotation", - "example-falling-spheres", - "example-animated-shapes", - "example-lottie", - "example-gold-price-chart", - "example-typewriter-highlight", - "example-word-carousel", + 'example-histogram', + 'example-progress-bar', + 'example-text-rotation', + 'example-falling-spheres', + 'example-animated-shapes', + 'example-lottie', + 'example-gold-price-chart', + 'example-typewriter-highlight', + 'example-word-carousel', ] as const; export const SKILL_NAMES = [...GUIDANCE_SKILLS, ...EXAMPLE_SKILLS] as const; @@ -43,55 +43,55 @@ export type SkillName = (typeof SKILL_NAMES)[number]; const guidanceSkillContent: Record<(typeof GUIDANCE_SKILLS)[number], string> = { charts: chartsSkill, typography: typographySkill, - "social-media": socialMediaSkill, + 'social-media': socialMediaSkill, messaging: messagingSkill, - "3d": threeDSkill, + '3d': threeDSkill, transitions: transitionsSkill, sequencing: sequencingSkill, - "spring-physics": springPhysicsSkill, + 'spring-physics': springPhysicsSkill, }; // Map example skill names to example IDs const exampleIdMap: Record<(typeof EXAMPLE_SKILLS)[number], string> = { - "example-histogram": "histogram", - "example-progress-bar": "progress-bar", - "example-text-rotation": "text-rotation", - "example-falling-spheres": "falling-spheres", - "example-animated-shapes": "animated-shapes", - "example-lottie": "lottie-animation", - "example-gold-price-chart": "gold-price-chart", - "example-typewriter-highlight": "typewriter-highlight", - "example-word-carousel": "word-carousel", + 'example-histogram': 'histogram', + 'example-progress-bar': 'progress-bar', + 'example-text-rotation': 'text-rotation', + 'example-falling-spheres': 'falling-spheres', + 'example-animated-shapes': 'animated-shapes', + 'example-lottie': 'lottie-animation', + 'example-gold-price-chart': 'gold-price-chart', + 'example-typewriter-highlight': 'typewriter-highlight', + 'example-word-carousel': 'word-carousel', }; export function getSkillContent(skillName: SkillName): string { // Handle example skills - return the code directly - if (skillName.startsWith("example-")) { + if (skillName.startsWith('example-')) { const exampleId = exampleIdMap[skillName as (typeof EXAMPLE_SKILLS)[number]]; const example = examples.find((e) => e.id === exampleId); if (example) { return `## Example: ${example.name}\n${example.description}\n\n\`\`\`tsx\n${example.code}\n\`\`\``; } - return ""; + return ''; } // Handle guidance skills - return imported markdown content return ( - guidanceSkillContent[skillName as (typeof GUIDANCE_SKILLS)[number]] || "" + guidanceSkillContent[skillName as (typeof GUIDANCE_SKILLS)[number]] || '' ); } export function getCombinedSkillContent(skills: SkillName[]): string { if (skills.length === 0) { - return ""; + return ''; } const contents = skills .map((skill) => getSkillContent(skill)) .filter((content) => content.length > 0); - return contents.join("\n\n---\n\n"); + return contents.join('\n\n---\n\n'); } export const SKILL_DETECTION_PROMPT = `Classify this motion graphics prompt into ALL applicable categories. diff --git a/packages/template-prompt-to-motion-graphics/src/types/conversation.ts b/packages/template-prompt-to-motion-graphics/src/types/conversation.ts index 38a61e69f2a..fcdf2918d76 100644 --- a/packages/template-prompt-to-motion-graphics/src/types/conversation.ts +++ b/packages/template-prompt-to-motion-graphics/src/types/conversation.ts @@ -9,7 +9,7 @@ export interface AssistantMetadata { /** Which skills were detected for this generation */ skills?: string[]; /** Whether this was a tool-based edit or full replacement */ - editType?: "tool_edit" | "full_replacement"; + editType?: 'tool_edit' | 'full_replacement'; /** The edit operations applied (if tool_edit) */ edits?: EditOperation[]; /** Model used for generation */ @@ -18,7 +18,7 @@ export interface AssistantMetadata { export interface ConversationMessage { id: string; - role: "user" | "assistant" | "error"; + role: 'user' | 'assistant' | 'error'; content: string; timestamp: number; /** For user messages, store attached images as base64 data URLs */ @@ -28,7 +28,7 @@ export interface ConversationMessage { /** For assistant messages, store metadata about the generation */ metadata?: AssistantMetadata; /** For error messages, store the error type */ - errorType?: "edit_failed" | "api" | "validation"; + errorType?: 'edit_failed' | 'api' | 'validation'; /** For edit_failed errors, store the failed edit operation */ failedEdit?: EditOperation; } @@ -47,7 +47,7 @@ export interface ConversationState { } export interface ConversationContextMessage { - role: "user" | "assistant"; + role: 'user' | 'assistant'; content: string; /** For user messages, attached images as base64 data URLs */ attachedImages?: string[]; diff --git a/packages/template-prompt-to-motion-graphics/src/types/generation.ts b/packages/template-prompt-to-motion-graphics/src/types/generation.ts index cb3e55f0756..cab9bcacc18 100644 --- a/packages/template-prompt-to-motion-graphics/src/types/generation.ts +++ b/packages/template-prompt-to-motion-graphics/src/types/generation.ts @@ -1,15 +1,15 @@ export const MODELS = [ - { id: "gpt-5.2:none", name: "GPT-5.2 (No Reasoning)" }, - { id: "gpt-5.2:low", name: "GPT-5.2 (Low Reasoning)" }, - { id: "gpt-5.2:medium", name: "GPT-5.2 (Medium Reasoning)" }, - { id: "gpt-5.2:high", name: "GPT-5.2 (High Reasoning)" }, - { id: "gpt-5.2-pro:medium", name: "GPT-5.2 Pro (Medium)" }, - { id: "gpt-5.2-pro:high", name: "GPT-5.2 Pro (High)" }, - { id: "gpt-5.2-pro:xhigh", name: "GPT-5.2 Pro (XHigh)" }, + { id: 'gpt-5.2:none', name: 'GPT-5.2 (No Reasoning)' }, + { id: 'gpt-5.2:low', name: 'GPT-5.2 (Low Reasoning)' }, + { id: 'gpt-5.2:medium', name: 'GPT-5.2 (Medium Reasoning)' }, + { id: 'gpt-5.2:high', name: 'GPT-5.2 (High Reasoning)' }, + { id: 'gpt-5.2-pro:medium', name: 'GPT-5.2 Pro (Medium)' }, + { id: 'gpt-5.2-pro:high', name: 'GPT-5.2 Pro (High)' }, + { id: 'gpt-5.2-pro:xhigh', name: 'GPT-5.2 Pro (XHigh)' }, ] as const; -export type ModelId = (typeof MODELS)[number]["id"]; +export type ModelId = (typeof MODELS)[number]['id']; -export type StreamPhase = "idle" | "reasoning" | "generating"; +export type StreamPhase = 'idle' | 'reasoning' | 'generating'; -export type GenerationErrorType = "validation" | "api"; +export type GenerationErrorType = 'validation' | 'api'; diff --git a/packages/template-prompt-to-video/package.json b/packages/template-prompt-to-video/package.json index d645e371429..5e442d8615f 100644 --- a/packages/template-prompt-to-video/package.json +++ b/packages/template-prompt-to-video/package.json @@ -35,7 +35,7 @@ "dotenv": "17.3.1", "eslint": "9.19.0", "ora": "^9.0.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "prompts": "^2.4.2", "tsx": "^4.20.6", "typescript": "5.9.3", diff --git a/packages/template-prompt-to-video/src/Root.tsx b/packages/template-prompt-to-video/src/Root.tsx index a7dbc6d9acb..dbfa6d9afe4 100644 --- a/packages/template-prompt-to-video/src/Root.tsx +++ b/packages/template-prompt-to-video/src/Root.tsx @@ -1,13 +1,13 @@ -import { Composition, getStaticFiles } from "remotion"; -import { AIVideo, aiVideoSchema } from "./components/AIVideo"; -import { FPS, INTRO_DURATION } from "./lib/constants"; -import { getTimelinePath, loadTimelineFromFile } from "./lib/utils"; +import { Composition, getStaticFiles } from 'remotion'; +import { AIVideo, aiVideoSchema } from './components/AIVideo'; +import { FPS, INTRO_DURATION } from './lib/constants'; +import { getTimelinePath, loadTimelineFromFile } from './lib/utils'; export const RemotionRoot: React.FC = () => { const staticFiles = getStaticFiles(); const timelines = staticFiles - .filter((file) => file.name.endsWith("timeline.json")) - .map((file) => file.name.split("/")[1]); + .filter((file) => file.name.endsWith('timeline.json')) + .map((file) => file.name.split('/')[1]); return ( <> diff --git a/packages/template-prompt-to-video/src/components/AIVideo.tsx b/packages/template-prompt-to-video/src/components/AIVideo.tsx index ce8e9578bee..3f2b9b3370c 100644 --- a/packages/template-prompt-to-video/src/components/AIVideo.tsx +++ b/packages/template-prompt-to-video/src/components/AIVideo.tsx @@ -1,12 +1,12 @@ -import { AbsoluteFill, Sequence, staticFile, useVideoConfig } from "remotion"; -import { z } from "zod"; -import { Audio } from "@remotion/media"; -import { TimelineSchema } from "../lib/types"; -import { FPS, INTRO_DURATION } from "../lib/constants"; -import { loadFont } from "@remotion/google-fonts/BreeSerif"; -import { Background } from "./Background"; -import Subtitle from "./Subtitle"; -import { calculateFrameTiming, getAudioPath } from "../lib/utils"; +import { loadFont } from '@remotion/google-fonts/BreeSerif'; +import { Audio } from '@remotion/media'; +import { AbsoluteFill, Sequence, staticFile, useVideoConfig } from 'remotion'; +import { z } from 'zod'; +import { FPS, INTRO_DURATION } from '../lib/constants'; +import { TimelineSchema } from '../lib/types'; +import { calculateFrameTiming, getAudioPath } from '../lib/utils'; +import { Background } from './Background'; +import Subtitle from './Subtitle'; export const aiVideoSchema = z.object({ timeline: TimelineSchema.nullable(), @@ -18,35 +18,35 @@ export const AIVideo: React.FC> = ({ timeline, }) => { if (!timeline) { - throw new Error("Expected timeline to be fetched"); + throw new Error('Expected timeline to be fetched'); } const { id } = useVideoConfig(); return ( - +
{timeline.shortTitle} diff --git a/packages/template-prompt-to-video/src/components/Background.tsx b/packages/template-prompt-to-video/src/components/Background.tsx index e2baf142b79..cadb4afa41c 100644 --- a/packages/template-prompt-to-video/src/components/Background.tsx +++ b/packages/template-prompt-to-video/src/components/Background.tsx @@ -4,10 +4,10 @@ import { staticFile, useCurrentFrame, useVideoConfig, -} from "remotion"; -import { FPS, IMAGE_HEIGHT, IMAGE_WIDTH } from "../lib/constants"; -import { BackgroundElement } from "../lib/types"; -import { calculateBlur, getImagePath } from "../lib/utils"; +} from 'remotion'; +import { FPS, IMAGE_HEIGHT, IMAGE_WIDTH } from '../lib/constants'; +import { BackgroundElement } from '../lib/types'; +import { calculateBlur, getImagePath } from '../lib/utils'; const EXTRA_SCALE = 0.2; @@ -27,7 +27,7 @@ export const Background: React.FC<{ const currentScaleAnim = item.animations?.find( (anim) => - anim.type === "scale" && anim.startMs <= localMs && anim.endMs >= localMs, + anim.type === 'scale' && anim.startMs <= localMs && anim.endMs >= localMs, ); if (currentScaleAnim) { @@ -56,7 +56,7 @@ export const Background: React.FC<{ style={{ width: imgWidth * imgScale, height: imgHeight * imgScale, - position: "absolute", + position: 'absolute', top, left, filter: `blur(${currentBlur}px)`, diff --git a/packages/template-prompt-to-video/src/components/Subtitle.tsx b/packages/template-prompt-to-video/src/components/Subtitle.tsx index 389ec762a3a..31063a51d87 100644 --- a/packages/template-prompt-to-video/src/components/Subtitle.tsx +++ b/packages/template-prompt-to-video/src/components/Subtitle.tsx @@ -1,11 +1,11 @@ -import React from "react"; +import React from 'react'; import { AbsoluteFill, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; -import { Word } from "./Word"; +} from 'remotion'; +import { Word } from './Word'; const Subtitle: React.FC<{ text: string }> = ({ text }) => { const frame = useCurrentFrame(); diff --git a/packages/template-prompt-to-video/src/components/Word.tsx b/packages/template-prompt-to-video/src/components/Word.tsx index bc30632b16a..47caa234a7b 100644 --- a/packages/template-prompt-to-video/src/components/Word.tsx +++ b/packages/template-prompt-to-video/src/components/Word.tsx @@ -1,8 +1,8 @@ -import type React from "react"; -import { AbsoluteFill, interpolate, useVideoConfig } from "remotion"; -import { fitText } from "@remotion/layout-utils"; -import { makeTransform, scale, translateY } from "@remotion/animation-utils"; -import { loadFont } from "@remotion/google-fonts/BreeSerif"; +import { makeTransform, scale, translateY } from '@remotion/animation-utils'; +import { loadFont } from '@remotion/google-fonts/BreeSerif'; +import { fitText } from '@remotion/layout-utils'; +import type React from 'react'; +import { AbsoluteFill, interpolate, useVideoConfig } from 'remotion'; export const Word: React.FC<{ enterProgress: number; @@ -24,8 +24,8 @@ export const Word: React.FC<{ return ( {text} diff --git a/packages/template-prompt-to-video/src/index.ts b/packages/template-prompt-to-video/src/index.ts index f31c790edb3..91fa0f3468e 100644 --- a/packages/template-prompt-to-video/src/index.ts +++ b/packages/template-prompt-to-video/src/index.ts @@ -1,4 +1,4 @@ -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; +import { registerRoot } from 'remotion'; +import { RemotionRoot } from './Root'; registerRoot(RemotionRoot); diff --git a/packages/template-prompt-to-video/src/lib/types.ts b/packages/template-prompt-to-video/src/lib/types.ts index ad0c9c423ad..3e6d49e343f 100644 --- a/packages/template-prompt-to-video/src/lib/types.ts +++ b/packages/template-prompt-to-video/src/lib/types.ts @@ -1,10 +1,10 @@ -import { CharacterAlignmentResponseModel } from "@elevenlabs/elevenlabs-js/api"; -import { z } from "zod"; +import { CharacterAlignmentResponseModel } from '@elevenlabs/elevenlabs-js/api'; +import { z } from 'zod'; const BackgroundTransitionTypeSchema = z.union([ - z.literal("fade"), - z.literal("blur"), - z.literal("none"), + z.literal('fade'), + z.literal('blur'), + z.literal('none'), ]); const TimelineElementSchema = z.object({ @@ -13,7 +13,7 @@ const TimelineElementSchema = z.object({ }); const ElementAnimationSchema = TimelineElementSchema.extend({ - type: z.literal("scale"), + type: z.literal('scale'), from: z.number(), to: z.number(), }); @@ -28,9 +28,9 @@ const BackgroundElementSchema = TimelineElementSchema.extend({ const TextElementSchema = TimelineElementSchema.extend({ text: z.string(), position: z.union([ - z.literal("top"), - z.literal("bottom"), - z.literal("center"), + z.literal('top'), + z.literal('bottom'), + z.literal('center'), ]), animations: z.array(ElementAnimationSchema).optional(), }); @@ -58,12 +58,12 @@ export type AudioElement = z.infer; export type Timeline = z.infer; export { + AudioElementSchema, + BackgroundElementSchema, BackgroundTransitionTypeSchema, - TimelineElementSchema, ElementAnimationSchema, - BackgroundElementSchema, TextElementSchema, - AudioElementSchema, + TimelineElementSchema, TimelineSchema, }; diff --git a/packages/template-prompt-to-video/src/lib/utils.ts b/packages/template-prompt-to-video/src/lib/utils.ts index f9347109957..d07b2902639 100644 --- a/packages/template-prompt-to-video/src/lib/utils.ts +++ b/packages/template-prompt-to-video/src/lib/utils.ts @@ -1,6 +1,6 @@ -import { staticFile } from "remotion"; -import { BackgroundElement, Timeline } from "./types"; -import { FPS, INTRO_DURATION } from "./constants"; +import { staticFile } from 'remotion'; +import { FPS, INTRO_DURATION } from './constants'; +import { BackgroundElement, Timeline } from './types'; export const loadTimelineFromFile = async (filename: string) => { const res = await fetch(staticFile(filename)); @@ -48,11 +48,11 @@ export const calculateBlur = ({ const { enterTransition } = item; const { exitTransition } = item; - if (enterTransition === "blur" && localMs < fadeMs) { + if (enterTransition === 'blur' && localMs < fadeMs) { return (1 - localMs / fadeMs) * maxBlur; } - if (exitTransition === "blur" && localMs > endMs - startMs - fadeMs) { + if (exitTransition === 'blur' && localMs > endMs - startMs - fadeMs) { return (1 - (endMs - startMs - localMs) / fadeMs) * maxBlur; } diff --git a/packages/template-react-router/package.json b/packages/template-react-router/package.json index d15317e64aa..5883a3a6007 100644 --- a/packages/template-react-router/package.json +++ b/packages/template-react-router/package.json @@ -48,7 +48,7 @@ "@types/react-dom": "19.2.3", "dotenv": "17.3.1", "eslint": "9.19.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "tsx": "4.19.3", "typescript": "5.9.3" } diff --git a/packages/template-recorder/package.json b/packages/template-recorder/package.json index 5dcc2134a26..d562d52403a 100644 --- a/packages/template-recorder/package.json +++ b/packages/template-recorder/package.json @@ -62,7 +62,7 @@ "@types/web": "0.0.187", "@types/webrtc": "0.0.44", "@vitejs/plugin-react": "4.1.0", - "prettier": "3.6.0", + "prettier": "3.8.1", "prettier-plugin-organize-imports": "3.2.3" } } diff --git a/packages/template-recorder/src/App.tsx b/packages/template-recorder/src/App.tsx index 8713f9e2a83..b11062eec3b 100644 --- a/packages/template-recorder/src/App.tsx +++ b/packages/template-recorder/src/App.tsx @@ -1,30 +1,30 @@ -import React, { useCallback, useMemo, useState } from "react"; +import React, { useCallback, useMemo, useState } from 'react'; import { ALTERNATIVE1_PREFIX, ALTERNATIVE2_PREFIX, DISPLAY_PREFIX, WEBCAM_PREFIX, -} from "../config/cameras"; -import "./App.css"; -import type { RecordingStatus } from "./RecordButton"; -import { RecordingView } from "./RecordingView"; -import { TopBar } from "./TopBar"; -import { WaitingForDevices } from "./WaitingForDevices"; -import { EnsureBrowserSupport } from "./components/EnsureBrowserSupport"; -import { Button } from "./components/ui/button"; -import { MediaSourcesProvider } from "./state/media-sources"; +} from '../config/cameras'; +import './App.css'; +import type { RecordingStatus } from './RecordButton'; +import { RecordingView } from './RecordingView'; +import { TopBar } from './TopBar'; +import { WaitingForDevices } from './WaitingForDevices'; +import { EnsureBrowserSupport } from './components/EnsureBrowserSupport'; +import { Button } from './components/ui/button'; +import { MediaSourcesProvider } from './state/media-sources'; const outer: React.CSSProperties = { - height: "100%", - display: "flex", - flexDirection: "column", + height: '100%', + display: 'flex', + flexDirection: 'column', }; const gridContainer: React.CSSProperties = { - display: "grid", - gridTemplateColumns: "repeat(2, 1fr)", - alignItems: "center", - justifyItems: "center", + display: 'grid', + gridTemplateColumns: 'repeat(2, 1fr)', + alignItems: 'center', + justifyItems: 'center', flex: 1, minWidth: 0, minHeight: 0, @@ -35,29 +35,29 @@ const gridContainer: React.CSSProperties = { const App = () => { const [recordingStatus, setRecordingStatus] = useState({ - type: "idle", + type: 'idle', }); const [showAllViews, setShowAllViews] = useState( - localStorage.getItem("showAlternativeViews") === "true", + localStorage.getItem('showAlternativeViews') === 'true', ); const dynamicGridContainer = useMemo(() => { if (showAllViews) { - return { ...gridContainer, gridTemplateRows: "repeat(2, 1fr)" }; + return { ...gridContainer, gridTemplateRows: 'repeat(2, 1fr)' }; } - return { ...gridContainer, maxHeight: "50%" }; + return { ...gridContainer, maxHeight: '50%' }; }, [showAllViews]); const handleShowMore = useCallback(() => { setShowAllViews(true); - localStorage.setItem("showAlternativeViews", "true"); + localStorage.setItem('showAlternativeViews', 'true'); }, []); const handleShowLess = useCallback(() => { setShowAllViews(false); - localStorage.setItem("showAlternativeViews", "false"); + localStorage.setItem('showAlternativeViews', 'false'); }, []); return ( @@ -93,20 +93,20 @@ const App = () => { />
-
+
{showAllViews ? ( ) : ( diff --git a/packages/template-recorder/src/BlinkingCircle.tsx b/packages/template-recorder/src/BlinkingCircle.tsx index 2cd95dc7ebb..1e3d6ca7c1c 100644 --- a/packages/template-recorder/src/BlinkingCircle.tsx +++ b/packages/template-recorder/src/BlinkingCircle.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useState } from 'react'; export const BlinkingCircle: React.FC = () => { const [isVisible, setIsVisible] = useState(true); @@ -15,7 +15,7 @@ export const BlinkingCircle: React.FC = () => { xmlns="http://www.w3.org/2000/svg" height="10px" viewBox="0 0 512 512" - style={{ visibility: isVisible ? "visible" : "hidden" }} + style={{ visibility: isVisible ? 'visible' : 'hidden' }} > diff --git a/packages/template-recorder/src/CropIndicator.tsx b/packages/template-recorder/src/CropIndicator.tsx index 855cbc9c0c4..88419c4233a 100644 --- a/packages/template-recorder/src/CropIndicator.tsx +++ b/packages/template-recorder/src/CropIndicator.tsx @@ -1,8 +1,8 @@ -import React, { useMemo } from "react"; -import { AbsoluteFill } from "remotion"; -import type { Dimensions } from "../config/layout"; -import { fitElementSizeInContainer } from "../remotion/layout/fit-element"; -import { useElementSize } from "./helpers/use-element-size"; +import React, { useMemo } from 'react'; +import { AbsoluteFill } from 'remotion'; +import type { Dimensions } from '../config/layout'; +import { fitElementSizeInContainer } from '../remotion/layout/fit-element'; +import { useElementSize } from './helpers/use-element-size'; export const CropIndicator: React.FC<{ resolution: Dimensions; @@ -34,7 +34,7 @@ export const CropIndicator: React.FC<{ const cropIndicator: React.CSSProperties = useMemo(() => { return { - border: "2px solid #F7D449", + border: '2px solid #F7D449', borderRadius: 10, ...cropIndicatorRect, }; diff --git a/packages/template-recorder/src/DeviceItem.tsx b/packages/template-recorder/src/DeviceItem.tsx index 7d6e297fa73..318044f6573 100644 --- a/packages/template-recorder/src/DeviceItem.tsx +++ b/packages/template-recorder/src/DeviceItem.tsx @@ -1,15 +1,15 @@ -import React from "react"; -import styles from "./deviceitem.module.css"; +import React from 'react'; +import styles from './deviceitem.module.css'; const deviceRow: React.CSSProperties = { - display: "flex", - flexDirection: "row", - alignItems: "center", - width: "100%", + display: 'flex', + flexDirection: 'row', + alignItems: 'center', + width: '100%', paddingTop: 10, paddingBottom: 10, - borderBottom: "1px solid #333", - cursor: "pointer", + borderBottom: '1px solid #333', + cursor: 'pointer', paddingRight: 10, }; @@ -72,7 +72,7 @@ const CheckIcon: React.FC = () => { export const DeviceItem: React.FC<{ deviceLabel: string; - type: "camera" | "microphone" | "screen"; + type: 'camera' | 'microphone' | 'screen'; handleClick: () => void; selected: boolean; }> = ({ deviceLabel, type, handleClick, selected }) => { @@ -81,16 +81,16 @@ export const DeviceItem: React.FC<{
{selected && }
- {type === "camera" ? : null} - {type === "microphone" ? : null} - {type === "screen" ? : null} + {type === 'camera' ? : null} + {type === 'microphone' ? : null} + {type === 'screen' ? : null}
{deviceLabel}
diff --git a/packages/template-recorder/src/DevicePermission.tsx b/packages/template-recorder/src/DevicePermission.tsx index d32345be118..7e20215b3cd 100644 --- a/packages/template-recorder/src/DevicePermission.tsx +++ b/packages/template-recorder/src/DevicePermission.tsx @@ -1,38 +1,38 @@ -import type { ReactNode } from "react"; -import React, { useCallback, useEffect, useMemo, useState } from "react"; -import { PermissionError } from "./PermissionError"; -import { CircleSpinner } from "./components/Spinner"; +import type { ReactNode } from 'react'; +import React, { useCallback, useEffect, useMemo, useState } from 'react'; +import { PermissionError } from './PermissionError'; +import { CircleSpinner } from './components/Spinner'; -type PermissionState = "granted" | "denied" | "prompt" | "initial"; +type PermissionState = 'granted' | 'denied' | 'prompt' | 'initial'; const BORDERRADIUS = 10; const largeContainer: React.CSSProperties = { - display: "flex", - alignItems: "center", - flexDirection: "column", - justifyContent: "center", - height: "100%", + display: 'flex', + alignItems: 'center', + flexDirection: 'column', + justifyContent: 'center', + height: '100%', }; const explanationWrapper: React.CSSProperties = { - display: "flex", - textAlign: "start", + display: 'flex', + textAlign: 'start', paddingLeft: 10, }; const explanationContainer: React.CSSProperties = { - display: "flex", - justifyContent: "flex-start", - flexDirection: "column", + display: 'flex', + justifyContent: 'flex-start', + flexDirection: 'column', maxWidth: 800, lineHeight: 2, }; const innerContainer: React.CSSProperties = { - display: "flex", - justifyContent: "center", - alignItems: "center", - flexDirection: "row", + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + flexDirection: 'row', }; const container: React.CSSProperties = { borderRadius: BORDERRADIUS, @@ -41,9 +41,9 @@ const container: React.CSSProperties = { }; const title: React.CSSProperties = { - display: "flex", - justifyContent: "center", - fontSize: "1rem", + display: 'flex', + justifyContent: 'center', + fontSize: '1rem', }; const textContainer: React.CSSProperties = { @@ -55,9 +55,9 @@ const textContainer: React.CSSProperties = { }; const peripheralContainer: React.CSSProperties = { - display: "flex", - flexDirection: "column", - backgroundColor: "#242424", + display: 'flex', + flexDirection: 'column', + backgroundColor: '#242424', borderRadius: BORDERRADIUS, margin: 10, padding: 16, @@ -66,7 +66,7 @@ const peripheralContainer: React.CSSProperties = { }; const Permission: React.FC<{ - type: "audio" | "video"; + type: 'audio' | 'video'; deviceState: PermissionState; setDeviceState: (newState: PermissionState) => void; isInitialState: boolean; @@ -80,10 +80,10 @@ const Permission: React.FC<{ }) => { const dynamicStyle: React.CSSProperties = useMemo(() => { return { - display: "flex", - justifyContent: "flex-end", - alignItems: "center", - color: deviceState === "denied" ? "red" : "white", + display: 'flex', + justifyContent: 'flex-end', + alignItems: 'center', + color: deviceState === 'denied' ? 'red' : 'white', }; }, [deviceState]); @@ -116,23 +116,23 @@ const Permission: React.FC<{ const handleError = useCallback( (error: Error) => { if ( - error.message.includes("Requested device not found") || - error.message.includes("The object can not be found here") + error.message.includes('Requested device not found') || + error.message.includes('The object can not be found here') ) { onNoDevicesFound(); return; } - setDeviceState("denied"); + setDeviceState('denied'); }, [onNoDevicesFound, setDeviceState], ); const run = useCallback(async () => { const name = - type === "audio" - ? ("microphone" as PermissionName) - : ("camera" as PermissionName); + type === 'audio' + ? ('microphone' as PermissionName) + : ('camera' as PermissionName); const result = await navigator.permissions .query({ name }) .then((res) => res) @@ -146,23 +146,23 @@ const Permission: React.FC<{ return null; }); // firefox case - if (!result && deviceState === "initial") { + if (!result && deviceState === 'initial') { // probe for permission try { const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true, }); - setDeviceState("prompt"); + setDeviceState('prompt'); stream.getVideoTracks().forEach((track) => track.stop()); stream.getAudioTracks().forEach((track) => track.stop()); } catch (err) { - console.log("Error on getUserMedia(", err); + console.log('Error on getUserMedia(', err); handleError(err as Error); return; } - setDeviceState("granted"); + setDeviceState('granted'); return; } @@ -172,23 +172,23 @@ const Permission: React.FC<{ setDeviceState(result.state); - if (result.state === "prompt" && type === "audio") { + if (result.state === 'prompt' && type === 'audio') { try { await navigator.mediaDevices.getUserMedia({ video: true, audio: true, }); } catch (err) { - console.log("Error on getUserMedia()", err); + console.log('Error on getUserMedia()', err); handleError(err as Error); return; } } - if (result.state === "granted") { - setDeviceState("granted"); - } else if (result.state === "denied") { - setDeviceState("denied"); + if (result.state === 'granted') { + setDeviceState('granted'); + } else if (result.state === 'denied') { + setDeviceState('denied'); } }, [deviceState, handleError, setDeviceState, type]); @@ -197,9 +197,9 @@ const Permission: React.FC<{ }, [run]); const accessInformation = useMemo(() => { - if (deviceState === "prompt") return "Access requested"; - if (deviceState === "denied") return "Access denied"; - if (deviceState === "granted") return "Access granted"; + if (deviceState === 'prompt') return 'Access requested'; + if (deviceState === 'denied') return 'Access denied'; + if (deviceState === 'granted') return 'Access granted'; }, [deviceState]); if (isInitialState) return null; @@ -207,26 +207,26 @@ const Permission: React.FC<{
- {type === "audio" ? microphoneIcon : cameraIcon} + {type === 'audio' ? microphoneIcon : cameraIcon}
{accessInformation}
- {deviceState === "prompt" ? ( + {deviceState === 'prompt' ? ( ) : (
@@ -240,17 +240,17 @@ export const DevicePermission: React.FC<{ children: ReactNode }> = ({ children, }) => { const [noDeviceFound, setNoDeviceFound] = useState(false); - const [audioState, setAudioState] = useState("initial"); - const [videoState, setVideoState] = useState("initial"); + const [audioState, setAudioState] = useState('initial'); + const [videoState, setVideoState] = useState('initial'); const isInitialState = useMemo(() => { - return audioState === "initial" || videoState === "initial"; + return audioState === 'initial' || videoState === 'initial'; }, [audioState, videoState]); const dynamicContainer: React.CSSProperties = useMemo(() => { return { ...container, - borderColor: isInitialState ? "black" : "white", + borderColor: isInitialState ? 'black' : 'white', }; }, [isInitialState]); @@ -262,7 +262,7 @@ export const DevicePermission: React.FC<{ children: ReactNode }> = ({ return ; } - if (audioState === "granted" && videoState === "granted") { + if (audioState === 'granted' && videoState === 'granted') { return <>{children}; } diff --git a/packages/template-recorder/src/Logo.tsx b/packages/template-recorder/src/Logo.tsx index 13807869d5a..004204d0a6b 100644 --- a/packages/template-recorder/src/Logo.tsx +++ b/packages/template-recorder/src/Logo.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; const style: React.CSSProperties = { height: 48 / 1.8, diff --git a/packages/template-recorder/src/PermissionError.tsx b/packages/template-recorder/src/PermissionError.tsx index e9e89bf74dc..c79c65da2e9 100644 --- a/packages/template-recorder/src/PermissionError.tsx +++ b/packages/template-recorder/src/PermissionError.tsx @@ -1,14 +1,14 @@ -import React from "react"; +import React from 'react'; const outer: React.CSSProperties = { - width: "100%", - position: "absolute", - height: "100%", - justifyContent: "center", - alignItems: "center", - display: "flex", - fontSize: "0.9em", - color: "#ddd", + width: '100%', + position: 'absolute', + height: '100%', + justifyContent: 'center', + alignItems: 'center', + display: 'flex', + fontSize: '0.9em', + color: '#ddd', }; export const PermissionError: React.FC = () => { diff --git a/packages/template-recorder/src/PrefixAndResolution.tsx b/packages/template-recorder/src/PrefixAndResolution.tsx index a73fb9367d1..cbb75921a40 100644 --- a/packages/template-recorder/src/PrefixAndResolution.tsx +++ b/packages/template-recorder/src/PrefixAndResolution.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { ResolutionAndFps } from "./Stream"; +import React from 'react'; +import { ResolutionAndFps } from './Stream'; export const PrefixLabel: React.FC<{ prefix: string; @@ -8,10 +8,10 @@ export const PrefixLabel: React.FC<{
- {prefix} + {prefix}
); }; @@ -23,17 +23,17 @@ export const Resolution: React.FC<{ <> - {resolution.width}x{resolution.height},{" "} + {resolution.width}x{resolution.height},{' '} {Math.round(resolution.fps * 100) / 100} FPS diff --git a/packages/template-recorder/src/RecordButton.tsx b/packages/template-recorder/src/RecordButton.tsx index 51317857046..dfe17237c1a 100644 --- a/packages/template-recorder/src/RecordButton.tsx +++ b/packages/template-recorder/src/RecordButton.tsx @@ -1,18 +1,18 @@ -import { CameraIcon, MicIcon } from "lucide-react"; -import React, { useCallback, useEffect, useMemo } from "react"; -import { FPS } from "../config/fps"; -import { truthy } from "../remotion/helpers/truthy"; -import { RecordCircle } from "./BlinkingCircle"; -import { ProcessStatus } from "./components/ProcessingStatus"; -import { Button } from "./components/ui/button"; -import { Prefix } from "./helpers/prefixes"; +import { CameraIcon, MicIcon } from 'lucide-react'; +import React, { useCallback, useEffect, useMemo } from 'react'; +import { FPS } from '../config/fps'; +import { truthy } from '../remotion/helpers/truthy'; +import { RecordCircle } from './BlinkingCircle'; +import { ProcessStatus } from './components/ProcessingStatus'; +import { Button } from './components/ui/button'; +import { Prefix } from './helpers/prefixes'; import { FinishedRecording, startMediaRecorder, -} from "./helpers/start-media-recorder"; -import { useKeyPress } from "./helpers/use-key-press"; -import { useMediaSources } from "./state/media-sources"; -import { visibleByDefault } from "./state/visible-views"; +} from './helpers/start-media-recorder'; +import { useKeyPress } from './helpers/use-key-press'; +import { useMediaSources } from './state/media-sources'; +import { visibleByDefault } from './state/visible-views'; export type CurrentRecorder = { recorder: MediaRecorder; @@ -22,14 +22,14 @@ export type CurrentRecorder = { export type RecordingStatus = | { - type: "idle"; + type: 'idle'; } | { - type: "recording"; + type: 'recording'; ongoing: OngoingRecording; } | { - type: "recording-finished"; + type: 'recording-finished'; blobs: FinishedRecording[]; expectedFrames: number; endDate: number; @@ -52,14 +52,14 @@ export const RecordButton: React.FC<{ processingStatus, }) => { const discardVideos = useCallback(async () => { - if (recordingStatus.type !== "recording-finished") { - throw new Error("Recording not finished"); + if (recordingStatus.type !== 'recording-finished') { + throw new Error('Recording not finished'); } for (const blob of recordingStatus.blobs) { await blob.releaseData(); } - setRecordingStatus({ type: "idle" }); + setRecordingStatus({ type: 'idle' }); }, [recordingStatus, setRecordingStatus]); const mediaSources = useMediaSources().mediaSources; @@ -68,7 +68,7 @@ export const RecordButton: React.FC<{ return Object.entries(mediaSources).filter(([prefix, source]) => { return ( (showAllViews || visibleByDefault[prefix as Prefix]) && - source.streamState.type === "loaded" + source.streamState.type === 'loaded' ); }); }, [mediaSources, showAllViews]); @@ -101,13 +101,13 @@ export const RecordButton: React.FC<{ ).filter(truthy); return setRecordingStatus({ - type: "recording", + type: 'recording', ongoing: { recorders: recorders, startDate }, }); }, [activeSources, setRecordingStatus]); const onStop = useCallback(async () => { - if (recordingStatus.type !== "recording") { + if (recordingStatus.type !== 'recording') { return; } @@ -120,7 +120,7 @@ export const RecordButton: React.FC<{ ((endDate - recordingStatus.ongoing.startDate) / 1000) * FPS; setRecordingStatus({ - type: "recording-finished", + type: 'recording-finished', blobs, expectedFrames, endDate, @@ -129,7 +129,7 @@ export const RecordButton: React.FC<{ useEffect(() => { return () => { - if (recordingStatus.type === "recording") { + if (recordingStatus.type === 'recording') { recordingStatus.ongoing.recorders.forEach((r) => { r.recorder.stop(); }); @@ -138,7 +138,7 @@ export const RecordButton: React.FC<{ }, [recordingStatus]); const disabled = - mediaSources.webcam.streamState.type !== "loaded" || + mediaSources.webcam.streamState.type !== 'loaded' || mediaSources.webcam.streamState.stream.getAudioTracks().length === 0 || processingStatus !== null; @@ -150,15 +150,15 @@ export const RecordButton: React.FC<{ const dialog = document.querySelector('[role="dialog"]'); if ( - (document.activeElement && document.activeElement.tagName === "input") || + (document.activeElement && document.activeElement.tagName === 'input') || dialog ) { return; } - if (recordingStatus.type === "recording") { + if (recordingStatus.type === 'recording') { onStop(); - } else if (recordingStatus.type === "idle") { + } else if (recordingStatus.type === 'idle') { start(); } }, [onStop, disabled, recordingStatus.type, start]); @@ -168,15 +168,15 @@ export const RecordButton: React.FC<{ start(); }, [discardVideos, start]); - useKeyPress({ keys: ["r"], callback: onPressR, metaKey: false }); + useKeyPress({ keys: ['r'], callback: onPressR, metaKey: false }); - if (recordingStatus.type === "recording") { + if (recordingStatus.type === 'recording') { return ( <>
); diff --git a/packages/template-recorder/src/components/EnsureBrowserSupport.tsx b/packages/template-recorder/src/components/EnsureBrowserSupport.tsx index c408d52e462..b76aec09a8e 100644 --- a/packages/template-recorder/src/components/EnsureBrowserSupport.tsx +++ b/packages/template-recorder/src/components/EnsureBrowserSupport.tsx @@ -1,32 +1,32 @@ -import { useEffect, useState } from "react"; -import { canUseWebFsWriter } from "../helpers/browser-support"; +import { useEffect, useState } from 'react'; +import { canUseWebFsWriter } from '../helpers/browser-support'; -type WebFsState = "loading" | "yes" | "no" | "security-error"; +type WebFsState = 'loading' | 'yes' | 'no' | 'security-error'; export const EnsureBrowserSupport: React.FC<{ children: React.ReactNode; }> = ({ children }) => { - const [canUseWebFs, setCanUseWebFs] = useState("loading"); + const [canUseWebFs, setCanUseWebFs] = useState('loading'); useEffect(() => { canUseWebFsWriter() .then((result) => { - setCanUseWebFs(result ? "yes" : "no"); + setCanUseWebFs(result ? 'yes' : 'no'); }) .catch((err) => { - if ((err as Error).message.includes("Security")) { - setCanUseWebFs("security-error"); + if ((err as Error).message.includes('Security')) { + setCanUseWebFs('security-error'); } else { - setCanUseWebFs("no"); + setCanUseWebFs('no'); console.log(err); } }); }, []); - if (canUseWebFs === "loading") { + if (canUseWebFs === 'loading') { return null; } - if (canUseWebFs === "no") { + if (canUseWebFs === 'no') { return (
Browser not supported @@ -38,7 +38,7 @@ export const EnsureBrowserSupport: React.FC<{ ); } - if (canUseWebFs === "security-error") { + if (canUseWebFs === 'security-error') { return (
Security error diff --git a/packages/template-recorder/src/components/NewFolderDialog.tsx b/packages/template-recorder/src/components/NewFolderDialog.tsx index 8a2fd651a9c..59793d5272e 100644 --- a/packages/template-recorder/src/components/NewFolderDialog.tsx +++ b/packages/template-recorder/src/components/NewFolderDialog.tsx @@ -1,14 +1,14 @@ -import type { ChangeEvent, SetStateAction } from "react"; +import type { ChangeEvent, SetStateAction } from 'react'; import React, { createRef, useCallback, useImperativeHandle, useMemo, useState, -} from "react"; -import { createFolder } from "../actions/create-folder"; -import { useKeyPress } from "../helpers/use-key-press"; -import { Button } from "./ui/button"; +} from 'react'; +import { createFolder } from '../actions/create-folder'; +import { useKeyPress } from '../helpers/use-key-press'; +import { Button } from './ui/button'; import { Dialog, DialogContent, @@ -16,9 +16,9 @@ import { DialogFooter, DialogHeader, DialogTitle, -} from "./ui/dialog"; -import { Input } from "./ui/input"; -import { Label } from "./ui/label"; +} from './ui/dialog'; +import { Input } from './ui/input'; +import { Label } from './ui/label'; export const createNewFolderRef = createRef<{ openDialog: () => void; @@ -28,7 +28,7 @@ export const NewFolderDialog: React.FC<{ setSelectedFolder: React.Dispatch>; refreshFoldersList: () => Promise; }> = ({ refreshFoldersList, setSelectedFolder }) => { - const [newProject, setNewProject] = useState(""); + const [newProject, setNewProject] = useState(''); const [open, setOpen] = useState(false); const handleChange = (event: ChangeEvent) => { @@ -62,7 +62,7 @@ export const NewFolderDialog: React.FC<{ } setSelectedFolder(newProject); - setNewProject(""); + setNewProject(''); refreshFoldersList(); setOpen(false); } catch (e) { @@ -84,7 +84,7 @@ export const NewFolderDialog: React.FC<{ } }, [disabled, handleSubmit]); - useKeyPress({ keys: ["Enter"], callback: handlePressEnter, metaKey: false }); + useKeyPress({ keys: ['Enter'], callback: handlePressEnter, metaKey: false }); return ( diff --git a/packages/template-recorder/src/components/ProcessingStatus.tsx b/packages/template-recorder/src/components/ProcessingStatus.tsx index 58a3dee64ed..58454d2f6ef 100644 --- a/packages/template-recorder/src/components/ProcessingStatus.tsx +++ b/packages/template-recorder/src/components/ProcessingStatus.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; export type ProcessStatus = { title: string; @@ -8,12 +8,12 @@ export type ProcessStatus = { const statusStyle: React.CSSProperties = { fontSize: 13, - color: "rgba(255, 255, 255, 0.8)", - display: "block", + color: 'rgba(255, 255, 255, 0.8)', + display: 'block', }; const subtitle: React.CSSProperties = { - color: "rgba(255, 255, 255, 0.5)", + color: 'rgba(255, 255, 255, 0.5)', fontSize: 13, }; @@ -24,7 +24,7 @@ export const ProcessingStatus: React.FC<{
{status.title}
- {status.description}{" "} + {status.description}{' '} {status.abort !== null ? ( Abort and discard - ) : null}{" "} + ) : null}{' '}
); diff --git a/packages/template-recorder/src/components/RescanDevices.tsx b/packages/template-recorder/src/components/RescanDevices.tsx index 963787de2f1..483ebfda45d 100644 --- a/packages/template-recorder/src/components/RescanDevices.tsx +++ b/packages/template-recorder/src/components/RescanDevices.tsx @@ -1,5 +1,5 @@ -import { useContext } from "react"; -import { DevicesContext } from "../WaitingForDevices"; +import { useContext } from 'react'; +import { DevicesContext } from '../WaitingForDevices'; export const RescanDevices = () => { const ctx = useContext(DevicesContext); @@ -10,7 +10,7 @@ export const RescanDevices = () => { data-disabled={ctx?.isRescanning} className="cursor-pointer hover:underline inline opacity-70 hover:opacity-100 transition-opacity data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50" > - {ctx?.isRescanning ? "Rescanning..." : "Rescan devices"} + {ctx?.isRescanning ? 'Rescanning...' : 'Rescan devices'}
); }; diff --git a/packages/template-recorder/src/components/SelectedFolder.tsx b/packages/template-recorder/src/components/SelectedFolder.tsx index 6b9ccc9cc1a..ab13a0f327f 100644 --- a/packages/template-recorder/src/components/SelectedFolder.tsx +++ b/packages/template-recorder/src/components/SelectedFolder.tsx @@ -1,6 +1,6 @@ -import type { SetStateAction } from "react"; -import React, { useCallback } from "react"; -import { createNewFolderRef } from "./NewFolderDialog"; +import type { SetStateAction } from 'react'; +import React, { useCallback } from 'react'; +import { createNewFolderRef } from './NewFolderDialog'; import { Select, SelectContent, @@ -8,9 +8,9 @@ import { SelectSeparator, SelectTrigger, SelectValue, -} from "./ui/select"; +} from './ui/select'; -const NEW_FOLDER_TOKEN = "__remotion_new_folder"; +const NEW_FOLDER_TOKEN = '__remotion_new_folder'; export const SelectedFolder: React.FC<{ readonly folders: string[]; @@ -45,13 +45,13 @@ export const SelectedFolder: React.FC<{ return (
-
Save to:
+
Save to:
- {state.status === "invoking" ? ( + {state.status === 'invoking' ? ( <>
-
+
{state.phase} {state.progress < 1 ? ` ${Math.max(Math.round(state.progress * 100), 1)}%` @@ -56,23 +56,23 @@ export const RenderControls: React.FC<{
- {state.subtitle ?? "\u00A0"} + {state.subtitle ?? '\u00A0'}
) : null} - {state.status === "error" ? ( + {state.status === 'error' ? ( ) : null} ) : null} - {state.status === "done" ? ( + {state.status === 'done' ? ( <> diff --git a/packages/template-vercel/src/components/Spacing.tsx b/packages/template-vercel/src/components/Spacing.tsx index c901cfdadb6..742905d320b 100644 --- a/packages/template-vercel/src/components/Spacing.tsx +++ b/packages/template-vercel/src/components/Spacing.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; export const Spacing: React.FC = () => { return
; diff --git a/packages/template-vercel/src/components/Spinner.tsx b/packages/template-vercel/src/components/Spinner.tsx index 405f2260c1a..e1cae300fab 100644 --- a/packages/template-vercel/src/components/Spinner.tsx +++ b/packages/template-vercel/src/components/Spinner.tsx @@ -1,6 +1,6 @@ -import React, { useMemo } from "react"; -import { makeRect } from "@remotion/shapes"; -import { translatePath } from "@remotion/paths"; +import { translatePath } from '@remotion/paths'; +import { makeRect } from '@remotion/shapes'; +import React, { useMemo } from 'react'; const viewBox = 100; const lines = 12; @@ -32,7 +32,7 @@ export const Spinner: React.FC<{ className="animate-spinner" style={{ rotate: `${(index * Math.PI * 2) / lines}rad`, - transformOrigin: "center center", + transformOrigin: 'center center', animationDelay: `${index * 0.1 - lines * 0.1}s`, }} key={index} diff --git a/packages/template-vercel/src/components/Tips.tsx b/packages/template-vercel/src/components/Tips.tsx index 3f88e15754b..dbfb3b90508 100644 --- a/packages/template-vercel/src/components/Tips.tsx +++ b/packages/template-vercel/src/components/Tips.tsx @@ -1,4 +1,4 @@ -import React from "react"; +import React from 'react'; const Tip: React.FC<{ title: React.ReactNode; diff --git a/packages/template-vercel/src/helpers/api-response.ts b/packages/template-vercel/src/helpers/api-response.ts index d4da4ce7862..574a3134aec 100644 --- a/packages/template-vercel/src/helpers/api-response.ts +++ b/packages/template-vercel/src/helpers/api-response.ts @@ -1,13 +1,13 @@ -import { NextResponse } from "next/server"; -import { z, ZodType } from "zod"; +import { NextResponse } from 'next/server'; +import { z, ZodType } from 'zod'; export type ApiResponse = | { - type: "error"; + type: 'error'; message: string; } | { - type: "success"; + type: 'success'; data: Res; }; @@ -22,12 +22,12 @@ export const executeApi = const parsed = schema.parse(payload); const data = await handler(req, parsed); return NextResponse.json({ - type: "success", + type: 'success', data: data, }); } catch (err) { return NextResponse.json( - { type: "error", message: (err as Error).message }, + { type: 'error', message: (err as Error).message }, { status: 500, }, diff --git a/packages/template-vercel/src/helpers/use-rendering.ts b/packages/template-vercel/src/helpers/use-rendering.ts index 3fd6783a98b..0e57ab29898 100644 --- a/packages/template-vercel/src/helpers/use-rendering.ts +++ b/packages/template-vercel/src/helpers/use-rendering.ts @@ -1,26 +1,26 @@ -import { z } from "zod"; -import { useCallback, useMemo, useState } from "react"; -import { CompositionProps } from "../../types/constants"; -import { SSEMessage } from "../../types/schema"; +import { useCallback, useMemo, useState } from 'react'; +import { z } from 'zod'; +import { CompositionProps } from '../../types/constants'; +import { SSEMessage } from '../../types/schema'; export type State = | { - status: "init"; + status: 'init'; } | { - status: "invoking"; + status: 'invoking'; phase: string; progress: number; subtitle: string | null; } | { - status: "error"; + status: 'error'; error: Error; } | { url: string; size: number; - status: "done"; + status: 'done'; }; export const useRendering = ( @@ -28,49 +28,49 @@ export const useRendering = ( inputProps: z.infer, ) => { const [state, setState] = useState({ - status: "init", + status: 'init', }); const renderMedia = useCallback(async () => { setState({ - status: "invoking", - phase: "Starting...", + status: 'invoking', + phase: 'Starting...', progress: 0, subtitle: null, }); try { - const response = await fetch("/api/render", { - method: "POST", - headers: { "content-type": "application/json" }, + const response = await fetch('/api/render', { + method: 'POST', + headers: { 'content-type': 'application/json' }, body: JSON.stringify({ id, inputProps }), }); if (!response.ok || !response.body) { - throw new Error("Failed to start render"); + throw new Error('Failed to start render'); } const reader = response.body.getReader(); const decoder = new TextDecoder(); - let buffer = ""; + let buffer = ''; while (true) { const { done, value } = await reader.read(); if (done) break; buffer += decoder.decode(value, { stream: true }); - const lines = buffer.split("\n\n"); - buffer = lines.pop() || ""; + const lines = buffer.split('\n\n'); + buffer = lines.pop() || ''; for (const line of lines) { - if (!line.startsWith("data: ")) continue; + if (!line.startsWith('data: ')) continue; const json = line.slice(6); const message = JSON.parse(json) as SSEMessage; - if (message.type === "phase") { + if (message.type === 'phase') { setState((prev) => { - if (prev.status !== "invoking") return prev; + if (prev.status !== 'invoking') return prev; return { ...prev, phase: message.phase, @@ -78,15 +78,15 @@ export const useRendering = ( subtitle: message.subtitle ?? null, }; }); - } else if (message.type === "done") { + } else if (message.type === 'done') { setState({ - status: "done", + status: 'done', url: message.url, size: message.size, }); - } else if (message.type === "error") { + } else if (message.type === 'error') { setState({ - status: "error", + status: 'error', error: new Error(message.message), }); } @@ -94,14 +94,14 @@ export const useRendering = ( } } catch (err) { setState({ - status: "error", + status: 'error', error: err as Error, }); } }, [id, inputProps]); const undo = useCallback(() => { - setState({ status: "init" }); + setState({ status: 'init' }); }, []); return useMemo(() => { diff --git a/packages/template-vercel/src/lib/utils.ts b/packages/template-vercel/src/lib/utils.ts index a5ef193506d..2819a830d24 100644 --- a/packages/template-vercel/src/lib/utils.ts +++ b/packages/template-vercel/src/lib/utils.ts @@ -1,5 +1,5 @@ -import { clsx, type ClassValue } from "clsx"; -import { twMerge } from "tailwind-merge"; +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); diff --git a/packages/template-vercel/src/remotion/MyComp/Main.tsx b/packages/template-vercel/src/remotion/MyComp/Main.tsx index cf23037a594..10a75830723 100644 --- a/packages/template-vercel/src/remotion/MyComp/Main.tsx +++ b/packages/template-vercel/src/remotion/MyComp/Main.tsx @@ -1,20 +1,20 @@ -import { z } from "zod"; +import { fontFamily, loadFont } from '@remotion/google-fonts/Inter'; import { AbsoluteFill, Sequence, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; -import { CompositionProps } from "../../../types/constants"; -import { NextLogo } from "./NextLogo"; -import { loadFont, fontFamily } from "@remotion/google-fonts/Inter"; -import { Rings } from "./Rings"; -import { TextFade } from "./TextFade"; +} from 'remotion'; +import { z } from 'zod'; +import { CompositionProps } from '../../../types/constants'; +import { NextLogo } from './NextLogo'; +import { Rings } from './Rings'; +import { TextFade } from './TextFade'; -loadFont("normal", { - subsets: ["latin"], - weights: ["400", "700"], +loadFont('normal', { + subsets: ['latin'], + weights: ['400', '700'], }); export const Main = ({ title }: z.infer) => { const frame = useCurrentFrame(); diff --git a/packages/template-vercel/src/remotion/MyComp/NextLogo.tsx b/packages/template-vercel/src/remotion/MyComp/NextLogo.tsx index b7f87f6bf29..f5aacd6d5e5 100644 --- a/packages/template-vercel/src/remotion/MyComp/NextLogo.tsx +++ b/packages/template-vercel/src/remotion/MyComp/NextLogo.tsx @@ -1,9 +1,9 @@ -import { evolvePath } from "@remotion/paths"; -import React, { useMemo } from "react"; -import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"; +import { evolvePath } from '@remotion/paths'; +import React, { useMemo } from 'react'; +import { interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'; const nStroke = - "M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z"; + 'M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z'; export const NextLogo: React.FC<{ outProgress: number; diff --git a/packages/template-vercel/src/remotion/MyComp/Rings.tsx b/packages/template-vercel/src/remotion/MyComp/Rings.tsx index 8e27bae8569..d4aa3ce0122 100644 --- a/packages/template-vercel/src/remotion/MyComp/Rings.tsx +++ b/packages/template-vercel/src/remotion/MyComp/Rings.tsx @@ -1,5 +1,5 @@ -import React from "react"; -import { AbsoluteFill, interpolateColors, useVideoConfig } from "remotion"; +import React from 'react'; +import { AbsoluteFill, interpolateColors, useVideoConfig } from 'remotion'; const RadialGradient: React.FC<{ radius: number; @@ -11,8 +11,8 @@ const RadialGradient: React.FC<{ return (
); }) diff --git a/packages/template-vercel/src/remotion/MyComp/TextFade.tsx b/packages/template-vercel/src/remotion/MyComp/TextFade.tsx index 1b71930a0b9..09ddcd20be8 100644 --- a/packages/template-vercel/src/remotion/MyComp/TextFade.tsx +++ b/packages/template-vercel/src/remotion/MyComp/TextFade.tsx @@ -1,11 +1,11 @@ -import React, { useMemo } from "react"; +import React, { useMemo } from 'react'; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, -} from "remotion"; +} from 'remotion'; export const TextFade: React.FC<{ children: React.ReactNode; diff --git a/packages/template-vercel/src/remotion/Root.tsx b/packages/template-vercel/src/remotion/Root.tsx index 83276274db8..284b680e91d 100644 --- a/packages/template-vercel/src/remotion/Root.tsx +++ b/packages/template-vercel/src/remotion/Root.tsx @@ -1,5 +1,4 @@ -import { Composition } from "remotion"; -import { Main } from "./MyComp/Main"; +import { Composition } from 'remotion'; import { COMP_NAME, defaultMyCompProps, @@ -7,8 +6,9 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from "../../types/constants"; -import { NextLogo } from "./MyComp/NextLogo"; +} from '../../types/constants'; +import { Main } from './MyComp/Main'; +import { NextLogo } from './MyComp/NextLogo'; export const RemotionRoot: React.FC = () => { return ( diff --git a/packages/template-vercel/src/remotion/index.ts b/packages/template-vercel/src/remotion/index.ts index 23d7a0fb208..092fe6e97d3 100644 --- a/packages/template-vercel/src/remotion/index.ts +++ b/packages/template-vercel/src/remotion/index.ts @@ -1,5 +1,5 @@ -import { registerRoot } from "remotion"; -import { RemotionRoot } from "./Root"; -import "../../styles/global.css"; +import { registerRoot } from 'remotion'; +import '../../styles/global.css'; +import { RemotionRoot } from './Root'; registerRoot(RemotionRoot); diff --git a/packages/webcodecs/src/test/stbl.test.ts b/packages/webcodecs/src/test/stbl.test.ts index 7e45768704b..63759bb529b 100644 --- a/packages/webcodecs/src/test/stbl.test.ts +++ b/packages/webcodecs/src/test/stbl.test.ts @@ -1,31 +1,22 @@ if (process.platform !== 'win32') { // @ts-expect-error const {expect, test} = await import('bun:test'); + // prettier-ignore // @ts-expect-error + const {createAvc1Data} = await import('../create/iso-base-media/codec-specific/avc1'); - const {createAvc1Data} = await import( - '../create/iso-base-media/codec-specific/avc1' - ); - + // prettier-ignore // @ts-expect-error - const {exampleVideoSamplePositions} = await import( - '../create/iso-base-media/example-stts' - ); + const {exampleVideoSamplePositions} = await import('../create/iso-base-media/example-stts'); + // prettier-ignore // @ts-expect-error - - const {createStbl} = await import( - '../create/iso-base-media/trak/mdia/minf/create-stbl' - ); + const {createStbl} = await import('../create/iso-base-media/trak/mdia/minf/create-stbl'); + // prettier-ignore // @ts-expect-error - - const {createAvccBox} = await import( - '../create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc' - ); + const {createAvccBox} = await import('../create/iso-base-media/trak/mdia/minf/stbl/stsd/create-avcc'); + // prettier-ignore // @ts-expect-error - - const {createPasp} = await import( - '../create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp' - ); + const {createPasp} = await import('../create/iso-base-media/trak/mdia/minf/stbl/stsd/create-pasp'); const sample = new Uint8Array([ 0, 0, 8, 125, 115, 116, 98, 108, 0, 0, 0, 177, 115, 116, 115, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 161, 97, 118, 99, 49, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, From 071c9b6d5ec829229060c407a150b97264d986e7 Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 13:28:47 +0100 Subject: [PATCH 08/30] hmm --- packages/lambda-go-example/package.json | 4 +- .../src/components/AlignEnd.tsx | 4 +- .../src/components/Button/Button.tsx | 10 ++--- .../src/components/Container.tsx | 14 +++---- .../src/components/DownloadButton.tsx | 32 +++++++-------- .../src/components/Error.tsx | 12 +++--- .../src/components/Input.tsx | 16 ++++---- .../src/components/ProgressBar.tsx | 12 +++--- .../src/components/RenderControls.tsx | 40 +++++++++---------- .../src/components/Spacing.tsx | 6 +-- .../src/components/Spinner/Spinner.tsx | 10 ++--- .../src/components/Tips/Tips.tsx | 22 +++++----- .../src/helpers/api-response.ts | 12 +++--- .../src/helpers/use-rendering.ts | 40 +++++++++---------- .../template-next-pages/src/lambda/api.ts | 20 +++++----- .../template-next-pages/src/pages/_app.tsx | 4 +- .../src/pages/api/lambda/progress.ts | 18 ++++----- .../src/pages/api/lambda/render.ts | 22 +++++----- .../template-next-pages/src/pages/index.tsx | 30 +++++++------- .../src/remotion/MyComp/Main.tsx | 28 ++++++------- .../src/remotion/MyComp/NextLogo.tsx | 10 ++--- .../src/remotion/MyComp/Rings.tsx | 16 ++++---- .../src/remotion/MyComp/TextFade.tsx | 8 ++-- .../template-next-pages/src/remotion/Root.tsx | 8 ++-- .../template-next-pages/src/remotion/index.ts | 4 +- 25 files changed, 200 insertions(+), 202 deletions(-) diff --git a/packages/lambda-go-example/package.json b/packages/lambda-go-example/package.json index 9ad72320af0..a3c7ce0320c 100644 --- a/packages/lambda-go-example/package.json +++ b/packages/lambda-go-example/package.json @@ -5,7 +5,5 @@ "name": "@remotion/lambda-go-example", "private": true, "version": "4.0.423", - "scripts": { - "lint": "node build.mjs" - } + "scripts": {} } diff --git a/packages/template-next-pages/src/components/AlignEnd.tsx b/packages/template-next-pages/src/components/AlignEnd.tsx index f7e736314bd..f08aa29ad5f 100644 --- a/packages/template-next-pages/src/components/AlignEnd.tsx +++ b/packages/template-next-pages/src/components/AlignEnd.tsx @@ -1,7 +1,7 @@ -import React from 'react'; +import React from "react"; const container: React.CSSProperties = { - alignSelf: 'flex-end', + alignSelf: "flex-end", }; export const AlignEnd: React.FC<{ diff --git a/packages/template-next-pages/src/components/Button/Button.tsx b/packages/template-next-pages/src/components/Button/Button.tsx index 8041ae33b2e..b697c903144 100644 --- a/packages/template-next-pages/src/components/Button/Button.tsx +++ b/packages/template-next-pages/src/components/Button/Button.tsx @@ -1,7 +1,7 @@ -import React, { forwardRef } from 'react'; -import { Spacing } from '../Spacing'; -import { Spinner } from '../Spinner/Spinner'; -import styles from './styles.module.css'; +import React, { forwardRef } from "react"; +import { Spacing } from "../Spacing"; +import { Spinner } from "../Spinner/Spinner"; +import styles from "./styles.module.css"; const ButtonForward: React.ForwardRefRenderFunction< HTMLButtonElement, @@ -19,7 +19,7 @@ const ButtonForward: React.ForwardRefRenderFunction< className={[ styles.button, secondary ? styles.secondarybutton : undefined, - ].join(' ')} + ].join(" ")} onClick={onClick} disabled={disabled} > diff --git a/packages/template-next-pages/src/components/Container.tsx b/packages/template-next-pages/src/components/Container.tsx index 4ad9da288f8..71fe2f9b7ea 100644 --- a/packages/template-next-pages/src/components/Container.tsx +++ b/packages/template-next-pages/src/components/Container.tsx @@ -1,12 +1,12 @@ -import React from 'react'; +import React from "react"; const inputContainer: React.CSSProperties = { - border: '1px solid var(--unfocused-border-color)', - padding: 'var(--geist-pad)', - borderRadius: 'var(--geist-border-radius)', - backgroundColor: 'var(--background)', - display: 'flex', - flexDirection: 'column', + border: "1px solid var(--unfocused-border-color)", + padding: "var(--geist-pad)", + borderRadius: "var(--geist-border-radius)", + backgroundColor: "var(--background)", + display: "flex", + flexDirection: "column", }; export const InputContainer: React.FC<{ diff --git a/packages/template-next-pages/src/components/DownloadButton.tsx b/packages/template-next-pages/src/components/DownloadButton.tsx index 6ba33109202..ac1b8fd5a73 100644 --- a/packages/template-next-pages/src/components/DownloadButton.tsx +++ b/packages/template-next-pages/src/components/DownloadButton.tsx @@ -1,30 +1,30 @@ -import Link from 'next/link'; -import React from 'react'; -import { State } from '../helpers/use-rendering'; -import { Button } from './Button/Button'; -import { Spacing } from './Spacing'; +import Link from "next/link"; +import React from "react"; +import { State } from "../helpers/use-rendering"; +import { Button } from "./Button/Button"; +import { Spacing } from "./Spacing"; const light: React.CSSProperties = { opacity: 0.6, }; const link: React.CSSProperties = { - textDecoration: 'none', + textDecoration: "none", }; const row: React.CSSProperties = { - display: 'flex', - flexDirection: 'row', + display: "flex", + flexDirection: "row", }; const Megabytes: React.FC<{ sizeInBytes: number; }> = ({ sizeInBytes }) => { - const megabytes = Intl.NumberFormat('en', { - notation: 'compact', - style: 'unit', - unit: 'byte', - unitDisplay: 'narrow', + const megabytes = Intl.NumberFormat("en", { + notation: "compact", + style: "unit", + unit: "byte", + unitDisplay: "narrow", }).format(sizeInBytes); return {megabytes}; }; @@ -33,12 +33,12 @@ export const DownloadButton: React.FC<{ state: State; undo: () => void; }> = ({ state, undo }) => { - if (state.status === 'rendering') { + if (state.status === "rendering") { return ; } - if (state.status !== 'done') { - throw new Error('Download button should not be rendered when not done'); + if (state.status !== "done") { + throw new Error("Download button should not be rendered when not done"); } return ( diff --git a/packages/template-next-pages/src/components/Error.tsx b/packages/template-next-pages/src/components/Error.tsx index 05db53a70fe..7fa5d80fb3b 100644 --- a/packages/template-next-pages/src/components/Error.tsx +++ b/packages/template-next-pages/src/components/Error.tsx @@ -1,15 +1,15 @@ -import React from 'react'; +import React from "react"; const container: React.CSSProperties = { - color: 'var(--geist-error)', - fontFamily: 'var(--geist-font)', - paddingTop: 'var(--geist-half-pad)', - paddingBottom: 'var(--geist-half-pad)', + color: "var(--geist-error)", + fontFamily: "var(--geist-font)", + paddingTop: "var(--geist-half-pad)", + paddingBottom: "var(--geist-half-pad)", }; const icon: React.CSSProperties = { height: 20, - verticalAlign: 'text-bottom', + verticalAlign: "text-bottom", marginRight: 6, }; diff --git a/packages/template-next-pages/src/components/Input.tsx b/packages/template-next-pages/src/components/Input.tsx index 454c033c5c0..40b32dd4705 100644 --- a/packages/template-next-pages/src/components/Input.tsx +++ b/packages/template-next-pages/src/components/Input.tsx @@ -1,14 +1,14 @@ -import React, { useCallback } from 'react'; +import React, { useCallback } from "react"; const textarea: React.CSSProperties = { - resize: 'none', + resize: "none", lineHeight: 1.7, - display: 'block', - width: '100%', - borderRadius: 'var(--geist-border-radius)', - backgroundColor: 'var(--background)', - padding: 'var(--geist-half-pad)', - color: 'var(--foreground)', + display: "block", + width: "100%", + borderRadius: "var(--geist-border-radius)", + backgroundColor: "var(--background)", + padding: "var(--geist-half-pad)", + color: "var(--foreground)", fontSize: 14, }; diff --git a/packages/template-next-pages/src/components/ProgressBar.tsx b/packages/template-next-pages/src/components/ProgressBar.tsx index 011cf3196ac..f383f994cd5 100644 --- a/packages/template-next-pages/src/components/ProgressBar.tsx +++ b/packages/template-next-pages/src/components/ProgressBar.tsx @@ -1,15 +1,15 @@ -import React, { useMemo } from 'react'; +import React, { useMemo } from "react"; export const ProgressBar: React.FC<{ progress: number; }> = ({ progress }) => { const style: React.CSSProperties = useMemo(() => { return { - width: '100%', + width: "100%", height: 10, borderRadius: 5, - appearance: 'none', - backgroundColor: 'var(--unfocused-border-color)', + appearance: "none", + backgroundColor: "var(--unfocused-border-color)", marginTop: 10, marginBottom: 25, }; @@ -17,10 +17,10 @@ export const ProgressBar: React.FC<{ const fill: React.CSSProperties = useMemo(() => { return { - backgroundColor: 'var(--foreground)', + backgroundColor: "var(--foreground)", height: 10, borderRadius: 5, - transition: 'width 0.1s ease-in-out', + transition: "width 0.1s ease-in-out", width: `${progress * 100}%`, }; }, [progress]); diff --git a/packages/template-next-pages/src/components/RenderControls.tsx b/packages/template-next-pages/src/components/RenderControls.tsx index c81f470a9ab..3e5c9dd7727 100644 --- a/packages/template-next-pages/src/components/RenderControls.tsx +++ b/packages/template-next-pages/src/components/RenderControls.tsx @@ -1,14 +1,14 @@ -import { z } from 'zod'; -import { COMP_NAME, CompositionProps } from '../../types/constants'; -import { useRendering } from '../helpers/use-rendering'; -import { AlignEnd } from './AlignEnd'; -import { Button } from './Button/Button'; -import { InputContainer } from './Container'; -import { DownloadButton } from './DownloadButton'; -import { ErrorComp } from './Error'; -import { Input } from './Input'; -import { ProgressBar } from './ProgressBar'; -import { Spacing } from './Spacing'; +import { z } from "zod"; +import { COMP_NAME, CompositionProps } from "../../types/constants"; +import { useRendering } from "../helpers/use-rendering"; +import { AlignEnd } from "./AlignEnd"; +import { Button } from "./Button/Button"; +import { InputContainer } from "./Container"; +import { DownloadButton } from "./DownloadButton"; +import { ErrorComp } from "./Error"; +import { Input } from "./Input"; +import { ProgressBar } from "./ProgressBar"; +import { Spacing } from "./Spacing"; export const RenderControls: React.FC<{ text: string; @@ -19,34 +19,34 @@ export const RenderControls: React.FC<{ return ( - {state.status === 'init' || - state.status === 'invoking' || - state.status === 'error' ? ( + {state.status === "init" || + state.status === "invoking" || + state.status === "error" ? ( <> - {state.status === 'error' ? ( + {state.status === "error" ? ( ) : null} ) : null} - {state.status === 'rendering' || state.status === 'done' ? ( + {state.status === "rendering" || state.status === "done" ? ( <> diff --git a/packages/template-next-pages/src/components/Spacing.tsx b/packages/template-next-pages/src/components/Spacing.tsx index 8bb0b451b6d..31965a480c4 100644 --- a/packages/template-next-pages/src/components/Spacing.tsx +++ b/packages/template-next-pages/src/components/Spacing.tsx @@ -1,11 +1,11 @@ -import React from 'react'; +import React from "react"; export const Spacing: React.FC = () => { return (
); diff --git a/packages/template-next-pages/src/components/Spinner/Spinner.tsx b/packages/template-next-pages/src/components/Spinner/Spinner.tsx index 098d16fd2ea..a15056424e3 100644 --- a/packages/template-next-pages/src/components/Spinner/Spinner.tsx +++ b/packages/template-next-pages/src/components/Spinner/Spinner.tsx @@ -1,7 +1,7 @@ -import { translatePath } from '@remotion/paths'; -import { makeRect } from '@remotion/shapes'; -import React, { useMemo } from 'react'; -import styles from './styles.module.css'; +import { translatePath } from "@remotion/paths"; +import { makeRect } from "@remotion/shapes"; +import React, { useMemo } from "react"; +import styles from "./styles.module.css"; const viewBox = 100; const lines = 12; @@ -33,7 +33,7 @@ export const Spinner: React.FC<{ className={styles.line} style={{ rotate: `${(index * Math.PI * 2) / lines}rad`, - transformOrigin: 'center center', + transformOrigin: "center center", animationDelay: `${index * 0.1 - lines * 0.1}s`, }} key={index} diff --git a/packages/template-next-pages/src/components/Tips/Tips.tsx b/packages/template-next-pages/src/components/Tips/Tips.tsx index d8f5498bf7a..3b26ca9c0b8 100644 --- a/packages/template-next-pages/src/components/Tips/Tips.tsx +++ b/packages/template-next-pages/src/components/Tips/Tips.tsx @@ -1,22 +1,22 @@ -import React from 'react'; -import styles from './styles.module.css'; +import React from "react"; +import styles from "./styles.module.css"; const titlerow: React.CSSProperties = { - display: 'flex', - flexDirection: 'row', - alignItems: 'center', - justifyContent: 'flex-start', + display: "flex", + flexDirection: "row", + alignItems: "center", + justifyContent: "flex-start", }; const titlestyle: React.CSSProperties = { - marginBottom: '0.75em', - marginTop: '0.75em', - color: 'var(--foreground)', + marginBottom: "0.75em", + marginTop: "0.75em", + color: "var(--foreground)", }; const a: React.CSSProperties = { - textDecoration: 'none', - color: 'inherit', + textDecoration: "none", + color: "inherit", flex: 1, }; diff --git a/packages/template-next-pages/src/helpers/api-response.ts b/packages/template-next-pages/src/helpers/api-response.ts index cc2fbf8c2ea..33a9cb8afde 100644 --- a/packages/template-next-pages/src/helpers/api-response.ts +++ b/packages/template-next-pages/src/helpers/api-response.ts @@ -1,13 +1,13 @@ -import { NextApiRequest, NextApiResponse } from 'next'; -import { z, ZodType } from 'zod'; +import { NextApiRequest, NextApiResponse } from "next"; +import { z, ZodType } from "zod"; export type ApiResponse = | { - type: 'error'; + type: "error"; message: string; } | { - type: 'success'; + type: "success"; data: Res; }; @@ -25,10 +25,10 @@ export const executeApi = const parsed = schema.parse(req.body); const data = await handler(req, parsed, res); res.status(200).json({ - type: 'success', + type: "success", data: data, }); } catch (err) { - res.status(500).json({ type: 'error', message: (err as Error).message }); + res.status(500).json({ type: "error", message: (err as Error).message }); } }; diff --git a/packages/template-next-pages/src/helpers/use-rendering.ts b/packages/template-next-pages/src/helpers/use-rendering.ts index c871bfc6f2a..072b4e93d05 100644 --- a/packages/template-next-pages/src/helpers/use-rendering.ts +++ b/packages/template-next-pages/src/helpers/use-rendering.ts @@ -1,30 +1,30 @@ -import { useCallback, useMemo, useState } from 'react'; -import { z } from 'zod'; -import { CompositionProps } from '../../types/constants'; -import { getProgress, renderVideo } from '../lambda/api'; +import { useCallback, useMemo, useState } from "react"; +import { z } from "zod"; +import { CompositionProps } from "../../types/constants"; +import { getProgress, renderVideo } from "../lambda/api"; export type State = | { - status: 'init'; + status: "init"; } | { - status: 'invoking'; + status: "invoking"; } | { renderId: string; bucketName: string; progress: number; - status: 'rendering'; + status: "rendering"; } | { renderId: string | null; - status: 'error'; + status: "error"; error: Error; } | { url: string; size: number; - status: 'done'; + status: "done"; }; const wait = async (milliSeconds: number) => { @@ -40,17 +40,17 @@ export const useRendering = ( inputProps: z.infer, ) => { const [state, setState] = useState({ - status: 'init', + status: "init", }); const renderMedia = useCallback(async () => { setState({ - status: 'invoking', + status: "invoking", }); try { const { renderId, bucketName } = await renderVideo({ id, inputProps }); setState({ - status: 'rendering', + status: "rendering", progress: 0, renderId: renderId, bucketName: bucketName, @@ -64,27 +64,27 @@ export const useRendering = ( bucketName: bucketName, }); switch (result.type) { - case 'error': { + case "error": { setState({ - status: 'error', + status: "error", renderId: renderId, error: new Error(result.message), }); pending = false; break; } - case 'done': { + case "done": { setState({ size: result.size, url: result.url, - status: 'done', + status: "done", }); pending = false; break; } - case 'progress': { + case "progress": { setState({ - status: 'rendering', + status: "rendering", bucketName: bucketName, progress: result.progress, renderId: renderId, @@ -95,7 +95,7 @@ export const useRendering = ( } } catch (err) { setState({ - status: 'error', + status: "error", error: err as Error, renderId: null, }); @@ -103,7 +103,7 @@ export const useRendering = ( }, [id, inputProps]); const undo = useCallback(() => { - setState({ status: 'init' }); + setState({ status: "init" }); }, []); return useMemo(() => { diff --git a/packages/template-next-pages/src/lambda/api.ts b/packages/template-next-pages/src/lambda/api.ts index 44de9effdbb..74a8e550568 100644 --- a/packages/template-next-pages/src/lambda/api.ts +++ b/packages/template-next-pages/src/lambda/api.ts @@ -1,26 +1,26 @@ -import type { RenderMediaOnLambdaOutput } from '@remotion/lambda/client'; -import { z } from 'zod'; -import { CompositionProps } from '../../types/constants'; +import type { RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; +import { z } from "zod"; +import { CompositionProps } from "../../types/constants"; import { ProgressRequest, ProgressResponse, RenderRequest, -} from '../../types/schema'; -import { ApiResponse } from '../helpers/api-response'; +} from "../../types/schema"; +import { ApiResponse } from "../helpers/api-response"; const makeRequest = async ( endpoint: string, body: unknown, ): Promise => { const result = await fetch(endpoint, { - method: 'post', + method: "post", body: JSON.stringify(body), headers: { - 'content-type': 'application/json', + "content-type": "application/json", }, }); const json = (await result.json()) as ApiResponse; - if (json.type === 'error') { + if (json.type === "error") { throw new Error(json.message); } @@ -39,7 +39,7 @@ export const renderVideo = async ({ inputProps, }; - return makeRequest('/api/lambda/render', body); + return makeRequest("/api/lambda/render", body); }; export const getProgress = async ({ @@ -54,5 +54,5 @@ export const getProgress = async ({ bucketName, }; - return makeRequest('/api/lambda/progress', body); + return makeRequest("/api/lambda/progress", body); }; diff --git a/packages/template-next-pages/src/pages/_app.tsx b/packages/template-next-pages/src/pages/_app.tsx index 762bde25b83..a8f5489dcf6 100644 --- a/packages/template-next-pages/src/pages/_app.tsx +++ b/packages/template-next-pages/src/pages/_app.tsx @@ -1,5 +1,5 @@ -import type { AppProps } from 'next/app'; -import '../../styles/global.css'; +import type { AppProps } from "next/app"; +import "../../styles/global.css"; function MyApp({ Component, pageProps }: AppProps) { return ; diff --git a/packages/template-next-pages/src/pages/api/lambda/progress.ts b/packages/template-next-pages/src/pages/api/lambda/progress.ts index 1c8bce8424f..456106b01cc 100644 --- a/packages/template-next-pages/src/pages/api/lambda/progress.ts +++ b/packages/template-next-pages/src/pages/api/lambda/progress.ts @@ -2,16 +2,16 @@ import { AwsRegion, getRenderProgress, speculateFunctionName, -} from '@remotion/lambda/client'; -import { DISK, RAM, REGION, TIMEOUT } from '../../../../config.mjs'; -import { ProgressRequest, ProgressResponse } from '../../../../types/schema'; -import { executeApi } from '../../../helpers/api-response'; +} from "@remotion/lambda/client"; +import { DISK, RAM, REGION, TIMEOUT } from "../../../../config.mjs"; +import { ProgressRequest, ProgressResponse } from "../../../../types/schema"; +import { executeApi } from "../../../helpers/api-response"; const progress = executeApi( ProgressRequest, async (req, body) => { - if (req.method !== 'POST') { - throw new Error('Only POST requests are allowed'); + if (req.method !== "POST") { + throw new Error("Only POST requests are allowed"); } const renderProgress = await getRenderProgress({ @@ -27,21 +27,21 @@ const progress = executeApi( if (renderProgress.fatalErrorEncountered) { return { - type: 'error', + type: "error", message: renderProgress.errors[0].message, }; } if (renderProgress.done) { return { - type: 'done', + type: "done", url: renderProgress.outputFile as string, size: renderProgress.outputSizeInBytes as number, }; } return { - type: 'progress', + type: "progress", progress: Math.max(0.03, renderProgress.overallProgress), }; }, diff --git a/packages/template-next-pages/src/pages/api/lambda/render.ts b/packages/template-next-pages/src/pages/api/lambda/render.ts index eaa48168af3..4f22b1846d6 100644 --- a/packages/template-next-pages/src/pages/api/lambda/render.ts +++ b/packages/template-next-pages/src/pages/api/lambda/render.ts @@ -3,16 +3,16 @@ import { renderMediaOnLambda, RenderMediaOnLambdaOutput, speculateFunctionName, -} from '@remotion/lambda/client'; -import { DISK, RAM, REGION, SITE_NAME, TIMEOUT } from '../../../../config.mjs'; -import { RenderRequest } from '../../../../types/schema'; -import { executeApi } from '../../../helpers/api-response'; +} from "@remotion/lambda/client"; +import { DISK, RAM, REGION, SITE_NAME, TIMEOUT } from "../../../../config.mjs"; +import { RenderRequest } from "../../../../types/schema"; +import { executeApi } from "../../../helpers/api-response"; const render = executeApi( RenderRequest, async (req, body) => { - if (req.method !== 'POST') { - throw new Error('Only POST requests are allowed'); + if (req.method !== "POST") { + throw new Error("Only POST requests are allowed"); } if ( @@ -20,7 +20,7 @@ const render = executeApi( !process.env.REMOTION_AWS_ACCESS_KEY_ID ) { throw new TypeError( - 'Set up Remotion Lambda to render videos. See the README.md for how to do so.', + "Set up Remotion Lambda to render videos. See the README.md for how to do so.", ); } if ( @@ -28,12 +28,12 @@ const render = executeApi( !process.env.REMOTION_AWS_SECRET_ACCESS_KEY ) { throw new TypeError( - 'The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.', + "The environment variable REMOTION_AWS_SECRET_ACCESS_KEY is missing. Add it to your .env file.", ); } const result = await renderMediaOnLambda({ - codec: 'h264', + codec: "h264", functionName: speculateFunctionName({ diskSizeInMb: DISK, memorySizeInMb: RAM, @@ -45,8 +45,8 @@ const render = executeApi( inputProps: body.inputProps, framesPerLambda: 10, downloadBehavior: { - type: 'download', - fileName: 'video.mp4', + type: "download", + fileName: "video.mp4", }, }); diff --git a/packages/template-next-pages/src/pages/index.tsx b/packages/template-next-pages/src/pages/index.tsx index 78845e8a7b9..b1342ab9737 100644 --- a/packages/template-next-pages/src/pages/index.tsx +++ b/packages/template-next-pages/src/pages/index.tsx @@ -1,8 +1,8 @@ -import { Player } from '@remotion/player'; -import type { NextPage } from 'next'; -import Head from 'next/head'; -import React, { useMemo, useState } from 'react'; -import { z } from 'zod'; +import { Player } from "@remotion/player"; +import type { NextPage } from "next"; +import Head from "next/head"; +import React, { useMemo, useState } from "react"; +import { z } from "zod"; import { CompositionProps, defaultMyCompProps, @@ -10,30 +10,30 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from '../../types/constants'; -import { RenderControls } from '../components/RenderControls'; -import { Spacing } from '../components/Spacing'; -import { Tips } from '../components/Tips/Tips'; -import { Main } from '../remotion/MyComp/Main'; +} from "../../types/constants"; +import { RenderControls } from "../components/RenderControls"; +import { Spacing } from "../components/Spacing"; +import { Tips } from "../components/Tips/Tips"; +import { Main } from "../remotion/MyComp/Main"; const container: React.CSSProperties = { maxWidth: 768, - margin: 'auto', + margin: "auto", marginBottom: 20, paddingLeft: 16, paddingRight: 16, }; const outer: React.CSSProperties = { - borderRadius: 'var(--geist-border-radius)', - overflow: 'hidden', - boxShadow: '0 0 200px rgba(0, 0, 0, 0.15)', + borderRadius: "var(--geist-border-radius)", + overflow: "hidden", + boxShadow: "0 0 200px rgba(0, 0, 0, 0.15)", marginBottom: 40, marginTop: 60, }; const player: React.CSSProperties = { - width: '100%', + width: "100%", }; const Home: NextPage = () => { diff --git a/packages/template-next-pages/src/remotion/MyComp/Main.tsx b/packages/template-next-pages/src/remotion/MyComp/Main.tsx index dfaa1239ca8..1cd39c471e5 100644 --- a/packages/template-next-pages/src/remotion/MyComp/Main.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/Main.tsx @@ -1,30 +1,30 @@ -import { fontFamily, loadFont } from '@remotion/google-fonts/Inter'; -import React, { useMemo } from 'react'; +import { fontFamily, loadFont } from "@remotion/google-fonts/Inter"; +import React, { useMemo } from "react"; import { AbsoluteFill, Sequence, spring, useCurrentFrame, useVideoConfig, -} from 'remotion'; -import { z } from 'zod'; -import { CompositionProps } from '../../../types/constants'; -import { NextLogo } from './NextLogo'; -import { Rings } from './Rings'; -import { TextFade } from './TextFade'; +} from "remotion"; +import { z } from "zod"; +import { CompositionProps } from "../../../types/constants"; +import { NextLogo } from "./NextLogo"; +import { Rings } from "./Rings"; +import { TextFade } from "./TextFade"; -loadFont('normal', { - subsets: ['latin'], - weights: ['400', '700'], +loadFont("normal", { + subsets: ["latin"], + weights: ["400", "700"], }); const container: React.CSSProperties = { - backgroundColor: 'white', + backgroundColor: "white", }; const logo: React.CSSProperties = { - justifyContent: 'center', - alignItems: 'center', + justifyContent: "center", + alignItems: "center", }; export const Main = ({ title }: z.infer) => { diff --git a/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx b/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx index f2b477e1735..5d0f03ab6aa 100644 --- a/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/NextLogo.tsx @@ -1,13 +1,13 @@ -import { evolvePath } from '@remotion/paths'; -import React, { useMemo } from 'react'; -import { interpolate, spring, useCurrentFrame, useVideoConfig } from 'remotion'; +import { evolvePath } from "@remotion/paths"; +import React, { useMemo } from "react"; +import { interpolate, spring, useCurrentFrame, useVideoConfig } from "remotion"; const mask: React.CSSProperties = { - maskType: 'alpha', + maskType: "alpha", }; const nStroke = - 'M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z'; + "M149.508 157.52L69.142 54H54V125.97H66.1136V69.3836L139.999 164.845C143.333 162.614 146.509 160.165 149.508 157.52Z"; export const NextLogo: React.FC<{ outProgress: number; diff --git a/packages/template-next-pages/src/remotion/MyComp/Rings.tsx b/packages/template-next-pages/src/remotion/MyComp/Rings.tsx index 20801ee15f2..68adad54296 100644 --- a/packages/template-next-pages/src/remotion/MyComp/Rings.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/Rings.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { AbsoluteFill, interpolateColors, useVideoConfig } from 'remotion'; +import React from "react"; +import { AbsoluteFill, interpolateColors, useVideoConfig } from "remotion"; const RadialGradient: React.FC<{ radius: number; @@ -11,19 +11,19 @@ const RadialGradient: React.FC<{ return (
@@ -49,7 +49,7 @@ export const Rings: React.FC<{ ); }) diff --git a/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx b/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx index 1f3869b46f4..a9a0891aaad 100644 --- a/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx +++ b/packages/template-next-pages/src/remotion/MyComp/TextFade.tsx @@ -1,11 +1,11 @@ -import React, { useMemo } from 'react'; +import React, { useMemo } from "react"; import { AbsoluteFill, interpolate, spring, useCurrentFrame, useVideoConfig, -} from 'remotion'; +} from "remotion"; const outer: React.CSSProperties = {}; @@ -32,8 +32,8 @@ export const TextFade: React.FC<{ const container: React.CSSProperties = useMemo(() => { return { - justifyContent: 'center', - alignItems: 'center', + justifyContent: "center", + alignItems: "center", }; }, []); diff --git a/packages/template-next-pages/src/remotion/Root.tsx b/packages/template-next-pages/src/remotion/Root.tsx index 284b680e91d..35901f2f06a 100644 --- a/packages/template-next-pages/src/remotion/Root.tsx +++ b/packages/template-next-pages/src/remotion/Root.tsx @@ -1,4 +1,4 @@ -import { Composition } from 'remotion'; +import { Composition } from "remotion"; import { COMP_NAME, defaultMyCompProps, @@ -6,9 +6,9 @@ import { VIDEO_FPS, VIDEO_HEIGHT, VIDEO_WIDTH, -} from '../../types/constants'; -import { Main } from './MyComp/Main'; -import { NextLogo } from './MyComp/NextLogo'; +} from "../../types/constants"; +import { Main } from "./MyComp/Main"; +import { NextLogo } from "./MyComp/NextLogo"; export const RemotionRoot: React.FC = () => { return ( diff --git a/packages/template-next-pages/src/remotion/index.ts b/packages/template-next-pages/src/remotion/index.ts index 91fa0f3468e..f31c790edb3 100644 --- a/packages/template-next-pages/src/remotion/index.ts +++ b/packages/template-next-pages/src/remotion/index.ts @@ -1,4 +1,4 @@ -import { registerRoot } from 'remotion'; -import { RemotionRoot } from './Root'; +import { registerRoot } from "remotion"; +import { RemotionRoot } from "./Root"; registerRoot(RemotionRoot); From bbdc17b7970fcacff6d85b64403dee6d3d37465f Mon Sep 17 00:00:00 2001 From: Jonny Burger Date: Tue, 17 Feb 2026 13:30:50 +0100 Subject: [PATCH 09/30] run pretteir --- packages/skills/src/Root.tsx | 12 +- packages/skills/src/index.ts | 4 +- .../src/Audiogram/AudioVizContainer.tsx | 12 +- .../src/Audiogram/Captions.tsx | 26 +-- .../template-audiogram/src/Audiogram/Main.tsx | 56 +++---- .../src/Audiogram/Oscilloscope.tsx | 8 +- .../src/Audiogram/Spectrum.tsx | 10 +- .../src/Audiogram/WaitForFonts.tsx | 8 +- .../template-audiogram/src/Audiogram/Word.tsx | 20 +-- .../template-audiogram/src/Audiogram/font.ts | 6 +- .../Audiogram/get-number-of-lines-for-text.ts | 10 +- .../src/Audiogram/schema.ts | 18 +-- .../src/Audiogram/sentence-to-display.ts | 10 +- packages/template-audiogram/src/Root.tsx | 30 ++-- .../src/helpers/fetch-captions.ts | 8 +- packages/template-audiogram/src/index.ts | 4 +- packages/template-blank/src/Root.tsx | 4 +- packages/template-blank/src/index.ts | 4 +- .../template-code-hike/src/CodeTransition.tsx | 24 +-- packages/template-code-hike/src/Main.tsx | 24 +-- .../template-code-hike/src/ProgressBar.tsx | 20 +-- .../src/ReloadOnCodeChange.tsx | 10 +- packages/template-code-hike/src/Root.tsx | 12 +- .../src/annotations/Callout.tsx | 36 ++--- .../src/annotations/Error.tsx | 32 ++-- .../src/annotations/InlineToken.tsx | 6 +- .../calculate-metadata/calculate-metadata.tsx | 30 ++-- .../src/calculate-metadata/get-files.ts | 4 +- .../src/calculate-metadata/process-snippet.ts | 24 +-- .../src/calculate-metadata/schema.ts | 10 +- .../src/calculate-metadata/theme.tsx | 52 +++--- packages/template-code-hike/src/font.ts | 8 +- packages/template-code-hike/src/index.ts | 4 +- packages/template-code-hike/src/utils.ts | 6 +- .../template-helloworld/src/HelloWorld.tsx | 18 +-- .../src/HelloWorld/Arc.tsx | 6 +- .../src/HelloWorld/Atom.tsx | 6 +- .../src/HelloWorld/Logo.tsx | 10 +- .../src/HelloWorld/Subtitle.tsx | 12 +- .../src/HelloWorld/Title.tsx | 18 +-- .../src/HelloWorld/constants.ts | 4 +- packages/template-helloworld/src/Root.tsx | 18 +-- packages/template-helloworld/src/index.ts | 4 +- .../src/HelloWorld/Arc.jsx | 8 +- .../src/HelloWorld/Atom.jsx | 8 +- .../src/HelloWorld/Logo.jsx | 6 +- .../src/HelloWorld/Subtitle.jsx | 10 +- .../src/HelloWorld/Title.jsx | 16 +- .../src/HelloWorld/constants.js | 6 +- .../src/HelloWorld/index.jsx | 14 +- packages/template-javascript/src/Root.jsx | 10 +- packages/template-javascript/src/index.js | 4 +- .../template-music-visualization/src/Root.tsx | 24 +-- .../src/Visualizer/BassOverlay.tsx | 6 +- .../src/Visualizer/Main.tsx | 36 ++--- .../src/Visualizer/SongInfo.tsx | 30 ++-- .../src/Visualizer/Spectrum.tsx | 30 ++-- .../src/Visualizer/Waveform.tsx | 6 +- .../src/helpers/WaitForFonts.tsx | 8 +- .../src/helpers/font.ts | 8 +- .../src/helpers/schema.ts | 16 +- .../template-music-visualization/src/index.ts | 4 +- .../src/app/api/lambda/progress/route.ts | 14 +- .../src/app/api/lambda/render/route.ts | 18 +-- .../src/app/layout.tsx | 10 +- .../src/app/page.tsx | 22 +-- .../src/components/AlignEnd.tsx | 2 +- .../src/components/Button.tsx | 12 +- .../src/components/Container.tsx | 2 +- .../src/components/DownloadButton.tsx | 24 +-- .../src/components/Error.tsx | 2 +- .../src/components/Input.tsx | 2 +- .../src/components/ProgressBar.tsx | 2 +- .../src/components/RenderControls.tsx | 40 ++--- .../src/components/Spacing.tsx | 2 +- .../src/components/Spinner.tsx | 8 +- .../src/components/Tips.tsx | 2 +- .../src/helpers/api-response.ts | 12 +- .../src/helpers/use-rendering.ts | 40 ++--- .../src/lambda/api.ts | 20 +-- .../src/lib/utils.ts | 4 +- .../src/remotion/MyComp/Main.tsx | 20 +-- .../src/remotion/MyComp/NextLogo.tsx | 8 +- .../src/remotion/MyComp/Rings.tsx | 10 +- .../src/remotion/MyComp/TextFade.tsx | 4 +- .../src/remotion/Root.tsx | 8 +- .../src/remotion/index.ts | 6 +- .../src/app/api/lambda/progress/route.ts | 14 +- .../src/app/api/lambda/render/route.ts | 18 +-- packages/template-next-app/src/app/layout.tsx | 10 +- packages/template-next-app/src/app/page.tsx | 30 ++-- .../src/components/AlignEnd.tsx | 4 +- .../src/components/Button/Button.tsx | 10 +- .../src/components/Container.tsx | 14 +- .../src/components/DownloadButton.tsx | 30 ++-- .../src/components/Error.tsx | 12 +- .../src/components/Input.tsx | 16 +- .../src/components/ProgressBar.tsx | 12 +- .../src/components/RenderControls.tsx | 40 ++--- .../src/components/Spacing.tsx | 6 +- .../src/components/Spinner/Spinner.tsx | 10 +- .../src/components/Tips/Tips.tsx | 22 +-- .../src/helpers/api-response.ts | 12 +- .../src/helpers/use-rendering.ts | 40 ++--- packages/template-next-app/src/lambda/api.ts | 20 +-- .../src/remotion/MyComp/Main.tsx | 28 ++-- .../src/remotion/MyComp/NextLogo.tsx | 10 +- .../src/remotion/MyComp/Rings.tsx | 16 +- .../src/remotion/MyComp/TextFade.tsx | 8 +- .../template-next-app/src/remotion/Root.tsx | 8 +- .../template-next-app/src/remotion/index.ts | 4 +- .../template-next-app/src/types/constants.ts | 6 +- .../template-next-app/src/types/schema.ts | 10 +- packages/template-overlay/src/Overlay.tsx | 22 +-- packages/template-overlay/src/Root.tsx | 4 +- packages/template-overlay/src/index.ts | 4 +- .../src/app/api/generate/route.ts | 150 +++++++++--------- .../src/app/api/lambda/progress/route.ts | 14 +- .../src/app/api/lambda/render/route.ts | 20 +-- .../src/app/code-examples/page.tsx | 36 ++--- .../src/app/generate/page.tsx | 50 +++--- .../src/app/layout.tsx | 10 +- .../src/app/page.tsx | 18 +-- .../RenderControls/DownloadButton.tsx | 22 +-- .../AnimationPlayer/RenderControls/Error.tsx | 8 +- .../RenderControls/ProgressBar.tsx | 2 +- .../AnimationPlayer/RenderControls/index.tsx | 40 ++--- .../AnimationPlayer/SettingsModal.tsx | 10 +- .../src/components/AnimationPlayer/index.tsx | 36 ++--- .../components/ChatSidebar/ChatHistory.tsx | 38 ++--- .../src/components/ChatSidebar/ChatInput.tsx | 30 ++-- .../components/ChatSidebar/ChatSidebar.tsx | 36 ++--- .../src/components/ChatSidebar/index.ts | 2 +- .../src/components/CodeEditor/CodeEditor.tsx | 52 +++--- .../src/components/CodeEditor/CopyButton.tsx | 8 +- .../components/CodeEditor/EditorHeader.tsx | 6 +- .../CodeEditor/StreamingOverlay.tsx | 6 +- .../src/components/CodeEditor/index.ts | 2 +- .../src/components/ErrorDisplay.tsx | 50 +++--- .../src/components/Header.tsx | 2 +- .../src/components/LandingPageInput.tsx | 34 ++-- .../src/components/PageLayout.tsx | 4 +- .../src/components/TabPanel.tsx | 26 +-- .../src/components/ui/alert.tsx | 24 +-- .../src/components/ui/button.tsx | 42 ++--- .../src/components/ui/dialog.tsx | 26 +-- .../src/components/ui/select.tsx | 38 ++--- .../src/components/ui/spinner.tsx | 8 +- .../src/components/ui/tooltip.tsx | 10 +- .../src/examples/code/animated-shapes.ts | 10 +- .../src/examples/code/falling-spheres.ts | 10 +- .../src/examples/code/gold-price-chart.ts | 10 +- .../src/examples/code/histogram.ts | 10 +- .../src/examples/code/index.ts | 22 +-- .../src/examples/code/lottie-animation.ts | 10 +- .../src/examples/code/progress-bar.ts | 10 +- .../src/examples/code/text-rotation.ts | 10 +- .../src/examples/code/typewriter-highlight.ts | 10 +- .../src/examples/code/word-carousel.ts | 10 +- .../src/examples/prompts.ts | 40 ++--- .../src/helpers/api-response.ts | 12 +- .../src/helpers/capture-frame.ts | 10 +- .../src/helpers/sanitize-response.ts | 14 +- .../src/helpers/use-rendering.ts | 40 ++--- .../src/hooks/useAnimationState.ts | 8 +- .../src/hooks/useAutoCorrection.ts | 20 +-- .../src/hooks/useConversationState.ts | 30 ++-- .../src/hooks/useGenerationApi.ts | 76 ++++----- .../src/hooks/useImageAttachments.ts | 16 +- .../src/lambda/api.ts | 20 +-- .../src/lib/utils.ts | 4 +- .../src/markdown.d.ts | 2 +- .../src/remotion/DynamicComp.tsx | 34 ++-- .../src/remotion/Root.tsx | 6 +- .../src/remotion/compiler.ts | 134 ++++++++-------- .../src/remotion/index.ts | 4 +- .../src/skills/3d.md | 12 +- .../src/skills/charts.md | 32 ++-- .../src/skills/index.ts | 86 +++++----- .../src/skills/messaging.md | 86 ++++++---- .../src/skills/sequencing.md | 23 ++- .../src/skills/social-media.md | 32 ++-- .../src/skills/spring-physics.md | 24 +-- .../src/skills/transitions.md | 8 +- .../src/skills/typography.md | 1 - .../src/types/conversation.ts | 8 +- .../src/types/generation.ts | 20 +-- .../template-prompt-to-video/src/Root.tsx | 12 +- .../src/components/AIVideo.tsx | 42 ++--- .../src/components/Background.tsx | 12 +- .../src/components/Subtitle.tsx | 6 +- .../src/components/Word.tsx | 22 +-- .../template-prompt-to-video/src/index.ts | 4 +- .../template-prompt-to-video/src/lib/types.ts | 18 +-- .../template-prompt-to-video/src/lib/utils.ts | 10 +- packages/template-recorder/src/App.tsx | 56 +++---- .../template-recorder/src/BlinkingCircle.tsx | 4 +- .../template-recorder/src/CropIndicator.tsx | 12 +- packages/template-recorder/src/DeviceItem.tsx | 30 ++-- .../src/DevicePermission.tsx | 126 +++++++-------- packages/template-recorder/src/Logo.tsx | 2 +- .../template-recorder/src/PermissionError.tsx | 18 +-- .../src/PrefixAndResolution.tsx | 18 +-- .../template-recorder/src/RecordButton.tsx | 72 ++++----- .../template-recorder/src/RecordingView.tsx | 138 ++++++++-------- .../src/ResolutionLimiter.tsx | 44 ++--- packages/template-recorder/src/Rotate.tsx | 4 +- packages/template-recorder/src/Stream.tsx | 70 ++++---- packages/template-recorder/src/Timer.tsx | 4 +- packages/template-recorder/src/ToggleCrop.tsx | 4 +- .../template-recorder/src/ToggleMirror.tsx | 4 +- packages/template-recorder/src/TopBar.tsx | 48 +++--- .../src/WaitingForDevices.tsx | 6 +- .../src/actions/create-folder.ts | 8 +- .../src/actions/fetch-project-folders.ts | 8 +- .../src/components/ClearCurrentVideo.tsx | 16 +- .../src/components/CurrentAudio.tsx | 16 +- .../src/components/CurrentVideo.tsx | 30 ++-- .../src/components/Divider.tsx | 4 +- .../src/components/EnsureBrowserSupport.tsx | 22 +-- .../src/components/NewFolderDialog.tsx | 22 +-- .../src/components/ProcessingStatus.tsx | 12 +- .../src/components/RescanDevices.tsx | 6 +- .../src/components/SelectedFolder.tsx | 20 +-- .../src/components/Spinner.tsx | 2 +- .../src/components/StreamPicker.tsx | 42 ++--- .../src/components/UseThisTake.tsx | 80 +++++----- .../src/components/VolumeMeter.tsx | 36 ++--- .../src/components/theme-provider.tsx | 20 +-- .../src/components/ui/button.tsx | 38 ++--- .../src/components/ui/dialog.tsx | 24 +-- .../src/components/ui/dropdown-menu.tsx | 36 ++--- .../src/components/ui/input.tsx | 8 +- .../src/components/ui/label.tsx | 10 +- .../src/components/ui/select.tsx | 30 ++-- .../src/components/ui/toggle.tsx | 24 +-- .../src/helpers/browser-support.ts | 6 +- .../src/helpers/can-rotate-camera.ts | 6 +- .../src/helpers/cancel-transcribe.ts | 4 +- .../src/helpers/convert-in-browser.ts | 8 +- .../src/helpers/download-video.ts | 10 +- .../helpers/enumerate-devices-or-time-out.ts | 2 +- .../src/helpers/find-good-supported-codec.ts | 30 ++-- .../src/helpers/format-device-label.ts | 14 +- .../src/helpers/format-time.ts | 8 +- .../src/helpers/get-devices.ts | 14 +- .../src/helpers/get-folders.ts | 8 +- .../helpers/get-max-resolution-of-device.ts | 2 +- .../src/helpers/get-selected-video-source.ts | 26 +-- .../src/helpers/get-video-stream.ts | 26 +-- .../template-recorder/src/helpers/prefixes.ts | 2 +- .../src/helpers/start-media-recorder.ts | 22 +-- .../src/helpers/store-file.ts | 2 +- .../src/helpers/transcribe-video.ts | 26 +-- .../src/helpers/upload-file.ts | 10 +- .../src/helpers/use-element-size.ts | 10 +- .../src/helpers/use-key-press.ts | 6 +- .../template-recorder/src/helpers/utils.ts | 4 +- packages/template-recorder/src/main.tsx | 12 +- .../src/preferred-device-localstorage.ts | 10 +- .../src/preferred-resolution.ts | 4 +- .../src/state/media-sources.tsx | 32 ++-- .../src/state/visible-views.ts | 2 +- packages/template-skia/src/AssetManager.tsx | 18 +-- packages/template-skia/src/Drawing.tsx | 10 +- packages/template-skia/src/HelloSkia.tsx | 16 +- packages/template-skia/src/Root.tsx | 6 +- packages/template-skia/src/SkiaNeon.tsx | 28 ++-- packages/template-skia/src/index.ts | 6 +- packages/template-stargazer/src/Content.tsx | 66 ++++---- packages/template-stargazer/src/Main.tsx | 10 +- packages/template-stargazer/src/Root.tsx | 14 +- packages/template-stargazer/src/cache.ts | 4 +- .../src/fetch/fetch-data.ts | 10 +- .../src/fetch/via-graphql.ts | 18 +-- .../template-stargazer/src/fetch/via-rest.ts | 6 +- packages/template-stargazer/src/index.ts | 4 +- .../template-stargazer/src/repo-header.tsx | 38 ++--- .../src/wait-for-no-input.ts | 6 +- packages/template-still/src/PreviewCard.tsx | 42 ++--- packages/template-still/src/Root.tsx | 10 +- packages/template-still/src/Swirl.tsx | 6 +- packages/template-still/src/index.ts | 4 +- packages/template-still/src/server/cache.ts | 28 ++-- packages/template-still/src/server/config.ts | 8 +- packages/template-still/src/server/handler.ts | 6 +- .../template-still/src/server/image-types.ts | 22 +-- packages/template-still/src/server/index.ts | 36 ++--- .../template-still/src/server/make-hash.ts | 4 +- packages/template-still/src/server/s3.ts | 6 +- .../template-still/src/server/send-file.ts | 8 +- packages/template-three/src/Phone.tsx | 22 +-- packages/template-three/src/Root.tsx | 16 +- packages/template-three/src/RoundedBox.tsx | 6 +- packages/template-three/src/Scene.tsx | 24 +-- .../src/helpers/get-media-metadata.ts | 2 +- packages/template-three/src/helpers/layout.ts | 2 +- .../src/helpers/rounded-rectangle.ts | 2 +- packages/template-three/src/index.ts | 4 +- .../src/CaptionedVideo/NoCaptionFile.tsx | 12 +- .../src/CaptionedVideo/Page.tsx | 34 ++-- .../src/CaptionedVideo/SubtitlePage.tsx | 8 +- .../src/CaptionedVideo/index.tsx | 28 ++-- packages/template-tiktok/src/Root.tsx | 6 +- packages/template-tiktok/src/index.ts | 4 +- packages/template-tiktok/src/load-font.ts | 4 +- .../template-tts-azure/src/HelloWorld.tsx | 16 +- .../src/HelloWorld/Title.tsx | 16 +- packages/template-tts-azure/src/Root.tsx | 18 +-- packages/template-tts-azure/src/debounce.ts | 6 +- packages/template-tts-azure/src/index.ts | 4 +- packages/template-tts-azure/src/tts.ts | 20 +-- packages/template-tts-azure/src/types.ts | 6 +- .../template-tts-google/src/HelloWorld.tsx | 18 +-- .../src/HelloWorld/Title.tsx | 30 ++-- packages/template-tts-google/src/Root.tsx | 32 ++-- packages/template-tts-google/src/debounce.ts | 6 +- packages/template-tts-google/src/index.ts | 4 +- .../src/lib/client-utils.ts | 10 +- .../src/lib/firebase/index.ts | 6 +- .../src/lib/firebase/utils.ts | 4 +- .../template-tts-google/src/lib/interfaces.ts | 10 +- packages/template-tts-google/src/render.ts | 16 +- .../src/server/TextToSpeech/constants.ts | 12 +- .../src/server/TextToSpeech/index.ts | 16 +- .../template-tts-google/src/server/server.ts | 16 +- packages/template-tts-google/src/studio.ts | 10 +- .../src/app/api/render/helpers.ts | 14 +- .../src/app/api/render/render.ts | 36 ++--- .../src/app/api/render/route.ts | 36 ++--- .../src/app/api/render/sandbox/add-bundle.ts | 24 +-- .../app/api/render/sandbox/create-sandbox.ts | 40 ++--- .../app/api/render/sandbox/install-browser.ts | 18 +-- .../render/sandbox/install-js-dependencies.ts | 6 +- .../sandbox/install-system-dependencies.ts | 40 ++--- .../api/render/sandbox/patch-compositor.ts | 10 +- .../render/sandbox/reuse-or-create-sandbox.ts | 14 +- .../src/app/api/render/sandbox/snapshots.ts | 8 +- packages/template-vercel/src/app/layout.tsx | 10 +- packages/template-vercel/src/app/page.tsx | 20 +-- .../src/components/AlignEnd.tsx | 4 +- .../template-vercel/src/components/Button.tsx | 12 +- .../src/components/Container.tsx | 2 +- .../src/components/DownloadButton.tsx | 22 +-- .../template-vercel/src/components/Error.tsx | 2 +- .../template-vercel/src/components/Input.tsx | 2 +- .../src/components/ProgressBar.tsx | 2 +- .../src/components/RenderControls.tsx | 50 +++--- .../src/components/Spacing.tsx | 2 +- .../src/components/Spinner.tsx | 8 +- .../template-vercel/src/components/Tips.tsx | 2 +- .../src/helpers/api-response.ts | 12 +- .../src/helpers/use-rendering.ts | 54 +++---- packages/template-vercel/src/lib/utils.ts | 4 +- .../src/remotion/MyComp/Main.tsx | 20 +-- .../src/remotion/MyComp/NextLogo.tsx | 8 +- .../src/remotion/MyComp/Rings.tsx | 10 +- .../src/remotion/MyComp/TextFade.tsx | 4 +- .../template-vercel/src/remotion/Root.tsx | 8 +- .../template-vercel/src/remotion/index.ts | 6 +- 360 files changed, 3227 insertions(+), 3185 deletions(-) diff --git a/packages/skills/src/Root.tsx b/packages/skills/src/Root.tsx index c2a78dee443..df2ae5c7590 100644 --- a/packages/skills/src/Root.tsx +++ b/packages/skills/src/Root.tsx @@ -1,7 +1,7 @@ -import { Composition } from 'remotion'; -import { MyAnimation as BarChartAnimation } from '../skills/remotion/rules/assets/charts-bar-chart'; -import { MyAnimation as TypewriterAnimation } from '../skills/remotion/rules/assets/text-animations-typewriter'; -import { MyAnimation as WordHighlightAnimation } from '../skills/remotion/rules/assets/text-animations-word-highlight'; +import { Composition } from "remotion"; +import { MyAnimation as BarChartAnimation } from "../skills/remotion/rules/assets/charts-bar-chart"; +import { MyAnimation as TypewriterAnimation } from "../skills/remotion/rules/assets/text-animations-typewriter"; +import { MyAnimation as WordHighlightAnimation } from "../skills/remotion/rules/assets/text-animations-word-highlight"; export const RemotionRoot = () => { return ( @@ -22,8 +22,8 @@ export const RemotionRoot = () => { width={1920} height={1080} defaultProps={{ - fullText: 'From prompt to motion graphics. This is Remotion.', - pauseAfter: 'From prompt to motion graphics.', + fullText: "From prompt to motion graphics. This is Remotion.", + pauseAfter: "From prompt to motion graphics.", }} /> = ({ children, }) => { const containerStyle: React.CSSProperties = useMemo( () => ({ - display: 'flex', - flexDirection: 'row', + display: "flex", + flexDirection: "row", height: `${BASE_SIZE * 4}px`, - alignItems: 'center', - justifyContent: 'center', + alignItems: "center", + justifyContent: "center", gap: `${BASE_SIZE * 0.25}px`, marginTop: `${BASE_SIZE}px`, }), diff --git a/packages/template-audiogram/src/Audiogram/Captions.tsx b/packages/template-audiogram/src/Audiogram/Captions.tsx index a747a194260..6657af671d8 100644 --- a/packages/template-audiogram/src/Audiogram/Captions.tsx +++ b/packages/template-audiogram/src/Audiogram/Captions.tsx @@ -1,15 +1,15 @@ -import { Caption } from '@remotion/captions'; -import React, { useMemo, useRef } from 'react'; -import { useCurrentFrame } from 'remotion'; -import { msToFrame } from '../helpers/ms-to-frame'; -import { CAPTIONS_FONT_SIZE } from './constants'; -import { FONT_FAMILY } from './font'; +import { Caption } from "@remotion/captions"; +import React, { useMemo, useRef } from "react"; +import { useCurrentFrame } from "remotion"; +import { msToFrame } from "../helpers/ms-to-frame"; +import { CAPTIONS_FONT_SIZE } from "./constants"; +import { FONT_FAMILY } from "./font"; import { filterCurrentlyDisplayedLines, layoutText, -} from './get-number-of-lines-for-text'; -import { getSentenceToDisplay } from './sentence-to-display'; -import { Word } from './Word'; +} from "./get-number-of-lines-for-text"; +import { getSentenceToDisplay } from "./sentence-to-display"; +import { Word } from "./Word"; const useWindowedFrameCaptions = ({ captions, @@ -76,14 +76,14 @@ export const PaginatedCaptions: React.FC<{ return (
{currentlyShownLines.map((line) => ( -
item.text).join(' ')}> +
item.text).join(" ")}> {line.map((item) => ( = ({ visualizer, @@ -30,7 +30,7 @@ export const Audiogram: React.FC = ({ if (!captions) { throw new Error( - 'subtitles should have been provided through calculateMetadata', + "subtitles should have been provided through calculateMetadata", ); } @@ -45,44 +45,44 @@ export const Audiogram: React.FC = ({