UNPKG

@consensys/create-web3-app

Version:

CLI tool for generating Web3 starter projects, streamlining the setup of monorepo structures with a frontend (Next.js or React) and blockchain tooling (HardHat or Foundry). It leverages the commander library for command-line interactions and guides users

232 lines (231 loc) 27.6 kB
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; var __generator = (this && this.__generator) || function (thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } }; import path from "path"; import { promises as fs } from "fs"; import { addShadcnButton, addShadcnCard, createWagmiConfigFile, execAsync, pathOrProjectName, updatePackageJsonDependencies, usePackageManager, addShadcnDropdownMenu, addShadcnSeparator, createNoise, createArrow, createMetamaskLogo, createComponentsFolder, createUtils, } from "./index.js"; export var createNextApp = function (options, projectPath) { return __awaiter(void 0, void 0, void 0, function () { var projectName, packageManager, projectPathOrName, command, error_1; return __generator(this, function (_a) { switch (_a.label) { case 0: console.log("Creating Next.js project..."); _a.label = 1; case 1: _a.trys.push([1, 21, , 22]); projectName = options.projectName, packageManager = options.packageManager; projectPathOrName = pathOrProjectName(projectName, projectPath); command = "npx create-next-app ".concat(projectPathOrName, " --ts --tailwind --eslint --app --src-dir --skip-install --import-alias \"@/*\" ").concat(usePackageManager(packageManager), " --turbopack"); return [4 /*yield*/, execAsync(command)]; case 2: _a.sent(); return [4 /*yield*/, updatePackageJsonDependencies({ "@tanstack/react-query": "^5.51.23", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.3", "@radix-ui/react-separator": "^1.1.1", "lucide-react": "^0.468.0", "class-variance-authority": "^0.7.1", "tailwind-merge": "^2.5.5", "tailwindcss-animate": "^1.0.7", clsx: "^2.1.1", viem: "2.x", wagmi: "^2.14.8", }, projectPathOrName)]; case 3: _a.sent(); return [4 /*yield*/, updateTsConfig(projectPathOrName)]; case 4: _a.sent(); return [4 /*yield*/, createComponentsFolder(projectPathOrName)]; case 5: _a.sent(); return [4 /*yield*/, updateLayoutFile(projectPathOrName)]; case 6: _a.sent(); return [4 /*yield*/, createProvider(projectPathOrName)]; case 7: _a.sent(); return [4 /*yield*/, createWagmiConfigFile(projectPathOrName, true)]; case 8: _a.sent(); return [4 /*yield*/, createUtils(projectPathOrName)]; case 9: _a.sent(); return [4 /*yield*/, addShadcnButton(projectPathOrName)]; case 10: _a.sent(); return [4 /*yield*/, addShadcnCard(projectPathOrName)]; case 11: _a.sent(); return [4 /*yield*/, addShadcnDropdownMenu(projectPathOrName)]; case 12: _a.sent(); return [4 /*yield*/, addShadcnSeparator(projectPathOrName)]; case 13: _a.sent(); return [4 /*yield*/, createNoise(projectPathOrName)]; case 14: _a.sent(); return [4 /*yield*/, createArrow(projectPathOrName)]; case 15: _a.sent(); return [4 /*yield*/, createMetamaskLogo(projectPathOrName)]; case 16: _a.sent(); return [4 /*yield*/, createHero(projectPathOrName)]; case 17: _a.sent(); return [4 /*yield*/, createNavbar(projectPathOrName)]; case 18: _a.sent(); return [4 /*yield*/, updateGlobalStyles(projectPathOrName)]; case 19: _a.sent(); return [4 /*yield*/, updatePageFile(projectPathOrName)]; case 20: _a.sent(); console.log("Next.js project created successfully!"); return [3 /*break*/, 22]; case 21: error_1 = _a.sent(); console.error("An unexpected error occurred:", error_1); return [3 /*break*/, 22]; case 22: return [2 /*return*/]; } }); }); }; var updateTsConfig = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { var tsConfigPath, tsConfigContent, tsConfig, newTsConfigContent; return __generator(this, function (_a) { switch (_a.label) { case 0: tsConfigPath = path.join(projectPath, "tsconfig.json"); return [4 /*yield*/, fs.readFile(tsConfigPath, "utf-8")]; case 1: tsConfigContent = _a.sent(); tsConfig = JSON.parse(tsConfigContent); tsConfig.compilerOptions.paths = { "@/*": ["./*"], }; newTsConfigContent = JSON.stringify(tsConfig, null, 2); return [4 /*yield*/, fs.writeFile(tsConfigPath, newTsConfigContent, "utf-8")]; case 2: _a.sent(); return [2 /*return*/]; } }); }); }; var updateLayoutFile = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { var layoutFilePath; return __generator(this, function (_a) { switch (_a.label) { case 0: layoutFilePath = path.join(projectPath, "src", "app", "layout.tsx"); return [4 /*yield*/, fs.writeFile(layoutFilePath, "\n import type { Metadata } from \"next\";\n import { Geist, Geist_Mono } from \"next/font/google\";\n import { headers } from \"next/headers\";\n import { cookieToInitialState } from \"wagmi\";\n import \"./globals.css\";\n import { getConfig } from \"@/wagmi.config\";\n import { Providers } from \"@/src/providers/WagmiProvider\";\n import { Navbar } from \"@/src/components/navbar\";\n \n const geistSans = Geist({\n variable: \"--font-geist-sans\",\n subsets: [\"latin\"],\n });\n \n const geistMono = Geist_Mono({\n variable: \"--font-geist-mono\",\n subsets: [\"latin\"],\n });\n \n export const metadata: Metadata = {\n title: \"MetaMask SDK Quickstart\",\n description: \"MetaMask SDK Quickstart app\",\n };\n \n export default async function RootLayout({\n children,\n }: Readonly<{\n children: React.ReactNode;\n }>) {\n const initialState = cookieToInitialState(\n getConfig(),\n (await headers()).get(\"cookie\") ?? \"\"\n );\n return (\n <html lang=\"en\">\n <body\n className={\n geistSans.variable +\n \" \" +\n geistMono.variable +\n \" \" +\n \"bg-black bg-opacity-90 text-foreground antialiased\"\n }\n >\n <div className=\"fixed inset-0 w-full h-full bg-repeat bg-noise opacity-25 bg-[length:350px] z-[-20] before:content-[''] before:absolute before:w-[2500px] before:h-[2500px] before:rounded-full before:blur-[100px] before:-left-[1000px] before:-top-[2000px] before:bg-white before:opacity-50 before:z-[-100]\"></div>\n <main className=\"flex flex-col max-w-screen-lg mx-auto pb-20\">\n <Providers initialState={initialState}>\n <Navbar />\n {children}\n </Providers>\n </main>\n </body>\n </html>\n );\n } \n")]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; var createProvider = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { var providerFilePath; return __generator(this, function (_a) { switch (_a.label) { case 0: return [4 /*yield*/, fs.mkdir(path.join(projectPath, "src", "providers"))]; case 1: _a.sent(); providerFilePath = path.join(projectPath, "src", "providers", "WagmiProvider.tsx"); return [4 /*yield*/, fs.writeFile(providerFilePath, "\n\"use client\";\n\nimport { QueryClient, QueryClientProvider } from \"@tanstack/react-query\";\nimport { type ReactNode, useState } from \"react\";\nimport { type State, WagmiProvider } from \"wagmi\";\n\nimport { getConfig } from \"@/wagmi.config\";\n\ntype Props = {\n children: ReactNode;\n initialState: State | undefined;\n};\n\nexport function Providers({ children, initialState }: Props) {\n const [config] = useState(() => getConfig());\n const [queryClient] = useState(() => new QueryClient());\n\n return (\n <WagmiProvider config={config} initialState={initialState}>\n <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>\n </WagmiProvider>\n );\n}\n ")]; case 2: _a.sent(); return [2 /*return*/]; } }); }); }; var updatePageFile = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { var pageFilePath; return __generator(this, function (_a) { switch (_a.label) { case 0: pageFilePath = path.join(projectPath, "src", "app", "page.tsx"); return [4 /*yield*/, fs.writeFile(pageFilePath, "\n import { Separator } from \"@/src/components/ui/separator\";\n import { Card, CardContent, CardHeader, CardTitle } from \"@/src/components/ui/card\";\n import { ArrowRight } from \"lucide-react\";\n import { Hero } from \"@/src/components/Hero\";\n \n export default function Home() {\n return (\n <main className=\"\">\n <div className=\"flex flex-col gap-8 items-center sm:items-start w-full px-3 md:px-0\">\n <Hero />\n \n <Separator className=\"w-full my-14 opacity-15\" />\n \n <section className=\"flex flex-col items-center md:flex-row gap-10 w-full justify-center max-w-5xl\">\n <div className=\"flex flex-col gap-10\">\n {/* Docs Card */}\n <a\n href=\"https://docs.metamask.io/sdk/\"\n target=\"_blank\"\n className=\"relative bg-indigo-500 rounded-tr-sm rounded-bl-sm rounded-tl-xl rounded-br-xl bg-opacity-40 max-w-md text-white border-none transition-colors h-full\"\n >\n <div className=\"bg-indigo-500/20 h-[107%] w-[104%] rounded-xl -z-20 absolute right-0 bottom-0\"></div>\n <div className=\"bg-indigo-500/20 h-[107%] w-[104%] rounded-xl -z-20 absolute top-0 left-0\"></div>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-2xl\">\n Docs\n <ArrowRight className=\"h-5 w-5\" />\n </CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-lg text-indigo-100\">\n Find in-depth information about the SDK features\n </p>\n </CardContent>\n </a>\n \n {/* Get ETH Card */}\n <a\n href=\"https://docs.metamask.io/developer-tools/faucet/\"\n target=\"_blank\"\n className=\"bg-teal-300 bg-opacity-60 rounded-tr-sm rounded-bl-sm rounded-tl-xl rounded-br-xl relative max-w-md h-full text-white border-none transition-colors\"\n >\n <div className=\"bg-teal-300/20 h-[107%] w-[104%] rounded-xl -z-20 absolute right-0 bottom-0\"></div>\n <div className=\"bg-teal-300/20 h-[107%] w-[104%] rounded-xl -z-20 absolute top-0 left-0\"></div>\n <CardHeader>\n <CardTitle className=\"flex items-center gap-2 text-2xl\">\n Get ETH on testnet\n <ArrowRight className=\"h-5 w-5\" />\n </CardTitle>\n </CardHeader>\n <CardContent>\n <p className=\"text-lg text-emerald-100\">\n Get testnet tokens to use when testing your smart contracts.\n </p>\n </CardContent>\n </a>\n </div>\n \n <Card className=\"relative bg-pink-500 bg-opacity-35 rounded-tr-sm rounded-bl-sm text-white border-none h-full w-full max-w-xl self-start h-[360px]\">\n <div className=\"bg-pink-500/20 h-[104%] w-[103%] md:h-[103%] md:w-[102%] rounded-xl -z-20 absolute right-0 bottom-0\"></div>\n <div className=\"bg-pink-500/20 h-[104%] w-[103%] md:h-[103%] md:w-[102%] rounded-xl -z-20 absolute top-0 left-0\"></div>\n <CardHeader>\n <CardTitle className=\"text-2xl\">\n Add your own functionality\n </CardTitle>\n </CardHeader>\n <CardContent className=\"space-y-7\">\n <div className=\"space-y-1\">\n <h3 className=\"text-lg font-semibold\">Guides</h3>\n <div className=\"space-y-2\">\n {[\n {url: \"https://docs.metamask.io/sdk/guides/network-management/\", text: \"Manage Networks\"},\n {url: \"https://docs.metamask.io/sdk/guides/transaction-handling/\", text: \"Handle Transactions\"},\n {url: \"https://docs.metamask.io/sdk/guides/interact-with-contracts/\", text: \"Interact with Smart Contracts\"},\n ].map((item) => (\n <a\n href={item.url}\n key={item.text}\n target=\"_blank\"\n className=\"flex items-center gap-2 w-fit text-white text-opacity-80 cursor-pointer transition-colors\"\n >\n <span className=\"hover:mr-1 duration-300\">{item.text}</span>\n <ArrowRight className=\"h-5 w-5\" />\n </a>\n ))}\n </div>\n </div>\n <div className=\"space-y-1\">\n <h3 className=\"text-lg font-semibold\">Examples</h3>\n <div className=\"space-y-1\">\n {[\n {url: \"https://github.com/MetaMask/metamask-sdk-examples/tree/main/examples/quickstart\", text: \"Next.js + Wagmi\"},\n ].map((item) => (\n <a\n href={item.url}\n key={item.text}\n target=\"_blank\"\n className=\"flex items-center gap-2 w-fit text-white text-opacity-80 cursor-pointer transition-colors\"\n >\n <span className=\"hover:mr-1 duration-300\">{item.text}</span>\n <ArrowRight className=\"h-5 w-5\" />\n </a>\n ))}\n </div>\n </div>\n </CardContent>\n </Card>\n </section>\n </div>\n </main>\n );\n }\n ")]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; var createNavbar = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { var navbarFilePath; return __generator(this, function (_a) { switch (_a.label) { case 0: navbarFilePath = path.join(projectPath, "src", "components", "navbar.tsx"); return [4 /*yield*/, fs.writeFile(navbarFilePath, "\n\"use client\";\n\nimport Image from \"next/image\";\nimport { useAccount, useConnect, useDisconnect, useSwitchChain } from \"wagmi\";\nimport { Button } from \"./ui/button\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/src/components/ui/dropdown-menu\";\nimport { formatAddress } from \"@/src/lib/utils\";\nimport { ChevronDown } from \"lucide-react\";\n\nexport function Navbar() {\n const { address, isConnected, chain } = useAccount();\n const { connect, connectors } = useConnect();\n const { disconnect } = useDisconnect();\n const { switchChain, chains } = useSwitchChain();\n\n const connector = connectors[0];\n\n return (\n <nav className=\"flex w-full px-3 md:px-0 h-fit py-10 justify-between items-center\">\n <Image\n src=\"/metamask-logo.svg\"\n alt=\"Metamask Logo\"\n width={180}\n height={180}\n />\n\n {isConnected ? (\n <div className=\"flex-col md:flex-row flex gap-2\">\n <DropdownMenu>\n <DropdownMenuTrigger className=\"bg-white h-fit md:px-3 py-2 rounded-2xl font-semibold flex justify-center items-center gap-1\">\n {chain?.name.split(\" \").slice(0, 2).join(\" \")} <ChevronDown />\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"w-full justify-center rounded-2xl\">\n {chains.map(\n (c) =>\n c.id !== chain?.id && (\n <DropdownMenuItem\n key={c.id}\n onClick={() => switchChain({ chainId: c.id })}\n className=\"cursor-pointer w-full flex justify-center rounded-2xl font-semibold\"\n >\n {c.name}\n </DropdownMenuItem>\n )\n )}\n </DropdownMenuContent>\n </DropdownMenu>\n <DropdownMenu>\n <DropdownMenuTrigger className=\"bg-white h-fit px-7 py-2 rounded-2xl font-semibold flex items-center gap-1\">\n {formatAddress(address)} <ChevronDown />\n </DropdownMenuTrigger>\n <DropdownMenuContent className=\"w-full flex justify-center rounded-2xl\">\n <DropdownMenuItem\n onClick={() => disconnect()}\n className=\"text-red-400 cursor-pointer w-full flex justify-center rounded-2xl font-semibold\"\n >\n Disconnect\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n </div>\n ) : (\n <Button\n className=\"bg-blue-500 rounded-xl hover:bg-blue-600 shadow-xl md:px-10 font-semibold\"\n onClick={() => connect({ connector })}\n >\n Connect Wallet\n </Button>\n )}\n </nav>\n );\n}\n ")]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; var createHero = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { var heroFilePath; return __generator(this, function (_a) { switch (_a.label) { case 0: heroFilePath = path.join(projectPath, "src", "components", "Hero.tsx"); return [4 /*yield*/, fs.writeFile(heroFilePath, "\n \"use client\";\n\n import Image from \"next/image\";\n import { useAccount } from \"wagmi\";\n\n export const Hero = () => {\n const { isConnected } = useAccount();\n\n if (isConnected) {\n return (\n <section className=\"relative mx-auto mt-28\">\n <h1 className=\"text-7xl text-zinc-100 font-bold\">Welcome</h1>\n <p className=\"text-white opacity-70 text-center text-lg\">\n to the <strong>MetaMask SDK</strong> quick start app!\n <br /> Add your functionality.\n </p>\n <Image\n src=\"/arrow.svg\"\n alt=\"Arrow pointing to the connect wallet button\"\n className=\"absolute scale-y-[-1] hidden md:block md:bottom-[-65px] md:right-[-95px]\"\n width={130}\n height={130}\n />\n </section>\n );\n }\n\n return (\n <section className=\"relative mx-auto mt-28\">\n <h1 className=\"text-7xl text-zinc-100 font-bold\">Welcome</h1>\n <p className=\"text-white opacity-70 text-center text-lg\">\n to the <strong>MetaMask SDK</strong> quick start app!\n <br /> Connect your wallet to get started.\n </p>\n <Image\n src=\"/arrow.svg\"\n alt=\"Arrow pointing to the connect wallet button\"\n className=\"absolute hidden md:block md:bottom-5 md:-right-48\"\n width={150}\n height={150}\n />\n </section>\n );\n };\n ")]; case 1: _a.sent(); return [2 /*return*/]; } }); }); }; var updateGlobalStyles = function (projectPath) { return __awaiter(void 0, void 0, void 0, function () { var globalStylesFilePath; return __generator(this, function (_a) { switch (_a.label) { case 0: globalStylesFilePath = path.join(projectPath, "src", "app", "globals.css"); return [4 /*yield*/, fs.writeFile(globalStylesFilePath, "\n@import 'tailwindcss';\n\n@plugin 'tailwindcss-animate';\n\n@custom-variant dark (&:is(.dark *));\n\n@theme {\n --color-background: hsl(var(--background));\n --color-foreground: hsl(var(--foreground));\n\n --color-card: hsl(var(--card));\n --color-card-foreground: hsl(var(--card-foreground));\n\n --color-popover: hsl(var(--popover));\n --color-popover-foreground: hsl(var(--popover-foreground));\n\n --color-primary: hsl(var(--primary));\n --color-primary-foreground: hsl(var(--primary-foreground));\n\n --color-secondary: hsl(var(--secondary));\n --color-secondary-foreground: hsl(var(--secondary-foreground));\n\n --color-muted: hsl(var(--muted));\n --color-muted-foreground: hsl(var(--muted-foreground));\n\n --color-accent: hsl(var(--accent));\n --color-accent-foreground: hsl(var(--accent-foreground));\n\n --color-destructive: hsl(var(--destructive));\n --color-destructive-foreground: hsl(var(--destructive-foreground));\n\n --color-border: hsl(var(--border));\n --color-input: hsl(var(--input));\n --color-ring: hsl(var(--ring));\n\n --color-chart-1: hsl(var(--chart-1));\n --color-chart-2: hsl(var(--chart-2));\n --color-chart-3: hsl(var(--chart-3));\n --color-chart-4: hsl(var(--chart-4));\n --color-chart-5: hsl(var(--chart-5));\n\n --background-image-noise: url('/noise.svg');\n\n --radius-lg: var(--radius);\n --radius-md: calc(var(--radius) - 2px);\n --radius-sm: calc(var(--radius) - 4px);\n}\n\n@layer base {\n *,\n ::after,\n ::before,\n ::backdrop,\n ::file-selector-button {\n border-color: var(--color-gray-200, currentColor);\n }\n}\n\n@layer base {\n @font-face {\n font-family: \"Cedarville Cursive\";\n src: url(\"/fonts/cedarville-cursive-regular.woff2\") format(\"woff2\");\n }\n :root {\n --background: 0 0% 100%;\n --foreground: 0 0% 3.9%;\n --card: 0 0% 100%;\n --card-foreground: 0 0% 3.9%;\n --popover: 0 0% 100%;\n --popover-foreground: 0 0% 3.9%;\n --primary: 0 0% 9%;\n --primary-foreground: 0 0% 98%;\n --secondary: 0 0% 96.1%;\n --secondary-foreground: 0 0% 9%;\n --muted: 0 0% 96.1%;\n --muted-foreground: 0 0% 45.1%;\n --accent: 0 0% 96.1%;\n --accent-foreground: 0 0% 9%;\n --destructive: 0 84.2% 60.2%;\n --destructive-foreground: 0 0% 98%;\n --border: 0 0% 89.8%;\n --input: 0 0% 89.8%;\n --ring: 0 0% 3.9%;\n --chart-1: 12 76% 61%;\n --chart-2: 173 58% 39%;\n --chart-3: 197 37% 24%;\n --chart-4: 43 74% 66%;\n --chart-5: 27 87% 67%;\n --radius: 0.5rem;\n }\n .dark {\n --background: 0 0% 3.9%;\n --foreground: 0 0% 98%;\n --card: 0 0% 3.9%;\n --card-foreground: 0 0% 98%;\n --popover: 0 0% 3.9%;\n --popover-foreground: 0 0% 98%;\n --primary: 0 0% 98%;\n --primary-foreground: 0 0% 9%;\n --secondary: 0 0% 14.9%;\n --secondary-foreground: 0 0% 98%;\n --muted: 0 0% 14.9%;\n --muted-foreground: 0 0% 63.9%;\n --accent: 0 0% 14.9%;\n --accent-foreground: 0 0% 98%;\n --destructive: 0 62.8% 30.6%;\n --destructive-foreground: 0 0% 98%;\n --border: 0 0% 14.9%;\n --input: 0 0% 14.9%;\n --ring: 0 0% 83.1%;\n --chart-1: 220 70% 50%;\n --chart-2: 160 60% 45%;\n --chart-3: 30 80% 55%;\n --chart-4: 280 65% 60%;\n --chart-5: 340 75% 55%;\n }\n}\n\n@layer utilities {\n body {\n font-family: Arial, Helvetica, sans-serif;\n }\n}\n\n@layer base {\n * {\n @apply border-border;\n }\n body {\n @apply bg-background text-foreground;\n }\n}\n ")]; case 1: _a.sent(); return [2 /*return*/]; } }); }); };