diff --git a/bun.lock b/bun.lock index 28d4512badd..bfa7c93844c 100644 --- a/bun.lock +++ b/bun.lock @@ -10,6 +10,7 @@ "typescript": "5.9.3", }, "devDependencies": { + "@types/babel__standalone": "^7.1.9", "@types/bun": "catalog:", "@types/deno": "2.0.0", "@types/react": "catalog:", @@ -1395,6 +1396,69 @@ "typescript": "5.9.3", }, }, + "packages/template-code-generation": { + "name": "template-code-generation", + "version": "4.0.379", + "dependencies": { + "@ai-sdk/openai": "^2.0.74", + "@ai-sdk/react": "^2.0.104", + "@babel/standalone": "^7.28.5", + "@monaco-editor/react": "^4.7.0", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-tooltip": "^1.2.8", + "@react-three/fiber": "^9.4.2", + "@remotion/animated-emoji": "workspace:*", + "@remotion/bundler": "workspace:*", + "@remotion/cli": "workspace:*", + "@remotion/google-fonts": "workspace:*", + "@remotion/lambda": "workspace:*", + "@remotion/lottie": "workspace:*", + "@remotion/paths": "workspace:*", + "@remotion/player": "workspace:*", + "@remotion/shapes": "workspace:*", + "@remotion/tailwind-v4": "workspace:*", + "@remotion/three": "workspace:*", + "ai": "^5.0.104", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.555.0", + "monaco-editor": "^0.55.1", + "monaco-jsx-syntax-highlight": "^1.2.2", + "next": "16.0.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "remotion": "workspace:*", + "tailwind-merge": "^3.4.0", + "three": "^0.181.2", + "zod": "^4.1.13", + }, + "devDependencies": { + "@eslint/eslintrc": "3.1.0", + "@eslint/js": "9.38.0", + "@next/eslint-plugin-next": "15.1.6", + "@remotion/eslint-plugin": "workspace:*", + "@tailwindcss/postcss": "4.1.1", + "@types/node": "20.12.14", + "@types/react": "19.0.0", + "@types/react-dom": "19.0.0", + "@types/three": "^0.181.0", + "@types/web": "0.0.166", + "@typescript-eslint/eslint-plugin": "8.46.0", + "@typescript-eslint/parser": "8.46.0", + "autoprefixer": "10.4.20", + "dotenv": "16.0.3", + "eslint": "9.19.0", + "eslint-config-next": "15.1.6", + "postcss": "8.4.47", + "prettier": "3.6.0", + "tailwindcss": "4.0.3", + "tw-animate-css": "^1.4.0", + "typescript": "5.8.2", + "typescript-eslint": "8.46.0", + }, + }, "packages/template-code-hike": { "name": "template-code-hike", "version": "1.0.0", @@ -2125,6 +2189,16 @@ "packages": { "@aashutoshrathi/word-wrap": ["@aashutoshrathi/word-wrap@1.2.6", "", {}, "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA=="], + "@ai-sdk/gateway": ["@ai-sdk/gateway@2.0.17", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.18", "@vercel/oidc": "3.0.5" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-oVAG6q72KsjKlrYdLhWjRO7rcqAR8CjokAbYuyVZoCO4Uh2PH/VzZoxZav71w2ipwlXhHCNaInGYWNs889MMDA=="], + + "@ai-sdk/openai": ["@ai-sdk/openai@2.0.74", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.18" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-vvsL7rGoBEyQIePs630p31ebLeF+xxwLOrRKeIArHko8w7Wh9Kj3wL4Ns+PCzrEpAij31OKKDcxLQ1dSIg/qMw=="], + + "@ai-sdk/provider": ["@ai-sdk/provider@2.0.0", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-6o7Y2SeO9vFKB8lArHXehNuusnpddKPk7xqL7T2/b+OvXMRIXUO1rR4wcv1hAFUAT9avGZshty3Wlua/XA7TvA=="], + + "@ai-sdk/provider-utils": ["@ai-sdk/provider-utils@3.0.18", "", { "dependencies": { "@ai-sdk/provider": "2.0.0", "@standard-schema/spec": "^1.0.0", "eventsource-parser": "^3.0.6" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-ypv1xXMsgGcNKUP+hglKqtdDuMg68nWHucPPAhIENrbFAI+xCHiqPVN8Zllxyv1TNZwGWUghPxJXU+Mqps0YRQ=="], + + "@ai-sdk/react": ["@ai-sdk/react@2.0.104", "", { "dependencies": { "@ai-sdk/provider-utils": "3.0.18", "ai": "5.0.104", "swr": "^2.2.5", "throttleit": "2.1.0" }, "peerDependencies": { "react": "^18 || ^19 || ^19.0.0-rc", "zod": "^3.25.76 || ^4.1.8" }, "optionalPeers": ["zod"] }, "sha512-vpRNUwOrHXSsywZuEge78/LPbYMR/3tkBnwijGpIGnORMa/SzYhuVsE+sZBFVo/v0m5K/tg+CXNNvuJrVZ/MBQ=="], + "@algolia/abtesting": ["@algolia/abtesting@1.6.0", "", { "dependencies": { "@algolia/client-common": "5.40.0", "@algolia/requester-browser-xhr": "5.40.0", "@algolia/requester-fetch": "5.40.0", "@algolia/requester-node-http": "5.40.0" } }, "sha512-c4M/Z/KWkEG+RHpZsWKDTTlApXu3fe4vlABNcpankWBhdMe4oPZ/r4JxEr2zKUP6K+BT66tnp8UbHmgOd/vvqQ=="], "@algolia/autocomplete-core": ["@algolia/autocomplete-core@1.17.9", "", { "dependencies": { "@algolia/autocomplete-plugin-algolia-insights": "1.17.9", "@algolia/autocomplete-shared": "1.17.9" } }, "sha512-O7BxrpLDPJWWHv/DLA9DRFWs+iY1uOJZkqUwjS5HSZAGcl0hIVCQ97LTLewiZmZ402JYUrun+8NqFP+hCknlbQ=="], @@ -2517,6 +2591,8 @@ "@babel/runtime-corejs3": ["@babel/runtime-corejs3@7.26.0", "", { "dependencies": { "core-js-pure": "3.37.1", "regenerator-runtime": "0.14.1" } }, "sha512-YXHu5lN8kJCb1LOb9PgV6pvak43X2h4HvRApcN5SdWeaItQOzfn1hgP6jasD6KWQyJDBxrVmA9o9OivlnNJK/w=="], + "@babel/standalone": ["@babel/standalone@7.28.5", "", {}, "sha512-1DViPYJpRU50irpGMfLBQ9B4kyfQuL6X7SS7pwTeWeZX0mNkjzPi0XFqxCjSdddZXUQy4AhnQnnesA/ZHnvAdw=="], + "@babel/template": ["@babel/template@7.25.9", "", { "dependencies": { "@babel/code-frame": "7.26.2", "@babel/parser": "7.26.2", "@babel/types": "7.26.0" } }, "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg=="], "@babel/traverse": ["@babel/traverse@7.25.9", "", { "dependencies": { "@babel/code-frame": "7.27.1", "@babel/generator": "7.26.2", "@babel/parser": "7.26.2", "@babel/template": "7.25.9", "@babel/types": "7.26.0", "debug": "4.4.1", "globals": "11.12.0" } }, "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw=="], @@ -2615,6 +2691,8 @@ "@csstools/utilities": ["@csstools/utilities@2.0.0", "", { "peerDependencies": { "postcss": "8.5.1" } }, "sha512-5VdOr0Z71u+Yp3ozOx8T11N703wIFGVRgOWbOZMKgglPJsWA54MRIoMNVMa7shUToIhx5J8vX4sOZgD2XiihiQ=="], + "@dimforge/rapier3d-compat": ["@dimforge/rapier3d-compat@0.12.0", "", {}, "sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow=="], + "@discoveryjs/json-ext": ["@discoveryjs/json-ext@0.5.7", "", {}, "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw=="], "@docsearch/css": ["@docsearch/css@3.9.0", "", {}, "sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA=="], @@ -3009,6 +3087,10 @@ "@module-federation/webpack-bundler-runtime": ["@module-federation/webpack-bundler-runtime@0.18.0", "", { "dependencies": { "@module-federation/runtime": "0.18.0", "@module-federation/sdk": "0.18.0" } }, "sha512-TEvErbF+YQ+6IFimhUYKK3a5wapD90d90sLsNpcu2kB3QGT7t4nIluE25duXuZDVUKLz86tEPrza/oaaCWTpvQ=="], + "@monaco-editor/loader": ["@monaco-editor/loader@1.7.0", "", { "dependencies": { "state-local": "^1.0.6" } }, "sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA=="], + + "@monaco-editor/react": ["@monaco-editor/react@4.7.0", "", { "dependencies": { "@monaco-editor/loader": "^1.5.0" }, "peerDependencies": { "monaco-editor": ">= 0.25.0 < 1", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA=="], + "@monogrid/gainmap-js": ["@monogrid/gainmap-js@3.1.0", "", { "dependencies": { "promise-worker-transferable": "1.0.4" }, "peerDependencies": { "three": "0.178.0" } }, "sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw=="], "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.0.7", "", { "dependencies": { "@emnapi/core": "^1.5.0", "@emnapi/runtime": "^1.5.0", "@tybys/wasm-util": "^0.10.1" } }, "sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw=="], @@ -3193,6 +3275,8 @@ "@radix-ui/react-toggle": ["@radix-ui/react-toggle@1.1.9", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2" }, "peerDependencies": { "@types/react": "19.0.0", "@types/react-dom": "19.0.0", "react": "19.0.0", "react-dom": "19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-ZoFkBBz9zv9GWer7wIjvdRxmh2wyc2oKWw6C6CseWd6/yq1DK/l5lJ+wnsmFwJZbBYqr02mrf8A2q/CVCuM3ZA=="], + "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.8", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg=="], + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], "@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], @@ -3749,11 +3833,13 @@ "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0", "@types/babel__generator": "7.6.3", "@types/babel__template": "7.4.1", "@types/babel__traverse": "7.14.2" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], - "@types/babel__generator": ["@types/babel__generator@7.6.3", "", { "dependencies": { "@babel/types": "7.24.0" } }, "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA=="], + "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], + + "@types/babel__standalone": ["@types/babel__standalone@7.1.9", "", { "dependencies": { "@babel/parser": "^7.25.6", "@babel/types": "^7.25.6", "@types/babel__core": "^7.20.5", "@types/babel__generator": "^7.6.8", "@types/babel__template": "^7.4.4", "@types/babel__traverse": "^7.20.6" } }, "sha512-IcCNPLqpevUD7UpV8QB0uwQPOyoOKACFf0YtYWRHcmxcakaje4Q7dbG2+jMqxw/I8Zk0NHvEps66WwS7z/UaaA=="], - "@types/babel__template": ["@types/babel__template@7.4.1", "", { "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0" } }, "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g=="], + "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], - "@types/babel__traverse": ["@types/babel__traverse@7.14.2", "", { "dependencies": { "@babel/types": "7.24.0" } }, "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA=="], + "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], "@types/body-parser": ["@types/body-parser@1.19.1", "", { "dependencies": { "@types/connect": "3.4.38", "@types/node": "20.12.14" } }, "sha512-a6bTJ21vFOGIkwM0kzh9Yr89ziVxq4vYH2fQ6N8AeipEzai/cFK6aGMArIkUeIdRIgpwQa+2bXiLuUJCpSf2Cg=="], @@ -3943,6 +4029,8 @@ "@types/tough-cookie": ["@types/tough-cookie@4.0.5", "", {}, "sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA=="], + "@types/trusted-types": ["@types/trusted-types@2.0.7", "", {}, "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="], + "@types/unist": ["@types/unist@2.0.11", "", {}, "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA=="], "@types/uuid": ["@types/uuid@8.3.4", "", {}, "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw=="], @@ -4109,6 +4197,8 @@ "aggregate-error": ["aggregate-error@3.1.0", "", { "dependencies": { "clean-stack": "2.2.0", "indent-string": "4.0.0" } }, "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA=="], + "ai": ["ai@5.0.104", "", { "dependencies": { "@ai-sdk/gateway": "2.0.17", "@ai-sdk/provider": "2.0.0", "@ai-sdk/provider-utils": "3.0.18", "@opentelemetry/api": "1.9.0" }, "peerDependencies": { "zod": "^3.25.76 || ^4.1.8" } }, "sha512-MZOkL9++nY5PfkpWKBR3Rv+Oygxpb9S16ctv8h91GvrSif7UnNEdPMVZe3bUyMd2djxf0AtBk/csBixP0WwWZQ=="], + "ai-improvements": ["ai-improvements@workspace:packages/ai-improvements"], "ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "3.1.3", "fast-json-stable-stringify": "2.1.0", "json-schema-traverse": "0.4.1", "uri-js": "4.4.1" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], @@ -4645,6 +4735,8 @@ "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], + "dompurify": ["dompurify@3.2.7", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw=="], + "domutils": ["domutils@3.0.1", "", { "dependencies": { "dom-serializer": "2.0.0", "domelementtype": "2.3.0", "domhandler": "5.0.3" } }, "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q=="], "dot-case": ["dot-case@3.0.4", "", { "dependencies": { "no-case": "3.0.4", "tslib": "2.8.1" } }, "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w=="], @@ -5323,6 +5415,8 @@ "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], + "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], + "json-schema-to-ts": ["json-schema-to-ts@1.6.4", "", { "dependencies": { "@types/json-schema": "7.0.15", "ts-toolbelt": "6.15.5" } }, "sha512-pR4yQ9DHz6itqswtHCm26mw45FSNfQ9rEQjosaZErhn5J3J2sIViQiz8rDaezjKAhFGpmsoczYVBgGHzFw/stA=="], "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], @@ -5465,7 +5559,7 @@ "markdown-table": ["markdown-table@2.0.0", "", { "dependencies": { "repeat-string": "1.6.1" } }, "sha512-Ezda85ToJUBhM6WGaG6veasyym+Tbs3cMAw/ZhOPqXiYsr0jgocBV3j3nx+4lk47plLlIqjwuTm/ywVI+zjJ/A=="], - "marked": ["marked@4.3.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A=="], + "marked": ["marked@14.0.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ=="], "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], @@ -5651,6 +5745,10 @@ "modern-ahocorasick": ["modern-ahocorasick@1.0.1", "", {}, "sha512-yoe+JbhTClckZ67b2itRtistFKf8yPYelHLc7e5xAwtNAXxM6wJTUx2C7QeVSJFDzKT7bCIFyBVybPMKvmB9AA=="], + "monaco-editor": ["monaco-editor@0.55.1", "", { "dependencies": { "dompurify": "3.2.7", "marked": "14.0.0" } }, "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A=="], + + "monaco-jsx-syntax-highlight": ["monaco-jsx-syntax-highlight@1.2.2", "", {}, "sha512-V1JkspFJKIaRX5C2D3UuWjIz2xgWI+7slf+gMFgz8yIr0LSTl3AhD8Gk/7gvbMqp6pKOynIhWJEaluwwUtLz7w=="], + "morgan": ["morgan@1.10.0", "", { "dependencies": { "basic-auth": "2.0.1", "debug": "2.6.9", "depd": "2.0.0", "on-finished": "2.3.0", "on-headers": "1.0.2" } }, "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ=="], "mri": ["mri@1.2.0", "", {}, "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA=="], @@ -6463,6 +6561,8 @@ "stackback": ["stackback@0.0.2", "", {}, "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw=="], + "state-local": ["state-local@1.0.7", "", {}, "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="], + "stats-gl": ["stats-gl@2.4.2", "", { "peerDependencies": { "@types/three": "0.170.0", "three": "0.178.0" } }, "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ=="], "stats.js": ["stats.js@0.17.0", "", {}, "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw=="], @@ -6555,6 +6655,8 @@ "swc-loader": ["swc-loader@0.2.6", "", { "dependencies": { "@swc/counter": "0.1.3" }, "peerDependencies": { "@swc/core": "1.8.0", "webpack": "5.96.1" } }, "sha512-9Zi9UP2YmDpgmQVbyOPJClY0dwf58JDyDMQ7uRc4krmc72twNI2fvlBWHLqVekBpPc7h5NJkGVT1zNDxFrqhvg=="], + "swr": ["swr@2.3.7", "", { "dependencies": { "dequal": "^2.0.3", "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-ZEquQ82QvalqTxhBVv/DlAg2mbmUjF4UgpPg9wwk4ufb9rQnZXh1iKyyKBqV6bQGu1Ie7L1QwSYO07qFIa1p+g=="], + "tailwind-merge": ["tailwind-merge@2.5.2", "", {}, "sha512-kjEBm+pvD+6eAwzJL2Bi+02/9LFLal1Gs61+QB7HvTfQQ0aXwC5LGT8PEt1gS0CWKktKe6ysPTAy3cBC5MeiIg=="], "tailwindcss": ["tailwindcss@4.1.10", "", {}, "sha512-P3nr6WkvKV/ONsTzj6Gb57sWPMX29EPNPopo7+FcpkQaNsrNpZ1pv8QmrYI2RqEKD7mlGqLnGovlcYnBK0IqUA=="], @@ -6575,6 +6677,8 @@ "template-audiogram": ["template-audiogram@workspace:packages/template-audiogram"], + "template-code-generation": ["template-code-generation@workspace:packages/template-code-generation"], + "template-code-hike": ["template-code-hike@workspace:packages/template-code-hike"], "template-empty": ["template-empty@workspace:packages/template-blank"], @@ -6635,6 +6739,8 @@ "three-stdlib": ["three-stdlib@2.36.0", "", { "dependencies": { "@types/draco3d": "1.4.2", "@types/offscreencanvas": "2019.7.0", "@types/webxr": "0.5.2", "draco3d": "1.4.3", "fflate": "0.6.10", "potpack": "1.0.1" }, "peerDependencies": { "three": "0.178.0" } }, "sha512-kv0Byb++AXztEGsULgMAs8U2jgUdz6HPpAB/wDJnLiLlaWQX2APHhiTJIN7rqW+Of0eRgcp7jn05U1BsCP3xBA=="], + "throttleit": ["throttleit@2.1.0", "", {}, "sha512-nt6AMGKW1p/70DF/hGBdJB57B8Tspmbp5gfJ8ilhLnt7kkr2ye7hzD6NVG8GGErk2HWF34igrL2CXmNIkzKqKw=="], + "through2": ["through2@2.0.5", "", { "dependencies": { "readable-stream": "2.3.8", "xtend": "4.0.2" } }, "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ=="], "thunky": ["thunky@1.1.0", "", {}, "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA=="], @@ -6725,6 +6831,8 @@ "turbo-windows-arm64": ["turbo-windows-arm64@2.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-7w+AD5vJp3R+FB0YOj1YJcNcOOvBior7bcHTodqp90S3x3bLgpr7tE6xOea1e8JkP7GK6ciKVUpQvV7psiwU5Q=="], + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], + "twoslash": ["twoslash@0.3.1", "", { "dependencies": { "@typescript/vfs": "1.6.1", "twoslash-protocol": "0.3.1" }, "peerDependencies": { "typescript": "5.8.2" } }, "sha512-OGqMTGvqXTcb92YQdwGfEdK0nZJA64Aj/ChLOelbl3TfYch2IoBST0Yx4C0LQ7Lzyqm9RpgcpgDxeXQIz4p2Kg=="], "twoslash-cdn": ["twoslash-cdn@0.3.1", "", { "dependencies": { "twoslash": "0.3.1" }, "peerDependencies": { "typescript": "5.8.2" } }, "sha512-JbYbEIG82SlBVD03s7PW+VC5cV9zgWHCtdVkBEc38Kqz8D8ZAgPkthzPAj3isaiJo5xTu/Q/R4NYgihcMVmFXQ=="], @@ -7019,6 +7127,16 @@ "zwitch": ["zwitch@2.0.4", "", {}, "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A=="], + "@ai-sdk/gateway/@vercel/oidc": ["@vercel/oidc@3.0.5", "", {}, "sha512-fnYhv671l+eTTp48gB4zEsTW/YtRgRPnkI2nT7x6qw5rkI1Lq2hTmQIpHPgyThI0znLK+vX2n9XxKdXZ7BUbbw=="], + + "@ai-sdk/gateway/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "@ai-sdk/openai/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + + "@ai-sdk/provider-utils/eventsource-parser": ["eventsource-parser@3.0.6", "", {}, "sha512-Vo1ab+QXPzZ4tCa8SwIHJFaSzy4R6SHf7BY79rFBDf0idraZWAkYrDjDj8uWaSm3S2TK+hJ7/t1CEmZ7jXw+pg=="], + + "@ai-sdk/provider-utils/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "@algolia/autocomplete-preset-algolia/@algolia/client-search": ["@algolia/client-search@5.24.0", "", { "dependencies": { "@algolia/client-common": "5.24.0", "@algolia/requester-browser-xhr": "5.24.0", "@algolia/requester-fetch": "5.24.0", "@algolia/requester-node-http": "5.24.0" } }, "sha512-k+nuciQuq7WERNNE+hsx3DX636zIy+9R4xdtvW3PANT2a2BDGOv3fv2mta8+QUMcVTVcGe/Mo3QCb4pc1HNoxA=="], "@algolia/autocomplete-preset-algolia/algoliasearch": ["algoliasearch@5.18.0", "", { "dependencies": { "@algolia/client-abtesting": "5.18.0", "@algolia/client-analytics": "5.18.0", "@algolia/client-common": "5.18.0", "@algolia/client-insights": "5.18.0", "@algolia/client-personalization": "5.18.0", "@algolia/client-query-suggestions": "5.18.0", "@algolia/client-search": "5.18.0", "@algolia/ingestion": "1.18.0", "@algolia/monitoring": "1.18.0", "@algolia/recommend": "5.18.0", "@algolia/requester-browser-xhr": "5.18.0", "@algolia/requester-fetch": "5.18.0", "@algolia/requester-node-http": "5.18.0" } }, "sha512-/tfpK2A4FpS0o+S78o3YSdlqXr0MavJIDlFK3XZrlXLy7vaRXJvW5jYg3v5e/wCaF8y0IpMjkYLhoV6QqfpOgw=="], @@ -7847,8 +7965,6 @@ "@radix-ui/react-slot/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], - "@radix-ui/react-slot/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], - "@radix-ui/react-toggle/@radix-ui/primitive": ["@radix-ui/primitive@1.1.2", "", {}, "sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA=="], "@radix-ui/react-toggle/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "19.0.0", "@types/react-dom": "19.0.0", "react": "19.0.0", "react-dom": "19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], @@ -8125,6 +8241,24 @@ "@tybys/wasm-util/tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], + "@types/babel__core/@types/babel__generator": ["@types/babel__generator@7.6.3", "", { "dependencies": { "@babel/types": "7.24.0" } }, "sha512-/GWCmzJWqV7diQW54smJZzWbSFf4QYtF71WCKhcx6Ru/tFyQIY2eiiITcCAeuPbNSvT9YCGkVMqqvSk2Z0mXiA=="], + + "@types/babel__core/@types/babel__template": ["@types/babel__template@7.4.1", "", { "dependencies": { "@babel/parser": "7.24.1", "@babel/types": "7.24.0" } }, "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g=="], + + "@types/babel__core/@types/babel__traverse": ["@types/babel__traverse@7.14.2", "", { "dependencies": { "@babel/types": "7.24.0" } }, "sha512-K2waXdXBi2302XUdcHcR1jCeU0LL4TD9HRs/gk0N2Xvrht+G/BfJa4QObBQZfhMdxiCpV3COl5Nfq4uKTeTnJA=="], + + "@types/babel__generator/@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + + "@types/babel__standalone/@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="], + + "@types/babel__standalone/@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + + "@types/babel__template/@babel/parser": ["@babel/parser@7.28.5", "", { "dependencies": { "@babel/types": "^7.28.5" }, "bin": "./bin/babel-parser.js" }, "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ=="], + + "@types/babel__template/@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + + "@types/babel__traverse/@babel/types": ["@babel/types@7.28.5", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="], + "@types/connect-history-api-fallback/@types/express-serve-static-core": ["@types/express-serve-static-core@5.0.4", "", { "dependencies": { "@types/node": "20.12.14", "@types/qs": "6.9.7", "@types/range-parser": "1.2.4", "@types/send": "0.17.1" } }, "sha512-5kz9ScmzBdzTgB/3susoCgfqNDzBjvLL4taparufgSvlwjdLy6UyUy9T/tCpYd2GIdIilCatC4iSQS0QSYHt0w=="], "@types/express-rate-limit/@types/express": ["@types/express@5.0.1", "", { "dependencies": { "@types/body-parser": "1.19.1", "@types/express-serve-static-core": "5.0.4", "@types/serve-static": "1.13.10" } }, "sha512-UZUw8vjpWFXuDnjFTh7/5c2TWDlQqeXHi6hcN7F2XSVT5P+WmUnnbFS3KA6Jnc6IsEqI2qCVu2bK0R0J4A8ZQQ=="], @@ -8241,6 +8375,8 @@ "acorn-jsx/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], + "ai/zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], + "ajv-formats/ajv": ["ajv@8.11.0", "", { "dependencies": { "fast-deep-equal": "3.1.3", "json-schema-traverse": "1.0.0", "require-from-string": "2.0.2", "uri-js": "4.4.1" } }, "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg=="], "ansi-align/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "8.0.0", "is-fullwidth-code-point": "3.0.0", "strip-ansi": "6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], @@ -8595,6 +8731,8 @@ "jsdoc/escape-string-regexp": ["escape-string-regexp@2.0.0", "", {}, "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w=="], + "jsdoc/marked": ["marked@4.3.0", "", { "bin": { "marked": "bin/marked.js" } }, "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A=="], + "jszip/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "1.0.3", "inherits": "2.0.4", "isarray": "1.0.0", "process-nextick-args": "2.0.1", "safe-buffer": "5.1.2", "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], "lazystream/readable-stream": ["readable-stream@2.3.8", "", { "dependencies": { "core-util-is": "1.0.3", "inherits": "2.0.4", "isarray": "1.0.0", "process-nextick-args": "2.0.1", "safe-buffer": "5.1.2", "string_decoder": "1.1.1", "util-deprecate": "1.0.2" } }, "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA=="], @@ -9169,6 +9307,38 @@ "template-ai-video/uuid": ["uuid@13.0.0", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-XQegIaBTVUjSHliKqcnFqYypAd4S+WCYt5NIeRs6w/UAry7z8Y9j5ZwRRL4kzq9U3sD6v+85er9FvkEaBpji2w=="], + "template-code-generation/@eslint/js": ["@eslint/js@9.38.0", "", {}, "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A=="], + + "template-code-generation/@radix-ui/react-dialog": ["@radix-ui/react-dialog@1.1.15", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-controllable-state": "1.2.2", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw=="], + + "template-code-generation/@radix-ui/react-select": ["@radix-ui/react-select@2.2.6", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.3", "@radix-ui/react-collection": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-direction": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.11", "@radix-ui/react-focus-guards": "1.1.3", "@radix-ui/react-focus-scope": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.8", "@radix-ui/react-portal": "1.1.9", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-visually-hidden": "1.2.3", "aria-hidden": "^1.2.4", "react-remove-scroll": "^2.6.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-I30RydO+bnn2PQztvo25tswPH+wFBjehVGtmagkU78yMdwTwVf12wnAOF+AeP8S2N8xD+5UPbGhkUfPyvT+mwQ=="], + + "template-code-generation/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.4", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA=="], + + "template-code-generation/@react-three/fiber": ["@react-three/fiber@9.4.2", "", { "dependencies": { "@babel/runtime": "^7.17.8", "@types/react-reconciler": "^0.32.0", "@types/webxr": "*", "base64-js": "^1.5.1", "buffer": "^6.0.3", "its-fine": "^2.0.0", "react-reconciler": "^0.31.0", "react-use-measure": "^2.1.7", "scheduler": "^0.25.0", "suspend-react": "^0.1.3", "use-sync-external-store": "^1.4.0", "zustand": "^5.0.3" }, "peerDependencies": { "expo": ">=43.0", "expo-asset": ">=8.4", "expo-file-system": ">=11.0", "expo-gl": ">=11.0", "react": "^19.0.0", "react-dom": "^19.0.0", "react-native": ">=0.78", "three": ">=0.156" }, "optionalPeers": ["expo", "expo-asset", "expo-file-system", "expo-gl", "react-dom", "react-native"] }, "sha512-H4B4+FDNHpvIb4FmphH4ubxOfX5bxmfOw0+3pkQwR9u9wFiyMS7wUDkNn0m4RqQuiLWeia9jfN1eBvtyAVGEog=="], + + "template-code-generation/@types/three": ["@types/three@0.181.0", "", { "dependencies": { "@dimforge/rapier3d-compat": "~0.12.0", "@tweenjs/tween.js": "~23.1.3", "@types/stats.js": "*", "@types/webxr": "*", "@webgpu/types": "*", "fflate": "~0.8.2", "meshoptimizer": "~0.22.0" } }, "sha512-MLF1ks8yRM2k71D7RprFpDb9DOX0p22DbdPqT/uAkc6AtQXjxWCVDjCy23G9t1o8HcQPk7woD2NIyiaWcWPYmA=="], + + "template-code-generation/@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=="], + + "template-code-generation/@typescript-eslint/parser": ["@typescript-eslint/parser@8.46.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "8.46.0", "@typescript-eslint/types": "8.46.0", "@typescript-eslint/typescript-estree": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-n1H6IcDhmmUEG7TNVSspGmiHHutt7iVKtZwRppD7e04wha5MrkV1h3pti9xQLcCMt6YWsncpoT0HMjkH1FNwWQ=="], + + "template-code-generation/class-variance-authority": ["class-variance-authority@0.7.1", "", { "dependencies": { "clsx": "^2.1.1" } }, "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg=="], + + "template-code-generation/dotenv": ["dotenv@16.0.3", "", {}, "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ=="], + + "template-code-generation/lucide-react": ["lucide-react@0.555.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-D8FvHUGbxWBRQM90NZeIyhAvkFfsh3u9ekrMvJ30Z6gnpBHS6HC6ldLg7tL45hwiIz/u66eKDtdA23gwwGsAHA=="], + + "template-code-generation/tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="], + + "template-code-generation/tailwindcss": ["tailwindcss@4.0.3", "", {}, "sha512-ImmZF0Lon5RrQpsEAKGxRvHwCvMgSC4XVlFRqmbzTEDb/3wvin9zfEZrMwgsa3yqBbPqahYcVI6lulM2S7IZAA=="], + + "template-code-generation/three": ["three@0.181.2", "", {}, "sha512-k/CjiZ80bYss6Qs7/ex1TBlPD11whT9oKfT8oTGiHa34W4JRd1NiH/Tr1DbHWQ2/vMUypxksLnF2CfmlmM5XFQ=="], + + "template-code-generation/typescript-eslint": ["typescript-eslint@8.46.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.46.0", "@typescript-eslint/parser": "8.46.0", "@typescript-eslint/typescript-estree": "8.46.0", "@typescript-eslint/utils": "8.46.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-6+ZrB6y2bT2DX3K+Qd9vn7OFOJR+xSLDj+Aw/N3zBwUt27uTw2sw2TE2+UcY1RiyBZkaGbTkVg9SSdPNUG6aUw=="], + + "template-code-generation/zod": ["zod@4.1.13", "", {}, "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig=="], + "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=="], @@ -10195,6 +10365,8 @@ "@radix-ui/react-separator/react-dom/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + "@radix-ui/react-slot/@radix-ui/react-compose-refs/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + "@radix-ui/react-toggle/@radix-ui/react-use-controllable-state/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], "@radix-ui/react-toggle/react-dom/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], @@ -11195,6 +11367,86 @@ "teeny-request/https-proxy-agent/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "template-code-generation/@radix-ui/react-dialog/@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.5", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "19.0.0", "@types/react-dom": "19.0.0", "react": "19.0.0", "react-dom": "19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/number": ["@radix-ui/number@1.1.1", "", {}, "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/primitive": ["@radix-ui/primitive@1.1.3", "", {}, "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "19.0.0", "@types/react-dom": "19.0.0", "react": "19.0.0", "react-dom": "19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.11", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-escape-keydown": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.8", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.7", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.1", "@radix-ui/react-use-rect": "1.1.1", "@radix-ui/react-use-size": "1.1.1", "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "19.0.0", "@types/react-dom": "19.0.0", "react": "19.0.0", "react-dom": "19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-controllable-state": ["@radix-ui/react-use-controllable-state@1.2.2", "", { "dependencies": { "@radix-ui/react-use-effect-event": "0.0.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.3", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "19.0.0", "@types/react-dom": "19.0.0", "react": "19.0.0", "react-dom": "19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug=="], + + "template-code-generation/@radix-ui/react-slot/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.2", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg=="], + + "template-code-generation/@types/three/meshoptimizer": ["meshoptimizer@0.22.0", "", {}, "sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg=="], + + "template-code-generation/@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-code-generation/@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=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/utils": ["@typescript-eslint/utils@8.46.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.46.0", "@typescript-eslint/types": "8.46.0", "@typescript-eslint/typescript-estree": "8.46.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.0", "", { "dependencies": { "@typescript-eslint/types": "8.46.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": "5.7.3" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + + "template-code-generation/@typescript-eslint/parser/@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-code-generation/@typescript-eslint/parser/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], + + "template-code-generation/@typescript-eslint/parser/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.0", "@typescript-eslint/tsconfig-utils": "8.46.0", "@typescript-eslint/types": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg=="], + + "template-code-generation/@typescript-eslint/parser/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.0", "", { "dependencies": { "@typescript-eslint/types": "8.46.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q=="], + + "template-code-generation/@typescript-eslint/parser/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.0", "@typescript-eslint/tsconfig-utils": "8.46.0", "@typescript-eslint/types": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/utils": ["@typescript-eslint/utils@8.46.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.7.0", "@typescript-eslint/scope-manager": "8.46.0", "@typescript-eslint/types": "8.46.0", "@typescript-eslint/typescript-estree": "8.46.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-nD6yGWPj1xiOm4Gk0k6hLSZz2XkNXhuYmyIrOWcHoPuAhjT9i5bAG+xbWPgFeNR8HPHHtpNKdYUXJl/D3x7f5g=="], + "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=="], @@ -13203,6 +13455,94 @@ "shiki-twoslash/@typescript/twoslash/@typescript/vfs/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-compose-refs/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-context/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-primitive/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-primitive/react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "0.25.0" }, "peerDependencies": { "react": "19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-use-controllable-state/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-use-controllable-state/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-collection/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-collection/react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "0.25.0" }, "peerDependencies": { "react": "19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-compose-refs/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-context/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-direction/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "19.0.0", "@types/react-dom": "19.0.0", "react": "19.0.0", "react-dom": "19.0.0" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "19.0.0", "react": "19.0.0" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-primitive/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-primitive/react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "0.25.0" }, "peerDependencies": { "react": "19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-callback-ref/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-controllable-state/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-layout-effect/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-use-previous/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-visually-hidden/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-visually-hidden/react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "0.25.0" }, "peerDependencies": { "react": "19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], + + "template-code-generation/@radix-ui/react-slot/@radix-ui/react-compose-refs/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.0", "@typescript-eslint/tsconfig-utils": "8.46.0", "@typescript-eslint/types": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@8.46.0", "", { "dependencies": { "@typescript-eslint/project-service": "8.46.0", "@typescript-eslint/tsconfig-utils": "8.46.0", "@typescript-eslint/types": "8.46.0", "@typescript-eslint/visitor-keys": "8.46.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^2.1.0" }, "peerDependencies": { "typescript": ">=4.8.4 <6.0.0" } }, "sha512-ekDCUfVpAKWJbRfm8T1YRrCot1KFxZn21oV76v5Fj4tr7ELyk84OS+ouvYdcDAwZL89WpEkEj2DKQ+qg//+ucg=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/visitor-keys/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], + + "template-code-generation/@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "template-code-generation/@typescript-eslint/parser/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "template-code-generation/@typescript-eslint/parser/@typescript-eslint/typescript-estree/ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": "5.7.3" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.0", "", { "dependencies": { "@typescript-eslint/types": "8.46.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree/ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": "5.7.3" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/utils/@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-code-generation/typescript-eslint/@typescript-eslint/utils/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], + "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/scope-manager/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/types": ["@typescript-eslint/types@8.46.0", "", {}, "sha512-bHGGJyVjSE4dJJIO5yyEWt/cHyNwga/zXGJbJJ8TiO01aVREK6gCTu3L+5wrkb1FbDkQ+TKjMNe9R/QQQP9+rA=="], @@ -14075,6 +14415,42 @@ "renderkid/css-select/domutils/dom-serializer/entities": ["entities@2.2.0", "", {}, "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A=="], + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-presence/@radix-ui/react-use-layout-effect/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-dialog/@radix-ui/react-primitive/react-dom/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-collection/react-dom/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-arrow/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-arrow/react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "0.25.0" }, "peerDependencies": { "react": "19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-use-rect/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-use-size/react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-primitive/react-dom/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + + "template-code-generation/@radix-ui/react-select/@radix-ui/react-visually-hidden/react-dom/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/debug": ["debug@4.4.1", "", { "dependencies": { "ms": "2.1.3" } }, "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], + + "template-code-generation/@typescript-eslint/parser/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "1.0.2" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "1.0.2" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "template-code-generation/typescript-eslint/@typescript-eslint/utils/@typescript-eslint/scope-manager/@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@8.46.0", "", { "dependencies": { "@typescript-eslint/types": "8.46.0", "eslint-visitor-keys": "^4.2.1" } }, "sha512-FrvMpAK+hTbFy7vH5j1+tMYHMSKLE6RzluFJlkFNKD0p9YsUT75JlBSmr5so3QRzvMwU5/bIEdeNrxm8du8l3Q=="], + "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/semver": ["semver@7.7.2", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA=="], @@ -14457,6 +14833,12 @@ "remark-mdx/mdast-util-mdx/mdast-util-mdx-jsx/unist-util-remove-position/unist-util-visit/unist-util-visit-parents": ["unist-util-visit-parents@5.1.3", "", { "dependencies": { "@types/unist": "2.0.6", "unist-util-is": "5.2.0" } }, "sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg=="], + "template-code-generation/@radix-ui/react-select/@radix-ui/react-popper/@radix-ui/react-arrow/react-dom/scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "1.0.2" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + + "template-code-generation/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "1.0.2" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], + "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/type-utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "1.0.2" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "template-next-app-tailwind/@typescript-eslint/eslint-plugin/@typescript-eslint/utils/@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "1.0.2" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], diff --git a/package.json b/package.json index 48d773e9203..8450da8ecc9 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "node": ">=16" }, "devDependencies": { + "@types/babel__standalone": "^7.1.9", "@types/bun": "catalog:", "@types/deno": "2.0.0", "@types/react": "catalog:", diff --git a/packages/create-video/src/templates.ts b/packages/create-video/src/templates.ts index 3700e95108c..ed6eff63710 100644 --- a/packages/create-video/src/templates.ts +++ b/packages/create-video/src/templates.ts @@ -44,7 +44,8 @@ export type Template = { | 'tiktok' | 'code-hike' | 'render-server' - | 'recorder'; + | 'recorder' + | 'code-generation'; defaultBranch: string; featuredOnHomePage: string | null; previewURL: string | null; @@ -531,6 +532,28 @@ export const FEATURED_TEMPLATES: Template[] = [ allowEnableTailwind: true, contributedBy: null, }, + { + homePageLabel: 'Code Generation', + shortName: 'Code Generation', + org: 'remotion-dev', + repoName: 'template-code-generation', + description: 'AI-powered code generation for Remotion', + longerDescription: + 'A template that uses AI to generate Remotion video code from prompts.', + promoBanner: { + width: 1280, + height: 720, + src: '/img/code-generation-template.png', + }, + cliId: 'code-generation' as const, + type: 'image' as const, + defaultBranch: 'main', + featuredOnHomePage: null, + previewURL: null, + templateInMonorepo: 'template-code-generation', + allowEnableTailwind: false, + contributedBy: null, + }, ].filter(truthy); export const PAID_TEMPLATES = [ diff --git a/packages/template-code-generation/.env.example b/packages/template-code-generation/.env.example new file mode 100644 index 00000000000..c3cd82cdddd --- /dev/null +++ b/packages/template-code-generation/.env.example @@ -0,0 +1,4 @@ +REMOTION_AWS_ACCESS_KEY_ID= +REMOTION_AWS_SECRET_ACCESS_KEY= + +OPENAI_API_KEY= \ No newline at end of file diff --git a/packages/template-code-generation/.gitignore b/packages/template-code-generation/.gitignore new file mode 100644 index 00000000000..1efb618ffad --- /dev/null +++ b/packages/template-code-generation/.gitignore @@ -0,0 +1,39 @@ +# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. + +# dependencies +/node_modules +/.pnp +.pnp.js + +# testing +/coverage + +# next.js +/.next/ +/out/ + +# production +/build + +# misc +.DS_Store +*.pem + +# debug +npm-debug.log* +yarn-debug.log* +yarn-error.log* +.pnpm-debug.log* + +# local env files +.env*.local + +# vercel +.vercel + +# typescript +*.tsbuildinfo +next-env.d.ts +out/ +.env +build \ No newline at end of file diff --git a/packages/template-code-generation/.npmrc b/packages/template-code-generation/.npmrc new file mode 100644 index 00000000000..3e775efb0f4 --- /dev/null +++ b/packages/template-code-generation/.npmrc @@ -0,0 +1 @@ +auto-install-peers=true diff --git a/packages/template-code-generation/.prettierrc b/packages/template-code-generation/.prettierrc new file mode 100644 index 00000000000..37d50717489 --- /dev/null +++ b/packages/template-code-generation/.prettierrc @@ -0,0 +1,5 @@ +{ + "useTabs": false, + "bracketSpacing": true, + "tabWidth": 2 +} diff --git a/packages/template-code-generation/README.md b/packages/template-code-generation/README.md new file mode 100644 index 00000000000..f0990cb1e6f --- /dev/null +++ b/packages/template-code-generation/README.md @@ -0,0 +1,28 @@ +# template-code-generation + +AI-powered code generation template for Remotion. + +## Adding examples and capabilities + +When adding new capabilities to the assistant, we have to first create some examples to let the system know what we can do. So first we add the example to the template, tweak it a bit more to get it right with our taste and then add it as an example potentially to the system prompt of the assistant. + +## Model Selection + +GPT5.1 Low reasoning seems to be a good middle ground between generation speed and output quality. + +## Usage + +```bash +npx create-video@latest --template code-generation +``` + +## Development + +```bash +bun install +bun dev +``` + +## License + +Note that for some entities a company license is needed. [Read the terms here](https://github.com/remotion-dev/remotion/blob/main/LICENSE.md). diff --git a/packages/template-code-generation/components.json b/packages/template-code-generation/components.json new file mode 100644 index 00000000000..e152499ab4d --- /dev/null +++ b/packages/template-code-generation/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "", + "css": "styles/global.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/packages/template-code-generation/config.mjs b/packages/template-code-generation/config.mjs new file mode 100644 index 00000000000..b18ed95152c --- /dev/null +++ b/packages/template-code-generation/config.mjs @@ -0,0 +1,10 @@ +/** + * Use autocomplete to get a list of available regions. + * @type {import('@remotion/lambda').AwsRegion} + */ +export const REGION = "us-east-1"; + +export const SITE_NAME = "my-next-app"; +export const RAM = 3009; +export const DISK = 10240; +export const TIMEOUT = 240; diff --git a/packages/template-code-generation/deploy.mjs b/packages/template-code-generation/deploy.mjs new file mode 100644 index 00000000000..2dcc0bd8fe9 --- /dev/null +++ b/packages/template-code-generation/deploy.mjs @@ -0,0 +1,79 @@ +import { + deployFunction, + deploySite, + getOrCreateBucket, +} from "@remotion/lambda"; +import dotenv from "dotenv"; +import path from "path"; +import { DISK, RAM, REGION, SITE_NAME, TIMEOUT } from "./config.mjs"; +import { webpackOverride } from "./src/remotion/webpack-override.mjs"; + +console.log("Selected region:", REGION); +dotenv.config(); + +if (!process.env.AWS_ACCESS_KEY_ID && !process.env.REMOTION_AWS_ACCESS_KEY_ID) { + console.log( + 'The environment variable "REMOTION_AWS_ACCESS_KEY_ID" is not set.', + ); + console.log("Lambda renders were not set up."); + console.log( + "Complete the Lambda setup: at https://www.remotion.dev/docs/lambda/setup", + ); + process.exit(0); +} +if ( + !process.env.AWS_SECRET_ACCESS_KEY && + !process.env.REMOTION_AWS_SECRET_ACCESS_KEY +) { + console.log( + 'The environment variable "REMOTION_REMOTION_AWS_SECRET_ACCESS_KEY" is not set.', + ); + console.log("Lambda renders were not set up."); + console.log( + "Complete the Lambda setup: at https://www.remotion.dev/docs/lambda/setup", + ); + process.exit(0); +} + +process.stdout.write("Deploying Lambda function... "); + +const { functionName, alreadyExisted: functionAlreadyExisted } = + await deployFunction({ + createCloudWatchLogGroup: true, + memorySizeInMb: RAM, + region: REGION, + timeoutInSeconds: TIMEOUT, + diskSizeInMb: DISK, + }); +console.log( + functionName, + functionAlreadyExisted ? "(already existed)" : "(created)", +); + +process.stdout.write("Ensuring bucket... "); +const { bucketName, alreadyExisted: bucketAlreadyExisted } = + await getOrCreateBucket({ + region: REGION, + }); +console.log( + bucketName, + bucketAlreadyExisted ? "(already existed)" : "(created)", +); + +process.stdout.write("Deploying site... "); +const { siteName } = await deploySite({ + bucketName, + entryPoint: path.join(process.cwd(), "src", "remotion", "index.ts"), + siteName: SITE_NAME, + region: REGION, + options: { webpackOverride }, +}); + +console.log(siteName); + +console.log(); +console.log("You now have everything you need to render videos!"); +console.log("Re-run this command when:"); +console.log(" 1) you changed the video template"); +console.log(" 2) you changed config.mjs"); +console.log(" 3) you upgraded Remotion to a newer version"); diff --git a/packages/template-code-generation/eslint.config.mjs b/packages/template-code-generation/eslint.config.mjs new file mode 100644 index 00000000000..b37f42b2024 --- /dev/null +++ b/packages/template-code-generation/eslint.config.mjs @@ -0,0 +1,53 @@ +import js from "@eslint/js"; +import nextPlugin from "@next/eslint-plugin-next"; +import remotion from "@remotion/eslint-plugin"; +import tseslint from "typescript-eslint"; + +// Build Next.js recommended rules and an "off" map for overrides +const nextRecommended = nextPlugin.configs.recommended ?? { rules: {} }; +const nextRecommendedRules = nextRecommended.rules ?? {}; +const offNextRules = Object.fromEntries( + Object.keys(nextRecommendedRules).map((k) => [k, "off"]), +); + +export default [ + // Global ignores + { + ignores: [ + "node_modules/**", + ".next/**", + "out/**", + "build/**", + "next-env.d.ts", + "next.config.js", + "deploy.mjs", + ], + }, + // Base JS recommended + js.configs.recommended, + // TypeScript recommended (non type-checked for speed/simplicity) + ...tseslint.configs.recommended, + // Next.js recommended rules applied to app code + { + files: ["**/*.{js,jsx,ts,tsx}"], + plugins: { "@next/next": nextPlugin }, + rules: { + ...nextRecommendedRules, + }, + }, + // Remotion rules applied only to remotion files + { + files: ["src/remotion/**"], + ...remotion.flatPlugin, + rules: { + ...remotion.flatPlugin.rules, + }, + }, + // Disable all Next.js rules within remotion files + { + files: ["src/remotion/**"], + rules: { + ...offNextRules, + }, + }, +]; diff --git a/packages/template-code-generation/next.config.js b/packages/template-code-generation/next.config.js new file mode 100644 index 00000000000..91ef62f0db5 --- /dev/null +++ b/packages/template-code-generation/next.config.js @@ -0,0 +1,6 @@ +/** @type {import('next').NextConfig} */ +const nextConfig = { + reactStrictMode: true, +}; + +module.exports = nextConfig; diff --git a/packages/template-code-generation/package.json b/packages/template-code-generation/package.json new file mode 100644 index 00000000000..8bf8fe70f4b --- /dev/null +++ b/packages/template-code-generation/package.json @@ -0,0 +1,77 @@ +{ + "name": "template-code-generation", + "version": "4.0.379", + "description": "AI-powered code generation template for Remotion", + "repository": { + "url": "https://github.com/remotion-dev/remotion/tree/main/packages/template-code-generation" + }, + "homepage": "https://www.remotion.dev", + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint .", + "remotion": "remotion studio", + "render": "remotion render", + "deploy": "node deploy.mjs" + }, + "dependencies": { + "@ai-sdk/openai": "^2.0.74", + "@ai-sdk/react": "^2.0.104", + "@babel/standalone": "^7.28.5", + "@monaco-editor/react": "^4.7.0", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-select": "^2.2.6", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-tooltip": "^1.2.8", + "@react-three/fiber": "^9.4.2", + "@remotion/animated-emoji": "workspace:*", + "@remotion/bundler": "workspace:*", + "@remotion/cli": "workspace:*", + "@remotion/google-fonts": "workspace:*", + "@remotion/lambda": "workspace:*", + "@remotion/lottie": "workspace:*", + "@remotion/paths": "workspace:*", + "@remotion/player": "workspace:*", + "@remotion/shapes": "workspace:*", + "@remotion/tailwind-v4": "workspace:*", + "@remotion/three": "workspace:*", + "ai": "^5.0.104", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "lucide-react": "^0.555.0", + "monaco-editor": "^0.55.1", + "monaco-jsx-syntax-highlight": "^1.2.2", + "next": "16.0.0", + "react": "19.0.0", + "react-dom": "19.0.0", + "remotion": "workspace:*", + "tailwind-merge": "^3.4.0", + "three": "^0.181.2", + "zod": "^4.1.13" + }, + "devDependencies": { + "@eslint/eslintrc": "3.1.0", + "@eslint/js": "9.38.0", + "@next/eslint-plugin-next": "15.1.6", + "@remotion/eslint-plugin": "workspace:*", + "@tailwindcss/postcss": "4.1.1", + "@types/node": "20.12.14", + "@types/react": "19.0.0", + "@types/react-dom": "19.0.0", + "@types/three": "^0.181.0", + "@types/web": "0.0.166", + "@typescript-eslint/eslint-plugin": "8.46.0", + "@typescript-eslint/parser": "8.46.0", + "autoprefixer": "10.4.20", + "dotenv": "16.0.3", + "eslint": "9.19.0", + "eslint-config-next": "15.1.6", + "postcss": "8.4.47", + "prettier": "3.6.0", + "tailwindcss": "4.0.3", + "tw-animate-css": "^1.4.0", + "typescript": "5.8.2", + "typescript-eslint": "8.46.0" + } +} diff --git a/packages/template-code-generation/postcss.config.mjs b/packages/template-code-generation/postcss.config.mjs new file mode 100644 index 00000000000..7059fe95adc --- /dev/null +++ b/packages/template-code-generation/postcss.config.mjs @@ -0,0 +1,6 @@ +const config = { + plugins: { + "@tailwindcss/postcss": {}, + }, +}; +export default config; diff --git a/packages/template-code-generation/public/logo-white.svg b/packages/template-code-generation/public/logo-white.svg new file mode 100644 index 00000000000..263581d8efe --- /dev/null +++ b/packages/template-code-generation/public/logo-white.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/template-code-generation/public/logo.png b/packages/template-code-generation/public/logo.png new file mode 100644 index 00000000000..a35f38446a9 Binary files /dev/null and b/packages/template-code-generation/public/logo.png differ diff --git a/packages/template-code-generation/remotion.config.ts b/packages/template-code-generation/remotion.config.ts new file mode 100644 index 00000000000..cbf7520d9b4 --- /dev/null +++ b/packages/template-code-generation/remotion.config.ts @@ -0,0 +1,11 @@ +// See all configuration options: https://remotion.dev/docs/config +// Each option also is available as a CLI flag: https://remotion.dev/docs/cli + +// Note: When using the Node.JS APIs, the config file doesn't apply. Instead, pass options directly to the APIs + +import { Config } from "@remotion/cli/config"; +import { webpackOverride } from "./src/remotion/webpack-override.mjs"; + +Config.setVideoImageFormat("jpeg"); + +Config.overrideWebpackConfig(webpackOverride); diff --git a/packages/template-code-generation/src/app/api/generate/route.ts b/packages/template-code-generation/src/app/api/generate/route.ts new file mode 100644 index 00000000000..70f60c31f79 --- /dev/null +++ b/packages/template-code-generation/src/app/api/generate/route.ts @@ -0,0 +1,621 @@ +import { streamText } from "ai"; +import { createOpenAI } from "@ai-sdk/openai"; + +const SYSTEM_PROMPT = ` +You are an expert in generating React components for Remotion animations. + +LAYOUT RULES: +- ALWAYS USE THE FULL WIDTH of the container +- Ensure diagrams span edge-to-edge with appropriate padding (e.g., padding: 40px) +- Never constrain diagrams to a small centered box - maximize the visual space + +COLOR RULES: +- Keep colors minimal (2-4 colors max) and define them as constants INSIDE the component body +- Example: const COLOR_TEXT = "#000000"; const COLOR_HIGHLIGHT = "#A7C7E7"; + +TEXT CONTENT RULES (CRITICAL): +- ALL text strings that appear in the animation MUST be defined as constants INSIDE the component body +- Never hardcode text directly in JSX - always use variables +- This allows users to easily edit all text content +- Use descriptive constant names in UPPER_SNAKE_CASE +- Example: + const TITLE_TEXT = "Espresso Workflow"; + const SUBTITLE_TEXT = "5-Step Process Flow"; + const STEP_1_TEXT = "Grind Coffee"; + +ANIMATION TIMING RULES: +- Define animation speed/timing parameters as constants INSIDE the component body +- Use descriptive names for delays, durations, and speed multipliers +- This allows users to fine-tune animation pacing without editing code +- Example: + const ANIMATION_SPEED = 1.0; // Speed multiplier (1.0 = normal, 2.0 = 2x faster) + const FADE_DURATION = 20; // Duration in frames + const ELEMENT_DELAY = 5; // Delay between elements in frames + +CONSTANTS PLACEMENT (CRITICAL): +- NEVER define constants outside the component function +- ALL constants (colors, text, timing, layout) MUST be defined INSIDE the component body +- Place constants AFTER the hooks (useCurrentFrame, useVideoConfig) but BEFORE any calculations +- Correct order inside component: + 1) Multi-line comment description + 2) Hooks (useCurrentFrame, useVideoConfig, useState, etc.) + 3) Constants (COLORS, TEXT, TIMING, LAYOUT) + 4) Calculations and derived values + 5) return JSX +- NEVER put constants before hooks - this is a common mistake + +ADDITIONAL CONSTANTS TO DEFINE: +- Typography: FONT_SIZE, FONT_WEIGHT, LETTER_SPACING +- Layout: ROW_GAP, PADDING, BORDER_RADIUS, MAX_WIDTH_PERCENT +- Spring physics: BOUNCE_DAMPING, BOUNCE_MASS, BOUNCE_STIFFNESS +- Derived timing: Calculate from other constants (e.g., MSG2_START = MSG1_START + DURATION + DELAY) +- Responsive: Use Math.max(minValue, Math.round(width * percentage)) for responsive sizing + +ANIMATION QUALITY RULES (CRITICAL): +- PREFER spring() over interpolate() for organic, natural motion +- Use spring() for: entrances, bounces, highlights, scaling, any "snappy" movement +- Use interpolate() only for: linear progress bars, opacity fades, or when exact timing control is needed +- Example: const entrance = spring({fps, frame: frame - START_DELAY, config: {damping: 200, stiffness: 120}, durationInFrames: 20}); + +LAYERING & CROSSFADE TECHNIQUES: +- For text that changes appearance (e.g., gets highlighted), use TWO overlapping layers that crossfade +- Never abruptly switch styles - always transition smoothly + +PACING & DRAMATIC TIMING: +- Add intentional PAUSES between animation phases for dramatic effect +- Use delays like WAIT_AFTER_X_SECONDS for natural pacing +- Example: const PAUSE_FRAMES = Math.round(fps * 1.0); // 1 second pause + +CONTAINER ANIMATIONS: +- Add subtle entrance animations to the entire container (e.g., scale from 0.98 to 1.0 with spring) + +TYPEWRITER EFFECTS (CRITICAL): +- For typewriter/typing animations, use string slicing: typedText = FULL_TEXT.slice(0, typedChars) +- NEVER render all characters with varying opacity - this breaks cursor positioning +- The cursor must appear immediately after the last typed character +- Simple pattern: {typedText}{CARET} +--- +EXAMPLE 1: Typewriter with highlight (advanced) + +Prompt: "Text with typewriter effect, pause mid-sentence, then highlight a word" + +import { useCurrentFrame, useVideoConfig, AbsoluteFill, interpolate, spring } from "remotion"; + +export const MyAnimation = () => { + /* + * Typewriter with blinking cursor, dramatic pause, spring-based highlight, and layer crossfade. + */ + const frame = useCurrentFrame(); + const {fps} = useVideoConfig(); + + const COLOR_TEXT = "#000000"; + const COLOR_HIGHLIGHT = "#A7C7E7"; + + const FULL_TEXT = "From prompt to motion graphics. This is Veloce."; + const HIGHLIGHT_WORD = "Veloce"; + const CARET_SYMBOL = "▌"; + const SPLIT_AFTER = " This is Veloce."; // Phrase to delay before typing + + const FONT_SIZE = 72; + const FONT_WEIGHT = 700; + const CHAR_FRAMES = 2; + const CURSOR_BLINK_FRAMES = 16; + const HIGHLIGHT_DELAY = 6; + const HIGHLIGHT_WIPE_DURATION = 18; + const CROSSFADE_DURATION = 8; + const WAIT_AFTER_PRE_SECONDS = 1; // Dramatic pause mid-sentence + + const WAIT_AFTER_PRE_FRAMES = Math.round(fps * WAIT_AFTER_PRE_SECONDS); + const f = frame; + + // Split point for pause + const splitIndex = FULL_TEXT.indexOf(SPLIT_AFTER); + const preLen = splitIndex >= 0 ? splitIndex : FULL_TEXT.length; + const postLen = FULL_TEXT.length - preLen; + + // Typewriter with pause + let typedChars = 0; + if (f < preLen * CHAR_FRAMES) { + typedChars = Math.floor(f / CHAR_FRAMES); + } else if (f < preLen * CHAR_FRAMES + WAIT_AFTER_PRE_FRAMES) { + typedChars = preLen; + } else { + const postPhase = f - preLen * CHAR_FRAMES - WAIT_AFTER_PRE_FRAMES; + typedChars = Math.min(FULL_TEXT.length, preLen + Math.floor(postPhase / CHAR_FRAMES)); + } + const typedText = FULL_TEXT.slice(0, typedChars); + const typingDone = typedChars >= FULL_TEXT.length; + + // Caret blink (smooth) + const caretOpacity = !typingDone + ? interpolate(f % CURSOR_BLINK_FRAMES, [0, CURSOR_BLINK_FRAMES / 2, CURSOR_BLINK_FRAMES], [1, 0, 1], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}) + : 0; + + // Highlight segmentation + const highlightIndex = FULL_TEXT.indexOf(HIGHLIGHT_WORD); + const hasHighlight = highlightIndex >= 0; + const preText = hasHighlight ? FULL_TEXT.slice(0, highlightIndex) : FULL_TEXT; + const postText = hasHighlight ? FULL_TEXT.slice(highlightIndex + HIGHLIGHT_WORD.length) : ""; + + // Timing + const typeEnd = preLen * CHAR_FRAMES + WAIT_AFTER_PRE_FRAMES + postLen * CHAR_FRAMES; + const highlightStart = typeEnd + HIGHLIGHT_DELAY; + + const typedOpacity = interpolate(f, [highlightStart - CROSSFADE_DURATION, highlightStart + CROSSFADE_DURATION], [1, 0], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + const finalOpacity = interpolate(f, [highlightStart, highlightStart + CROSSFADE_DURATION], [0, 1], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + + // Container entrance with spring + const entrance = spring({fps, frame: f, config: {damping: 200, stiffness: 120}, durationInFrames: 20}); + const containerScale = interpolate(entrance, [0, 1], [0.98, 1], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + + // Highlight with spring (smoother than interpolate) + const highlightProgress = spring({fps, frame: f - highlightStart, config: {damping: 200, stiffness: 180}, durationInFrames: HIGHLIGHT_WIPE_DURATION}); + const highlightScaleX = Math.max(0, Math.min(1, highlightProgress)); + + return ( + +
+ {/* Typing layer */} +
+ {typedText} + {CARET_SYMBOL} +
+ {/* Final layer with highlight */} +
+ {hasHighlight ? ( + <> + {preText} + + + {HIGHLIGHT_WORD} + + {postText} + + ) : ( + {FULL_TEXT} + )} +
+
+
+ ); +}; +--- +EXAMPLE 2: Chat bubbles + +Prompt: "WhatsApp-style chat with messages appearing one by one" + +import { useCurrentFrame, useVideoConfig, AbsoluteFill, interpolate, spring } from "remotion"; + +export const MyAnimation = () => { + /* + * Chat conversation with bubbles sliding in with spring animation. + */ + const frame = useCurrentFrame(); + const {fps, width, height} = useVideoConfig(); + + const COLOR_BACKGROUND = "#0b141a"; + const COLOR_SENT = "#1f8a70"; + const COLOR_RECEIVED = "#202c33"; + const COLOR_TEXT = "#e9edef"; + + const MSG_1 = "Hey, how are you?"; + const MSG_2 = "Great, thanks!"; + const MSG_3 = "Want to grab coffee?"; + + const FONT_SIZE = 44; + const FADE_DURATION = 18; + const STAGGER_DELAY = 38; + const SLIDE_DISTANCE = 40; + const BOUNCE_DAMPING = 12; + const BOUNCE_STIFFNESS = 170; + const BUBBLE_RADIUS = 18; + const BUBBLE_PADDING_X = 24; + const BUBBLE_PADDING_Y = 18; + const ROW_GAP = 22; + const MAX_WIDTH_PERCENT = 72; + + // Derived timing + const MSG1_START = 0; + const MSG2_START = MSG1_START + FADE_DURATION + STAGGER_DELAY; + const MSG3_START = MSG2_START + FADE_DURATION + STAGGER_DELAY; + + // Helper component for repeated bubbles + const MessageRow = ({text, align, start}: {text: string, align: string, start: number}) => { + const local = frame - start; + const opacity = interpolate(local, [0, FADE_DURATION], [0, 1], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + const bounce = spring({frame: Math.max(0, local), fps, config: {damping: BOUNCE_DAMPING, stiffness: BOUNCE_STIFFNESS}}); + const scale = interpolate(bounce, [0, 1], [0.98, 1], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + const xFrom = align === "right" ? SLIDE_DISTANCE : -SLIDE_DISTANCE; + const tx = interpolate(opacity, [0, 1], [xFrom, 0], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + const bubbleBg = align === "right" ? COLOR_SENT : COLOR_RECEIVED; + + return ( +
+
+ {text} +
+
+ ); + }; + + return ( + +
+ + + +
+ + ); +}; + +--- + +EXAMPLE 3: Rotating word carousel + +Prompt: "Text that dissolves between different words" + +import { useCurrentFrame, AbsoluteFill, interpolate } from "remotion"; + +export const MyAnimation = () => { + /* + * Prefix text with rotating words that crossfade with blur. + */ + const frame = useCurrentFrame(); + + const COLOR_TEXT = "#7b92c1"; + const PREFIX = "Created for"; + const WORDS = ["Creators", "Marketers", "Developers", "Everyone"]; + + const PREFIX_FONT_SIZE = 80; + const WORD_FONT_SIZE = 80; + const PREFIX_WEIGHT = 300; + const WORD_WEIGHT = 700; + const WORD_GAP = 20; + const HOLD_DURATION = 32; + const FLIP_DURATION = 18; + const BLUR_AMOUNT = 6; + + const perStep = HOLD_DURATION + FLIP_DURATION; + const totalSteps = WORDS.length; + const currentStep = Math.floor(frame / perStep) % totalSteps; + const nextStep = (currentStep + 1) % totalSteps; + const phase = frame % perStep; + const isFlipping = phase >= HOLD_DURATION; + const flipProgress = isFlipping ? (phase - HOLD_DURATION) / FLIP_DURATION : 0; + + const outOpacity = interpolate(flipProgress, [0, 1], [1, 0], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + const inOpacity = interpolate(flipProgress, [0, 1], [0, 1], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + const outBlur = interpolate(flipProgress, [0, 1], [0, BLUR_AMOUNT], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + const inBlur = interpolate(flipProgress, [0, 1], [BLUR_AMOUNT, 0], {extrapolateLeft: "clamp", extrapolateRight: "clamp"}); + + // Find longest word for stable width + const longestWord = WORDS.reduce((a, b) => a.length >= b.length ? a : b, WORDS[0]); + + return ( + +
+
{PREFIX}
+
+ {/* Invisible width keeper */} +
{longestWord}
+ {/* Current word (fades out during flip) */} + {!isFlipping && ( +
{WORDS[currentStep]}
+ )} + {/* Crossfade during flip */} + {isFlipping && ( + <> +
+ {WORDS[currentStep]} +
+
+ {WORDS[nextStep]} +
+ + )} +
+
+
+ ); +}; + +--- + +EXAMPLE 4: Animated bar chart / histogram + +Prompt: "An animated histogram with the gold price. Focus on simplicity and elegance. Small headline, all bars are well laid out" + +import { useCurrentFrame, useVideoConfig, AbsoluteFill, spring } from "remotion"; + +export const MyAnimation = () => { + /* + * Elegant animated bar chart showing gold prices with Y-axis, staggered spring animations, and full-width layout. + */ + const frame = useCurrentFrame(); + const { fps, height: videoHeight } = useVideoConfig(); + + const TITLE = "Gold Price 2024"; + const UNIT = "USD per troy ounce"; + const COLOR_BAR = "#D4AF37"; + const COLOR_TEXT = "#ffffff"; + const COLOR_MUTED = "#888888"; + const COLOR_BG = "#0a0a0a"; + const COLOR_AXIS = "#333333"; + + const PADDING = 50; + const HEADER_HEIGHT = 70; + const LABEL_HEIGHT = 32; + const BAR_GAP = 8; + const BAR_RADIUS = 4; + const TITLE_FONT_SIZE = 24; + const LABEL_FONT_SIZE = 11; + const VALUE_FONT_SIZE = 11; + const AXIS_FONT_SIZE = 12; + const STAGGER_DELAY = 5; + const HEADER_START_FRAME = 0; + const BARS_START_FRAME = 10; + const SPRING_DAMPING = 18; + const SPRING_STIFFNESS = 80; + + const data = [ + { month: "Jan", price: 2039 }, + { month: "Feb", price: 2024 }, + { month: "Mar", price: 2160 }, + { month: "Apr", price: 2330 }, + { month: "May", price: 2327 }, + { month: "Jun", price: 2339 }, + { month: "Jul", price: 2426 }, + { month: "Aug", price: 2503 }, + { month: "Sep", price: 2634 }, + { month: "Oct", price: 2735 }, + { month: "Nov", price: 2672 }, + { month: "Dec", price: 2650 }, + ]; + + const minPrice = 1900; + const maxPrice = 2800; + const priceRange = maxPrice - minPrice; + const chartHeight = videoHeight - (PADDING * 2) - HEADER_HEIGHT - LABEL_HEIGHT; + const yAxisSteps = [1900, 2100, 2300, 2500, 2700]; + + const headerOpacity = spring({ + frame: frame - HEADER_START_FRAME, + fps, + config: { damping: 20, stiffness: 100 }, + }); + + return ( + + {/* Header */} +
+
{TITLE}
+
{UNIT}
+
+ + {/* Chart container */} +
+ {/* Y-Axis */} +
+ {yAxisSteps.slice().reverse().map((step) => ( +
+ {step.toLocaleString()} +
+ ))} +
+ + {/* Chart area */} +
+ {data.map((item, i) => { + const delay = i * STAGGER_DELAY; + const progress = spring({ + frame: frame - delay - BARS_START_FRAME, + fps, + config: { damping: SPRING_DAMPING, stiffness: SPRING_STIFFNESS }, + }); + + const normalizedHeight = ((item.price - minPrice) / priceRange) * chartHeight; + const height = normalizedHeight * progress; + + return ( +
+
0 ? 4 : 0, + }} + > + {height > 30 && ( + + {item.price.toLocaleString()} + + )} +
+
+ {item.month} +
+
+ ); + })} +
+
+
+ ); +}; + +---- +END OF EXAMPLES + +IMPORTANT RULES: +- Start with proper ES6 imports, then export the component as: export const MyAnimation = () => {...} +- Start the component body with a multi-line comment (/* */) containing a 2-3 sentence description of what you're building +- ALWAYS include the necessary imports at the top of the file + +AVAILABLE IMPORTS (use exactly these import statements): +- import { useCurrentFrame, useVideoConfig, AbsoluteFill, interpolate, spring, Sequence } from "remotion"; +- import { Circle, Rect, Triangle, Star, Ellipse, Pie } from "@remotion/shapes"; +- import { Lottie } from "@remotion/lottie"; +- import { ThreeCanvas } from "@remotion/three"; + +REACT HOOKS: +- Import React hooks using named imports: import { useState, useEffect } from "react"; +- Example: const [data, setData] = useState(null); + +EXPORT FORMAT: +- Always export as: export const MyAnimation = () => { ... }; +- Do not use default exports + +- Use creative animations with smooth transitions +- Component should use frame-based animations with interpolate() +- Make it visually impressive and modern +- Use inline styles for all styling +- ALWAYS use fontFamily: 'Inter, sans-serif' for ALL text elements to ensure consistent rendering +- Do not generate typescript types or interfaces +- ALWAYS make sure to show all contents on the screen WITHOUT going off-screen or being cut off +- ALWAYS set backgroundColor on AbsoluteFill from frame 0 - never fade in backgrounds +- NEVER NEVER NEVER use fade-in for the AbsoluteFill container - always have it fully visible from frame 0 + +`; + +export async function POST(req: Request) { + const { prompt, model = "gpt-5-mini" } = await req.json(); + + const apiKey = process.env.OPENAI_API_KEY; + + if (!apiKey) { + return new Response( + JSON.stringify({ error: "OPENAI_API_KEY environment variable is not set" }), + { + status: 500, + headers: { "Content-Type": "application/json" }, + }, + ); + } + + // Parse model ID - format can be "model-name" or "model-name:reasoning_effort" + const [modelName, reasoningEffort] = model.split(":"); + + const openai = createOpenAI({ apiKey }); + + try { + const result = streamText({ + model: openai(modelName), + system: SYSTEM_PROMPT, + prompt, + ...(reasoningEffort && { + providerOptions: { + openai: { + reasoningEffort: reasoningEffort, + }, + }, + }), + }); + + console.log( + "Generating React component with prompt:", + prompt, + "model:", + modelName, + reasoningEffort ? `reasoning_effort: ${reasoningEffort}` : "", + ); + + return result.toUIMessageStreamResponse({ + sendReasoning: true, + }); + } catch (error) { + console.error("Error generating code:", error); + return new Response( + JSON.stringify({ + error: "Failed to generate code. Please check your API key.", + }), + { status: 500, headers: { "Content-Type": "application/json" } }, + ); + } +} diff --git a/packages/template-code-generation/src/app/api/lambda/progress/route.ts b/packages/template-code-generation/src/app/api/lambda/progress/route.ts new file mode 100644 index 00000000000..7f6fbcfcba4 --- /dev/null +++ b/packages/template-code-generation/src/app/api/lambda/progress/route.ts @@ -0,0 +1,44 @@ +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"; + +export const POST = executeApi( + ProgressRequest, + async (req, body) => { + const renderProgress = await getRenderProgress({ + bucketName: body.bucketName, + functionName: speculateFunctionName({ + diskSizeInMb: DISK, + memorySizeInMb: RAM, + timeoutInSeconds: TIMEOUT, + }), + region: REGION as AwsRegion, + renderId: body.id, + }); + + if (renderProgress.fatalErrorEncountered) { + return { + type: "error", + message: renderProgress.errors[0].message, + }; + } + + if (renderProgress.done) { + return { + type: "done", + url: renderProgress.outputFile as string, + size: renderProgress.outputSizeInBytes as number, + }; + } + + return { + type: "progress", + progress: Math.max(0.03, renderProgress.overallProgress), + }; + }, +); diff --git a/packages/template-code-generation/src/app/api/lambda/render/route.ts b/packages/template-code-generation/src/app/api/lambda/render/route.ts new file mode 100644 index 00000000000..822349c0b4e --- /dev/null +++ b/packages/template-code-generation/src/app/api/lambda/render/route.ts @@ -0,0 +1,56 @@ +import { AwsRegion, RenderMediaOnLambdaOutput } from "@remotion/lambda/client"; +import { + renderMediaOnLambda, + 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"; + +export const POST = executeApi( + RenderRequest, + async (req, body) => { + if ( + !process.env.AWS_ACCESS_KEY_ID && + !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.", + ); + } + if ( + !process.env.AWS_SECRET_ACCESS_KEY && + !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.", + ); + } + + const result = await renderMediaOnLambda({ + codec: "h264", + functionName: speculateFunctionName({ + diskSizeInMb: DISK, + memorySizeInMb: RAM, + timeoutInSeconds: TIMEOUT, + }), + region: REGION as AwsRegion, + serveUrl: SITE_NAME, + composition: body.id, + inputProps: body.inputProps, + framesPerLambda: 10, + downloadBehavior: { + type: "download", + fileName: "video.mp4", + }, + }); + + return result; + }, +); diff --git a/packages/template-code-generation/src/app/code-examples/page.tsx b/packages/template-code-generation/src/app/code-examples/page.tsx new file mode 100644 index 00000000000..81a6850fe8c --- /dev/null +++ b/packages/template-code-generation/src/app/code-examples/page.tsx @@ -0,0 +1,196 @@ +"use client"; + +import { + useState, + useCallback, + useMemo, + Suspense, + useEffect, + 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 "../../templates"; +import { useAnimationState } from "../../hooks/useAnimationState"; +import { CodeEditor } from "../../components/CodeEditor"; +import { AnimationPlayer } from "../../components/AnimationPlayer"; +import { Logo } from "../../components/Logo"; + +function DemoPageContent() { + const searchParams = useSearchParams(); + const router = useRouter(); + + // Derive selected example directly from URL (single source of truth) + const selectedExample = useMemo(() => { + const exampleId = searchParams.get("example"); + if (exampleId) { + return getExampleById(exampleId) ?? examples[0]!; + } + return examples[0]!; + }, [searchParams]); + + const [sidebarOpen, setSidebarOpen] = useState(true); + const selectedButtonRef = useRef(null); + + const { code, Component, error, isCompiling, setCode, compileCode } = + useAnimationState(selectedExample.code); + + // Auto-scroll to selected example + useEffect(() => { + if (selectedButtonRef.current) { + selectedButtonRef.current.scrollIntoView({ + behavior: "smooth", + block: "nearest", + }); + } + }, [selectedExample.id]); + + const handleExampleSelect = useCallback( + (exampleId: string) => { + const example = getExampleById(exampleId); + if (example) { + setCode(example.code); + compileCode(example.code); + router.replace(`/code-examples?example=${exampleId}`, { + scroll: false, + }); + } + }, + [setCode, compileCode, router], + ); + + const handleCodeChange = useCallback( + (newCode: string) => { + setCode(newCode); + compileCode(newCode); + }, + [setCode, compileCode], + ); + + const categories = Array.from(new Set(examples.map((e) => e.category))); + + return ( +
+ {/* Header with logo */} +
+
+ + + + Back to Home + +
+
+

Example Gallery

+
+ + {/* Main content with sidebar */} +
+ {/* Sidebar */} +
+
+ {categories.map((category) => ( +
+

+ {category} +

+
+ {examples + .filter((e) => e.category === category) + .map((example) => ( + + ))} +
+
+ ))} +
+
+ + {/* Main content */} +
+
+ +
+

+ {selectedExample.name} +

+

+ {selectedExample.description} +

+
+
+ +
+ + +
+
+
+
+ ); +} + +export default function DemoPage() { + return ( + +
+
+ } + > + +
+ ); +} diff --git a/packages/template-code-generation/src/app/favicon.ico b/packages/template-code-generation/src/app/favicon.ico new file mode 100644 index 00000000000..718d6fea483 Binary files /dev/null and b/packages/template-code-generation/src/app/favicon.ico differ diff --git a/packages/template-code-generation/src/app/generate/page.tsx b/packages/template-code-generation/src/app/generate/page.tsx new file mode 100644 index 00000000000..f795cd35d7f --- /dev/null +++ b/packages/template-code-generation/src/app/generate/page.tsx @@ -0,0 +1,169 @@ +"use client"; + +import { useState, useCallback, useEffect, useRef, Suspense } from "react"; +import type { NextPage } from "next"; +import { useSearchParams } from "next/navigation"; +import { Loader2 } from "lucide-react"; +import { CodeEditor } from "../../components/CodeEditor"; +import { AnimationPlayer } from "../../components/AnimationPlayer"; +import { PageLayout } from "../../components/PageLayout"; +import { + PromptInput, + type StreamPhase, + type PromptInputRef, +} from "../../components/PromptInput"; +import { SettingsModal } from "../../components/SettingsModal"; +import { examples } from "../../templates"; +import { useAnimationState } from "../../hooks/useAnimationState"; + +function GeneratePageContent() { + const searchParams = useSearchParams(); + const initialPrompt = searchParams.get("prompt") || ""; + + // If we have an initial prompt from URL, start in streaming state + // so syntax highlighting is disabled from the beginning + const willAutoStart = Boolean(initialPrompt); + + const [durationInFrames, setDurationInFrames] = useState( + examples[0]?.durationInFrames || 150, + ); + const [fps, setFps] = useState(examples[0]?.fps || 30); + const [isStreaming, setIsStreaming] = useState(willAutoStart); + const [streamPhase, setStreamPhase] = useState( + willAutoStart ? "reasoning" : "idle", + ); + const [prompt, setPrompt] = useState(initialPrompt); + const [hasAutoStarted, setHasAutoStarted] = useState(false); + const [hasGeneratedOnce, setHasGeneratedOnce] = useState(false); + + const { code, Component, error, isCompiling, setCode, compileCode } = + useAnimationState(examples[0]?.code || ""); + + // Debounce compilation + const debounceRef = useRef | null>(null); + + const isStreamingRef = useRef(isStreaming); + const codeRef = useRef(code); + + useEffect(() => { + codeRef.current = code; + }, [code]); + + useEffect(() => { + const wasStreaming = isStreamingRef.current; + isStreamingRef.current = isStreaming; + + // Compile when streaming ends + if (wasStreaming && !isStreaming) { + compileCode(codeRef.current); + } + }, [isStreaming, compileCode]); + + const handleCodeChange = useCallback( + (newCode: string) => { + setCode(newCode); + setHasGeneratedOnce(true); + + // Clear existing debounce + if (debounceRef.current) { + clearTimeout(debounceRef.current); + } + + // Skip compilation while streaming - will compile when streaming ends + if (isStreamingRef.current) { + return; + } + + // Set new debounce + debounceRef.current = setTimeout(() => { + compileCode(newCode); + }, 500); + }, + [setCode, compileCode], + ); + + // Cleanup debounce on unmount + useEffect(() => { + return () => { + if (debounceRef.current) { + clearTimeout(debounceRef.current); + } + }; + }, []); + + const handleStreamingChange = useCallback((streaming: boolean) => { + setIsStreaming(streaming); + }, []); + + // Auto-trigger generation if prompt came from URL + const promptInputRef = useRef(null); + + useEffect(() => { + if (initialPrompt && !hasAutoStarted && promptInputRef.current) { + setHasAutoStarted(true); + // Small delay to ensure component is mounted + setTimeout(() => { + promptInputRef.current?.triggerGeneration(); + }, 100); + } + }, [initialPrompt, hasAutoStarted]); + + return ( + + } + > +
+
+ + +
+ + +
+
+ ); +} + +function LoadingFallback() { + return ( +
+ +
+ ); +} + +const GeneratePage: NextPage = () => { + return ( + }> + + + ); +}; + +export default GeneratePage; diff --git a/packages/template-code-generation/src/app/layout.tsx b/packages/template-code-generation/src/app/layout.tsx new file mode 100644 index 00000000000..e19d2dc5cb2 --- /dev/null +++ b/packages/template-code-generation/src/app/layout.tsx @@ -0,0 +1,25 @@ +import "../../styles/global.css"; +import { Metadata, Viewport } from "next"; + +export const metadata: Metadata = { + title: "Remotion and Next.js", + description: "Remotion and Next.js", +}; + +export const viewport: Viewport = { + width: "device-width", + initialScale: 1, + maximumScale: 1, +}; + +export default function RootLayout({ + children, +}: { + children: React.ReactNode; +}) { + return ( + + {children} + + ); +} diff --git a/packages/template-code-generation/src/app/page.tsx b/packages/template-code-generation/src/app/page.tsx new file mode 100644 index 00000000000..95c868ffee9 --- /dev/null +++ b/packages/template-code-generation/src/app/page.tsx @@ -0,0 +1,151 @@ +"use client"; + +import { useState } from "react"; +import type { NextPage } from "next"; +import { useRouter } from "next/navigation"; +import Link from "next/link"; +import { + ArrowUp, + SquareArrowOutUpRight, + Loader2, + Type, + MessageCircle, + Hash, + BarChart3, + Disc, + type LucideIcon, +} from "lucide-react"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { examplePrompts } from "@/data/examplePrompts"; +import { MODELS, type ModelId } from "@/components/PromptInput"; +import { PageLayout } from "@/components/PageLayout"; + +const iconMap: Record = { + Type, + MessageCircle, + Hash, + BarChart3, + Disc, +}; + +const Home: NextPage = () => { + const router = useRouter(); + const [prompt, setPrompt] = useState(""); + const [model, setModel] = useState("gpt-5.1:low"); + const [isNavigating, setIsNavigating] = useState(false); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (!prompt.trim()) return; + + setIsNavigating(true); + const params = new URLSearchParams({ prompt, model }); + router.push(`/generate?${params.toString()}`); + }; + + const handleKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { + e.preventDefault(); + handleSubmit(e); + } + }; + + return ( + +
+

+ What do you want to create? +

+ +
+
+