diff --git a/.changeset/long-schools-trade.md b/.changeset/long-schools-trade.md new file mode 100644 index 0000000..4f9cd8c --- /dev/null +++ b/.changeset/long-schools-trade.md @@ -0,0 +1,5 @@ +--- +"create-better-t-stack": minor +--- + +add nuxt and expo with orpc diff --git a/apps/cli/src/constants.ts b/apps/cli/src/constants.ts index 7413fdd..7edf3ee 100644 --- a/apps/cli/src/constants.ts +++ b/apps/cli/src/constants.ts @@ -25,8 +25,8 @@ export const DEFAULT_CONFIG: ProjectConfig = { }; export const dependencyVersionMap = { - "better-auth": "^1.2.6", - "@better-auth/expo": "^1.2.6", + "better-auth": "^1.2.7", + "@better-auth/expo": "^1.2.7", "drizzle-orm": "^0.38.4", "drizzle-kit": "^0.30.5", @@ -74,12 +74,14 @@ export const dependencyVersionMap = { ai: "^4.2.8", "@ai-sdk/google": "^1.2.3", + "@ai-sdk/vue": "^1.2.8", "@prisma/extension-accelerate": "^1.3.0", - "@orpc/server": "^1.0.3", - "@orpc/react-query": "^1.0.3", - "@orpc/client": "^1.0.3", + "@orpc/server": "^1.1.0", + "@orpc/client": "^1.1.0", + "@orpc/react-query": "^1.1.0", + "@orpc/vue-query": "^1.1.0", "@trpc/tanstack-react-query": "^11.0.0", "@trpc/server": "^11.0.0", diff --git a/apps/cli/src/helpers/addons-setup.ts b/apps/cli/src/helpers/addons-setup.ts index 9b299d4..64d11b4 100644 --- a/apps/cli/src/helpers/addons-setup.ts +++ b/apps/cli/src/helpers/addons-setup.ts @@ -10,8 +10,9 @@ import type { ProjectConfig } from "../types"; export async function setupAddons(config: ProjectConfig) { const { projectName, addons, frontend } = config; const projectDir = path.resolve(process.cwd(), projectName); - const hasWebFrontend = + const hasReactWebFrontend = frontend.includes("react-router") || frontend.includes("tanstack-router"); + const hasNuxtFrontend = frontend.includes("nuxt"); if (addons.includes("turborepo")) { await addPackageDependency({ @@ -20,10 +21,10 @@ export async function setupAddons(config: ProjectConfig) { }); } - if (addons.includes("pwa") && hasWebFrontend) { + if (addons.includes("pwa") && hasReactWebFrontend) { await setupPwa(projectDir, frontend); } - if (addons.includes("tauri") && hasWebFrontend) { + if (addons.includes("tauri") && (hasReactWebFrontend || hasNuxtFrontend)) { await setupTauri(config); } if (addons.includes("biome")) { @@ -89,6 +90,11 @@ async function setupHusky(projectDir: string) { } async function setupPwa(projectDir: string, frontends: ProjectFrontend[]) { + const isCompatibleFrontend = frontends.some((f) => + ["react-router", "tanstack-router"].includes(f), + ); + if (!isCompatibleFrontend) return; + const clientPackageDir = getWebAppDir(projectDir, frontends); if (!(await fs.pathExists(clientPackageDir))) { diff --git a/apps/cli/src/helpers/api-setup.ts b/apps/cli/src/helpers/api-setup.ts index 7328a81..98ebda1 100644 --- a/apps/cli/src/helpers/api-setup.ts +++ b/apps/cli/src/helpers/api-setup.ts @@ -4,39 +4,84 @@ import type { ProjectConfig } from "../types"; import { addPackageDependency } from "../utils/add-package-deps"; export async function setupApi(config: ProjectConfig): Promise { - const { api, projectName } = config; + const { api, projectName, frontend } = config; const projectDir = path.resolve(process.cwd(), projectName); const webDir = path.join(projectDir, "apps/web"); const serverDir = path.join(projectDir, "apps/server"); const webDirExists = await fs.pathExists(webDir); + const hasReactWeb = frontend.some((f) => + ["tanstack-router", "react-router", "tanstack-start", "next"].includes(f), + ); + const hasNuxtWeb = frontend.includes("nuxt"); if (api === "orpc") { - if (webDirExists) { - await addPackageDependency({ - dependencies: ["@orpc/react-query", "@orpc/server", "@orpc/client"], - projectDir: webDir, - }); - } await addPackageDependency({ dependencies: ["@orpc/server", "@orpc/client"], projectDir: serverDir, }); - } - - if (api === "trpc") { - if (webDirExists) { - await addPackageDependency({ - dependencies: [ - "@trpc/tanstack-react-query", - "@trpc/server", - "@trpc/client", - ], - projectDir: webDir, - }); - } + } else if (api === "trpc") { await addPackageDependency({ dependencies: ["@trpc/server", "@trpc/client"], projectDir: serverDir, }); + if (config.backend === "hono") { + await addPackageDependency({ + dependencies: ["@hono/trpc-server"], + projectDir: serverDir, + }); + } else if (config.backend === "elysia") { + await addPackageDependency({ + dependencies: ["@elysiajs/trpc"], + projectDir: serverDir, + }); + } + } + + if (webDirExists) { + if (hasReactWeb) { + if (api === "orpc") { + await addPackageDependency({ + dependencies: ["@orpc/react-query", "@orpc/client", "@orpc/server"], + projectDir: webDir, + }); + } else if (api === "trpc") { + await addPackageDependency({ + dependencies: [ + "@trpc/tanstack-react-query", + "@trpc/client", + "@trpc/server", + ], + projectDir: webDir, + }); + } + } else if (hasNuxtWeb) { + if (api === "orpc") { + await addPackageDependency({ + dependencies: ["@orpc/vue-query", "@orpc/client", "@orpc/server"], + projectDir: webDir, + }); + } + } + } + + if (frontend.includes("native")) { + const nativeDir = path.join(projectDir, "apps/native"); + if (await fs.pathExists(nativeDir)) { + if (api === "trpc") { + await addPackageDependency({ + dependencies: [ + "@trpc/tanstack-react-query", + "@trpc/client", + "@trpc/server", + ], + projectDir: nativeDir, + }); + } else if (api === "orpc") { + await addPackageDependency({ + dependencies: ["@orpc/react-query", "@orpc/client", "@orpc/server"], + projectDir: nativeDir, + }); + } + } } } diff --git a/apps/cli/src/helpers/auth-setup.ts b/apps/cli/src/helpers/auth-setup.ts index b43b184..bc263ed 100644 --- a/apps/cli/src/helpers/auth-setup.ts +++ b/apps/cli/src/helpers/auth-setup.ts @@ -25,11 +25,15 @@ export async function setupAuth(config: ProjectConfig): Promise { projectDir: serverDir, }); - const hasWebFrontend = - frontend.includes("react-router") || - frontend.includes("tanstack-router") || - frontend.includes("tanstack-start") || - frontend.includes("next"); + const hasWebFrontend = frontend.some((f) => + [ + "react-router", + "tanstack-router", + "tanstack-start", + "next", + "nuxt", + ].includes(f), + ); if (hasWebFrontend && clientDirExists) { await addPackageDependency({ diff --git a/apps/cli/src/helpers/create-project.ts b/apps/cli/src/helpers/create-project.ts index f5db2ad..269b57a 100644 --- a/apps/cli/src/helpers/create-project.ts +++ b/apps/cli/src/helpers/create-project.ts @@ -17,7 +17,6 @@ import { initializeGit, updatePackageConfigurations } from "./project-config"; import { setupRuntime } from "./runtime-setup"; import { copyBaseTemplate, - fixGitignoreFiles, handleExtras, setupAddonsTemplate, setupAuthTemplate, @@ -70,8 +69,6 @@ export async function createProject(options: ProjectConfig): Promise { await initializeGit(projectDir, options.git); - await fixGitignoreFiles(projectDir, options); - log.success("Project template successfully scaffolded!"); if (options.install) { diff --git a/apps/cli/src/helpers/env-setup.ts b/apps/cli/src/helpers/env-setup.ts index d83f45b..9a203bb 100644 --- a/apps/cli/src/helpers/env-setup.ts +++ b/apps/cli/src/helpers/env-setup.ts @@ -54,13 +54,18 @@ export async function setupEnvironmentVariables( const hasTanStackRouter = options.frontend.includes("tanstack-router"); const hasTanStackStart = options.frontend.includes("tanstack-start"); const hasNextJs = options.frontend.includes("next"); + const hasNuxt = options.frontend.includes("nuxt"); const hasWebFrontend = - hasReactRouter || hasTanStackRouter || hasTanStackStart || hasNextJs; + hasReactRouter || + hasTanStackRouter || + hasTanStackStart || + hasNextJs || + hasNuxt; - let corsOrigin = "http://localhost:3000"; + let corsOrigin = "http://localhost:3001"; if (hasReactRouter) { corsOrigin = "http://localhost:5173"; - } else if (hasTanStackRouter || hasTanStackStart || hasNextJs) { + } else if (hasTanStackRouter || hasTanStackStart || hasNextJs || hasNuxt) { corsOrigin = "http://localhost:3001"; } @@ -121,6 +126,8 @@ export async function setupEnvironmentVariables( if (hasNextJs) { envVarName = "NEXT_PUBLIC_SERVER_URL"; + } else if (hasNuxt) { + envVarName = "NUXT_PUBLIC_SERVER_URL"; } const clientVars: EnvVariable[] = [ diff --git a/apps/cli/src/helpers/examples-setup.ts b/apps/cli/src/helpers/examples-setup.ts index 031d8bc..0b3bc97 100644 --- a/apps/cli/src/helpers/examples-setup.ts +++ b/apps/cli/src/helpers/examples-setup.ts @@ -1,10 +1,11 @@ import path from "node:path"; import fs from "fs-extra"; +import type { AvailableDependencies } from "../constants"; import type { ProjectConfig } from "../types"; import { addPackageDependency } from "../utils/add-package-deps"; export async function setupExamples(config: ProjectConfig): Promise { - const { projectName, examples } = config; + const { projectName, examples, frontend } = config; const projectDir = path.resolve(process.cwd(), projectName); if (examples.includes("ai")) { @@ -12,9 +13,15 @@ export async function setupExamples(config: ProjectConfig): Promise { const serverDir = path.join(projectDir, "apps/server"); const clientDirExists = await fs.pathExists(clientDir); + const hasNuxt = frontend.includes("nuxt"); + if (clientDirExists) { + const dependencies: AvailableDependencies[] = ["ai"]; + if (hasNuxt) { + dependencies.push("@ai-sdk/vue"); + } await addPackageDependency({ - dependencies: ["ai"], + dependencies, projectDir: clientDir, }); } diff --git a/apps/cli/src/helpers/post-installation.ts b/apps/cli/src/helpers/post-installation.ts index 62019b0..0fee131 100644 --- a/apps/cli/src/helpers/post-installation.ts +++ b/apps/cli/src/helpers/post-installation.ts @@ -37,14 +37,22 @@ export function displayPostInstallInstructions( ? getNativeInstructions() : ""; const pwaInstructions = - addons?.includes("pwa") && frontend?.includes("react-router") + addons?.includes("pwa") && + (frontend?.includes("react-router") || + frontend?.includes("tanstack-router")) // Exclude Nuxt from PWA instructions ? getPwaInstructions() : ""; const starlightInstructions = addons?.includes("starlight") ? getStarlightInstructions(runCmd) : ""; const hasWeb = frontend?.some((f) => - ["tanstack-router", "react-router", "next", "tanstack-start"].includes(f), + [ + "tanstack-router", + "react-router", + "next", + "tanstack-start", + "nuxt", // Include Nuxt here + ].includes(f), ); const hasNative = frontend?.includes("native"); const bunWebNativeWarning = @@ -57,12 +65,13 @@ export function displayPostInstallInstructions( const hasTanstackRouter = frontend?.includes("tanstack-router"); const hasTanstackStart = frontend?.includes("tanstack-start"); const hasReactRouter = frontend?.includes("react-router"); + const hasNuxt = frontend?.includes("nuxt"); // Add Nuxt check const hasWebFrontend = - hasTanstackRouter || hasReactRouter || hasTanstackStart; + hasTanstackRouter || hasReactRouter || hasTanstackStart || hasNuxt; // Include Nuxt const hasNativeFrontend = frontend?.includes("native"); const hasFrontend = hasWebFrontend || hasNativeFrontend; - const webPort = hasReactRouter ? "5173" : "3001"; + const webPort = hasReactRouter ? "5173" : "3001"; // Nuxt uses 3001, same as others const tazeCommand = getPackageExecutionCommand(packageManager, "taze -r"); consola.box( @@ -93,7 +102,9 @@ ${ lintingInstructions ? `\n${lintingInstructions.trim()}` : "" }${pwaInstructions ? `\n${pwaInstructions.trim()}` : ""}${ starlightInstructions ? `\n${starlightInstructions.trim()}` : "" -}${noOrmWarning ? `\n${noOrmWarning.trim()}` : ""}${bunWebNativeWarning ? `\n${bunWebNativeWarning.trim()}` : ""} +}${noOrmWarning ? `\n${noOrmWarning.trim()}` : ""}${ + bunWebNativeWarning ? `\n${bunWebNativeWarning.trim()}` : "" +} ${pc.bold("Update all dependencies:\n")}${pc.cyan(tazeCommand)} @@ -177,9 +188,13 @@ function getStarlightInstructions(runCmd?: string): string { } function getNoOrmWarning(): string { - return `\n${pc.yellow("WARNING:")} Database selected without an ORM. Features requiring database access (e.g., examples, auth) need manual setup.\n`; + return `\n${pc.yellow( + "WARNING:", + )} Database selected without an ORM. Features requiring database access (e.g., examples, auth) need manual setup.\n`; } function getBunWebNativeWarning(): string { - return `\n${pc.yellow("WARNING:")} 'bun' might cause issues with web + native apps in a monorepo. Use 'pnpm' if problems arise.\n`; + return `\n${pc.yellow( + "WARNING:", + )} 'bun' might cause issues with web + native apps in a monorepo. Use 'pnpm' if problems arise.\n`; } diff --git a/apps/cli/src/helpers/project-config.ts b/apps/cli/src/helpers/project-config.ts index 6e38841..7085cb0 100644 --- a/apps/cli/src/helpers/project-config.ts +++ b/apps/cli/src/helpers/project-config.ts @@ -3,6 +3,7 @@ import { log } from "@clack/prompts"; import { $, execa } from "execa"; import fs from "fs-extra"; import pc from "picocolors"; +import { dependencyVersionMap } from "../constants"; import type { ProjectConfig } from "../types"; export async function updatePackageConfigurations( diff --git a/apps/cli/src/helpers/tauri-setup.ts b/apps/cli/src/helpers/tauri-setup.ts index 62acf3f..bb4844d 100644 --- a/apps/cli/src/helpers/tauri-setup.ts +++ b/apps/cli/src/helpers/tauri-setup.ts @@ -42,15 +42,19 @@ export async function setupTauri(config: ProjectConfig): Promise { } const hasReactRouter = frontend.includes("react-router"); + const hasNuxt = frontend.includes("nuxt"); + const devUrl = hasReactRouter ? "http://localhost:5173" : "http://localhost:3001"; + const frontendDist = hasNuxt ? "../.output/public" : "../dist"; + const tauriArgs = [ "init", `--app-name=${path.basename(projectDir)}`, `--window-title=${path.basename(projectDir)}`, - "--frontend-dist=../dist", + `--frontend-dist=${frontendDist}`, `--dev-url=${devUrl}`, `--before-dev-command=\"${packageManager} run dev\"`, `--before-build-command=\"${packageManager} run build\"`, diff --git a/apps/cli/src/helpers/template-manager.ts b/apps/cli/src/helpers/template-manager.ts index d7974f6..30b5292 100644 --- a/apps/cli/src/helpers/template-manager.ts +++ b/apps/cli/src/helpers/template-manager.ts @@ -28,17 +28,21 @@ async function processAndCopyFiles( if (relativeSrcPath.endsWith(".hbs")) { relativeDestPath = relativeSrcPath.slice(0, -4); } + if (path.basename(relativeSrcPath) === "_gitignore") { + relativeDestPath = path.join(path.dirname(relativeSrcPath), ".gitignore"); + } const destPath = path.join(destDir, relativeDestPath); await fs.ensureDir(path.dirname(destPath)); + if (!overwrite && (await fs.pathExists(destPath))) { + continue; + } + if (srcPath.endsWith(".hbs")) { await processTemplate(srcPath, destPath, context); } else { - if (!overwrite && (await fs.pathExists(destPath))) { - continue; - } await fs.copy(srcPath, destPath, { overwrite: true }); } } @@ -49,62 +53,69 @@ export async function copyBaseTemplate( context: ProjectConfig, ): Promise { const templateDir = path.join(PKG_ROOT, "templates/base"); - await processAndCopyFiles( - ["package.json", "_gitignore"], - templateDir, - projectDir, - context, - ); + await processAndCopyFiles(["**/*"], templateDir, projectDir, context); } export async function setupFrontendTemplates( projectDir: string, context: ProjectConfig, ): Promise { - const webFrontends = context.frontend.filter( - (f) => - f === "tanstack-router" || - f === "react-router" || - f === "tanstack-start" || - f === "next", + const hasReactWeb = context.frontend.some((f) => + ["tanstack-router", "react-router", "tanstack-start", "next"].includes(f), ); + const hasNuxtWeb = context.frontend.includes("nuxt"); const hasNative = context.frontend.includes("native"); - if (webFrontends.length > 0) { + if (hasReactWeb || hasNuxtWeb) { const webAppDir = path.join(projectDir, "apps/web"); await fs.ensureDir(webAppDir); - const webBaseDir = path.join(PKG_ROOT, "templates/frontend/web-base"); - if (await fs.pathExists(webBaseDir)) { - await processAndCopyFiles("**/*", webBaseDir, webAppDir, context); - } - - for (const framework of webFrontends) { - const frameworkSrcDir = path.join( + if (hasReactWeb) { + const webBaseDir = path.join( PKG_ROOT, - `templates/frontend/${framework}`, + "templates/frontend/react/web-base", ); - if (await fs.pathExists(frameworkSrcDir)) { - await processAndCopyFiles("**/*", frameworkSrcDir, webAppDir, context); + if (await fs.pathExists(webBaseDir)) { + await processAndCopyFiles("**/*", webBaseDir, webAppDir, context); + } + const reactFramework = context.frontend.find((f) => + ["tanstack-router", "react-router", "tanstack-start", "next"].includes( + f, + ), + ); + if (reactFramework) { + const frameworkSrcDir = path.join( + PKG_ROOT, + `templates/frontend/react/${reactFramework}`, + ); + if (await fs.pathExists(frameworkSrcDir)) { + await processAndCopyFiles( + "**/*", + frameworkSrcDir, + webAppDir, + context, + ); + } + const apiWebBaseDir = path.join( + PKG_ROOT, + `templates/api/${context.api}/web/react/base`, + ); + if (await fs.pathExists(apiWebBaseDir)) { + await processAndCopyFiles("**/*", apiWebBaseDir, webAppDir, context); + } + } + } else if (hasNuxtWeb) { + const nuxtBaseDir = path.join(PKG_ROOT, "templates/frontend/nuxt"); + if (await fs.pathExists(nuxtBaseDir)) { + await processAndCopyFiles("**/*", nuxtBaseDir, webAppDir, context); + } + const apiWebNuxtDir = path.join( + PKG_ROOT, + `templates/api/${context.api}/web/nuxt`, + ); + if (await fs.pathExists(apiWebNuxtDir)) { + await processAndCopyFiles("**/*", apiWebNuxtDir, webAppDir, context); } - } - - const webFramework = webFrontends[0]; - - const apiWebBaseDir = path.join( - PKG_ROOT, - `templates/api/${context.api}/web/base`, - ); - if (await fs.pathExists(apiWebBaseDir)) { - await processAndCopyFiles("**/*", apiWebBaseDir, webAppDir, context); - } - - const apiWebFrameworkDir = path.join( - PKG_ROOT, - `templates/api/${context.api}/web/${webFramework}`, - ); - if (await fs.pathExists(apiWebFrameworkDir)) { - await processAndCopyFiles("**/*", apiWebFrameworkDir, webAppDir, context); } } @@ -117,14 +128,32 @@ export async function setupFrontendTemplates( await processAndCopyFiles("**/*", nativeBaseDir, nativeAppDir, context); } - const apiNativeSrcDir = path.join( - PKG_ROOT, - `templates/api/${context.api}/native`, - ); - - if (await fs.pathExists(apiNativeSrcDir)) { - await processAndCopyFiles("**/*", apiNativeSrcDir, nativeAppDir, context); - } else { + if (context.api === "trpc") { + const apiNativeSrcDir = path.join( + PKG_ROOT, + `templates/api/${context.api}/native`, + ); + if (await fs.pathExists(apiNativeSrcDir)) { + await processAndCopyFiles( + "**/*", + apiNativeSrcDir, + nativeAppDir, + context, + ); + } + } else if (context.api === "orpc") { + const apiNativeSrcDir = path.join( + PKG_ROOT, + `templates/api/${context.api}/native`, + ); + if (await fs.pathExists(apiNativeSrcDir)) { + await processAndCopyFiles( + "**/*", + apiNativeSrcDir, + nativeAppDir, + context, + ); + } } } } @@ -222,13 +251,10 @@ export async function setupAuthTemplate( const webAppDirExists = await fs.pathExists(webAppDir); const nativeAppDirExists = await fs.pathExists(nativeAppDir); - const webFrontends = context.frontend.filter( - (f) => - f === "tanstack-router" || - f === "react-router" || - f === "tanstack-start" || - f === "next", + const hasReactWeb = context.frontend.some((f) => + ["tanstack-router", "react-router", "tanstack-start", "next"].includes(f), ); + const hasNuxtWeb = context.frontend.includes("nuxt"); const hasNative = context.frontend.includes("native"); if (serverAppDirExists) { @@ -240,12 +266,6 @@ export async function setupAuthTemplate( serverAppDir, context, ); - } else { - consola.warn( - pc.yellow( - `Warning: Base auth server template not found at ${authServerBaseSrc}`, - ), - ); } if (context.backend === "next") { @@ -260,12 +280,6 @@ export async function setupAuthTemplate( serverAppDir, context, ); - } else { - consola.warn( - pc.yellow( - `Warning: Next auth server template not found at ${authServerNextSrc}`, - ), - ); } } @@ -294,44 +308,40 @@ export async function setupAuthTemplate( ); } } - } else { - consola.warn( - pc.yellow( - "Warning: apps/server directory does not exist, skipping server-side auth template setup.", - ), - ); } - if (webFrontends.length > 0 && webAppDirExists) { - const authWebBaseSrc = path.join(PKG_ROOT, "templates/auth/web/base"); - if (await fs.pathExists(authWebBaseSrc)) { - await processAndCopyFiles("**/*", authWebBaseSrc, webAppDir, context); - } else { - consola.warn( - pc.yellow( - `Warning: Base auth web template not found at ${authWebBaseSrc}`, + if ((hasReactWeb || hasNuxtWeb) && webAppDirExists) { + if (hasReactWeb) { + const authWebBaseSrc = path.join( + PKG_ROOT, + "templates/auth/web/react/base", + ); + if (await fs.pathExists(authWebBaseSrc)) { + await processAndCopyFiles("**/*", authWebBaseSrc, webAppDir, context); + } + const reactFramework = context.frontend.find((f) => + ["tanstack-router", "react-router", "tanstack-start", "next"].includes( + f, ), ); - } - - for (const framework of webFrontends) { - const authWebFrameworkSrc = path.join( - PKG_ROOT, - `templates/auth/web/${framework}`, - ); - if (await fs.pathExists(authWebFrameworkSrc)) { - await processAndCopyFiles( - "**/*", - authWebFrameworkSrc, - webAppDir, - context, - ); - } else { - consola.warn( - pc.yellow( - `Warning: Auth web template for ${framework} not found at ${authWebFrameworkSrc}`, - ), + if (reactFramework) { + const authWebFrameworkSrc = path.join( + PKG_ROOT, + `templates/auth/web/react/${reactFramework}`, ); + if (await fs.pathExists(authWebFrameworkSrc)) { + await processAndCopyFiles( + "**/*", + authWebFrameworkSrc, + webAppDir, + context, + ); + } + } + } else if (hasNuxtWeb) { + const authWebNuxtSrc = path.join(PKG_ROOT, "templates/auth/web/nuxt"); + if (await fs.pathExists(authWebNuxtSrc)) { + await processAndCopyFiles("**/*", authWebNuxtSrc, webAppDir, context); } } } @@ -354,50 +364,25 @@ export async function setupAddonsTemplate( projectDir: string, context: ProjectConfig, ): Promise { - if (context.addons.includes("turborepo")) { - const turboSrcDir = path.join(PKG_ROOT, "templates/addons/turborepo"); - if (await fs.pathExists(turboSrcDir)) { - await processAndCopyFiles("**/*", turboSrcDir, projectDir, context); - } else { - consola.warn(pc.yellow("Warning: Turborepo addon template not found.")); - } - } + if (!context.addons || context.addons.length === 0) return; - if (context.addons.includes("husky")) { - const huskySrcDir = path.join(PKG_ROOT, "templates/addons/husky"); - if (await fs.pathExists(huskySrcDir)) { - await processAndCopyFiles("**/*", huskySrcDir, projectDir, context); - } else { - consola.warn(pc.yellow("Warning: Husky addon template not found.")); - } - } + for (const addon of context.addons) { + if (addon === "none") continue; - if (context.addons.includes("biome")) { - const biomeSrcDir = path.join(PKG_ROOT, "templates/addons/biome"); - if (await fs.pathExists(biomeSrcDir)) { - await processAndCopyFiles("**/*", biomeSrcDir, projectDir, context); - } else { - consola.warn(pc.yellow("Warning: Biome addon template not found.")); - } - } + let addonSrcDir = path.join(PKG_ROOT, `templates/addons/${addon}`); + let addonDestDir = projectDir; - if (context.addons.includes("pwa")) { - const pwaSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web"); - const webAppDir = path.join(projectDir, "apps/web"); - const webAppDirExists = await fs.pathExists(webAppDir); - - if (await fs.pathExists(pwaSrcDir)) { - if (webAppDirExists) { - await processAndCopyFiles("**/*", pwaSrcDir, webAppDir, context); - } else { - consola.warn( - pc.yellow( - "Warning: apps/web directory not found, cannot setup PWA addon template.", - ), - ); + if (addon === "pwa") { + addonSrcDir = path.join(PKG_ROOT, "templates/addons/pwa/apps/web"); + addonDestDir = path.join(projectDir, "apps/web"); + if (!(await fs.pathExists(addonDestDir))) { + continue; } + } + + if (await fs.pathExists(addonSrcDir)) { + await processAndCopyFiles("**/*", addonSrcDir, addonDestDir, context); } else { - consola.warn(pc.yellow("Warning: PWA addon template not found.")); } } } @@ -414,7 +399,14 @@ export async function setupExamplesTemplate( const serverAppDirExists = await fs.pathExists(serverAppDir); const webAppDirExists = await fs.pathExists(webAppDir); + const hasReactWeb = context.frontend.some((f) => + ["tanstack-router", "react-router", "tanstack-start", "next"].includes(f), + ); + const hasNuxtWeb = context.frontend.includes("nuxt"); + for (const example of context.examples) { + if (example === "none") continue; + const exampleBaseDir = path.join(PKG_ROOT, `templates/examples/${example}`); if (serverAppDirExists) { @@ -456,10 +448,10 @@ export async function setupExamplesTemplate( } } - if (webAppDirExists) { - const exampleWebSrc = path.join(exampleBaseDir, "web"); + if (hasReactWeb && webAppDirExists) { + const exampleWebSrc = path.join(exampleBaseDir, "web/react"); if (await fs.pathExists(exampleWebSrc)) { - const webFrameworks = context.frontend.filter((f) => + const reactFramework = context.frontend.find((f) => [ "next", "react-router", @@ -467,8 +459,11 @@ export async function setupExamplesTemplate( "tanstack-start", ].includes(f), ); - for (const framework of webFrameworks) { - const exampleWebFrameworkSrc = path.join(exampleWebSrc, framework); + if (reactFramework) { + const exampleWebFrameworkSrc = path.join( + exampleWebSrc, + reactFramework, + ); if (await fs.pathExists(exampleWebFrameworkSrc)) { await processAndCopyFiles( "**/*", @@ -480,36 +475,27 @@ export async function setupExamplesTemplate( } } } - } - } -} - -export async function fixGitignoreFiles( - projectDir: string, - context: ProjectConfig, -): Promise { - const gitignoreFiles = await globby(["**/.gitignore.hbs", "**/_gitignore"], { - cwd: projectDir, - dot: true, - onlyFiles: true, - absolute: true, - ignore: ["**/node_modules/**", "**/.git/**"], - }); - - for (const currentPath of gitignoreFiles) { - const dir = path.dirname(currentPath); - const filename = path.basename(currentPath); - const destPath = path.join(dir, ".gitignore"); - - try { - if (filename === ".gitignore.hbs") { - await processTemplate(currentPath, destPath, context); - await fs.remove(currentPath); - } else if (filename === "_gitignore") { - await fs.move(currentPath, destPath, { overwrite: true }); + } else if (hasNuxtWeb && webAppDirExists) { + // Only copy Nuxt examples if the API is oRPC (as tRPC is not supported) + if (context.api === "orpc") { + const exampleWebNuxtSrc = path.join(exampleBaseDir, "web/nuxt"); + if (await fs.pathExists(exampleWebNuxtSrc)) { + await processAndCopyFiles( + "**/*", + exampleWebNuxtSrc, + webAppDir, + context, + false, + ); + } else { + consola.info( + pc.gray( + `Skipping Nuxt web template for example '${example}' (template not found).`, + ), + ); + } } - } catch (error) { - consola.error(`Error processing gitignore file ${currentPath}:`, error); + // If API is tRPC, skip Nuxt examples silently as CLI validation prevents this combo. } } } @@ -518,24 +504,24 @@ export async function handleExtras( projectDir: string, context: ProjectConfig, ): Promise { + const extrasDir = path.join(PKG_ROOT, "templates/extras"); + if (context.packageManager === "pnpm") { - const pnpmWorkspaceSrc = path.join( - PKG_ROOT, - "templates/extras/pnpm-workspace.yaml", - ); + const pnpmWorkspaceSrc = path.join(extrasDir, "pnpm-workspace.yaml"); const pnpmWorkspaceDest = path.join(projectDir, "pnpm-workspace.yaml"); if (await fs.pathExists(pnpmWorkspaceSrc)) { await fs.copy(pnpmWorkspaceSrc, pnpmWorkspaceDest); - } else { } } - if (context.frontend.includes("native")) { - const npmrcSrc = path.join(PKG_ROOT, "templates/extras/_npmrc"); + if ( + context.packageManager === "pnpm" && + (context.frontend.includes("native") || context.frontend.includes("nuxt")) + ) { + const npmrcTemplateSrc = path.join(extrasDir, "_npmrc.hbs"); const npmrcDest = path.join(projectDir, ".npmrc"); - if (await fs.pathExists(npmrcSrc)) { - await fs.copy(npmrcSrc, npmrcDest); - } else { + if (await fs.pathExists(npmrcTemplateSrc)) { + await processTemplate(npmrcTemplateSrc, npmrcDest, context); } } } diff --git a/apps/cli/src/index.ts b/apps/cli/src/index.ts index fc4c1ec..199636a 100644 --- a/apps/cli/src/index.ts +++ b/apps/cli/src/index.ts @@ -75,6 +75,7 @@ async function main() { "react-router", "tanstack-start", "next", + "nuxt", "native", "none", ], @@ -268,11 +269,12 @@ function processAndValidateFlags( f === "tanstack-router" || f === "react-router" || f === "tanstack-start" || - f === "next", + f === "next" || + f === "nuxt", ); if (webFrontends.length > 1) { consola.fatal( - "Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next", + "Cannot select multiple web frameworks. Choose only one of: tanstack-router, tanstack-start, react-router, next, nuxt", ); process.exit(1); } @@ -445,18 +447,20 @@ function processAndValidateFlags( } const includesNative = effectiveFrontend?.includes("native"); - if (includesNative && effectiveApi === "orpc") { + const includesNuxt = effectiveFrontend?.includes("nuxt"); + + if (includesNuxt && effectiveApi === "trpc") { consola.fatal( - `oRPC API is not supported with 'native' frontend. Please use --api trpc or remove 'native' from --frontend.`, + `tRPC API is not supported with 'nuxt' frontend. Please use --api orpc or remove 'nuxt' from --frontend.`, ); process.exit(1); } if ( - includesNative && - effectiveApi !== "trpc" && - (!options.api || (options.yes && options.api !== "orpc")) + includesNuxt && + effectiveApi !== "orpc" && + (!options.api || (options.yes && options.api !== "trpc")) ) { - config.api = "trpc"; + config.api = "orpc"; } if (config.addons && config.addons.length > 0) { @@ -465,18 +469,35 @@ function processAndValidateFlags( webSpecificAddons.includes(addon), ); const hasCompatibleWebFrontend = effectiveFrontend?.some( - (f) => f === "tanstack-router" || f === "react-router", + (f) => + f === "tanstack-router" || + f === "react-router" || + (f === "nuxt" && + config.addons?.includes("tauri") && + !config.addons?.includes("pwa")), // Nuxt compatible with Tauri, not PWA ); if (hasWebSpecificAddons && !hasCompatibleWebFrontend) { + let incompatibleAddon = ""; + if (config.addons.includes("pwa") && includesNuxt) { + incompatibleAddon = "PWA addon is not compatible with Nuxt."; + } else if ( + config.addons.includes("pwa") || + config.addons.includes("tauri") + ) { + incompatibleAddon = + "PWA and Tauri addons require tanstack-router, react-router, or Nuxt (Tauri only)."; + } consola.fatal( - "PWA and Tauri addons require tanstack-router or react-router. Cannot use these addons with your frontend selection.", + `${incompatibleAddon} Cannot use these addons with your frontend selection.`, ); process.exit(1); } if (config.addons.includes("husky") && !config.addons.includes("biome")) { - config.addons.push("biome"); + consola.warn( + "Husky addon is recommended to be used with Biome for lint-staged configuration.", + ); } config.addons = [...new Set(config.addons)]; } @@ -484,17 +505,24 @@ function processAndValidateFlags( if (config.examples && config.examples.length > 0) { if (config.examples.includes("ai") && effectiveBackend === "elysia") { consola.fatal( - "AI example is not compatible with Elysia backend. Cannot use --examples ai with --backend elysia", + "The 'ai' example is not compatible with the Elysia backend.", ); process.exit(1); } const hasWebFrontendForExamples = effectiveFrontend?.some((f) => - ["tanstack-router", "react-router", "tanstack-start", "next"].includes(f), + [ + "tanstack-router", + "react-router", + "tanstack-start", + "next", + "nuxt", + ].includes(f), ); - if (!hasWebFrontendForExamples) { + + if (config.examples.length > 0 && !hasWebFrontendForExamples) { consola.fatal( - "Examples require a web frontend (tanstack-router, react-router, tanstack-start, or next). Cannot use --examples with your frontend selection.", + "Examples require a web frontend (tanstack-router, react-router, tanstack-start, next, or nuxt).", ); process.exit(1); } @@ -507,12 +535,8 @@ main().catch((err) => { consola.error("Aborting installation due to unexpected error..."); if (err instanceof Error) { consola.error(err.message); - console.error(err.stack); } else { - consola.error( - "An unknown error has occurred. Please open an issue on GitHub with the below:", - ); console.error(err); } - process.exit(1); + process.exit(1); // Ensure exit on error }); diff --git a/apps/cli/src/prompts/api.ts b/apps/cli/src/prompts/api.ts index 8be2c98..5fdc94b 100644 --- a/apps/cli/src/prompts/api.ts +++ b/apps/cli/src/prompts/api.ts @@ -9,7 +9,7 @@ export async function getApiChoice( ): Promise { if (Api) return Api; - const includesNative = frontend?.includes("native"); + const includesNuxt = frontend?.includes("nuxt"); let apiOptions = [ { @@ -24,12 +24,12 @@ export async function getApiChoice( }, ]; - if (includesNative) { + if (includesNuxt) { apiOptions = [ { - value: "trpc" as const, - label: "tRPC", - hint: "End-to-end typesafe APIs made easy (Required for Native frontend)", + value: "orpc" as const, + label: "oRPC", + hint: "End-to-end type-safe APIs (Required for Nuxt frontend)", }, ]; } @@ -37,7 +37,7 @@ export async function getApiChoice( const apiType = await select({ message: "Select API type", options: apiOptions, - initialValue: includesNative ? "trpc" : DEFAULT_CONFIG.api, + initialValue: includesNuxt ? "orpc" : DEFAULT_CONFIG.api, }); if (isCancel(apiType)) { @@ -45,8 +45,8 @@ export async function getApiChoice( process.exit(0); } - if (includesNative && apiType !== "trpc") { - return "trpc"; + if (includesNuxt && apiType !== "orpc") { + return "orpc"; } return apiType; diff --git a/apps/cli/src/prompts/examples.ts b/apps/cli/src/prompts/examples.ts index ea250ed..a77013e 100644 --- a/apps/cli/src/prompts/examples.ts +++ b/apps/cli/src/prompts/examples.ts @@ -2,7 +2,6 @@ import { cancel, isCancel, multiselect } from "@clack/prompts"; import pc from "picocolors"; import { DEFAULT_CONFIG } from "../constants"; import type { - ProjectApi, ProjectBackend, ProjectDatabase, ProjectExamples, @@ -22,46 +21,36 @@ export async function getExamplesChoice( const hasWebFrontend = frontends?.includes("react-router") || frontends?.includes("tanstack-router") || - frontends?.includes("tanstack-start"); + frontends?.includes("tanstack-start") || + frontends?.includes("next") || // Added next + frontends?.includes("nuxt"); // Added nuxt if (!hasWebFrontend) return []; let response: ProjectExamples[] | symbol = []; + const options: { value: ProjectExamples; label: string; hint: string }[] = [ + { + value: "todo" as const, + label: "Todo App", + hint: "A simple CRUD example app", + }, + ]; - if (backend === "elysia") { - response = await multiselect({ - message: "Include examples", - options: [ - { - value: "todo", - label: "Todo App", - hint: "A simple CRUD example app", - }, - ], - required: false, - initialValues: DEFAULT_CONFIG.examples, + // AI example is available for hono, express, next backends, and Nuxt (if backend is not elysia) + if (backend !== "elysia") { + options.push({ + value: "ai" as const, + label: "AI Chat", + hint: "A simple AI chat interface using AI SDK", }); } - if (backend === "hono" || backend === "express") { - response = await multiselect({ - message: "Include examples", - options: [ - { - value: "todo", - label: "Todo App", - hint: "A simple CRUD example app", - }, - { - value: "ai", - label: "AI Chat", - hint: "A simple AI chat interface using AI SDK", - }, - ], - required: false, - initialValues: DEFAULT_CONFIG.examples, - }); - } + response = await multiselect({ + message: "Include examples", + options: options, + required: false, + initialValues: DEFAULT_CONFIG.examples, + }); if (isCancel(response)) { cancel(pc.red("Operation cancelled")); diff --git a/apps/cli/src/prompts/frontend-option.ts b/apps/cli/src/prompts/frontend-option.ts index e12da7a..246e3cc 100644 --- a/apps/cli/src/prompts/frontend-option.ts +++ b/apps/cli/src/prompts/frontend-option.ts @@ -14,7 +14,7 @@ export async function getFrontendChoice( { value: "web", label: "Web", - hint: "React Web Application", + hint: "React or Vue Web Application", }, { value: "native", @@ -28,7 +28,8 @@ export async function getFrontendChoice( f === "tanstack-router" || f === "react-router" || f === "tanstack-start" || - f === "next", + f === "next" || + f === "nuxt", ) ? ["web"] : [], @@ -60,6 +61,11 @@ export async function getFrontendChoice( label: "Next.js", hint: "The React Framework for the Web", }, + { + value: "nuxt", + label: "Nuxt", + hint: "The Progressive Web Framework for Vue.js", + }, { value: "tanstack-start", label: "TanStack Start (beta)", diff --git a/apps/cli/src/types.ts b/apps/cli/src/types.ts index 71fbea2..4efe104 100644 --- a/apps/cli/src/types.ts +++ b/apps/cli/src/types.ts @@ -22,6 +22,7 @@ export type ProjectFrontend = | "tanstack-router" | "tanstack-start" | "next" + | "nuxt" | "native" | "none"; export type ProjectDBSetup = diff --git a/apps/cli/templates/api/orpc/native/utils/orpc.ts.hbs b/apps/cli/templates/api/orpc/native/utils/orpc.ts.hbs new file mode 100644 index 0000000..756593f --- /dev/null +++ b/apps/cli/templates/api/orpc/native/utils/orpc.ts.hbs @@ -0,0 +1,49 @@ +import { createORPCClient } from "@orpc/client"; +import { RPCLink } from "@orpc/client/fetch"; +import { createORPCReactQueryUtils } from "@orpc/react-query"; +import type { RouterUtils } from "@orpc/react-query"; +import type { RouterClient } from "@orpc/server"; +import { QueryCache, QueryClient } from "@tanstack/react-query"; +import { createContext, useContext } from "react"; +import type { appRouter } from "../../server/src/routers"; +{{#if auth}} +import { authClient } from "@/lib/auth-client"; +{{/if}} + +type ORPCReactUtils = RouterUtils>; + +export const queryClient = new QueryClient({ + queryCache: new QueryCache({ + onError: (error) => { + console.log(error) + }, + }), +}); + +export const link = new RPCLink({ + url: `${process.env.EXPO_PUBLIC_SERVER_URL}/rpc`, + {{#if auth}} + headers() { + const headers = new Map(); + const cookies = authClient.getCookie(); + if (cookies) { + headers.set("Cookie", cookies); + } + return Object.fromEntries(headers); + }, + {{/if}} +}); + +export const client: RouterClient = createORPCClient(link); + +export const orpc = createORPCReactQueryUtils(client); + +export const ORPCContext = createContext(undefined); + +export function useORPC(): ORPCReactUtils { + const orpc = useContext(ORPCContext); + if (!orpc) { + throw new Error("ORPCContext is not set up properly"); + } + return orpc; +} diff --git a/apps/cli/templates/api/orpc/web/nuxt/app/plugins/orpc.ts.hbs b/apps/cli/templates/api/orpc/web/nuxt/app/plugins/orpc.ts.hbs new file mode 100644 index 0000000..6becb5e --- /dev/null +++ b/apps/cli/templates/api/orpc/web/nuxt/app/plugins/orpc.ts.hbs @@ -0,0 +1,35 @@ +import { defineNuxtPlugin, useRuntimeConfig } from '#app' +import type { RouterClient } from '@orpc/server' +import type { appRouter } from "../../../server/src/routers/index"; +import { createORPCClient } from '@orpc/client' +import { RPCLink } from '@orpc/client/fetch' +import { createORPCVueQueryUtils } from '@orpc/vue-query' + +export default defineNuxtPlugin(() => { + const config = useRuntimeConfig() + const serverUrl = config.public.serverURL + + const rpcUrl = `${serverUrl}/rpc`; + + const rpcLink = new RPCLink({ + url: rpcUrl, + {{#if auth}} + fetch(url, options) { + return fetch(url, { + ...options, + credentials: "include", + }); + }, + {{/if}} + }) + + + const client: RouterClient = createORPCClient(rpcLink) + const orpcUtils = createORPCVueQueryUtils(client) + + return { + provide: { + orpc: orpcUtils + } + } +}) diff --git a/apps/cli/templates/api/orpc/web/base/src/utils/orpc.ts.hbs b/apps/cli/templates/api/orpc/web/react/base/src/utils/orpc.ts.hbs similarity index 100% rename from apps/cli/templates/api/orpc/web/base/src/utils/orpc.ts.hbs rename to apps/cli/templates/api/orpc/web/react/base/src/utils/orpc.ts.hbs diff --git a/apps/cli/templates/auth/native/utils/trpc.ts b/apps/cli/templates/api/trpc/native/utils/trpc.ts.hbs similarity index 94% rename from apps/cli/templates/auth/native/utils/trpc.ts rename to apps/cli/templates/api/trpc/native/utils/trpc.ts.hbs index abfbe3a..f4560fe 100644 --- a/apps/cli/templates/auth/native/utils/trpc.ts +++ b/apps/cli/templates/api/trpc/native/utils/trpc.ts.hbs @@ -1,4 +1,6 @@ +{{#if auth}} import { authClient } from "@/lib/auth-client"; +{{/if}} import { QueryClient } from "@tanstack/react-query"; import { createTRPCClient, httpBatchLink } from "@trpc/client"; import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query"; @@ -10,6 +12,7 @@ const trpcClient = createTRPCClient({ links: [ httpBatchLink({ url: `${process.env.EXPO_PUBLIC_SERVER_URL}/trpc`, + {{#if auth}} headers() { const headers = new Map(); const cookies = authClient.getCookie(); @@ -18,6 +21,7 @@ const trpcClient = createTRPCClient({ } return Object.fromEntries(headers); }, + {{/if}} }), ], }); diff --git a/apps/cli/templates/api/trpc/web/base/src/utils/trpc.ts.hbs b/apps/cli/templates/api/trpc/web/react/base/src/utils/trpc.ts.hbs similarity index 96% rename from apps/cli/templates/api/trpc/web/base/src/utils/trpc.ts.hbs rename to apps/cli/templates/api/trpc/web/react/base/src/utils/trpc.ts.hbs index ba6dafe..3d6cc97 100644 --- a/apps/cli/templates/api/trpc/web/base/src/utils/trpc.ts.hbs +++ b/apps/cli/templates/api/trpc/web/react/base/src/utils/trpc.ts.hbs @@ -3,7 +3,7 @@ import { QueryCache, QueryClient } from '@tanstack/react-query'; import { createTRPCClient, httpBatchLink } from '@trpc/client'; import { createTRPCOptionsProxy } from '@trpc/tanstack-react-query'; -import type { AppRouter } from '../../../server/src/routers'; {{! Adjust path if necessary }} +import type { AppRouter } from '../../../server/src/routers'; import { toast } from 'sonner'; export const queryClient = new QueryClient({ diff --git a/apps/cli/templates/auth/native/app/(drawer)/index.tsx b/apps/cli/templates/auth/native/app/(drawer)/index.tsx.hbs similarity index 89% rename from apps/cli/templates/auth/native/app/(drawer)/index.tsx rename to apps/cli/templates/auth/native/app/(drawer)/index.tsx.hbs index cba09c1..f6954b6 100644 --- a/apps/cli/templates/auth/native/app/(drawer)/index.tsx +++ b/apps/cli/templates/auth/native/app/(drawer)/index.tsx.hbs @@ -5,11 +5,22 @@ import { ScrollView, Text, TouchableOpacity, View } from "react-native"; import { Container } from "@/components/container"; import { SignIn } from "@/components/sign-in"; import { SignUp } from "@/components/sign-up"; +{{#if (eq api "orpc")}} +import { queryClient, orpc } from "@/utils/orpc"; +{{/if}} +{{#if (eq api "trpc")}} import { queryClient, trpc } from "@/utils/trpc"; +{{/if}} export default function Home() { + {{#if (eq api "orpc")}} + const healthCheck = useQuery(orpc.healthCheck.queryOptions()); + const privateData = useQuery(orpc.privateData.queryOptions()); + {{/if}} + {{#if (eq api "trpc")}} const healthCheck = useQuery(trpc.healthCheck.queryOptions()); const privateData = useQuery(trpc.privateData.queryOptions()); + {{/if}} const { data: session } = authClient.useSession(); return ( diff --git a/apps/cli/templates/auth/native/components/sign-in.tsx b/apps/cli/templates/auth/native/components/sign-in.tsx.hbs similarity index 95% rename from apps/cli/templates/auth/native/components/sign-in.tsx rename to apps/cli/templates/auth/native/components/sign-in.tsx.hbs index d5e6369..244627b 100644 --- a/apps/cli/templates/auth/native/components/sign-in.tsx +++ b/apps/cli/templates/auth/native/components/sign-in.tsx.hbs @@ -1,5 +1,10 @@ import { authClient } from "@/lib/auth-client"; +{{#if (eq api "trpc")}} import { queryClient } from "@/utils/trpc"; +{{/if}} +{{#if (eq api "orpc")}} +import { queryClient } from "@/utils/orpc"; +{{/if}} import { useState } from "react"; import { ActivityIndicator, @@ -85,4 +90,4 @@ export function SignIn() { ); -} +} \ No newline at end of file diff --git a/apps/cli/templates/auth/native/components/sign-up.tsx b/apps/cli/templates/auth/native/components/sign-up.tsx.hbs similarity index 95% rename from apps/cli/templates/auth/native/components/sign-up.tsx rename to apps/cli/templates/auth/native/components/sign-up.tsx.hbs index 7c1d315..bccd9c7 100644 --- a/apps/cli/templates/auth/native/components/sign-up.tsx +++ b/apps/cli/templates/auth/native/components/sign-up.tsx.hbs @@ -1,5 +1,10 @@ import { authClient } from "@/lib/auth-client"; +{{#if (eq api "trpc")}} import { queryClient } from "@/utils/trpc"; +{{/if}} +{{#if (eq api "orpc")}} +import { queryClient } from "@/utils/orpc"; +{{/if}} import { useState } from "react"; import { ActivityIndicator, diff --git a/apps/cli/templates/auth/server/base/src/lib/auth.ts.hbs b/apps/cli/templates/auth/server/base/src/lib/auth.ts.hbs index 489228a..61578c6 100644 --- a/apps/cli/templates/auth/server/base/src/lib/auth.ts.hbs +++ b/apps/cli/templates/auth/server/base/src/lib/auth.ts.hbs @@ -1,6 +1,9 @@ {{#if (eq orm "prisma")}} import { betterAuth } from "better-auth"; import { prismaAdapter } from "better-auth/adapters/prisma"; +{{#if (includes frontend "native")}} +import { expo } from "@better-auth/expo"; +{{/if}} import prisma from "../../prisma"; export const auth = betterAuth({ @@ -9,14 +12,27 @@ export const auth = betterAuth({ {{#if (eq database "sqlite")}}provider: "sqlite"{{/if}} {{#if (eq database "mysql")}}provider: "mysql"{{/if}} }), - trustedOrigins: [process.env.CORS_ORIGIN || ""], - emailAndPassword: { enabled: true } + trustedOrigins: [ + process.env.CORS_ORIGIN || "",{{#if (includes frontend "native")}} + "my-better-t-app://",{{/if}} + ], + emailAndPassword: { + enabled: true, + } + + {{~#if (includes frontend "native")}} + , + plugins: [expo()] + {{/if~}} }); {{/if}} {{#if (eq orm "drizzle")}} import { betterAuth } from "better-auth"; import { drizzleAdapter } from "better-auth/adapters/drizzle"; +{{#if (includes frontend "native")}} +import { expo } from "@better-auth/expo"; +{{/if}} import { db } from "../db"; import * as schema from "../db/schema/auth"; @@ -25,19 +41,42 @@ export const auth = betterAuth({ {{#if (eq database "postgres")}}provider: "pg",{{/if}} {{#if (eq database "sqlite")}}provider: "sqlite",{{/if}} {{#if (eq database "mysql")}}provider: "mysql",{{/if}} - schema: schema + schema: schema, }), - trustedOrigins: [process.env.CORS_ORIGIN || ""], - emailAndPassword: { enabled: true } + trustedOrigins: [ + process.env.CORS_ORIGIN || "",{{#if (includes frontend "native")}} + "my-better-t-app://",{{/if}} + ], + emailAndPassword: { + enabled: true, + } + + {{~#if (includes frontend "native")}} + , + plugins: [expo()] + {{/if~}} }); {{/if}} {{#if (eq orm "none")}} import { betterAuth } from "better-auth"; +{{#if (includes frontend "native")}} +import { expo } from "@better-auth/expo"; +{{/if}} export const auth = betterAuth({ - database: "", - trustedOrigins: [process.env.CORS_ORIGIN || ""], - emailAndPassword: { enabled: true } + database: "", // Invalid configuration + trustedOrigins: [ + process.env.CORS_ORIGIN || "",{{#if (includes frontend "native")}} + "my-better-t-app://", // Use hardcoded scheme{{/if}} + ], + emailAndPassword: { + enabled: true, + } + + {{~#if (includes frontend "native")}} + , + plugins: [expo()] + {{/if~}} }); -{{/if}} +{{/if}} \ No newline at end of file diff --git a/apps/cli/templates/auth/web/nuxt/app/components/SignInForm.vue b/apps/cli/templates/auth/web/nuxt/app/components/SignInForm.vue new file mode 100644 index 0000000..ff44ba7 --- /dev/null +++ b/apps/cli/templates/auth/web/nuxt/app/components/SignInForm.vue @@ -0,0 +1,78 @@ + + + diff --git a/apps/cli/templates/auth/web/nuxt/app/components/SignUpForm.vue b/apps/cli/templates/auth/web/nuxt/app/components/SignUpForm.vue new file mode 100644 index 0000000..eea0c6c --- /dev/null +++ b/apps/cli/templates/auth/web/nuxt/app/components/SignUpForm.vue @@ -0,0 +1,85 @@ + + + diff --git a/apps/cli/templates/auth/web/nuxt/app/components/UserMenu.vue b/apps/cli/templates/auth/web/nuxt/app/components/UserMenu.vue new file mode 100644 index 0000000..a69531a --- /dev/null +++ b/apps/cli/templates/auth/web/nuxt/app/components/UserMenu.vue @@ -0,0 +1,43 @@ + + + diff --git a/apps/cli/templates/auth/web/nuxt/app/middleware/auth.ts b/apps/cli/templates/auth/web/nuxt/app/middleware/auth.ts new file mode 100644 index 0000000..c2073f1 --- /dev/null +++ b/apps/cli/templates/auth/web/nuxt/app/middleware/auth.ts @@ -0,0 +1,12 @@ +export default defineNuxtRouteMiddleware(async (to, from) => { + if (import.meta.server) return + + const { $authClient } = useNuxtApp() + const session = $authClient.useSession() + + if (session.value.isPending || !session.value) { + if (to.path === "/dashboard") { + return navigateTo("/login"); + } + } +}); diff --git a/apps/cli/templates/auth/web/nuxt/app/pages/dashboard.vue b/apps/cli/templates/auth/web/nuxt/app/pages/dashboard.vue new file mode 100644 index 0000000..16aba27 --- /dev/null +++ b/apps/cli/templates/auth/web/nuxt/app/pages/dashboard.vue @@ -0,0 +1,27 @@ + + + diff --git a/apps/cli/templates/auth/web/nuxt/app/pages/login.vue b/apps/cli/templates/auth/web/nuxt/app/pages/login.vue new file mode 100644 index 0000000..61a63cb --- /dev/null +++ b/apps/cli/templates/auth/web/nuxt/app/pages/login.vue @@ -0,0 +1,24 @@ + + + diff --git a/apps/cli/templates/auth/web/nuxt/app/plugins/auth-client.ts b/apps/cli/templates/auth/web/nuxt/app/plugins/auth-client.ts new file mode 100644 index 0000000..38bf8db --- /dev/null +++ b/apps/cli/templates/auth/web/nuxt/app/plugins/auth-client.ts @@ -0,0 +1,16 @@ +import { createAuthClient } from "better-auth/vue"; + +export default defineNuxtPlugin(nuxtApp => { + const config = useRuntimeConfig() + const serverUrl = config.public.serverURL + + const authClient = createAuthClient({ + baseURL: serverUrl + }) + + return { + provide: { + authClient: authClient + } + } +}) diff --git a/apps/cli/templates/auth/web/base/src/lib/auth-client.ts.hbs b/apps/cli/templates/auth/web/react/base/src/lib/auth-client.ts.hbs similarity index 100% rename from apps/cli/templates/auth/web/base/src/lib/auth-client.ts.hbs rename to apps/cli/templates/auth/web/react/base/src/lib/auth-client.ts.hbs diff --git a/apps/cli/templates/auth/web/next/src/app/dashboard/page.tsx.hbs b/apps/cli/templates/auth/web/react/next/src/app/dashboard/page.tsx.hbs similarity index 100% rename from apps/cli/templates/auth/web/next/src/app/dashboard/page.tsx.hbs rename to apps/cli/templates/auth/web/react/next/src/app/dashboard/page.tsx.hbs diff --git a/apps/cli/templates/auth/web/next/src/app/login/page.tsx b/apps/cli/templates/auth/web/react/next/src/app/login/page.tsx similarity index 100% rename from apps/cli/templates/auth/web/next/src/app/login/page.tsx rename to apps/cli/templates/auth/web/react/next/src/app/login/page.tsx diff --git a/apps/cli/templates/auth/web/next/src/components/sign-in-form.tsx b/apps/cli/templates/auth/web/react/next/src/components/sign-in-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/next/src/components/sign-in-form.tsx rename to apps/cli/templates/auth/web/react/next/src/components/sign-in-form.tsx diff --git a/apps/cli/templates/auth/web/next/src/components/sign-up-form.tsx b/apps/cli/templates/auth/web/react/next/src/components/sign-up-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/next/src/components/sign-up-form.tsx rename to apps/cli/templates/auth/web/react/next/src/components/sign-up-form.tsx diff --git a/apps/cli/templates/auth/web/next/src/components/theme-provider.tsx b/apps/cli/templates/auth/web/react/next/src/components/theme-provider.tsx similarity index 100% rename from apps/cli/templates/auth/web/next/src/components/theme-provider.tsx rename to apps/cli/templates/auth/web/react/next/src/components/theme-provider.tsx diff --git a/apps/cli/templates/auth/web/next/src/components/user-menu.tsx b/apps/cli/templates/auth/web/react/next/src/components/user-menu.tsx similarity index 100% rename from apps/cli/templates/auth/web/next/src/components/user-menu.tsx rename to apps/cli/templates/auth/web/react/next/src/components/user-menu.tsx diff --git a/apps/cli/templates/auth/web/react-router/src/components/sign-in-form.tsx b/apps/cli/templates/auth/web/react/react-router/src/components/sign-in-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/react-router/src/components/sign-in-form.tsx rename to apps/cli/templates/auth/web/react/react-router/src/components/sign-in-form.tsx diff --git a/apps/cli/templates/auth/web/react-router/src/components/sign-up-form.tsx b/apps/cli/templates/auth/web/react/react-router/src/components/sign-up-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/react-router/src/components/sign-up-form.tsx rename to apps/cli/templates/auth/web/react/react-router/src/components/sign-up-form.tsx diff --git a/apps/cli/templates/auth/web/react-router/src/components/user-menu.tsx b/apps/cli/templates/auth/web/react/react-router/src/components/user-menu.tsx similarity index 100% rename from apps/cli/templates/auth/web/react-router/src/components/user-menu.tsx rename to apps/cli/templates/auth/web/react/react-router/src/components/user-menu.tsx diff --git a/apps/cli/templates/auth/web/react-router/src/routes/dashboard.tsx.hbs b/apps/cli/templates/auth/web/react/react-router/src/routes/dashboard.tsx.hbs similarity index 100% rename from apps/cli/templates/auth/web/react-router/src/routes/dashboard.tsx.hbs rename to apps/cli/templates/auth/web/react/react-router/src/routes/dashboard.tsx.hbs diff --git a/apps/cli/templates/auth/web/react-router/src/routes/login.tsx b/apps/cli/templates/auth/web/react/react-router/src/routes/login.tsx similarity index 100% rename from apps/cli/templates/auth/web/react-router/src/routes/login.tsx rename to apps/cli/templates/auth/web/react/react-router/src/routes/login.tsx diff --git a/apps/cli/templates/auth/web/tanstack-router/src/components/sign-in-form.tsx b/apps/cli/templates/auth/web/react/tanstack-router/src/components/sign-in-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-router/src/components/sign-in-form.tsx rename to apps/cli/templates/auth/web/react/tanstack-router/src/components/sign-in-form.tsx diff --git a/apps/cli/templates/auth/web/tanstack-router/src/components/sign-up-form.tsx b/apps/cli/templates/auth/web/react/tanstack-router/src/components/sign-up-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-router/src/components/sign-up-form.tsx rename to apps/cli/templates/auth/web/react/tanstack-router/src/components/sign-up-form.tsx diff --git a/apps/cli/templates/auth/web/tanstack-router/src/components/user-menu.tsx b/apps/cli/templates/auth/web/react/tanstack-router/src/components/user-menu.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-router/src/components/user-menu.tsx rename to apps/cli/templates/auth/web/react/tanstack-router/src/components/user-menu.tsx diff --git a/apps/cli/templates/auth/web/tanstack-router/src/routes/dashboard.tsx.hbs b/apps/cli/templates/auth/web/react/tanstack-router/src/routes/dashboard.tsx.hbs similarity index 100% rename from apps/cli/templates/auth/web/tanstack-router/src/routes/dashboard.tsx.hbs rename to apps/cli/templates/auth/web/react/tanstack-router/src/routes/dashboard.tsx.hbs diff --git a/apps/cli/templates/auth/web/tanstack-router/src/routes/login.tsx b/apps/cli/templates/auth/web/react/tanstack-router/src/routes/login.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-router/src/routes/login.tsx rename to apps/cli/templates/auth/web/react/tanstack-router/src/routes/login.tsx diff --git a/apps/cli/templates/auth/web/tanstack-start/src/components/sign-in-form.tsx b/apps/cli/templates/auth/web/react/tanstack-start/src/components/sign-in-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-start/src/components/sign-in-form.tsx rename to apps/cli/templates/auth/web/react/tanstack-start/src/components/sign-in-form.tsx diff --git a/apps/cli/templates/auth/web/tanstack-start/src/components/sign-up-form.tsx b/apps/cli/templates/auth/web/react/tanstack-start/src/components/sign-up-form.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-start/src/components/sign-up-form.tsx rename to apps/cli/templates/auth/web/react/tanstack-start/src/components/sign-up-form.tsx diff --git a/apps/cli/templates/auth/web/tanstack-start/src/components/user-menu.tsx b/apps/cli/templates/auth/web/react/tanstack-start/src/components/user-menu.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-start/src/components/user-menu.tsx rename to apps/cli/templates/auth/web/react/tanstack-start/src/components/user-menu.tsx diff --git a/apps/cli/templates/auth/web/tanstack-start/src/routes/dashboard.tsx.hbs b/apps/cli/templates/auth/web/react/tanstack-start/src/routes/dashboard.tsx.hbs similarity index 100% rename from apps/cli/templates/auth/web/tanstack-start/src/routes/dashboard.tsx.hbs rename to apps/cli/templates/auth/web/react/tanstack-start/src/routes/dashboard.tsx.hbs diff --git a/apps/cli/templates/auth/web/tanstack-start/src/routes/login.tsx b/apps/cli/templates/auth/web/react/tanstack-start/src/routes/login.tsx similarity index 100% rename from apps/cli/templates/auth/web/tanstack-start/src/routes/login.tsx rename to apps/cli/templates/auth/web/react/tanstack-start/src/routes/login.tsx diff --git a/apps/cli/templates/examples/ai/web/nuxt/app/pages/ai.vue b/apps/cli/templates/examples/ai/web/nuxt/app/pages/ai.vue new file mode 100644 index 0000000..51f8edf --- /dev/null +++ b/apps/cli/templates/examples/ai/web/nuxt/app/pages/ai.vue @@ -0,0 +1,64 @@ + + + diff --git a/apps/cli/templates/examples/ai/web/react-router/src/routes/ai.tsx b/apps/cli/templates/examples/ai/web/react/react-router/src/routes/ai.tsx similarity index 100% rename from apps/cli/templates/examples/ai/web/react-router/src/routes/ai.tsx rename to apps/cli/templates/examples/ai/web/react/react-router/src/routes/ai.tsx diff --git a/apps/cli/templates/examples/ai/web/tanstack-router/src/routes/ai.tsx b/apps/cli/templates/examples/ai/web/react/tanstack-router/src/routes/ai.tsx similarity index 100% rename from apps/cli/templates/examples/ai/web/tanstack-router/src/routes/ai.tsx rename to apps/cli/templates/examples/ai/web/react/tanstack-router/src/routes/ai.tsx diff --git a/apps/cli/templates/examples/ai/web/tanstack-start/src/routes/ai.tsx b/apps/cli/templates/examples/ai/web/react/tanstack-start/src/routes/ai.tsx similarity index 100% rename from apps/cli/templates/examples/ai/web/tanstack-start/src/routes/ai.tsx rename to apps/cli/templates/examples/ai/web/react/tanstack-start/src/routes/ai.tsx diff --git a/apps/cli/templates/examples/todo/web/nuxt/app/pages/todos.vue b/apps/cli/templates/examples/todo/web/nuxt/app/pages/todos.vue new file mode 100644 index 0000000..5e3e26c --- /dev/null +++ b/apps/cli/templates/examples/todo/web/nuxt/app/pages/todos.vue @@ -0,0 +1,108 @@ + + + diff --git a/apps/cli/templates/examples/todo/web/react-router/src/routes/todos.tsx.hbs b/apps/cli/templates/examples/todo/web/react/react-router/src/routes/todos.tsx.hbs similarity index 100% rename from apps/cli/templates/examples/todo/web/react-router/src/routes/todos.tsx.hbs rename to apps/cli/templates/examples/todo/web/react/react-router/src/routes/todos.tsx.hbs diff --git a/apps/cli/templates/examples/todo/web/tanstack-router/src/routes/todos.tsx.hbs b/apps/cli/templates/examples/todo/web/react/tanstack-router/src/routes/todos.tsx.hbs similarity index 100% rename from apps/cli/templates/examples/todo/web/tanstack-router/src/routes/todos.tsx.hbs rename to apps/cli/templates/examples/todo/web/react/tanstack-router/src/routes/todos.tsx.hbs diff --git a/apps/cli/templates/examples/todo/web/tanstack-start/src/routes/todos.tsx.hbs b/apps/cli/templates/examples/todo/web/react/tanstack-start/src/routes/todos.tsx.hbs similarity index 100% rename from apps/cli/templates/examples/todo/web/tanstack-start/src/routes/todos.tsx.hbs rename to apps/cli/templates/examples/todo/web/react/tanstack-start/src/routes/todos.tsx.hbs diff --git a/apps/cli/templates/extras/_npmrc b/apps/cli/templates/extras/_npmrc deleted file mode 100644 index d67f374..0000000 --- a/apps/cli/templates/extras/_npmrc +++ /dev/null @@ -1 +0,0 @@ -node-linker=hoisted diff --git a/apps/cli/templates/extras/_npmrc.hbs b/apps/cli/templates/extras/_npmrc.hbs new file mode 100644 index 0000000..a26d6fd --- /dev/null +++ b/apps/cli/templates/extras/_npmrc.hbs @@ -0,0 +1,5 @@ +node-linker=hoisted +{{#if (includes frontend "nuxt")}} +shamefully-hoist=true +strict-peer-dependencies=false +{{/if}} diff --git a/apps/cli/templates/frontend/native/app/(drawer)/index.tsx b/apps/cli/templates/frontend/native/app/(drawer)/index.tsx.hbs similarity index 83% rename from apps/cli/templates/frontend/native/app/(drawer)/index.tsx rename to apps/cli/templates/frontend/native/app/(drawer)/index.tsx.hbs index ee6c5d4..8458edf 100644 --- a/apps/cli/templates/frontend/native/app/(drawer)/index.tsx +++ b/apps/cli/templates/frontend/native/app/(drawer)/index.tsx.hbs @@ -1,10 +1,20 @@ import { useQuery } from "@tanstack/react-query"; import { View, Text, ScrollView } from "react-native"; import { Container } from "@/components/container"; +{{#if (eq api "orpc")}} +import { orpc } from "@/utils/orpc"; +{{/if}} +{{#if (eq api "trpc")}} import { trpc } from "@/utils/trpc"; +{{/if}} export default function Home() { + {{#if (eq api "orpc")}} + const healthCheck = useQuery(orpc.healthCheck.queryOptions()); + {{/if}} + {{#if (eq api "trpc")}} const healthCheck = useQuery(trpc.healthCheck.queryOptions()); + {{/if}} return ( diff --git a/apps/cli/templates/frontend/native/app/_layout.tsx b/apps/cli/templates/frontend/native/app/_layout.tsx.hbs similarity index 87% rename from apps/cli/templates/frontend/native/app/_layout.tsx rename to apps/cli/templates/frontend/native/app/_layout.tsx.hbs index d8a17b0..71206c9 100644 --- a/apps/cli/templates/frontend/native/app/_layout.tsx +++ b/apps/cli/templates/frontend/native/app/_layout.tsx.hbs @@ -9,7 +9,12 @@ import { import { StatusBar } from "expo-status-bar"; import { GestureHandlerRootView } from "react-native-gesture-handler"; import "../global.css"; +{{#if (eq api "trpc")}} import { queryClient } from "@/utils/trpc"; +{{/if}} +{{#if (eq api "orpc")}} +import { queryClient } from "@/utils/orpc"; +{{/if}} import { NAV_THEME } from "@/lib/constants"; import React, { useRef } from "react"; import { useColorScheme } from "@/lib/use-color-scheme"; @@ -56,12 +61,12 @@ export default function RootLayout() { - + - + diff --git a/apps/cli/templates/frontend/native/package.json b/apps/cli/templates/frontend/native/package.json index a511656..d6edcbf 100644 --- a/apps/cli/templates/frontend/native/package.json +++ b/apps/cli/templates/frontend/native/package.json @@ -16,9 +16,6 @@ "@react-navigation/native": "^7.0.14", "@tanstack/react-form": "^1.0.5", "@tanstack/react-query": "^5.69.2", - "@trpc/client": "^11.0.0", - "@trpc/server": "^11.0.0", - "@trpc/tanstack-react-query": "^11.0.0", "expo": "^52.0.44", "expo-constants": "~17.0.8", "expo-linking": "~7.0.5", diff --git a/apps/cli/templates/frontend/native/utils/trpc.ts b/apps/cli/templates/frontend/native/utils/trpc.ts deleted file mode 100644 index adc6da3..0000000 --- a/apps/cli/templates/frontend/native/utils/trpc.ts +++ /dev/null @@ -1,19 +0,0 @@ -import type { AppRouter } from "../../server/src/routers"; -import { QueryClient } from "@tanstack/react-query"; -import { createTRPCClient, httpBatchLink } from "@trpc/client"; -import { createTRPCOptionsProxy } from "@trpc/tanstack-react-query"; - -export const queryClient = new QueryClient(); - -const trpcClient = createTRPCClient({ - links: [ - httpBatchLink({ - url: `${process.env.EXPO_PUBLIC_SERVER_URL}/trpc`, - }), - ], -}); - -export const trpc = createTRPCOptionsProxy({ - client: trpcClient, - queryClient, -}); diff --git a/apps/cli/templates/frontend/nuxt/_gitignore b/apps/cli/templates/frontend/nuxt/_gitignore new file mode 100644 index 0000000..4a7f73a --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/_gitignore @@ -0,0 +1,24 @@ +# Nuxt dev/build outputs +.output +.data +.nuxt +.nitro +.cache +dist + +# Node dependencies +node_modules + +# Logs +logs +*.log + +# Misc +.DS_Store +.fleet +.idea + +# Local env files +.env +.env.* +!.env.example diff --git a/apps/cli/templates/frontend/nuxt/app/app.config.ts b/apps/cli/templates/frontend/nuxt/app/app.config.ts new file mode 100644 index 0000000..52071b3 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/app.config.ts @@ -0,0 +1,15 @@ +export default defineAppConfig({ + // https://ui.nuxt.com/getting-started/theme#design-system + ui: { + colors: { + primary: 'emerald', + neutral: 'slate', + }, + button: { + defaultVariants: { + // Set default button color to neutral + // color: 'neutral' + } + } + } +}) diff --git a/apps/cli/templates/frontend/nuxt/app/app.vue b/apps/cli/templates/frontend/nuxt/app/app.vue new file mode 100644 index 0000000..e8b9138 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/app.vue @@ -0,0 +1,13 @@ + + + diff --git a/apps/cli/templates/frontend/nuxt/app/assets/css/main.css b/apps/cli/templates/frontend/nuxt/app/assets/css/main.css new file mode 100644 index 0000000..7c95c6f --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/assets/css/main.css @@ -0,0 +1,2 @@ +@import "tailwindcss"; +@import "@nuxt/ui"; diff --git a/apps/cli/templates/frontend/nuxt/app/components/Header.vue.hbs b/apps/cli/templates/frontend/nuxt/app/components/Header.vue.hbs new file mode 100644 index 0000000..2a554f3 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/components/Header.vue.hbs @@ -0,0 +1,45 @@ + + + diff --git a/apps/cli/templates/frontend/nuxt/app/components/Loader.vue b/apps/cli/templates/frontend/nuxt/app/components/Loader.vue new file mode 100644 index 0000000..eca3990 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/components/Loader.vue @@ -0,0 +1,5 @@ + diff --git a/apps/cli/templates/frontend/nuxt/app/components/ModeToggle.vue b/apps/cli/templates/frontend/nuxt/app/components/ModeToggle.vue new file mode 100644 index 0000000..fde2172 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/components/ModeToggle.vue @@ -0,0 +1,23 @@ + + + diff --git a/apps/cli/templates/frontend/nuxt/app/layouts/default.vue b/apps/cli/templates/frontend/nuxt/app/layouts/default.vue new file mode 100644 index 0000000..1ad9992 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/layouts/default.vue @@ -0,0 +1,11 @@ + + + diff --git a/apps/cli/templates/frontend/nuxt/app/pages/index.vue b/apps/cli/templates/frontend/nuxt/app/pages/index.vue new file mode 100644 index 0000000..6ca298b --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/pages/index.vue @@ -0,0 +1,63 @@ + + + diff --git a/apps/cli/templates/frontend/nuxt/app/plugins/vue-query.ts b/apps/cli/templates/frontend/nuxt/app/plugins/vue-query.ts new file mode 100644 index 0000000..67cf45e --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/app/plugins/vue-query.ts @@ -0,0 +1,44 @@ +import type { + DehydratedState, + VueQueryPluginOptions, +} from '@tanstack/vue-query' +import { + dehydrate, + hydrate, + QueryCache, + QueryClient, + VueQueryPlugin, +} from '@tanstack/vue-query' + +export default defineNuxtPlugin((nuxt) => { + const vueQueryState = useState('vue-query') + + const toast = useToast() + + const queryClient = new QueryClient({ + queryCache: new QueryCache({ + onError: (error) => { + console.log(error) + toast.add({ + title: 'Error', + description: error?.message || 'An unexpected error occurred.', + }) + }, + }), + }) + const options: VueQueryPluginOptions = { queryClient } + + nuxt.vueApp.use(VueQueryPlugin, options) + + if (import.meta.server) { + nuxt.hooks.hook('app:rendered', () => { + vueQueryState.value = dehydrate(queryClient) + }) + } + + if (import.meta.client) { + nuxt.hooks.hook('app:created', () => { + hydrate(queryClient, vueQueryState.value) + }) + } +}) diff --git a/apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs b/apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs new file mode 100644 index 0000000..e2c1532 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/nuxt.config.ts.hbs @@ -0,0 +1,19 @@ +// https://nuxt.com/docs/api/configuration/nuxt-config +export default defineNuxtConfig({ + compatibilityDate: '2024-11-01', + future: { + compatibilityVersion: 4 + }, + devtools: { enabled: true }, + modules: ['@nuxt/ui'], + css: ['~/assets/css/main.css'], + devServer: { + port: 3001 + }, + ssr: false, + runtimeConfig: { + public: { + serverURL: process.env.NUXT_PUBLIC_SERVER_URL, + } + } +}) diff --git a/apps/cli/templates/frontend/nuxt/package.json b/apps/cli/templates/frontend/nuxt/package.json new file mode 100644 index 0000000..045efd1 --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/package.json @@ -0,0 +1,25 @@ +{ + "name": "web", + "private": true, + "type": "module", + "scripts": { + "build": "nuxt build", + "dev": "nuxt dev", + "generate": "nuxt generate", + "preview": "nuxt preview", + "postinstall": "nuxt prepare" + }, + "dependencies": { + "@nuxt/ui": "3.0.2", + "@tanstack/vue-query": "^5.74.5", + "nuxt": "^3.16.2", + "typescript": "^5.6.3", + "vue": "^3.5.13", + "vue-router": "^4.5.0", + "zod": "^3.24.3" + }, + "devDependencies": { + "@tanstack/vue-query-devtools": "^5.74.5", + "@iconify-json/lucide": "^1.2.38" + } +} diff --git a/apps/cli/templates/frontend/nuxt/public/favicon.ico b/apps/cli/templates/frontend/nuxt/public/favicon.ico new file mode 100644 index 0000000..18993ad Binary files /dev/null and b/apps/cli/templates/frontend/nuxt/public/favicon.ico differ diff --git a/apps/cli/templates/frontend/nuxt/public/robots.txt b/apps/cli/templates/frontend/nuxt/public/robots.txt new file mode 100644 index 0000000..0ad279c --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/public/robots.txt @@ -0,0 +1,2 @@ +User-Agent: * +Disallow: diff --git a/apps/cli/templates/frontend/nuxt/server/tsconfig.json b/apps/cli/templates/frontend/nuxt/server/tsconfig.json new file mode 100644 index 0000000..b9ed69c --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/server/tsconfig.json @@ -0,0 +1,3 @@ +{ + "extends": "../.nuxt/tsconfig.server.json" +} diff --git a/apps/cli/templates/frontend/nuxt/tsconfig.json b/apps/cli/templates/frontend/nuxt/tsconfig.json new file mode 100644 index 0000000..a746f2a --- /dev/null +++ b/apps/cli/templates/frontend/nuxt/tsconfig.json @@ -0,0 +1,4 @@ +{ + // https://nuxt.com/docs/guide/concepts/typescript + "extends": "./.nuxt/tsconfig.json" +} diff --git a/apps/cli/templates/frontend/next/next-env.d.ts b/apps/cli/templates/frontend/react/next/next-env.d.ts similarity index 100% rename from apps/cli/templates/frontend/next/next-env.d.ts rename to apps/cli/templates/frontend/react/next/next-env.d.ts diff --git a/apps/cli/templates/frontend/next/next.config.ts b/apps/cli/templates/frontend/react/next/next.config.ts similarity index 100% rename from apps/cli/templates/frontend/next/next.config.ts rename to apps/cli/templates/frontend/react/next/next.config.ts diff --git a/apps/cli/templates/frontend/next/package.json b/apps/cli/templates/frontend/react/next/package.json similarity index 100% rename from apps/cli/templates/frontend/next/package.json rename to apps/cli/templates/frontend/react/next/package.json diff --git a/apps/cli/templates/frontend/next/postcss.config.mjs b/apps/cli/templates/frontend/react/next/postcss.config.mjs similarity index 100% rename from apps/cli/templates/frontend/next/postcss.config.mjs rename to apps/cli/templates/frontend/react/next/postcss.config.mjs diff --git a/apps/cli/templates/frontend/next/src/app/favicon.ico b/apps/cli/templates/frontend/react/next/src/app/favicon.ico similarity index 100% rename from apps/cli/templates/frontend/next/src/app/favicon.ico rename to apps/cli/templates/frontend/react/next/src/app/favicon.ico diff --git a/apps/cli/templates/frontend/next/src/app/layout.tsx b/apps/cli/templates/frontend/react/next/src/app/layout.tsx similarity index 100% rename from apps/cli/templates/frontend/next/src/app/layout.tsx rename to apps/cli/templates/frontend/react/next/src/app/layout.tsx diff --git a/apps/cli/templates/frontend/next/src/app/page.tsx.hbs b/apps/cli/templates/frontend/react/next/src/app/page.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/next/src/app/page.tsx.hbs rename to apps/cli/templates/frontend/react/next/src/app/page.tsx.hbs diff --git a/apps/cli/templates/frontend/next/src/components/mode-toggle.tsx b/apps/cli/templates/frontend/react/next/src/components/mode-toggle.tsx similarity index 100% rename from apps/cli/templates/frontend/next/src/components/mode-toggle.tsx rename to apps/cli/templates/frontend/react/next/src/components/mode-toggle.tsx diff --git a/apps/cli/templates/frontend/next/src/components/providers.tsx.hbs b/apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/next/src/components/providers.tsx.hbs rename to apps/cli/templates/frontend/react/next/src/components/providers.tsx.hbs diff --git a/apps/cli/templates/frontend/next/src/components/theme-provider.tsx b/apps/cli/templates/frontend/react/next/src/components/theme-provider.tsx similarity index 100% rename from apps/cli/templates/frontend/next/src/components/theme-provider.tsx rename to apps/cli/templates/frontend/react/next/src/components/theme-provider.tsx diff --git a/apps/cli/templates/frontend/next/tsconfig.json b/apps/cli/templates/frontend/react/next/tsconfig.json similarity index 100% rename from apps/cli/templates/frontend/next/tsconfig.json rename to apps/cli/templates/frontend/react/next/tsconfig.json diff --git a/apps/cli/templates/frontend/react-router/package.json b/apps/cli/templates/frontend/react/react-router/package.json similarity index 100% rename from apps/cli/templates/frontend/react-router/package.json rename to apps/cli/templates/frontend/react/react-router/package.json diff --git a/apps/cli/templates/frontend/react-router/public/favicon.ico b/apps/cli/templates/frontend/react/react-router/public/favicon.ico similarity index 100% rename from apps/cli/templates/frontend/react-router/public/favicon.ico rename to apps/cli/templates/frontend/react/react-router/public/favicon.ico diff --git a/apps/cli/templates/frontend/react-router/react-router.config.ts b/apps/cli/templates/frontend/react/react-router/react-router.config.ts similarity index 100% rename from apps/cli/templates/frontend/react-router/react-router.config.ts rename to apps/cli/templates/frontend/react/react-router/react-router.config.ts diff --git a/apps/cli/templates/frontend/react-router/src/components/mode-toggle.tsx b/apps/cli/templates/frontend/react/react-router/src/components/mode-toggle.tsx similarity index 100% rename from apps/cli/templates/frontend/react-router/src/components/mode-toggle.tsx rename to apps/cli/templates/frontend/react/react-router/src/components/mode-toggle.tsx diff --git a/apps/cli/templates/frontend/react-router/src/components/theme-provider.tsx b/apps/cli/templates/frontend/react/react-router/src/components/theme-provider.tsx similarity index 100% rename from apps/cli/templates/frontend/react-router/src/components/theme-provider.tsx rename to apps/cli/templates/frontend/react/react-router/src/components/theme-provider.tsx diff --git a/apps/cli/templates/frontend/react-router/src/root.tsx.hbs b/apps/cli/templates/frontend/react/react-router/src/root.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/react-router/src/root.tsx.hbs rename to apps/cli/templates/frontend/react/react-router/src/root.tsx.hbs diff --git a/apps/cli/templates/frontend/react-router/src/routes.ts b/apps/cli/templates/frontend/react/react-router/src/routes.ts similarity index 100% rename from apps/cli/templates/frontend/react-router/src/routes.ts rename to apps/cli/templates/frontend/react/react-router/src/routes.ts diff --git a/apps/cli/templates/frontend/react-router/src/routes/_index.tsx.hbs b/apps/cli/templates/frontend/react/react-router/src/routes/_index.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/react-router/src/routes/_index.tsx.hbs rename to apps/cli/templates/frontend/react/react-router/src/routes/_index.tsx.hbs diff --git a/apps/cli/templates/frontend/react-router/tsconfig.json b/apps/cli/templates/frontend/react/react-router/tsconfig.json similarity index 100% rename from apps/cli/templates/frontend/react-router/tsconfig.json rename to apps/cli/templates/frontend/react/react-router/tsconfig.json diff --git a/apps/cli/templates/frontend/react-router/vite.config.ts.hbs b/apps/cli/templates/frontend/react/react-router/vite.config.ts.hbs similarity index 100% rename from apps/cli/templates/frontend/react-router/vite.config.ts.hbs rename to apps/cli/templates/frontend/react/react-router/vite.config.ts.hbs diff --git a/apps/cli/templates/frontend/tanstack-router/index.html b/apps/cli/templates/frontend/react/tanstack-router/index.html similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/index.html rename to apps/cli/templates/frontend/react/tanstack-router/index.html diff --git a/apps/cli/templates/frontend/tanstack-router/package.json b/apps/cli/templates/frontend/react/tanstack-router/package.json similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/package.json rename to apps/cli/templates/frontend/react/tanstack-router/package.json diff --git a/apps/cli/templates/frontend/tanstack-router/src/components/mode-toggle.tsx b/apps/cli/templates/frontend/react/tanstack-router/src/components/mode-toggle.tsx similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/src/components/mode-toggle.tsx rename to apps/cli/templates/frontend/react/tanstack-router/src/components/mode-toggle.tsx diff --git a/apps/cli/templates/frontend/tanstack-router/src/components/theme-provider.tsx b/apps/cli/templates/frontend/react/tanstack-router/src/components/theme-provider.tsx similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/src/components/theme-provider.tsx rename to apps/cli/templates/frontend/react/tanstack-router/src/components/theme-provider.tsx diff --git a/apps/cli/templates/frontend/tanstack-router/src/main.tsx.hbs b/apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/src/main.tsx.hbs rename to apps/cli/templates/frontend/react/tanstack-router/src/main.tsx.hbs diff --git a/apps/cli/templates/frontend/tanstack-router/src/routes/__root.tsx.hbs b/apps/cli/templates/frontend/react/tanstack-router/src/routes/__root.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/src/routes/__root.tsx.hbs rename to apps/cli/templates/frontend/react/tanstack-router/src/routes/__root.tsx.hbs diff --git a/apps/cli/templates/frontend/tanstack-router/src/routes/index.tsx.hbs b/apps/cli/templates/frontend/react/tanstack-router/src/routes/index.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/src/routes/index.tsx.hbs rename to apps/cli/templates/frontend/react/tanstack-router/src/routes/index.tsx.hbs diff --git a/apps/cli/templates/frontend/tanstack-router/tsconfig.json b/apps/cli/templates/frontend/react/tanstack-router/tsconfig.json similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/tsconfig.json rename to apps/cli/templates/frontend/react/tanstack-router/tsconfig.json diff --git a/apps/cli/templates/frontend/tanstack-router/vite.config.ts.hbs b/apps/cli/templates/frontend/react/tanstack-router/vite.config.ts.hbs similarity index 100% rename from apps/cli/templates/frontend/tanstack-router/vite.config.ts.hbs rename to apps/cli/templates/frontend/react/tanstack-router/vite.config.ts.hbs diff --git a/apps/cli/templates/frontend/tanstack-start/app.config.ts b/apps/cli/templates/frontend/react/tanstack-start/app.config.ts similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/app.config.ts rename to apps/cli/templates/frontend/react/tanstack-start/app.config.ts diff --git a/apps/cli/templates/frontend/tanstack-start/package.json b/apps/cli/templates/frontend/react/tanstack-start/package.json similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/package.json rename to apps/cli/templates/frontend/react/tanstack-start/package.json diff --git a/apps/cli/templates/frontend/tanstack-start/public/robots.txt b/apps/cli/templates/frontend/react/tanstack-start/public/robots.txt similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/public/robots.txt rename to apps/cli/templates/frontend/react/tanstack-start/public/robots.txt diff --git a/apps/cli/templates/frontend/tanstack-start/src/api.ts b/apps/cli/templates/frontend/react/tanstack-start/src/api.ts similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/src/api.ts rename to apps/cli/templates/frontend/react/tanstack-start/src/api.ts diff --git a/apps/cli/templates/frontend/tanstack-start/src/client.tsx b/apps/cli/templates/frontend/react/tanstack-start/src/client.tsx similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/src/client.tsx rename to apps/cli/templates/frontend/react/tanstack-start/src/client.tsx diff --git a/apps/cli/templates/frontend/tanstack-start/src/router.tsx.hbs b/apps/cli/templates/frontend/react/tanstack-start/src/router.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/src/router.tsx.hbs rename to apps/cli/templates/frontend/react/tanstack-start/src/router.tsx.hbs diff --git a/apps/cli/templates/frontend/tanstack-start/src/routes/__root.tsx.hbs b/apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/src/routes/__root.tsx.hbs rename to apps/cli/templates/frontend/react/tanstack-start/src/routes/__root.tsx.hbs diff --git a/apps/cli/templates/frontend/tanstack-start/src/routes/index.tsx.hbs b/apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/src/routes/index.tsx.hbs rename to apps/cli/templates/frontend/react/tanstack-start/src/routes/index.tsx.hbs diff --git a/apps/cli/templates/frontend/tanstack-start/src/ssr.tsx b/apps/cli/templates/frontend/react/tanstack-start/src/ssr.tsx similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/src/ssr.tsx rename to apps/cli/templates/frontend/react/tanstack-start/src/ssr.tsx diff --git a/apps/cli/templates/frontend/tanstack-start/tsconfig.json b/apps/cli/templates/frontend/react/tanstack-start/tsconfig.json similarity index 100% rename from apps/cli/templates/frontend/tanstack-start/tsconfig.json rename to apps/cli/templates/frontend/react/tanstack-start/tsconfig.json diff --git a/apps/cli/templates/frontend/web-base/_gitignore b/apps/cli/templates/frontend/react/web-base/_gitignore similarity index 100% rename from apps/cli/templates/frontend/web-base/_gitignore rename to apps/cli/templates/frontend/react/web-base/_gitignore diff --git a/apps/cli/templates/frontend/web-base/components.json b/apps/cli/templates/frontend/react/web-base/components.json similarity index 100% rename from apps/cli/templates/frontend/web-base/components.json rename to apps/cli/templates/frontend/react/web-base/components.json diff --git a/apps/cli/templates/frontend/web-base/src/components/header.tsx.hbs b/apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/header.tsx.hbs rename to apps/cli/templates/frontend/react/web-base/src/components/header.tsx.hbs diff --git a/apps/cli/templates/frontend/web-base/src/components/loader.tsx b/apps/cli/templates/frontend/react/web-base/src/components/loader.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/loader.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/loader.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/button.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/button.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/button.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/button.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/card.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/card.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/card.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/card.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/checkbox.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/checkbox.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/checkbox.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/checkbox.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/dropdown-menu.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/dropdown-menu.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/dropdown-menu.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/dropdown-menu.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/input.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/input.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/input.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/input.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/label.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/label.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/label.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/label.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/skeleton.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/skeleton.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/skeleton.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/skeleton.tsx diff --git a/apps/cli/templates/frontend/web-base/src/components/ui/sonner.tsx b/apps/cli/templates/frontend/react/web-base/src/components/ui/sonner.tsx similarity index 100% rename from apps/cli/templates/frontend/web-base/src/components/ui/sonner.tsx rename to apps/cli/templates/frontend/react/web-base/src/components/ui/sonner.tsx diff --git a/apps/cli/templates/frontend/web-base/src/index.css b/apps/cli/templates/frontend/react/web-base/src/index.css similarity index 100% rename from apps/cli/templates/frontend/web-base/src/index.css rename to apps/cli/templates/frontend/react/web-base/src/index.css diff --git a/apps/cli/templates/frontend/web-base/src/lib/utils.ts b/apps/cli/templates/frontend/react/web-base/src/lib/utils.ts similarity index 100% rename from apps/cli/templates/frontend/web-base/src/lib/utils.ts rename to apps/cli/templates/frontend/react/web-base/src/lib/utils.ts diff --git a/apps/web/package.json b/apps/web/package.json index 164b888..5b4392d 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -13,6 +13,7 @@ "@heroicons/react": "^2.2.0", "@radix-ui/react-scroll-area": "^1.2.5", "@radix-ui/react-switch": "^1.2.2", + "@radix-ui/react-tooltip": "^1.2.4", "@xyflow/react": "^12.5.5", "babel-plugin-react-compiler": "^19.0.0-beta-e993439-20250405", "class-variance-authority": "^0.7.1", diff --git a/apps/web/public/icon/nuxt.svg b/apps/web/public/icon/nuxt.svg new file mode 100644 index 0000000..81b2e6f --- /dev/null +++ b/apps/web/public/icon/nuxt.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/web/src/app/(home)/_components/StackArchitech.tsx b/apps/web/src/app/(home)/_components/StackArchitech.tsx index a171689..14464be 100644 --- a/apps/web/src/app/(home)/_components/StackArchitech.tsx +++ b/apps/web/src/app/(home)/_components/StackArchitech.tsx @@ -2,6 +2,12 @@ import { ThemeToggle } from "@/components/theme-toggle"; import { ScrollArea } from "@/components/ui/scroll-area"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { DEFAULT_STACK, PRESET_TEMPLATES, @@ -78,6 +84,9 @@ const hasWebFrontend = (frontend: string[]) => const hasPWACompatibleFrontend = (frontend: string[]) => frontend.some((f) => ["tanstack-router", "react-router"].includes(f)); +const hasTauriCompatibleFrontend = (frontend: string[]) => + frontend.some((f) => ["tanstack-router", "react-router", "nuxt"].includes(f)); + const hasNativeFrontend = (frontend: string[]) => frontend.includes("native"); const TechIcon = ({ @@ -173,6 +182,10 @@ const StackArchitect = () => { () => hasPWACompatibleFrontend(stack.frontend), [stack.frontend], ); + const currentHasTauriCompatibleFrontend = useMemo( + () => hasTauriCompatibleFrontend(stack.frontend), + [stack.frontend], + ); const currentHasNativeFrontend = useMemo( () => hasNativeFrontend(stack.frontend), [stack.frontend], @@ -201,7 +214,9 @@ const StackArchitect = () => { const isWeb = hasWebFrontend(nextStack.frontend); const isPWACompat = hasPWACompatibleFrontend(nextStack.frontend); + const isTauriCompat = hasTauriCompatibleFrontend(nextStack.frontend); const isNative = hasNativeFrontend(nextStack.frontend); + const isNuxt = nextStack.frontend.includes("nuxt"); if (nextStack.database === "none") { if (nextStack.orm !== "none") { @@ -256,13 +271,14 @@ const StackArchitect = () => { changed = true; } - if (isNative && nextStack.api !== "trpc") { - nextStack.api = "trpc"; + if (isNuxt && nextStack.api === "trpc") { + nextStack.api = "orpc"; changed = true; } const incompatibleAddons: string[] = []; - if (!isPWACompat) incompatibleAddons.push("pwa", "tauri"); + if (!isPWACompat) incompatibleAddons.push("pwa"); + if (!isTauriCompat) incompatibleAddons.push("tauri"); const originalAddonsLength = nextStack.addons.length; nextStack.addons = nextStack.addons.filter( (addon) => !incompatibleAddons.includes(addon), @@ -356,7 +372,9 @@ const StackArchitect = () => { flags.push(`--database ${stackState.database}`); } - if (stackState.database !== "none" && !isDefault("orm", stackState.orm)) { + if (stackState.database === "none") { + flags.push("--orm none"); + } else if (!isDefault("orm", stackState.orm)) { flags.push(`--orm ${stackState.orm}`); } @@ -426,35 +444,35 @@ const StackArchitect = () => { const isWeb = currentHasWebFrontend; const isPWACompat = currentHasPWACompatibleFrontend; + const isTauriCompat = currentHasTauriCompatibleFrontend; const isNative = currentHasNativeFrontend; + const isNuxt = stack.frontend.includes("nuxt"); - if (isNative && stack.frontend.length > 1) { - notes.frontend.notes.push( - "React Native requires the tRPC API when used with other frontends. oRPC will be disabled. (temporarily)", - ); - if (stack.api !== "trpc") notes.frontend.hasIssue = true; + if (!isPWACompat && stack.addons.includes("pwa")) { + notes.frontend.notes.push("PWA addon requires TanStack or React Router."); + notes.frontend.hasIssue = true; + notes.addons.hasIssue = true; } - if ( - !isPWACompat && - stack.addons.some((a) => ["pwa", "tauri"].includes(a)) - ) { + if (!isTauriCompat && stack.addons.includes("tauri")) { notes.frontend.notes.push( - "PWA/Tauri addons require TanStack or React Router.", + "Tauri addon requires TanStack Router, React Router, or Nuxt.", ); notes.frontend.hasIssue = true; notes.addons.hasIssue = true; } + if (!isWeb && stack.examples.length > 0) { notes.frontend.notes.push("Examples require a web frontend."); notes.frontend.hasIssue = true; notes.examples.hasIssue = true; } - if (isNative && stack.api !== "trpc") { + if (isNuxt && stack.api === "trpc") { notes.api.notes.push( - "React Native requires tRPC. It will be selected automatically.", + "Nuxt requires oRPC. It will be selected automatically.", ); notes.api.hasIssue = true; + notes.frontend.hasIssue = true; } if (stack.database === "mongodb" && stack.orm !== "prisma") { @@ -592,6 +610,7 @@ const StackArchitect = () => { generateCommand, currentHasWebFrontend, currentHasPWACompatibleFrontend, + currentHasTauriCompatibleFrontend, currentHasNativeFrontend, ]); @@ -601,44 +620,55 @@ const StackArchitect = () => { const catKey = category as keyof StackState; const update: Partial = {}; - if ( - catKey === "frontend" || - catKey === "addons" || - catKey === "examples" - ) { + if (catKey === "frontend") { const currentArray = [...(currentStack[catKey] as string[])]; let nextArray = [...currentArray]; const isSelected = currentArray.includes(techId); - if (catKey === "frontend") { - const webTypes = [ - "tanstack-router", - "react-router", - "tanstack-start", - "next", - ]; - if (techId === "none") { - nextArray = ["none"]; - } else if (isSelected) { - nextArray = nextArray.filter((id) => id !== techId); - if (nextArray.length === 0) { - return {}; - } - } else { - nextArray = nextArray.filter((id) => id !== "none"); - if (webTypes.includes(techId)) { - nextArray = nextArray.filter((id) => !webTypes.includes(id)); - } - nextArray.push(techId); + const webTypes = [ + "tanstack-router", + "react-router", + "tanstack-start", + "next", + "nuxt", + ]; + + if (techId === "none") { + nextArray = ["none"]; + } else if (isSelected) { + nextArray = nextArray.filter((id) => id !== techId); + if (nextArray.length === 0) { + return {}; } } else { - if (isSelected) { - nextArray = nextArray.filter((id) => id !== techId); - } else { - nextArray.push(techId); + nextArray = nextArray.filter((id) => id !== "none"); + if (webTypes.includes(techId)) { + nextArray = nextArray.filter((id) => !webTypes.includes(id)); } + nextArray.push(techId); } + const selectedWeb = nextArray.filter((id) => webTypes.includes(id)); + if (selectedWeb.length > 1) { + nextArray = nextArray.filter((id) => !webTypes.includes(id)); + nextArray.push(techId); + } + + if ( + JSON.stringify([...new Set(nextArray)].sort()) !== + JSON.stringify(currentArray.sort()) + ) { + update[catKey] = [...new Set(nextArray)]; + } + } else if (catKey === "addons" || catKey === "examples") { + const currentArray = [...(currentStack[catKey] as string[])]; + let nextArray = [...currentArray]; + const isSelected = currentArray.includes(techId); + if (isSelected) { + nextArray = nextArray.filter((id) => id !== techId); + } else { + nextArray.push(techId); + } if ( JSON.stringify([...new Set(nextArray)].sort()) !== JSON.stringify(currentArray.sort()) @@ -657,6 +687,7 @@ const StackArchitect = () => { [setStack], ); + // biome-ignore lint/correctness/useExhaustiveDependencies: const getDisabledReason = useCallback( (category: keyof typeof TECH_OPTIONS, techId: string): string | null => { const catKey = category as keyof StackState; @@ -684,8 +715,10 @@ const StackArchitect = () => { } } - if (catKey === "api" && techId !== "trpc" && currentHasNativeFrontend) { - return "Only tRPC API is supported with React Native."; + if (catKey === "api") { + if (techId === "trpc" && stack.frontend.includes("nuxt")) { + return "tRPC is not supported with Nuxt. Use oRPC instead."; + } } if (catKey === "orm") { @@ -725,12 +758,12 @@ const StackArchitect = () => { } if (catKey === "addons") { - if ( - (techId === "pwa" || techId === "tauri") && - !currentHasPWACompatibleFrontend - ) { + if (techId === "pwa" && !currentHasPWACompatibleFrontend) { return "Requires TanStack Router or React Router frontend."; } + if (techId === "tauri" && !currentHasTauriCompatibleFrontend) { + return "Requires TanStack Router, React Router, or Nuxt frontend."; + } } if (catKey === "examples") { @@ -751,6 +784,7 @@ const StackArchitect = () => { stack, currentHasNativeFrontend, currentHasPWACompatibleFrontend, + currentHasTauriCompatibleFrontend, currentHasWebFrontend, ], ); @@ -818,483 +852,461 @@ const StackArchitect = () => { }; return ( -
+
- -
- Home +
+ +
+ Home +
+ +
+ Create Better T Stack
- -
- Create Better T Stack -
-
- - - - -
-
- - {showHelp && ( -
-

- How to Use Stack Architect -

-
    -
  • Use the sidebar to navigate between configuration sections.
  • -
  • Select your preferred technologies in the main area.
  • -
  • - Some selections may disable or automatically change other options - based on compatibility (check notes within each section!). -
  • -
  • - The command below updates automatically based on your selections. -
  • -
  • - Click the copy button ( - ) next to the command - to copy it. -
  • -
  • - Use presets () for quick setup - or reset () to defaults. -
  • -
  • - Save () your preferences to - load () them later. -
  • -
-
- )} - - {showPresets && ( -
-

- Quick Start Presets -

-
- {PRESET_TEMPLATES.map((preset) => ( - - ))} -
-
- )} - -
-
-
-
-
- $ - - {command} - + + {showHelp && ( +
+

+ How to Use Stack Architect +

+
    +
  • + Use the sidebar to navigate between configuration sections. +
  • +
  • Select your preferred technologies in the main area.
  • +
  • + Some selections may disable or automatically change other + options based on compatibility (check notes within each + section!). +
  • +
  • + The command below updates automatically based on your + selections. +
  • +
  • + Click the copy button ( + ) next to the + command to copy it. +
  • +
  • + Use presets () for quick + setup or reset () to + defaults. +
  • +
  • + Save () your preferences to + load () them later. +
  • +
- -
+ )} -
-
- {CATEGORY_ORDER.flatMap((category) => { - const categoryKey = category as keyof StackState; - const options = - TECH_OPTIONS[category as keyof typeof TECH_OPTIONS]; - const selectedValue = stack[categoryKey]; - - if (!options) return []; - - if (Array.isArray(selectedValue)) { - if (selectedValue.length === 0 || selectedValue[0] === "none") - return []; - - return selectedValue - .map((id) => options.find((opt) => opt.id === id)) - .filter((tech): tech is NonNullable => - Boolean(tech), - ) - .map((tech) => ( - - - {tech.name} - - )); - } - const tech = options.find((opt) => opt.id === selectedValue); - - if ( - !tech || - tech.id === "none" || - tech.id === "false" || - ((category === "git" || - category === "install" || - category === "auth") && - tech.id === "true") - ) { - return []; - } - - return ( - - - {tech.name} - - ); - })} -
-
-
- -
- + ))} +
+
+ )} - -
- {CATEGORY_ORDER.map((categoryKey) => { - const categoryOptions = - TECH_OPTIONS[categoryKey as keyof typeof TECH_OPTIONS] || []; - const categoryDisplayName = getCategoryDisplayName(categoryKey); - const notesInfo = compatNotes[categoryKey]; - - return ( -
{ - sectionRefs.current[categoryKey] = el; - }} - key={categoryKey} - id={`section-${categoryKey}`} - className="mb-8 scroll-mt-4" +
+
+ +
+ + {lastSavedStack && ( + + )} + +
+
+
+
+ $ + + {command} + +
+ +
- {notesInfo?.notes && notesInfo.notes.length > 0 && ( -
-
+
+ {CATEGORY_ORDER.flatMap((category) => { + const categoryKey = category as keyof StackState; + const options = + TECH_OPTIONS[category as keyof typeof TECH_OPTIONS]; + const selectedValue = stack[categoryKey]; + + if (!options) return []; + + if (Array.isArray(selectedValue)) { + if (selectedValue.length === 0 || selectedValue[0] === "none") + return []; + + return selectedValue + .map((id) => options.find((opt) => opt.id === id)) + .filter((tech): tech is NonNullable => + Boolean(tech), + ) + .map((tech) => ( + - - - {notesInfo.hasIssue - ? "Compatibility Issues / Auto-Adjustments" - : "Notes"} - -
-
    - {notesInfo.notes.map((note, index) => ( - // biome-ignore lint/suspicious/noArrayIndexKey: -
  • {note}
  • - ))} -
+ + {tech.name} + + )); + } + const tech = options.find((opt) => opt.id === selectedValue); + + if ( + !tech || + tech.id === "none" || + tech.id === "false" || + ((category === "git" || + category === "install" || + category === "auth") && + tech.id === "true") + ) { + return []; + } + + return ( + + + {tech.name} + + ); + })} +
+
+
+ +
+ + + +
+ {CATEGORY_ORDER.map((categoryKey) => { + const categoryOptions = + TECH_OPTIONS[categoryKey as keyof typeof TECH_OPTIONS] || []; + const categoryDisplayName = getCategoryDisplayName(categoryKey); + + return ( +
{ + sectionRefs.current[categoryKey] = el; + }} + key={categoryKey} + id={`section-${categoryKey}`} + className="mb-8 scroll-mt-4" + > +
+ +

+ {categoryDisplayName} +

- )} -
- {categoryOptions.map((tech) => { - let isSelected = false; - const category = categoryKey as keyof StackState; +
+ {categoryOptions.map((tech) => { + let isSelected = false; + const category = categoryKey as keyof StackState; - if ( - category === "addons" || - category === "examples" || - category === "frontend" - ) { - isSelected = ( - (stack[category] as string[]) || [] - ).includes(tech.id); - } else { - isSelected = stack[category] === tech.id; - } + if ( + category === "addons" || + category === "examples" || + category === "frontend" + ) { + isSelected = ( + (stack[category] as string[]) || [] + ).includes(tech.id); + } else { + isSelected = stack[category] === tech.id; + } - const disabledReason = getDisabledReason( - categoryKey as keyof typeof TECH_OPTIONS, - tech.id, - ); - const isDisabled = !!disabledReason && !isSelected; + const disabledReason = getDisabledReason( + categoryKey as keyof typeof TECH_OPTIONS, + tech.id, + ); + const isDisabled = !!disabledReason && !isSelected; - return ( - - !isDisabled && - handleTechSelect( - categoryKey as keyof typeof TECH_OPTIONS, - tech.id, - ) - } - > -
-
- {isSelected ? ( - - ) : ( - - )} -
-
-
-
- - + + + !isDisabled && + handleTechSelect( + categoryKey as keyof typeof TECH_OPTIONS, + tech.id, + ) + } + > +
+
+ {isSelected ? ( + + ) : ( + )} - > - {tech.name} - +
+
+
+
+ + + {tech.name} + +
+ {isDisabled && ( + + )} +
+

+ {tech.description} +

+
-
-

- {tech.description} -

-
-
- {tech.default && !isSelected && !isDisabled && ( - - Default - - )} - - ); - })} -
-
- ); - })} -
-
-
+ {tech.default && !isSelected && !isDisabled && ( + + Default + + )} + + + {isDisabled && disabledReason && ( + +

{disabledReason}

+
+ )} + + ); + })} +
+
+ ); + })} +
+
+
+
-
+ ); }; diff --git a/apps/web/src/components/ui/tooltip.tsx b/apps/web/src/components/ui/tooltip.tsx new file mode 100644 index 0000000..bcce829 --- /dev/null +++ b/apps/web/src/components/ui/tooltip.tsx @@ -0,0 +1,61 @@ +"use client"; + +import * as TooltipPrimitive from "@radix-ui/react-tooltip"; +import type * as React from "react"; + +import { cn } from "@/lib/utils"; + +function TooltipProvider({ + delayDuration = 0, + ...props +}: React.ComponentProps) { + return ( + + ); +} + +function Tooltip({ + ...props +}: React.ComponentProps) { + return ( + + + + ); +} + +function TooltipTrigger({ + ...props +}: React.ComponentProps) { + return ; +} + +function TooltipContent({ + className, + sideOffset = 0, + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + + + ); +} + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/apps/web/src/lib/constant.ts b/apps/web/src/lib/constant.ts index cb43570..5e087d5 100644 --- a/apps/web/src/lib/constant.ts +++ b/apps/web/src/lib/constant.ts @@ -50,6 +50,14 @@ export const TECH_OPTIONS = { color: "from-gray-700 to-black", default: false, }, + { + id: "nuxt", + name: "Nuxt", + description: "Vue full-stack framework (SSR, SSG, hybrid)", + icon: "/icon/nuxt.svg", + color: "from-green-400 to-green-700", + default: false, + }, { id: "native", name: "React Native", diff --git a/bun.lock b/bun.lock index 0e38c9c..5632479 100644 --- a/bun.lock +++ b/bun.lock @@ -14,7 +14,7 @@ }, "apps/cli": { "name": "create-better-t-stack", - "version": "2.0.10", + "version": "2.0.12", "bin": { "create-better-t-stack": "dist/index.js", }, @@ -45,6 +45,7 @@ "@heroicons/react": "^2.2.0", "@radix-ui/react-scroll-area": "^1.2.5", "@radix-ui/react-switch": "^1.2.2", + "@radix-ui/react-tooltip": "^1.2.4", "@xyflow/react": "^12.5.5", "babel-plugin-react-compiler": "^19.0.0-beta-e993439-20250405", "class-variance-authority": "^0.7.1", @@ -326,7 +327,7 @@ "@radix-ui/react-accordion": ["@radix-ui/react-accordion@1.2.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collapsible": "1.1.3", "@radix-ui/react-collection": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-controllable-state": "1.1.0" }, "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-RIQ15mrcvqIkDARJeERSuXSry2N8uYnxkdDetpfmalT/+0ntOXLkFOsh9iwlAsCv+qcmhZjbdJogIm6WBa6c4A=="], - "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "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-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg=="], + "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0" }, "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-qz+fxrqgNxG0dYew5l7qR3c7wdgRu1XVUHGnGYX7rg5HM4p9SWaRmJwfgR3J0SgyUKayLmzQIun+N6rWRgiRKw=="], "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-jFSerheto1X03MUC0g6R7LedNW9EEGWdg9W1+MlpkMLwGkgkbUXLPBH/KIuWKXUoeYRVY11llqbTBDzuLg7qrw=="], @@ -340,21 +341,21 @@ "@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw=="], - "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "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-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="], + "@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.7", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@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-j5+WBUdhccJsmH5/H0K6RncjDtoALSEr6jbkaZu+bjw6hOPOhHycr6vEUujl+HBK8kjUfWcoCJXxP6e4lUlMZw=="], "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg=="], "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0" }, "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-zxwE80FCU7lcXUGWkdt6XpTTCKPitG1XKOwViTxHVKIJhZl9MvIl2dVHeZENCWD9+EdWv05wlaEkRXUykU27RA=="], - "@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], "@radix-ui/react-navigation-menu": ["@radix-ui/react-navigation-menu@1.2.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-collection": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-controllable-state": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-previous": "1.1.0", "@radix-ui/react-visually-hidden": "1.1.2" }, "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-myMHHQUZ3ZLTi8W381/Vu43Ia0NqakkQZ2vzynMmTUtQQ9kNkjzhOwkZC9TAM5R07OZUVIQyHC06f/9JZJpvvA=="], "@radix-ui/react-popover": ["@radix-ui/react-popover@1.1.6", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-dismissable-layer": "1.1.5", "@radix-ui/react-focus-guards": "1.1.1", "@radix-ui/react-focus-scope": "1.1.2", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-popper": "1.2.2", "@radix-ui/react-portal": "1.1.4", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-slot": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0", "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-NQouW0x4/GnkFJ/pRqsIS3rM/k97VzKnVb2jB7Gq7VEGPy5g7uNV1ykySFt7eWSp3i2uSGFwaJcvIRJBAHmmFg=="], - "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.2", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-rect": "1.1.0", "@radix-ui/react-use-size": "1.1.0", "@radix-ui/rect": "1.1.0" }, "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-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA=="], + "@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.4", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.4", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@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-3p2Rgm/a1cK0r/UVkx5F/K9v/EplfjAeIFCGOPYPO4lZ0jtg4iSQXt/YGTSLWaf4x7NG6Z4+uKFcylcTZjeqDA=="], - "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="], + "@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.6", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0", "@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-XmsIl2z1n/TsYFLIdYam2rmFwf9OC/Sh2avkbmVMDuBZIe7hSpM0cYnWPAo7nHOVx8zTuwDZGByfcqLdnzp3Vw=="], "@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.3", "", { "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-IrVLIhskYhH3nLvtcBLQFZr61tBG7wx7O3kEmdzcYwRGAEBmBicGGL7ATzNgruYJ3xBTbuzEEq9OXJM3PAX3tA=="], @@ -364,31 +365,33 @@ "@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.5", "", { "dependencies": { "@radix-ui/number": "1.1.1", "@radix-ui/primitive": "1.1.2", "@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-presence": "1.1.3", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-callback-ref": "1.1.1", "@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-VyLjxI8/gXYn+Wij1FLpXjZp6Z/uNklUFQQ75tOpJNESeNaZ2kCRfjiEDmHgWmLeUPeJGwrqbgRmcdFjtYEkMA=="], - "@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "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-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="], "@radix-ui/react-switch": ["@radix-ui/react-switch@1.2.2", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-previous": "1.1.1", "@radix-ui/react-use-size": "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-7Z8n6L+ifMIIYZ83f28qWSceUpkXuslI2FJ34+kDMTiyj91ENdpdQ7VCidrzj5JfwfZTeano/BnGBbu/jqa5rQ=="], "@radix-ui/react-tabs": ["@radix-ui/react-tabs@1.1.3", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-id": "1.1.0", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-roving-focus": "1.1.2", "@radix-ui/react-use-controllable-state": "1.1.0" }, "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-9mFyI30cuRDImbmFF6O2KUJdgEOsGh9Vmx9x/Dh9tOhL7BngmQPQfwW4aejKm5OHpfWIdmeV6ySyuxoOGjtNng=="], + "@radix-ui/react-tooltip": ["@radix-ui/react-tooltip@1.2.4", "", { "dependencies": { "@radix-ui/primitive": "1.1.2", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-dismissable-layer": "1.1.7", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-popper": "1.2.4", "@radix-ui/react-portal": "1.1.6", "@radix-ui/react-presence": "1.1.4", "@radix-ui/react-primitive": "2.1.0", "@radix-ui/react-slot": "1.2.0", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-visually-hidden": "1.2.0" }, "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-DyW8VVeeMSSLFvAmnVnCwvI3H+1tpJFHT50r+tdOoMse9XqYDBCcyux8u3G2y+LOpt7fPQ6KKH0mhs+ce1+Z5w=="], + "@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg=="], "@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": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg=="], "@radix-ui/react-use-effect-event": ["@radix-ui/react-use-effect-event@0.0.2", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA=="], - "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="], + "@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.1", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g=="], "@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ=="], "@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ=="], - "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.0", "", { "dependencies": { "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ=="], + "@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.1", "", { "dependencies": { "@radix-ui/rect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w=="], "@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": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ=="], - "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "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-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q=="], + "@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.2.0", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.0" }, "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-rQj0aAWOpCdCMRbI6pLQm8r7S2BM3YhTa0SzOYD55k+hJA8oo9J+H+9wLM9oMlZWOX/wJWPTzfDfmZkf7LvCfg=="], - "@radix-ui/rect": ["@radix-ui/rect@1.1.0", "", {}, "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="], + "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.34.8", "", { "os": "android", "cpu": "arm" }, "sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw=="], @@ -1764,18 +1767,20 @@ "@radix-ui/react-accordion/@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg=="], + "@radix-ui/react-accordion/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + "@radix-ui/react-accordion/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], "@radix-ui/react-accordion/@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": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], - "@radix-ui/react-arrow/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], - "@radix-ui/react-collapsible/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], "@radix-ui/react-collapsible/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], "@radix-ui/react-collapsible/@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], + "@radix-ui/react-collapsible/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + "@radix-ui/react-collapsible/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], "@radix-ui/react-collapsible/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], @@ -1790,34 +1795,34 @@ "@radix-ui/react-collection/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], + "@radix-ui/react-collection/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "@radix-ui/react-dialog/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], "@radix-ui/react-dialog/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], "@radix-ui/react-dialog/@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], + "@radix-ui/react-dialog/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "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-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="], + + "@radix-ui/react-dialog/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + + "@radix-ui/react-dialog/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="], + "@radix-ui/react-dialog/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], "@radix-ui/react-dialog/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], + "@radix-ui/react-dialog/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "@radix-ui/react-dialog/@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": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], - "@radix-ui/react-dismissable-layer/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], - - "@radix-ui/react-dismissable-layer/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], - - "@radix-ui/react-dismissable-layer/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], - - "@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], - "@radix-ui/react-focus-scope/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], "@radix-ui/react-focus-scope/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], "@radix-ui/react-focus-scope/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], - "@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], - "@radix-ui/react-navigation-menu/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], "@radix-ui/react-navigation-menu/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], @@ -1826,6 +1831,10 @@ "@radix-ui/react-navigation-menu/@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg=="], + "@radix-ui/react-navigation-menu/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "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-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="], + + "@radix-ui/react-navigation-menu/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + "@radix-ui/react-navigation-menu/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], "@radix-ui/react-navigation-menu/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], @@ -1838,36 +1847,30 @@ "@radix-ui/react-navigation-menu/@radix-ui/react-use-previous": ["@radix-ui/react-use-previous@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og=="], + "@radix-ui/react-navigation-menu/@radix-ui/react-visually-hidden": ["@radix-ui/react-visually-hidden@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "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-1SzA4ns2M1aRlvxErqhLHsBHoS5eI5UUcI2awAMgGUp4LoaoWOKYmvqDY2s/tltuPkh3Yk77YF/r3IRj+Amx4Q=="], + "@radix-ui/react-popover/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], "@radix-ui/react-popover/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], "@radix-ui/react-popover/@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], + "@radix-ui/react-popover/@radix-ui/react-dismissable-layer": ["@radix-ui/react-dismissable-layer@1.1.5", "", { "dependencies": { "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-escape-keydown": "1.1.0" }, "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-E4TywXY6UsXNRhFrECa5HAvE5/4BFcGyfTyK36gP+pAW1ed7UTK4vKwdr53gAJYwqbfCWC6ATvJa3J3R/9+Qrg=="], + + "@radix-ui/react-popover/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + + "@radix-ui/react-popover/@radix-ui/react-popper": ["@radix-ui/react-popper@1.2.2", "", { "dependencies": { "@floating-ui/react-dom": "^2.0.0", "@radix-ui/react-arrow": "1.1.2", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0", "@radix-ui/react-use-rect": "1.1.0", "@radix-ui/react-use-size": "1.1.0", "@radix-ui/rect": "1.1.0" }, "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-Rvqc3nOpwseCyj/rgjlJDYAgyfw7OC1tTkKn2ivhaMGcYt8FSBlahHOZak2i3QwkRXUXgGgzeEe2RuqeEHuHgA=="], + + "@radix-ui/react-popover/@radix-ui/react-portal": ["@radix-ui/react-portal@1.1.4", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-sn2O9k1rPFYVyKd5LAJfo96JlSGVFpa1fS6UuBJfrZadudiw5tAmru+n1x7aMRQ84qDM71Zh1+SzK5QwU0tJfA=="], + "@radix-ui/react-popover/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], "@radix-ui/react-popover/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], + "@radix-ui/react-popover/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "@radix-ui/react-popover/@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": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], - "@radix-ui/react-popper/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], - - "@radix-ui/react-popper/@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], - - "@radix-ui/react-popper/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], - - "@radix-ui/react-popper/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], - - "@radix-ui/react-popper/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], - - "@radix-ui/react-popper/@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw=="], - - "@radix-ui/react-portal/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], - - "@radix-ui/react-portal/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], - - "@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.0", "", { "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-ujc+V6r0HNDviYqIK3rW4ffgYiZ8g5DEHrGJVk4x7kTlLXRDILnKX9vAUYeIsLOoDpDJ0ujpqMkjH4w2ofuo6w=="], - "@radix-ui/react-roving-focus/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], "@radix-ui/react-roving-focus/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], @@ -1876,29 +1879,29 @@ "@radix-ui/react-roving-focus/@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg=="], + "@radix-ui/react-roving-focus/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + "@radix-ui/react-roving-focus/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], "@radix-ui/react-roving-focus/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], "@radix-ui/react-roving-focus/@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": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], - "@radix-ui/react-slot/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], - "@radix-ui/react-tabs/@radix-ui/primitive": ["@radix-ui/primitive@1.1.1", "", {}, "sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA=="], "@radix-ui/react-tabs/@radix-ui/react-context": ["@radix-ui/react-context@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q=="], "@radix-ui/react-tabs/@radix-ui/react-direction": ["@radix-ui/react-direction@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg=="], + "@radix-ui/react-tabs/@radix-ui/react-id": ["@radix-ui/react-id@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA=="], + "@radix-ui/react-tabs/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg=="], "@radix-ui/react-tabs/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], "@radix-ui/react-tabs/@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": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw=="], - "@radix-ui/react-use-escape-keydown/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], - - "@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.0.2", "", { "dependencies": { "@radix-ui/react-slot": "1.1.2" }, "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-Ec/0d38EIuvDF+GZjcMU/Ze6MxntVJYO/fRlCPhCaVUyPY9WTalHJw54tp9sXeJo3tlShWpy41vQRgLRGOuz+w=="], + "@radix-ui/react-tooltip/@radix-ui/react-presence": ["@radix-ui/react-presence@1.1.4", "", { "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-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA=="], "@types/fs-extra/@types/node": ["@types/node@22.13.1", "", { "dependencies": { "undici-types": "~6.20.0" } }, "sha512-jK8uzQlrvXqEU91UxiK5J7pKHyzgnI1Qnl0QDHIgVGuolJhRb9EEl28Cj9b3rGR8B2lhFCtvIm5os8lFnO/1Ew=="], @@ -1942,6 +1945,8 @@ "fumadocs-ui/@radix-ui/react-scroll-area": ["@radix-ui/react-scroll-area@1.2.3", "", { "dependencies": { "@radix-ui/number": "1.1.0", "@radix-ui/primitive": "1.1.1", "@radix-ui/react-compose-refs": "1.1.1", "@radix-ui/react-context": "1.1.1", "@radix-ui/react-direction": "1.1.0", "@radix-ui/react-presence": "1.1.2", "@radix-ui/react-primitive": "2.0.2", "@radix-ui/react-use-callback-ref": "1.1.0", "@radix-ui/react-use-layout-effect": "1.1.0" }, "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-l7+NNBfBYYJa9tNqVcP2AGvxdE3lmE6kFTBXdvHgUaZuy+4wGCL1Cl2AfaR7RKyimj7lZURGLwFO59k4eBnDJQ=="], + "fumadocs-ui/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "fumadocs-ui/lucide-react": ["lucide-react@0.483.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-WldsY17Qb/T3VZdMnVQ9C3DDIP7h1ViDTHVdVGnLZcvHNg30zH/MTQ04RTORjexoGmpsXroiQXZ4QyR0kBy0FA=="], "fumadocs-ui/tailwind-merge": ["tailwind-merge@3.0.2", "", {}, "sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw=="], @@ -2046,22 +2051,70 @@ "@next/eslint-plugin-next/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], + "@radix-ui/react-accordion/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + + "@radix-ui/react-accordion/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "@radix-ui/react-accordion/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + "@radix-ui/react-collapsible/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "@radix-ui/react-collapsible/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + "@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + + "@radix-ui/react-dialog/@radix-ui/react-dismissable-layer/@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="], + + "@radix-ui/react-dialog/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + + "@radix-ui/react-dialog/@radix-ui/react-portal/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + "@radix-ui/react-dialog/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], "@radix-ui/react-dialog/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + "@radix-ui/react-focus-scope/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + + "@radix-ui/react-navigation-menu/@radix-ui/react-dismissable-layer/@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="], + + "@radix-ui/react-navigation-menu/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + + "@radix-ui/react-popover/@radix-ui/react-dismissable-layer/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + + "@radix-ui/react-popover/@radix-ui/react-dismissable-layer/@radix-ui/react-use-escape-keydown": ["@radix-ui/react-use-escape-keydown@1.1.0", "", { "dependencies": { "@radix-ui/react-use-callback-ref": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw=="], + + "@radix-ui/react-popover/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + + "@radix-ui/react-popover/@radix-ui/react-popper/@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.2", "", { "dependencies": { "@radix-ui/react-primitive": "2.0.2" }, "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-G+KcpzXHq24iH0uGG/pF8LyzpFJYGD4RfLjCIBfGdSLXvjLHST31RUiRVrupIBMvIppMgSzQ6l66iAxl03tdlg=="], + + "@radix-ui/react-popover/@radix-ui/react-popper/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + + "@radix-ui/react-popover/@radix-ui/react-popper/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + + "@radix-ui/react-popover/@radix-ui/react-popper/@radix-ui/react-use-rect": ["@radix-ui/react-use-rect@1.1.0", "", { "dependencies": { "@radix-ui/rect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ=="], + + "@radix-ui/react-popover/@radix-ui/react-popper/@radix-ui/react-use-size": ["@radix-ui/react-use-size@1.1.0", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw=="], + + "@radix-ui/react-popover/@radix-ui/react-popper/@radix-ui/rect": ["@radix-ui/rect@1.1.0", "", {}, "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg=="], + + "@radix-ui/react-popover/@radix-ui/react-portal/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + "@radix-ui/react-popover/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], "@radix-ui/react-popover/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], + "@radix-ui/react-roving-focus/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + + "@radix-ui/react-roving-focus/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + + "@radix-ui/react-tabs/@radix-ui/react-id/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + "@radix-ui/react-tabs/@radix-ui/react-presence/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], "@radix-ui/react-tabs/@radix-ui/react-presence/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + "@radix-ui/react-tabs/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.1.2", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-YAKxaiGsSQJ38VzKH86/BPRC4rh+b1Jpa+JneA5LRE7skmLPNAyeG8kPJj/oo4STLvlrs8vkf/iYyc3A5stYCQ=="], + "@radix-ui/react-tabs/@radix-ui/react-use-controllable-state/@radix-ui/react-use-callback-ref": ["@radix-ui/react-use-callback-ref@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw=="], "@types/fs-extra/@types/node/undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="], @@ -2090,6 +2143,8 @@ "fumadocs-ui/@radix-ui/react-scroll-area/@radix-ui/react-use-layout-effect": ["@radix-ui/react-use-layout-effect@1.1.0", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w=="], + "fumadocs-ui/@radix-ui/react-slot/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], + "glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "gray-matter/js-yaml/argparse": ["argparse@1.0.10", "", { "dependencies": { "sprintf-js": "~1.0.2" } }, "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg=="], @@ -2112,6 +2167,8 @@ "@manypkg/find-root/find-up/locate-path/p-locate": ["p-locate@4.1.0", "", { "dependencies": { "p-limit": "^2.2.0" } }, "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A=="], + "@radix-ui/react-tabs/@radix-ui/react-primitive/@radix-ui/react-slot/@radix-ui/react-compose-refs": ["@radix-ui/react-compose-refs@1.1.1", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw=="], + "cli-truncate/string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="], } }