virastack 0.0.1 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +94 -18
- package/bin/virastack.js +7 -0
- package/package.json +43 -9
- package/src/commands/add.js +64 -0
- package/src/commands/init.js +286 -0
- package/src/i18n.js +231 -0
- package/src/index.js +64 -0
- package/src/utils/args.js +60 -0
- package/src/utils/copy-template.js +81 -0
- package/src/utils/exec.js +29 -0
- package/src/utils/git.js +38 -0
- package/src/utils/is-online.js +14 -0
- package/src/utils/package-info.js +12 -0
- package/src/utils/package-manager.js +33 -0
- package/src/utils/setup-env.js +25 -0
- package/src/utils/telemetry.js +86 -0
- package/src/utils/tools.js +48 -0
- package/src/utils/update-package-json.js +44 -0
- package/src/utils/update-readme.js +25 -0
- package/src/utils/validate-project-name.js +26 -0
- package/templates/nextjs/.changeset/README.md +8 -0
- package/templates/nextjs/.changeset/config.json +11 -0
- package/templates/nextjs/.env.example +6 -0
- package/templates/nextjs/.env.local +6 -0
- package/templates/nextjs/.eslintcache +1 -0
- package/templates/nextjs/.github/workflows/ci.yml +41 -0
- package/templates/nextjs/.husky/commit-msg +1 -0
- package/templates/nextjs/.husky/pre-commit +1 -0
- package/templates/nextjs/.husky/pre-push +1 -0
- package/templates/nextjs/.prettierignore +6 -0
- package/templates/nextjs/.prettierrc +42 -0
- package/templates/nextjs/.vscode/extensions.json +7 -0
- package/templates/nextjs/.vscode/settings.json +20 -0
- package/templates/nextjs/LICENSE +21 -0
- package/templates/nextjs/README.md +202 -0
- package/templates/nextjs/_gitignore +45 -0
- package/templates/nextjs/commitlint.config.js +6 -0
- package/templates/nextjs/eslint.config.mjs +27 -0
- package/templates/nextjs/knip.config.js +25 -0
- package/templates/nextjs/next-env.d.ts +6 -0
- package/templates/nextjs/next.config.ts +39 -0
- package/templates/nextjs/package.json +115 -0
- package/templates/nextjs/pnpm-lock.yaml +6467 -0
- package/templates/nextjs/pnpm-workspace.yaml +3 -0
- package/templates/nextjs/postcss.config.mjs +7 -0
- package/templates/nextjs/public/favicon.ico +0 -0
- package/templates/nextjs/public/llms.txt +96 -0
- package/templates/nextjs/public/logo.png +0 -0
- package/templates/nextjs/public/logo.webp +0 -0
- package/templates/nextjs/public/og.png +0 -0
- package/templates/nextjs/src/app/error.tsx +34 -0
- package/templates/nextjs/src/app/favicon.ico +0 -0
- package/templates/nextjs/src/app/global-error.tsx +32 -0
- package/templates/nextjs/src/app/layout.tsx +37 -0
- package/templates/nextjs/src/app/loading.tsx +12 -0
- package/templates/nextjs/src/app/manifest.ts +22 -0
- package/templates/nextjs/src/app/not-found.tsx +18 -0
- package/templates/nextjs/src/app/page.tsx +5 -0
- package/templates/nextjs/src/app/robots.ts +13 -0
- package/templates/nextjs/src/app/sitemap.ts +14 -0
- package/templates/nextjs/src/components/shared/ThemeToggle.tsx +30 -0
- package/templates/nextjs/src/components/ui/avatar.tsx +54 -0
- package/templates/nextjs/src/components/ui/button.tsx +46 -0
- package/templates/nextjs/src/components/ui/dialog.tsx +107 -0
- package/templates/nextjs/src/components/ui/field.tsx +24 -0
- package/templates/nextjs/src/components/ui/index.ts +27 -0
- package/templates/nextjs/src/components/ui/input.tsx +23 -0
- package/templates/nextjs/src/components/ui/label.tsx +17 -0
- package/templates/nextjs/src/components/ui/skeleton.tsx +13 -0
- package/templates/nextjs/src/components/ui/table.tsx +94 -0
- package/templates/nextjs/src/components/ui/tabs.tsx +46 -0
- package/templates/nextjs/src/config/seo.config.ts +37 -0
- package/templates/nextjs/src/config/site.config.ts +15 -0
- package/templates/nextjs/src/constants/index.ts +5 -0
- package/templates/nextjs/src/env.ts +41 -0
- package/templates/nextjs/src/features/landing/api/get-users.api.ts +7 -0
- package/templates/nextjs/src/features/landing/api/index.ts +2 -0
- package/templates/nextjs/src/features/landing/api/query-keys.ts +7 -0
- package/templates/nextjs/src/features/landing/components/CartDemo.tsx +66 -0
- package/templates/nextjs/src/features/landing/components/Features.tsx +39 -0
- package/templates/nextjs/src/features/landing/components/Hero.tsx +65 -0
- package/templates/nextjs/src/features/landing/components/LandingPage.tsx +17 -0
- package/templates/nextjs/src/features/landing/components/ProjectFormDemo.tsx +62 -0
- package/templates/nextjs/src/features/landing/components/Reveal.tsx +83 -0
- package/templates/nextjs/src/features/landing/components/Showcase.tsx +66 -0
- package/templates/nextjs/src/features/landing/components/UsersDemo.tsx +188 -0
- package/templates/nextjs/src/features/landing/data/features.data.tsx +47 -0
- package/templates/nextjs/src/features/landing/data/index.ts +1 -0
- package/templates/nextjs/src/features/landing/helpers/get-initials.ts +15 -0
- package/templates/nextjs/src/features/landing/helpers/index.ts +7 -0
- package/templates/nextjs/src/features/landing/helpers/motion.ts +21 -0
- package/templates/nextjs/src/features/landing/hooks/index.ts +1 -0
- package/templates/nextjs/src/features/landing/hooks/use-users.ts +16 -0
- package/templates/nextjs/src/features/landing/icons/index.ts +6 -0
- package/templates/nextjs/src/features/landing/icons/nextjs.tsx +68 -0
- package/templates/nextjs/src/features/landing/icons/react-hook-form.tsx +18 -0
- package/templates/nextjs/src/features/landing/icons/react.tsx +20 -0
- package/templates/nextjs/src/features/landing/icons/tailwind.tsx +14 -0
- package/templates/nextjs/src/features/landing/icons/tanstack.tsx +321 -0
- package/templates/nextjs/src/features/landing/icons/typescript.tsx +16 -0
- package/templates/nextjs/src/features/landing/index.ts +1 -0
- package/templates/nextjs/src/features/landing/schemas/index.ts +1 -0
- package/templates/nextjs/src/features/landing/schemas/project.schema.ts +7 -0
- package/templates/nextjs/src/features/landing/stores/counter.store.ts +18 -0
- package/templates/nextjs/src/features/landing/stores/index.ts +1 -0
- package/templates/nextjs/src/features/landing/types/index.ts +1 -0
- package/templates/nextjs/src/features/landing/types/user.types.ts +9 -0
- package/templates/nextjs/src/helpers/format-date.ts +13 -0
- package/templates/nextjs/src/helpers/index.ts +1 -0
- package/templates/nextjs/src/hooks/index.ts +5 -0
- package/templates/nextjs/src/lib/api.ts +97 -0
- package/templates/nextjs/src/lib/query-client.ts +18 -0
- package/templates/nextjs/src/lib/utils.ts +12 -0
- package/templates/nextjs/src/providers/Providers.tsx +15 -0
- package/templates/nextjs/src/providers/QueryProvider.tsx +19 -0
- package/templates/nextjs/src/providers/ThemeProvider.tsx +9 -0
- package/templates/nextjs/src/providers/index.ts +1 -0
- package/templates/nextjs/src/proxy.ts +6 -0
- package/templates/nextjs/src/schemas/index.ts +5 -0
- package/templates/nextjs/src/stores/index.ts +5 -0
- package/templates/nextjs/src/styles/tailwind.css +122 -0
- package/templates/nextjs/src/types/site-config.types.ts +10 -0
- package/templates/nextjs/tsconfig.json +45 -0
- package/templates/nextjs/tsconfig.tsbuildinfo +1 -0
- package/templates/tanstack/.changeset/README.md +8 -0
- package/templates/tanstack/.changeset/config.json +11 -0
- package/templates/tanstack/.env.example +6 -0
- package/templates/tanstack/.env.local +6 -0
- package/templates/tanstack/.eslintcache +1 -0
- package/templates/tanstack/.github/workflows/ci.yml +41 -0
- package/templates/tanstack/.husky/commit-msg +1 -0
- package/templates/tanstack/.husky/pre-commit +1 -0
- package/templates/tanstack/.husky/pre-push +1 -0
- package/templates/tanstack/.prettierignore +7 -0
- package/templates/tanstack/.prettierrc +41 -0
- package/templates/tanstack/.vscode/extensions.json +7 -0
- package/templates/tanstack/.vscode/settings.json +22 -0
- package/templates/tanstack/LICENSE +21 -0
- package/templates/tanstack/README.md +204 -0
- package/templates/tanstack/_gitignore +52 -0
- package/templates/tanstack/commitlint.config.js +6 -0
- package/templates/tanstack/eslint.config.js +28 -0
- package/templates/tanstack/knip.config.js +22 -0
- package/templates/tanstack/package.json +130 -0
- package/templates/tanstack/pnpm-lock.yaml +5835 -0
- package/templates/tanstack/pnpm-workspace.yaml +3 -0
- package/templates/tanstack/public/favicon.ico +0 -0
- package/templates/tanstack/public/llms.txt +86 -0
- package/templates/tanstack/public/logo.png +0 -0
- package/templates/tanstack/public/logo.webp +0 -0
- package/templates/tanstack/public/og.png +0 -0
- package/templates/tanstack/src/components/shared/DefaultCatchBoundary.tsx +36 -0
- package/templates/tanstack/src/components/shared/NotFound.tsx +18 -0
- package/templates/tanstack/src/components/shared/Pending.tsx +13 -0
- package/templates/tanstack/src/components/shared/ThemeToggle.tsx +31 -0
- package/templates/tanstack/src/components/ui/avatar.tsx +52 -0
- package/templates/tanstack/src/components/ui/button.tsx +47 -0
- package/templates/tanstack/src/components/ui/dialog.tsx +107 -0
- package/templates/tanstack/src/components/ui/field.tsx +24 -0
- package/templates/tanstack/src/components/ui/index.ts +27 -0
- package/templates/tanstack/src/components/ui/input.tsx +23 -0
- package/templates/tanstack/src/components/ui/label.tsx +17 -0
- package/templates/tanstack/src/components/ui/skeleton.tsx +13 -0
- package/templates/tanstack/src/components/ui/table.tsx +94 -0
- package/templates/tanstack/src/components/ui/tabs.tsx +46 -0
- package/templates/tanstack/src/config/seo.config.ts +52 -0
- package/templates/tanstack/src/config/site.config.ts +15 -0
- package/templates/tanstack/src/constants/index.ts +5 -0
- package/templates/tanstack/src/env.ts +47 -0
- package/templates/tanstack/src/features/landing/api/get-users.api.ts +7 -0
- package/templates/tanstack/src/features/landing/api/index.ts +2 -0
- package/templates/tanstack/src/features/landing/api/query-keys.ts +7 -0
- package/templates/tanstack/src/features/landing/components/CartDemo.tsx +66 -0
- package/templates/tanstack/src/features/landing/components/Features.tsx +39 -0
- package/templates/tanstack/src/features/landing/components/Hero.tsx +63 -0
- package/templates/tanstack/src/features/landing/components/LandingPage.tsx +17 -0
- package/templates/tanstack/src/features/landing/components/ProjectFormDemo.tsx +63 -0
- package/templates/tanstack/src/features/landing/components/Reveal.tsx +83 -0
- package/templates/tanstack/src/features/landing/components/Showcase.tsx +66 -0
- package/templates/tanstack/src/features/landing/components/UsersDemo.tsx +191 -0
- package/templates/tanstack/src/features/landing/data/features.data.tsx +45 -0
- package/templates/tanstack/src/features/landing/data/index.ts +1 -0
- package/templates/tanstack/src/features/landing/helpers/get-initials.ts +15 -0
- package/templates/tanstack/src/features/landing/helpers/index.ts +7 -0
- package/templates/tanstack/src/features/landing/helpers/motion.ts +21 -0
- package/templates/tanstack/src/features/landing/hooks/index.ts +1 -0
- package/templates/tanstack/src/features/landing/hooks/use-users.ts +19 -0
- package/templates/tanstack/src/features/landing/icons/index.ts +5 -0
- package/templates/tanstack/src/features/landing/icons/react-hook-form.tsx +18 -0
- package/templates/tanstack/src/features/landing/icons/react.tsx +20 -0
- package/templates/tanstack/src/features/landing/icons/tailwind.tsx +14 -0
- package/templates/tanstack/src/features/landing/icons/tanstack.tsx +321 -0
- package/templates/tanstack/src/features/landing/icons/typescript.tsx +16 -0
- package/templates/tanstack/src/features/landing/index.ts +1 -0
- package/templates/tanstack/src/features/landing/schemas/index.ts +1 -0
- package/templates/tanstack/src/features/landing/schemas/project.schema.ts +7 -0
- package/templates/tanstack/src/features/landing/stores/counter.store.ts +18 -0
- package/templates/tanstack/src/features/landing/stores/index.ts +1 -0
- package/templates/tanstack/src/features/landing/types/index.ts +1 -0
- package/templates/tanstack/src/features/landing/types/user.types.ts +9 -0
- package/templates/tanstack/src/helpers/format-date.ts +13 -0
- package/templates/tanstack/src/helpers/index.ts +1 -0
- package/templates/tanstack/src/hooks/index.ts +5 -0
- package/templates/tanstack/src/lib/api.ts +97 -0
- package/templates/tanstack/src/lib/query-client.ts +18 -0
- package/templates/tanstack/src/lib/utils.ts +13 -0
- package/templates/tanstack/src/providers/Providers.tsx +12 -0
- package/templates/tanstack/src/providers/ThemeProvider.tsx +98 -0
- package/templates/tanstack/src/providers/devtools.tsx +6 -0
- package/templates/tanstack/src/providers/index.ts +1 -0
- package/templates/tanstack/src/providers/root-provider.ts +9 -0
- package/templates/tanstack/src/routeTree.gen.ts +123 -0
- package/templates/tanstack/src/router.tsx +27 -0
- package/templates/tanstack/src/routes/__root.tsx +78 -0
- package/templates/tanstack/src/routes/index.tsx +13 -0
- package/templates/tanstack/src/routes/robots[.]txt.ts +21 -0
- package/templates/tanstack/src/routes/site[.]webmanifest.ts +32 -0
- package/templates/tanstack/src/routes/sitemap[.]xml.ts +27 -0
- package/templates/tanstack/src/schemas/index.ts +5 -0
- package/templates/tanstack/src/start.ts +20 -0
- package/templates/tanstack/src/stores/index.ts +5 -0
- package/templates/tanstack/src/styles/tailwind.css +123 -0
- package/templates/tanstack/src/types/site-config.types.ts +10 -0
- package/templates/tanstack/tsconfig.json +25 -0
- package/templates/tanstack/tsr.config.json +3 -0
- package/templates/tanstack/vite.config.ts +12 -0
- package/templates-i18n/nextjs/.changeset/README.md +8 -0
- package/templates-i18n/nextjs/.changeset/config.json +11 -0
- package/templates-i18n/nextjs/.env.example +6 -0
- package/templates-i18n/nextjs/.eslintcache +1 -0
- package/templates-i18n/nextjs/.github/workflows/ci.yml +41 -0
- package/templates-i18n/nextjs/.husky/commit-msg +1 -0
- package/templates-i18n/nextjs/.husky/pre-commit +1 -0
- package/templates-i18n/nextjs/.husky/pre-push +1 -0
- package/templates-i18n/nextjs/.prettierignore +6 -0
- package/templates-i18n/nextjs/.prettierrc +42 -0
- package/templates-i18n/nextjs/.vscode/extensions.json +7 -0
- package/templates-i18n/nextjs/.vscode/settings.json +20 -0
- package/templates-i18n/nextjs/LICENSE +21 -0
- package/templates-i18n/nextjs/README.md +202 -0
- package/templates-i18n/nextjs/_gitignore +45 -0
- package/templates-i18n/nextjs/commitlint.config.js +6 -0
- package/templates-i18n/nextjs/eslint.config.mjs +27 -0
- package/templates-i18n/nextjs/knip.config.js +29 -0
- package/templates-i18n/nextjs/next-env.d.ts +6 -0
- package/templates-i18n/nextjs/next.config.ts +42 -0
- package/templates-i18n/nextjs/package.json +117 -0
- package/templates-i18n/nextjs/pnpm-lock.yaml +6854 -0
- package/templates-i18n/nextjs/pnpm-workspace.yaml +3 -0
- package/templates-i18n/nextjs/postcss.config.mjs +7 -0
- package/templates-i18n/nextjs/public/favicon.ico +0 -0
- package/templates-i18n/nextjs/public/llms.txt +96 -0
- package/templates-i18n/nextjs/public/logo.png +0 -0
- package/templates-i18n/nextjs/public/logo.webp +0 -0
- package/templates-i18n/nextjs/public/og.png +0 -0
- package/templates-i18n/nextjs/src/app/[locale]/error.tsx +34 -0
- package/templates-i18n/nextjs/src/app/[locale]/layout.tsx +60 -0
- package/templates-i18n/nextjs/src/app/[locale]/loading.tsx +12 -0
- package/templates-i18n/nextjs/src/app/[locale]/not-found.tsx +18 -0
- package/templates-i18n/nextjs/src/app/[locale]/page.tsx +10 -0
- package/templates-i18n/nextjs/src/app/favicon.ico +0 -0
- package/templates-i18n/nextjs/src/app/global-error.tsx +32 -0
- package/templates-i18n/nextjs/src/app/manifest.ts +22 -0
- package/templates-i18n/nextjs/src/app/robots.ts +13 -0
- package/templates-i18n/nextjs/src/app/sitemap.ts +14 -0
- package/templates-i18n/nextjs/src/components/shared/LanguageSwitcher.tsx +48 -0
- package/templates-i18n/nextjs/src/components/shared/ThemeToggle.tsx +30 -0
- package/templates-i18n/nextjs/src/components/ui/avatar.tsx +54 -0
- package/templates-i18n/nextjs/src/components/ui/button.tsx +46 -0
- package/templates-i18n/nextjs/src/components/ui/dialog.tsx +107 -0
- package/templates-i18n/nextjs/src/components/ui/field.tsx +24 -0
- package/templates-i18n/nextjs/src/components/ui/index.ts +27 -0
- package/templates-i18n/nextjs/src/components/ui/input.tsx +23 -0
- package/templates-i18n/nextjs/src/components/ui/label.tsx +17 -0
- package/templates-i18n/nextjs/src/components/ui/skeleton.tsx +13 -0
- package/templates-i18n/nextjs/src/components/ui/table.tsx +94 -0
- package/templates-i18n/nextjs/src/components/ui/tabs.tsx +46 -0
- package/templates-i18n/nextjs/src/config/seo.config.ts +37 -0
- package/templates-i18n/nextjs/src/config/site.config.ts +15 -0
- package/templates-i18n/nextjs/src/constants/index.ts +5 -0
- package/templates-i18n/nextjs/src/env.ts +41 -0
- package/templates-i18n/nextjs/src/features/landing/api/get-users.api.ts +7 -0
- package/templates-i18n/nextjs/src/features/landing/api/index.ts +2 -0
- package/templates-i18n/nextjs/src/features/landing/api/query-keys.ts +7 -0
- package/templates-i18n/nextjs/src/features/landing/components/CartDemo.tsx +68 -0
- package/templates-i18n/nextjs/src/features/landing/components/Features.tsx +84 -0
- package/templates-i18n/nextjs/src/features/landing/components/Hero.tsx +76 -0
- package/templates-i18n/nextjs/src/features/landing/components/LandingPage.tsx +17 -0
- package/templates-i18n/nextjs/src/features/landing/components/ProjectFormDemo.tsx +64 -0
- package/templates-i18n/nextjs/src/features/landing/components/Reveal.tsx +83 -0
- package/templates-i18n/nextjs/src/features/landing/components/Showcase.tsx +83 -0
- package/templates-i18n/nextjs/src/features/landing/components/UsersDemo.tsx +191 -0
- package/templates-i18n/nextjs/src/features/landing/data/features.data.tsx +47 -0
- package/templates-i18n/nextjs/src/features/landing/data/index.ts +1 -0
- package/templates-i18n/nextjs/src/features/landing/helpers/get-initials.ts +15 -0
- package/templates-i18n/nextjs/src/features/landing/helpers/index.ts +7 -0
- package/templates-i18n/nextjs/src/features/landing/helpers/motion.ts +21 -0
- package/templates-i18n/nextjs/src/features/landing/hooks/index.ts +1 -0
- package/templates-i18n/nextjs/src/features/landing/hooks/use-users.ts +16 -0
- package/templates-i18n/nextjs/src/features/landing/icons/index.ts +6 -0
- package/templates-i18n/nextjs/src/features/landing/icons/nextjs.tsx +68 -0
- package/templates-i18n/nextjs/src/features/landing/icons/react-hook-form.tsx +18 -0
- package/templates-i18n/nextjs/src/features/landing/icons/react.tsx +20 -0
- package/templates-i18n/nextjs/src/features/landing/icons/tailwind.tsx +14 -0
- package/templates-i18n/nextjs/src/features/landing/icons/tanstack.tsx +321 -0
- package/templates-i18n/nextjs/src/features/landing/icons/typescript.tsx +16 -0
- package/templates-i18n/nextjs/src/features/landing/index.ts +1 -0
- package/templates-i18n/nextjs/src/features/landing/schemas/index.ts +1 -0
- package/templates-i18n/nextjs/src/features/landing/schemas/project.schema.ts +9 -0
- package/templates-i18n/nextjs/src/features/landing/stores/counter.store.ts +18 -0
- package/templates-i18n/nextjs/src/features/landing/stores/index.ts +1 -0
- package/templates-i18n/nextjs/src/features/landing/types/index.ts +1 -0
- package/templates-i18n/nextjs/src/features/landing/types/user.types.ts +9 -0
- package/templates-i18n/nextjs/src/helpers/format-date.ts +13 -0
- package/templates-i18n/nextjs/src/helpers/index.ts +1 -0
- package/templates-i18n/nextjs/src/hooks/index.ts +5 -0
- package/templates-i18n/nextjs/src/i18n/request.ts +16 -0
- package/templates-i18n/nextjs/src/i18n/routing.ts +11 -0
- package/templates-i18n/nextjs/src/lib/api.ts +97 -0
- package/templates-i18n/nextjs/src/lib/query-client.ts +18 -0
- package/templates-i18n/nextjs/src/lib/utils.ts +12 -0
- package/templates-i18n/nextjs/src/messages/en.json +55 -0
- package/templates-i18n/nextjs/src/messages/tr.json +55 -0
- package/templates-i18n/nextjs/src/providers/Providers.tsx +15 -0
- package/templates-i18n/nextjs/src/providers/QueryProvider.tsx +19 -0
- package/templates-i18n/nextjs/src/providers/ThemeProvider.tsx +9 -0
- package/templates-i18n/nextjs/src/providers/index.ts +1 -0
- package/templates-i18n/nextjs/src/proxy.ts +16 -0
- package/templates-i18n/nextjs/src/schemas/index.ts +5 -0
- package/templates-i18n/nextjs/src/stores/index.ts +5 -0
- package/templates-i18n/nextjs/src/styles/tailwind.css +122 -0
- package/templates-i18n/nextjs/src/types/site-config.types.ts +10 -0
- package/templates-i18n/nextjs/tsconfig.json +45 -0
- package/templates-i18n/nextjs/tsconfig.tsbuildinfo +1 -0
- package/templates-i18n/tanstack/.changeset/README.md +8 -0
- package/templates-i18n/tanstack/.changeset/config.json +11 -0
- package/templates-i18n/tanstack/.env.example +6 -0
- package/templates-i18n/tanstack/.eslintcache +1 -0
- package/templates-i18n/tanstack/.github/workflows/ci.yml +41 -0
- package/templates-i18n/tanstack/.husky/commit-msg +1 -0
- package/templates-i18n/tanstack/.husky/pre-commit +1 -0
- package/templates-i18n/tanstack/.husky/pre-push +1 -0
- package/templates-i18n/tanstack/.prettierignore +7 -0
- package/templates-i18n/tanstack/.prettierrc +41 -0
- package/templates-i18n/tanstack/.vscode/extensions.json +7 -0
- package/templates-i18n/tanstack/.vscode/settings.json +22 -0
- package/templates-i18n/tanstack/LICENSE +21 -0
- package/templates-i18n/tanstack/README.md +204 -0
- package/templates-i18n/tanstack/_gitignore +52 -0
- package/templates-i18n/tanstack/commitlint.config.js +6 -0
- package/templates-i18n/tanstack/eslint.config.js +29 -0
- package/templates-i18n/tanstack/knip.config.js +26 -0
- package/templates-i18n/tanstack/messages/en.json +65 -0
- package/templates-i18n/tanstack/messages/tr.json +65 -0
- package/templates-i18n/tanstack/package.json +132 -0
- package/templates-i18n/tanstack/pnpm-lock.yaml +5998 -0
- package/templates-i18n/tanstack/pnpm-workspace.yaml +3 -0
- package/templates-i18n/tanstack/project.inlang/README.md +157 -0
- package/templates-i18n/tanstack/project.inlang/settings.json +9 -0
- package/templates-i18n/tanstack/public/favicon.ico +0 -0
- package/templates-i18n/tanstack/public/llms.txt +86 -0
- package/templates-i18n/tanstack/public/logo.png +0 -0
- package/templates-i18n/tanstack/public/logo.webp +0 -0
- package/templates-i18n/tanstack/public/og.png +0 -0
- package/templates-i18n/tanstack/src/components/shared/DefaultCatchBoundary.tsx +36 -0
- package/templates-i18n/tanstack/src/components/shared/LanguageSwitcher.tsx +57 -0
- package/templates-i18n/tanstack/src/components/shared/NotFound.tsx +18 -0
- package/templates-i18n/tanstack/src/components/shared/Pending.tsx +13 -0
- package/templates-i18n/tanstack/src/components/shared/ThemeToggle.tsx +31 -0
- package/templates-i18n/tanstack/src/components/ui/avatar.tsx +52 -0
- package/templates-i18n/tanstack/src/components/ui/button.tsx +47 -0
- package/templates-i18n/tanstack/src/components/ui/dialog.tsx +107 -0
- package/templates-i18n/tanstack/src/components/ui/field.tsx +24 -0
- package/templates-i18n/tanstack/src/components/ui/index.ts +27 -0
- package/templates-i18n/tanstack/src/components/ui/input.tsx +23 -0
- package/templates-i18n/tanstack/src/components/ui/label.tsx +17 -0
- package/templates-i18n/tanstack/src/components/ui/skeleton.tsx +13 -0
- package/templates-i18n/tanstack/src/components/ui/table.tsx +94 -0
- package/templates-i18n/tanstack/src/components/ui/tabs.tsx +46 -0
- package/templates-i18n/tanstack/src/config/seo.config.ts +52 -0
- package/templates-i18n/tanstack/src/config/site.config.ts +15 -0
- package/templates-i18n/tanstack/src/constants/index.ts +5 -0
- package/templates-i18n/tanstack/src/env.ts +47 -0
- package/templates-i18n/tanstack/src/features/landing/api/get-users.api.ts +7 -0
- package/templates-i18n/tanstack/src/features/landing/api/index.ts +2 -0
- package/templates-i18n/tanstack/src/features/landing/api/query-keys.ts +7 -0
- package/templates-i18n/tanstack/src/features/landing/components/CartDemo.tsx +67 -0
- package/templates-i18n/tanstack/src/features/landing/components/Features.tsx +79 -0
- package/templates-i18n/tanstack/src/features/landing/components/Hero.tsx +68 -0
- package/templates-i18n/tanstack/src/features/landing/components/LandingPage.tsx +17 -0
- package/templates-i18n/tanstack/src/features/landing/components/ProjectFormDemo.tsx +64 -0
- package/templates-i18n/tanstack/src/features/landing/components/Reveal.tsx +83 -0
- package/templates-i18n/tanstack/src/features/landing/components/Showcase.tsx +81 -0
- package/templates-i18n/tanstack/src/features/landing/components/UsersDemo.tsx +191 -0
- package/templates-i18n/tanstack/src/features/landing/data/features.data.tsx +45 -0
- package/templates-i18n/tanstack/src/features/landing/data/index.ts +1 -0
- package/templates-i18n/tanstack/src/features/landing/helpers/get-initials.ts +15 -0
- package/templates-i18n/tanstack/src/features/landing/helpers/index.ts +7 -0
- package/templates-i18n/tanstack/src/features/landing/helpers/motion.ts +21 -0
- package/templates-i18n/tanstack/src/features/landing/hooks/index.ts +1 -0
- package/templates-i18n/tanstack/src/features/landing/hooks/use-users.ts +19 -0
- package/templates-i18n/tanstack/src/features/landing/icons/index.ts +5 -0
- package/templates-i18n/tanstack/src/features/landing/icons/react-hook-form.tsx +18 -0
- package/templates-i18n/tanstack/src/features/landing/icons/react.tsx +20 -0
- package/templates-i18n/tanstack/src/features/landing/icons/tailwind.tsx +14 -0
- package/templates-i18n/tanstack/src/features/landing/icons/tanstack.tsx +321 -0
- package/templates-i18n/tanstack/src/features/landing/icons/typescript.tsx +16 -0
- package/templates-i18n/tanstack/src/features/landing/index.ts +1 -0
- package/templates-i18n/tanstack/src/features/landing/schemas/index.ts +1 -0
- package/templates-i18n/tanstack/src/features/landing/schemas/project.schema.ts +10 -0
- package/templates-i18n/tanstack/src/features/landing/stores/counter.store.ts +18 -0
- package/templates-i18n/tanstack/src/features/landing/stores/index.ts +1 -0
- package/templates-i18n/tanstack/src/features/landing/types/index.ts +1 -0
- package/templates-i18n/tanstack/src/features/landing/types/user.types.ts +9 -0
- package/templates-i18n/tanstack/src/helpers/format-date.ts +13 -0
- package/templates-i18n/tanstack/src/helpers/index.ts +1 -0
- package/templates-i18n/tanstack/src/hooks/index.ts +5 -0
- package/templates-i18n/tanstack/src/lib/api.ts +97 -0
- package/templates-i18n/tanstack/src/lib/query-client.ts +18 -0
- package/templates-i18n/tanstack/src/lib/utils.ts +13 -0
- package/templates-i18n/tanstack/src/paraglide/README.md +162 -0
- package/templates-i18n/tanstack/src/providers/Providers.tsx +12 -0
- package/templates-i18n/tanstack/src/providers/ThemeProvider.tsx +98 -0
- package/templates-i18n/tanstack/src/providers/devtools.tsx +6 -0
- package/templates-i18n/tanstack/src/providers/index.ts +1 -0
- package/templates-i18n/tanstack/src/providers/root-provider.ts +9 -0
- package/templates-i18n/tanstack/src/routeTree.gen.ts +179 -0
- package/templates-i18n/tanstack/src/router.tsx +27 -0
- package/templates-i18n/tanstack/src/routes/$lang/index.tsx +13 -0
- package/templates-i18n/tanstack/src/routes/$lang.tsx +22 -0
- package/templates-i18n/tanstack/src/routes/__root.tsx +80 -0
- package/templates-i18n/tanstack/src/routes/index.tsx +13 -0
- package/templates-i18n/tanstack/src/routes/robots[.]txt.ts +21 -0
- package/templates-i18n/tanstack/src/routes/site[.]webmanifest.ts +32 -0
- package/templates-i18n/tanstack/src/routes/sitemap[.]xml.ts +27 -0
- package/templates-i18n/tanstack/src/schemas/index.ts +5 -0
- package/templates-i18n/tanstack/src/server.ts +10 -0
- package/templates-i18n/tanstack/src/start.ts +20 -0
- package/templates-i18n/tanstack/src/stores/index.ts +5 -0
- package/templates-i18n/tanstack/src/styles/tailwind.css +123 -0
- package/templates-i18n/tanstack/src/types/site-config.types.ts +10 -0
- package/templates-i18n/tanstack/tsconfig.json +26 -0
- package/templates-i18n/tanstack/tsr.config.json +3 -0
- package/templates-i18n/tanstack/vite.config.ts +31 -0
- package/index.js +0 -3
- package/public/start.jpg +0 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
## What is this folder?
|
|
2
|
+
|
|
3
|
+
This is an [unpacked (git-friendly)](https://inlang.com/docs/unpacked-project) inlang project.
|
|
4
|
+
|
|
5
|
+
## At a glance
|
|
6
|
+
|
|
7
|
+
Purpose:
|
|
8
|
+
|
|
9
|
+
- This folder is the Git-friendly representation of an `.inlang` project.
|
|
10
|
+
- The canonical `.inlang` format is a single binary file; this directory is the unpacked version for Git.
|
|
11
|
+
- This folder stores project configuration and plugin cache data.
|
|
12
|
+
- Translation files live outside this folder and are referenced from `settings.json`.
|
|
13
|
+
|
|
14
|
+
Safe to edit:
|
|
15
|
+
|
|
16
|
+
- `settings.json`
|
|
17
|
+
|
|
18
|
+
Do not edit:
|
|
19
|
+
|
|
20
|
+
- `cache/`
|
|
21
|
+
- `.gitignore`
|
|
22
|
+
|
|
23
|
+
Key files:
|
|
24
|
+
|
|
25
|
+
- `settings.json` — locales, plugins, file patterns
|
|
26
|
+
- `cache/` — plugin caches (safe to delete)
|
|
27
|
+
- `.gitignore` — generated
|
|
28
|
+
- `README.md` — generated, explains this folder
|
|
29
|
+
- `.meta.json` — generated SDK metadata
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
*.inlang/
|
|
33
|
+
├── settings.json # Locales, plugins, and file patterns; kept in Git
|
|
34
|
+
├── .gitignore # Ignores everything except settings.json
|
|
35
|
+
├── README.md # Generated, explains this folder
|
|
36
|
+
├── .meta.json # Generated SDK metadata
|
|
37
|
+
└── cache/ # Plugin caches, usually cache/plugins/
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Translation files (like `messages/en.json`) live **outside** this folder and are referenced via plugins in `settings.json`.
|
|
41
|
+
|
|
42
|
+
## What is inlang?
|
|
43
|
+
|
|
44
|
+
[Inlang](https://inlang.com) is an open project file format for localization. An `.inlang` project is canonically a single binary file: a SQLite database with version control via [lix](https://lix.dev). Like `.sqlite` for relational data, `.inlang` packages localization data into one file that tools can share.
|
|
45
|
+
|
|
46
|
+
For Git repositories, that binary file can be unpacked into a directory of plain files. The packed file is the canonical format; this directory is the Git-friendly representation.
|
|
47
|
+
|
|
48
|
+
Use inlang when multiple tools, teams, automations, or agents need to use the same localization data. The `@inlang/sdk` is the reference implementation for reading and writing `.inlang` projects.
|
|
49
|
+
|
|
50
|
+
`.inlang` is the canonical project format. Plugins import and export external translation files for compatibility with existing runtimes and workflows. Messages, variants, and locale data live in the `.inlang` database; translation files such as `messages/en.json` live outside this folder and are connected through plugins. Version control via lix adds file-level history, merging, and change proposals to `.inlang` projects.
|
|
51
|
+
|
|
52
|
+
It provides:
|
|
53
|
+
|
|
54
|
+
- **CRUD API** — Read and write translations programmatically via SQL
|
|
55
|
+
- **Plugin system** — Import/export external translation files (JSON, XLIFF, etc.)
|
|
56
|
+
- **Version control** — Version control via [lix](https://lix.dev)
|
|
57
|
+
|
|
58
|
+
Core data model:
|
|
59
|
+
|
|
60
|
+
- **Bundle** — one translatable unit across locales
|
|
61
|
+
- **Message** — locale-specific translation for a bundle
|
|
62
|
+
- **Variant** — text pattern plus selector matches
|
|
63
|
+
|
|
64
|
+
```
|
|
65
|
+
┌──────────┐ ┌───────────┐ ┌────────────┐
|
|
66
|
+
│ i18n lib │ │Translation│ │ CI/CD │
|
|
67
|
+
│ │ │ Tool │ │ Automation │
|
|
68
|
+
└────┬─────┘ └─────┬─────┘ └─────┬──────┘
|
|
69
|
+
│ │ │
|
|
70
|
+
└─────────┐ │ ┌──────────┘
|
|
71
|
+
▼ ▼ ▼
|
|
72
|
+
┌──────────────────────────────────┐
|
|
73
|
+
│ *.inlang file │
|
|
74
|
+
└──────────────────────────────────┘
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Quick start
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
npm install @inlang/sdk
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import fs from "node:fs";
|
|
85
|
+
|
|
86
|
+
import { loadProjectFromDirectory, saveProjectToDirectory } from "@inlang/sdk";
|
|
87
|
+
|
|
88
|
+
const project = await loadProjectFromDirectory({
|
|
89
|
+
path: "./project.inlang",
|
|
90
|
+
fs,
|
|
91
|
+
});
|
|
92
|
+
// Query messages with the SDK.
|
|
93
|
+
const messages = await project.db.selectFrom("message").selectAll().execute();
|
|
94
|
+
|
|
95
|
+
// Use project.db to update messages.
|
|
96
|
+
await saveProjectToDirectory({
|
|
97
|
+
path: "./project.inlang",
|
|
98
|
+
fs,
|
|
99
|
+
project,
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
await project.close();
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`loadProjectFromDirectory()` and `saveProjectToDirectory()` both accept `node:fs`. `saveProjectToDirectory()` writes translation files through import/export plugins. If no exporter plugin is configured, save the canonical packed file with `project.toBlob()` instead.
|
|
106
|
+
|
|
107
|
+
## For coding agents and tool builders
|
|
108
|
+
|
|
109
|
+
Target `.inlang` instead of inventing a custom JSON schema.
|
|
110
|
+
|
|
111
|
+
Why target `.inlang`?
|
|
112
|
+
|
|
113
|
+
- One file gives every tool the same data model for bundles, messages, variants, locales, metadata, and settings.
|
|
114
|
+
- CRUD operations are available through the SDK instead of custom parsing and rewriting.
|
|
115
|
+
- Version control via [lix](https://lix.dev) keeps localization changes reviewable and mergeable.
|
|
116
|
+
- Plugins handle JSON, ICU, i18next, XLIFF, and other formats for compatibility.
|
|
117
|
+
|
|
118
|
+
Do not:
|
|
119
|
+
|
|
120
|
+
- Invent a custom `locales/en.json` schema as the project format.
|
|
121
|
+
- Create a new localization config when a `.inlang` project already exists.
|
|
122
|
+
- Edit generated or cached files in this directory.
|
|
123
|
+
- Bypass `@inlang/sdk` when reading or writing `.inlang`.
|
|
124
|
+
|
|
125
|
+
## Ideas for custom tooling
|
|
126
|
+
|
|
127
|
+
- Translation health dashboard (missing/empty/stale messages)
|
|
128
|
+
- Locale coverage report in CI
|
|
129
|
+
- Auto-PR for new keys with placeholders
|
|
130
|
+
- Migration tool between file formats via plugins
|
|
131
|
+
- Glossary/term consistency checker
|
|
132
|
+
|
|
133
|
+
## Data model ([docs](https://inlang.com/docs/data-model))
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
bundle (a concept, e.g., "welcome_header")
|
|
137
|
+
└── message (per locale, e.g., "en", "de")
|
|
138
|
+
└── variant (plural forms, gender, etc.)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
- **bundle**: Groups messages by ID (e.g., `welcome_header`)
|
|
142
|
+
- **message**: A translation for a specific locale
|
|
143
|
+
- **variant**: Handles pluralization/selectors (most messages have one variant)
|
|
144
|
+
|
|
145
|
+
## Common tasks
|
|
146
|
+
|
|
147
|
+
- List bundles: `project.db.selectFrom("bundle").selectAll().execute()`
|
|
148
|
+
- List messages for locale: `project.db.selectFrom("message").where("locale", "=", "en").selectAll().execute()`
|
|
149
|
+
- Find missing translations: compare message counts across locales
|
|
150
|
+
- Update a message: `project.db.updateTable("message").set({ ... }).where("id", "=", "...").execute()`
|
|
151
|
+
|
|
152
|
+
## Links
|
|
153
|
+
|
|
154
|
+
- [SDK documentation](https://inlang.com/docs)
|
|
155
|
+
- [inlang.com](https://inlang.com)
|
|
156
|
+
- [List of plugins](https://inlang.com/c/plugins)
|
|
157
|
+
- [List of tools](https://inlang.com/c/tools)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://inlang.com/schema/project-settings",
|
|
3
|
+
"sourceLanguageTag": "en",
|
|
4
|
+
"languageTags": ["en", "tr"],
|
|
5
|
+
"modules": ["https://cdn.jsdelivr.net/npm/@inlang/plugin-message-format@3/dist/index.js"],
|
|
6
|
+
"plugin.inlang.messageFormat": {
|
|
7
|
+
"pathPattern": "./messages/{languageTag}.json"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# ViraStack Start — TanStack Start Edition
|
|
2
|
+
|
|
3
|
+
> Premium TanStack Start + React 19 + Tailwind CSS 4 boilerplate focused on clean architecture, UI/UX, and agent-ready developer experience. Auth, database/ORM, i18n, and testing are intentionally omitted — bring the solution that fits your project.
|
|
4
|
+
|
|
5
|
+
Built on TanStack Router file-based routing with type-safe loaders, nested layouts, and SSR via TanStack Start. UI primitives use **Base UI** (unstyled, accessible) styled with Tailwind CSS 4 design tokens. State is split by job: TanStack Query for server state, Zustand for client state, `nuqs` for URL state. Forms use React Hook Form + Zod. The home route renders a deletable `features/landing` demo that follows the canonical ViraStack feature tree. **ViraStack AI** (`@virastack/ai`) adds agent rules on scaffold; design skills come from [emilkowalski/skills](https://github.com/emilkowalski/skills) and [make-interfaces-feel-better](https://github.com/jakubkrehel/make-interfaces-feel-better).
|
|
6
|
+
|
|
7
|
+
- Tech stack: TanStack Start, TanStack Router, React 19, Tailwind CSS 4, TypeScript (strict + `noUncheckedIndexedAccess`), Node.js `>=20.9`
|
|
8
|
+
- UI: Base UI, Framer Motion, Sonner, Lucide React, `next-themes`, `class-variance-authority`
|
|
9
|
+
- Data & state: TanStack Query 5, Zustand, `nuqs`
|
|
10
|
+
- Forms: React Hook Form + Zod (+ `@hookform/resolvers`)
|
|
11
|
+
- API: Native `fetch` wrapper in `src/lib/api.ts` (`ApiError` with `message`, `status`, `data`); Axios is optional, not installed
|
|
12
|
+
- Env: Hand-rolled Zod schema in `src/env.ts` (`VITE_*` public vars)
|
|
13
|
+
- Tooling: ESLint 9, Prettier 3, Husky, Knip, Commitlint, Changesets, Vite 8
|
|
14
|
+
- Quality scripts: `pnpm typecheck`, `pnpm lint` / `lint:ci`, `pnpm knip`, `pnpm build`
|
|
15
|
+
- ViraStack AI (via `npx @virastack/ai init`): `AGENTS.md`, `CLAUDE.md`, `.cursor/rules/*.mdc`, `docs/*`
|
|
16
|
+
- Not included by default: Auth, DB/ORM, i18n, test runner, CSP
|
|
17
|
+
|
|
18
|
+
## Docs
|
|
19
|
+
- [Repository (GitHub)](https://github.com/virastack/start): CLI and templates
|
|
20
|
+
- [README](https://github.com/virastack/start/tree/main/templates/tanstack): Features, structure, and conventions
|
|
21
|
+
- [Architecture guide](https://github.com/virastack/ai/blob/main/templates/core/docs/architecture-guide.md): Placement rules and import conventions
|
|
22
|
+
- [Product docs](https://www.virastack.com/): ViraStack
|
|
23
|
+
|
|
24
|
+
## Key Files & Entry Points
|
|
25
|
+
- [`src/routes/__root.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/__root.tsx): Root route, document shell, providers, SEO head
|
|
26
|
+
- [`src/routes/index.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/index.tsx): Home route → `<LandingPage />`
|
|
27
|
+
- [`src/routes/robots[.]txt.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/robots%5B.%5Dtxt.ts): Dynamic robots.txt from `siteConfig`
|
|
28
|
+
- [`src/routes/sitemap[.]xml.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/sitemap%5B.%5Dxml.ts): Dynamic sitemap from `siteConfig`
|
|
29
|
+
- [`src/routes/site[.]webmanifest.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/routes/site%5B.%5Dwebmanifest.ts): Dynamic web manifest from `siteConfig`
|
|
30
|
+
- [`src/start.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/start.ts): Global request middleware (baseline security headers)
|
|
31
|
+
- [`src/router.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/router.tsx): Router factory + TanStack Query SSR integration
|
|
32
|
+
- [`src/env.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/env.ts): Zod-validated environment schema (`VITE_*` public vars)
|
|
33
|
+
- [`src/config/site.config.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/config/site.config.ts): Site config (name, URL, links)
|
|
34
|
+
- [`src/config/seo.config.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/config/seo.config.ts): Default SEO meta helpers
|
|
35
|
+
- [`src/lib/api.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/lib/api.ts): Native `fetch` wrapper with retry & typed `ApiError`
|
|
36
|
+
- [`src/lib/query-client.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/lib/query-client.ts): QueryClient factory & defaults
|
|
37
|
+
- [`src/providers/Providers.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/providers/Providers.tsx): App-wide providers (Theme, Nuqs, Toaster)
|
|
38
|
+
- [`vite.config.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/vite.config.ts): Vite + TanStack Start + Tailwind
|
|
39
|
+
|
|
40
|
+
## Landing Feature (demo — delete when building)
|
|
41
|
+
Canonical tree under `src/features/landing/`. Home route composes `LandingPage`.
|
|
42
|
+
|
|
43
|
+
- [`src/features/landing/index.ts`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/index.ts): Public export (`LandingPage`)
|
|
44
|
+
- [`src/features/landing/components/LandingPage.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/LandingPage.tsx): Page composition (Header + sections + Footer)
|
|
45
|
+
- [`src/features/landing/components/Hero.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/Hero.tsx): Hero section
|
|
46
|
+
- [`src/features/landing/components/Features.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/Features.tsx): Feature grid
|
|
47
|
+
- [`src/features/landing/components/Showcase.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/Showcase.tsx): Stack demos host (Query, Zustand, forms, nuqs)
|
|
48
|
+
- [`src/features/landing/components/UsersDemo.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/UsersDemo.tsx): TanStack Query + `nuqs` demo
|
|
49
|
+
- [`src/features/landing/components/CartDemo.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/CartDemo.tsx): Zustand demo
|
|
50
|
+
- [`src/features/landing/components/ProjectFormDemo.tsx`](https://github.com/virastack/start/blob/main/templates/tanstack/src/features/landing/components/ProjectFormDemo.tsx): RHF + Zod demo
|
|
51
|
+
|
|
52
|
+
Quick start: delete `src/features/landing`, replace `src/routes/index.tsx`, keep `components/layout` if you still want chrome.
|
|
53
|
+
|
|
54
|
+
## UI & Shared Layers
|
|
55
|
+
- [`src/components/ui`](https://github.com/virastack/start/tree/main/templates/tanstack/src/components/ui): Base UI primitives (Button, Input, Field, Dialog, Tabs, Skeleton, Label, Avatar, Table)
|
|
56
|
+
- [`src/components/layout`](https://github.com/virastack/start/tree/main/templates/tanstack/src/components/layout): Header / Footer (reusable; Header accepts optional `links`)
|
|
57
|
+
- [`src/components/shared`](https://github.com/virastack/start/tree/main/templates/tanstack/src/components/shared): Cross-feature components (ThemeToggle, NotFound, DefaultCatchBoundary)
|
|
58
|
+
- [`src/hooks`](https://github.com/virastack/start/tree/main/templates/tanstack/src/hooks), [`src/stores`](https://github.com/virastack/start/tree/main/templates/tanstack/src/stores), [`src/schemas`](https://github.com/virastack/start/tree/main/templates/tanstack/src/schemas): Shared barrels (promote via Rule of Three)
|
|
59
|
+
- [`src/helpers`](https://github.com/virastack/start/tree/main/templates/tanstack/src/helpers): Shared helpers
|
|
60
|
+
- [`src/styles/tailwind.css`](https://github.com/virastack/start/blob/main/templates/tanstack/src/styles/tailwind.css): Tailwind v4 entry + design tokens
|
|
61
|
+
- Assets: [`public/logo.webp`](https://github.com/virastack/start/blob/main/templates/tanstack/public/logo.webp), [`public/og.png`](https://github.com/virastack/start/blob/main/templates/tanstack/public/og.png), [`public/favicon.ico`](https://github.com/virastack/start/blob/main/templates/tanstack/public/favicon.ico)
|
|
62
|
+
|
|
63
|
+
## Customization & Imports
|
|
64
|
+
- Search the project for `FIXME:` (site config, auth attachment on the API client).
|
|
65
|
+
- Prefer short path aliases: `@/ui`, `@/hooks`, `@/schemas`, `@/layout` over long forms. Prefer feature-local imports under `@/features/[feature]/…` for demo-scoped code.
|
|
66
|
+
- Default scope is `features/[feature]/` — promote to global `src/` only when a second feature needs it. No cross-feature imports.
|
|
67
|
+
|
|
68
|
+
## ViraStack AI
|
|
69
|
+
- Install or refresh: `npx @virastack/ai init --force`
|
|
70
|
+
- `AGENTS.md`: Agent operating guide (all agents)
|
|
71
|
+
- `CLAUDE.md`: Claude Code entry point (`@AGENTS.md`)
|
|
72
|
+
- `.cursor/rules/*.mdc`: Scoped coding rules (Cursor auto-loads)
|
|
73
|
+
- `docs/architecture-guide.md`, `docs/MEMORIES.md`: Architecture and project memory
|
|
74
|
+
- Skills: [emilkowalski/skills](https://github.com/emilkowalski/skills) (7 design-engineering skills) + [make-interfaces-feel-better](https://github.com/jakubkrehel/make-interfaces-feel-better)
|
|
75
|
+
- Package: [`@virastack/ai`](https://github.com/virastack/ai)
|
|
76
|
+
|
|
77
|
+
## External References
|
|
78
|
+
- [TanStack Start Docs](https://tanstack.com/start/latest): Routing, SSR, server functions
|
|
79
|
+
- [TanStack Router](https://tanstack.com/router/latest): File-based routing, loaders, type safety
|
|
80
|
+
- [React](https://react.dev/): Modern React APIs
|
|
81
|
+
- [Tailwind CSS v4](https://tailwindcss.com/): Design tokens & utility-first styling
|
|
82
|
+
- [Base UI](https://base-ui.com/): Unstyled, accessible React components
|
|
83
|
+
- [TanStack Query](https://tanstack.com/query/latest): Server-state syncing & caching
|
|
84
|
+
- [nuqs](https://nuqs.dev/): Type-safe URL search param state
|
|
85
|
+
- [Zod](https://zod.dev/): Runtime validation and parsing
|
|
86
|
+
- [ViraStack AI](https://github.com/virastack/ai): Shared agent rules package (`@virastack/ai`)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { ErrorComponentProps } from "@tanstack/react-router";
|
|
2
|
+
import { Link, rootRouteId, useMatch, useRouter } from "@tanstack/react-router";
|
|
3
|
+
|
|
4
|
+
import { Button } from "@/components/ui/button";
|
|
5
|
+
|
|
6
|
+
export function DefaultCatchBoundary({ error }: ErrorComponentProps) {
|
|
7
|
+
const router = useRouter();
|
|
8
|
+
const isRoot = useMatch({
|
|
9
|
+
strict: false,
|
|
10
|
+
select: (state) => state.id === rootRouteId,
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
console.error(error);
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<div className="mx-auto flex flex-1 flex-col items-center justify-center gap-4 px-6 py-24 text-center">
|
|
17
|
+
<h1 className="text-2xl font-semibold tracking-tight">Something went wrong</h1>
|
|
18
|
+
<p className="max-w-md text-sm text-muted-foreground">
|
|
19
|
+
An unexpected error occurred while rendering this page. You can try again, or head back to
|
|
20
|
+
the homepage.
|
|
21
|
+
</p>
|
|
22
|
+
<div className="flex gap-3">
|
|
23
|
+
<Button onClick={() => router.invalidate()}>Try again</Button>
|
|
24
|
+
{isRoot ? (
|
|
25
|
+
<Button variant="outline" nativeButton={false} render={<Link to="/" />}>
|
|
26
|
+
Go home
|
|
27
|
+
</Button>
|
|
28
|
+
) : (
|
|
29
|
+
<Button variant="outline" onClick={() => window.history.back()}>
|
|
30
|
+
Go back
|
|
31
|
+
</Button>
|
|
32
|
+
)}
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useRouter } from "@tanstack/react-router";
|
|
2
|
+
|
|
3
|
+
import { getLocale, setLocale } from "@/paraglide/runtime.js";
|
|
4
|
+
|
|
5
|
+
export function LanguageSwitcher() {
|
|
6
|
+
const router = useRouter();
|
|
7
|
+
const currentLang = getLocale();
|
|
8
|
+
|
|
9
|
+
const onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
|
|
10
|
+
const nextLocale = e.target.value as "en" | "tr";
|
|
11
|
+
|
|
12
|
+
// Geçici olarak as-needed kapatıldı. Her dil için prefix eklenecek.
|
|
13
|
+
// Issue çözüldüğünde eski localizeUrl mantığına dönülebilir.
|
|
14
|
+
const url = new URL(window.location.href);
|
|
15
|
+
const pathSegments = url.pathname.split("/").filter(Boolean);
|
|
16
|
+
|
|
17
|
+
if (pathSegments.length > 0 && (pathSegments[0] === "en" || pathSegments[0] === "tr")) {
|
|
18
|
+
pathSegments[0] = nextLocale;
|
|
19
|
+
} else {
|
|
20
|
+
pathSegments.unshift(nextLocale);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const newPath = "/" + pathSegments.join("/");
|
|
24
|
+
|
|
25
|
+
setLocale(nextLocale, { reload: false });
|
|
26
|
+
void router.navigate({
|
|
27
|
+
to: `${newPath}${url.search}${url.hash}`,
|
|
28
|
+
replace: true,
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div className="relative">
|
|
34
|
+
<select
|
|
35
|
+
value={currentLang}
|
|
36
|
+
onChange={onChange}
|
|
37
|
+
className="h-10 cursor-pointer appearance-none rounded-md border border-input bg-background pr-8 pl-3 text-sm text-foreground focus:border-primary focus:ring-1 focus:ring-primary focus:outline-none disabled:opacity-50"
|
|
38
|
+
>
|
|
39
|
+
<option value="en">EN</option>
|
|
40
|
+
<option value="tr">TR</option>
|
|
41
|
+
</select>
|
|
42
|
+
<div className="pointer-events-none absolute top-[11px] right-2.5 h-4 w-4 text-muted-foreground">
|
|
43
|
+
<svg
|
|
44
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
45
|
+
viewBox="0 0 24 24"
|
|
46
|
+
fill="none"
|
|
47
|
+
stroke="currentColor"
|
|
48
|
+
strokeWidth="2"
|
|
49
|
+
strokeLinecap="round"
|
|
50
|
+
strokeLinejoin="round"
|
|
51
|
+
>
|
|
52
|
+
<path d="m6 9 6 6 6-6" />
|
|
53
|
+
</svg>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Link } from "@tanstack/react-router";
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
|
|
5
|
+
export function NotFound() {
|
|
6
|
+
return (
|
|
7
|
+
<div className="mx-auto flex flex-1 flex-col items-center justify-center gap-4 px-6 py-24 text-center">
|
|
8
|
+
<p className="text-sm font-medium text-muted-foreground">404</p>
|
|
9
|
+
<h1 className="text-2xl font-semibold tracking-tight">Page not found</h1>
|
|
10
|
+
<p className="max-w-md text-sm text-muted-foreground">
|
|
11
|
+
The page you're looking for doesn't exist or has been moved.
|
|
12
|
+
</p>
|
|
13
|
+
<Button nativeButton={false} render={<Link to="/" />}>
|
|
14
|
+
Go home
|
|
15
|
+
</Button>
|
|
16
|
+
</div>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Skeleton } from "@/components/ui/skeleton";
|
|
2
|
+
|
|
3
|
+
/** Route-level pending UI (TanStack equivalent of Next.js `loading.tsx`). */
|
|
4
|
+
export function Pending() {
|
|
5
|
+
return (
|
|
6
|
+
<div className="mx-auto flex w-full max-w-3xl flex-1 flex-col items-center gap-4 px-6 py-24">
|
|
7
|
+
<Skeleton className="h-10 w-2/3" />
|
|
8
|
+
<Skeleton className="h-4 w-full" />
|
|
9
|
+
<Skeleton className="h-4 w-5/6" />
|
|
10
|
+
<Skeleton className="mt-6 h-40 w-full" />
|
|
11
|
+
</div>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { MoonIcon, SunIcon } from "lucide-react";
|
|
4
|
+
import { useIsClient } from "usehooks-ts";
|
|
5
|
+
|
|
6
|
+
import { useTheme } from "@/providers/ThemeProvider";
|
|
7
|
+
|
|
8
|
+
import { Button } from "@/components/ui/button";
|
|
9
|
+
|
|
10
|
+
export function ThemeToggle() {
|
|
11
|
+
const { resolvedTheme, setTheme } = useTheme();
|
|
12
|
+
const isClient = useIsClient();
|
|
13
|
+
|
|
14
|
+
if (!isClient) {
|
|
15
|
+
return <Button variant="outline" size="icon" aria-hidden className="size-8 opacity-0" />;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const isDark = resolvedTheme === "dark";
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<Button
|
|
22
|
+
variant="outline"
|
|
23
|
+
size="icon"
|
|
24
|
+
className="size-8"
|
|
25
|
+
aria-label={isDark ? "Switch to light theme" : "Switch to dark theme"}
|
|
26
|
+
onClick={() => setTheme(isDark ? "light" : "dark")}
|
|
27
|
+
>
|
|
28
|
+
{isDark ? <SunIcon className="size-3.5" /> : <MoonIcon className="size-3.5" />}
|
|
29
|
+
</Button>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@/lib/utils";
|
|
4
|
+
|
|
5
|
+
const Avatar = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
6
|
+
({ className, ...props }, ref) => (
|
|
7
|
+
<div
|
|
8
|
+
ref={ref}
|
|
9
|
+
className={cn("relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
),
|
|
13
|
+
);
|
|
14
|
+
Avatar.displayName = "Avatar";
|
|
15
|
+
|
|
16
|
+
const AvatarImage = React.forwardRef<
|
|
17
|
+
HTMLImageElement,
|
|
18
|
+
React.ImgHTMLAttributes<HTMLImageElement> & {
|
|
19
|
+
onLoadingStatusChange?: (status: "loading" | "loaded" | "error") => void;
|
|
20
|
+
}
|
|
21
|
+
>(({ className, src, alt = "", ...props }, ref) => {
|
|
22
|
+
const [status, setStatus] = React.useState<"loading" | "loaded" | "error">("loading");
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<img
|
|
26
|
+
ref={ref}
|
|
27
|
+
src={src}
|
|
28
|
+
alt={alt}
|
|
29
|
+
className={cn("aspect-square h-full w-full", status !== "loaded" && "hidden", className)}
|
|
30
|
+
onLoad={() => setStatus("loaded")}
|
|
31
|
+
onError={() => setStatus("error")}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
AvatarImage.displayName = "AvatarImage";
|
|
37
|
+
|
|
38
|
+
const AvatarFallback = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
39
|
+
({ className, ...props }, ref) => (
|
|
40
|
+
<div
|
|
41
|
+
ref={ref}
|
|
42
|
+
className={cn(
|
|
43
|
+
"flex h-full w-full items-center justify-center rounded-full bg-muted text-xs",
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
),
|
|
49
|
+
);
|
|
50
|
+
AvatarFallback.displayName = "AvatarFallback";
|
|
51
|
+
|
|
52
|
+
export { Avatar, AvatarImage, AvatarFallback };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { ComponentProps } from "react";
|
|
2
|
+
|
|
3
|
+
import { Button as BaseButton } from "@base-ui/react/button";
|
|
4
|
+
import { cva } from "class-variance-authority";
|
|
5
|
+
import type { VariantProps } from "class-variance-authority";
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/lib/utils";
|
|
8
|
+
|
|
9
|
+
export const buttonVariants = cva(
|
|
10
|
+
"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
11
|
+
{
|
|
12
|
+
variants: {
|
|
13
|
+
variant: {
|
|
14
|
+
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
15
|
+
destructive:
|
|
16
|
+
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20",
|
|
17
|
+
outline:
|
|
18
|
+
"border border-input bg-background shadow-xs hover:bg-accent hover:text-accent-foreground",
|
|
19
|
+
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
20
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
21
|
+
link: "text-primary underline-offset-4 hover:underline",
|
|
22
|
+
},
|
|
23
|
+
size: {
|
|
24
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
25
|
+
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
26
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
27
|
+
icon: "size-9",
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
defaultVariants: {
|
|
31
|
+
variant: "default",
|
|
32
|
+
size: "default",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
export type ButtonProps = ComponentProps<typeof BaseButton> & VariantProps<typeof buttonVariants>;
|
|
38
|
+
|
|
39
|
+
export function Button({ className, variant, size, ...props }: ButtonProps) {
|
|
40
|
+
return (
|
|
41
|
+
<BaseButton
|
|
42
|
+
data-slot="button"
|
|
43
|
+
className={cn(buttonVariants({ variant, size, className }))}
|
|
44
|
+
{...props}
|
|
45
|
+
/>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { ComponentProps } from "react";
|
|
2
|
+
|
|
3
|
+
import { XIcon } from "lucide-react";
|
|
4
|
+
import { Dialog as BaseDialog } from "@base-ui/react/dialog";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@/lib/utils";
|
|
7
|
+
|
|
8
|
+
export function Dialog(props: ComponentProps<typeof BaseDialog.Root>) {
|
|
9
|
+
return <BaseDialog.Root data-slot="dialog" {...props} />;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function DialogTrigger(props: ComponentProps<typeof BaseDialog.Trigger>) {
|
|
13
|
+
return <BaseDialog.Trigger data-slot="dialog-trigger" {...props} />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function DialogClose(props: ComponentProps<typeof BaseDialog.Close>) {
|
|
17
|
+
return <BaseDialog.Close data-slot="dialog-close" {...props} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function DialogContent({
|
|
21
|
+
className,
|
|
22
|
+
children,
|
|
23
|
+
showCloseButton = true,
|
|
24
|
+
...props
|
|
25
|
+
}: ComponentProps<typeof BaseDialog.Popup> & { showCloseButton?: boolean }) {
|
|
26
|
+
return (
|
|
27
|
+
<BaseDialog.Portal>
|
|
28
|
+
<BaseDialog.Backdrop
|
|
29
|
+
data-slot="dialog-backdrop"
|
|
30
|
+
className={cn(
|
|
31
|
+
"fixed inset-0 z-50 bg-black/50",
|
|
32
|
+
"data-[ending-style]:opacity-0 data-[starting-style]:opacity-0",
|
|
33
|
+
"transition-opacity duration-150",
|
|
34
|
+
)}
|
|
35
|
+
/>
|
|
36
|
+
<BaseDialog.Popup
|
|
37
|
+
data-slot="dialog-content"
|
|
38
|
+
className={cn(
|
|
39
|
+
"fixed top-1/2 left-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4",
|
|
40
|
+
"rounded-lg border border-border bg-background p-6 shadow-lg",
|
|
41
|
+
"data-[starting-style]:scale-95 data-[starting-style]:opacity-0",
|
|
42
|
+
"data-[ending-style]:scale-95 data-[ending-style]:opacity-0",
|
|
43
|
+
"transition-all duration-150",
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
{children}
|
|
49
|
+
{showCloseButton && (
|
|
50
|
+
<BaseDialog.Close
|
|
51
|
+
data-slot="dialog-close"
|
|
52
|
+
className={cn(
|
|
53
|
+
"absolute top-4 right-4 rounded-xs opacity-70 transition-opacity outline-none",
|
|
54
|
+
"hover:opacity-100 focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
55
|
+
)}
|
|
56
|
+
>
|
|
57
|
+
<XIcon className="size-4" />
|
|
58
|
+
<span className="sr-only">Close</span>
|
|
59
|
+
</BaseDialog.Close>
|
|
60
|
+
)}
|
|
61
|
+
</BaseDialog.Popup>
|
|
62
|
+
</BaseDialog.Portal>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function DialogHeader({ className, ...props }: ComponentProps<"div">) {
|
|
67
|
+
return (
|
|
68
|
+
<div
|
|
69
|
+
data-slot="dialog-header"
|
|
70
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
71
|
+
{...props}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function DialogFooter({ className, ...props }: ComponentProps<"div">) {
|
|
77
|
+
return (
|
|
78
|
+
<div
|
|
79
|
+
data-slot="dialog-footer"
|
|
80
|
+
className={cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function DialogTitle({ className, ...props }: ComponentProps<typeof BaseDialog.Title>) {
|
|
87
|
+
return (
|
|
88
|
+
<BaseDialog.Title
|
|
89
|
+
data-slot="dialog-title"
|
|
90
|
+
className={cn("text-lg leading-none font-semibold", className)}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
export function DialogDescription({
|
|
97
|
+
className,
|
|
98
|
+
...props
|
|
99
|
+
}: ComponentProps<typeof BaseDialog.Description>) {
|
|
100
|
+
return (
|
|
101
|
+
<BaseDialog.Description
|
|
102
|
+
data-slot="dialog-description"
|
|
103
|
+
className={cn("text-sm text-muted-foreground", className)}
|
|
104
|
+
{...props}
|
|
105
|
+
/>
|
|
106
|
+
);
|
|
107
|
+
}
|