@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
JavaScript
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*/];
}
});
}); };