The recipes.blue monorepo recipes.blue
recipes appview atproto

Compare changes

Choose any two refs to compare.

Changed files
+6124 -6046
apps
api
app
ingester
web
config
dev
libs
+1 -2
.env.example
··· 1 1 # Database 2 - DATABASE_URL=http://localhost:4001 3 - DATABASE_AUTH_TOKEN= 2 + DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres 4 3 5 4 # API 6 5 PORT=3000
+3 -1
apps/api/package.json
··· 4 4 "private": true, 5 5 "scripts": { 6 6 "build": "bun --bun run check-types && bun --bun run compile", 7 - "dev": "bun run --hot src/index.ts", 7 + "dev": "bun run --hot src/index.ts | pino-pretty", 8 8 "check-types": "tsc --noEmit", 9 9 "compile": "bun build src/index.ts --compile --minify --sourcemap --outfile=dist/api --target=bun", 10 10 "clean": "rimraf dist" ··· 20 20 "@cookware/lexicons": "workspace:*", 21 21 "@libsql/client": "^0.14.0", 22 22 "drizzle-orm": "catalog:", 23 + "hono": "^4.10.7", 23 24 "pino": "^9.5.0" 24 25 }, 25 26 "devDependencies": { ··· 27 28 "@cookware/tsconfig": "workspace:*", 28 29 "@types/bun": "catalog:", 29 30 "drizzle-kit": "^0.29.0", 31 + "pino-pretty": "^13.1.2", 30 32 "rimraf": "^6.0.1" 31 33 } 32 34 }
-25
apps/api/scripts/generate-jwk.ts
··· 1 - import { generateKeyPair } from "jose"; 2 - 3 - async function serializeKeyToJwk() { 4 - // Generate an RSA key pair 5 - const { publicKey, privateKey } = await generateKeyPair("ES256"); 6 - 7 - // Export keys as JWK 8 - const publicJwk = await import("jose").then((lib) => 9 - lib.exportJWK(publicKey) 10 - ); 11 - const privateJwk = await import("jose").then((lib) => 12 - lib.exportJWK(privateKey) 13 - ); 14 - 15 - // Convert to JSON strings 16 - const publicJwkString = JSON.stringify(publicJwk); 17 - const privateJwkString = JSON.stringify(privateJwk); 18 - 19 - // save 3 of these to PRIVATE_KEY_X env vars 20 - console.log(privateJwkString); 21 - 22 - return { publicJwkString, privateJwkString }; 23 - } 24 - 25 - serializeKeyToJwk();
+16 -7
apps/api/src/index.ts
··· 6 6 import pino from 'pino'; 7 7 import { RedisClient } from 'bun'; 8 8 import { registerGetProfile } from './xrpc/blue.recipes.actor.getProfile.js'; 9 + import { Hono } from 'hono'; 10 + import { mountXrpcRouter } from './util/hono.js'; 9 11 10 12 const logger = pino(); 11 13 const redis = new RedisClient(Bun.env.REDIS_URL ?? "redis://127.0.0.1:6379/0"); 12 14 13 - const router = new XRPCRouter({ 15 + const xrpcRouter = new XRPCRouter({ 14 16 handleException: (err, _req) => { 15 17 if (err instanceof XRPCError) { 16 18 return err.toResponse(); ··· 34 36 }); 35 37 36 38 // actor 37 - registerGetProfile(router, logger, redis); 39 + registerGetProfile(xrpcRouter, logger, redis); 38 40 39 41 // feed 40 - registerGetRecipes(router, logger, redis); 41 - registerGetRecipe(router, logger, redis); 42 + registerGetRecipes(xrpcRouter, logger, redis); 43 + registerGetRecipe(xrpcRouter, logger, redis); 44 + 45 + const app = new Hono(); 46 + 47 + // mount xrpc router at /xrpc 48 + const xrpcApp = new Hono(); 49 + mountXrpcRouter(xrpcApp, xrpcRouter); 50 + app.route('/xrpc', xrpcApp); 42 51 43 52 const server = Bun.serve({ 44 - port: process.env.PORT || 3000, 45 - ...router 53 + port: process.env.PORT || 4000, 54 + fetch: app.fetch, 46 55 }); 47 56 48 - console.log(`Server running on http://localhost:${server.port}`); 57 + logger.info({ url: server.url.toString() }, `Recipes.blue API started up`);
+19 -1
apps/api/src/util/api.ts
··· 1 1 import type {} from '@atcute/atproto'; 2 2 import { CompositeDidDocumentResolver, PlcDidDocumentResolver, WebDidDocumentResolver } from '@atcute/identity-resolver'; 3 3 import { CompositeHandleResolver, DohJsonHandleResolver, WellKnownHandleResolver } from '@atcute/identity-resolver'; 4 - import { ActorIdentifier, AtprotoDid, Handle, isHandle } from '@atcute/lexicons/syntax'; 4 + import { type ActorIdentifier, type AtprotoDid, type Handle, isHandle } from '@atcute/lexicons/syntax'; 5 5 import { isAtprotoDid } from '@atcute/identity'; 6 6 import { RedisClient } from 'bun'; 7 + import type { BlueRecipesActorDefs } from '@cookware/lexicons'; 8 + import type { Blob, LegacyBlob } from '@atcute/lexicons'; 9 + import { buildCdnUrl } from './cdn.js'; 7 10 8 11 const handleResolver = new CompositeHandleResolver({ 9 12 strategy: 'race', ··· 43 46 44 47 return handle; 45 48 } 49 + 50 + export const buildProfileViewBasic = async (author: { 51 + did: AtprotoDid; 52 + displayName: string; 53 + pronouns: string | null; 54 + avatarRef: Blob | LegacyBlob | null; 55 + createdAt: Date; 56 + }, redis: RedisClient): Promise<BlueRecipesActorDefs.ProfileViewBasic> => ({ 57 + did: author.did, 58 + handle: await getHandle(author.did, redis), 59 + displayName: author.displayName, 60 + pronouns: author.pronouns ?? undefined, 61 + avatar: author.avatarRef ? buildCdnUrl('avatar', author.did, author.avatarRef) : undefined, 62 + createdAt: author.createdAt.toISOString(), 63 + });
+40
apps/api/src/util/hono.ts
··· 1 + import { XRPCRouter } from '@atcute/xrpc-server'; 2 + import type { Context, Hono } from 'hono'; 3 + 4 + export type ApiContext = {}; 5 + 6 + /** 7 + * mounts an @atcute/xrpc-server router into hono as a nested route 8 + * 9 + * basically just bridges the two request handlers since both are 10 + * web standard Request/Response. you can optionally pass hono context 11 + * properties to xrpc handlers via the request object 12 + */ 13 + export const mountXrpcRouter = ( 14 + app: Hono, 15 + router: XRPCRouter, 16 + injectContext?: (c: Context) => ApiContext, 17 + ) => { 18 + app.all('*', async (c) => { 19 + let request = c.req.raw; 20 + 21 + // if context injector provided, attach properties to request 22 + if (injectContext) { 23 + const contextData = injectContext(c); 24 + request = Object.assign(request, contextData); 25 + } 26 + 27 + const response = await router.fetch(request); 28 + return response; 29 + }); 30 + }; 31 + 32 + /** 33 + * helper to extract injected context from xrpc request 34 + * use this in your xrpc handlers to access hono context data 35 + */ 36 + export const getInjectedContext = ( 37 + request: Request 38 + ): ApiContext => { 39 + return request as any as ApiContext; 40 + };
+2 -2
apps/api/src/xrpc/blue.recipes.actor.getProfile.ts
··· 2 2 import { BlueRecipesActorGetProfile } from '@cookware/lexicons'; 3 3 import { db, eq } from '@cookware/database'; 4 4 import { getHandle, parseDid } from '../util/api.js'; 5 - import { Logger } from 'pino'; 5 + import { type Logger } from 'pino'; 6 6 import { profilesTable, recipeTable } from '@cookware/database/schema'; 7 7 import { RedisClient } from 'bun'; 8 8 import { buildCdnUrl } from '../util/cdn.js'; ··· 35 35 pronouns: profile.pronouns ?? undefined, 36 36 website: profile.website ?? undefined, 37 37 avatar: profile.avatarRef ? buildCdnUrl('avatar', profile.did, profile.avatarRef) : undefined, 38 - banner: profile.avatarRef ? buildCdnUrl('avatar', profile.did, profile.avatarRef) : undefined, 38 + banner: profile.bannerRef ? buildCdnUrl('feed_thumbnail', profile.did, profile.bannerRef) : undefined, 39 39 recipesCount: profile.recipesCount, 40 40 createdAt: profile.createdAt.toISOString(), 41 41 });
+38 -27
apps/api/src/xrpc/blue.recipes.feed.getRecipe.ts
··· 1 1 import { json, XRPCRouter, XRPCError } from '@atcute/xrpc-server'; 2 - import { BlueRecipesFeedGetRecipe, BlueRecipesFeedRecipe, BlueRecipesActorDefs } from '@cookware/lexicons'; 2 + import { BlueRecipesFeedGetRecipe, BlueRecipesFeedRecipe } from '@cookware/lexicons'; 3 3 import { db, and, or, eq } from '@cookware/database'; 4 - import { parseDid } from '../util/api.js'; 5 - import { Logger } from 'pino'; 6 - import { parseResourceUri, ResourceUri } from '@atcute/lexicons'; 4 + import { buildProfileViewBasic, parseDid } from '../util/api.js'; 5 + import { type Logger } from 'pino'; 6 + import { parseResourceUri, type ResourceUri } from '@atcute/lexicons'; 7 7 import { recipeTable } from '@cookware/database/schema'; 8 8 import { isLegacyBlob } from '@atcute/lexicons/interfaces'; 9 9 import { RedisClient } from 'bun'; 10 + import { buildCdnUrl } from '../util/cdn.js'; 10 11 11 12 const invalidUriError = (uri: string) => new XRPCError({ 12 13 status: 400, ··· 14 15 description: `The provided URI is invalid: ${uri}`, 15 16 }); 16 17 17 - export const registerGetRecipe = (router: XRPCRouter, _logger: Logger, _redis: RedisClient) => { 18 + export const registerGetRecipe = (router: XRPCRouter, _logger: Logger, redis: RedisClient) => { 18 19 router.addQuery(BlueRecipesFeedGetRecipe.mainSchema, { 19 20 async handler({ params: { uris } }) { 20 21 const whereClauses = []; ··· 36 37 const recipes = await db.query.recipeTable.findMany({ 37 38 orderBy: recipeTable.createdAt, 38 39 where: or(...whereClauses), 40 + with: { 41 + author: { 42 + columns: { 43 + did: true, 44 + displayName: true, 45 + pronouns: true, 46 + avatarRef: true, 47 + createdAt: true, 48 + }, 49 + }, 50 + }, 39 51 }); 40 52 41 53 return json({ 42 - recipes: recipes.map((recipe) => ({ 43 - author: { 44 - $type: BlueRecipesActorDefs.profileViewBasicSchema.shape.$type.wrapped.expected, 45 - did: recipe.did, 46 - handle: 'hayden.moe', 47 - createdAt: new Date().toISOString(), 48 - }, 49 - cid: '', 50 - indexedAt: new Date().toISOString(), 51 - record: { 52 - $type: BlueRecipesFeedRecipe.mainSchema.object.shape.$type.expected, 53 - title: recipe.title, 54 - description: recipe.description ?? undefined, 55 - time: recipe.time ?? undefined, 56 - serves: recipe.serves ?? undefined, 57 - ingredients: recipe.ingredients as BlueRecipesFeedRecipe.Ingredient[], 58 - steps: recipe.steps as BlueRecipesFeedRecipe.Step[], 59 - image: isLegacyBlob(recipe.imageRef) ? undefined : recipe.imageRef ?? undefined, 60 - createdAt: recipe.createdAt.toISOString(), 61 - }, 62 - uri: recipe.uri as ResourceUri, 63 - })), 54 + recipes: await Promise.all( 55 + recipes.map(async ({ author, ...recipe }) => ({ 56 + uri: recipe.uri as ResourceUri, 57 + author: await buildProfileViewBasic(author, redis), 58 + cid: recipe.cid, 59 + rkey: recipe.rkey, 60 + imageUrl: recipe.imageRef ? buildCdnUrl('post_image', recipe.did, recipe.imageRef) : undefined, 61 + indexedAt: recipe.ingestedAt.toISOString(), 62 + record: { 63 + $type: BlueRecipesFeedRecipe.mainSchema.object.shape.$type.expected, 64 + title: recipe.title, 65 + description: recipe.description ?? undefined, 66 + time: recipe.time ?? undefined, 67 + serves: recipe.serves ?? undefined, 68 + ingredients: recipe.ingredients as BlueRecipesFeedRecipe.Ingredient[], 69 + steps: recipe.steps as BlueRecipesFeedRecipe.Step[], 70 + image: isLegacyBlob(recipe.imageRef) ? undefined : recipe.imageRef ?? undefined, 71 + createdAt: recipe.createdAt.toISOString(), 72 + }, 73 + })), 74 + ), 64 75 }); 65 76 }, 66 77 });
+15 -5
apps/api/src/xrpc/blue.recipes.feed.getRecipes.ts
··· 3 3 import { BlueRecipesFeedGetRecipes, BlueRecipesFeedRecipe } from '@cookware/lexicons'; 4 4 import { json, XRPCRouter } from '@atcute/xrpc-server'; 5 5 import { getHandle, parseDid } from '../util/api.js'; 6 - import { ResourceUri } from '@atcute/lexicons/syntax'; 7 - import { Logger } from 'pino'; 6 + import { type ResourceUri } from '@atcute/lexicons/syntax'; 7 + import { type Logger } from 'pino'; 8 8 import { isLegacyBlob } from '@atcute/lexicons/interfaces'; 9 9 import { RedisClient } from 'bun'; 10 + import { buildCdnUrl } from '../util/cdn.js'; 10 11 11 12 export const registerGetRecipes = (router: XRPCRouter, _logger: Logger, redis: RedisClient) => { 12 13 router.addQuery(BlueRecipesFeedGetRecipes.mainSchema, { ··· 27 28 limit: limit, 28 29 where: whereClauses ? and(...whereClauses) : undefined, 29 30 with: { 30 - author: true, 31 + author: { 32 + columns: { 33 + did: true, 34 + displayName: true, 35 + pronouns: true, 36 + avatarRef: true, 37 + createdAt: true, 38 + }, 39 + }, 31 40 }, 32 41 }); 33 42 ··· 44 53 did: recipe.author.did, 45 54 handle: await getHandle(recipe.author.did, redis), 46 55 displayName: recipe.author.displayName, 47 - avatar: isLegacyBlob(recipe.author.avatarRef) ? undefined : recipe.author.avatarRef ?? undefined, 56 + avatar: recipe.author.avatarRef ? buildCdnUrl('avatar', recipe.author.did, recipe.author.avatarRef) : undefined, 48 57 pronouns: recipe.author.pronouns ?? undefined, 49 58 createdAt: recipe.author.createdAt.toISOString(), 50 59 }, 51 - cid: '', 60 + cid: recipe.cid, 61 + rkey: recipe.rkey, 52 62 indexedAt: recipe.ingestedAt.toISOString(), 53 63 record: { 54 64 $type: BlueRecipesFeedRecipe.mainSchema.object.shape.$type.expected,
+41
apps/app/.gitignore
··· 1 + # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 + 3 + # dependencies 4 + /node_modules 5 + /.pnp 6 + .pnp.* 7 + .yarn/* 8 + !.yarn/patches 9 + !.yarn/plugins 10 + !.yarn/releases 11 + !.yarn/versions 12 + 13 + # testing 14 + /coverage 15 + 16 + # next.js 17 + /.next/ 18 + /out/ 19 + 20 + # production 21 + /build 22 + 23 + # misc 24 + .DS_Store 25 + *.pem 26 + 27 + # debug 28 + npm-debug.log* 29 + yarn-debug.log* 30 + yarn-error.log* 31 + .pnpm-debug.log* 32 + 33 + # env files (can opt-in for committing if needed) 34 + .env* 35 + 36 + # vercel 37 + .vercel 38 + 39 + # typescript 40 + *.tsbuildinfo 41 + next-env.d.ts
+36
apps/app/README.md
··· 1 + This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app). 2 + 3 + ## Getting Started 4 + 5 + First, run the development server: 6 + 7 + ```bash 8 + npm run dev 9 + # or 10 + yarn dev 11 + # or 12 + pnpm dev 13 + # or 14 + bun dev 15 + ``` 16 + 17 + Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 18 + 19 + You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file. 20 + 21 + This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel. 22 + 23 + ## Learn More 24 + 25 + To learn more about Next.js, take a look at the following resources: 26 + 27 + - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 28 + - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 29 + 30 + You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome! 31 + 32 + ## Deploy on Vercel 33 + 34 + The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 35 + 36 + Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
+63
apps/app/app/(app)/home/home.tsx
··· 1 + 'use client'; 2 + 3 + import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; 4 + import { Input } from "@/components/ui/input"; 5 + import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; 6 + import { ClockIcon } from "lucide-react"; 7 + import { Separator } from "@/components/ui/separator"; 8 + import { useGetRecipesQuery } from "@/lib/queries/recipes"; 9 + import { RecipeCard } from "@/components/views/recipe-card"; 10 + 11 + export const Home = () => { 12 + const { data } = useGetRecipesQuery(); 13 + 14 + return ( 15 + <div className="p-4 flex flex-col gap-8"> 16 + <div className="flex flex-col gap-4 max-w-3xl items-center mx-auto py-16"> 17 + <h1 className="font-bold text-3xl">Welcome to Cookware!</h1> 18 + <span className="text-xl">A little corner of the internet for you to share your recipes with the world.</span> 19 + <Input placeholder="Search recipes..." className="w-full max-w-md" /> 20 + </div> 21 + 22 + <Separator /> 23 + 24 + <h1 className="font-bold text-2xl text-center">Recently-added recipes</h1> 25 + 26 + <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6"> 27 + 28 + {data && data.recipes.map(v => <RecipeCard key={v.cid} recipe={v} />)} 29 + 30 + {[1, 2, 3, 4, 5, 6, 7, 8, 9].map(v => ( 31 + <Card key={v}> 32 + <CardHeader> 33 + <CardTitle>Featured Recipe {v}</CardTitle> 34 + <CardDescription>A recipe to make some of the best food you've ever had!</CardDescription> 35 + </CardHeader> 36 + 37 + <CardContent> 38 + <img className="rounded-md ratio-[4/3] object-cover" src="https://cdn.bsky.app/img/feed_thumbnail/plain/did:plc:26tsx5juuss4yealylyfbj4h/bafkreia4wvg2y4rr6liuffdt4ckcskf4bvdmzbfdsv3ul6t442fu4jxy6m@jpeg" /> 39 + </CardContent> 40 + 41 + <CardFooter> 42 + <div className="flex flex-col gap-2"> 43 + <div className="flex items-center gap-2 text-sm"> 44 + <Avatar className="!size-8"> 45 + <AvatarImage></AvatarImage> 46 + <AvatarFallback>HM</AvatarFallback> 47 + </Avatar> 48 + <span>@hayden.moe</span> 49 + </div> 50 + 51 + <div className="flex items-center gap-2 text-sm"> 52 + <ClockIcon className="!size-4" /> 53 + <span>15 mins</span> 54 + </div> 55 + </div> 56 + </CardFooter> 57 + </Card> 58 + ))} 59 + 60 + </div> 61 + </div> 62 + ); 63 + }
+18
apps/app/app/(app)/home/page.tsx
··· 1 + import { getRecipesOptions } from "@/lib/queries/recipes"; 2 + import { dehydrate, HydrationBoundary, QueryClient } from "@tanstack/react-query"; 3 + import { Home } from "./home"; 4 + import { Client, simpleFetchHandler } from "@atcute/client"; 5 + import { COOKWARE_API_URL } from "@/lib/consts"; 6 + 7 + export default async function HomeRoute() { 8 + const queryClient = new QueryClient(); 9 + await queryClient.prefetchQuery(getRecipesOptions(new Client({ 10 + handler: simpleFetchHandler({ service: COOKWARE_API_URL }), 11 + }))); 12 + 13 + return ( 14 + <HydrationBoundary state={dehydrate(queryClient)}> 15 + <Home /> 16 + </HydrationBoundary> 17 + ); 18 + };
+21
apps/app/app/(app)/layout.tsx
··· 1 + import { AppSidebar } from "@/components/app-sidebar"; 2 + import { SidebarInset, SidebarProvider } from "@/components/ui/sidebar"; 3 + import { PropsWithChildren } from "react"; 4 + 5 + export default ({ children }: PropsWithChildren) => { 6 + return ( 7 + <SidebarProvider 8 + style={ 9 + { 10 + "--sidebar-width": "calc(var(--spacing) * 72)", 11 + "--header-height": "calc(var(--spacing) * 12)", 12 + } as React.CSSProperties 13 + } 14 + > 15 + <AppSidebar variant="inset" /> 16 + <SidebarInset> 17 + {children} 18 + </SidebarInset> 19 + </SidebarProvider> 20 + ); 21 + }
+5
apps/app/app/auth/layout.tsx
··· 1 + import { PropsWithChildren } from "react"; 2 + 3 + export default ({ children }: PropsWithChildren) => { 4 + return children; 5 + };
+97
apps/app/app/auth/login/page.tsx
··· 1 + "use client"; 2 + 3 + import { Button } from "@/components/ui/button"; 4 + import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; 5 + import { Field, FieldDescription, FieldError, FieldGroup, FieldLabel } from "@/components/ui/field"; 6 + import { InputGroup, InputGroupAddon, InputGroupInput } from "@/components/ui/input-group"; 7 + import { Separator } from "@/components/ui/separator"; 8 + import { createAuthorizationUrl, OAuthResponseError } from "@atcute/oauth-browser-client"; 9 + import { IconAt } from "@tabler/icons-react"; 10 + import Link from "next/link"; 11 + import { FormEvent, useState } from "react"; 12 + import { isActorIdentifier } from "@atcute/lexicons/syntax"; 13 + 14 + export default () => { 15 + const [handle, setHandle] = useState(''); 16 + const [error, setError] = useState<string | null>(null); 17 + 18 + const submit = async (e: FormEvent) => { 19 + e.preventDefault(); 20 + 21 + if (!isActorIdentifier(handle)) { 22 + setError('Invalid handle or DID.'); 23 + return; 24 + } 25 + 26 + try { 27 + const authUrl = await createAuthorizationUrl({ 28 + target: { type: 'account', identifier: handle }, 29 + scope: 'atproto transition:generic', 30 + }); 31 + 32 + setTimeout(() => { 33 + window.location.assign(authUrl); 34 + }, 200); 35 + } catch (e) { 36 + if (e instanceof OAuthResponseError) { 37 + setError(e.message); 38 + return; 39 + } 40 + console.error(e); 41 + setError('Something went wrong, try again later.'); 42 + } 43 + }; 44 + 45 + return ( 46 + <div className="min-h-screen min-w-screen flex flex-col p-4 items-center justify-center"> 47 + <Card className="max-w-sm w-full"> 48 + <CardHeader> 49 + <CardTitle>Sign in to Cookware</CardTitle> 50 + <CardDescription>Enter your ATProto/Bluesky handle to log in or sign up.</CardDescription> 51 + </CardHeader> 52 + 53 + <CardContent> 54 + <form onSubmit={submit}> 55 + <FieldGroup> 56 + <Field> 57 + <FieldLabel htmlFor="login_handle">Handle</FieldLabel> 58 + <InputGroup> 59 + <InputGroupInput 60 + name="handle" 61 + id="login_handle" 62 + placeholder="john.doe" 63 + autoFocus 64 + aria-invalid={false} 65 + tabIndex={1} 66 + value={handle} 67 + onChange={(e) => { 68 + e.preventDefault(); 69 + setHandle(e.currentTarget.value); 70 + }} 71 + /> 72 + <InputGroupAddon><IconAt /></InputGroupAddon> 73 + </InputGroup> 74 + <FieldDescription>This is the username you use to log in to sites like Bluesky and Leaflet.</FieldDescription> 75 + {error && <FieldError>{error}</FieldError>} 76 + </Field> 77 + <Field> 78 + <Button 79 + type="submit" 80 + tabIndex={2} 81 + > 82 + Sign in 83 + </Button> 84 + </Field> 85 + </FieldGroup> 86 + <Separator className="my-4" /> 87 + <FieldDescription> 88 + <span> 89 + Don't have an account? <Link className="text-bluesky underline" href="https://bsky.app">Sign up on Bluesky!</Link> 90 + </span> 91 + </FieldDescription> 92 + </form> 93 + </CardContent> 94 + </Card> 95 + </div> 96 + ); 97 + };
+132
apps/app/app/auth/signup/page.tsx
··· 1 + "use client"; 2 + 3 + import { Button } from "@/components/ui/button"; 4 + import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"; 5 + import { Field, FieldDescription, FieldError, FieldGroup, FieldLabel } from "@/components/ui/field"; 6 + import { FormEvent, useState } from "react"; 7 + import { useAuth } from "@/lib/state/auth"; 8 + import { redirect } from "next/navigation"; 9 + import { Input } from "@/components/ui/input"; 10 + import { Textarea } from "@/components/ui/textarea"; 11 + import { BlueRecipesActorProfile } from "@cookware/lexicons"; 12 + import { parse } from "@atcute/lexicons/validations"; 13 + 14 + export default () => { 15 + const auth = useAuth(); 16 + const [displayName, setHandle] = useState(''); 17 + const [bio, setBio] = useState(''); 18 + const [pronouns, setPronouns] = useState(''); 19 + const [error, setError] = useState<string | null>(null); 20 + 21 + if (!auth.loggedIn) throw redirect('/auth/login'); 22 + if (auth.profile.exists) throw redirect('/home'); 23 + 24 + const submit = async (e: FormEvent) => { 25 + e.preventDefault(); 26 + 27 + const res = await auth.pdsClient.post('com.atproto.repo.putRecord', { 28 + input: { 29 + rkey: 'self', 30 + repo: auth.actorDid, 31 + collection: BlueRecipesActorProfile.mainSchema.object.shape.$type.expected, 32 + record: parse(BlueRecipesActorProfile.mainSchema, { 33 + $type: BlueRecipesActorProfile.mainSchema.object.shape.$type.expected, 34 + displayName: displayName, 35 + description: bio, 36 + pronouns: pronouns, 37 + }), 38 + } 39 + }); 40 + 41 + if (!res.ok) { 42 + setError(res.data.error); 43 + return; 44 + } 45 + 46 + throw redirect('/home'); 47 + }; 48 + 49 + return ( 50 + <div className="min-h-screen min-w-screen flex flex-col p-4 items-center justify-center"> 51 + <Card className="max-w-sm w-full"> 52 + <CardHeader> 53 + <CardTitle>Finish setting up your profile</CardTitle> 54 + <CardDescription>You've logged in, but now tell us about yourself before you start sharing foodie tidbits with the world.</CardDescription> 55 + </CardHeader> 56 + 57 + <CardContent> 58 + <form onSubmit={submit}> 59 + <FieldGroup> 60 + <Field> 61 + <FieldLabel htmlFor="signup_displayname">Display name</FieldLabel> 62 + <Input 63 + name="displayName" 64 + id="signup_displayname" 65 + placeholder="Cookery Master" 66 + autoFocus 67 + aria-invalid={false} 68 + tabIndex={1} 69 + value={displayName} 70 + onChange={(e) => { 71 + e.preventDefault(); 72 + setHandle(e.currentTarget.value); 73 + }} 74 + /> 75 + <FieldDescription>What should we call you?</FieldDescription> 76 + {error && <FieldError>{error}</FieldError>} 77 + </Field> 78 + 79 + <Field> 80 + <FieldLabel htmlFor="signup_bio"> 81 + Your bio 82 + <span className="text-muted-foreground">(optional)</span> 83 + </FieldLabel> 84 + <Textarea 85 + name="bio" 86 + id="signup_bio" 87 + placeholder="I'm a chef from the UK, and I love..." 88 + aria-invalid={false} 89 + tabIndex={2} 90 + value={bio} 91 + onChange={(e) => { 92 + e.preventDefault(); 93 + setBio(e.currentTarget.value); 94 + }} 95 + /> 96 + {error && <FieldError>{error}</FieldError>} 97 + </Field> 98 + 99 + <Field> 100 + <FieldLabel htmlFor="signup_pronouns"> 101 + Your pronouns 102 + <span className="text-muted-foreground">(optional)</span> 103 + </FieldLabel> 104 + <Input 105 + name="pronouns" 106 + id="signup_pronouns" 107 + aria-invalid={false} 108 + tabIndex={3} 109 + value={pronouns} 110 + onChange={(e) => { 111 + e.preventDefault(); 112 + setPronouns(e.currentTarget.value); 113 + }} 114 + /> 115 + {error && <FieldError>{error}</FieldError>} 116 + </Field> 117 + 118 + <Field> 119 + <Button 120 + type="submit" 121 + tabIndex={2} 122 + > 123 + Continue 124 + </Button> 125 + </Field> 126 + </FieldGroup> 127 + </form> 128 + </CardContent> 129 + </Card> 130 + </div> 131 + ); 132 + };
apps/app/app/favicon.ico

This is a binary file and will not be displayed.

+126
apps/app/app/globals.css
··· 1 + @import "tailwindcss"; 2 + @import "tw-animate-css"; 3 + 4 + @custom-variant dark (&:is(.dark *)); 5 + 6 + @theme inline { 7 + --color-background: var(--background); 8 + --color-foreground: var(--foreground); 9 + --font-sans: var(--font-geist-sans); 10 + --font-mono: var(--font-geist-mono); 11 + --color-sidebar-ring: var(--sidebar-ring); 12 + --color-sidebar-border: var(--sidebar-border); 13 + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); 14 + --color-sidebar-accent: var(--sidebar-accent); 15 + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); 16 + --color-sidebar-primary: var(--sidebar-primary); 17 + --color-sidebar-foreground: var(--sidebar-foreground); 18 + --color-sidebar: var(--sidebar); 19 + --color-chart-5: var(--chart-5); 20 + --color-chart-4: var(--chart-4); 21 + --color-chart-3: var(--chart-3); 22 + --color-chart-2: var(--chart-2); 23 + --color-chart-1: var(--chart-1); 24 + --color-ring: var(--ring); 25 + --color-input: var(--input); 26 + --color-border: var(--border); 27 + --color-destructive: var(--destructive); 28 + --color-accent-foreground: var(--accent-foreground); 29 + --color-accent: var(--accent); 30 + --color-muted-foreground: var(--muted-foreground); 31 + --color-muted: var(--muted); 32 + --color-secondary-foreground: var(--secondary-foreground); 33 + --color-secondary: var(--secondary); 34 + --color-primary-foreground: var(--primary-foreground); 35 + --color-primary: var(--primary); 36 + --color-popover-foreground: var(--popover-foreground); 37 + --color-popover: var(--popover); 38 + --color-card-foreground: var(--card-foreground); 39 + --color-card: var(--card); 40 + --color-bluesky: var(--bluesky); 41 + --color-bluesky-foreground: var(--bluesky-foreground); 42 + --radius-sm: calc(var(--radius) - 4px); 43 + --radius-md: calc(var(--radius) - 2px); 44 + --radius-lg: var(--radius); 45 + --radius-xl: calc(var(--radius) + 4px); 46 + } 47 + 48 + :root { 49 + --radius: 0.625rem; 50 + --background: oklch(1 0 0); 51 + --foreground: oklch(0.141 0.005 285.823); 52 + --card: oklch(1 0 0); 53 + --card-foreground: oklch(0.141 0.005 285.823); 54 + --popover: oklch(1 0 0); 55 + --popover-foreground: oklch(0.141 0.005 285.823); 56 + --primary: oklch(0.21 0.006 285.885); 57 + --primary-foreground: oklch(0.985 0 0); 58 + --secondary: oklch(0.967 0.001 286.375); 59 + --secondary-foreground: oklch(0.21 0.006 285.885); 60 + --muted: oklch(0.967 0.001 286.375); 61 + --muted-foreground: oklch(0.552 0.016 285.938); 62 + --accent: oklch(0.967 0.001 286.375); 63 + --accent-foreground: oklch(0.21 0.006 285.885); 64 + --destructive: oklch(0.577 0.245 27.325); 65 + --border: oklch(0.92 0.004 286.32); 66 + --input: oklch(0.92 0.004 286.32); 67 + --ring: oklch(0.705 0.015 286.067); 68 + --bluesky: oklch(0.6462 0.1927 254.47); 69 + --bluesky-foreground: oklch(1 0 0); 70 + --chart-1: oklch(0.646 0.222 41.116); 71 + --chart-2: oklch(0.6 0.118 184.704); 72 + --chart-3: oklch(0.398 0.07 227.392); 73 + --chart-4: oklch(0.828 0.189 84.429); 74 + --chart-5: oklch(0.769 0.188 70.08); 75 + --sidebar: oklch(0.985 0 0); 76 + --sidebar-foreground: oklch(0.141 0.005 285.823); 77 + --sidebar-primary: oklch(0.21 0.006 285.885); 78 + --sidebar-primary-foreground: oklch(0.985 0 0); 79 + --sidebar-accent: oklch(0.967 0.001 286.375); 80 + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); 81 + --sidebar-border: oklch(0.92 0.004 286.32); 82 + --sidebar-ring: oklch(0.705 0.015 286.067); 83 + } 84 + 85 + .dark { 86 + --background: oklch(0.141 0.005 285.823); 87 + --foreground: oklch(0.985 0 0); 88 + --card: oklch(0.21 0.006 285.885); 89 + --card-foreground: oklch(0.985 0 0); 90 + --popover: oklch(0.21 0.006 285.885); 91 + --popover-foreground: oklch(0.985 0 0); 92 + --primary: oklch(0.92 0.004 286.32); 93 + --primary-foreground: oklch(0.21 0.006 285.885); 94 + --secondary: oklch(0.274 0.006 286.033); 95 + --secondary-foreground: oklch(0.985 0 0); 96 + --muted: oklch(0.274 0.006 286.033); 97 + --muted-foreground: oklch(0.705 0.015 286.067); 98 + --accent: oklch(0.274 0.006 286.033); 99 + --accent-foreground: oklch(0.985 0 0); 100 + --destructive: oklch(0.704 0.191 22.216); 101 + --border: oklch(1 0 0 / 10%); 102 + --input: oklch(1 0 0 / 15%); 103 + --ring: oklch(0.552 0.016 285.938); 104 + --chart-1: oklch(0.488 0.243 264.376); 105 + --chart-2: oklch(0.696 0.17 162.48); 106 + --chart-3: oklch(0.769 0.188 70.08); 107 + --chart-4: oklch(0.627 0.265 303.9); 108 + --chart-5: oklch(0.645 0.246 16.439); 109 + --sidebar: oklch(0.21 0.006 285.885); 110 + --sidebar-foreground: oklch(0.985 0 0); 111 + --sidebar-primary: oklch(0.488 0.243 264.376); 112 + --sidebar-primary-foreground: oklch(0.985 0 0); 113 + --sidebar-accent: oklch(0.274 0.006 286.033); 114 + --sidebar-accent-foreground: oklch(0.985 0 0); 115 + --sidebar-border: oklch(1 0 0 / 10%); 116 + --sidebar-ring: oklch(0.552 0.016 285.938); 117 + } 118 + 119 + @layer base { 120 + * { 121 + @apply border-border outline-ring/50; 122 + } 123 + body { 124 + @apply bg-background text-foreground; 125 + } 126 + }
+37
apps/app/app/layout.tsx
··· 1 + import type { Metadata } from "next"; 2 + import { Noto_Sans } from "next/font/google"; 3 + import Providers from './providers' 4 + import "./globals.css"; 5 + 6 + const notoSans = Noto_Sans({ 7 + variable: "--font-noto-sans", 8 + display: "swap", 9 + subsets: ["latin"], 10 + }); 11 + 12 + export const metadata: Metadata = { 13 + title: "Cookware", 14 + description: "tiny social platform for cooking and recipe sharing", 15 + metadataBase: new URL("https://cookware.social"), 16 + appleWebApp: { 17 + title: "Cookware", 18 + statusBarStyle: "black-translucent", 19 + capable: true, 20 + }, 21 + }; 22 + 23 + export default function RootLayout({ 24 + children, 25 + }: Readonly<{ 26 + children: React.ReactNode; 27 + }>) { 28 + return ( 29 + <html lang="en" className={`${notoSans.variable}`}> 30 + <body className="antialiased bg-sidebar text-foreground"> 31 + <Providers> 32 + {children} 33 + </Providers> 34 + </body> 35 + </html> 36 + ); 37 + }
+20
apps/app/app/manifest.json
··· 1 + { 2 + "name": "Cookware", 3 + "id": "cookware", 4 + "description": "An app to manage and share your recipes with the world.", 5 + "short_name": "Cookware", 6 + "start_url": "/home", 7 + "shortcuts": [ 8 + { 9 + "name": "New Recipe", 10 + "url": "/recipes/new" 11 + }, 12 + { 13 + "name": "New Cookbook", 14 + "url": "/books/new" 15 + } 16 + ], 17 + "theme_color": "#FFFFFF", 18 + "background_color": "#FFFFFF", 19 + "display": "standalone" 20 + }
+9
apps/app/app/not-found.tsx
··· 1 + import Layout from './(app)/layout'; 2 + 3 + export default () => { 4 + return ( 5 + <Layout> 6 + <>Not found</> 7 + </Layout> 8 + ); 9 + }
+43
apps/app/app/providers.tsx
··· 1 + 'use client'; 2 + 3 + import { isServer, QueryClient, QueryClientProvider } from "@tanstack/react-query"; 4 + import { PropsWithChildren } from "react"; 5 + import { ReactQueryDevtools } from "@tanstack/react-query-devtools"; 6 + import { ClientProvider } from "@/lib/state/query-provider"; 7 + import { AuthProvider } from "@/lib/state/auth"; 8 + 9 + const makeQueryClient = () => { 10 + return new QueryClient({ 11 + defaultOptions: { 12 + queries: { 13 + staleTime: 60 * 1000, // 1 minute 14 + }, 15 + } 16 + }); 17 + }; 18 + 19 + let browserQueryClient: QueryClient | undefined = undefined; 20 + 21 + const getQueryClient = () => { 22 + if (isServer) { 23 + return makeQueryClient(); 24 + } else { 25 + if (!browserQueryClient) browserQueryClient = makeQueryClient(); 26 + return browserQueryClient; 27 + } 28 + }; 29 + 30 + export default ({ children }: PropsWithChildren) => { 31 + const queryClient = getQueryClient(); 32 + 33 + return ( 34 + <ClientProvider> 35 + <AuthProvider> 36 + <QueryClientProvider client={queryClient}> 37 + {children} 38 + <ReactQueryDevtools /> 39 + </QueryClientProvider> 40 + </AuthProvider> 41 + </ClientProvider> 42 + ); 43 + }
+8
apps/app/app/route.tsx
··· 1 + import { redirect } from "next/navigation"; 2 + 3 + export const dynamic = "force-dynamic"; 4 + export const fetchCache = "force-no-store"; 5 + 6 + export async function GET() { 7 + redirect("/home"); 8 + }
+35
apps/app/components/app-sidebar/index.tsx
··· 1 + import { ComponentProps } from "react"; 2 + import Link from "next/link"; 3 + import { IconChefHat } from "@tabler/icons-react"; 4 + import { Sidebar, SidebarContent, SidebarFooter, SidebarHeader, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar"; 5 + import { NavMain } from "./nav-main"; 6 + import { NavSecondary } from "./nav-secondary"; 7 + import { NavAuth } from "./nav-auth"; 8 + 9 + export const AppSidebar = ({ ...props }: ComponentProps<typeof Sidebar>) => { 10 + return ( 11 + <Sidebar collapsible="offcanvas" {...props}> 12 + <SidebarHeader> 13 + <SidebarMenu> 14 + <SidebarMenuItem> 15 + <SidebarMenuButton asChild className="data-[slot=sidebar-menu-button]:!p-1.5"> 16 + <Link href="/home"> 17 + <IconChefHat className="!size-5" /> 18 + <span className="text-base font-semibold">Cookware</span> 19 + </Link> 20 + </SidebarMenuButton> 21 + </SidebarMenuItem> 22 + </SidebarMenu> 23 + </SidebarHeader> 24 + 25 + <SidebarContent> 26 + <NavMain /> 27 + <NavSecondary /> 28 + </SidebarContent> 29 + 30 + <SidebarFooter> 31 + <NavAuth /> 32 + </SidebarFooter> 33 + </Sidebar> 34 + ); 35 + };
+57
apps/app/components/app-sidebar/nav-auth.tsx
··· 1 + "use client"; 2 + 3 + import { IconBrandBluesky, IconArrowRight, IconDotsVertical } from "@tabler/icons-react"; 4 + import { SidebarMenuItem, SidebarMenuButton, SidebarMenu } from "../ui/sidebar"; 5 + import Link from "next/link"; 6 + import { useAuth } from "@/lib/state/auth"; 7 + import { redirect } from "next/navigation"; 8 + import { DropdownMenu, DropdownMenuTrigger } from "../ui/dropdown-menu"; 9 + import { Avatar, AvatarFallback, AvatarImage } from "../ui/avatar"; 10 + 11 + export const NavAuth = () => { 12 + const auth = useAuth(); 13 + 14 + if (auth.loggedIn) { 15 + if (auth.profile.exists) { 16 + return ( 17 + <SidebarMenu> 18 + <SidebarMenuItem className="flex items-center gap-2"> 19 + <DropdownMenu> 20 + <DropdownMenuTrigger asChild> 21 + <SidebarMenuButton size="lg" className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"> 22 + <Avatar className="h-8 w-8 rounded-lg"> 23 + <AvatarImage src={auth.profile.profileView.avatar} alt={auth.profile.profileView.displayName ?? auth.profile.profileView.handle} /> 24 + <AvatarFallback className="rounded-lg"> 25 + {auth.profile.profileView.handle.split('.').map(v => v[0]).join('')} 26 + </AvatarFallback> 27 + </Avatar> 28 + <div className="grid flex-1 text-left text-sm leading-tight"> 29 + <span className="truncate text-medium">{auth.profile.profileView.displayName ?? auth.profile.profileView.handle}</span> 30 + <span className="text-muted-foreground truncate text-cs">@{auth.profile.profileView.handle}</span> 31 + </div> 32 + <IconDotsVertical className="ml-auto size-4" /> 33 + </SidebarMenuButton> 34 + </DropdownMenuTrigger> 35 + </DropdownMenu> 36 + </SidebarMenuItem> 37 + </SidebarMenu> 38 + ); 39 + } else { 40 + throw redirect("/auth/signup"); 41 + } 42 + } else { 43 + return ( 44 + <SidebarMenu> 45 + <SidebarMenuItem className="flex items-center gap-2"> 46 + <SidebarMenuButton asChild size="lg" className="bg-bluesky text-bluesky-foreground hover:bg-bluesky/90 hover:text-bluesky-foreground min-w-8 duration-200 ease-linear"> 47 + <Link href="/auth/login"> 48 + <IconBrandBluesky className="!size-6" /> 49 + <span className="font-bold">Sign in with Bluesky</span> 50 + <IconArrowRight className="!size-5" /> 51 + </Link> 52 + </SidebarMenuButton> 53 + </SidebarMenuItem> 54 + </SidebarMenu> 55 + ); 56 + } 57 + }
+75
apps/app/components/app-sidebar/nav-main.tsx
··· 1 + import { IconCirclePlusFilled, IconBook, IconHome, IconSearch, IconCookie, IconUsers } from "@tabler/icons-react"; 2 + import { Button } from "../ui/button"; 3 + import { SidebarGroup, SidebarGroupContent, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar"; 4 + import Link from "next/link"; 5 + import { InputGroup, InputGroupAddon, InputGroupInput } from "../ui/input-group"; 6 + 7 + const items = [ 8 + { 9 + title: 'Home', 10 + icon: IconHome, 11 + url: '/home', 12 + }, 13 + { 14 + title: 'Recipes', 15 + icon: IconCookie, 16 + url: '/recipes', 17 + }, 18 + { 19 + title: 'Cookbooks', 20 + icon: IconBook, 21 + url: '/cookbooks', 22 + }, 23 + { 24 + title: 'Authors', 25 + icon: IconUsers, 26 + url: '/profiles', 27 + }, 28 + ]; 29 + 30 + export const NavMain = () => ( 31 + <SidebarGroup> 32 + <SidebarGroupContent className="flex flex-col gap-2"> 33 + <SidebarMenu className="flex flex-col gap-2"> 34 + <SidebarMenuItem className="flex items-center gap-2"> 35 + <SidebarMenuButton 36 + tooltip="Quick Create" 37 + className="bg-primary text-primary-foreground hover:bg-primary/90 hover:text-primary-foreground active:bg-primary/90 active:text-primary-foreground min-w-8 duration-200 ease-linear" 38 + > 39 + <IconCirclePlusFilled /> 40 + <span>Create Recipe</span> 41 + </SidebarMenuButton> 42 + 43 + <Button 44 + size="icon" 45 + className="size-8 group-data-[collapsible=icon]:opacity-0" 46 + variant="outline" 47 + > 48 + <IconBook /> 49 + <span className="sr-only">My Recipes</span> 50 + </Button> 51 + </SidebarMenuItem> 52 + <SidebarMenuItem> 53 + <InputGroup className="bg-background"> 54 + <InputGroupInput placeholder="Search" /> 55 + <InputGroupAddon> 56 + <IconSearch /> 57 + </InputGroupAddon> 58 + </InputGroup> 59 + </SidebarMenuItem> 60 + </SidebarMenu> 61 + <SidebarMenu> 62 + {items.map(item => ( 63 + <SidebarMenuItem key={item.title}> 64 + <SidebarMenuButton asChild> 65 + <Link href={item.url}> 66 + <item.icon /> 67 + <span>{item.title}</span> 68 + </Link> 69 + </SidebarMenuButton> 70 + </SidebarMenuItem> 71 + ))} 72 + </SidebarMenu> 73 + </SidebarGroupContent> 74 + </SidebarGroup> 75 + );
+38
apps/app/components/app-sidebar/nav-secondary.tsx
··· 1 + import { BLUESKY_PROFILE_URL, DISCORD_URL } from "@/lib/consts"; 2 + import { SidebarGroup, SidebarGroupContent, SidebarMenu, SidebarMenuButton, SidebarMenuItem } from "../ui/sidebar"; 3 + import { IconBrandBluesky, IconBrandDiscord } from "@tabler/icons-react"; 4 + import Link from "next/link"; 5 + 6 + const items = [ 7 + { 8 + icon: IconBrandBluesky, 9 + title: "Bluesky", 10 + url: BLUESKY_PROFILE_URL, 11 + }, 12 + { 13 + icon: IconBrandDiscord, 14 + title: "Discord", 15 + url: DISCORD_URL, 16 + } 17 + ]; 18 + 19 + export const NavSecondary = () => { 20 + return ( 21 + <SidebarGroup className="mt-auto"> 22 + <SidebarGroupContent> 23 + <SidebarMenu> 24 + {items.map(item => ( 25 + <SidebarMenuItem key={item.title}> 26 + <SidebarMenuButton asChild> 27 + <Link href={item.url}> 28 + <item.icon /> 29 + <span>{item.title}</span> 30 + </Link> 31 + </SidebarMenuButton> 32 + </SidebarMenuItem> 33 + ))} 34 + </SidebarMenu> 35 + </SidebarGroupContent> 36 + </SidebarGroup> 37 + ); 38 + };
+53
apps/app/components/ui/avatar.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import * as AvatarPrimitive from "@radix-ui/react-avatar" 5 + 6 + import { cn } from "@/lib/utils" 7 + 8 + function Avatar({ 9 + className, 10 + ...props 11 + }: React.ComponentProps<typeof AvatarPrimitive.Root>) { 12 + return ( 13 + <AvatarPrimitive.Root 14 + data-slot="avatar" 15 + className={cn( 16 + "relative flex size-8 shrink-0 overflow-hidden rounded-full", 17 + className 18 + )} 19 + {...props} 20 + /> 21 + ) 22 + } 23 + 24 + function AvatarImage({ 25 + className, 26 + ...props 27 + }: React.ComponentProps<typeof AvatarPrimitive.Image>) { 28 + return ( 29 + <AvatarPrimitive.Image 30 + data-slot="avatar-image" 31 + className={cn("aspect-square size-full", className)} 32 + {...props} 33 + /> 34 + ) 35 + } 36 + 37 + function AvatarFallback({ 38 + className, 39 + ...props 40 + }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) { 41 + return ( 42 + <AvatarPrimitive.Fallback 43 + data-slot="avatar-fallback" 44 + className={cn( 45 + "bg-muted flex size-full items-center justify-center rounded-full", 46 + className 47 + )} 48 + {...props} 49 + /> 50 + ) 51 + } 52 + 53 + export { Avatar, AvatarImage, AvatarFallback }
+60
apps/app/components/ui/button.tsx
··· 1 + import * as React from "react" 2 + import { Slot } from "@radix-ui/react-slot" 3 + import { cva, type VariantProps } from "class-variance-authority" 4 + 5 + import { cn } from "@/lib/utils" 6 + 7 + const buttonVariants = cva( 8 + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", 9 + { 10 + variants: { 11 + variant: { 12 + default: "bg-primary text-primary-foreground hover:bg-primary/90", 13 + destructive: 14 + "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", 15 + outline: 16 + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", 17 + secondary: 18 + "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 + ghost: 20 + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", 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 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", 26 + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", 27 + icon: "size-9", 28 + "icon-sm": "size-8", 29 + "icon-lg": "size-10", 30 + }, 31 + }, 32 + defaultVariants: { 33 + variant: "default", 34 + size: "default", 35 + }, 36 + } 37 + ) 38 + 39 + function Button({ 40 + className, 41 + variant, 42 + size, 43 + asChild = false, 44 + ...props 45 + }: React.ComponentProps<"button"> & 46 + VariantProps<typeof buttonVariants> & { 47 + asChild?: boolean 48 + }) { 49 + const Comp = asChild ? Slot : "button" 50 + 51 + return ( 52 + <Comp 53 + data-slot="button" 54 + className={cn(buttonVariants({ variant, size, className }))} 55 + {...props} 56 + /> 57 + ) 58 + } 59 + 60 + export { Button, buttonVariants }
+92
apps/app/components/ui/card.tsx
··· 1 + import * as React from "react" 2 + 3 + import { cn } from "@/lib/utils" 4 + 5 + function Card({ className, ...props }: React.ComponentProps<"div">) { 6 + return ( 7 + <div 8 + data-slot="card" 9 + className={cn( 10 + "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", 11 + className 12 + )} 13 + {...props} 14 + /> 15 + ) 16 + } 17 + 18 + function CardHeader({ className, ...props }: React.ComponentProps<"div">) { 19 + return ( 20 + <div 21 + data-slot="card-header" 22 + className={cn( 23 + "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", 24 + className 25 + )} 26 + {...props} 27 + /> 28 + ) 29 + } 30 + 31 + function CardTitle({ className, ...props }: React.ComponentProps<"div">) { 32 + return ( 33 + <div 34 + data-slot="card-title" 35 + className={cn("leading-none font-semibold", className)} 36 + {...props} 37 + /> 38 + ) 39 + } 40 + 41 + function CardDescription({ className, ...props }: React.ComponentProps<"div">) { 42 + return ( 43 + <div 44 + data-slot="card-description" 45 + className={cn("text-muted-foreground text-sm", className)} 46 + {...props} 47 + /> 48 + ) 49 + } 50 + 51 + function CardAction({ className, ...props }: React.ComponentProps<"div">) { 52 + return ( 53 + <div 54 + data-slot="card-action" 55 + className={cn( 56 + "col-start-2 row-span-2 row-start-1 self-start justify-self-end", 57 + className 58 + )} 59 + {...props} 60 + /> 61 + ) 62 + } 63 + 64 + function CardContent({ className, ...props }: React.ComponentProps<"div">) { 65 + return ( 66 + <div 67 + data-slot="card-content" 68 + className={cn("px-6", className)} 69 + {...props} 70 + /> 71 + ) 72 + } 73 + 74 + function CardFooter({ className, ...props }: React.ComponentProps<"div">) { 75 + return ( 76 + <div 77 + data-slot="card-footer" 78 + className={cn("flex items-center px-6 [.border-t]:pt-6", className)} 79 + {...props} 80 + /> 81 + ) 82 + } 83 + 84 + export { 85 + Card, 86 + CardHeader, 87 + CardFooter, 88 + CardTitle, 89 + CardAction, 90 + CardDescription, 91 + CardContent, 92 + }
+257
apps/app/components/ui/dropdown-menu.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" 5 + import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" 6 + 7 + import { cn } from "@/lib/utils" 8 + 9 + function DropdownMenu({ 10 + ...props 11 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) { 12 + return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} /> 13 + } 14 + 15 + function DropdownMenuPortal({ 16 + ...props 17 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) { 18 + return ( 19 + <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} /> 20 + ) 21 + } 22 + 23 + function DropdownMenuTrigger({ 24 + ...props 25 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) { 26 + return ( 27 + <DropdownMenuPrimitive.Trigger 28 + data-slot="dropdown-menu-trigger" 29 + {...props} 30 + /> 31 + ) 32 + } 33 + 34 + function DropdownMenuContent({ 35 + className, 36 + sideOffset = 4, 37 + ...props 38 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) { 39 + return ( 40 + <DropdownMenuPrimitive.Portal> 41 + <DropdownMenuPrimitive.Content 42 + data-slot="dropdown-menu-content" 43 + sideOffset={sideOffset} 44 + className={cn( 45 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", 46 + className 47 + )} 48 + {...props} 49 + /> 50 + </DropdownMenuPrimitive.Portal> 51 + ) 52 + } 53 + 54 + function DropdownMenuGroup({ 55 + ...props 56 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) { 57 + return ( 58 + <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} /> 59 + ) 60 + } 61 + 62 + function DropdownMenuItem({ 63 + className, 64 + inset, 65 + variant = "default", 66 + ...props 67 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & { 68 + inset?: boolean 69 + variant?: "default" | "destructive" 70 + }) { 71 + return ( 72 + <DropdownMenuPrimitive.Item 73 + data-slot="dropdown-menu-item" 74 + data-inset={inset} 75 + data-variant={variant} 76 + className={cn( 77 + "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 78 + className 79 + )} 80 + {...props} 81 + /> 82 + ) 83 + } 84 + 85 + function DropdownMenuCheckboxItem({ 86 + className, 87 + children, 88 + checked, 89 + ...props 90 + }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) { 91 + return ( 92 + <DropdownMenuPrimitive.CheckboxItem 93 + data-slot="dropdown-menu-checkbox-item" 94 + className={cn( 95 + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 96 + className 97 + )} 98 + checked={checked} 99 + {...props} 100 + > 101 + <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center"> 102 + <DropdownMenuPrimitive.ItemIndicator> 103 + <CheckIcon className="size-4" /> 104 + </DropdownMenuPrimitive.ItemIndicator> 105 + </span> 106 + {children} 107 + </DropdownMenuPrimitive.CheckboxItem> 108 + ) 109 + } 110 + 111 + function DropdownMenuRadioGroup({ 112 + ...props 113 + }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) { 114 + return ( 115 + <DropdownMenuPrimitive.RadioGroup 116 + data-slot="dropdown-menu-radio-group" 117 + {...props} 118 + /> 119 + ) 120 + } 121 + 122 + function DropdownMenuRadioItem({ 123 + className, 124 + children, 125 + ...props 126 + }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) { 127 + return ( 128 + <DropdownMenuPrimitive.RadioItem 129 + data-slot="dropdown-menu-radio-item" 130 + className={cn( 131 + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 132 + className 133 + )} 134 + {...props} 135 + > 136 + <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center"> 137 + <DropdownMenuPrimitive.ItemIndicator> 138 + <CircleIcon className="size-2 fill-current" /> 139 + </DropdownMenuPrimitive.ItemIndicator> 140 + </span> 141 + {children} 142 + </DropdownMenuPrimitive.RadioItem> 143 + ) 144 + } 145 + 146 + function DropdownMenuLabel({ 147 + className, 148 + inset, 149 + ...props 150 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & { 151 + inset?: boolean 152 + }) { 153 + return ( 154 + <DropdownMenuPrimitive.Label 155 + data-slot="dropdown-menu-label" 156 + data-inset={inset} 157 + className={cn( 158 + "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8", 159 + className 160 + )} 161 + {...props} 162 + /> 163 + ) 164 + } 165 + 166 + function DropdownMenuSeparator({ 167 + className, 168 + ...props 169 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) { 170 + return ( 171 + <DropdownMenuPrimitive.Separator 172 + data-slot="dropdown-menu-separator" 173 + className={cn("bg-border -mx-1 my-1 h-px", className)} 174 + {...props} 175 + /> 176 + ) 177 + } 178 + 179 + function DropdownMenuShortcut({ 180 + className, 181 + ...props 182 + }: React.ComponentProps<"span">) { 183 + return ( 184 + <span 185 + data-slot="dropdown-menu-shortcut" 186 + className={cn( 187 + "text-muted-foreground ml-auto text-xs tracking-widest", 188 + className 189 + )} 190 + {...props} 191 + /> 192 + ) 193 + } 194 + 195 + function DropdownMenuSub({ 196 + ...props 197 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) { 198 + return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} /> 199 + } 200 + 201 + function DropdownMenuSubTrigger({ 202 + className, 203 + inset, 204 + children, 205 + ...props 206 + }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & { 207 + inset?: boolean 208 + }) { 209 + return ( 210 + <DropdownMenuPrimitive.SubTrigger 211 + data-slot="dropdown-menu-sub-trigger" 212 + data-inset={inset} 213 + className={cn( 214 + "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 215 + className 216 + )} 217 + {...props} 218 + > 219 + {children} 220 + <ChevronRightIcon className="ml-auto size-4" /> 221 + </DropdownMenuPrimitive.SubTrigger> 222 + ) 223 + } 224 + 225 + function DropdownMenuSubContent({ 226 + className, 227 + ...props 228 + }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) { 229 + return ( 230 + <DropdownMenuPrimitive.SubContent 231 + data-slot="dropdown-menu-sub-content" 232 + className={cn( 233 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg", 234 + className 235 + )} 236 + {...props} 237 + /> 238 + ) 239 + } 240 + 241 + export { 242 + DropdownMenu, 243 + DropdownMenuPortal, 244 + DropdownMenuTrigger, 245 + DropdownMenuContent, 246 + DropdownMenuGroup, 247 + DropdownMenuLabel, 248 + DropdownMenuItem, 249 + DropdownMenuCheckboxItem, 250 + DropdownMenuRadioGroup, 251 + DropdownMenuRadioItem, 252 + DropdownMenuSeparator, 253 + DropdownMenuShortcut, 254 + DropdownMenuSub, 255 + DropdownMenuSubTrigger, 256 + DropdownMenuSubContent, 257 + }
+248
apps/app/components/ui/field.tsx
··· 1 + "use client" 2 + 3 + import { useMemo } from "react" 4 + import { cva, type VariantProps } from "class-variance-authority" 5 + 6 + import { cn } from "@/lib/utils" 7 + import { Label } from "@/components/ui/label" 8 + import { Separator } from "@/components/ui/separator" 9 + 10 + function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { 11 + return ( 12 + <fieldset 13 + data-slot="field-set" 14 + className={cn( 15 + "flex flex-col gap-6", 16 + "has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", 17 + className 18 + )} 19 + {...props} 20 + /> 21 + ) 22 + } 23 + 24 + function FieldLegend({ 25 + className, 26 + variant = "legend", 27 + ...props 28 + }: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) { 29 + return ( 30 + <legend 31 + data-slot="field-legend" 32 + data-variant={variant} 33 + className={cn( 34 + "mb-3 font-medium", 35 + "data-[variant=legend]:text-base", 36 + "data-[variant=label]:text-sm", 37 + className 38 + )} 39 + {...props} 40 + /> 41 + ) 42 + } 43 + 44 + function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { 45 + return ( 46 + <div 47 + data-slot="field-group" 48 + className={cn( 49 + "group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4", 50 + className 51 + )} 52 + {...props} 53 + /> 54 + ) 55 + } 56 + 57 + const fieldVariants = cva( 58 + "group/field flex w-full gap-3 data-[invalid=true]:text-destructive", 59 + { 60 + variants: { 61 + orientation: { 62 + vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"], 63 + horizontal: [ 64 + "flex-row items-center", 65 + "[&>[data-slot=field-label]]:flex-auto", 66 + "has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", 67 + ], 68 + responsive: [ 69 + "flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto", 70 + "@md/field-group:[&>[data-slot=field-label]]:flex-auto", 71 + "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", 72 + ], 73 + }, 74 + }, 75 + defaultVariants: { 76 + orientation: "vertical", 77 + }, 78 + } 79 + ) 80 + 81 + function Field({ 82 + className, 83 + orientation = "vertical", 84 + ...props 85 + }: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) { 86 + return ( 87 + <div 88 + role="group" 89 + data-slot="field" 90 + data-orientation={orientation} 91 + className={cn(fieldVariants({ orientation }), className)} 92 + {...props} 93 + /> 94 + ) 95 + } 96 + 97 + function FieldContent({ className, ...props }: React.ComponentProps<"div">) { 98 + return ( 99 + <div 100 + data-slot="field-content" 101 + className={cn( 102 + "group/field-content flex flex-1 flex-col gap-1.5 leading-snug", 103 + className 104 + )} 105 + {...props} 106 + /> 107 + ) 108 + } 109 + 110 + function FieldLabel({ 111 + className, 112 + ...props 113 + }: React.ComponentProps<typeof Label>) { 114 + return ( 115 + <Label 116 + data-slot="field-label" 117 + className={cn( 118 + "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50", 119 + "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4", 120 + "has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10", 121 + className 122 + )} 123 + {...props} 124 + /> 125 + ) 126 + } 127 + 128 + function FieldTitle({ className, ...props }: React.ComponentProps<"div">) { 129 + return ( 130 + <div 131 + data-slot="field-label" 132 + className={cn( 133 + "flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50", 134 + className 135 + )} 136 + {...props} 137 + /> 138 + ) 139 + } 140 + 141 + function FieldDescription({ className, ...props }: React.ComponentProps<"p">) { 142 + return ( 143 + <p 144 + data-slot="field-description" 145 + className={cn( 146 + "text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance", 147 + "last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5", 148 + "[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", 149 + className 150 + )} 151 + {...props} 152 + /> 153 + ) 154 + } 155 + 156 + function FieldSeparator({ 157 + children, 158 + className, 159 + ...props 160 + }: React.ComponentProps<"div"> & { 161 + children?: React.ReactNode 162 + }) { 163 + return ( 164 + <div 165 + data-slot="field-separator" 166 + data-content={!!children} 167 + className={cn( 168 + "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2", 169 + className 170 + )} 171 + {...props} 172 + > 173 + <Separator className="absolute inset-0 top-1/2" /> 174 + {children && ( 175 + <span 176 + className="bg-background text-muted-foreground relative mx-auto block w-fit px-2" 177 + data-slot="field-separator-content" 178 + > 179 + {children} 180 + </span> 181 + )} 182 + </div> 183 + ) 184 + } 185 + 186 + function FieldError({ 187 + className, 188 + children, 189 + errors, 190 + ...props 191 + }: React.ComponentProps<"div"> & { 192 + errors?: Array<{ message?: string } | undefined> 193 + }) { 194 + const content = useMemo(() => { 195 + if (children) { 196 + return children 197 + } 198 + 199 + if (!errors?.length) { 200 + return null 201 + } 202 + 203 + const uniqueErrors = [ 204 + ...new Map(errors.map((error) => [error?.message, error])).values(), 205 + ] 206 + 207 + if (uniqueErrors?.length == 1) { 208 + return uniqueErrors[0]?.message 209 + } 210 + 211 + return ( 212 + <ul className="ml-4 flex list-disc flex-col gap-1"> 213 + {uniqueErrors.map( 214 + (error, index) => 215 + error?.message && <li key={index}>{error.message}</li> 216 + )} 217 + </ul> 218 + ) 219 + }, [children, errors]) 220 + 221 + if (!content) { 222 + return null 223 + } 224 + 225 + return ( 226 + <div 227 + role="alert" 228 + data-slot="field-error" 229 + className={cn("text-destructive text-sm font-normal", className)} 230 + {...props} 231 + > 232 + {content} 233 + </div> 234 + ) 235 + } 236 + 237 + export { 238 + Field, 239 + FieldLabel, 240 + FieldDescription, 241 + FieldError, 242 + FieldGroup, 243 + FieldLegend, 244 + FieldSeparator, 245 + FieldSet, 246 + FieldContent, 247 + FieldTitle, 248 + }
+170
apps/app/components/ui/input-group.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { cva, type VariantProps } from "class-variance-authority" 5 + 6 + import { cn } from "@/lib/utils" 7 + import { Button } from "@/components/ui/button" 8 + import { Input } from "@/components/ui/input" 9 + import { Textarea } from "@/components/ui/textarea" 10 + 11 + function InputGroup({ className, ...props }: React.ComponentProps<"div">) { 12 + return ( 13 + <div 14 + data-slot="input-group" 15 + role="group" 16 + className={cn( 17 + "group/input-group border-input dark:bg-input/30 relative flex w-full items-center rounded-md border shadow-xs transition-[color,box-shadow] outline-none", 18 + "h-9 min-w-0 has-[>textarea]:h-auto", 19 + 20 + // Variants based on alignment. 21 + "has-[>[data-align=inline-start]]:[&>input]:pl-2", 22 + "has-[>[data-align=inline-end]]:[&>input]:pr-2", 23 + "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3", 24 + "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3", 25 + 26 + // Focus state. 27 + "has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]", 28 + 29 + // Error state. 30 + "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40", 31 + 32 + className 33 + )} 34 + {...props} 35 + /> 36 + ) 37 + } 38 + 39 + const inputGroupAddonVariants = cva( 40 + "text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium select-none [&>svg:not([class*='size-'])]:size-4 [&>kbd]:rounded-[calc(var(--radius)-5px)] group-data-[disabled=true]/input-group:opacity-50", 41 + { 42 + variants: { 43 + align: { 44 + "inline-start": 45 + "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]", 46 + "inline-end": 47 + "order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]", 48 + "block-start": 49 + "order-first w-full justify-start px-3 pt-3 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5", 50 + "block-end": 51 + "order-last w-full justify-start px-3 pb-3 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5", 52 + }, 53 + }, 54 + defaultVariants: { 55 + align: "inline-start", 56 + }, 57 + } 58 + ) 59 + 60 + function InputGroupAddon({ 61 + className, 62 + align = "inline-start", 63 + ...props 64 + }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) { 65 + return ( 66 + <div 67 + role="group" 68 + data-slot="input-group-addon" 69 + data-align={align} 70 + className={cn(inputGroupAddonVariants({ align }), className)} 71 + onClick={(e) => { 72 + if ((e.target as HTMLElement).closest("button")) { 73 + return 74 + } 75 + e.currentTarget.parentElement?.querySelector("input")?.focus() 76 + }} 77 + {...props} 78 + /> 79 + ) 80 + } 81 + 82 + const inputGroupButtonVariants = cva( 83 + "text-sm shadow-none flex gap-2 items-center", 84 + { 85 + variants: { 86 + size: { 87 + xs: "h-6 gap-1 px-2 rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2", 88 + sm: "h-8 px-2.5 gap-1.5 rounded-md has-[>svg]:px-2.5", 89 + "icon-xs": 90 + "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0", 91 + "icon-sm": "size-8 p-0 has-[>svg]:p-0", 92 + }, 93 + }, 94 + defaultVariants: { 95 + size: "xs", 96 + }, 97 + } 98 + ) 99 + 100 + function InputGroupButton({ 101 + className, 102 + type = "button", 103 + variant = "ghost", 104 + size = "xs", 105 + ...props 106 + }: Omit<React.ComponentProps<typeof Button>, "size"> & 107 + VariantProps<typeof inputGroupButtonVariants>) { 108 + return ( 109 + <Button 110 + type={type} 111 + data-size={size} 112 + variant={variant} 113 + className={cn(inputGroupButtonVariants({ size }), className)} 114 + {...props} 115 + /> 116 + ) 117 + } 118 + 119 + function InputGroupText({ className, ...props }: React.ComponentProps<"span">) { 120 + return ( 121 + <span 122 + className={cn( 123 + "text-muted-foreground flex items-center gap-2 text-sm [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", 124 + className 125 + )} 126 + {...props} 127 + /> 128 + ) 129 + } 130 + 131 + function InputGroupInput({ 132 + className, 133 + ...props 134 + }: React.ComponentProps<"input">) { 135 + return ( 136 + <Input 137 + data-slot="input-group-control" 138 + className={cn( 139 + "flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent", 140 + className 141 + )} 142 + {...props} 143 + /> 144 + ) 145 + } 146 + 147 + function InputGroupTextarea({ 148 + className, 149 + ...props 150 + }: React.ComponentProps<"textarea">) { 151 + return ( 152 + <Textarea 153 + data-slot="input-group-control" 154 + className={cn( 155 + "flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent", 156 + className 157 + )} 158 + {...props} 159 + /> 160 + ) 161 + } 162 + 163 + export { 164 + InputGroup, 165 + InputGroupAddon, 166 + InputGroupButton, 167 + InputGroupText, 168 + InputGroupInput, 169 + InputGroupTextarea, 170 + }
+21
apps/app/components/ui/input.tsx
··· 1 + import * as React from "react" 2 + 3 + import { cn } from "@/lib/utils" 4 + 5 + function Input({ className, type, ...props }: React.ComponentProps<"input">) { 6 + return ( 7 + <input 8 + type={type} 9 + data-slot="input" 10 + className={cn( 11 + "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", 12 + "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", 13 + "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", 14 + className 15 + )} 16 + {...props} 17 + /> 18 + ) 19 + } 20 + 21 + export { Input }
+24
apps/app/components/ui/label.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import * as LabelPrimitive from "@radix-ui/react-label" 5 + 6 + import { cn } from "@/lib/utils" 7 + 8 + function Label({ 9 + className, 10 + ...props 11 + }: React.ComponentProps<typeof LabelPrimitive.Root>) { 12 + return ( 13 + <LabelPrimitive.Root 14 + data-slot="label" 15 + className={cn( 16 + "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", 17 + className 18 + )} 19 + {...props} 20 + /> 21 + ) 22 + } 23 + 24 + export { Label }
+28
apps/app/components/ui/separator.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import * as SeparatorPrimitive from "@radix-ui/react-separator" 5 + 6 + import { cn } from "@/lib/utils" 7 + 8 + function Separator({ 9 + className, 10 + orientation = "horizontal", 11 + decorative = true, 12 + ...props 13 + }: React.ComponentProps<typeof SeparatorPrimitive.Root>) { 14 + return ( 15 + <SeparatorPrimitive.Root 16 + data-slot="separator" 17 + decorative={decorative} 18 + orientation={orientation} 19 + className={cn( 20 + "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", 21 + className 22 + )} 23 + {...props} 24 + /> 25 + ) 26 + } 27 + 28 + export { Separator }
+139
apps/app/components/ui/sheet.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import * as SheetPrimitive from "@radix-ui/react-dialog" 5 + import { XIcon } from "lucide-react" 6 + 7 + import { cn } from "@/lib/utils" 8 + 9 + function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) { 10 + return <SheetPrimitive.Root data-slot="sheet" {...props} /> 11 + } 12 + 13 + function SheetTrigger({ 14 + ...props 15 + }: React.ComponentProps<typeof SheetPrimitive.Trigger>) { 16 + return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} /> 17 + } 18 + 19 + function SheetClose({ 20 + ...props 21 + }: React.ComponentProps<typeof SheetPrimitive.Close>) { 22 + return <SheetPrimitive.Close data-slot="sheet-close" {...props} /> 23 + } 24 + 25 + function SheetPortal({ 26 + ...props 27 + }: React.ComponentProps<typeof SheetPrimitive.Portal>) { 28 + return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} /> 29 + } 30 + 31 + function SheetOverlay({ 32 + className, 33 + ...props 34 + }: React.ComponentProps<typeof SheetPrimitive.Overlay>) { 35 + return ( 36 + <SheetPrimitive.Overlay 37 + data-slot="sheet-overlay" 38 + className={cn( 39 + "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", 40 + className 41 + )} 42 + {...props} 43 + /> 44 + ) 45 + } 46 + 47 + function SheetContent({ 48 + className, 49 + children, 50 + side = "right", 51 + ...props 52 + }: React.ComponentProps<typeof SheetPrimitive.Content> & { 53 + side?: "top" | "right" | "bottom" | "left" 54 + }) { 55 + return ( 56 + <SheetPortal> 57 + <SheetOverlay /> 58 + <SheetPrimitive.Content 59 + data-slot="sheet-content" 60 + className={cn( 61 + "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500", 62 + side === "right" && 63 + "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm", 64 + side === "left" && 65 + "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm", 66 + side === "top" && 67 + "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b", 68 + side === "bottom" && 69 + "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t", 70 + className 71 + )} 72 + {...props} 73 + > 74 + {children} 75 + <SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none"> 76 + <XIcon className="size-4" /> 77 + <span className="sr-only">Close</span> 78 + </SheetPrimitive.Close> 79 + </SheetPrimitive.Content> 80 + </SheetPortal> 81 + ) 82 + } 83 + 84 + function SheetHeader({ className, ...props }: React.ComponentProps<"div">) { 85 + return ( 86 + <div 87 + data-slot="sheet-header" 88 + className={cn("flex flex-col gap-1.5 p-4", className)} 89 + {...props} 90 + /> 91 + ) 92 + } 93 + 94 + function SheetFooter({ className, ...props }: React.ComponentProps<"div">) { 95 + return ( 96 + <div 97 + data-slot="sheet-footer" 98 + className={cn("mt-auto flex flex-col gap-2 p-4", className)} 99 + {...props} 100 + /> 101 + ) 102 + } 103 + 104 + function SheetTitle({ 105 + className, 106 + ...props 107 + }: React.ComponentProps<typeof SheetPrimitive.Title>) { 108 + return ( 109 + <SheetPrimitive.Title 110 + data-slot="sheet-title" 111 + className={cn("text-foreground font-semibold", className)} 112 + {...props} 113 + /> 114 + ) 115 + } 116 + 117 + function SheetDescription({ 118 + className, 119 + ...props 120 + }: React.ComponentProps<typeof SheetPrimitive.Description>) { 121 + return ( 122 + <SheetPrimitive.Description 123 + data-slot="sheet-description" 124 + className={cn("text-muted-foreground text-sm", className)} 125 + {...props} 126 + /> 127 + ) 128 + } 129 + 130 + export { 131 + Sheet, 132 + SheetTrigger, 133 + SheetClose, 134 + SheetContent, 135 + SheetHeader, 136 + SheetFooter, 137 + SheetTitle, 138 + SheetDescription, 139 + }
+726
apps/app/components/ui/sidebar.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import { Slot } from "@radix-ui/react-slot" 5 + import { cva, type VariantProps } from "class-variance-authority" 6 + import { PanelLeftIcon } from "lucide-react" 7 + 8 + import { useIsMobile } from "@/hooks/use-mobile" 9 + import { cn } from "@/lib/utils" 10 + import { Button } from "@/components/ui/button" 11 + import { Input } from "@/components/ui/input" 12 + import { Separator } from "@/components/ui/separator" 13 + import { 14 + Sheet, 15 + SheetContent, 16 + SheetDescription, 17 + SheetHeader, 18 + SheetTitle, 19 + } from "@/components/ui/sheet" 20 + import { Skeleton } from "@/components/ui/skeleton" 21 + import { 22 + Tooltip, 23 + TooltipContent, 24 + TooltipProvider, 25 + TooltipTrigger, 26 + } from "@/components/ui/tooltip" 27 + 28 + const SIDEBAR_COOKIE_NAME = "sidebar_state" 29 + const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 30 + const SIDEBAR_WIDTH = "16rem" 31 + const SIDEBAR_WIDTH_MOBILE = "18rem" 32 + const SIDEBAR_WIDTH_ICON = "3rem" 33 + const SIDEBAR_KEYBOARD_SHORTCUT = "b" 34 + 35 + type SidebarContextProps = { 36 + state: "expanded" | "collapsed" 37 + open: boolean 38 + setOpen: (open: boolean) => void 39 + openMobile: boolean 40 + setOpenMobile: (open: boolean) => void 41 + isMobile: boolean 42 + toggleSidebar: () => void 43 + } 44 + 45 + const SidebarContext = React.createContext<SidebarContextProps | null>(null) 46 + 47 + function useSidebar() { 48 + const context = React.useContext(SidebarContext) 49 + if (!context) { 50 + throw new Error("useSidebar must be used within a SidebarProvider.") 51 + } 52 + 53 + return context 54 + } 55 + 56 + function SidebarProvider({ 57 + defaultOpen = true, 58 + open: openProp, 59 + onOpenChange: setOpenProp, 60 + className, 61 + style, 62 + children, 63 + ...props 64 + }: React.ComponentProps<"div"> & { 65 + defaultOpen?: boolean 66 + open?: boolean 67 + onOpenChange?: (open: boolean) => void 68 + }) { 69 + const isMobile = useIsMobile() 70 + const [openMobile, setOpenMobile] = React.useState(false) 71 + 72 + // This is the internal state of the sidebar. 73 + // We use openProp and setOpenProp for control from outside the component. 74 + const [_open, _setOpen] = React.useState(defaultOpen) 75 + const open = openProp ?? _open 76 + const setOpen = React.useCallback( 77 + (value: boolean | ((value: boolean) => boolean)) => { 78 + const openState = typeof value === "function" ? value(open) : value 79 + if (setOpenProp) { 80 + setOpenProp(openState) 81 + } else { 82 + _setOpen(openState) 83 + } 84 + 85 + // This sets the cookie to keep the sidebar state. 86 + document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` 87 + }, 88 + [setOpenProp, open] 89 + ) 90 + 91 + // Helper to toggle the sidebar. 92 + const toggleSidebar = React.useCallback(() => { 93 + return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open) 94 + }, [isMobile, setOpen, setOpenMobile]) 95 + 96 + // Adds a keyboard shortcut to toggle the sidebar. 97 + React.useEffect(() => { 98 + const handleKeyDown = (event: KeyboardEvent) => { 99 + if ( 100 + event.key === SIDEBAR_KEYBOARD_SHORTCUT && 101 + (event.metaKey || event.ctrlKey) 102 + ) { 103 + event.preventDefault() 104 + toggleSidebar() 105 + } 106 + } 107 + 108 + window.addEventListener("keydown", handleKeyDown) 109 + return () => window.removeEventListener("keydown", handleKeyDown) 110 + }, [toggleSidebar]) 111 + 112 + // We add a state so that we can do data-state="expanded" or "collapsed". 113 + // This makes it easier to style the sidebar with Tailwind classes. 114 + const state = open ? "expanded" : "collapsed" 115 + 116 + const contextValue = React.useMemo<SidebarContextProps>( 117 + () => ({ 118 + state, 119 + open, 120 + setOpen, 121 + isMobile, 122 + openMobile, 123 + setOpenMobile, 124 + toggleSidebar, 125 + }), 126 + [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar] 127 + ) 128 + 129 + return ( 130 + <SidebarContext.Provider value={contextValue}> 131 + <TooltipProvider delayDuration={0}> 132 + <div 133 + data-slot="sidebar-wrapper" 134 + style={ 135 + { 136 + "--sidebar-width": SIDEBAR_WIDTH, 137 + "--sidebar-width-icon": SIDEBAR_WIDTH_ICON, 138 + ...style, 139 + } as React.CSSProperties 140 + } 141 + className={cn( 142 + "group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full", 143 + className 144 + )} 145 + {...props} 146 + > 147 + {children} 148 + </div> 149 + </TooltipProvider> 150 + </SidebarContext.Provider> 151 + ) 152 + } 153 + 154 + function Sidebar({ 155 + side = "left", 156 + variant = "sidebar", 157 + collapsible = "offcanvas", 158 + className, 159 + children, 160 + ...props 161 + }: React.ComponentProps<"div"> & { 162 + side?: "left" | "right" 163 + variant?: "sidebar" | "floating" | "inset" 164 + collapsible?: "offcanvas" | "icon" | "none" 165 + }) { 166 + const { isMobile, state, openMobile, setOpenMobile } = useSidebar() 167 + 168 + if (collapsible === "none") { 169 + return ( 170 + <div 171 + data-slot="sidebar" 172 + className={cn( 173 + "bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col", 174 + className 175 + )} 176 + {...props} 177 + > 178 + {children} 179 + </div> 180 + ) 181 + } 182 + 183 + if (isMobile) { 184 + return ( 185 + <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}> 186 + <SheetContent 187 + data-sidebar="sidebar" 188 + data-slot="sidebar" 189 + data-mobile="true" 190 + className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden" 191 + style={ 192 + { 193 + "--sidebar-width": SIDEBAR_WIDTH_MOBILE, 194 + } as React.CSSProperties 195 + } 196 + side={side} 197 + > 198 + <SheetHeader className="sr-only"> 199 + <SheetTitle>Sidebar</SheetTitle> 200 + <SheetDescription>Displays the mobile sidebar.</SheetDescription> 201 + </SheetHeader> 202 + <div className="flex h-full w-full flex-col">{children}</div> 203 + </SheetContent> 204 + </Sheet> 205 + ) 206 + } 207 + 208 + return ( 209 + <div 210 + className="group peer text-sidebar-foreground hidden md:block" 211 + data-state={state} 212 + data-collapsible={state === "collapsed" ? collapsible : ""} 213 + data-variant={variant} 214 + data-side={side} 215 + data-slot="sidebar" 216 + > 217 + {/* This is what handles the sidebar gap on desktop */} 218 + <div 219 + data-slot="sidebar-gap" 220 + className={cn( 221 + "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear", 222 + "group-data-[collapsible=offcanvas]:w-0", 223 + "group-data-[side=right]:rotate-180", 224 + variant === "floating" || variant === "inset" 225 + ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" 226 + : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)" 227 + )} 228 + /> 229 + <div 230 + data-slot="sidebar-container" 231 + className={cn( 232 + "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex", 233 + side === "left" 234 + ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" 235 + : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", 236 + // Adjust the padding for floating and inset variants. 237 + variant === "floating" || variant === "inset" 238 + ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" 239 + : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", 240 + className 241 + )} 242 + {...props} 243 + > 244 + <div 245 + data-sidebar="sidebar" 246 + data-slot="sidebar-inner" 247 + className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm" 248 + > 249 + {children} 250 + </div> 251 + </div> 252 + </div> 253 + ) 254 + } 255 + 256 + function SidebarTrigger({ 257 + className, 258 + onClick, 259 + ...props 260 + }: React.ComponentProps<typeof Button>) { 261 + const { toggleSidebar } = useSidebar() 262 + 263 + return ( 264 + <Button 265 + data-sidebar="trigger" 266 + data-slot="sidebar-trigger" 267 + variant="ghost" 268 + size="icon" 269 + className={cn("size-7", className)} 270 + onClick={(event) => { 271 + onClick?.(event) 272 + toggleSidebar() 273 + }} 274 + {...props} 275 + > 276 + <PanelLeftIcon /> 277 + <span className="sr-only">Toggle Sidebar</span> 278 + </Button> 279 + ) 280 + } 281 + 282 + function SidebarRail({ className, ...props }: React.ComponentProps<"button">) { 283 + const { toggleSidebar } = useSidebar() 284 + 285 + return ( 286 + <button 287 + data-sidebar="rail" 288 + data-slot="sidebar-rail" 289 + aria-label="Toggle Sidebar" 290 + tabIndex={-1} 291 + onClick={toggleSidebar} 292 + title="Toggle Sidebar" 293 + className={cn( 294 + "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex", 295 + "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", 296 + "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", 297 + "hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full", 298 + "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", 299 + "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", 300 + className 301 + )} 302 + {...props} 303 + /> 304 + ) 305 + } 306 + 307 + function SidebarInset({ className, ...props }: React.ComponentProps<"main">) { 308 + return ( 309 + <main 310 + data-slot="sidebar-inset" 311 + className={cn( 312 + "bg-background relative flex w-full flex-1 flex-col", 313 + "md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2", 314 + className 315 + )} 316 + {...props} 317 + /> 318 + ) 319 + } 320 + 321 + function SidebarInput({ 322 + className, 323 + ...props 324 + }: React.ComponentProps<typeof Input>) { 325 + return ( 326 + <Input 327 + data-slot="sidebar-input" 328 + data-sidebar="input" 329 + className={cn("bg-background h-8 w-full shadow-none", className)} 330 + {...props} 331 + /> 332 + ) 333 + } 334 + 335 + function SidebarHeader({ className, ...props }: React.ComponentProps<"div">) { 336 + return ( 337 + <div 338 + data-slot="sidebar-header" 339 + data-sidebar="header" 340 + className={cn("flex flex-col gap-2 p-2", className)} 341 + {...props} 342 + /> 343 + ) 344 + } 345 + 346 + function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) { 347 + return ( 348 + <div 349 + data-slot="sidebar-footer" 350 + data-sidebar="footer" 351 + className={cn("flex flex-col gap-2 p-2", className)} 352 + {...props} 353 + /> 354 + ) 355 + } 356 + 357 + function SidebarSeparator({ 358 + className, 359 + ...props 360 + }: React.ComponentProps<typeof Separator>) { 361 + return ( 362 + <Separator 363 + data-slot="sidebar-separator" 364 + data-sidebar="separator" 365 + className={cn("bg-sidebar-border mx-2 w-auto", className)} 366 + {...props} 367 + /> 368 + ) 369 + } 370 + 371 + function SidebarContent({ className, ...props }: React.ComponentProps<"div">) { 372 + return ( 373 + <div 374 + data-slot="sidebar-content" 375 + data-sidebar="content" 376 + className={cn( 377 + "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", 378 + className 379 + )} 380 + {...props} 381 + /> 382 + ) 383 + } 384 + 385 + function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) { 386 + return ( 387 + <div 388 + data-slot="sidebar-group" 389 + data-sidebar="group" 390 + className={cn("relative flex w-full min-w-0 flex-col p-2", className)} 391 + {...props} 392 + /> 393 + ) 394 + } 395 + 396 + function SidebarGroupLabel({ 397 + className, 398 + asChild = false, 399 + ...props 400 + }: React.ComponentProps<"div"> & { asChild?: boolean }) { 401 + const Comp = asChild ? Slot : "div" 402 + 403 + return ( 404 + <Comp 405 + data-slot="sidebar-group-label" 406 + data-sidebar="group-label" 407 + className={cn( 408 + "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 409 + "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", 410 + className 411 + )} 412 + {...props} 413 + /> 414 + ) 415 + } 416 + 417 + function SidebarGroupAction({ 418 + className, 419 + asChild = false, 420 + ...props 421 + }: React.ComponentProps<"button"> & { asChild?: boolean }) { 422 + const Comp = asChild ? Slot : "button" 423 + 424 + return ( 425 + <Comp 426 + data-slot="sidebar-group-action" 427 + data-sidebar="group-action" 428 + className={cn( 429 + "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 430 + // Increases the hit area of the button on mobile. 431 + "after:absolute after:-inset-2 md:after:hidden", 432 + "group-data-[collapsible=icon]:hidden", 433 + className 434 + )} 435 + {...props} 436 + /> 437 + ) 438 + } 439 + 440 + function SidebarGroupContent({ 441 + className, 442 + ...props 443 + }: React.ComponentProps<"div">) { 444 + return ( 445 + <div 446 + data-slot="sidebar-group-content" 447 + data-sidebar="group-content" 448 + className={cn("w-full text-sm", className)} 449 + {...props} 450 + /> 451 + ) 452 + } 453 + 454 + function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) { 455 + return ( 456 + <ul 457 + data-slot="sidebar-menu" 458 + data-sidebar="menu" 459 + className={cn("flex w-full min-w-0 flex-col gap-1", className)} 460 + {...props} 461 + /> 462 + ) 463 + } 464 + 465 + function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) { 466 + return ( 467 + <li 468 + data-slot="sidebar-menu-item" 469 + data-sidebar="menu-item" 470 + className={cn("group/menu-item relative", className)} 471 + {...props} 472 + /> 473 + ) 474 + } 475 + 476 + const sidebarMenuButtonVariants = cva( 477 + "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", 478 + { 479 + variants: { 480 + variant: { 481 + default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", 482 + outline: 483 + "bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]", 484 + }, 485 + size: { 486 + default: "h-8 text-sm", 487 + sm: "h-7 text-xs", 488 + lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!", 489 + }, 490 + }, 491 + defaultVariants: { 492 + variant: "default", 493 + size: "default", 494 + }, 495 + } 496 + ) 497 + 498 + function SidebarMenuButton({ 499 + asChild = false, 500 + isActive = false, 501 + variant = "default", 502 + size = "default", 503 + tooltip, 504 + className, 505 + ...props 506 + }: React.ComponentProps<"button"> & { 507 + asChild?: boolean 508 + isActive?: boolean 509 + tooltip?: string | React.ComponentProps<typeof TooltipContent> 510 + } & VariantProps<typeof sidebarMenuButtonVariants>) { 511 + const Comp = asChild ? Slot : "button" 512 + const { isMobile, state } = useSidebar() 513 + 514 + const button = ( 515 + <Comp 516 + data-slot="sidebar-menu-button" 517 + data-sidebar="menu-button" 518 + data-size={size} 519 + data-active={isActive} 520 + className={cn(sidebarMenuButtonVariants({ variant, size }), className)} 521 + {...props} 522 + /> 523 + ) 524 + 525 + if (!tooltip) { 526 + return button 527 + } 528 + 529 + if (typeof tooltip === "string") { 530 + tooltip = { 531 + children: tooltip, 532 + } 533 + } 534 + 535 + return ( 536 + <Tooltip> 537 + <TooltipTrigger asChild>{button}</TooltipTrigger> 538 + <TooltipContent 539 + side="right" 540 + align="center" 541 + hidden={state !== "collapsed" || isMobile} 542 + {...tooltip} 543 + /> 544 + </Tooltip> 545 + ) 546 + } 547 + 548 + function SidebarMenuAction({ 549 + className, 550 + asChild = false, 551 + showOnHover = false, 552 + ...props 553 + }: React.ComponentProps<"button"> & { 554 + asChild?: boolean 555 + showOnHover?: boolean 556 + }) { 557 + const Comp = asChild ? Slot : "button" 558 + 559 + return ( 560 + <Comp 561 + data-slot="sidebar-menu-action" 562 + data-sidebar="menu-action" 563 + className={cn( 564 + "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 565 + // Increases the hit area of the button on mobile. 566 + "after:absolute after:-inset-2 md:after:hidden", 567 + "peer-data-[size=sm]/menu-button:top-1", 568 + "peer-data-[size=default]/menu-button:top-1.5", 569 + "peer-data-[size=lg]/menu-button:top-2.5", 570 + "group-data-[collapsible=icon]:hidden", 571 + showOnHover && 572 + "peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0", 573 + className 574 + )} 575 + {...props} 576 + /> 577 + ) 578 + } 579 + 580 + function SidebarMenuBadge({ 581 + className, 582 + ...props 583 + }: React.ComponentProps<"div">) { 584 + return ( 585 + <div 586 + data-slot="sidebar-menu-badge" 587 + data-sidebar="menu-badge" 588 + className={cn( 589 + "text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none", 590 + "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground", 591 + "peer-data-[size=sm]/menu-button:top-1", 592 + "peer-data-[size=default]/menu-button:top-1.5", 593 + "peer-data-[size=lg]/menu-button:top-2.5", 594 + "group-data-[collapsible=icon]:hidden", 595 + className 596 + )} 597 + {...props} 598 + /> 599 + ) 600 + } 601 + 602 + function SidebarMenuSkeleton({ 603 + className, 604 + showIcon = false, 605 + ...props 606 + }: React.ComponentProps<"div"> & { 607 + showIcon?: boolean 608 + }) { 609 + // Random width between 50 to 90%. 610 + const width = React.useMemo(() => { 611 + return `${Math.floor(Math.random() * 40) + 50}%` 612 + }, []) 613 + 614 + return ( 615 + <div 616 + data-slot="sidebar-menu-skeleton" 617 + data-sidebar="menu-skeleton" 618 + className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)} 619 + {...props} 620 + > 621 + {showIcon && ( 622 + <Skeleton 623 + className="size-4 rounded-md" 624 + data-sidebar="menu-skeleton-icon" 625 + /> 626 + )} 627 + <Skeleton 628 + className="h-4 max-w-(--skeleton-width) flex-1" 629 + data-sidebar="menu-skeleton-text" 630 + style={ 631 + { 632 + "--skeleton-width": width, 633 + } as React.CSSProperties 634 + } 635 + /> 636 + </div> 637 + ) 638 + } 639 + 640 + function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) { 641 + return ( 642 + <ul 643 + data-slot="sidebar-menu-sub" 644 + data-sidebar="menu-sub" 645 + className={cn( 646 + "border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5", 647 + "group-data-[collapsible=icon]:hidden", 648 + className 649 + )} 650 + {...props} 651 + /> 652 + ) 653 + } 654 + 655 + function SidebarMenuSubItem({ 656 + className, 657 + ...props 658 + }: React.ComponentProps<"li">) { 659 + return ( 660 + <li 661 + data-slot="sidebar-menu-sub-item" 662 + data-sidebar="menu-sub-item" 663 + className={cn("group/menu-sub-item relative", className)} 664 + {...props} 665 + /> 666 + ) 667 + } 668 + 669 + function SidebarMenuSubButton({ 670 + asChild = false, 671 + size = "md", 672 + isActive = false, 673 + className, 674 + ...props 675 + }: React.ComponentProps<"a"> & { 676 + asChild?: boolean 677 + size?: "sm" | "md" 678 + isActive?: boolean 679 + }) { 680 + const Comp = asChild ? Slot : "a" 681 + 682 + return ( 683 + <Comp 684 + data-slot="sidebar-menu-sub-button" 685 + data-sidebar="menu-sub-button" 686 + data-size={size} 687 + data-active={isActive} 688 + className={cn( 689 + "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", 690 + "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground", 691 + size === "sm" && "text-xs", 692 + size === "md" && "text-sm", 693 + "group-data-[collapsible=icon]:hidden", 694 + className 695 + )} 696 + {...props} 697 + /> 698 + ) 699 + } 700 + 701 + export { 702 + Sidebar, 703 + SidebarContent, 704 + SidebarFooter, 705 + SidebarGroup, 706 + SidebarGroupAction, 707 + SidebarGroupContent, 708 + SidebarGroupLabel, 709 + SidebarHeader, 710 + SidebarInput, 711 + SidebarInset, 712 + SidebarMenu, 713 + SidebarMenuAction, 714 + SidebarMenuBadge, 715 + SidebarMenuButton, 716 + SidebarMenuItem, 717 + SidebarMenuSkeleton, 718 + SidebarMenuSub, 719 + SidebarMenuSubButton, 720 + SidebarMenuSubItem, 721 + SidebarProvider, 722 + SidebarRail, 723 + SidebarSeparator, 724 + SidebarTrigger, 725 + useSidebar, 726 + }
+13
apps/app/components/ui/skeleton.tsx
··· 1 + import { cn } from "@/lib/utils" 2 + 3 + function Skeleton({ className, ...props }: React.ComponentProps<"div">) { 4 + return ( 5 + <div 6 + data-slot="skeleton" 7 + className={cn("bg-accent animate-pulse rounded-md", className)} 8 + {...props} 9 + /> 10 + ) 11 + } 12 + 13 + export { Skeleton }
+18
apps/app/components/ui/textarea.tsx
··· 1 + import * as React from "react" 2 + 3 + import { cn } from "@/lib/utils" 4 + 5 + function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 6 + return ( 7 + <textarea 8 + data-slot="textarea" 9 + className={cn( 10 + "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", 11 + className 12 + )} 13 + {...props} 14 + /> 15 + ) 16 + } 17 + 18 + export { Textarea }
+61
apps/app/components/ui/tooltip.tsx
··· 1 + "use client" 2 + 3 + import * as React from "react" 4 + import * as TooltipPrimitive from "@radix-ui/react-tooltip" 5 + 6 + import { cn } from "@/lib/utils" 7 + 8 + function TooltipProvider({ 9 + delayDuration = 0, 10 + ...props 11 + }: React.ComponentProps<typeof TooltipPrimitive.Provider>) { 12 + return ( 13 + <TooltipPrimitive.Provider 14 + data-slot="tooltip-provider" 15 + delayDuration={delayDuration} 16 + {...props} 17 + /> 18 + ) 19 + } 20 + 21 + function Tooltip({ 22 + ...props 23 + }: React.ComponentProps<typeof TooltipPrimitive.Root>) { 24 + return ( 25 + <TooltipProvider> 26 + <TooltipPrimitive.Root data-slot="tooltip" {...props} /> 27 + </TooltipProvider> 28 + ) 29 + } 30 + 31 + function TooltipTrigger({ 32 + ...props 33 + }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) { 34 + return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} /> 35 + } 36 + 37 + function TooltipContent({ 38 + className, 39 + sideOffset = 0, 40 + children, 41 + ...props 42 + }: React.ComponentProps<typeof TooltipPrimitive.Content>) { 43 + return ( 44 + <TooltipPrimitive.Portal> 45 + <TooltipPrimitive.Content 46 + data-slot="tooltip-content" 47 + sideOffset={sideOffset} 48 + className={cn( 49 + "bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", 50 + className 51 + )} 52 + {...props} 53 + > 54 + {children} 55 + <TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" /> 56 + </TooltipPrimitive.Content> 57 + </TooltipPrimitive.Portal> 58 + ) 59 + } 60 + 61 + export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
+45
apps/app/components/views/recipe-card.tsx
··· 1 + import { BlueRecipesFeedDefs } from "@cookware/lexicons"; 2 + import { ClockIcon } from "lucide-react"; 3 + import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter } from "../ui/card"; 4 + import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; 5 + import Link from "next/link"; 6 + 7 + export type RecipeCardProps = { 8 + recipe: BlueRecipesFeedDefs.RecipeView; 9 + } 10 + 11 + export const RecipeCard = ({ recipe }: RecipeCardProps) => ( 12 + <Link href={`/recipes/${recipe.author.handle}/${recipe.rkey}`}> 13 + <Card> 14 + <CardHeader> 15 + <CardTitle>{recipe.record.title}</CardTitle> 16 + {recipe.record.description && <CardDescription>{recipe.record.description}</CardDescription>} 17 + </CardHeader> 18 + 19 + {recipe.imageUrl && ( 20 + <CardContent> 21 + <img className="rounded-md ratio-[4/3] object-cover" src={recipe.imageUrl} /> 22 + </CardContent> 23 + )} 24 + 25 + <CardFooter> 26 + <div className="flex flex-col gap-2"> 27 + <div className="flex items-center gap-2 text-sm"> 28 + <Avatar className="!size-8"> 29 + <AvatarImage> 30 + <img src={recipe.author.avatar} /> 31 + </AvatarImage> 32 + <AvatarFallback>{recipe.author.handle.split('.').map(v => v.startsWith('@') ? v[1] : v[0]).join('').toUpperCase()}</AvatarFallback> 33 + </Avatar> 34 + <span>{recipe.author.displayName ?? recipe.author.handle}</span> 35 + </div> 36 + 37 + <div className="flex items-center gap-2 text-sm"> 38 + <ClockIcon className="!size-4" /> 39 + <span>{recipe.record.time} mins</span> 40 + </div> 41 + </div> 42 + </CardFooter> 43 + </Card> 44 + </Link> 45 + );
+22
apps/app/components.json
··· 1 + { 2 + "$schema": "https://ui.shadcn.com/schema.json", 3 + "style": "new-york", 4 + "rsc": true, 5 + "tsx": true, 6 + "tailwind": { 7 + "config": "", 8 + "css": "app/globals.css", 9 + "baseColor": "zinc", 10 + "cssVariables": true, 11 + "prefix": "" 12 + }, 13 + "iconLibrary": "lucide", 14 + "aliases": { 15 + "components": "@/components", 16 + "utils": "@/lib/utils", 17 + "ui": "@/components/ui", 18 + "lib": "@/lib", 19 + "hooks": "@/hooks" 20 + }, 21 + "registries": {} 22 + }
+18
apps/app/eslint.config.mjs
··· 1 + import { defineConfig, globalIgnores } from "eslint/config"; 2 + import nextVitals from "eslint-config-next/core-web-vitals"; 3 + import nextTs from "eslint-config-next/typescript"; 4 + 5 + const eslintConfig = defineConfig([ 6 + ...nextVitals, 7 + ...nextTs, 8 + // Override default ignores of eslint-config-next. 9 + globalIgnores([ 10 + // Default ignores of eslint-config-next: 11 + ".next/**", 12 + "out/**", 13 + "build/**", 14 + "next-env.d.ts", 15 + ]), 16 + ]); 17 + 18 + export default eslintConfig;
+19
apps/app/hooks/use-mobile.ts
··· 1 + import * as React from "react" 2 + 3 + const MOBILE_BREAKPOINT = 768 4 + 5 + export function useIsMobile() { 6 + const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) 7 + 8 + React.useEffect(() => { 9 + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 + const onChange = () => { 11 + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 + } 13 + mql.addEventListener("change", onChange) 14 + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 + return () => mql.removeEventListener("change", onChange) 16 + }, []) 17 + 18 + return !!isMobile 19 + }
+18
apps/app/lib/consts.ts
··· 1 + export const IS_DEV = process.env.NODE_ENV == "development"; 2 + export const OAUTH_SCOPE = ['atproto', 'transition:generic']; 3 + 4 + export const REDIRECT_URI = IS_DEV 5 + ? "http://127.0.0.1:3000" 6 + : "https://cookware.social"; 7 + 8 + export const CLIENT_ID = IS_DEV 9 + ? `http://localhost?redirect_uri=${encodeURIComponent(REDIRECT_URI)}&scope=${encodeURIComponent(OAUTH_SCOPE.join(' '))}` 10 + : "https://cookware.social/oauth-client-metadata.json"; 11 + 12 + export const COOKWARE_API_URL = IS_DEV 13 + ? "http://localhost:4000" 14 + : "https://api.cookware.social"; 15 + 16 + export const BLUESKY_PROFILE_URL = "https://bsky.app/profile/cookware.social"; 17 + export const DISCORD_URL = "https://discord.gg/64nAv9QPJ9"; 18 + export const HANDLE_RESOLUTION_SERVICE = "https://slingshot.microcosm.blue";
+25
apps/app/lib/queries/recipes.tsx
··· 1 + import { Client } from '@atcute/client'; 2 + import { useQuery, queryOptions } from '@tanstack/react-query'; 3 + import { useClient } from '../state/query-provider'; 4 + 5 + export const GET_RECIPES_QK = ['recipes']; 6 + 7 + export const getRecipesOptions = (client: Client) => queryOptions({ 8 + queryKey: GET_RECIPES_QK, 9 + queryFn: async () => { 10 + const res = await client.get('blue.recipes.feed.getRecipes', { 11 + params: {}, 12 + }); 13 + 14 + if (!res.ok) throw res; 15 + 16 + return res.data; 17 + }, 18 + }); 19 + 20 + export const useGetRecipesQuery = () => { 21 + const { client } = useClient(); 22 + return useQuery({ 23 + ...getRecipesOptions(client) 24 + }); 25 + };
+135
apps/app/lib/state/auth.tsx
··· 1 + "use client"; 2 + 3 + import { LocalActorResolver, XrpcHandleResolver, CompositeDidDocumentResolver, PlcDidDocumentResolver, WebDidDocumentResolver } from "@atcute/identity-resolver"; 4 + import { configureOAuth, finalizeAuthorization, getSession, OAuthUserAgent } from "@atcute/oauth-browser-client"; 5 + import { createContext, PropsWithChildren, useContext, useEffect, useLayoutEffect, useState } from "react"; 6 + import { CLIENT_ID, HANDLE_RESOLUTION_SERVICE, REDIRECT_URI } from "@/lib/consts"; 7 + import { useClient } from "./query-provider"; 8 + import { Did, isDid } from "@atcute/lexicons/syntax"; 9 + import { BlueRecipesActorDefs } from "@cookware/lexicons"; 10 + import { Client } from "@atcute/client"; 11 + 12 + type AuthContext = { 13 + loggedIn: false; 14 + } | { 15 + loggedIn: true; 16 + actorDid: Did; 17 + pdsClient: Client; 18 + profile: { 19 + exists: true; 20 + profileView: BlueRecipesActorDefs.ProfileViewDetailed; 21 + } | { 22 + exists: false; 23 + } 24 + }; 25 + 26 + const authContext = createContext<AuthContext | undefined>(undefined); 27 + 28 + export const identityResolver = new LocalActorResolver({ 29 + handleResolver: new XrpcHandleResolver({ serviceUrl: HANDLE_RESOLUTION_SERVICE }), 30 + didDocumentResolver: new CompositeDidDocumentResolver({ 31 + methods: { 32 + plc: new PlcDidDocumentResolver(), 33 + web: new WebDidDocumentResolver(), 34 + }, 35 + }), 36 + }); 37 + 38 + export const AuthProvider = ({ children }: PropsWithChildren) => { 39 + const { client, setHandler } = useClient(); 40 + const [loading, setLoading] = useState<boolean>(true); 41 + const [loggedIn, setLoggedIn] = useState<boolean>(false); 42 + const [actorDid, setActorDid] = useState<Did>(); 43 + const [pdsClient, setPdsClient] = useState<Client>(); 44 + const [hasProfile, setHasProfile] = useState<boolean>(false); 45 + const [profileView, setProfileView] = useState<BlueRecipesActorDefs.ProfileViewDetailed>(); 46 + 47 + useLayoutEffect(() => { 48 + configureOAuth({ 49 + identityResolver, 50 + metadata: { 51 + client_id: CLIENT_ID, 52 + redirect_uri: REDIRECT_URI, 53 + }, 54 + }); 55 + 56 + const params = new URLSearchParams(location.hash.slice(1)); 57 + if (params.has('state') && params.has('iss') && params.has('code')) { 58 + // Remove state & code to prevent thievery and abject tomfoolery 59 + window.history.replaceState(null, '', location.pathname + location.search); 60 + 61 + finalizeAuthorization(params) 62 + .then(({ session }) => { 63 + localStorage.setItem('lastSignedIn', session.info.sub); 64 + const agent = new OAuthUserAgent(session); 65 + setHandler(agent); 66 + setActorDid(session.info.sub); 67 + setLoggedIn(true); 68 + setPdsClient(new Client({ handler: agent })); 69 + }); 70 + } else { 71 + const existing = localStorage.getItem('lastSignedIn'); 72 + if (!existing || !isDid(existing)) { 73 + setLoading(false); 74 + return; 75 + }; 76 + getSession(existing, { allowStale: true }) 77 + .then(session => { 78 + localStorage.setItem('lastSignedIn', session.info.sub); 79 + const agent = new OAuthUserAgent(session); 80 + setHandler(new OAuthUserAgent(session)); 81 + setActorDid(session.info.sub); 82 + setLoggedIn(true); 83 + setPdsClient(new Client({ handler: agent })); 84 + setLoading(false); 85 + }); 86 + } 87 + }, []); 88 + 89 + useEffect(() => { 90 + if (loggedIn && actorDid) { 91 + client.get('blue.recipes.actor.getProfile', { 92 + params: { actor: actorDid }, 93 + }) 94 + .then(res => { 95 + if (!res.ok) { 96 + if (res.data.error === 'ProfileNotFound') { 97 + setHasProfile(false); 98 + return; 99 + } 100 + throw res.data.error; 101 + } else { 102 + setHasProfile(true); 103 + setProfileView(res.data); 104 + if (loading) setLoading(false); 105 + } 106 + }); 107 + } 108 + }, [loggedIn]); 109 + 110 + if (loading) return <>Loading...</>; 111 + 112 + return ( 113 + <authContext.Provider value={ 114 + loggedIn 115 + ? { 116 + loggedIn, 117 + actorDid: actorDid!, 118 + pdsClient: pdsClient!, 119 + profile: hasProfile ? { 120 + exists: hasProfile, 121 + profileView: profileView!, 122 + } : { exists: false }, 123 + } 124 + : { loggedIn: false } 125 + }> 126 + {children} 127 + </authContext.Provider> 128 + ); 129 + }; 130 + 131 + export const useAuth = () => { 132 + const ctx = useContext(authContext); 133 + if (!ctx) throw new Error("useAuth() must be called inside <AuthProvider />"); 134 + return ctx; 135 + }
+44
apps/app/lib/state/query-provider.tsx
··· 1 + "use client"; 2 + 3 + import { createContext, PropsWithChildren, useContext, useEffect, useState } from "react"; 4 + import { Client, CredentialManager, FetchHandler, FetchHandlerObject } from "@atcute/client"; 5 + import { COOKWARE_API_URL } from "../consts"; 6 + 7 + type QueryContext = { 8 + client: Client; 9 + handler: FetchHandler | FetchHandlerObject; 10 + setHandler: (handler: FetchHandler | FetchHandlerObject) => void; 11 + }; 12 + 13 + export const queryContext = createContext<QueryContext | undefined>(undefined); 14 + 15 + export const ClientProvider = ({ children }: PropsWithChildren) => { 16 + const [isLoaded, setIsLoaded] = useState(false); 17 + const [handler, setHandler] = useState<QueryContext["handler"]>( 18 + new CredentialManager({ service: COOKWARE_API_URL }), 19 + ); 20 + const [client, setClient] = useState<QueryContext["client"]>(new Client({ handler })); 21 + 22 + useEffect(() => { 23 + if (!isLoaded) { 24 + setIsLoaded(true); 25 + return; 26 + } 27 + setClient(new Client({ handler })); 28 + setIsLoaded(true); 29 + }, [handler]); 30 + 31 + if (!isLoaded || !client) return <>Loading...</>; 32 + 33 + return ( 34 + <queryContext.Provider value={{ client: client!, handler, setHandler }}> 35 + {children} 36 + </queryContext.Provider> 37 + ); 38 + }; 39 + 40 + export const useClient = () => { 41 + const ctx = useContext(queryContext); 42 + if (!ctx) throw new Error("useClient must be used within a ClientProvider"); 43 + return ctx; 44 + }
+6
apps/app/lib/utils.ts
··· 1 + import { clsx, type ClassValue } from "clsx" 2 + import { twMerge } from "tailwind-merge" 3 + 4 + export function cn(...inputs: ClassValue[]) { 5 + return twMerge(clsx(inputs)) 6 + }
+7
apps/app/next.config.ts
··· 1 + import type { NextConfig } from "next"; 2 + 3 + const nextConfig: NextConfig = { 4 + /* config options here */ 5 + }; 6 + 7 + export default nextConfig;
+49
apps/app/package.json
··· 1 + { 2 + "name": "app", 3 + "version": "0.1.0", 4 + "private": true, 5 + "scripts": { 6 + "dev": "next dev", 7 + "build": "next build", 8 + "start": "next start", 9 + "lint": "eslint" 10 + }, 11 + "dependencies": { 12 + "@atcute/atproto": "catalog:", 13 + "@atcute/client": "catalog:", 14 + "@atcute/identity": "catalog:", 15 + "@atcute/identity-resolver": "catalog:", 16 + "@atcute/lexicons": "catalog:", 17 + "@atproto/oauth-client-node": "^0.3.13", 18 + "@cookware/lexicons": "workspace:*", 19 + "@radix-ui/react-avatar": "^1.1.11", 20 + "@radix-ui/react-dialog": "^1.1.15", 21 + "@radix-ui/react-dropdown-menu": "^2.1.16", 22 + "@radix-ui/react-label": "^2.1.8", 23 + "@radix-ui/react-separator": "^1.1.8", 24 + "@radix-ui/react-slot": "^1.2.4", 25 + "@radix-ui/react-tooltip": "^1.2.8", 26 + "@tabler/icons-react": "^3.35.0", 27 + "@tanstack/react-query": "^5.90.12", 28 + "class-variance-authority": "^0.7.1", 29 + "clsx": "^2.1.1", 30 + "lucide-react": "^0.556.0", 31 + "next": "16.0.7", 32 + "react": "19.2.0", 33 + "react-dom": "19.2.0", 34 + "tailwind-merge": "^3.4.0" 35 + }, 36 + "devDependencies": { 37 + "@tailwindcss/postcss": "^4", 38 + "@tanstack/query-devtools": "^5.91.1", 39 + "@tanstack/react-query-devtools": "^5.91.1", 40 + "@types/node": "^20", 41 + "@types/react": "^19", 42 + "@types/react-dom": "^19", 43 + "eslint": "^9", 44 + "eslint-config-next": "16.0.7", 45 + "tailwindcss": "^4", 46 + "tw-animate-css": "^1.4.0", 47 + "typescript": "^5" 48 + } 49 + }
+7
apps/app/postcss.config.mjs
··· 1 + const config = { 2 + plugins: { 3 + "@tailwindcss/postcss": {}, 4 + }, 5 + }; 6 + 7 + export default config;
+35
apps/app/tsconfig.json
··· 1 + { 2 + "compilerOptions": { 3 + "types": ["@atcute/atproto", "@cookware/lexicons"], 4 + "target": "ES2017", 5 + "lib": ["dom", "dom.iterable", "esnext"], 6 + "allowJs": true, 7 + "skipLibCheck": true, 8 + "strict": true, 9 + "noEmit": true, 10 + "esModuleInterop": true, 11 + "module": "esnext", 12 + "moduleResolution": "bundler", 13 + "resolveJsonModule": true, 14 + "isolatedModules": true, 15 + "jsx": "react-jsx", 16 + "incremental": true, 17 + "plugins": [ 18 + { 19 + "name": "next" 20 + } 21 + ], 22 + "paths": { 23 + "@/*": ["./*"] 24 + } 25 + }, 26 + "include": [ 27 + "next-env.d.ts", 28 + "**/*.ts", 29 + "**/*.tsx", 30 + ".next/types/**/*.ts", 31 + ".next/dev/types/**/*.ts", 32 + "**/*.mts" 33 + ], 34 + "exclude": ["node_modules"] 35 + }
+1 -1
apps/ingester/package.json
··· 10 10 "build": "bun --bun run check-types && bun --bun run compile", 11 11 "dev": "bun run --hot src/index.ts | pino-pretty", 12 12 "check-types": "tsc --noEmit", 13 - "compile": "bun build src/index.ts --compile --minify --sourcemap --outfile=dist/api --target=bun", 13 + "compile": "bun build src/index.ts --compile --minify --sourcemap --outfile=dist/ingester --target=bun", 14 14 "clean": "rimraf dist" 15 15 }, 16 16 "dependencies": {
+3 -3
apps/ingester/src/ingesters/profile.ts
··· 2 2 import { profilesTable } from "@cookware/database/schema"; 3 3 import { is } from '@atcute/lexicons'; 4 4 import { BlueRecipesActorProfile } from "@cookware/lexicons"; 5 - import { CommitOperation } from "@atcute/jetstream"; 6 - import { Logger } from "pino"; 7 - import { AtprotoDid } from "@atcute/lexicons/syntax"; 5 + import type { CommitOperation } from "@atcute/jetstream"; 6 + import type { Logger } from "pino"; 7 + import type { AtprotoDid } from "@atcute/lexicons/syntax"; 8 8 import { RedisClient } from "bun"; 9 9 import { CompositeDidDocumentResolver, PlcDidDocumentResolver, WebDidDocumentResolver } from "@atcute/identity-resolver"; 10 10 import env from "../config.js";
+3 -3
apps/ingester/src/ingesters/recipe.ts
··· 2 2 import { recipeTable } from "@cookware/database/schema"; 3 3 import { is } from '@atcute/lexicons'; 4 4 import { BlueRecipesFeedRecipe } from "@cookware/lexicons"; 5 - import { CommitOperation } from "@atcute/jetstream"; 6 - import { Logger } from "pino"; 7 - import { AtprotoDid } from "@atcute/lexicons/syntax"; 5 + import type { CommitOperation } from "@atcute/jetstream"; 6 + import type { Logger } from "pino"; 7 + import type { AtprotoDid } from "@atcute/lexicons/syntax"; 8 8 9 9 export const ingestRecipe = async (did: AtprotoDid, commit: CommitOperation, logger: Logger) => { 10 10 if (commit.operation == 'create' || commit.operation == 'update') {
+52 -29
apps/web/README.md
··· 4 4 5 5 Currently, two official plugins are available: 6 6 7 - - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh 8 - - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 7 + - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh 8 + - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh 9 + 10 + ## React Compiler 11 + 12 + The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). 9 13 10 14 ## Expanding the ESLint configuration 11 15 12 - If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: 16 + If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: 17 + 18 + ```js 19 + export default defineConfig([ 20 + globalIgnores(['dist']), 21 + { 22 + files: ['**/*.{ts,tsx}'], 23 + extends: [ 24 + // Other configs... 13 25 14 - - Configure the top-level `parserOptions` property like this: 26 + // Remove tseslint.configs.recommended and replace with this 27 + tseslint.configs.recommendedTypeChecked, 28 + // Alternatively, use this for stricter rules 29 + tseslint.configs.strictTypeChecked, 30 + // Optionally, add this for stylistic rules 31 + tseslint.configs.stylisticTypeChecked, 15 32 16 - ```js 17 - export default tseslint.config({ 18 - languageOptions: { 19 - // other options... 20 - parserOptions: { 21 - project: ['./tsconfig.node.json', './tsconfig.app.json'], 22 - tsconfigRootDir: import.meta.dirname, 33 + // Other configs... 34 + ], 35 + languageOptions: { 36 + parserOptions: { 37 + project: ['./tsconfig.node.json', './tsconfig.app.json'], 38 + tsconfigRootDir: import.meta.dirname, 39 + }, 40 + // other options... 23 41 }, 24 42 }, 25 - }) 43 + ]) 26 44 ``` 27 45 28 - - Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` 29 - - Optionally add `...tseslint.configs.stylisticTypeChecked` 30 - - Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: 46 + You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: 31 47 32 48 ```js 33 49 // eslint.config.js 34 - import react from 'eslint-plugin-react' 50 + import reactX from 'eslint-plugin-react-x' 51 + import reactDom from 'eslint-plugin-react-dom' 35 52 36 - export default tseslint.config({ 37 - // Set the react version 38 - settings: { react: { version: '18.3' } }, 39 - plugins: { 40 - // Add the react plugin 41 - react, 42 - }, 43 - rules: { 44 - // other rules... 45 - // Enable its recommended rules 46 - ...react.configs.recommended.rules, 47 - ...react.configs['jsx-runtime'].rules, 53 + export default defineConfig([ 54 + globalIgnores(['dist']), 55 + { 56 + files: ['**/*.{ts,tsx}'], 57 + extends: [ 58 + // Other configs... 59 + // Enable lint rules for React 60 + reactX.configs['recommended-typescript'], 61 + // Enable lint rules for React DOM 62 + reactDom.configs.recommended, 63 + ], 64 + languageOptions: { 65 + parserOptions: { 66 + project: ['./tsconfig.node.json', './tsconfig.app.json'], 67 + tsconfigRootDir: import.meta.dirname, 68 + }, 69 + // other options... 70 + }, 48 71 }, 49 - }) 72 + ]) 50 73 ```
+4 -3
apps/web/components.json
··· 4 4 "rsc": false, 5 5 "tsx": true, 6 6 "tailwind": { 7 - "config": "tailwind.config.js", 7 + "config": "", 8 8 "css": "src/index.css", 9 9 "baseColor": "zinc", 10 10 "cssVariables": true, 11 11 "prefix": "" 12 12 }, 13 + "iconLibrary": "lucide", 13 14 "aliases": { 14 15 "components": "@/components", 15 16 "utils": "@/lib/utils", ··· 17 18 "lib": "@/lib", 18 19 "hooks": "@/hooks" 19 20 }, 20 - "iconLibrary": "lucide" 21 - } 21 + "registries": {} 22 + }
+10 -15
apps/web/eslint.config.js
··· 3 3 import reactHooks from 'eslint-plugin-react-hooks' 4 4 import reactRefresh from 'eslint-plugin-react-refresh' 5 5 import tseslint from 'typescript-eslint' 6 + import { defineConfig, globalIgnores } from 'eslint/config' 6 7 7 - export default tseslint.config( 8 - { ignores: ['dist'] }, 8 + export default defineConfig([ 9 + globalIgnores(['dist']), 9 10 { 10 - extends: [js.configs.recommended, ...tseslint.configs.recommended], 11 11 files: ['**/*.{ts,tsx}'], 12 + extends: [ 13 + js.configs.recommended, 14 + tseslint.configs.recommended, 15 + reactHooks.configs.flat.recommended, 16 + reactRefresh.configs.vite, 17 + ], 12 18 languageOptions: { 13 19 ecmaVersion: 2020, 14 20 globals: globals.browser, 15 21 }, 16 - plugins: { 17 - 'react-hooks': reactHooks, 18 - 'react-refresh': reactRefresh, 19 - }, 20 - rules: { 21 - ...reactHooks.configs.recommended.rules, 22 - 'react-refresh/only-export-components': [ 23 - 'warn', 24 - { allowConstantExport: true }, 25 - ], 26 - }, 27 22 }, 28 - ) 23 + ])
+2 -1
apps/web/index.html
··· 2 2 <html lang="en"> 3 3 <head> 4 4 <meta charset="UTF-8" /> 5 + <link rel="icon" type="image/svg+xml" href="/icon.svg" /> 5 6 <meta name="viewport" content="width=device-width, initial-scale=1.0" /> 6 - <title>Recipes</title> 7 + <title>Cookware</title> 7 8 </head> 8 9 <body> 9 10 <div id="root"></div>
+32 -55
apps/web/package.json
··· 1 1 { 2 - "name": "@cookware/web", 2 + "name": "web", 3 3 "private": true, 4 4 "version": "0.0.0", 5 5 "type": "module", 6 6 "scripts": { 7 - "dev": "vite --host", 7 + "dev": "vite", 8 8 "build": "tsc -b && vite build", 9 9 "lint": "eslint .", 10 10 "preview": "vite preview" 11 11 }, 12 12 "dependencies": { 13 - "@atcute/atproto": "^3.1.9", 14 - "@atcute/client": "catalog:", 15 - "@atcute/identity-resolver": "^1.1.4", 16 - "@atcute/lexicons": "catalog:", 17 - "@atcute/oauth-browser-client": "^2.0.1", 18 - "@atproto/common": "^0.4.5", 19 - "@atproto/common-web": "^0.3.1", 20 - "@dnd-kit/core": "^6.3.1", 21 - "@dnd-kit/modifiers": "^9.0.0", 22 - "@dnd-kit/sortable": "^10.0.0", 23 - "@dnd-kit/utilities": "^3.2.2", 24 - "@hookform/resolvers": "^3.9.1", 25 - "@radix-ui/react-avatar": "^1.1.1", 26 - "@radix-ui/react-collapsible": "^1.1.1", 27 - "@radix-ui/react-dialog": "^1.1.4", 28 - "@radix-ui/react-dropdown-menu": "^2.1.4", 29 - "@radix-ui/react-icons": "^1.3.2", 30 - "@radix-ui/react-label": "^2.1.0", 31 - "@radix-ui/react-separator": "^1.1.0", 32 - "@radix-ui/react-slot": "^1.1.0", 33 - "@radix-ui/react-tooltip": "^1.1.4", 34 - "@tanstack/react-query": "^5.62.2", 35 - "@tanstack/react-query-devtools": "^5.62.2", 36 - "@tanstack/react-router": "^1.91.2", 37 - "axios": "^1.7.9", 13 + "@radix-ui/react-avatar": "^1.1.11", 14 + "@radix-ui/react-dialog": "^1.1.15", 15 + "@radix-ui/react-dropdown-menu": "^2.1.16", 16 + "@radix-ui/react-label": "^2.1.8", 17 + "@radix-ui/react-separator": "^1.1.8", 18 + "@radix-ui/react-slot": "^1.2.4", 19 + "@radix-ui/react-tooltip": "^1.2.8", 38 20 "class-variance-authority": "^0.7.1", 39 21 "clsx": "^2.1.1", 40 - "lucide-react": "^0.464.0", 41 - "react-dom": "19.0.0", 42 - "react-hook-form": "^7.54.1", 43 - "tailwind-merge": "^2.5.5", 44 - "tailwindcss-animate": "^1.0.7", 45 - "zod": "^3.23.8" 22 + "lucide-react": "^0.556.0", 23 + "react": "^19.2.0", 24 + "react-dom": "^19.2.0", 25 + "tailwind-merge": "^3.4.0", 26 + "tailwindcss": "^4.1.17" 46 27 }, 47 28 "devDependencies": { 48 - "@atcute/bluesky": "^1.0.9", 49 - "@cookware/lexicons": "workspace:*", 50 - "@eslint/js": "^9.15.0", 51 - "@tanstack/eslint-plugin-query": "^5.62.1", 52 - "@tanstack/router-devtools": "^1.85.5", 53 - "@tanstack/router-plugin": "^1.85.3", 54 - "@types/node": "^22.10.1", 55 - "@types/react": "^19.0.0", 56 - "@types/react-dom": "^19.0.0", 57 - "@vitejs/plugin-react-swc": "^3.5.0", 58 - "autoprefixer": "^10.4.20", 59 - "cssnano": "^7.0.6", 60 - "eslint": "^9.15.0", 61 - "eslint-plugin-react-hooks": "^5.0.0", 62 - "eslint-plugin-react-refresh": "^0.4.14", 63 - "globals": "^15.12.0", 64 - "postcss": "^8.4.49", 65 - "react": "19.0.0", 66 - "tailwindcss": "^3.4.16", 67 - "typescript": "~5.6.2", 68 - "typescript-eslint": "^8.15.0", 69 - "vite": "^6.0.1" 29 + "@cookware/tsconfig": "workspace:*", 30 + "@eslint/js": "^9.39.1", 31 + "@tailwindcss/vite": "^4.1.17", 32 + "@types/bun": "^1.3.4", 33 + "@types/react": "^19.2.5", 34 + "@types/react-dom": "^19.2.3", 35 + "@vitejs/plugin-react": "^5.1.1", 36 + "eslint": "^9.39.1", 37 + "eslint-plugin-react-hooks": "^7.0.1", 38 + "eslint-plugin-react-refresh": "^0.4.24", 39 + "globals": "^16.5.0", 40 + "tw-animate-css": "^1.4.0", 41 + "typescript": "~5.9.3", 42 + "typescript-eslint": "^8.46.4", 43 + "vite": "npm:rolldown-vite@7.2.5" 44 + }, 45 + "overrides": { 46 + "vite": "npm:rolldown-vite@7.2.5" 70 47 } 71 48 }
-7
apps/web/postcss.config.js
··· 1 - export default { 2 - plugins: { 3 - tailwindcss: {}, 4 - autoprefixer: {}, 5 - ...(process.env.NODE_ENV === 'production' ? { cssnano: {} } : {}) 6 - }, 7 - }
-13
apps/web/public/.well-known/did.json
··· 1 - { 2 - "@context": [ 3 - "https://www.w3.org/ns/did/v1" 4 - ], 5 - "id": "did:web:recipes.blue", 6 - "service": [ 7 - { 8 - "id": "#api", 9 - "type": "RecipesApiService", 10 - "serviceEndpoint": "https://recipes.blue" 11 - } 12 - ] 13 - }
+1
apps/web/public/icon.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-chef-hat"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 3c1.918 0 3.52 1.35 3.91 3.151a4 4 0 0 1 2.09 7.723l0 7.126h-12v-7.126a4 4 0 1 1 2.092 -7.723a4 4 0 0 1 3.908 -3.151z" /><path d="M6.161 17.009l11.839 -.009" /></svg>
-9
apps/web/public/oauth-client-metadata.json
··· 1 - { 2 - "client_id": "https://recipes.blue/oauth-client-metadata.json", 3 - "client_name": "Recipes.blue", 4 - "redirect_uris": ["https://recipes.blue/"], 5 - "scope": "atproto transition:generic", 6 - "token_endpoint_auth_method": "none", 7 - "application_type": "web", 8 - "dpop_bound_access_tokens": true 9 - }
-90
apps/web/src/components/app-sidebar.tsx
··· 1 - import * as React from "react" 2 - import { 3 - Book, 4 - CookingPot, 5 - ForkKnife, 6 - } from "lucide-react" 7 - 8 - import { NavMain } from "@/components/nav-main" 9 - import { NavUser } from "@/components/nav-user" 10 - import { 11 - Sidebar, 12 - SidebarContent, 13 - SidebarFooter, 14 - SidebarHeader, 15 - SidebarMenu, 16 - SidebarMenuButton, 17 - SidebarMenuItem, 18 - SidebarRail, 19 - } from "@/components/ui/sidebar" 20 - import { NavUserOpts } from "./nav-user-opts" 21 - import { ModeToggle } from "./mode-toggle" 22 - 23 - const data = { 24 - navMain: [ 25 - { 26 - title: "Recipes", 27 - url: "#", 28 - icon: ForkKnife, 29 - isActive: true, 30 - items: [ 31 - { 32 - title: "Browse", 33 - url: "/", 34 - isActive: true, 35 - }, 36 - { 37 - title: "Starred", 38 - url: "#", 39 - }, 40 - ], 41 - }, 42 - { 43 - title: "Cookbooks", 44 - url: "#", 45 - icon: Book, 46 - items: [ 47 - { 48 - title: "Browse", 49 - url: "/", 50 - }, 51 - { 52 - title: "Starred", 53 - url: "#", 54 - }, 55 - ], 56 - }, 57 - ] 58 - } 59 - 60 - export function AppSidebar({ ...props }: React.ComponentProps<typeof Sidebar>) { 61 - return ( 62 - <Sidebar collapsible="icon" {...props}> 63 - <SidebarHeader> 64 - <SidebarMenu> 65 - <SidebarMenuItem className="flex items-center justify-between gap-x-2"> 66 - <SidebarMenuButton size="lg" asChild> 67 - <a href="#"> 68 - <div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground"> 69 - <CookingPot className="size-4" /> 70 - </div> 71 - <div className="flex flex-col gap-0.5 leading-none"> 72 - <span className="font-semibold">Recipes</span> 73 - </div> 74 - </a> 75 - </SidebarMenuButton> 76 - <ModeToggle /> 77 - </SidebarMenuItem> 78 - </SidebarMenu> 79 - </SidebarHeader> 80 - <SidebarContent> 81 - <NavMain items={data.navMain} /> 82 - <NavUserOpts /> 83 - </SidebarContent> 84 - <SidebarFooter> 85 - <NavUser /> 86 - </SidebarFooter> 87 - <SidebarRail /> 88 - </Sidebar> 89 - ) 90 - }
-37
apps/web/src/components/mode-toggle.tsx
··· 1 - import { Moon, Sun } from "lucide-react" 2 - 3 - import { Button } from "@/components/ui/button" 4 - import { 5 - DropdownMenu, 6 - DropdownMenuContent, 7 - DropdownMenuItem, 8 - DropdownMenuTrigger, 9 - } from "@/components/ui/dropdown-menu" 10 - import { useTheme } from "@/components/theme-provider" 11 - 12 - export function ModeToggle() { 13 - const { setTheme } = useTheme() 14 - 15 - return ( 16 - <DropdownMenu> 17 - <DropdownMenuTrigger asChild> 18 - <Button variant="outline" size="icon" className="size-8 aspect-square flex items-center justify-center rounded-lg"> 19 - <Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" /> 20 - <Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" /> 21 - <span className="sr-only">Toggle theme</span> 22 - </Button> 23 - </DropdownMenuTrigger> 24 - <DropdownMenuContent align="end"> 25 - <DropdownMenuItem onClick={() => setTheme("light")}> 26 - Light 27 - </DropdownMenuItem> 28 - <DropdownMenuItem onClick={() => setTheme("dark")}> 29 - Dark 30 - </DropdownMenuItem> 31 - <DropdownMenuItem onClick={() => setTheme("system")}> 32 - System 33 - </DropdownMenuItem> 34 - </DropdownMenuContent> 35 - </DropdownMenu> 36 - ) 37 - }
-75
apps/web/src/components/nav-main.tsx
··· 1 - "use client" 2 - 3 - import { ChevronRight, type LucideIcon } from "lucide-react" 4 - 5 - import { 6 - Collapsible, 7 - CollapsibleContent, 8 - CollapsibleTrigger, 9 - } from "@/components/ui/collapsible" 10 - import { 11 - SidebarGroup, 12 - SidebarGroupLabel, 13 - SidebarMenu, 14 - SidebarMenuButton, 15 - SidebarMenuItem, 16 - SidebarMenuSub, 17 - SidebarMenuSubButton, 18 - SidebarMenuSubItem, 19 - } from "@/components/ui/sidebar" 20 - import { Link } from "@tanstack/react-router" 21 - 22 - export function NavMain({ 23 - items, 24 - }: { 25 - items: { 26 - title: string 27 - url: string 28 - icon?: LucideIcon 29 - isActive?: boolean 30 - items?: { 31 - title: string 32 - url: string 33 - isActive?: boolean 34 - }[] 35 - }[] 36 - }) { 37 - return ( 38 - <SidebarGroup> 39 - <SidebarGroupLabel>Community</SidebarGroupLabel> 40 - <SidebarMenu> 41 - {items.map((item) => ( 42 - <Collapsible 43 - key={item.title} 44 - asChild 45 - defaultOpen={item.isActive} 46 - className="group/collapsible" 47 - > 48 - <SidebarMenuItem> 49 - <CollapsibleTrigger asChild> 50 - <SidebarMenuButton tooltip={item.title}> 51 - {item.icon && <item.icon />} 52 - <span>{item.title}</span> 53 - <ChevronRight className="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90" /> 54 - </SidebarMenuButton> 55 - </CollapsibleTrigger> 56 - <CollapsibleContent> 57 - <SidebarMenuSub> 58 - {item.items?.map((subItem) => ( 59 - <SidebarMenuSubItem key={subItem.title}> 60 - <SidebarMenuSubButton asChild isActive={subItem.isActive}> 61 - <Link to={subItem.url}> 62 - <span>{subItem.title}</span> 63 - </Link> 64 - </SidebarMenuSubButton> 65 - </SidebarMenuSubItem> 66 - ))} 67 - </SidebarMenuSub> 68 - </CollapsibleContent> 69 - </SidebarMenuItem> 70 - </Collapsible> 71 - ))} 72 - </SidebarMenu> 73 - </SidebarGroup> 74 - ) 75 - }
-67
apps/web/src/components/nav-user-opts.tsx
··· 1 - "use client" 2 - 3 - import { 4 - SidebarGroup, 5 - SidebarGroupContent, 6 - SidebarMenu, 7 - SidebarMenuButton, 8 - SidebarMenuItem, 9 - } from "@/components/ui/sidebar" 10 - import { useAuth } from "@/state/auth" 11 - import { Link } from "@tanstack/react-router"; 12 - import { LifeBuoy, Pencil, Send } from "lucide-react"; 13 - 14 - export function NavUserOpts() { 15 - const { isLoggedIn } = useAuth(); 16 - 17 - if (!isLoggedIn) { 18 - return ( 19 - <SidebarGroup className="mt-auto"> 20 - <SidebarGroupContent> 21 - <SidebarMenu> 22 - <AlwaysItems /> 23 - </SidebarMenu> 24 - </SidebarGroupContent> 25 - </SidebarGroup> 26 - ); 27 - } 28 - 29 - return ( 30 - <SidebarGroup className="mt-auto"> 31 - <SidebarGroupContent> 32 - <SidebarMenu> 33 - <AlwaysItems /> 34 - <SidebarMenuItem> 35 - <SidebarMenuButton asChild size="sm"> 36 - <Link to="/recipes/new"> 37 - <Pencil /> 38 - <span>New recipe</span> 39 - </Link> 40 - </SidebarMenuButton> 41 - </SidebarMenuItem> 42 - </SidebarMenu> 43 - </SidebarGroupContent> 44 - </SidebarGroup> 45 - ) 46 - } 47 - 48 - const AlwaysItems = () => ( 49 - <> 50 - <SidebarMenuItem> 51 - <SidebarMenuButton asChild size="sm"> 52 - <a href="https://github.com/recipes-blue/recipes.blue/issues/new"> 53 - <LifeBuoy /> 54 - <span>Support</span> 55 - </a> 56 - </SidebarMenuButton> 57 - </SidebarMenuItem> 58 - <SidebarMenuItem> 59 - <SidebarMenuButton asChild size="sm"> 60 - <a href="https://github.com/recipes-blue/recipes.blue/discussions"> 61 - <Send /> 62 - <span>Feedback</span> 63 - </a> 64 - </SidebarMenuButton> 65 - </SidebarMenuItem> 66 - </> 67 - );
-113
apps/web/src/components/nav-user.tsx
··· 1 - "use client" 2 - 3 - import { 4 - ChevronsUpDown, 5 - LogOut, 6 - } from "lucide-react" 7 - import { 8 - DropdownMenu, 9 - DropdownMenuContent, 10 - DropdownMenuItem, 11 - DropdownMenuLabel, 12 - DropdownMenuSeparator, 13 - DropdownMenuTrigger, 14 - } from "@/components/ui/dropdown-menu" 15 - import { 16 - SidebarMenu, 17 - SidebarMenuButton, 18 - SidebarMenuItem, 19 - useSidebar, 20 - } from "@/components/ui/sidebar" 21 - import { Button } from "./ui/button" 22 - import { Link } from "@tanstack/react-router" 23 - import { useAuth } from "@/state/auth" 24 - import { Skeleton } from "./ui/skeleton" 25 - import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar" 26 - import { useUserQuery } from "@/queries/self" 27 - 28 - export function NavUser() { 29 - const { isMobile } = useSidebar() 30 - const { isLoggedIn, agent, logOut } = useAuth(); 31 - 32 - const userQuery = useUserQuery(); 33 - 34 - if (!isLoggedIn || !agent || userQuery.isError || !userQuery.data) { 35 - return ( 36 - <SidebarMenu> 37 - <SidebarMenuItem> 38 - <SidebarMenuButton 39 - size="lg" 40 - className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" 41 - > 42 - <Button asChild> 43 - <Link to="/login" className="w-full">Log in</Link> 44 - </Button> 45 - </SidebarMenuButton> 46 - </SidebarMenuItem> 47 - </SidebarMenu> 48 - ); 49 - } 50 - 51 - if (userQuery.isFetching) return ( 52 - <SidebarMenu> 53 - <SidebarMenuItem> 54 - <SidebarMenuButton 55 - size="lg" 56 - className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" 57 - > 58 - <Skeleton className="h-8 w-8 rounded-lg" /> 59 - <div className="grid flex-1 text-left text-sm leading-tight"> 60 - <Skeleton className="h-2 w-20 rounded-lg" /> 61 - </div> 62 - </SidebarMenuButton> 63 - </SidebarMenuItem> 64 - </SidebarMenu> 65 - ); 66 - 67 - return ( 68 - <SidebarMenu> 69 - <SidebarMenuItem> 70 - <DropdownMenu> 71 - <DropdownMenuTrigger asChild> 72 - <SidebarMenuButton 73 - size="lg" 74 - className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground" 75 - > 76 - <Avatar className="h-8 w-8 rounded-lg"> 77 - <AvatarImage src={`https://cdn.bsky.app/img/avatar_thumbnail/plain/${agent.sub}/${userQuery.data.avatar?.ref.$link}@jpeg`} alt={userQuery.data.displayName} /> 78 - <AvatarFallback className="rounded-lg">{userQuery.data.displayName}</AvatarFallback> 79 - </Avatar> 80 - <div className="grid flex-1 text-left text-sm leading-tight"> 81 - <span className="truncate font-semibold">{userQuery.data.displayName}</span> 82 - </div> 83 - <ChevronsUpDown className="ml-auto size-4" /> 84 - </SidebarMenuButton> 85 - </DropdownMenuTrigger> 86 - <DropdownMenuContent 87 - className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg" 88 - side={isMobile ? "bottom" : "right"} 89 - align="end" 90 - sideOffset={4} 91 - > 92 - <DropdownMenuLabel className="p-0 font-normal"> 93 - <div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm"> 94 - <Avatar className="h-8 w-8 rounded-lg"> 95 - <AvatarImage src={`https://cdn.bsky.app/img/avatar_thumbnail/plain/${agent.sub}/${userQuery.data.avatar?.ref.$link}@jpeg`} alt={userQuery.data.displayName} /> 96 - <AvatarFallback className="rounded-lg">{userQuery.data.displayName}</AvatarFallback> 97 - </Avatar> 98 - <div className="grid flex-1 text-left text-sm leading-tight"> 99 - <span className="truncate font-semibold">{userQuery.data.displayName}</span> 100 - </div> 101 - </div> 102 - </DropdownMenuLabel> 103 - <DropdownMenuSeparator /> 104 - <DropdownMenuItem className="cursor-pointer" onClick={() => logOut()}> 105 - <LogOut /> 106 - Log out 107 - </DropdownMenuItem> 108 - </DropdownMenuContent> 109 - </DropdownMenu> 110 - </SidebarMenuItem> 111 - </SidebarMenu> 112 - ) 113 - }
-58
apps/web/src/components/query-placeholder.tsx
··· 1 - import type { UseQueryResult } from '@tanstack/react-query'; 2 - import { PropsWithChildren, ReactNode } from 'react'; 3 - import { Skeleton } from './ui/skeleton'; 4 - import { Alert, AlertDescription, AlertTitle } from './ui/alert'; 5 - import { AlertCircle } from 'lucide-react'; 6 - import { XRPCError } from '@atcute/client'; 7 - 8 - type QueryPlaceholderProps<TData, TError> = PropsWithChildren<{ 9 - query: UseQueryResult<TData, TError>; 10 - cards?: boolean; 11 - cardsCount?: number; 12 - noData?: ReactNode; 13 - }>; 14 - 15 - const QueryPlaceholder = <TData = {}, TError = Error>( 16 - { 17 - query, 18 - children, 19 - cards = false, 20 - cardsCount = 3, 21 - noData = <></>, 22 - }: QueryPlaceholderProps<TData, TError> 23 - ) => { 24 - if (query.isPending || query.isLoading) { 25 - if (cards) { 26 - return [...Array(cardsCount)].map((_, i) => <Skeleton key={i} className="h-[200px] w-full rounded-lg" />); 27 - } 28 - 29 - return ( 30 - <p>Loading...</p> 31 - ) 32 - } else if (query.isError) { 33 - const { error } = query; 34 - let errMsg = 'Unknown'; 35 - if (error instanceof XRPCError) { 36 - errMsg = error.kind ?? `HTTP_${error.status}`; 37 - } if (error instanceof Error) { 38 - errMsg = `${error.message} (${error.name})`; 39 - } 40 - 41 - return ( 42 - <Alert variant="destructive"> 43 - <AlertCircle className="size-4" /> 44 - 45 - <AlertTitle>Error fetching data.</AlertTitle> 46 - <AlertDescription> 47 - The data you were trying to see failed to fetch.<br/> 48 - <b>Error code: {errMsg}</b> 49 - </AlertDescription> 50 - </Alert> 51 - ) 52 - } else if (query.data) { 53 - return children; 54 - } 55 - return noData; 56 - }; 57 - 58 - export default QueryPlaceholder;
-72
apps/web/src/components/recipe-card.tsx
··· 1 - import { BlueRecipesFeedGetRecipes } from "@atcute/client/lexicons"; 2 - import { Card, CardContent, CardFooter, CardHeader } from "./ui/card"; 3 - import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar"; 4 - import { Link } from "@tanstack/react-router"; 5 - import { Clock, ListOrdered, Users, Utensils } from "lucide-react"; 6 - 7 - type RecipeCardProps = { 8 - recipe: BlueRecipesFeedGetRecipes.Result; 9 - }; 10 - 11 - function truncateDescription(description: string, maxLength: number = 120) { 12 - if (description.length <= maxLength) return description; 13 - return description.slice(0, maxLength).trim() + '...'; 14 - } 15 - 16 - export const RecipeCard = ({ recipe }: RecipeCardProps) => { 17 - return ( 18 - <Link to="/recipes/$author/$rkey" params={{ author: recipe.author.handle, rkey: recipe.rkey }} className="w-full"> 19 - <Card className="overflow-hidden"> 20 - <CardHeader className="p-0"> 21 - { recipe.imageUrl && 22 - <div className="relative h-48 w-full"> 23 - <img 24 - src={recipe.imageUrl} 25 - alt={recipe.title} 26 - className="h-full w-full object-cover" 27 - /> 28 - </div> 29 - } 30 - </CardHeader> 31 - <CardContent className="p-4"> 32 - <h3 className="text-lg font-semibold mb-2">{recipe.title}</h3> 33 - <p className="text-sm text-muted-foreground mb-4"> 34 - {truncateDescription(recipe.description || '')} 35 - </p> 36 - </CardContent> 37 - <CardFooter className="p-4 pt-0"> 38 - <div className="w-full flex items-center justify-between"> 39 - <div className="flex items-center"> 40 - <Avatar className="h-8 w-8 mr-2"> 41 - <AvatarImage src={recipe.author.avatarUrl} alt={recipe.author.displayName} /> 42 - <AvatarFallback className="rounded-lg">{recipe.author.displayName?.charAt(0)}</AvatarFallback> 43 - </Avatar> 44 - <span className="text-sm text-muted-foreground">{recipe.author.displayName}</span> 45 - </div> 46 - <div className="flex gap-6 justify-between items-center text-sm text-muted-foreground"> 47 - <div className="flex items-center"> 48 - <Utensils className="w-4 h-4 mr-1" /> 49 - <span>{recipe.ingredients}</span> 50 - </div> 51 - 52 - <div className="flex items-center"> 53 - <ListOrdered className="w-4 h-4 mr-1" /> 54 - <span>{recipe.steps}</span> 55 - </div> 56 - 57 - <div className="flex items-center"> 58 - <Users className="w-4 h-4 mr-1" /> 59 - <span>{recipe.serves}</span> 60 - </div> 61 - 62 - <div className="flex items-center"> 63 - <Clock className="w-4 h-4 mr-1" /> 64 - <span>{recipe.time} min</span> 65 - </div> 66 - </div> 67 - </div> 68 - </CardFooter> 69 - </Card> 70 - </Link> 71 - ); 72 - };
-23
apps/web/src/components/sidebar-title.tsx
··· 1 - import { CookingPot } from "lucide-react" 2 - 3 - import { 4 - SidebarMenu, 5 - SidebarMenuItem, 6 - } from "@/components/ui/sidebar" 7 - import { ModeToggle } from "./mode-toggle" 8 - 9 - export function SidebarTitle() { 10 - return ( 11 - <SidebarMenu> 12 - <SidebarMenuItem> 13 - <div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground"> 14 - <CookingPot className="size-4" /> 15 - </div> 16 - <div className="flex flex-col gap-0.5 leading-none"> 17 - <span className="font-semibold">Recipes</span> 18 - </div> 19 - <ModeToggle /> 20 - </SidebarMenuItem> 21 - </SidebarMenu> 22 - ) 23 - }
-73
apps/web/src/components/theme-provider.tsx
··· 1 - import { createContext, useContext, useEffect, useState } from "react" 2 - 3 - type Theme = "dark" | "light" | "system" 4 - 5 - type ThemeProviderProps = { 6 - children: React.ReactNode 7 - defaultTheme?: Theme 8 - storageKey?: string 9 - } 10 - 11 - type ThemeProviderState = { 12 - theme: Theme 13 - setTheme: (theme: Theme) => void 14 - } 15 - 16 - const initialState: ThemeProviderState = { 17 - theme: "system", 18 - setTheme: () => null, 19 - } 20 - 21 - const ThemeProviderContext = createContext<ThemeProviderState>(initialState) 22 - 23 - export function ThemeProvider({ 24 - children, 25 - defaultTheme = "system", 26 - storageKey = "vite-ui-theme", 27 - ...props 28 - }: ThemeProviderProps) { 29 - const [theme, setTheme] = useState<Theme>( 30 - () => (localStorage.getItem(storageKey) as Theme) || defaultTheme 31 - ) 32 - 33 - useEffect(() => { 34 - const root = window.document.documentElement 35 - 36 - root.classList.remove("light", "dark") 37 - 38 - if (theme === "system") { 39 - const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") 40 - .matches 41 - ? "dark" 42 - : "light" 43 - 44 - root.classList.add(systemTheme) 45 - return 46 - } 47 - 48 - root.classList.add(theme) 49 - }, [theme]) 50 - 51 - const value = { 52 - theme, 53 - setTheme: (theme: Theme) => { 54 - localStorage.setItem(storageKey, theme) 55 - setTheme(theme) 56 - }, 57 - } 58 - 59 - return ( 60 - <ThemeProviderContext.Provider {...props} value={value}> 61 - {children} 62 - </ThemeProviderContext.Provider> 63 - ) 64 - } 65 - 66 - export const useTheme = () => { 67 - const context = useContext(ThemeProviderContext) 68 - 69 - if (context === undefined) 70 - throw new Error("useTheme must be used within a ThemeProvider") 71 - 72 - return context 73 - }
-59
apps/web/src/components/ui/alert.tsx
··· 1 - import * as React from "react" 2 - import { cva, type VariantProps } from "class-variance-authority" 3 - 4 - import { cn } from "@/lib/utils" 5 - 6 - const alertVariants = cva( 7 - "relative w-full rounded-lg border px-4 py-3 text-sm [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", 8 - { 9 - variants: { 10 - variant: { 11 - default: "bg-background text-foreground", 12 - destructive: 13 - "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive", 14 - }, 15 - }, 16 - defaultVariants: { 17 - variant: "default", 18 - }, 19 - } 20 - ) 21 - 22 - const Alert = React.forwardRef< 23 - HTMLDivElement, 24 - React.HTMLAttributes<HTMLDivElement> & VariantProps<typeof alertVariants> 25 - >(({ className, variant, ...props }, ref) => ( 26 - <div 27 - ref={ref} 28 - role="alert" 29 - className={cn(alertVariants({ variant }), className)} 30 - {...props} 31 - /> 32 - )) 33 - Alert.displayName = "Alert" 34 - 35 - const AlertTitle = React.forwardRef< 36 - HTMLParagraphElement, 37 - React.HTMLAttributes<HTMLHeadingElement> 38 - >(({ className, ...props }, ref) => ( 39 - <h5 40 - ref={ref} 41 - className={cn("mb-1 font-medium leading-none tracking-tight", className)} 42 - {...props} 43 - /> 44 - )) 45 - AlertTitle.displayName = "AlertTitle" 46 - 47 - const AlertDescription = React.forwardRef< 48 - HTMLParagraphElement, 49 - React.HTMLAttributes<HTMLParagraphElement> 50 - >(({ className, ...props }, ref) => ( 51 - <div 52 - ref={ref} 53 - className={cn("text-sm [&_p]:leading-relaxed", className)} 54 - {...props} 55 - /> 56 - )) 57 - AlertDescription.displayName = "AlertDescription" 58 - 59 - export { Alert, AlertTitle, AlertDescription }
+42 -39
apps/web/src/components/ui/avatar.tsx
··· 3 3 4 4 import { cn } from "@/lib/utils" 5 5 6 - const Avatar = React.forwardRef< 7 - React.ElementRef<typeof AvatarPrimitive.Root>, 8 - React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Root> 9 - >(({ className, ...props }, ref) => ( 10 - <AvatarPrimitive.Root 11 - ref={ref} 12 - className={cn( 13 - "relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full", 14 - className 15 - )} 16 - {...props} 17 - /> 18 - )) 19 - Avatar.displayName = AvatarPrimitive.Root.displayName 6 + function Avatar({ 7 + className, 8 + ...props 9 + }: React.ComponentProps<typeof AvatarPrimitive.Root>) { 10 + return ( 11 + <AvatarPrimitive.Root 12 + data-slot="avatar" 13 + className={cn( 14 + "relative flex size-8 shrink-0 overflow-hidden rounded-full", 15 + className 16 + )} 17 + {...props} 18 + /> 19 + ) 20 + } 20 21 21 - const AvatarImage = React.forwardRef< 22 - React.ElementRef<typeof AvatarPrimitive.Image>, 23 - React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Image> 24 - >(({ className, ...props }, ref) => ( 25 - <AvatarPrimitive.Image 26 - ref={ref} 27 - className={cn("aspect-square h-full w-full", className)} 28 - {...props} 29 - /> 30 - )) 31 - AvatarImage.displayName = AvatarPrimitive.Image.displayName 22 + function AvatarImage({ 23 + className, 24 + ...props 25 + }: React.ComponentProps<typeof AvatarPrimitive.Image>) { 26 + return ( 27 + <AvatarPrimitive.Image 28 + data-slot="avatar-image" 29 + className={cn("aspect-square size-full", className)} 30 + {...props} 31 + /> 32 + ) 33 + } 32 34 33 - const AvatarFallback = React.forwardRef< 34 - React.ElementRef<typeof AvatarPrimitive.Fallback>, 35 - React.ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback> 36 - >(({ className, ...props }, ref) => ( 37 - <AvatarPrimitive.Fallback 38 - ref={ref} 39 - className={cn( 40 - "flex h-full w-full items-center justify-center rounded-full bg-muted", 41 - className 42 - )} 43 - {...props} 44 - /> 45 - )) 46 - AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName 35 + function AvatarFallback({ 36 + className, 37 + ...props 38 + }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) { 39 + return ( 40 + <AvatarPrimitive.Fallback 41 + data-slot="avatar-fallback" 42 + className={cn( 43 + "bg-muted flex size-full items-center justify-center rounded-full", 44 + className 45 + )} 46 + {...props} 47 + /> 48 + ) 49 + } 47 50 48 51 export { Avatar, AvatarImage, AvatarFallback }
-36
apps/web/src/components/ui/badge.tsx
··· 1 - import * as React from "react" 2 - import { cva, type VariantProps } from "class-variance-authority" 3 - 4 - import { cn } from "@/lib/utils" 5 - 6 - const badgeVariants = cva( 7 - "inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", 8 - { 9 - variants: { 10 - variant: { 11 - default: 12 - "border-transparent bg-primary text-primary-foreground shadow hover:bg-primary/80", 13 - secondary: 14 - "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80", 15 - destructive: 16 - "border-transparent bg-destructive text-destructive-foreground shadow hover:bg-destructive/80", 17 - outline: "text-foreground", 18 - }, 19 - }, 20 - defaultVariants: { 21 - variant: "default", 22 - }, 23 - } 24 - ) 25 - 26 - export interface BadgeProps 27 - extends React.HTMLAttributes<HTMLDivElement>, 28 - VariantProps<typeof badgeVariants> {} 29 - 30 - function Badge({ className, variant, ...props }: BadgeProps) { 31 - return ( 32 - <div className={cn(badgeVariants({ variant }), className)} {...props} /> 33 - ) 34 - } 35 - 36 - export { Badge, badgeVariants }
-115
apps/web/src/components/ui/breadcrumb.tsx
··· 1 - import * as React from "react" 2 - import { Slot } from "@radix-ui/react-slot" 3 - import { ChevronRight, MoreHorizontal } from "lucide-react" 4 - 5 - import { cn } from "@/lib/utils" 6 - 7 - const Breadcrumb = React.forwardRef< 8 - HTMLElement, 9 - React.ComponentPropsWithoutRef<"nav"> & { 10 - separator?: React.ReactNode 11 - } 12 - >(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />) 13 - Breadcrumb.displayName = "Breadcrumb" 14 - 15 - const BreadcrumbList = React.forwardRef< 16 - HTMLOListElement, 17 - React.ComponentPropsWithoutRef<"ol"> 18 - >(({ className, ...props }, ref) => ( 19 - <ol 20 - ref={ref} 21 - className={cn( 22 - "flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5", 23 - className 24 - )} 25 - {...props} 26 - /> 27 - )) 28 - BreadcrumbList.displayName = "BreadcrumbList" 29 - 30 - const BreadcrumbItem = React.forwardRef< 31 - HTMLLIElement, 32 - React.ComponentPropsWithoutRef<"li"> 33 - >(({ className, ...props }, ref) => ( 34 - <li 35 - ref={ref} 36 - className={cn("inline-flex items-center gap-1.5", className)} 37 - {...props} 38 - /> 39 - )) 40 - BreadcrumbItem.displayName = "BreadcrumbItem" 41 - 42 - const BreadcrumbLink = React.forwardRef< 43 - HTMLAnchorElement, 44 - React.ComponentPropsWithoutRef<"a"> & { 45 - asChild?: boolean 46 - } 47 - >(({ asChild, className, ...props }, ref) => { 48 - const Comp = asChild ? Slot : "a" 49 - 50 - return ( 51 - <Comp 52 - ref={ref} 53 - className={cn("transition-colors hover:text-foreground", className)} 54 - {...props} 55 - /> 56 - ) 57 - }) 58 - BreadcrumbLink.displayName = "BreadcrumbLink" 59 - 60 - const BreadcrumbPage = React.forwardRef< 61 - HTMLSpanElement, 62 - React.ComponentPropsWithoutRef<"span"> 63 - >(({ className, ...props }, ref) => ( 64 - <span 65 - ref={ref} 66 - role="link" 67 - aria-disabled="true" 68 - aria-current="page" 69 - className={cn("font-normal text-foreground", className)} 70 - {...props} 71 - /> 72 - )) 73 - BreadcrumbPage.displayName = "BreadcrumbPage" 74 - 75 - const BreadcrumbSeparator = ({ 76 - children, 77 - className, 78 - ...props 79 - }: React.ComponentProps<"li">) => ( 80 - <li 81 - role="presentation" 82 - aria-hidden="true" 83 - className={cn("[&>svg]:w-3.5 [&>svg]:h-3.5", className)} 84 - {...props} 85 - > 86 - {children ?? <ChevronRight />} 87 - </li> 88 - ) 89 - BreadcrumbSeparator.displayName = "BreadcrumbSeparator" 90 - 91 - const BreadcrumbEllipsis = ({ 92 - className, 93 - ...props 94 - }: React.ComponentProps<"span">) => ( 95 - <span 96 - role="presentation" 97 - aria-hidden="true" 98 - className={cn("flex h-9 w-9 items-center justify-center", className)} 99 - {...props} 100 - > 101 - <MoreHorizontal className="h-4 w-4" /> 102 - <span className="sr-only">More</span> 103 - </span> 104 - ) 105 - BreadcrumbEllipsis.displayName = "BreadcrumbElipssis" 106 - 107 - export { 108 - Breadcrumb, 109 - BreadcrumbList, 110 - BreadcrumbItem, 111 - BreadcrumbLink, 112 - BreadcrumbPage, 113 - BreadcrumbSeparator, 114 - BreadcrumbEllipsis, 115 - }
+32 -29
apps/web/src/components/ui/button.tsx
··· 5 5 import { cn } from "@/lib/utils" 6 6 7 7 const buttonVariants = cva( 8 - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", 8 + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", 9 9 { 10 10 variants: { 11 11 variant: { 12 - default: 13 - "bg-primary text-primary-foreground shadow hover:bg-primary/90", 12 + default: "bg-primary text-primary-foreground hover:bg-primary/90", 14 13 destructive: 15 - "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", 14 + "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", 16 15 outline: 17 - "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", 16 + "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", 18 17 secondary: 19 - "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", 20 - ghost: "hover:bg-accent hover:text-accent-foreground", 18 + "bg-secondary text-secondary-foreground hover:bg-secondary/80", 19 + ghost: 20 + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", 21 21 link: "text-primary underline-offset-4 hover:underline", 22 22 }, 23 23 size: { 24 - default: "h-9 px-4 py-2", 25 - sm: "h-8 rounded-md px-3 text-xs", 26 - lg: "h-10 rounded-md px-8", 27 - icon: "h-9 w-9", 24 + default: "h-9 px-4 py-2 has-[>svg]:px-3", 25 + sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5", 26 + lg: "h-10 rounded-md px-6 has-[>svg]:px-4", 27 + icon: "size-9", 28 + "icon-sm": "size-8", 29 + "icon-lg": "size-10", 28 30 }, 29 31 }, 30 32 defaultVariants: { ··· 34 36 } 35 37 ) 36 38 37 - export interface ButtonProps 38 - extends React.ButtonHTMLAttributes<HTMLButtonElement>, 39 - VariantProps<typeof buttonVariants> { 40 - asChild?: boolean 41 - } 39 + function Button({ 40 + className, 41 + variant, 42 + size, 43 + asChild = false, 44 + ...props 45 + }: React.ComponentProps<"button"> & 46 + VariantProps<typeof buttonVariants> & { 47 + asChild?: boolean 48 + }) { 49 + const Comp = asChild ? Slot : "button" 42 50 43 - const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( 44 - ({ className, variant, size, asChild = false, ...props }, ref) => { 45 - const Comp = asChild ? Slot : "button" 46 - return ( 47 - <Comp 48 - className={cn(buttonVariants({ variant, size, className }))} 49 - ref={ref} 50 - {...props} 51 - /> 52 - ) 53 - } 54 - ) 55 - Button.displayName = "Button" 51 + return ( 52 + <Comp 53 + data-slot="button" 54 + className={cn(buttonVariants({ variant, size, className }))} 55 + {...props} 56 + /> 57 + ) 58 + } 56 59 57 60 export { Button, buttonVariants }
+82 -66
apps/web/src/components/ui/card.tsx
··· 2 2 3 3 import { cn } from "@/lib/utils" 4 4 5 - const Card = React.forwardRef< 6 - HTMLDivElement, 7 - React.HTMLAttributes<HTMLDivElement> 8 - >(({ className, ...props }, ref) => ( 9 - <div 10 - ref={ref} 11 - className={cn( 12 - "rounded-xl border bg-card text-card-foreground shadow", 13 - className 14 - )} 15 - {...props} 16 - /> 17 - )) 18 - Card.displayName = "Card" 5 + function Card({ className, ...props }: React.ComponentProps<"div">) { 6 + return ( 7 + <div 8 + data-slot="card" 9 + className={cn( 10 + "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm", 11 + className 12 + )} 13 + {...props} 14 + /> 15 + ) 16 + } 19 17 20 - const CardHeader = React.forwardRef< 21 - HTMLDivElement, 22 - React.HTMLAttributes<HTMLDivElement> 23 - >(({ className, ...props }, ref) => ( 24 - <div 25 - ref={ref} 26 - className={cn("flex flex-col space-y-1.5 p-6", className)} 27 - {...props} 28 - /> 29 - )) 30 - CardHeader.displayName = "CardHeader" 18 + function CardHeader({ className, ...props }: React.ComponentProps<"div">) { 19 + return ( 20 + <div 21 + data-slot="card-header" 22 + className={cn( 23 + "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6", 24 + className 25 + )} 26 + {...props} 27 + /> 28 + ) 29 + } 31 30 32 - const CardTitle = React.forwardRef< 33 - HTMLDivElement, 34 - React.HTMLAttributes<HTMLDivElement> 35 - >(({ className, ...props }, ref) => ( 36 - <div 37 - ref={ref} 38 - className={cn("font-semibold leading-none tracking-tight", className)} 39 - {...props} 40 - /> 41 - )) 42 - CardTitle.displayName = "CardTitle" 31 + function CardTitle({ className, ...props }: React.ComponentProps<"div">) { 32 + return ( 33 + <div 34 + data-slot="card-title" 35 + className={cn("leading-none font-semibold", className)} 36 + {...props} 37 + /> 38 + ) 39 + } 43 40 44 - const CardDescription = React.forwardRef< 45 - HTMLDivElement, 46 - React.HTMLAttributes<HTMLDivElement> 47 - >(({ className, ...props }, ref) => ( 48 - <div 49 - ref={ref} 50 - className={cn("text-sm text-muted-foreground", className)} 51 - {...props} 52 - /> 53 - )) 54 - CardDescription.displayName = "CardDescription" 41 + function CardDescription({ className, ...props }: React.ComponentProps<"div">) { 42 + return ( 43 + <div 44 + data-slot="card-description" 45 + className={cn("text-muted-foreground text-sm", className)} 46 + {...props} 47 + /> 48 + ) 49 + } 55 50 56 - const CardContent = React.forwardRef< 57 - HTMLDivElement, 58 - React.HTMLAttributes<HTMLDivElement> 59 - >(({ className, ...props }, ref) => ( 60 - <div ref={ref} className={cn("p-6 pt-0", className)} {...props} /> 61 - )) 62 - CardContent.displayName = "CardContent" 51 + function CardAction({ className, ...props }: React.ComponentProps<"div">) { 52 + return ( 53 + <div 54 + data-slot="card-action" 55 + className={cn( 56 + "col-start-2 row-span-2 row-start-1 self-start justify-self-end", 57 + className 58 + )} 59 + {...props} 60 + /> 61 + ) 62 + } 63 63 64 - const CardFooter = React.forwardRef< 65 - HTMLDivElement, 66 - React.HTMLAttributes<HTMLDivElement> 67 - >(({ className, ...props }, ref) => ( 68 - <div 69 - ref={ref} 70 - className={cn("flex items-center p-6 pt-0", className)} 71 - {...props} 72 - /> 73 - )) 74 - CardFooter.displayName = "CardFooter" 64 + function CardContent({ className, ...props }: React.ComponentProps<"div">) { 65 + return ( 66 + <div 67 + data-slot="card-content" 68 + className={cn("px-6", className)} 69 + {...props} 70 + /> 71 + ) 72 + } 73 + 74 + function CardFooter({ className, ...props }: React.ComponentProps<"div">) { 75 + return ( 76 + <div 77 + data-slot="card-footer" 78 + className={cn("flex items-center px-6 [.border-t]:pt-6", className)} 79 + {...props} 80 + /> 81 + ) 82 + } 75 83 76 - export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent } 84 + export { 85 + Card, 86 + CardHeader, 87 + CardFooter, 88 + CardTitle, 89 + CardAction, 90 + CardDescription, 91 + CardContent, 92 + }
-9
apps/web/src/components/ui/collapsible.tsx
··· 1 - import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 2 - 3 - const Collapsible = CollapsiblePrimitive.Root 4 - 5 - const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 6 - 7 - const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 8 - 9 - export { Collapsible, CollapsibleTrigger, CollapsibleContent }
+212 -156
apps/web/src/components/ui/dropdown-menu.tsx
··· 2 2 3 3 import * as React from "react" 4 4 import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" 5 - import { Check, ChevronRight, Circle } from "lucide-react" 5 + import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" 6 6 7 7 import { cn } from "@/lib/utils" 8 8 9 - const DropdownMenu = DropdownMenuPrimitive.Root 9 + function DropdownMenu({ 10 + ...props 11 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) { 12 + return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} /> 13 + } 10 14 11 - const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger 15 + function DropdownMenuPortal({ 16 + ...props 17 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) { 18 + return ( 19 + <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} /> 20 + ) 21 + } 12 22 13 - const DropdownMenuGroup = DropdownMenuPrimitive.Group 23 + function DropdownMenuTrigger({ 24 + ...props 25 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) { 26 + return ( 27 + <DropdownMenuPrimitive.Trigger 28 + data-slot="dropdown-menu-trigger" 29 + {...props} 30 + /> 31 + ) 32 + } 14 33 15 - const DropdownMenuPortal = DropdownMenuPrimitive.Portal 34 + function DropdownMenuContent({ 35 + className, 36 + sideOffset = 4, 37 + ...props 38 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) { 39 + return ( 40 + <DropdownMenuPrimitive.Portal> 41 + <DropdownMenuPrimitive.Content 42 + data-slot="dropdown-menu-content" 43 + sideOffset={sideOffset} 44 + className={cn( 45 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md", 46 + className 47 + )} 48 + {...props} 49 + /> 50 + </DropdownMenuPrimitive.Portal> 51 + ) 52 + } 16 53 17 - const DropdownMenuSub = DropdownMenuPrimitive.Sub 54 + function DropdownMenuGroup({ 55 + ...props 56 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) { 57 + return ( 58 + <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} /> 59 + ) 60 + } 18 61 19 - const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup 62 + function DropdownMenuItem({ 63 + className, 64 + inset, 65 + variant = "default", 66 + ...props 67 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & { 68 + inset?: boolean 69 + variant?: "default" | "destructive" 70 + }) { 71 + return ( 72 + <DropdownMenuPrimitive.Item 73 + data-slot="dropdown-menu-item" 74 + data-inset={inset} 75 + data-variant={variant} 76 + className={cn( 77 + "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 78 + className 79 + )} 80 + {...props} 81 + /> 82 + ) 83 + } 20 84 21 - const DropdownMenuSubTrigger = React.forwardRef< 22 - React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>, 23 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & { 24 - inset?: boolean 25 - } 26 - >(({ className, inset, children, ...props }, ref) => ( 27 - <DropdownMenuPrimitive.SubTrigger 28 - ref={ref} 29 - className={cn( 30 - "flex cursor-default gap-2 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", 31 - inset && "pl-8", 32 - className 33 - )} 34 - {...props} 35 - > 36 - {children} 37 - <ChevronRight className="ml-auto" /> 38 - </DropdownMenuPrimitive.SubTrigger> 39 - )) 40 - DropdownMenuSubTrigger.displayName = 41 - DropdownMenuPrimitive.SubTrigger.displayName 85 + function DropdownMenuCheckboxItem({ 86 + className, 87 + children, 88 + checked, 89 + ...props 90 + }: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) { 91 + return ( 92 + <DropdownMenuPrimitive.CheckboxItem 93 + data-slot="dropdown-menu-checkbox-item" 94 + className={cn( 95 + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 96 + className 97 + )} 98 + checked={checked} 99 + {...props} 100 + > 101 + <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center"> 102 + <DropdownMenuPrimitive.ItemIndicator> 103 + <CheckIcon className="size-4" /> 104 + </DropdownMenuPrimitive.ItemIndicator> 105 + </span> 106 + {children} 107 + </DropdownMenuPrimitive.CheckboxItem> 108 + ) 109 + } 42 110 43 - const DropdownMenuSubContent = React.forwardRef< 44 - React.ElementRef<typeof DropdownMenuPrimitive.SubContent>, 45 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent> 46 - >(({ className, ...props }, ref) => ( 47 - <DropdownMenuPrimitive.SubContent 48 - ref={ref} 49 - className={cn( 50 - "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 51 - className 52 - )} 53 - {...props} 54 - /> 55 - )) 56 - DropdownMenuSubContent.displayName = 57 - DropdownMenuPrimitive.SubContent.displayName 111 + function DropdownMenuRadioGroup({ 112 + ...props 113 + }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) { 114 + return ( 115 + <DropdownMenuPrimitive.RadioGroup 116 + data-slot="dropdown-menu-radio-group" 117 + {...props} 118 + /> 119 + ) 120 + } 58 121 59 - const DropdownMenuContent = React.forwardRef< 60 - React.ElementRef<typeof DropdownMenuPrimitive.Content>, 61 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content> 62 - >(({ className, sideOffset = 4, ...props }, ref) => ( 63 - <DropdownMenuPrimitive.Portal> 64 - <DropdownMenuPrimitive.Content 65 - ref={ref} 66 - sideOffset={sideOffset} 122 + function DropdownMenuRadioItem({ 123 + className, 124 + children, 125 + ...props 126 + }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) { 127 + return ( 128 + <DropdownMenuPrimitive.RadioItem 129 + data-slot="dropdown-menu-radio-item" 67 130 className={cn( 68 - "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md", 69 - "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 131 + "focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 70 132 className 71 133 )} 72 134 {...props} 73 - /> 74 - </DropdownMenuPrimitive.Portal> 75 - )) 76 - DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName 135 + > 136 + <span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center"> 137 + <DropdownMenuPrimitive.ItemIndicator> 138 + <CircleIcon className="size-2 fill-current" /> 139 + </DropdownMenuPrimitive.ItemIndicator> 140 + </span> 141 + {children} 142 + </DropdownMenuPrimitive.RadioItem> 143 + ) 144 + } 77 145 78 - const DropdownMenuItem = React.forwardRef< 79 - React.ElementRef<typeof DropdownMenuPrimitive.Item>, 80 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & { 81 - inset?: boolean 82 - } 83 - >(({ className, inset, ...props }, ref) => ( 84 - <DropdownMenuPrimitive.Item 85 - ref={ref} 86 - className={cn( 87 - "relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0", 88 - inset && "pl-8", 89 - className 90 - )} 91 - {...props} 92 - /> 93 - )) 94 - DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName 146 + function DropdownMenuLabel({ 147 + className, 148 + inset, 149 + ...props 150 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & { 151 + inset?: boolean 152 + }) { 153 + return ( 154 + <DropdownMenuPrimitive.Label 155 + data-slot="dropdown-menu-label" 156 + data-inset={inset} 157 + className={cn( 158 + "px-2 py-1.5 text-sm font-medium data-[inset]:pl-8", 159 + className 160 + )} 161 + {...props} 162 + /> 163 + ) 164 + } 95 165 96 - const DropdownMenuCheckboxItem = React.forwardRef< 97 - React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>, 98 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem> 99 - >(({ className, children, checked, ...props }, ref) => ( 100 - <DropdownMenuPrimitive.CheckboxItem 101 - ref={ref} 102 - className={cn( 103 - "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 104 - className 105 - )} 106 - checked={checked} 107 - {...props} 108 - > 109 - <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> 110 - <DropdownMenuPrimitive.ItemIndicator> 111 - <Check className="h-4 w-4" /> 112 - </DropdownMenuPrimitive.ItemIndicator> 113 - </span> 114 - {children} 115 - </DropdownMenuPrimitive.CheckboxItem> 116 - )) 117 - DropdownMenuCheckboxItem.displayName = 118 - DropdownMenuPrimitive.CheckboxItem.displayName 166 + function DropdownMenuSeparator({ 167 + className, 168 + ...props 169 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) { 170 + return ( 171 + <DropdownMenuPrimitive.Separator 172 + data-slot="dropdown-menu-separator" 173 + className={cn("bg-border -mx-1 my-1 h-px", className)} 174 + {...props} 175 + /> 176 + ) 177 + } 119 178 120 - const DropdownMenuRadioItem = React.forwardRef< 121 - React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>, 122 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> 123 - >(({ className, children, ...props }, ref) => ( 124 - <DropdownMenuPrimitive.RadioItem 125 - ref={ref} 126 - className={cn( 127 - "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50", 128 - className 129 - )} 130 - {...props} 131 - > 132 - <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center"> 133 - <DropdownMenuPrimitive.ItemIndicator> 134 - <Circle className="h-2 w-2 fill-current" /> 135 - </DropdownMenuPrimitive.ItemIndicator> 136 - </span> 137 - {children} 138 - </DropdownMenuPrimitive.RadioItem> 139 - )) 140 - DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName 179 + function DropdownMenuShortcut({ 180 + className, 181 + ...props 182 + }: React.ComponentProps<"span">) { 183 + return ( 184 + <span 185 + data-slot="dropdown-menu-shortcut" 186 + className={cn( 187 + "text-muted-foreground ml-auto text-xs tracking-widest", 188 + className 189 + )} 190 + {...props} 191 + /> 192 + ) 193 + } 141 194 142 - const DropdownMenuLabel = React.forwardRef< 143 - React.ElementRef<typeof DropdownMenuPrimitive.Label>, 144 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & { 145 - inset?: boolean 146 - } 147 - >(({ className, inset, ...props }, ref) => ( 148 - <DropdownMenuPrimitive.Label 149 - ref={ref} 150 - className={cn( 151 - "px-2 py-1.5 text-sm font-semibold", 152 - inset && "pl-8", 153 - className 154 - )} 155 - {...props} 156 - /> 157 - )) 158 - DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName 195 + function DropdownMenuSub({ 196 + ...props 197 + }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) { 198 + return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} /> 199 + } 159 200 160 - const DropdownMenuSeparator = React.forwardRef< 161 - React.ElementRef<typeof DropdownMenuPrimitive.Separator>, 162 - React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator> 163 - >(({ className, ...props }, ref) => ( 164 - <DropdownMenuPrimitive.Separator 165 - ref={ref} 166 - className={cn("-mx-1 my-1 h-px bg-muted", className)} 167 - {...props} 168 - /> 169 - )) 170 - DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName 201 + function DropdownMenuSubTrigger({ 202 + className, 203 + inset, 204 + children, 205 + ...props 206 + }: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & { 207 + inset?: boolean 208 + }) { 209 + return ( 210 + <DropdownMenuPrimitive.SubTrigger 211 + data-slot="dropdown-menu-sub-trigger" 212 + data-inset={inset} 213 + className={cn( 214 + "focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", 215 + className 216 + )} 217 + {...props} 218 + > 219 + {children} 220 + <ChevronRightIcon className="ml-auto size-4" /> 221 + </DropdownMenuPrimitive.SubTrigger> 222 + ) 223 + } 171 224 172 - const DropdownMenuShortcut = ({ 225 + function DropdownMenuSubContent({ 173 226 className, 174 227 ...props 175 - }: React.HTMLAttributes<HTMLSpanElement>) => { 228 + }: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) { 176 229 return ( 177 - <span 178 - className={cn("ml-auto text-xs tracking-widest opacity-60", className)} 230 + <DropdownMenuPrimitive.SubContent 231 + data-slot="dropdown-menu-sub-content" 232 + className={cn( 233 + "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg", 234 + className 235 + )} 179 236 {...props} 180 237 /> 181 238 ) 182 239 } 183 - DropdownMenuShortcut.displayName = "DropdownMenuShortcut" 184 240 185 241 export { 186 242 DropdownMenu, 243 + DropdownMenuPortal, 187 244 DropdownMenuTrigger, 188 245 DropdownMenuContent, 246 + DropdownMenuGroup, 247 + DropdownMenuLabel, 189 248 DropdownMenuItem, 190 249 DropdownMenuCheckboxItem, 250 + DropdownMenuRadioGroup, 191 251 DropdownMenuRadioItem, 192 - DropdownMenuLabel, 193 252 DropdownMenuSeparator, 194 253 DropdownMenuShortcut, 195 - DropdownMenuGroup, 196 - DropdownMenuPortal, 197 254 DropdownMenuSub, 255 + DropdownMenuSubTrigger, 198 256 DropdownMenuSubContent, 199 - DropdownMenuSubTrigger, 200 - DropdownMenuRadioGroup, 201 257 }
+248
apps/web/src/components/ui/field.tsx
··· 1 + "use client" 2 + 3 + import { useMemo } from "react" 4 + import { cva, type VariantProps } from "class-variance-authority" 5 + 6 + import { cn } from "@/lib/utils" 7 + import { Label } from "@/components/ui/label" 8 + import { Separator } from "@/components/ui/separator" 9 + 10 + function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { 11 + return ( 12 + <fieldset 13 + data-slot="field-set" 14 + className={cn( 15 + "flex flex-col gap-6", 16 + "has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3", 17 + className 18 + )} 19 + {...props} 20 + /> 21 + ) 22 + } 23 + 24 + function FieldLegend({ 25 + className, 26 + variant = "legend", 27 + ...props 28 + }: React.ComponentProps<"legend"> & { variant?: "legend" | "label" }) { 29 + return ( 30 + <legend 31 + data-slot="field-legend" 32 + data-variant={variant} 33 + className={cn( 34 + "mb-3 font-medium", 35 + "data-[variant=legend]:text-base", 36 + "data-[variant=label]:text-sm", 37 + className 38 + )} 39 + {...props} 40 + /> 41 + ) 42 + } 43 + 44 + function FieldGroup({ className, ...props }: React.ComponentProps<"div">) { 45 + return ( 46 + <div 47 + data-slot="field-group" 48 + className={cn( 49 + "group/field-group @container/field-group flex w-full flex-col gap-7 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4", 50 + className 51 + )} 52 + {...props} 53 + /> 54 + ) 55 + } 56 + 57 + const fieldVariants = cva( 58 + "group/field flex w-full gap-3 data-[invalid=true]:text-destructive", 59 + { 60 + variants: { 61 + orientation: { 62 + vertical: ["flex-col [&>*]:w-full [&>.sr-only]:w-auto"], 63 + horizontal: [ 64 + "flex-row items-center", 65 + "[&>[data-slot=field-label]]:flex-auto", 66 + "has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", 67 + ], 68 + responsive: [ 69 + "flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto", 70 + "@md/field-group:[&>[data-slot=field-label]]:flex-auto", 71 + "@md/field-group:has-[>[data-slot=field-content]]:items-start @md/field-group:has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", 72 + ], 73 + }, 74 + }, 75 + defaultVariants: { 76 + orientation: "vertical", 77 + }, 78 + } 79 + ) 80 + 81 + function Field({ 82 + className, 83 + orientation = "vertical", 84 + ...props 85 + }: React.ComponentProps<"div"> & VariantProps<typeof fieldVariants>) { 86 + return ( 87 + <div 88 + role="group" 89 + data-slot="field" 90 + data-orientation={orientation} 91 + className={cn(fieldVariants({ orientation }), className)} 92 + {...props} 93 + /> 94 + ) 95 + } 96 + 97 + function FieldContent({ className, ...props }: React.ComponentProps<"div">) { 98 + return ( 99 + <div 100 + data-slot="field-content" 101 + className={cn( 102 + "group/field-content flex flex-1 flex-col gap-1.5 leading-snug", 103 + className 104 + )} 105 + {...props} 106 + /> 107 + ) 108 + } 109 + 110 + function FieldLabel({ 111 + className, 112 + ...props 113 + }: React.ComponentProps<typeof Label>) { 114 + return ( 115 + <Label 116 + data-slot="field-label" 117 + className={cn( 118 + "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50", 119 + "has-[>[data-slot=field]]:w-full has-[>[data-slot=field]]:flex-col has-[>[data-slot=field]]:rounded-md has-[>[data-slot=field]]:border [&>*]:data-[slot=field]:p-4", 120 + "has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10", 121 + className 122 + )} 123 + {...props} 124 + /> 125 + ) 126 + } 127 + 128 + function FieldTitle({ className, ...props }: React.ComponentProps<"div">) { 129 + return ( 130 + <div 131 + data-slot="field-label" 132 + className={cn( 133 + "flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50", 134 + className 135 + )} 136 + {...props} 137 + /> 138 + ) 139 + } 140 + 141 + function FieldDescription({ className, ...props }: React.ComponentProps<"p">) { 142 + return ( 143 + <p 144 + data-slot="field-description" 145 + className={cn( 146 + "text-muted-foreground text-sm leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance", 147 + "last:mt-0 nth-last-2:-mt-1 [[data-variant=legend]+&]:-mt-1.5", 148 + "[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", 149 + className 150 + )} 151 + {...props} 152 + /> 153 + ) 154 + } 155 + 156 + function FieldSeparator({ 157 + children, 158 + className, 159 + ...props 160 + }: React.ComponentProps<"div"> & { 161 + children?: React.ReactNode 162 + }) { 163 + return ( 164 + <div 165 + data-slot="field-separator" 166 + data-content={!!children} 167 + className={cn( 168 + "relative -my-2 h-5 text-sm group-data-[variant=outline]/field-group:-mb-2", 169 + className 170 + )} 171 + {...props} 172 + > 173 + <Separator className="absolute inset-0 top-1/2" /> 174 + {children && ( 175 + <span 176 + className="bg-background text-muted-foreground relative mx-auto block w-fit px-2" 177 + data-slot="field-separator-content" 178 + > 179 + {children} 180 + </span> 181 + )} 182 + </div> 183 + ) 184 + } 185 + 186 + function FieldError({ 187 + className, 188 + children, 189 + errors, 190 + ...props 191 + }: React.ComponentProps<"div"> & { 192 + errors?: Array<{ message?: string } | undefined> 193 + }) { 194 + const content = useMemo(() => { 195 + if (children) { 196 + return children 197 + } 198 + 199 + if (!errors?.length) { 200 + return null 201 + } 202 + 203 + const uniqueErrors = [ 204 + ...new Map(errors.map((error) => [error?.message, error])).values(), 205 + ] 206 + 207 + if (uniqueErrors?.length == 1) { 208 + return uniqueErrors[0]?.message 209 + } 210 + 211 + return ( 212 + <ul className="ml-4 flex list-disc flex-col gap-1"> 213 + {uniqueErrors.map( 214 + (error, index) => 215 + error?.message && <li key={index}>{error.message}</li> 216 + )} 217 + </ul> 218 + ) 219 + }, [children, errors]) 220 + 221 + if (!content) { 222 + return null 223 + } 224 + 225 + return ( 226 + <div 227 + role="alert" 228 + data-slot="field-error" 229 + className={cn("text-destructive text-sm font-normal", className)} 230 + {...props} 231 + > 232 + {content} 233 + </div> 234 + ) 235 + } 236 + 237 + export { 238 + Field, 239 + FieldLabel, 240 + FieldDescription, 241 + FieldError, 242 + FieldGroup, 243 + FieldLegend, 244 + FieldSeparator, 245 + FieldSet, 246 + FieldContent, 247 + FieldTitle, 248 + }
-176
apps/web/src/components/ui/form.tsx
··· 1 - import * as React from "react" 2 - import * as LabelPrimitive from "@radix-ui/react-label" 3 - import { Slot } from "@radix-ui/react-slot" 4 - import { 5 - Controller, 6 - ControllerProps, 7 - FieldPath, 8 - FieldValues, 9 - FormProvider, 10 - useFormContext, 11 - } from "react-hook-form" 12 - 13 - import { cn } from "@/lib/utils" 14 - import { Label } from "@/components/ui/label" 15 - 16 - const Form = FormProvider 17 - 18 - type FormFieldContextValue< 19 - TFieldValues extends FieldValues = FieldValues, 20 - TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> 21 - > = { 22 - name: TName 23 - } 24 - 25 - const FormFieldContext = React.createContext<FormFieldContextValue>( 26 - {} as FormFieldContextValue 27 - ) 28 - 29 - const FormField = < 30 - TFieldValues extends FieldValues = FieldValues, 31 - TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues> 32 - >({ 33 - ...props 34 - }: ControllerProps<TFieldValues, TName>) => { 35 - return ( 36 - <FormFieldContext.Provider value={{ name: props.name }}> 37 - <Controller {...props} /> 38 - </FormFieldContext.Provider> 39 - ) 40 - } 41 - 42 - const useFormField = () => { 43 - const fieldContext = React.useContext(FormFieldContext) 44 - const itemContext = React.useContext(FormItemContext) 45 - const { getFieldState, formState } = useFormContext() 46 - 47 - const fieldState = getFieldState(fieldContext.name, formState) 48 - 49 - if (!fieldContext) { 50 - throw new Error("useFormField should be used within <FormField>") 51 - } 52 - 53 - const { id } = itemContext 54 - 55 - return { 56 - id, 57 - name: fieldContext.name, 58 - formItemId: `${id}-form-item`, 59 - formDescriptionId: `${id}-form-item-description`, 60 - formMessageId: `${id}-form-item-message`, 61 - ...fieldState, 62 - } 63 - } 64 - 65 - type FormItemContextValue = { 66 - id: string 67 - } 68 - 69 - const FormItemContext = React.createContext<FormItemContextValue>( 70 - {} as FormItemContextValue 71 - ) 72 - 73 - const FormItem = React.forwardRef< 74 - HTMLDivElement, 75 - React.HTMLAttributes<HTMLDivElement> 76 - >(({ className, ...props }, ref) => { 77 - const id = React.useId() 78 - 79 - return ( 80 - <FormItemContext.Provider value={{ id }}> 81 - <div ref={ref} className={cn("space-y-2", className)} {...props} /> 82 - </FormItemContext.Provider> 83 - ) 84 - }) 85 - FormItem.displayName = "FormItem" 86 - 87 - const FormLabel = React.forwardRef< 88 - React.ElementRef<typeof LabelPrimitive.Root>, 89 - React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> 90 - >(({ className, ...props }, ref) => { 91 - const { error, formItemId } = useFormField() 92 - 93 - return ( 94 - <Label 95 - ref={ref} 96 - className={cn(error && "text-destructive", className)} 97 - htmlFor={formItemId} 98 - {...props} 99 - /> 100 - ) 101 - }) 102 - FormLabel.displayName = "FormLabel" 103 - 104 - const FormControl = React.forwardRef< 105 - React.ElementRef<typeof Slot>, 106 - React.ComponentPropsWithoutRef<typeof Slot> 107 - >(({ ...props }, ref) => { 108 - const { error, formItemId, formDescriptionId, formMessageId } = useFormField() 109 - 110 - return ( 111 - <Slot 112 - ref={ref} 113 - id={formItemId} 114 - aria-describedby={ 115 - !error 116 - ? `${formDescriptionId}` 117 - : `${formDescriptionId} ${formMessageId}` 118 - } 119 - aria-invalid={!!error} 120 - {...props} 121 - /> 122 - ) 123 - }) 124 - FormControl.displayName = "FormControl" 125 - 126 - const FormDescription = React.forwardRef< 127 - HTMLParagraphElement, 128 - React.HTMLAttributes<HTMLParagraphElement> 129 - >(({ className, ...props }, ref) => { 130 - const { formDescriptionId } = useFormField() 131 - 132 - return ( 133 - <p 134 - ref={ref} 135 - id={formDescriptionId} 136 - className={cn("text-[0.8rem] text-muted-foreground", className)} 137 - {...props} 138 - /> 139 - ) 140 - }) 141 - FormDescription.displayName = "FormDescription" 142 - 143 - const FormMessage = React.forwardRef< 144 - HTMLParagraphElement, 145 - React.HTMLAttributes<HTMLParagraphElement> 146 - >(({ className, children, ...props }, ref) => { 147 - const { error, formMessageId } = useFormField() 148 - const body = error ? String(error?.message) : children 149 - 150 - if (!body) { 151 - return null 152 - } 153 - 154 - return ( 155 - <p 156 - ref={ref} 157 - id={formMessageId} 158 - className={cn("text-[0.8rem] font-medium text-destructive", className)} 159 - {...props} 160 - > 161 - {body} 162 - </p> 163 - ) 164 - }) 165 - FormMessage.displayName = "FormMessage" 166 - 167 - export { 168 - useFormField, 169 - Form, 170 - FormItem, 171 - FormLabel, 172 - FormControl, 173 - FormDescription, 174 - FormMessage, 175 - FormField, 176 - }
+168
apps/web/src/components/ui/input-group.tsx
··· 1 + import * as React from "react" 2 + import { cva, type VariantProps } from "class-variance-authority" 3 + 4 + import { cn } from "@/lib/utils" 5 + import { Button } from "@/components/ui/button" 6 + import { Input } from "@/components/ui/input" 7 + import { Textarea } from "@/components/ui/textarea" 8 + 9 + function InputGroup({ className, ...props }: React.ComponentProps<"div">) { 10 + return ( 11 + <div 12 + data-slot="input-group" 13 + role="group" 14 + className={cn( 15 + "group/input-group border-input dark:bg-input/30 relative flex w-full items-center rounded-md border shadow-xs transition-[color,box-shadow] outline-none", 16 + "h-9 min-w-0 has-[>textarea]:h-auto", 17 + 18 + // Variants based on alignment. 19 + "has-[>[data-align=inline-start]]:[&>input]:pl-2", 20 + "has-[>[data-align=inline-end]]:[&>input]:pr-2", 21 + "has-[>[data-align=block-start]]:h-auto has-[>[data-align=block-start]]:flex-col has-[>[data-align=block-start]]:[&>input]:pb-3", 22 + "has-[>[data-align=block-end]]:h-auto has-[>[data-align=block-end]]:flex-col has-[>[data-align=block-end]]:[&>input]:pt-3", 23 + 24 + // Focus state. 25 + "has-[[data-slot=input-group-control]:focus-visible]:border-ring has-[[data-slot=input-group-control]:focus-visible]:ring-ring/50 has-[[data-slot=input-group-control]:focus-visible]:ring-[3px]", 26 + 27 + // Error state. 28 + "has-[[data-slot][aria-invalid=true]]:ring-destructive/20 has-[[data-slot][aria-invalid=true]]:border-destructive dark:has-[[data-slot][aria-invalid=true]]:ring-destructive/40", 29 + 30 + className 31 + )} 32 + {...props} 33 + /> 34 + ) 35 + } 36 + 37 + const inputGroupAddonVariants = cva( 38 + "text-muted-foreground flex h-auto cursor-text items-center justify-center gap-2 py-1.5 text-sm font-medium select-none [&>svg:not([class*='size-'])]:size-4 [&>kbd]:rounded-[calc(var(--radius)-5px)] group-data-[disabled=true]/input-group:opacity-50", 39 + { 40 + variants: { 41 + align: { 42 + "inline-start": 43 + "order-first pl-3 has-[>button]:ml-[-0.45rem] has-[>kbd]:ml-[-0.35rem]", 44 + "inline-end": 45 + "order-last pr-3 has-[>button]:mr-[-0.45rem] has-[>kbd]:mr-[-0.35rem]", 46 + "block-start": 47 + "order-first w-full justify-start px-3 pt-3 [.border-b]:pb-3 group-has-[>input]/input-group:pt-2.5", 48 + "block-end": 49 + "order-last w-full justify-start px-3 pb-3 [.border-t]:pt-3 group-has-[>input]/input-group:pb-2.5", 50 + }, 51 + }, 52 + defaultVariants: { 53 + align: "inline-start", 54 + }, 55 + } 56 + ) 57 + 58 + function InputGroupAddon({ 59 + className, 60 + align = "inline-start", 61 + ...props 62 + }: React.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) { 63 + return ( 64 + <div 65 + role="group" 66 + data-slot="input-group-addon" 67 + data-align={align} 68 + className={cn(inputGroupAddonVariants({ align }), className)} 69 + onClick={(e) => { 70 + if ((e.target as HTMLElement).closest("button")) { 71 + return 72 + } 73 + e.currentTarget.parentElement?.querySelector("input")?.focus() 74 + }} 75 + {...props} 76 + /> 77 + ) 78 + } 79 + 80 + const inputGroupButtonVariants = cva( 81 + "text-sm shadow-none flex gap-2 items-center", 82 + { 83 + variants: { 84 + size: { 85 + xs: "h-6 gap-1 px-2 rounded-[calc(var(--radius)-5px)] [&>svg:not([class*='size-'])]:size-3.5 has-[>svg]:px-2", 86 + sm: "h-8 px-2.5 gap-1.5 rounded-md has-[>svg]:px-2.5", 87 + "icon-xs": 88 + "size-6 rounded-[calc(var(--radius)-5px)] p-0 has-[>svg]:p-0", 89 + "icon-sm": "size-8 p-0 has-[>svg]:p-0", 90 + }, 91 + }, 92 + defaultVariants: { 93 + size: "xs", 94 + }, 95 + } 96 + ) 97 + 98 + function InputGroupButton({ 99 + className, 100 + type = "button", 101 + variant = "ghost", 102 + size = "xs", 103 + ...props 104 + }: Omit<React.ComponentProps<typeof Button>, "size"> & 105 + VariantProps<typeof inputGroupButtonVariants>) { 106 + return ( 107 + <Button 108 + type={type} 109 + data-size={size} 110 + variant={variant} 111 + className={cn(inputGroupButtonVariants({ size }), className)} 112 + {...props} 113 + /> 114 + ) 115 + } 116 + 117 + function InputGroupText({ className, ...props }: React.ComponentProps<"span">) { 118 + return ( 119 + <span 120 + className={cn( 121 + "text-muted-foreground flex items-center gap-2 text-sm [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4", 122 + className 123 + )} 124 + {...props} 125 + /> 126 + ) 127 + } 128 + 129 + function InputGroupInput({ 130 + className, 131 + ...props 132 + }: React.ComponentProps<"input">) { 133 + return ( 134 + <Input 135 + data-slot="input-group-control" 136 + className={cn( 137 + "flex-1 rounded-none border-0 bg-transparent shadow-none focus-visible:ring-0 dark:bg-transparent", 138 + className 139 + )} 140 + {...props} 141 + /> 142 + ) 143 + } 144 + 145 + function InputGroupTextarea({ 146 + className, 147 + ...props 148 + }: React.ComponentProps<"textarea">) { 149 + return ( 150 + <Textarea 151 + data-slot="input-group-control" 152 + className={cn( 153 + "flex-1 resize-none rounded-none border-0 bg-transparent py-3 shadow-none focus-visible:ring-0 dark:bg-transparent", 154 + className 155 + )} 156 + {...props} 157 + /> 158 + ) 159 + } 160 + 161 + export { 162 + InputGroup, 163 + InputGroupAddon, 164 + InputGroupButton, 165 + InputGroupText, 166 + InputGroupInput, 167 + InputGroupTextarea, 168 + }
+15 -16
apps/web/src/components/ui/input.tsx
··· 2 2 3 3 import { cn } from "@/lib/utils" 4 4 5 - const Input = React.forwardRef<HTMLInputElement, React.ComponentProps<"input">>( 6 - ({ className, type, ...props }, ref) => { 7 - return ( 8 - <input 9 - type={type} 10 - className={cn( 11 - "flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", 12 - className 13 - )} 14 - ref={ref} 15 - {...props} 16 - /> 17 - ) 18 - } 19 - ) 20 - Input.displayName = "Input" 5 + function Input({ className, type, ...props }: React.ComponentProps<"input">) { 6 + return ( 7 + <input 8 + type={type} 9 + data-slot="input" 10 + className={cn( 11 + "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", 12 + "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", 13 + "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", 14 + className 15 + )} 16 + {...props} 17 + /> 18 + ) 19 + } 21 20 22 21 export { Input }
+15 -17
apps/web/src/components/ui/label.tsx
··· 1 1 import * as React from "react" 2 2 import * as LabelPrimitive from "@radix-ui/react-label" 3 - import { cva, type VariantProps } from "class-variance-authority" 4 3 5 4 import { cn } from "@/lib/utils" 6 5 7 - const labelVariants = cva( 8 - "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70" 9 - ) 10 - 11 - const Label = React.forwardRef< 12 - React.ElementRef<typeof LabelPrimitive.Root>, 13 - React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> & 14 - VariantProps<typeof labelVariants> 15 - >(({ className, ...props }, ref) => ( 16 - <LabelPrimitive.Root 17 - ref={ref} 18 - className={cn(labelVariants(), className)} 19 - {...props} 20 - /> 21 - )) 22 - Label.displayName = LabelPrimitive.Root.displayName 6 + function Label({ 7 + className, 8 + ...props 9 + }: React.ComponentProps<typeof LabelPrimitive.Root>) { 10 + return ( 11 + <LabelPrimitive.Root 12 + data-slot="label" 13 + className={cn( 14 + "flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50", 15 + className 16 + )} 17 + {...props} 18 + /> 19 + ) 20 + } 23 21 24 22 export { Label }
+12 -13
apps/web/src/components/ui/separator.tsx
··· 1 + "use client" 2 + 1 3 import * as React from "react" 2 4 import * as SeparatorPrimitive from "@radix-ui/react-separator" 3 5 4 6 import { cn } from "@/lib/utils" 5 7 6 - const Separator = React.forwardRef< 7 - React.ElementRef<typeof SeparatorPrimitive.Root>, 8 - React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> 9 - >( 10 - ( 11 - { className, orientation = "horizontal", decorative = true, ...props }, 12 - ref 13 - ) => ( 8 + function Separator({ 9 + className, 10 + orientation = "horizontal", 11 + decorative = true, 12 + ...props 13 + }: React.ComponentProps<typeof SeparatorPrimitive.Root>) { 14 + return ( 14 15 <SeparatorPrimitive.Root 15 - ref={ref} 16 + data-slot="separator" 16 17 decorative={decorative} 17 18 orientation={orientation} 18 19 className={cn( 19 - "shrink-0 bg-border", 20 - orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]", 20 + "bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px", 21 21 className 22 22 )} 23 23 {...props} 24 24 /> 25 25 ) 26 - ) 27 - Separator.displayName = SeparatorPrimitive.Root.displayName 26 + } 28 27 29 28 export { Separator }
+107 -110
apps/web/src/components/ui/sheet.tsx
··· 1 - "use client" 2 - 3 1 import * as React from "react" 4 2 import * as SheetPrimitive from "@radix-ui/react-dialog" 5 - import { cva, type VariantProps } from "class-variance-authority" 6 - import { X } from "lucide-react" 3 + import { XIcon } from "lucide-react" 7 4 8 5 import { cn } from "@/lib/utils" 9 6 10 - const Sheet = SheetPrimitive.Root 7 + function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) { 8 + return <SheetPrimitive.Root data-slot="sheet" {...props} /> 9 + } 11 10 12 - const SheetTrigger = SheetPrimitive.Trigger 11 + function SheetTrigger({ 12 + ...props 13 + }: React.ComponentProps<typeof SheetPrimitive.Trigger>) { 14 + return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} /> 15 + } 13 16 14 - const SheetClose = SheetPrimitive.Close 17 + function SheetClose({ 18 + ...props 19 + }: React.ComponentProps<typeof SheetPrimitive.Close>) { 20 + return <SheetPrimitive.Close data-slot="sheet-close" {...props} /> 21 + } 15 22 16 - const SheetPortal = SheetPrimitive.Portal 23 + function SheetPortal({ 24 + ...props 25 + }: React.ComponentProps<typeof SheetPrimitive.Portal>) { 26 + return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} /> 27 + } 17 28 18 - const SheetOverlay = React.forwardRef< 19 - React.ElementRef<typeof SheetPrimitive.Overlay>, 20 - React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay> 21 - >(({ className, ...props }, ref) => ( 22 - <SheetPrimitive.Overlay 23 - className={cn( 24 - "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", 25 - className 26 - )} 27 - {...props} 28 - ref={ref} 29 - /> 30 - )) 31 - SheetOverlay.displayName = SheetPrimitive.Overlay.displayName 29 + function SheetOverlay({ 30 + className, 31 + ...props 32 + }: React.ComponentProps<typeof SheetPrimitive.Overlay>) { 33 + return ( 34 + <SheetPrimitive.Overlay 35 + data-slot="sheet-overlay" 36 + className={cn( 37 + "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", 38 + className 39 + )} 40 + {...props} 41 + /> 42 + ) 43 + } 32 44 33 - const sheetVariants = cva( 34 - "fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out", 35 - { 36 - variants: { 37 - side: { 38 - top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top", 39 - bottom: 40 - "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom", 41 - left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm", 42 - right: 43 - "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm", 44 - }, 45 - }, 46 - defaultVariants: { 47 - side: "right", 48 - }, 49 - } 50 - ) 45 + function SheetContent({ 46 + className, 47 + children, 48 + side = "right", 49 + ...props 50 + }: React.ComponentProps<typeof SheetPrimitive.Content> & { 51 + side?: "top" | "right" | "bottom" | "left" 52 + }) { 53 + return ( 54 + <SheetPortal> 55 + <SheetOverlay /> 56 + <SheetPrimitive.Content 57 + data-slot="sheet-content" 58 + className={cn( 59 + "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500", 60 + side === "right" && 61 + "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm", 62 + side === "left" && 63 + "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm", 64 + side === "top" && 65 + "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b", 66 + side === "bottom" && 67 + "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t", 68 + className 69 + )} 70 + {...props} 71 + > 72 + {children} 73 + <SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none"> 74 + <XIcon className="size-4" /> 75 + <span className="sr-only">Close</span> 76 + </SheetPrimitive.Close> 77 + </SheetPrimitive.Content> 78 + </SheetPortal> 79 + ) 80 + } 51 81 52 - interface SheetContentProps 53 - extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, 54 - VariantProps<typeof sheetVariants> {} 82 + function SheetHeader({ className, ...props }: React.ComponentProps<"div">) { 83 + return ( 84 + <div 85 + data-slot="sheet-header" 86 + className={cn("flex flex-col gap-1.5 p-4", className)} 87 + {...props} 88 + /> 89 + ) 90 + } 55 91 56 - const SheetContent = React.forwardRef< 57 - React.ElementRef<typeof SheetPrimitive.Content>, 58 - SheetContentProps 59 - >(({ side = "right", className, children, ...props }, ref) => ( 60 - <SheetPortal> 61 - <SheetOverlay /> 62 - <SheetPrimitive.Content 63 - ref={ref} 64 - className={cn(sheetVariants({ side }), className)} 92 + function SheetFooter({ className, ...props }: React.ComponentProps<"div">) { 93 + return ( 94 + <div 95 + data-slot="sheet-footer" 96 + className={cn("mt-auto flex flex-col gap-2 p-4", className)} 65 97 {...props} 66 - > 67 - <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary"> 68 - <X className="h-4 w-4" /> 69 - <span className="sr-only">Close</span> 70 - </SheetPrimitive.Close> 71 - {children} 72 - </SheetPrimitive.Content> 73 - </SheetPortal> 74 - )) 75 - SheetContent.displayName = SheetPrimitive.Content.displayName 98 + /> 99 + ) 100 + } 76 101 77 - const SheetHeader = ({ 102 + function SheetTitle({ 78 103 className, 79 104 ...props 80 - }: React.HTMLAttributes<HTMLDivElement>) => ( 81 - <div 82 - className={cn( 83 - "flex flex-col space-y-2 text-center sm:text-left", 84 - className 85 - )} 86 - {...props} 87 - /> 88 - ) 89 - SheetHeader.displayName = "SheetHeader" 105 + }: React.ComponentProps<typeof SheetPrimitive.Title>) { 106 + return ( 107 + <SheetPrimitive.Title 108 + data-slot="sheet-title" 109 + className={cn("text-foreground font-semibold", className)} 110 + {...props} 111 + /> 112 + ) 113 + } 90 114 91 - const SheetFooter = ({ 115 + function SheetDescription({ 92 116 className, 93 117 ...props 94 - }: React.HTMLAttributes<HTMLDivElement>) => ( 95 - <div 96 - className={cn( 97 - "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", 98 - className 99 - )} 100 - {...props} 101 - /> 102 - ) 103 - SheetFooter.displayName = "SheetFooter" 104 - 105 - const SheetTitle = React.forwardRef< 106 - React.ElementRef<typeof SheetPrimitive.Title>, 107 - React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title> 108 - >(({ className, ...props }, ref) => ( 109 - <SheetPrimitive.Title 110 - ref={ref} 111 - className={cn("text-lg font-semibold text-foreground", className)} 112 - {...props} 113 - /> 114 - )) 115 - SheetTitle.displayName = SheetPrimitive.Title.displayName 116 - 117 - const SheetDescription = React.forwardRef< 118 - React.ElementRef<typeof SheetPrimitive.Description>, 119 - React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description> 120 - >(({ className, ...props }, ref) => ( 121 - <SheetPrimitive.Description 122 - ref={ref} 123 - className={cn("text-sm text-muted-foreground", className)} 124 - {...props} 125 - /> 126 - )) 127 - SheetDescription.displayName = SheetPrimitive.Description.displayName 118 + }: React.ComponentProps<typeof SheetPrimitive.Description>) { 119 + return ( 120 + <SheetPrimitive.Description 121 + data-slot="sheet-description" 122 + className={cn("text-muted-foreground text-sm", className)} 123 + {...props} 124 + /> 125 + ) 126 + } 128 127 129 128 export { 130 129 Sheet, 131 - SheetPortal, 132 - SheetOverlay, 133 130 SheetTrigger, 134 131 SheetClose, 135 132 SheetContent,
+414 -453
apps/web/src/components/ui/sidebar.tsx
··· 1 - "use client" 2 - 3 1 import * as React from "react" 4 2 import { Slot } from "@radix-ui/react-slot" 5 - import { VariantProps, cva } from "class-variance-authority" 6 - import { PanelLeft } from "lucide-react" 3 + import { cva, type VariantProps } from "class-variance-authority" 4 + import { PanelLeftIcon } from "lucide-react" 7 5 8 6 import { useIsMobile } from "@/hooks/use-mobile" 9 7 import { cn } from "@/lib/utils" 10 8 import { Button } from "@/components/ui/button" 11 9 import { Input } from "@/components/ui/input" 12 10 import { Separator } from "@/components/ui/separator" 13 - import { Sheet, SheetContent } from "@/components/ui/sheet" 11 + import { 12 + Sheet, 13 + SheetContent, 14 + SheetDescription, 15 + SheetHeader, 16 + SheetTitle, 17 + } from "@/components/ui/sheet" 14 18 import { Skeleton } from "@/components/ui/skeleton" 15 19 import { 16 20 Tooltip, ··· 19 23 TooltipTrigger, 20 24 } from "@/components/ui/tooltip" 21 25 22 - const SIDEBAR_COOKIE_NAME = "sidebar:state" 26 + const SIDEBAR_COOKIE_NAME = "sidebar_state" 23 27 const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 24 28 const SIDEBAR_WIDTH = "16rem" 25 29 const SIDEBAR_WIDTH_MOBILE = "18rem" 26 30 const SIDEBAR_WIDTH_ICON = "3rem" 27 31 const SIDEBAR_KEYBOARD_SHORTCUT = "b" 28 32 29 - type SidebarContext = { 33 + type SidebarContextProps = { 30 34 state: "expanded" | "collapsed" 31 35 open: boolean 32 36 setOpen: (open: boolean) => void ··· 36 40 toggleSidebar: () => void 37 41 } 38 42 39 - const SidebarContext = React.createContext<SidebarContext | null>(null) 43 + const SidebarContext = React.createContext<SidebarContextProps | null>(null) 40 44 41 45 function useSidebar() { 42 46 const context = React.useContext(SidebarContext) ··· 47 51 return context 48 52 } 49 53 50 - const SidebarProvider = React.forwardRef< 51 - HTMLDivElement, 52 - React.ComponentProps<"div"> & { 53 - defaultOpen?: boolean 54 - open?: boolean 55 - onOpenChange?: (open: boolean) => void 56 - } 57 - >( 58 - ( 59 - { 60 - defaultOpen = true, 61 - open: openProp, 62 - onOpenChange: setOpenProp, 63 - className, 64 - style, 65 - children, 66 - ...props 67 - }, 68 - ref 69 - ) => { 70 - const isMobile = useIsMobile() 71 - const [openMobile, setOpenMobile] = React.useState(false) 54 + function SidebarProvider({ 55 + defaultOpen = true, 56 + open: openProp, 57 + onOpenChange: setOpenProp, 58 + className, 59 + style, 60 + children, 61 + ...props 62 + }: React.ComponentProps<"div"> & { 63 + defaultOpen?: boolean 64 + open?: boolean 65 + onOpenChange?: (open: boolean) => void 66 + }) { 67 + const isMobile = useIsMobile() 68 + const [openMobile, setOpenMobile] = React.useState(false) 72 69 73 - // This is the internal state of the sidebar. 74 - // We use openProp and setOpenProp for control from outside the component. 75 - const [_open, _setOpen] = React.useState(defaultOpen) 76 - const open = openProp ?? _open 77 - const setOpen = React.useCallback( 78 - (value: boolean | ((value: boolean) => boolean)) => { 79 - const openState = typeof value === "function" ? value(open) : value 80 - if (setOpenProp) { 81 - setOpenProp(openState) 82 - } else { 83 - _setOpen(openState) 84 - } 70 + // This is the internal state of the sidebar. 71 + // We use openProp and setOpenProp for control from outside the component. 72 + const [_open, _setOpen] = React.useState(defaultOpen) 73 + const open = openProp ?? _open 74 + const setOpen = React.useCallback( 75 + (value: boolean | ((value: boolean) => boolean)) => { 76 + const openState = typeof value === "function" ? value(open) : value 77 + if (setOpenProp) { 78 + setOpenProp(openState) 79 + } else { 80 + _setOpen(openState) 81 + } 85 82 86 - // This sets the cookie to keep the sidebar state. 87 - document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` 88 - }, 89 - [setOpenProp, open] 90 - ) 83 + // This sets the cookie to keep the sidebar state. 84 + document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}` 85 + }, 86 + [setOpenProp, open] 87 + ) 91 88 92 - // Helper to toggle the sidebar. 93 - const toggleSidebar = React.useCallback(() => { 94 - return isMobile 95 - ? setOpenMobile((open) => !open) 96 - : setOpen((open) => !open) 97 - }, [isMobile, setOpen, setOpenMobile]) 89 + // Helper to toggle the sidebar. 90 + const toggleSidebar = React.useCallback(() => { 91 + return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open) 92 + }, [isMobile, setOpen, setOpenMobile]) 98 93 99 - // Adds a keyboard shortcut to toggle the sidebar. 100 - React.useEffect(() => { 101 - const handleKeyDown = (event: KeyboardEvent) => { 102 - if ( 103 - event.key === SIDEBAR_KEYBOARD_SHORTCUT && 104 - (event.metaKey || event.ctrlKey) 105 - ) { 106 - event.preventDefault() 107 - toggleSidebar() 108 - } 94 + // Adds a keyboard shortcut to toggle the sidebar. 95 + React.useEffect(() => { 96 + const handleKeyDown = (event: KeyboardEvent) => { 97 + if ( 98 + event.key === SIDEBAR_KEYBOARD_SHORTCUT && 99 + (event.metaKey || event.ctrlKey) 100 + ) { 101 + event.preventDefault() 102 + toggleSidebar() 109 103 } 104 + } 110 105 111 - window.addEventListener("keydown", handleKeyDown) 112 - return () => window.removeEventListener("keydown", handleKeyDown) 113 - }, [toggleSidebar]) 114 - 115 - // We add a state so that we can do data-state="expanded" or "collapsed". 116 - // This makes it easier to style the sidebar with Tailwind classes. 117 - const state = open ? "expanded" : "collapsed" 118 - 119 - const contextValue = React.useMemo<SidebarContext>( 120 - () => ({ 121 - state, 122 - open, 123 - setOpen, 124 - isMobile, 125 - openMobile, 126 - setOpenMobile, 127 - toggleSidebar, 128 - }), 129 - [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar] 130 - ) 106 + window.addEventListener("keydown", handleKeyDown) 107 + return () => window.removeEventListener("keydown", handleKeyDown) 108 + }, [toggleSidebar]) 131 109 132 - return ( 133 - <SidebarContext.Provider value={contextValue}> 134 - <TooltipProvider delayDuration={0}> 135 - <div 136 - style={ 137 - { 138 - "--sidebar-width": SIDEBAR_WIDTH, 139 - "--sidebar-width-icon": SIDEBAR_WIDTH_ICON, 140 - ...style, 141 - } as React.CSSProperties 142 - } 143 - className={cn( 144 - "group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar", 145 - className 146 - )} 147 - ref={ref} 148 - {...props} 149 - > 150 - {children} 151 - </div> 152 - </TooltipProvider> 153 - </SidebarContext.Provider> 154 - ) 155 - } 156 - ) 157 - SidebarProvider.displayName = "SidebarProvider" 110 + // We add a state so that we can do data-state="expanded" or "collapsed". 111 + // This makes it easier to style the sidebar with Tailwind classes. 112 + const state = open ? "expanded" : "collapsed" 158 113 159 - const Sidebar = React.forwardRef< 160 - HTMLDivElement, 161 - React.ComponentProps<"div"> & { 162 - side?: "left" | "right" 163 - variant?: "sidebar" | "floating" | "inset" 164 - collapsible?: "offcanvas" | "icon" | "none" 165 - } 166 - >( 167 - ( 168 - { 169 - side = "left", 170 - variant = "sidebar", 171 - collapsible = "offcanvas", 172 - className, 173 - children, 174 - ...props 175 - }, 176 - ref 177 - ) => { 178 - const { isMobile, state, openMobile, setOpenMobile } = useSidebar() 114 + const contextValue = React.useMemo<SidebarContextProps>( 115 + () => ({ 116 + state, 117 + open, 118 + setOpen, 119 + isMobile, 120 + openMobile, 121 + setOpenMobile, 122 + toggleSidebar, 123 + }), 124 + [state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar] 125 + ) 179 126 180 - if (collapsible === "none") { 181 - return ( 127 + return ( 128 + <SidebarContext.Provider value={contextValue}> 129 + <TooltipProvider delayDuration={0}> 182 130 <div 131 + data-slot="sidebar-wrapper" 132 + style={ 133 + { 134 + "--sidebar-width": SIDEBAR_WIDTH, 135 + "--sidebar-width-icon": SIDEBAR_WIDTH_ICON, 136 + ...style, 137 + } as React.CSSProperties 138 + } 183 139 className={cn( 184 - "flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground", 140 + "group/sidebar-wrapper has-data-[variant=inset]:bg-sidebar flex min-h-svh w-full", 185 141 className 186 142 )} 187 - ref={ref} 188 143 {...props} 189 144 > 190 145 {children} 191 146 </div> 192 - ) 193 - } 147 + </TooltipProvider> 148 + </SidebarContext.Provider> 149 + ) 150 + } 194 151 195 - if (isMobile) { 196 - return ( 197 - <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}> 198 - <SheetContent 199 - data-sidebar="sidebar" 200 - data-mobile="true" 201 - className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden" 202 - style={ 203 - { 204 - "--sidebar-width": SIDEBAR_WIDTH_MOBILE, 205 - } as React.CSSProperties 206 - } 207 - side={side} 208 - > 209 - <div className="flex h-full w-full flex-col">{children}</div> 210 - </SheetContent> 211 - </Sheet> 212 - ) 213 - } 152 + function Sidebar({ 153 + side = "left", 154 + variant = "sidebar", 155 + collapsible = "offcanvas", 156 + className, 157 + children, 158 + ...props 159 + }: React.ComponentProps<"div"> & { 160 + side?: "left" | "right" 161 + variant?: "sidebar" | "floating" | "inset" 162 + collapsible?: "offcanvas" | "icon" | "none" 163 + }) { 164 + const { isMobile, state, openMobile, setOpenMobile } = useSidebar() 165 + 166 + if (collapsible === "none") { 167 + return ( 168 + <div 169 + data-slot="sidebar" 170 + className={cn( 171 + "bg-sidebar text-sidebar-foreground flex h-full w-(--sidebar-width) flex-col", 172 + className 173 + )} 174 + {...props} 175 + > 176 + {children} 177 + </div> 178 + ) 179 + } 214 180 181 + if (isMobile) { 215 182 return ( 183 + <Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}> 184 + <SheetContent 185 + data-sidebar="sidebar" 186 + data-slot="sidebar" 187 + data-mobile="true" 188 + className="bg-sidebar text-sidebar-foreground w-(--sidebar-width) p-0 [&>button]:hidden" 189 + style={ 190 + { 191 + "--sidebar-width": SIDEBAR_WIDTH_MOBILE, 192 + } as React.CSSProperties 193 + } 194 + side={side} 195 + > 196 + <SheetHeader className="sr-only"> 197 + <SheetTitle>Sidebar</SheetTitle> 198 + <SheetDescription>Displays the mobile sidebar.</SheetDescription> 199 + </SheetHeader> 200 + <div className="flex h-full w-full flex-col">{children}</div> 201 + </SheetContent> 202 + </Sheet> 203 + ) 204 + } 205 + 206 + return ( 207 + <div 208 + className="group peer text-sidebar-foreground hidden md:block" 209 + data-state={state} 210 + data-collapsible={state === "collapsed" ? collapsible : ""} 211 + data-variant={variant} 212 + data-side={side} 213 + data-slot="sidebar" 214 + > 215 + {/* This is what handles the sidebar gap on desktop */} 216 216 <div 217 - ref={ref} 218 - className="group peer hidden md:block text-sidebar-foreground" 219 - data-state={state} 220 - data-collapsible={state === "collapsed" ? collapsible : ""} 221 - data-variant={variant} 222 - data-side={side} 217 + data-slot="sidebar-gap" 218 + className={cn( 219 + "relative w-(--sidebar-width) bg-transparent transition-[width] duration-200 ease-linear", 220 + "group-data-[collapsible=offcanvas]:w-0", 221 + "group-data-[side=right]:rotate-180", 222 + variant === "floating" || variant === "inset" 223 + ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4)))]" 224 + : "group-data-[collapsible=icon]:w-(--sidebar-width-icon)" 225 + )} 226 + /> 227 + <div 228 + data-slot="sidebar-container" 229 + className={cn( 230 + "fixed inset-y-0 z-10 hidden h-svh w-(--sidebar-width) transition-[left,right,width] duration-200 ease-linear md:flex", 231 + side === "left" 232 + ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" 233 + : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", 234 + // Adjust the padding for floating and inset variants. 235 + variant === "floating" || variant === "inset" 236 + ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)+(--spacing(4))+2px)]" 237 + : "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", 238 + className 239 + )} 240 + {...props} 223 241 > 224 - {/* This is what handles the sidebar gap on desktop */} 225 242 <div 226 - className={cn( 227 - "duration-200 relative h-svh w-[--sidebar-width] bg-transparent transition-[width] ease-linear", 228 - "group-data-[collapsible=offcanvas]:w-0", 229 - "group-data-[side=right]:rotate-180", 230 - variant === "floating" || variant === "inset" 231 - ? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]" 232 - : "group-data-[collapsible=icon]:w-[--sidebar-width-icon]" 233 - )} 234 - /> 235 - <div 236 - className={cn( 237 - "duration-200 fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] ease-linear md:flex", 238 - side === "left" 239 - ? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]" 240 - : "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]", 241 - // Adjust the padding for floating and inset variants. 242 - variant === "floating" || variant === "inset" 243 - ? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]" 244 - : "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l", 245 - className 246 - )} 247 - {...props} 243 + data-sidebar="sidebar" 244 + data-slot="sidebar-inner" 245 + className="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow-sm" 248 246 > 249 - <div 250 - data-sidebar="sidebar" 251 - className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow" 252 - > 253 - {children} 254 - </div> 247 + {children} 255 248 </div> 256 249 </div> 257 - ) 258 - } 259 - ) 260 - Sidebar.displayName = "Sidebar" 250 + </div> 251 + ) 252 + } 261 253 262 - const SidebarTrigger = React.forwardRef< 263 - React.ElementRef<typeof Button>, 264 - React.ComponentProps<typeof Button> 265 - >(({ className, onClick, ...props }, ref) => { 254 + function SidebarTrigger({ 255 + className, 256 + onClick, 257 + ...props 258 + }: React.ComponentProps<typeof Button>) { 266 259 const { toggleSidebar } = useSidebar() 267 260 268 261 return ( 269 262 <Button 270 - ref={ref} 271 263 data-sidebar="trigger" 264 + data-slot="sidebar-trigger" 272 265 variant="ghost" 273 266 size="icon" 274 - className={cn("h-7 w-7", className)} 267 + className={cn("size-7", className)} 275 268 onClick={(event) => { 276 269 onClick?.(event) 277 270 toggleSidebar() 278 271 }} 279 272 {...props} 280 273 > 281 - <PanelLeft /> 274 + <PanelLeftIcon /> 282 275 <span className="sr-only">Toggle Sidebar</span> 283 276 </Button> 284 277 ) 285 - }) 286 - SidebarTrigger.displayName = "SidebarTrigger" 278 + } 287 279 288 - const SidebarRail = React.forwardRef< 289 - HTMLButtonElement, 290 - React.ComponentProps<"button"> 291 - >(({ className, ...props }, ref) => { 280 + function SidebarRail({ className, ...props }: React.ComponentProps<"button">) { 292 281 const { toggleSidebar } = useSidebar() 293 282 294 283 return ( 295 284 <button 296 - ref={ref} 297 285 data-sidebar="rail" 286 + data-slot="sidebar-rail" 298 287 aria-label="Toggle Sidebar" 299 288 tabIndex={-1} 300 289 onClick={toggleSidebar} 301 290 title="Toggle Sidebar" 302 291 className={cn( 303 - "absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex", 304 - "[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize", 292 + "hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear group-data-[side=left]:-right-4 group-data-[side=right]:left-0 after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] sm:flex", 293 + "in-data-[side=left]:cursor-w-resize in-data-[side=right]:cursor-e-resize", 305 294 "[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize", 306 - "group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar", 295 + "hover:group-data-[collapsible=offcanvas]:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full", 307 296 "[[data-side=left][data-collapsible=offcanvas]_&]:-right-2", 308 297 "[[data-side=right][data-collapsible=offcanvas]_&]:-left-2", 309 298 className ··· 311 300 {...props} 312 301 /> 313 302 ) 314 - }) 315 - SidebarRail.displayName = "SidebarRail" 303 + } 316 304 317 - const SidebarInset = React.forwardRef< 318 - HTMLDivElement, 319 - React.ComponentProps<"main"> 320 - >(({ className, ...props }, ref) => { 305 + function SidebarInset({ className, ...props }: React.ComponentProps<"main">) { 321 306 return ( 322 307 <main 323 - ref={ref} 308 + data-slot="sidebar-inset" 324 309 className={cn( 325 - "relative flex min-h-svh flex-1 flex-col bg-background", 326 - "peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow", 310 + "bg-background relative flex w-full flex-1 flex-col", 311 + "md:peer-data-[variant=inset]:m-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow-sm md:peer-data-[variant=inset]:peer-data-[state=collapsed]:ml-2", 327 312 className 328 313 )} 329 314 {...props} 330 315 /> 331 316 ) 332 - }) 333 - SidebarInset.displayName = "SidebarInset" 317 + } 334 318 335 - const SidebarInput = React.forwardRef< 336 - React.ElementRef<typeof Input>, 337 - React.ComponentProps<typeof Input> 338 - >(({ className, ...props }, ref) => { 319 + function SidebarInput({ 320 + className, 321 + ...props 322 + }: React.ComponentProps<typeof Input>) { 339 323 return ( 340 324 <Input 341 - ref={ref} 325 + data-slot="sidebar-input" 342 326 data-sidebar="input" 343 - className={cn( 344 - "h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring", 345 - className 346 - )} 327 + className={cn("bg-background h-8 w-full shadow-none", className)} 347 328 {...props} 348 329 /> 349 330 ) 350 - }) 351 - SidebarInput.displayName = "SidebarInput" 331 + } 352 332 353 - const SidebarHeader = React.forwardRef< 354 - HTMLDivElement, 355 - React.ComponentProps<"div"> 356 - >(({ className, ...props }, ref) => { 333 + function SidebarHeader({ className, ...props }: React.ComponentProps<"div">) { 357 334 return ( 358 335 <div 359 - ref={ref} 336 + data-slot="sidebar-header" 360 337 data-sidebar="header" 361 338 className={cn("flex flex-col gap-2 p-2", className)} 362 339 {...props} 363 340 /> 364 341 ) 365 - }) 366 - SidebarHeader.displayName = "SidebarHeader" 342 + } 367 343 368 - const SidebarFooter = React.forwardRef< 369 - HTMLDivElement, 370 - React.ComponentProps<"div"> 371 - >(({ className, ...props }, ref) => { 344 + function SidebarFooter({ className, ...props }: React.ComponentProps<"div">) { 372 345 return ( 373 346 <div 374 - ref={ref} 347 + data-slot="sidebar-footer" 375 348 data-sidebar="footer" 376 349 className={cn("flex flex-col gap-2 p-2", className)} 377 350 {...props} 378 351 /> 379 352 ) 380 - }) 381 - SidebarFooter.displayName = "SidebarFooter" 353 + } 382 354 383 - const SidebarSeparator = React.forwardRef< 384 - React.ElementRef<typeof Separator>, 385 - React.ComponentProps<typeof Separator> 386 - >(({ className, ...props }, ref) => { 355 + function SidebarSeparator({ 356 + className, 357 + ...props 358 + }: React.ComponentProps<typeof Separator>) { 387 359 return ( 388 360 <Separator 389 - ref={ref} 361 + data-slot="sidebar-separator" 390 362 data-sidebar="separator" 391 - className={cn("mx-2 w-auto bg-sidebar-border", className)} 363 + className={cn("bg-sidebar-border mx-2 w-auto", className)} 392 364 {...props} 393 365 /> 394 366 ) 395 - }) 396 - SidebarSeparator.displayName = "SidebarSeparator" 367 + } 397 368 398 - const SidebarContent = React.forwardRef< 399 - HTMLDivElement, 400 - React.ComponentProps<"div"> 401 - >(({ className, ...props }, ref) => { 369 + function SidebarContent({ className, ...props }: React.ComponentProps<"div">) { 402 370 return ( 403 371 <div 404 - ref={ref} 372 + data-slot="sidebar-content" 405 373 data-sidebar="content" 406 374 className={cn( 407 375 "flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden", ··· 410 378 {...props} 411 379 /> 412 380 ) 413 - }) 414 - SidebarContent.displayName = "SidebarContent" 381 + } 415 382 416 - const SidebarGroup = React.forwardRef< 417 - HTMLDivElement, 418 - React.ComponentProps<"div"> 419 - >(({ className, ...props }, ref) => { 383 + function SidebarGroup({ className, ...props }: React.ComponentProps<"div">) { 420 384 return ( 421 385 <div 422 - ref={ref} 386 + data-slot="sidebar-group" 423 387 data-sidebar="group" 424 388 className={cn("relative flex w-full min-w-0 flex-col p-2", className)} 425 389 {...props} 426 390 /> 427 391 ) 428 - }) 429 - SidebarGroup.displayName = "SidebarGroup" 392 + } 430 393 431 - const SidebarGroupLabel = React.forwardRef< 432 - HTMLDivElement, 433 - React.ComponentProps<"div"> & { asChild?: boolean } 434 - >(({ className, asChild = false, ...props }, ref) => { 394 + function SidebarGroupLabel({ 395 + className, 396 + asChild = false, 397 + ...props 398 + }: React.ComponentProps<"div"> & { asChild?: boolean }) { 435 399 const Comp = asChild ? Slot : "div" 436 400 437 401 return ( 438 402 <Comp 439 - ref={ref} 403 + data-slot="sidebar-group-label" 440 404 data-sidebar="group-label" 441 405 className={cn( 442 - "duration-200 flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 406 + "text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-hidden transition-[margin,opacity] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 443 407 "group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0", 444 408 className 445 409 )} 446 410 {...props} 447 411 /> 448 412 ) 449 - }) 450 - SidebarGroupLabel.displayName = "SidebarGroupLabel" 413 + } 451 414 452 - const SidebarGroupAction = React.forwardRef< 453 - HTMLButtonElement, 454 - React.ComponentProps<"button"> & { asChild?: boolean } 455 - >(({ className, asChild = false, ...props }, ref) => { 415 + function SidebarGroupAction({ 416 + className, 417 + asChild = false, 418 + ...props 419 + }: React.ComponentProps<"button"> & { asChild?: boolean }) { 456 420 const Comp = asChild ? Slot : "button" 457 421 458 422 return ( 459 423 <Comp 460 - ref={ref} 424 + data-slot="sidebar-group-action" 461 425 data-sidebar="group-action" 462 426 className={cn( 463 - "absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 427 + "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute top-3.5 right-3 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 464 428 // Increases the hit area of the button on mobile. 465 - "after:absolute after:-inset-2 after:md:hidden", 429 + "after:absolute after:-inset-2 md:after:hidden", 466 430 "group-data-[collapsible=icon]:hidden", 467 431 className 468 432 )} 469 433 {...props} 470 434 /> 471 435 ) 472 - }) 473 - SidebarGroupAction.displayName = "SidebarGroupAction" 436 + } 474 437 475 - const SidebarGroupContent = React.forwardRef< 476 - HTMLDivElement, 477 - React.ComponentProps<"div"> 478 - >(({ className, ...props }, ref) => ( 479 - <div 480 - ref={ref} 481 - data-sidebar="group-content" 482 - className={cn("w-full text-sm", className)} 483 - {...props} 484 - /> 485 - )) 486 - SidebarGroupContent.displayName = "SidebarGroupContent" 438 + function SidebarGroupContent({ 439 + className, 440 + ...props 441 + }: React.ComponentProps<"div">) { 442 + return ( 443 + <div 444 + data-slot="sidebar-group-content" 445 + data-sidebar="group-content" 446 + className={cn("w-full text-sm", className)} 447 + {...props} 448 + /> 449 + ) 450 + } 487 451 488 - const SidebarMenu = React.forwardRef< 489 - HTMLUListElement, 490 - React.ComponentProps<"ul"> 491 - >(({ className, ...props }, ref) => ( 492 - <ul 493 - ref={ref} 494 - data-sidebar="menu" 495 - className={cn("flex w-full min-w-0 flex-col gap-1", className)} 496 - {...props} 497 - /> 498 - )) 499 - SidebarMenu.displayName = "SidebarMenu" 452 + function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">) { 453 + return ( 454 + <ul 455 + data-slot="sidebar-menu" 456 + data-sidebar="menu" 457 + className={cn("flex w-full min-w-0 flex-col gap-1", className)} 458 + {...props} 459 + /> 460 + ) 461 + } 500 462 501 - const SidebarMenuItem = React.forwardRef< 502 - HTMLLIElement, 503 - React.ComponentProps<"li"> 504 - >(({ className, ...props }, ref) => ( 505 - <li 506 - ref={ref} 507 - data-sidebar="menu-item" 508 - className={cn("group/menu-item relative", className)} 509 - {...props} 510 - /> 511 - )) 512 - SidebarMenuItem.displayName = "SidebarMenuItem" 463 + function SidebarMenuItem({ className, ...props }: React.ComponentProps<"li">) { 464 + return ( 465 + <li 466 + data-slot="sidebar-menu-item" 467 + data-sidebar="menu-item" 468 + className={cn("group/menu-item relative", className)} 469 + {...props} 470 + /> 471 + ) 472 + } 513 473 514 474 const sidebarMenuButtonVariants = cva( 515 - "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", 475 + "peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", 516 476 { 517 477 variants: { 518 478 variant: { ··· 523 483 size: { 524 484 default: "h-8 text-sm", 525 485 sm: "h-7 text-xs", 526 - lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0", 486 + lg: "h-12 text-sm group-data-[collapsible=icon]:p-0!", 527 487 }, 528 488 }, 529 489 defaultVariants: { ··· 533 493 } 534 494 ) 535 495 536 - const SidebarMenuButton = React.forwardRef< 537 - HTMLButtonElement, 538 - React.ComponentProps<"button"> & { 539 - asChild?: boolean 540 - isActive?: boolean 541 - tooltip?: string | React.ComponentProps<typeof TooltipContent> 542 - } & VariantProps<typeof sidebarMenuButtonVariants> 543 - >( 544 - ( 545 - { 546 - asChild = false, 547 - isActive = false, 548 - variant = "default", 549 - size = "default", 550 - tooltip, 551 - className, 552 - ...props 553 - }, 554 - ref 555 - ) => { 556 - const Comp = asChild ? Slot : "button" 557 - const { isMobile, state } = useSidebar() 496 + function SidebarMenuButton({ 497 + asChild = false, 498 + isActive = false, 499 + variant = "default", 500 + size = "default", 501 + tooltip, 502 + className, 503 + ...props 504 + }: React.ComponentProps<"button"> & { 505 + asChild?: boolean 506 + isActive?: boolean 507 + tooltip?: string | React.ComponentProps<typeof TooltipContent> 508 + } & VariantProps<typeof sidebarMenuButtonVariants>) { 509 + const Comp = asChild ? Slot : "button" 510 + const { isMobile, state } = useSidebar() 558 511 559 - const button = ( 560 - <Comp 561 - ref={ref} 562 - data-sidebar="menu-button" 563 - data-size={size} 564 - data-active={isActive} 565 - className={cn(sidebarMenuButtonVariants({ variant, size }), className)} 566 - {...props} 567 - /> 568 - ) 512 + const button = ( 513 + <Comp 514 + data-slot="sidebar-menu-button" 515 + data-sidebar="menu-button" 516 + data-size={size} 517 + data-active={isActive} 518 + className={cn(sidebarMenuButtonVariants({ variant, size }), className)} 519 + {...props} 520 + /> 521 + ) 569 522 570 - if (!tooltip) { 571 - return button 572 - } 523 + if (!tooltip) { 524 + return button 525 + } 573 526 574 - if (typeof tooltip === "string") { 575 - tooltip = { 576 - children: tooltip, 577 - } 527 + if (typeof tooltip === "string") { 528 + tooltip = { 529 + children: tooltip, 578 530 } 579 - 580 - return ( 581 - <Tooltip> 582 - <TooltipTrigger asChild>{button}</TooltipTrigger> 583 - <TooltipContent 584 - side="right" 585 - align="center" 586 - hidden={state !== "collapsed" || isMobile} 587 - {...tooltip} 588 - /> 589 - </Tooltip> 590 - ) 591 531 } 592 - ) 593 - SidebarMenuButton.displayName = "SidebarMenuButton" 594 532 595 - const SidebarMenuAction = React.forwardRef< 596 - HTMLButtonElement, 597 - React.ComponentProps<"button"> & { 598 - asChild?: boolean 599 - showOnHover?: boolean 600 - } 601 - >(({ className, asChild = false, showOnHover = false, ...props }, ref) => { 533 + return ( 534 + <Tooltip> 535 + <TooltipTrigger asChild>{button}</TooltipTrigger> 536 + <TooltipContent 537 + side="right" 538 + align="center" 539 + hidden={state !== "collapsed" || isMobile} 540 + {...tooltip} 541 + /> 542 + </Tooltip> 543 + ) 544 + } 545 + 546 + function SidebarMenuAction({ 547 + className, 548 + asChild = false, 549 + showOnHover = false, 550 + ...props 551 + }: React.ComponentProps<"button"> & { 552 + asChild?: boolean 553 + showOnHover?: boolean 554 + }) { 602 555 const Comp = asChild ? Slot : "button" 603 556 604 557 return ( 605 558 <Comp 606 - ref={ref} 559 + data-slot="sidebar-menu-action" 607 560 data-sidebar="menu-action" 608 561 className={cn( 609 - "absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 peer-hover/menu-button:text-sidebar-accent-foreground [&>svg]:size-4 [&>svg]:shrink-0", 562 + "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute top-1.5 right-1 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-hidden transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0", 610 563 // Increases the hit area of the button on mobile. 611 - "after:absolute after:-inset-2 after:md:hidden", 564 + "after:absolute after:-inset-2 md:after:hidden", 612 565 "peer-data-[size=sm]/menu-button:top-1", 613 566 "peer-data-[size=default]/menu-button:top-1.5", 614 567 "peer-data-[size=lg]/menu-button:top-2.5", 615 568 "group-data-[collapsible=icon]:hidden", 616 569 showOnHover && 617 - "group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0", 570 + "peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0", 618 571 className 619 572 )} 620 573 {...props} 621 574 /> 622 575 ) 623 - }) 624 - SidebarMenuAction.displayName = "SidebarMenuAction" 576 + } 625 577 626 - const SidebarMenuBadge = React.forwardRef< 627 - HTMLDivElement, 628 - React.ComponentProps<"div"> 629 - >(({ className, ...props }, ref) => ( 630 - <div 631 - ref={ref} 632 - data-sidebar="menu-badge" 633 - className={cn( 634 - "absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground select-none pointer-events-none", 635 - "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground", 636 - "peer-data-[size=sm]/menu-button:top-1", 637 - "peer-data-[size=default]/menu-button:top-1.5", 638 - "peer-data-[size=lg]/menu-button:top-2.5", 639 - "group-data-[collapsible=icon]:hidden", 640 - className 641 - )} 642 - {...props} 643 - /> 644 - )) 645 - SidebarMenuBadge.displayName = "SidebarMenuBadge" 578 + function SidebarMenuBadge({ 579 + className, 580 + ...props 581 + }: React.ComponentProps<"div">) { 582 + return ( 583 + <div 584 + data-slot="sidebar-menu-badge" 585 + data-sidebar="menu-badge" 586 + className={cn( 587 + "text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums select-none", 588 + "peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground", 589 + "peer-data-[size=sm]/menu-button:top-1", 590 + "peer-data-[size=default]/menu-button:top-1.5", 591 + "peer-data-[size=lg]/menu-button:top-2.5", 592 + "group-data-[collapsible=icon]:hidden", 593 + className 594 + )} 595 + {...props} 596 + /> 597 + ) 598 + } 646 599 647 - const SidebarMenuSkeleton = React.forwardRef< 648 - HTMLDivElement, 649 - React.ComponentProps<"div"> & { 650 - showIcon?: boolean 651 - } 652 - >(({ className, showIcon = false, ...props }, ref) => { 600 + function SidebarMenuSkeleton({ 601 + className, 602 + showIcon = false, 603 + ...props 604 + }: React.ComponentProps<"div"> & { 605 + showIcon?: boolean 606 + }) { 653 607 // Random width between 50 to 90%. 654 608 const width = React.useMemo(() => { 655 609 return `${Math.floor(Math.random() * 40) + 50}%` ··· 657 611 658 612 return ( 659 613 <div 660 - ref={ref} 614 + data-slot="sidebar-menu-skeleton" 661 615 data-sidebar="menu-skeleton" 662 - className={cn("rounded-md h-8 flex gap-2 px-2 items-center", className)} 616 + className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)} 663 617 {...props} 664 618 > 665 619 {showIcon && ( ··· 669 623 /> 670 624 )} 671 625 <Skeleton 672 - className="h-4 flex-1 max-w-[--skeleton-width]" 626 + className="h-4 max-w-(--skeleton-width) flex-1" 673 627 data-sidebar="menu-skeleton-text" 674 628 style={ 675 629 { ··· 679 633 /> 680 634 </div> 681 635 ) 682 - }) 683 - SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton" 636 + } 684 637 685 - const SidebarMenuSub = React.forwardRef< 686 - HTMLUListElement, 687 - React.ComponentProps<"ul"> 688 - >(({ className, ...props }, ref) => ( 689 - <ul 690 - ref={ref} 691 - data-sidebar="menu-sub" 692 - className={cn( 693 - "mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5", 694 - "group-data-[collapsible=icon]:hidden", 695 - className 696 - )} 697 - {...props} 698 - /> 699 - )) 700 - SidebarMenuSub.displayName = "SidebarMenuSub" 638 + function SidebarMenuSub({ className, ...props }: React.ComponentProps<"ul">) { 639 + return ( 640 + <ul 641 + data-slot="sidebar-menu-sub" 642 + data-sidebar="menu-sub" 643 + className={cn( 644 + "border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5", 645 + "group-data-[collapsible=icon]:hidden", 646 + className 647 + )} 648 + {...props} 649 + /> 650 + ) 651 + } 701 652 702 - const SidebarMenuSubItem = React.forwardRef< 703 - HTMLLIElement, 704 - React.ComponentProps<"li"> 705 - >(({ ...props }, ref) => <li ref={ref} {...props} />) 706 - SidebarMenuSubItem.displayName = "SidebarMenuSubItem" 653 + function SidebarMenuSubItem({ 654 + className, 655 + ...props 656 + }: React.ComponentProps<"li">) { 657 + return ( 658 + <li 659 + data-slot="sidebar-menu-sub-item" 660 + data-sidebar="menu-sub-item" 661 + className={cn("group/menu-sub-item relative", className)} 662 + {...props} 663 + /> 664 + ) 665 + } 707 666 708 - const SidebarMenuSubButton = React.forwardRef< 709 - HTMLAnchorElement, 710 - React.ComponentProps<"a"> & { 711 - asChild?: boolean 712 - size?: "sm" | "md" 713 - isActive?: boolean 714 - } 715 - >(({ asChild = false, size = "md", isActive, className, ...props }, ref) => { 667 + function SidebarMenuSubButton({ 668 + asChild = false, 669 + size = "md", 670 + isActive = false, 671 + className, 672 + ...props 673 + }: React.ComponentProps<"a"> & { 674 + asChild?: boolean 675 + size?: "sm" | "md" 676 + isActive?: boolean 677 + }) { 716 678 const Comp = asChild ? Slot : "a" 717 679 718 680 return ( 719 681 <Comp 720 - ref={ref} 682 + data-slot="sidebar-menu-sub-button" 721 683 data-sidebar="menu-sub-button" 722 684 data-size={size} 723 685 data-active={isActive} 724 686 className={cn( 725 - "flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground", 687 + "text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-hidden focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0", 726 688 "data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground", 727 689 size === "sm" && "text-xs", 728 690 size === "md" && "text-sm", ··· 732 694 {...props} 733 695 /> 734 696 ) 735 - }) 736 - SidebarMenuSubButton.displayName = "SidebarMenuSubButton" 697 + } 737 698 738 699 export { 739 700 Sidebar,
+3 -5
apps/web/src/components/ui/skeleton.tsx
··· 1 1 import { cn } from "@/lib/utils" 2 2 3 - function Skeleton({ 4 - className, 5 - ...props 6 - }: React.HTMLAttributes<HTMLDivElement>) { 3 + function Skeleton({ className, ...props }: React.ComponentProps<"div">) { 7 4 return ( 8 5 <div 9 - className={cn("animate-pulse rounded-md bg-primary/10", className)} 6 + data-slot="skeleton" 7 + className={cn("bg-accent animate-pulse rounded-md", className)} 10 8 {...props} 11 9 /> 12 10 )
-336
apps/web/src/components/ui/sortable.tsx
··· 1 - "use client" 2 - 3 - import * as React from "react" 4 - import type { 5 - DndContextProps, 6 - DraggableSyntheticListeners, 7 - DropAnimation, 8 - UniqueIdentifier, 9 - } from "@dnd-kit/core" 10 - import { 11 - closestCenter, 12 - defaultDropAnimationSideEffects, 13 - DndContext, 14 - DragOverlay, 15 - KeyboardSensor, 16 - MouseSensor, 17 - TouchSensor, 18 - useSensor, 19 - useSensors, 20 - } from "@dnd-kit/core" 21 - import { 22 - restrictToHorizontalAxis, 23 - restrictToParentElement, 24 - restrictToVerticalAxis, 25 - } from "@dnd-kit/modifiers" 26 - import { 27 - arrayMove, 28 - horizontalListSortingStrategy, 29 - SortableContext, 30 - useSortable, 31 - verticalListSortingStrategy, 32 - type SortableContextProps, 33 - } from "@dnd-kit/sortable" 34 - import { CSS } from "@dnd-kit/utilities" 35 - import { Slot, type SlotProps } from "@radix-ui/react-slot" 36 - 37 - import { composeRefs } from "@/lib/compose-refs" 38 - import { cn } from "@/lib/utils" 39 - import { Button, type ButtonProps } from "@/components/ui/button" 40 - 41 - const orientationConfig = { 42 - vertical: { 43 - modifiers: [restrictToVerticalAxis, restrictToParentElement], 44 - strategy: verticalListSortingStrategy, 45 - }, 46 - horizontal: { 47 - modifiers: [restrictToHorizontalAxis, restrictToParentElement], 48 - strategy: horizontalListSortingStrategy, 49 - }, 50 - mixed: { 51 - modifiers: [restrictToParentElement], 52 - strategy: undefined, 53 - }, 54 - } 55 - 56 - interface SortableProps<TData extends { id: UniqueIdentifier }> 57 - extends DndContextProps { 58 - /** 59 - * An array of data items that the sortable component will render. 60 - * @example 61 - * value={[ 62 - * { id: 1, name: 'Item 1' }, 63 - * { id: 2, name: 'Item 2' }, 64 - * ]} 65 - */ 66 - value: TData[] 67 - 68 - /** 69 - * An optional callback function that is called when the order of the data items changes. 70 - * It receives the new array of items as its argument. 71 - * @example 72 - * onValueChange={(items) => console.log(items)} 73 - */ 74 - onValueChange?: (items: TData[]) => void 75 - 76 - /** 77 - * An optional callback function that is called when an item is moved. 78 - * It receives an event object with `activeIndex` and `overIndex` properties, representing the original and new positions of the moved item. 79 - * This will override the default behavior of updating the order of the data items. 80 - * @type (event: { activeIndex: number; overIndex: number }) => void 81 - * @example 82 - * onMove={(event) => console.log(`Item moved from index ${event.activeIndex} to index ${event.overIndex}`)} 83 - */ 84 - onMove?: (event: { activeIndex: number; overIndex: number }) => void 85 - 86 - /** 87 - * A collision detection strategy that will be used to determine the closest sortable item. 88 - * @default closestCenter 89 - * @type DndContextProps["collisionDetection"] 90 - */ 91 - collisionDetection?: DndContextProps["collisionDetection"] 92 - 93 - /** 94 - * An array of modifiers that will be used to modify the behavior of the sortable component. 95 - * @default 96 - * [restrictToVerticalAxis, restrictToParentElement] 97 - * @type Modifier[] 98 - */ 99 - modifiers?: DndContextProps["modifiers"] 100 - 101 - /** 102 - * A sorting strategy that will be used to determine the new order of the data items. 103 - * @default verticalListSortingStrategy 104 - * @type SortableContextProps["strategy"] 105 - */ 106 - strategy?: SortableContextProps["strategy"] 107 - 108 - /** 109 - * Specifies the axis for the drag-and-drop operation. It can be "vertical", "horizontal", or "both". 110 - * @default "vertical" 111 - * @type "vertical" | "horizontal" | "mixed" 112 - */ 113 - orientation?: "vertical" | "horizontal" | "mixed" 114 - 115 - /** 116 - * An optional React node that is rendered on top of the sortable component. 117 - * It can be used to display additional information or controls. 118 - * @default null 119 - * @type React.ReactNode | null 120 - * @example 121 - * overlay={<Skeleton className="w-full h-8" />} 122 - */ 123 - overlay?: React.ReactNode | null 124 - } 125 - 126 - function Sortable<TData extends { id: UniqueIdentifier }>({ 127 - value, 128 - onValueChange, 129 - collisionDetection = closestCenter, 130 - modifiers, 131 - strategy, 132 - onMove, 133 - orientation = "vertical", 134 - overlay, 135 - children, 136 - ...props 137 - }: SortableProps<TData>) { 138 - const [activeId, setActiveId] = React.useState<UniqueIdentifier | null>(null) 139 - const sensors = useSensors( 140 - useSensor(MouseSensor), 141 - useSensor(TouchSensor), 142 - useSensor(KeyboardSensor) 143 - ) 144 - 145 - const config = orientationConfig[orientation] 146 - 147 - return ( 148 - <DndContext 149 - modifiers={modifiers ?? config.modifiers} 150 - sensors={sensors} 151 - onDragStart={({ active }) => setActiveId(active.id)} 152 - onDragEnd={({ active, over }) => { 153 - if (over && active.id !== over?.id) { 154 - const activeIndex = value.findIndex((item) => item.id === active.id) 155 - const overIndex = value.findIndex((item) => item.id === over.id) 156 - 157 - if (onMove) { 158 - onMove({ activeIndex, overIndex }) 159 - } else { 160 - onValueChange?.(arrayMove(value, activeIndex, overIndex)) 161 - } 162 - } 163 - setActiveId(null) 164 - }} 165 - onDragCancel={() => setActiveId(null)} 166 - collisionDetection={collisionDetection} 167 - {...props} 168 - > 169 - <SortableContext items={value} strategy={strategy ?? config.strategy}> 170 - {children} 171 - </SortableContext> 172 - {overlay ? ( 173 - <SortableOverlay activeId={activeId}>{overlay}</SortableOverlay> 174 - ) : null} 175 - </DndContext> 176 - ) 177 - } 178 - 179 - const dropAnimationOpts: DropAnimation = { 180 - sideEffects: defaultDropAnimationSideEffects({ 181 - styles: { 182 - active: { 183 - opacity: "0.4", 184 - }, 185 - }, 186 - }), 187 - } 188 - 189 - interface SortableOverlayProps 190 - extends React.ComponentPropsWithRef<typeof DragOverlay> { 191 - activeId?: UniqueIdentifier | null 192 - } 193 - 194 - const SortableOverlay = React.forwardRef<HTMLDivElement, SortableOverlayProps>( 195 - ( 196 - { activeId, dropAnimation = dropAnimationOpts, children, ...props }, 197 - ref 198 - ) => { 199 - return ( 200 - <DragOverlay dropAnimation={dropAnimation} {...props}> 201 - {activeId ? ( 202 - <SortableItem 203 - ref={ref} 204 - value={activeId} 205 - className="cursor-grabbing" 206 - asChild 207 - > 208 - {children} 209 - </SortableItem> 210 - ) : null} 211 - </DragOverlay> 212 - ) 213 - } 214 - ) 215 - SortableOverlay.displayName = "SortableOverlay" 216 - 217 - interface SortableItemContextProps { 218 - attributes: React.HTMLAttributes<HTMLElement> 219 - listeners: DraggableSyntheticListeners | undefined 220 - isDragging?: boolean 221 - } 222 - 223 - const SortableItemContext = React.createContext<SortableItemContextProps>({ 224 - attributes: {}, 225 - listeners: undefined, 226 - isDragging: false, 227 - }) 228 - 229 - function useSortableItem() { 230 - const context = React.useContext(SortableItemContext) 231 - 232 - if (!context) { 233 - throw new Error("useSortableItem must be used within a SortableItem") 234 - } 235 - 236 - return context 237 - } 238 - 239 - interface SortableItemProps extends SlotProps { 240 - /** 241 - * The unique identifier of the item. 242 - * @example "item-1" 243 - * @type UniqueIdentifier 244 - */ 245 - value: UniqueIdentifier 246 - 247 - /** 248 - * Specifies whether the item should act as a trigger for the drag-and-drop action. 249 - * @default false 250 - * @type boolean | undefined 251 - */ 252 - asTrigger?: boolean 253 - 254 - /** 255 - * Merges the item's props into its immediate child. 256 - * @default false 257 - * @type boolean | undefined 258 - */ 259 - asChild?: boolean 260 - } 261 - 262 - const SortableItem = React.forwardRef<HTMLDivElement, SortableItemProps>( 263 - ({ value, asTrigger, asChild, className, ...props }, ref) => { 264 - const { 265 - attributes, 266 - listeners, 267 - setNodeRef, 268 - transform, 269 - transition, 270 - isDragging, 271 - } = useSortable({ id: value }) 272 - 273 - const context = React.useMemo<SortableItemContextProps>( 274 - () => ({ 275 - attributes, 276 - listeners, 277 - isDragging, 278 - }), 279 - [attributes, listeners, isDragging] 280 - ) 281 - const style: React.CSSProperties = { 282 - opacity: isDragging ? 0.5 : 1, 283 - transform: CSS.Translate.toString(transform), 284 - transition, 285 - } 286 - 287 - const Comp = asChild ? Slot : "div" 288 - 289 - return ( 290 - <SortableItemContext.Provider value={context}> 291 - <Comp 292 - data-state={isDragging ? "dragging" : undefined} 293 - className={cn( 294 - "data-[state=dragging]:cursor-grabbing", 295 - { "cursor-grab": !isDragging && asTrigger }, 296 - className 297 - )} 298 - ref={composeRefs(ref, setNodeRef as React.Ref<HTMLDivElement>)} 299 - style={style} 300 - {...(asTrigger ? attributes : {})} 301 - {...(asTrigger ? listeners : {})} 302 - {...props} 303 - /> 304 - </SortableItemContext.Provider> 305 - ) 306 - } 307 - ) 308 - SortableItem.displayName = "SortableItem" 309 - 310 - interface SortableDragHandleProps extends ButtonProps { 311 - withHandle?: boolean 312 - } 313 - 314 - const SortableDragHandle = React.forwardRef< 315 - HTMLButtonElement, 316 - SortableDragHandleProps 317 - >(({ className, ...props }, ref) => { 318 - const { attributes, listeners, isDragging } = useSortableItem() 319 - 320 - return ( 321 - <Button 322 - ref={composeRefs(ref)} 323 - data-state={isDragging ? "dragging" : undefined} 324 - className={cn( 325 - "cursor-grab data-[state=dragging]:cursor-grabbing", 326 - className 327 - )} 328 - {...attributes} 329 - {...listeners} 330 - {...props} 331 - /> 332 - ) 333 - }) 334 - SortableDragHandle.displayName = "SortableDragHandle" 335 - 336 - export { Sortable, SortableDragHandle, SortableItem, SortableOverlay }
+4 -8
apps/web/src/components/ui/textarea.tsx
··· 2 2 3 3 import { cn } from "@/lib/utils" 4 4 5 - const Textarea = React.forwardRef< 6 - HTMLTextAreaElement, 7 - React.ComponentProps<"textarea"> 8 - >(({ className, ...props }, ref) => { 5 + function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { 9 6 return ( 10 7 <textarea 8 + data-slot="textarea" 11 9 className={cn( 12 - "flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", 10 + "border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", 13 11 className 14 12 )} 15 - ref={ref} 16 13 {...props} 17 14 /> 18 15 ) 19 - }) 20 - Textarea.displayName = "Textarea" 16 + } 21 17 22 18 export { Textarea }
+51 -20
apps/web/src/components/ui/tooltip.tsx
··· 1 + "use client" 2 + 1 3 import * as React from "react" 2 4 import * as TooltipPrimitive from "@radix-ui/react-tooltip" 3 5 4 6 import { cn } from "@/lib/utils" 5 7 6 - const TooltipProvider = TooltipPrimitive.Provider 8 + function TooltipProvider({ 9 + delayDuration = 0, 10 + ...props 11 + }: React.ComponentProps<typeof TooltipPrimitive.Provider>) { 12 + return ( 13 + <TooltipPrimitive.Provider 14 + data-slot="tooltip-provider" 15 + delayDuration={delayDuration} 16 + {...props} 17 + /> 18 + ) 19 + } 7 20 8 - const Tooltip = TooltipPrimitive.Root 21 + function Tooltip({ 22 + ...props 23 + }: React.ComponentProps<typeof TooltipPrimitive.Root>) { 24 + return ( 25 + <TooltipProvider> 26 + <TooltipPrimitive.Root data-slot="tooltip" {...props} /> 27 + </TooltipProvider> 28 + ) 29 + } 9 30 10 - const TooltipTrigger = TooltipPrimitive.Trigger 31 + function TooltipTrigger({ 32 + ...props 33 + }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) { 34 + return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} /> 35 + } 11 36 12 - const TooltipContent = React.forwardRef< 13 - React.ElementRef<typeof TooltipPrimitive.Content>, 14 - React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> 15 - >(({ className, sideOffset = 4, ...props }, ref) => ( 16 - <TooltipPrimitive.Portal> 17 - <TooltipPrimitive.Content 18 - ref={ref} 19 - sideOffset={sideOffset} 20 - className={cn( 21 - "z-50 overflow-hidden rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", 22 - className 23 - )} 24 - {...props} 25 - /> 26 - </TooltipPrimitive.Portal> 27 - )) 28 - TooltipContent.displayName = TooltipPrimitive.Content.displayName 37 + function TooltipContent({ 38 + className, 39 + sideOffset = 0, 40 + children, 41 + ...props 42 + }: React.ComponentProps<typeof TooltipPrimitive.Content>) { 43 + return ( 44 + <TooltipPrimitive.Portal> 45 + <TooltipPrimitive.Content 46 + data-slot="tooltip-content" 47 + sideOffset={sideOffset} 48 + className={cn( 49 + "bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", 50 + className 51 + )} 52 + {...props} 53 + > 54 + {children} 55 + <TooltipPrimitive.Arrow className="bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" /> 56 + </TooltipPrimitive.Content> 57 + </TooltipPrimitive.Portal> 58 + ) 59 + } 29 60 30 61 export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
+19
apps/web/src/hooks/use-mobile.ts
··· 1 + import * as React from "react" 2 + 3 + const MOBILE_BREAKPOINT = 768 4 + 5 + export function useIsMobile() { 6 + const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) 7 + 8 + React.useEffect(() => { 9 + const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 + const onChange = () => { 11 + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 + } 13 + mql.addEventListener("change", onChange) 14 + setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 + return () => mql.removeEventListener("change", onChange) 16 + }, []) 17 + 18 + return !!isMobile 19 + }
-19
apps/web/src/hooks/use-mobile.tsx
··· 1 - import * as React from "react" 2 - 3 - const MOBILE_BREAKPOINT = 768 4 - 5 - export function useIsMobile() { 6 - const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined) 7 - 8 - React.useEffect(() => { 9 - const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`) 10 - const onChange = () => { 11 - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 12 - } 13 - mql.addEventListener("change", onChange) 14 - setIsMobile(window.innerWidth < MOBILE_BREAKPOINT) 15 - return () => mql.removeEventListener("change", onChange) 16 - }, []) 17 - 18 - return !!isMobile 19 - }
-20
apps/web/src/hooks/use-xrpc.tsx
··· 1 - import { SERVER_URL } from "@/lib/utils"; 2 - import { useAuth } from "@/state/auth"; 3 - import { Client, FetchHandler, FetchHandlerObject, ServiceProxyOptions, simpleFetchHandler } from "@atcute/client"; 4 - 5 - export function useXrpc() { 6 - const { agent } = useAuth(); 7 - 8 - let handler: FetchHandler | FetchHandlerObject = simpleFetchHandler({ service: `https://${SERVER_URL}` }); 9 - let proxy: ServiceProxyOptions | null = null; 10 - 11 - if (agent) { 12 - handler = agent; 13 - proxy = { 14 - did: `did:web:${SERVER_URL}`, 15 - serviceId: '#recipes_blue', 16 - }; 17 - } 18 - 19 - return new Client({ handler, proxy }); 20 - }
+110 -74
apps/web/src/index.css
··· 1 - @tailwind base; 2 - @tailwind components; 3 - @tailwind utilities; 1 + @import "tailwindcss"; 2 + @import "tw-animate-css"; 4 3 5 - @layer base { 6 - :root { 7 - --background: 0 0% 96.1%; 8 - --foreground: 0 0% 3.9%; 9 - --card: 0 0% 100%; 10 - --card-foreground: 0 0% 3.9%; 11 - --popover: 0 0% 100%; 12 - --popover-foreground: 0 0% 3.9%; 13 - --primary: 221.2 83.2% 53.3%; 14 - --primary-foreground: 210 40% 98%; 15 - --secondary: 210 40% 96.1%; 16 - --secondary-foreground: 222.2 47.4% 11.2%; 17 - --muted: 0 0% 96.1%; 18 - --muted-foreground: 0 0% 45.1%; 19 - --accent: 210 40% 96.1%; 20 - --accent-foreground: 222.2 47.4% 11.2%; 21 - --destructive: 0 84.2% 60.2%; 22 - --destructive-foreground: 0 0% 98%; 23 - --border: 214.3 31.8% 91.4%; 24 - --input: 214.3 31.8% 91.4%; 25 - --ring: 221.2 83.2% 53.3%; 26 - --radius: 0.5rem; 27 - --chart-1: 12 76% 61%; 28 - --chart-2: 173 58% 39%; 29 - --chart-3: 197 37% 24%; 30 - --chart-4: 43 74% 66%; 31 - --chart-5: 27 87% 67%; 32 - --sidebar-background: 0 0% 98%; 33 - --sidebar-foreground: 240 5.3% 26.1%; 34 - --sidebar-primary: 221.2 83.2% 53.3%; 35 - --sidebar-primary-foreground: 0 0% 98%; 36 - --sidebar-accent: 210 40% 96.1%; 37 - --sidebar-accent-foreground: 240 5.9% 10%; 38 - --sidebar-border: 220 13% 91%; 39 - --sidebar-ring: 221.2 83.2% 53.3%; 40 - } 41 - .dark { 42 - --background: 0 0% 3.9%; 43 - --foreground: 0 0% 98%; 44 - --card: 0 0% 3.9%; 45 - --card-foreground: 0 0% 98%; 46 - --popover: 0 0% 3.9%; 47 - --popover-foreground: 0 0% 98%; 48 - --primary: 217.2 91.2% 59.8%; 49 - --primary-foreground: 222.2 47.4% 11.2%; 50 - --secondary: 217.2 32.6% 17.5%; 51 - --secondary-foreground: 210 40% 98%; 52 - --muted: 217.2 32.6% 17.5%; 53 - --muted-foreground: 215 20.2% 65.1%; 54 - --accent: 217.2 32.6% 17.5%; 55 - --accent-foreground: 210 40% 98%; 56 - --destructive: 0 62.8% 30.6%; 57 - --destructive-foreground: 210 40% 98%; 58 - --border: 217.2 32.6% 17.5%; 59 - --input: 217.2 32.6% 17.5%; 60 - --ring: 224.3 76.3% 48%; 61 - --chart-1: 220 70% 50%; 62 - --chart-2: 160 60% 45%; 63 - --chart-3: 30 80% 55%; 64 - --chart-4: 280 65% 60%; 65 - --chart-5: 340 75% 55%; 66 - --sidebar-background: 240 5.9% 10%; 67 - --sidebar-foreground: 240 4.8% 95.9%; 68 - --sidebar-primary: 217.2 91.2% 59.8%; 69 - --sidebar-primary-foreground: 0 0% 100%; 70 - --sidebar-accent: 217.2 32.6% 17.5%; 71 - --sidebar-accent-foreground: 240 4.8% 95.9%; 72 - --sidebar-border: 240 3.7% 15.9%; 73 - --sidebar-ring: 217.2 91.2% 59.8%; 74 - } 4 + @custom-variant dark (&:is(.dark *)); 5 + 6 + @theme inline { 7 + --radius-sm: calc(var(--radius) - 4px); 8 + --radius-md: calc(var(--radius) - 2px); 9 + --radius-lg: var(--radius); 10 + --radius-xl: calc(var(--radius) + 4px); 11 + --color-background: var(--background); 12 + --color-foreground: var(--foreground); 13 + --color-card: var(--card); 14 + --color-card-foreground: var(--card-foreground); 15 + --color-popover: var(--popover); 16 + --color-popover-foreground: var(--popover-foreground); 17 + --color-primary: var(--primary); 18 + --color-primary-foreground: var(--primary-foreground); 19 + --color-secondary: var(--secondary); 20 + --color-secondary-foreground: var(--secondary-foreground); 21 + --color-muted: var(--muted); 22 + --color-muted-foreground: var(--muted-foreground); 23 + --color-accent: var(--accent); 24 + --color-accent-foreground: var(--accent-foreground); 25 + --color-destructive: var(--destructive); 26 + --color-border: var(--border); 27 + --color-input: var(--input); 28 + --color-ring: var(--ring); 29 + --color-chart-1: var(--chart-1); 30 + --color-chart-2: var(--chart-2); 31 + --color-chart-3: var(--chart-3); 32 + --color-chart-4: var(--chart-4); 33 + --color-chart-5: var(--chart-5); 34 + --color-sidebar: var(--sidebar); 35 + --color-sidebar-foreground: var(--sidebar-foreground); 36 + --color-sidebar-primary: var(--sidebar-primary); 37 + --color-sidebar-primary-foreground: var(--sidebar-primary-foreground); 38 + --color-sidebar-accent: var(--sidebar-accent); 39 + --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); 40 + --color-sidebar-border: var(--sidebar-border); 41 + --color-sidebar-ring: var(--sidebar-ring); 42 + } 43 + 44 + :root { 45 + --radius: 0.625rem; 46 + --background: oklch(1 0 0); 47 + --foreground: oklch(0.141 0.005 285.823); 48 + --card: oklch(1 0 0); 49 + --card-foreground: oklch(0.141 0.005 285.823); 50 + --popover: oklch(1 0 0); 51 + --popover-foreground: oklch(0.141 0.005 285.823); 52 + --primary: oklch(0.21 0.006 285.885); 53 + --primary-foreground: oklch(0.985 0 0); 54 + --secondary: oklch(0.967 0.001 286.375); 55 + --secondary-foreground: oklch(0.21 0.006 285.885); 56 + --muted: oklch(0.967 0.001 286.375); 57 + --muted-foreground: oklch(0.552 0.016 285.938); 58 + --accent: oklch(0.967 0.001 286.375); 59 + --accent-foreground: oklch(0.21 0.006 285.885); 60 + --destructive: oklch(0.577 0.245 27.325); 61 + --border: oklch(0.92 0.004 286.32); 62 + --input: oklch(0.92 0.004 286.32); 63 + --ring: oklch(0.705 0.015 286.067); 64 + --chart-1: oklch(0.646 0.222 41.116); 65 + --chart-2: oklch(0.6 0.118 184.704); 66 + --chart-3: oklch(0.398 0.07 227.392); 67 + --chart-4: oklch(0.828 0.189 84.429); 68 + --chart-5: oklch(0.769 0.188 70.08); 69 + --sidebar: oklch(0.985 0 0); 70 + --sidebar-foreground: oklch(0.141 0.005 285.823); 71 + --sidebar-primary: oklch(0.21 0.006 285.885); 72 + --sidebar-primary-foreground: oklch(0.985 0 0); 73 + --sidebar-accent: oklch(0.967 0.001 286.375); 74 + --sidebar-accent-foreground: oklch(0.21 0.006 285.885); 75 + --sidebar-border: oklch(0.92 0.004 286.32); 76 + --sidebar-ring: oklch(0.705 0.015 286.067); 77 + } 78 + 79 + .dark { 80 + --background: oklch(0.141 0.005 285.823); 81 + --foreground: oklch(0.985 0 0); 82 + --card: oklch(0.21 0.006 285.885); 83 + --card-foreground: oklch(0.985 0 0); 84 + --popover: oklch(0.21 0.006 285.885); 85 + --popover-foreground: oklch(0.985 0 0); 86 + --primary: oklch(0.92 0.004 286.32); 87 + --primary-foreground: oklch(0.21 0.006 285.885); 88 + --secondary: oklch(0.274 0.006 286.033); 89 + --secondary-foreground: oklch(0.985 0 0); 90 + --muted: oklch(0.274 0.006 286.033); 91 + --muted-foreground: oklch(0.705 0.015 286.067); 92 + --accent: oklch(0.274 0.006 286.033); 93 + --accent-foreground: oklch(0.985 0 0); 94 + --destructive: oklch(0.704 0.191 22.216); 95 + --border: oklch(1 0 0 / 10%); 96 + --input: oklch(1 0 0 / 15%); 97 + --ring: oklch(0.552 0.016 285.938); 98 + --chart-1: oklch(0.488 0.243 264.376); 99 + --chart-2: oklch(0.696 0.17 162.48); 100 + --chart-3: oklch(0.769 0.188 70.08); 101 + --chart-4: oklch(0.627 0.265 303.9); 102 + --chart-5: oklch(0.645 0.246 16.439); 103 + --sidebar: oklch(0.21 0.006 285.885); 104 + --sidebar-foreground: oklch(0.985 0 0); 105 + --sidebar-primary: oklch(0.488 0.243 264.376); 106 + --sidebar-primary-foreground: oklch(0.985 0 0); 107 + --sidebar-accent: oklch(0.274 0.006 286.033); 108 + --sidebar-accent-foreground: oklch(0.985 0 0); 109 + --sidebar-border: oklch(1 0 0 / 10%); 110 + --sidebar-ring: oklch(0.552 0.016 285.938); 75 111 } 76 112 77 113 @layer base { 78 114 * { 79 - @apply border-border; 115 + @apply border-border outline-ring/50; 80 116 } 81 117 body { 82 118 @apply bg-background text-foreground;
-36
apps/web/src/lib/compose-refs.ts
··· 1 - // @see https://github.com/radix-ui/primitives/blob/main/packages/react/compose-refs/src/composeRefs.tsx 2 - 3 - import * as React from "react" 4 - 5 - type PossibleRef<T> = React.Ref<T> | undefined 6 - 7 - /** 8 - * Set a given ref to a given value 9 - * This utility takes care of different types of refs: callback refs and RefObject(s) 10 - */ 11 - function setRef<T>(ref: PossibleRef<T>, value: T) { 12 - if (typeof ref === "function") { 13 - ref(value) 14 - } else if (ref !== null && ref !== undefined) { 15 - ;(ref as React.MutableRefObject<T>).current = value 16 - } 17 - } 18 - 19 - /** 20 - * A utility to compose multiple refs together 21 - * Accepts callback refs and RefObject(s) 22 - */ 23 - function composeRefs<T>(...refs: PossibleRef<T>[]) { 24 - return (node: T) => refs.forEach((ref) => setRef(ref, node)) 25 - } 26 - 27 - /** 28 - * A custom hook that composes multiple refs 29 - * Accepts callback refs and RefObject(s) 30 - */ 31 - function useComposedRefs<T>(...refs: PossibleRef<T>[]) { 32 - // eslint-disable-next-line react-hooks/exhaustive-deps 33 - return React.useCallback(composeRefs(...refs), refs) 34 - } 35 - 36 - export { composeRefs, useComposedRefs }
+1
apps/web/src/lib/consts.ts
··· 1 + export const IS_DEV = import.meta.env.DEV;
-139
apps/web/src/lib/did.ts
··· 1 - import { z } from "zod"; 2 - 3 - type Brand<K, T> = K & { __brand: T }; 4 - export type DID = Brand<string, "DID">; 5 - 6 - export function isDid(s: string): s is DID { 7 - return s.startsWith("did:"); 8 - } 9 - 10 - export function parseDid(s: string): DID | null { 11 - if (!isDid(s)) { 12 - return null; 13 - } 14 - return s; 15 - } 16 - 17 - export const getDidDoc = async (did: DID) => { 18 - let url = `https://plc.directory/${did}`; 19 - if (did.startsWith('did:web')) { 20 - url = `https://${did.split(':')[2]}/.well-known/did.json`; 21 - } 22 - 23 - const response = await fetch(url); 24 - 25 - return PlcDocument.parse(await response.json()); 26 - }; 27 - 28 - export const getPdsUrl = async (did: DID) => { 29 - const plc = await getDidDoc(did); 30 - 31 - return ( 32 - plc.service.find((s) => s.type === "AtprotoPersonalDataServer") 33 - ?.serviceEndpoint ?? null 34 - ); 35 - }; 36 - 37 - const PlcDocument = z.object({ 38 - id: z.string(), 39 - alsoKnownAs: z.array(z.string()), 40 - service: z.array( 41 - z.object({ 42 - id: z.string(), 43 - type: z.string(), 44 - serviceEndpoint: z.string(), 45 - }), 46 - ), 47 - }); 48 - 49 - const DnsQueryResponse = z.object({ 50 - Answer: z.array( 51 - z.object({ 52 - name: z.string(), 53 - type: z.number(), 54 - TTL: z.number(), 55 - data: z.string(), 56 - }), 57 - ), 58 - }); 59 - 60 - async function getAtprotoDidFromDns(handle: string) { 61 - const url = new URL("https://cloudflare-dns.com/dns-query"); 62 - url.searchParams.set("type", "TXT"); 63 - url.searchParams.set("name", `_atproto.${handle}`); 64 - 65 - const response = await fetch(url, { 66 - headers: { 67 - Accept: "application/dns-json", 68 - }, 69 - }); 70 - 71 - const { Answer } = DnsQueryResponse.parse(await response.json()); 72 - // Answer[0].data is "\"did=...\"" (with quotes) 73 - const val = Answer[0]?.data 74 - ? JSON.parse(Answer[0]?.data).split("did=")[1] 75 - : null; 76 - 77 - return val ? parseDid(val) : null; 78 - } 79 - 80 - const getAtprotoFromHttps = async (handle: string) => { 81 - let res; 82 - const timeoutSignal = AbortSignal.timeout(1500); 83 - try { 84 - res = await fetch(`https://${handle}/.well-known/atproto-did`, { 85 - signal: timeoutSignal, 86 - }); 87 - } catch (_e) { 88 - // We're caching failures here, we should at some point invalidate the cache by listening to handle changes on the network 89 - return null; 90 - } 91 - 92 - if (!res.ok) { 93 - return null; 94 - } 95 - return parseDid((await res.text()).trim()); 96 - }; 97 - 98 - export const getVerifiedDid = async (handle: string) => { 99 - const [dnsDid, httpDid] = await Promise.all([ 100 - getAtprotoDidFromDns(handle).catch((_) => { 101 - return null; 102 - }), 103 - getAtprotoFromHttps(handle).catch(() => { 104 - return null; 105 - }), 106 - ]); 107 - 108 - if (dnsDid && httpDid && dnsDid !== httpDid) { 109 - return null; 110 - } 111 - 112 - const did = dnsDid ?? (httpDid ? parseDid(httpDid) : null); 113 - if (!did) { 114 - return null; 115 - } 116 - 117 - const plcDoc = await getDidDoc(did); 118 - const plcHandle = plcDoc.alsoKnownAs 119 - .find((handle) => handle.startsWith("at://")) 120 - ?.replace("at://", ""); 121 - 122 - if (!plcHandle) return null; 123 - 124 - return plcHandle.toLowerCase() === handle.toLowerCase() ? did : null; 125 - }; 126 - 127 - export const getDidFromHandleOrDid = async (handleOrDid: string) => { 128 - const decodedHandleOrDid = decodeURIComponent(handleOrDid); 129 - if (isDid(decodedHandleOrDid)) { 130 - return decodedHandleOrDid; 131 - } 132 - 133 - return getVerifiedDid(decodedHandleOrDid); 134 - }; 135 - 136 - export const getHandleFromHandleOrDid = async (did: string) => { 137 - const didDoc = await getDidDoc(did as DID); 138 - return didDoc.alsoKnownAs[0]?.substring(5); 139 - }
-11
apps/web/src/lib/react-query.ts
··· 1 - import { QueryClient } from "@tanstack/react-query"; 2 - 3 - export const queryClient = new QueryClient({ 4 - defaultOptions: { 5 - queries: { 6 - refetchOnWindowFocus: false, 7 - structuralSharing: false, 8 - retry: false, 9 - } 10 - } 11 - });
-4
apps/web/src/lib/utils.ts
··· 4 4 export function cn(...inputs: ClassValue[]) { 5 5 return twMerge(clsx(inputs)) 6 6 } 7 - 8 - export const sleep = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms)) 9 - 10 - export const SERVER_URL = import.meta.env.VITE_API_SERVICE;
+14 -65
apps/web/src/main.tsx
··· 1 - import { StrictMode } from 'react' 2 - import { createRoot } from 'react-dom/client' 3 - import { routeTree } from './routeTree.gen'; 1 + import { StrictMode } from 'react'; 2 + import { createRoot } from 'react-dom/client'; 4 3 import { createRouter, RouterProvider } from '@tanstack/react-router'; 5 - import { QueryClientProvider, QueryClient } from '@tanstack/react-query' 6 - import { ReactQueryDevtools } from '@tanstack/react-query-devtools' 7 - import { configureOAuth, defaultIdentityResolver } from '@atcute/oauth-browser-client'; 8 - import './index.css' 9 - import { AuthProvider, useAuth } from './state/auth'; 10 - import { ThemeProvider } from './components/theme-provider'; 11 - import { CompositeDidDocumentResolver, PlcDidDocumentResolver, WebDidDocumentResolver, XrpcHandleResolver } from '@atcute/identity-resolver'; 12 - import { SessionProvider } from './state/auth/session'; 4 + import { routeTree } from './routeTree.gen'; 13 5 14 - const router = createRouter({ 15 - routeTree, 16 - context: { 17 - auth: undefined!, 18 - }, 19 - }); 6 + import './index.css'; 20 7 21 - declare module '@tanstack/react-router' { 22 - interface Register { 23 - router: typeof router 24 - } 25 - } 8 + const router = createRouter({ routeTree }); 26 9 27 - configureOAuth({ 28 - metadata: { 29 - client_id: import.meta.env.VITE_OAUTH_CLIENT_ID, 30 - redirect_uri: import.meta.env.VITE_OAUTH_REDIRECT_URL, 31 - }, 32 - identityResolver: defaultIdentityResolver({ 33 - handleResolver: new XrpcHandleResolver({ serviceUrl: 'https://slingshot.microcosm.blue' }), 34 - didDocumentResolver: new CompositeDidDocumentResolver({ 35 - methods: { 36 - plc: new PlcDidDocumentResolver(), 37 - web: new WebDidDocumentResolver(), 38 - }, 39 - }), 40 - }), 41 - }); 42 - 43 - const queryClient = new QueryClient({ 44 - defaultOptions: { 45 - queries: { 46 - refetchOnWindowFocus: false, 47 - structuralSharing: false, 48 - retry: false, 49 - } 50 - } 51 - }); 52 - 53 - const InnerApp = () => { 54 - const auth = useAuth(); 55 - return <RouterProvider router={router} context={{ auth }} /> 56 - }; 57 - 58 - createRoot(document.getElementById('root')!).render( 59 - <StrictMode> 60 - <SessionProvider> 61 - <ThemeProvider defaultTheme="dark" storageKey="recipes-theme"> 62 - <QueryClientProvider client={queryClient}> 63 - <InnerApp /> 64 - <ReactQueryDevtools initialIsOpen={false} /> 65 - </QueryClientProvider> 66 - </ThemeProvider> 67 - </SessionProvider> 68 - </StrictMode>, 69 - ) 10 + const rootElement = document.getElementById('root')!; 11 + if (!rootElement.innerHTML) { 12 + const root = createRoot(rootElement); 13 + root.render( 14 + <StrictMode> 15 + <RouterProvider router={router} /> 16 + </StrictMode>, 17 + ); 18 + }
-107
apps/web/src/queries/recipe.ts
··· 1 - import { useXrpc } from "@/hooks/use-xrpc"; 2 - import { useAuth } from "@/state/auth"; 3 - import { queryOptions, useMutation, useQuery } from "@tanstack/react-query"; 4 - import { Client } from "@atcute/client"; 5 - import { notFound } from "@tanstack/react-router"; 6 - import { UseFormReturn } from "react-hook-form"; 7 - import { TID } from '@atproto/common-web'; 8 - import { recipeSchema } from "@/forms/recipe"; 9 - import { z } from "zod"; 10 - import { ActorIdentifier, Did } from "@atcute/lexicons"; 11 - 12 - import type {} from '@atcute/atproto'; 13 - import type {} from '@cookware/lexicons'; 14 - 15 - const RQKEY_ROOT = 'posts'; 16 - export const RQKEY = (cursor: string, did: string, rkey: string) => [RQKEY_ROOT, cursor, did, rkey]; 17 - 18 - export const useRecipesQuery = (cursor: string, did?: Did) => { 19 - const rpc = useXrpc(); 20 - return useQuery({ 21 - queryKey: RQKEY(cursor, did ?? '', ''), 22 - queryFn: async () => { 23 - const res = await rpc.get('blue.recipes.feed.getRecipes', { 24 - params: { cursor, did }, 25 - }); 26 - return res.data; 27 - }, 28 - }); 29 - }; 30 - 31 - export const recipeQueryOptions = (rpc: Client, did: Did, rkey: string) => { 32 - return queryOptions({ 33 - queryKey: RQKEY('', did, rkey), 34 - queryFn: async () => { 35 - const { ok, data } = await rpc.get('blue.recipes.feed.getRecipe', { 36 - params: { did, rkey }, 37 - }); 38 - 39 - if (!ok) { 40 - switch (data.error) { 41 - case 'RecipeNotFound': 42 - throw notFound({ routeId: '/_' }); 43 - default: 44 - throw new Error(`Error fetching recipe: ${data.error}`); 45 - } 46 - } 47 - 48 - return data; 49 - }, 50 - }); 51 - }; 52 - 53 - export const useRecipeQuery = (did: Did, rkey: string) => { 54 - const rpc = useXrpc(); 55 - return useQuery(recipeQueryOptions(rpc, did, rkey)); 56 - }; 57 - 58 - export const useNewRecipeMutation = (form: UseFormReturn<z.infer<typeof recipeSchema>>) => { 59 - const { agent } = useAuth(); 60 - const rpc = useXrpc(); 61 - return useMutation({ 62 - mutationKey: ['recipes.new'], 63 - mutationFn: async ({ recipe: { image, ...recipe } }: { recipe: z.infer<typeof recipeSchema> }) => { 64 - let recipeImg = null; 65 - if (image) { 66 - const imageFile = image.item(0) as File; 67 - const { ok, data } = await rpc.post('com.atproto.repo.uploadBlob', { 68 - input: imageFile, 69 - }); 70 - 71 - if (!ok) { 72 - throw new Error(`Image upload failed: ${data.error}`); 73 - } 74 - 75 - recipeImg = data.blob; 76 - } 77 - 78 - const rkey = TID.nextStr(); 79 - const { ok, data } = await rpc.post(`com.atproto.repo.createRecord`, { 80 - input: { 81 - repo: agent?.session.info.sub as ActorIdentifier, 82 - record: { 83 - ...recipe, 84 - image: recipeImg, 85 - }, 86 - collection: 'blue.recipes.feed.recipe', 87 - rkey: rkey, 88 - } 89 - }); 90 - 91 - if (!ok) { 92 - throw new Error(`Recipe creation failed: ${data.error}`); 93 - } 94 - 95 - return { 96 - rkey: rkey, 97 - resp: data, 98 - }; 99 - }, 100 - onError: (error) => { 101 - form.setError('title', error); 102 - }, 103 - onSuccess: ({ rkey }) => { 104 - window.location.assign(`/recipes/${agent?.sub}/${rkey}`); 105 - }, 106 - }); 107 - };
-26
apps/web/src/queries/self.ts
··· 1 - import { useXrpc } from "@/hooks/use-xrpc"; 2 - import { useAuth } from "@/state/auth"; 3 - import { AppBskyActorProfile } from "@atcute/client/lexicons"; 4 - import { At } from "@atcute/client/lexicons"; 5 - import { useQuery } from "@tanstack/react-query"; 6 - 7 - export const useUserQuery = () => { 8 - const { isLoggedIn, agent } = useAuth(); 9 - const rpc = useXrpc(); 10 - 11 - return useQuery({ 12 - queryKey: ['self'], 13 - queryFn: async () => { 14 - const res = await rpc.get('com.atproto.repo.getRecord', { 15 - params: { 16 - repo: agent?.sub as At.DID, 17 - collection: 'app.bsky.actor.profile', 18 - rkey: 'self', 19 - }, 20 - }); 21 - 22 - return res.data.value as AppBskyActorProfile.Record; 23 - }, 24 - enabled: isLoggedIn, 25 - }); 26 - }
+8 -164
apps/web/src/routeTree.gen.ts
··· 8 8 // You should NOT make any changes in this file as it will be overwritten. 9 9 // Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. 10 10 11 - import { createFileRoute } from '@tanstack/react-router' 12 - 13 11 import { Route as rootRouteImport } from './routes/__root' 14 - import { Route as RouteImport } from './routes/_' 15 - import { Route as authLoginRouteImport } from './routes/_.(auth)/login' 16 - import { Route as appRecipesNewRouteImport } from './routes/_.(app)/recipes/new' 17 12 18 - const appIndexLazyRouteImport = createFileRoute('/_/(app)/')() 19 - const appRecipesAuthorIndexLazyRouteImport = createFileRoute( 20 - '/_/(app)/recipes/$author/', 21 - )() 22 - const appRecipesAuthorRkeyIndexLazyRouteImport = createFileRoute( 23 - '/_/(app)/recipes/$author/$rkey/', 24 - )() 25 - 26 - const Route = RouteImport.update({ 27 - id: '/_', 28 - getParentRoute: () => rootRouteImport, 29 - } as any) 30 - const appIndexLazyRoute = appIndexLazyRouteImport 31 - .update({ 32 - id: '/(app)/', 33 - path: '/', 34 - getParentRoute: () => Route, 35 - } as any) 36 - .lazy(() => import('./routes/_.(app)/index.lazy').then((d) => d.Route)) 37 - const authLoginRoute = authLoginRouteImport.update({ 38 - id: '/(auth)/login', 39 - path: '/login', 40 - getParentRoute: () => Route, 41 - } as any) 42 - const appRecipesNewRoute = appRecipesNewRouteImport.update({ 43 - id: '/(app)/recipes/new', 44 - path: '/recipes/new', 45 - getParentRoute: () => Route, 46 - } as any) 47 - const appRecipesAuthorIndexLazyRoute = appRecipesAuthorIndexLazyRouteImport 48 - .update({ 49 - id: '/(app)/recipes/$author/', 50 - path: '/recipes/$author/', 51 - getParentRoute: () => Route, 52 - } as any) 53 - .lazy(() => 54 - import('./routes/_.(app)/recipes/$author/index.lazy').then((d) => d.Route), 55 - ) 56 - const appRecipesAuthorRkeyIndexLazyRoute = 57 - appRecipesAuthorRkeyIndexLazyRouteImport 58 - .update({ 59 - id: '/(app)/recipes/$author/$rkey/', 60 - path: '/recipes/$author/$rkey/', 61 - getParentRoute: () => Route, 62 - } as any) 63 - .lazy(() => 64 - import('./routes/_.(app)/recipes/$author/$rkey/index.lazy').then( 65 - (d) => d.Route, 66 - ), 67 - ) 68 - 69 - export interface FileRoutesByFullPath { 70 - '/login': typeof authLoginRoute 71 - '/': typeof appIndexLazyRoute 72 - '/recipes/new': typeof appRecipesNewRoute 73 - '/recipes/$author': typeof appRecipesAuthorIndexLazyRoute 74 - '/recipes/$author/$rkey': typeof appRecipesAuthorRkeyIndexLazyRoute 75 - } 76 - export interface FileRoutesByTo { 77 - '/login': typeof authLoginRoute 78 - '/': typeof appIndexLazyRoute 79 - '/recipes/new': typeof appRecipesNewRoute 80 - '/recipes/$author': typeof appRecipesAuthorIndexLazyRoute 81 - '/recipes/$author/$rkey': typeof appRecipesAuthorRkeyIndexLazyRoute 82 - } 13 + export interface FileRoutesByFullPath {} 14 + export interface FileRoutesByTo {} 83 15 export interface FileRoutesById { 84 16 __root__: typeof rootRouteImport 85 - '/_': typeof RouteWithChildren 86 - '/_/(auth)/login': typeof authLoginRoute 87 - '/_/(app)/': typeof appIndexLazyRoute 88 - '/_/(app)/recipes/new': typeof appRecipesNewRoute 89 - '/_/(app)/recipes/$author/': typeof appRecipesAuthorIndexLazyRoute 90 - '/_/(app)/recipes/$author/$rkey/': typeof appRecipesAuthorRkeyIndexLazyRoute 91 17 } 92 18 export interface FileRouteTypes { 93 19 fileRoutesByFullPath: FileRoutesByFullPath 94 - fullPaths: 95 - | '/login' 96 - | '/' 97 - | '/recipes/new' 98 - | '/recipes/$author' 99 - | '/recipes/$author/$rkey' 20 + fullPaths: never 100 21 fileRoutesByTo: FileRoutesByTo 101 - to: 102 - | '/login' 103 - | '/' 104 - | '/recipes/new' 105 - | '/recipes/$author' 106 - | '/recipes/$author/$rkey' 107 - id: 108 - | '__root__' 109 - | '/_' 110 - | '/_/(auth)/login' 111 - | '/_/(app)/' 112 - | '/_/(app)/recipes/new' 113 - | '/_/(app)/recipes/$author/' 114 - | '/_/(app)/recipes/$author/$rkey/' 22 + to: never 23 + id: '__root__' 115 24 fileRoutesById: FileRoutesById 116 25 } 117 - export interface RootRouteChildren { 118 - Route: typeof RouteWithChildren 119 - } 26 + export interface RootRouteChildren {} 120 27 121 28 declare module '@tanstack/react-router' { 122 - interface FileRoutesByPath { 123 - '/_': { 124 - id: '/_' 125 - path: '' 126 - fullPath: '' 127 - preLoaderRoute: typeof RouteImport 128 - parentRoute: typeof rootRouteImport 129 - } 130 - '/_/(app)/': { 131 - id: '/_/(app)/' 132 - path: '/' 133 - fullPath: '/' 134 - preLoaderRoute: typeof appIndexLazyRouteImport 135 - parentRoute: typeof Route 136 - } 137 - '/_/(auth)/login': { 138 - id: '/_/(auth)/login' 139 - path: '/login' 140 - fullPath: '/login' 141 - preLoaderRoute: typeof authLoginRouteImport 142 - parentRoute: typeof Route 143 - } 144 - '/_/(app)/recipes/new': { 145 - id: '/_/(app)/recipes/new' 146 - path: '/recipes/new' 147 - fullPath: '/recipes/new' 148 - preLoaderRoute: typeof appRecipesNewRouteImport 149 - parentRoute: typeof Route 150 - } 151 - '/_/(app)/recipes/$author/': { 152 - id: '/_/(app)/recipes/$author/' 153 - path: '/recipes/$author' 154 - fullPath: '/recipes/$author' 155 - preLoaderRoute: typeof appRecipesAuthorIndexLazyRouteImport 156 - parentRoute: typeof Route 157 - } 158 - '/_/(app)/recipes/$author/$rkey/': { 159 - id: '/_/(app)/recipes/$author/$rkey/' 160 - path: '/recipes/$author/$rkey' 161 - fullPath: '/recipes/$author/$rkey' 162 - preLoaderRoute: typeof appRecipesAuthorRkeyIndexLazyRouteImport 163 - parentRoute: typeof Route 164 - } 165 - } 29 + interface FileRoutesByPath {} 166 30 } 167 31 168 - interface RouteChildren { 169 - authLoginRoute: typeof authLoginRoute 170 - appIndexLazyRoute: typeof appIndexLazyRoute 171 - appRecipesNewRoute: typeof appRecipesNewRoute 172 - appRecipesAuthorIndexLazyRoute: typeof appRecipesAuthorIndexLazyRoute 173 - appRecipesAuthorRkeyIndexLazyRoute: typeof appRecipesAuthorRkeyIndexLazyRoute 174 - } 175 - 176 - const RouteChildren: RouteChildren = { 177 - authLoginRoute: authLoginRoute, 178 - appIndexLazyRoute: appIndexLazyRoute, 179 - appRecipesNewRoute: appRecipesNewRoute, 180 - appRecipesAuthorIndexLazyRoute: appRecipesAuthorIndexLazyRoute, 181 - appRecipesAuthorRkeyIndexLazyRoute: appRecipesAuthorRkeyIndexLazyRoute, 182 - } 183 - 184 - const RouteWithChildren = Route._addFileChildren(RouteChildren) 185 - 186 - const rootRouteChildren: RootRouteChildren = { 187 - Route: RouteWithChildren, 188 - } 32 + const rootRouteChildren: RootRouteChildren = {} 189 33 export const routeTree = rootRouteImport 190 34 ._addFileChildren(rootRouteChildren) 191 35 ._addFileTypes<FileRouteTypes>()
-62
apps/web/src/routes/_.(app)/index.lazy.tsx
··· 1 - import { createLazyFileRoute, Link } from '@tanstack/react-router' 2 - import { 3 - Breadcrumb, 4 - BreadcrumbItem, 5 - BreadcrumbLink, 6 - BreadcrumbList, 7 - BreadcrumbPage, 8 - BreadcrumbSeparator, 9 - } from '@/components/ui/breadcrumb' 10 - import { Separator } from '@/components/ui/separator' 11 - import { SidebarTrigger } from '@/components/ui/sidebar' 12 - import QueryPlaceholder from '@/components/query-placeholder' 13 - import { useRecipesQuery } from '@/queries/recipe' 14 - import { RecipeCard } from '@/components/recipe-card'; 15 - 16 - export const Route = createLazyFileRoute('/_/(app)/')({ 17 - component: RouteComponent, 18 - }) 19 - 20 - function RouteComponent() { 21 - const query = useRecipesQuery('') 22 - 23 - return ( 24 - <> 25 - <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"> 26 - <div className="flex items-center gap-2 px-4"> 27 - <SidebarTrigger className="-ml-1" /> 28 - <Separator orientation="vertical" className="mr-2 h-4" /> 29 - <Breadcrumb> 30 - <BreadcrumbList> 31 - <BreadcrumbItem className="hidden md:block"> 32 - <BreadcrumbLink asChild> 33 - <Link href="/">Community</Link> 34 - </BreadcrumbLink> 35 - </BreadcrumbItem> 36 - <BreadcrumbSeparator className="hidden md:block" /> 37 - <BreadcrumbItem> 38 - <BreadcrumbPage>Browse Recipes</BreadcrumbPage> 39 - </BreadcrumbItem> 40 - </BreadcrumbList> 41 - </Breadcrumb> 42 - </div> 43 - </header> 44 - <div className="flex flex-col gap-4 p-4 pt-6 items-center"> 45 - <h1 className="text-4xl font-black">Community Recipes!</h1> 46 - <p className="text-lg">See what the community's been cooking.</p> 47 - </div> 48 - <div className="flex-1 flex flex-col items-center p-4"> 49 - <div className="flex flex-col gap-4 max-w-2xl w-full items-center"> 50 - <QueryPlaceholder query={query} cards cardsCount={12}> 51 - {query.data?.recipes.map((recipe, idx) => ( 52 - <RecipeCard 53 - recipe={recipe} 54 - key={idx} 55 - /> 56 - ))} 57 - </QueryPlaceholder> 58 - </div> 59 - </div> 60 - </> 61 - ) 62 - }
-135
apps/web/src/routes/_.(app)/recipes/$author/$rkey/index.lazy.tsx
··· 1 - import { createLazyFileRoute, Link } from '@tanstack/react-router' 2 - import { 3 - Breadcrumb, 4 - BreadcrumbItem, 5 - BreadcrumbLink, 6 - BreadcrumbList, 7 - BreadcrumbPage, 8 - BreadcrumbSeparator, 9 - } from '@/components/ui/breadcrumb' 10 - import { Separator } from '@/components/ui/separator' 11 - import { SidebarTrigger } from '@/components/ui/sidebar' 12 - import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' 13 - import { recipeQueryOptions } from '@/queries/recipe' 14 - import { useSuspenseQuery } from '@tanstack/react-query' 15 - import { useXrpc } from '@/hooks/use-xrpc' 16 - import { Badge } from '@/components/ui/badge' 17 - import { Clock, Users } from 'lucide-react' 18 - import { useAuth } from '@/state/auth' 19 - import { Button } from '@/components/ui/button' 20 - 21 - export const Route = createLazyFileRoute('/_/(app)/recipes/$author/$rkey/')({ 22 - component: RouteComponent, 23 - }) 24 - 25 - function RouteComponent() { 26 - const rpc = useXrpc(); 27 - const { author, rkey } = Route.useParams() 28 - const { 29 - data: { recipe }, 30 - error, 31 - } = useSuspenseQuery(recipeQueryOptions(rpc, author, rkey)) 32 - const { isLoggedIn, agent } = useAuth(); 33 - 34 - if (error) return <p>Error</p> 35 - 36 - return ( 37 - <> 38 - <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"> 39 - <div className="flex items-center gap-2 px-4"> 40 - <SidebarTrigger className="-ml-1" /> 41 - <Separator orientation="vertical" className="mr-2 h-4" /> 42 - <Breadcrumb> 43 - <BreadcrumbList> 44 - <BreadcrumbItem className="hidden md:block"> 45 - <BreadcrumbLink asChild> 46 - <Link to="/">Community</Link> 47 - </BreadcrumbLink> 48 - </BreadcrumbItem> 49 - <BreadcrumbSeparator className="hidden md:block" /> 50 - <BreadcrumbItem className="hidden md:block"> 51 - <BreadcrumbLink asChild> 52 - <Link to="/">Browse Recipes</Link> 53 - </BreadcrumbLink> 54 - </BreadcrumbItem> 55 - <BreadcrumbSeparator className="hidden md:block" /> 56 - <BreadcrumbItem className="hidden md:block"> 57 - <BreadcrumbLink asChild> 58 - <Link to="/recipes/$author" params={{ author: recipe.author.handle }}> 59 - {recipe.author.displayName} 60 - </Link> 61 - </BreadcrumbLink> 62 - </BreadcrumbItem> 63 - <BreadcrumbSeparator className="hidden md:block" /> 64 - <BreadcrumbItem> 65 - <BreadcrumbPage>{recipe.title}</BreadcrumbPage> 66 - </BreadcrumbItem> 67 - </BreadcrumbList> 68 - </Breadcrumb> 69 - </div> 70 - </header> 71 - <div className="flex flex-col gap-4 px-4 py-8 items-center max-w-2xl w-full mx-auto"> 72 - <Card className="w-full"> 73 - 74 - <CardHeader> 75 - <CardTitle className="text-3xl font-bold">{recipe.title}</CardTitle> 76 - <CardDescription>{recipe.description}</CardDescription> 77 - </CardHeader> 78 - 79 - <CardContent className="space-y-6"> 80 - { 81 - recipe.imageUrl && 82 - <img 83 - src={recipe.imageUrl} 84 - alt={recipe.title} 85 - className="h-64 w-full object-cover rounded-md" 86 - /> 87 - } 88 - <div className="flex flex-wrap gap-4"> 89 - <Badge variant="secondary" className="flex items-center gap-2"> 90 - <Clock className="size-4" /> 91 - <span>{recipe.time} mins</span> 92 - </Badge> 93 - <Badge variant="secondary" className="flex items-center gap-2"> 94 - <Users className="size-4" /> 95 - <span>Serves {recipe.serves ?? '1'}</span> 96 - </Badge> 97 - </div> 98 - 99 - <div> 100 - <h3 className="text-xl font-semibold mb-2">Ingredients</h3> 101 - <ul className="list-disc list-inside space-y-1"> 102 - {recipe.ingredients.map((ing, idx) => ( 103 - <li key={idx}> 104 - <b>{ing.amount}</b> {ing.name} 105 - </li> 106 - ))} 107 - </ul> 108 - </div> 109 - 110 - <div> 111 - <h3 className="text-xl font-semibold mb-2">Steps</h3> 112 - <ol className="list-decimal list-outside space-y-1 ml-4"> 113 - {recipe.steps.map((ing, idx) => ( 114 - <li key={idx}>{ing.text}</li> 115 - ))} 116 - </ol> 117 - </div> 118 - </CardContent> 119 - <CardFooter className="flex justify-between"> 120 - {(isLoggedIn && agent?.sub == recipe.author.did) && ( 121 - <div className="flex items-center gap-x-4"> 122 - <Button variant="outline">Edit</Button> 123 - <Button variant="destructive">Delete</Button> 124 - </div> 125 - )} 126 - 127 - <div className="flex items-center gap-x-4"> 128 - {/* TODO: share options */} 129 - </div> 130 - </CardFooter> 131 - </Card> 132 - </div> 133 - </> 134 - ) 135 - }
-74
apps/web/src/routes/_.(app)/recipes/$author/index.lazy.tsx
··· 1 - import { createLazyFileRoute, Link } from '@tanstack/react-router' 2 - import { 3 - Breadcrumb, 4 - BreadcrumbItem, 5 - BreadcrumbLink, 6 - BreadcrumbList, 7 - BreadcrumbPage, 8 - BreadcrumbSeparator, 9 - } from '@/components/ui/breadcrumb' 10 - import { Separator } from '@/components/ui/separator' 11 - import { SidebarTrigger } from '@/components/ui/sidebar' 12 - import QueryPlaceholder from '@/components/query-placeholder' 13 - import { useRecipesQuery } from '@/queries/recipe' 14 - import { RecipeCard } from '@/components/recipe-card' 15 - import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar' 16 - 17 - export const Route = createLazyFileRoute('/_/(app)/recipes/$author/')({ 18 - component: RouteComponent, 19 - }) 20 - 21 - function RouteComponent() { 22 - const { author } = Route.useParams() 23 - const query = useRecipesQuery('', author) 24 - 25 - return ( 26 - <> 27 - <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"> 28 - <div className="flex items-center gap-2 px-4"> 29 - <SidebarTrigger className="-ml-1" /> 30 - <Separator orientation="vertical" className="mr-2 h-4" /> 31 - <Breadcrumb> 32 - <BreadcrumbList> 33 - <BreadcrumbItem className="hidden md:block"> 34 - <BreadcrumbLink asChild> 35 - <Link href="/">Community</Link> 36 - </BreadcrumbLink> 37 - </BreadcrumbItem> 38 - <BreadcrumbSeparator className="hidden md:block" /> 39 - <BreadcrumbItem> 40 - <BreadcrumbLink asChild> 41 - <Link to="/">Browse Recipes</Link> 42 - </BreadcrumbLink> 43 - </BreadcrumbItem> 44 - <BreadcrumbSeparator className="hidden md:block" /> 45 - <BreadcrumbItem className="hidden md:block"> 46 - <BreadcrumbPage>{author}</BreadcrumbPage> 47 - </BreadcrumbItem> 48 - </BreadcrumbList> 49 - </Breadcrumb> 50 - </div> 51 - </header> 52 - <div className="flex flex-col gap-4 p-4 pt-6 items-center"> 53 - <Avatar className="h-24 w-24 rounded-lg"> 54 - <AvatarImage src={query.data?.author?.avatarUrl} alt={query.data?.author?.displayName} /> 55 - <AvatarFallback className="rounded-lg">{query.data?.author?.displayName}</AvatarFallback> 56 - </Avatar> 57 - <h1 className="text-4xl font-black">{query.data?.author?.displayName}'s recipes!</h1> 58 - <p className="text-lg">See what they've been cooking.</p> 59 - </div> 60 - <div className="flex-1 flex flex-col items-center p-4"> 61 - <div className="flex flex-col gap-4 max-w-2xl w-full items-center"> 62 - <QueryPlaceholder query={query} cards cardsCount={12}> 63 - {query.data?.recipes.map((recipe, idx) => ( 64 - <RecipeCard 65 - recipe={recipe} 66 - key={idx} 67 - /> 68 - ))} 69 - </QueryPlaceholder> 70 - </div> 71 - </div> 72 - </> 73 - ) 74 - }
-372
apps/web/src/routes/_.(app)/recipes/new.tsx
··· 1 - import { createFileRoute, Link, redirect } from "@tanstack/react-router"; 2 - import { 3 - Breadcrumb, 4 - BreadcrumbItem, 5 - BreadcrumbLink, 6 - BreadcrumbList, 7 - BreadcrumbPage, 8 - BreadcrumbSeparator, 9 - } from "@/components/ui/breadcrumb"; 10 - import { Separator } from "@/components/ui/separator"; 11 - import { SidebarTrigger } from "@/components/ui/sidebar"; 12 - import { useFieldArray, useForm } from "react-hook-form"; 13 - import { z } from "zod"; 14 - import { zodResolver } from "@hookform/resolvers/zod"; 15 - import { 16 - Form, 17 - FormControl, 18 - FormDescription, 19 - FormField, 20 - FormItem, 21 - FormLabel, 22 - FormMessage, 23 - } from "@/components/ui/form"; 24 - import { Button } from "@/components/ui/button"; 25 - import { Input } from "@/components/ui/input"; 26 - import { Textarea } from "@/components/ui/textarea"; 27 - import { 28 - Card, 29 - CardContent, 30 - CardDescription, 31 - CardHeader, 32 - CardTitle, 33 - } from "@/components/ui/card"; 34 - import { 35 - Sortable, 36 - SortableDragHandle, 37 - SortableItem, 38 - } from "@/components/ui/sortable"; 39 - import { DragHandleDots2Icon } from "@radix-ui/react-icons"; 40 - import { Label } from "@/components/ui/label"; 41 - import { TrashIcon } from "lucide-react"; 42 - import { useNewRecipeMutation } from "@/queries/recipe"; 43 - 44 - export const Route = createFileRoute("/_/(app)/recipes/new")({ 45 - beforeLoad: async ({ context }) => { 46 - if (!context.auth.isLoggedIn) { 47 - throw redirect({ 48 - to: '/login', 49 - }); 50 - } 51 - }, 52 - component: RouteComponent, 53 - }); 54 - 55 - function RouteComponent() { 56 - return (<></>); 57 - // const form = useForm<z.infer<typeof recipeSchema>>({ 58 - // resolver: zodResolver(recipeSchema), 59 - // defaultValues: { 60 - // title: "", 61 - // time: 0, 62 - // image: null, 63 - // description: "", 64 - // ingredients: [{ name: "" }], 65 - // steps: [{ text: "" }], 66 - // }, 67 - // }); 68 - // 69 - // const { mutate, isPending } = useNewRecipeMutation(form); 70 - // 71 - // const onSubmit = (values: z.infer<typeof recipeSchema>) => { 72 - // mutate({ recipe: values }); 73 - // }; 74 - // 75 - // const imageRef = form.register("image"); 76 - // 77 - // const ingredients = useFieldArray({ 78 - // control: form.control, 79 - // name: "ingredients", 80 - // }); 81 - // 82 - // const steps = useFieldArray({ 83 - // control: form.control, 84 - // name: "steps", 85 - // }); 86 - // 87 - // return ( 88 - // <> 89 - // <Breadcrumbs /> 90 - // <div className="flex-1 flex-col p-4 pt-0 max-w-xl w-full mx-auto"> 91 - // <Card> 92 - // <CardHeader> 93 - // <CardTitle>New recipe</CardTitle> 94 - // <CardDescription>Share your recipe with the world!</CardDescription> 95 - // </CardHeader> 96 - // <CardContent> 97 - // <Form {...form}> 98 - // <form 99 - // onSubmit={form.handleSubmit(onSubmit)} 100 - // className="space-y-8" 101 - // > 102 - // <FormField 103 - // name="title" 104 - // control={form.control} 105 - // render={({ field }) => ( 106 - // <FormItem> 107 - // <FormLabel>Title</FormLabel> 108 - // <FormControl> 109 - // <Input placeholder="My awesome recipe!" {...field} /> 110 - // </FormControl> 111 - // <FormDescription> 112 - // This is your recipe's name. 113 - // </FormDescription> 114 - // <FormMessage /> 115 - // </FormItem> 116 - // )} 117 - // /> 118 - // 119 - // <FormField 120 - // name="description" 121 - // control={form.control} 122 - // render={({ field: { value, ...field } }) => ( 123 - // <FormItem> 124 - // <FormLabel>Description</FormLabel> 125 - // <FormControl> 126 - // <Textarea 127 - // className="resize-none" 128 - // value={value || ""} 129 - // {...field} 130 - // /> 131 - // </FormControl> 132 - // <FormDescription>Describe your recipe, maybe tell the world how tasty it is? (Optional)</FormDescription> 133 - // <FormMessage /> 134 - // </FormItem> 135 - // )} 136 - // /> 137 - // 138 - // <FormField 139 - // name="image" 140 - // control={form.control} 141 - // render={(_props) => ( 142 - // <FormItem> 143 - // <FormLabel>Image</FormLabel> 144 - // <FormControl> 145 - // <Input 146 - // type="file" 147 - // className="resize-none" 148 - // {...imageRef} 149 - // /> 150 - // </FormControl> 151 - // <FormMessage /> 152 - // </FormItem> 153 - // )} 154 - // /> 155 - // 156 - // <FormField 157 - // name="time" 158 - // control={form.control} 159 - // render={({ field: { value, ...field } }) => ( 160 - // <FormItem> 161 - // <FormLabel>Time</FormLabel> 162 - // <FormControl> 163 - // <Input 164 - // type="number" 165 - // className="resize-none" 166 - // value={value || ""} 167 - // {...field} 168 - // /> 169 - // </FormControl> 170 - // <FormDescription>How long (in minutes) does your recipe take to complete?</FormDescription> 171 - // <FormMessage /> 172 - // </FormItem> 173 - // )} 174 - // /> 175 - // 176 - // <div className="grid gap-2"> 177 - // <Label>Ingredients</Label> 178 - // <Sortable 179 - // value={ingredients.fields} 180 - // onMove={({ activeIndex, overIndex }) => 181 - // ingredients.move(activeIndex, overIndex)} 182 - // > 183 - // <div className="flex w-full flex-col gap-2"> 184 - // {ingredients.fields.map((field, index) => ( 185 - // <SortableItem key={field.id} value={field.id} asChild> 186 - // <div className="grid grid-cols-[2rem_0.3fr_1fr_2rem] items-center gap-2"> 187 - // <SortableDragHandle 188 - // type="button" 189 - // variant="outline" 190 - // size="icon" 191 - // className="size-8 shrink-0" 192 - // > 193 - // <DragHandleDots2Icon 194 - // className="size-4" 195 - // aria-hidden="true" 196 - // /> 197 - // </SortableDragHandle> 198 - // 199 - // <FormField 200 - // control={form.control} 201 - // name={`ingredients.${index}.amount`} 202 - // render={({ field: { value, ...field } }) => ( 203 - // <FormItem> 204 - // <FormControl> 205 - // <Input 206 - // placeholder="Amount" 207 - // value={value || ""} 208 - // className="h-8" 209 - // {...field} 210 - // /> 211 - // </FormControl> 212 - // <FormMessage /> 213 - // </FormItem> 214 - // )} 215 - // /> 216 - // 217 - // <FormField 218 - // control={form.control} 219 - // name={`ingredients.${index}.name`} 220 - // render={({ field }) => ( 221 - // <FormItem> 222 - // <FormControl> 223 - // <Input 224 - // placeholder="Ingredient" 225 - // className="h-8" 226 - // {...field} 227 - // /> 228 - // </FormControl> 229 - // <FormMessage /> 230 - // </FormItem> 231 - // )} 232 - // /> 233 - // 234 - // <Button 235 - // type="button" 236 - // variant="destructive" 237 - // className="size-8" 238 - // onClick={(e) => { 239 - // e.preventDefault(); 240 - // ingredients.remove(index); 241 - // }} 242 - // > 243 - // <TrashIcon /> 244 - // </Button> 245 - // </div> 246 - // </SortableItem> 247 - // ))} 248 - // </div> 249 - // </Sortable> 250 - // <Button 251 - // type="button" 252 - // variant="secondary" 253 - // onClick={(e) => { 254 - // e.preventDefault(); 255 - // ingredients.append({ 256 - // name: "", 257 - // amount: "", 258 - // }); 259 - // }} 260 - // > 261 - // Add 262 - // </Button> 263 - // </div> 264 - // 265 - // <div className="grid gap-2"> 266 - // <Label>Steps</Label> 267 - // <Sortable 268 - // value={steps.fields} 269 - // onMove={({ activeIndex, overIndex }) => 270 - // steps.move(activeIndex, overIndex)} 271 - // > 272 - // <div className="flex w-full flex-col gap-2"> 273 - // {steps.fields.map((field, index) => ( 274 - // <SortableItem key={field.id} value={field.id} asChild> 275 - // <div className="grid grid-cols-[2rem_auto_2rem] items-center gap-2"> 276 - // <SortableDragHandle 277 - // type="button" 278 - // variant="outline" 279 - // size="icon" 280 - // className="size-8 shrink-0" 281 - // > 282 - // <DragHandleDots2Icon 283 - // className="size-4" 284 - // aria-hidden="true" 285 - // /> 286 - // </SortableDragHandle> 287 - // <FormField 288 - // control={form.control} 289 - // name={`steps.${index}.text`} 290 - // render={({ field }) => ( 291 - // <FormItem> 292 - // <FormControl> 293 - // <Input className="h-8" {...field} /> 294 - // </FormControl> 295 - // <FormMessage /> 296 - // </FormItem> 297 - // )} 298 - // /> 299 - // 300 - // <Button 301 - // type="button" 302 - // variant="destructive" 303 - // className="size-8" 304 - // onClick={(e) => { 305 - // e.preventDefault(); 306 - // steps.remove(index); 307 - // }} 308 - // > 309 - // <TrashIcon /> 310 - // </Button> 311 - // </div> 312 - // </SortableItem> 313 - // ))} 314 - // </div> 315 - // </Sortable> 316 - // <Button 317 - // type="button" 318 - // variant="secondary" 319 - // onClick={(e) => { 320 - // e.preventDefault(); 321 - // steps.append({ text: "" }); 322 - // }} 323 - // > 324 - // Add 325 - // </Button> 326 - // </div> 327 - // 328 - // <div className="grid justify-end"> 329 - // <Button 330 - // type="submit" 331 - // className="ml-auto" 332 - // disabled={isPending} 333 - // > 334 - // Submit 335 - // </Button> 336 - // </div> 337 - // </form> 338 - // </Form> 339 - // </CardContent> 340 - // </Card> 341 - // </div> 342 - // </> 343 - // ); 344 - } 345 - 346 - const Breadcrumbs = () => ( 347 - <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"> 348 - <div className="flex items-center gap-2 px-4"> 349 - <SidebarTrigger className="-ml-1" /> 350 - <Separator orientation="vertical" className="mr-2 h-4" /> 351 - <Breadcrumb> 352 - <BreadcrumbList> 353 - <BreadcrumbItem className="hidden md:block"> 354 - <BreadcrumbLink asChild> 355 - <Link href="/">Home</Link> 356 - </BreadcrumbLink> 357 - </BreadcrumbItem> 358 - <BreadcrumbSeparator className="hidden md:block" /> 359 - <BreadcrumbItem className="hidden md:block"> 360 - <BreadcrumbLink asChild> 361 - <Link href="/recipes">Recipes</Link> 362 - </BreadcrumbLink> 363 - </BreadcrumbItem> 364 - <BreadcrumbSeparator className="hidden md:block" /> 365 - <BreadcrumbItem> 366 - <BreadcrumbPage>New</BreadcrumbPage> 367 - </BreadcrumbItem> 368 - </BreadcrumbList> 369 - </Breadcrumb> 370 - </div> 371 - </header> 372 - );
-106
apps/web/src/routes/_.(auth)/login.tsx
··· 1 - import { 2 - Breadcrumb, 3 - BreadcrumbItem, 4 - BreadcrumbList, 5 - BreadcrumbPage, 6 - } from '@/components/ui/breadcrumb' 7 - import { Button } from '@/components/ui/button' 8 - import { 9 - Card, 10 - CardContent, 11 - CardDescription, 12 - CardFooter, 13 - CardHeader, 14 - CardTitle, 15 - } from '@/components/ui/card' 16 - import { Input } from '@/components/ui/input' 17 - import { Label } from '@/components/ui/label' 18 - import { Separator } from '@/components/ui/separator' 19 - import { SidebarTrigger } from '@/components/ui/sidebar' 20 - import { sleep } from '@/lib/utils' 21 - import { useSession } from '@/state/auth/session' 22 - import { isHandle } from '@atcute/lexicons/syntax' 23 - import { createAuthorizationUrl } from '@atcute/oauth-browser-client' 24 - import { useMutation } from '@tanstack/react-query' 25 - import { createFileRoute } from '@tanstack/react-router' 26 - import { useState } from 'react' 27 - 28 - export const Route = createFileRoute('/_/(auth)/login')({ 29 - component: RouteComponent, 30 - }) 31 - 32 - function RouteComponent() { 33 - const { signIn } = useSession(); 34 - const [handle, setHandle] = useState('') 35 - 36 - const { mutate, isPending, error } = useMutation({ 37 - mutationKey: ['login'], 38 - mutationFn: async () => { 39 - await signIn(handle); 40 - return; 41 - }, 42 - }) 43 - 44 - return ( 45 - <> 46 - <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"> 47 - <div className="flex items-center gap-2 px-4"> 48 - <SidebarTrigger className="-ml-1" /> 49 - <Separator orientation="vertical" className="mr-2 h-4" /> 50 - <Breadcrumb> 51 - <BreadcrumbList> 52 - <BreadcrumbItem> 53 - <BreadcrumbPage>Log in</BreadcrumbPage> 54 - </BreadcrumbItem> 55 - </BreadcrumbList> 56 - </Breadcrumb> 57 - </div> 58 - </header> 59 - <div className="flex flex-1 flex-col items-center justify-center gap-4 p-4 pt-0"> 60 - <Card className="max-w-sm w-full"> 61 - <CardHeader> 62 - <CardTitle>Log in</CardTitle> 63 - <CardDescription> 64 - Enter your handle below to sign in to your account. 65 - </CardDescription> 66 - </CardHeader> 67 - <CardContent> 68 - <div className="flex flex-col gap-2"> 69 - <Label htmlFor="handle">Handle</Label> 70 - <Input 71 - className={`${error ? 'border-destructive text-destructive' : ''}`} 72 - type="text" 73 - id="handle" 74 - name="handle" 75 - placeholder="johndoe.bsky.social" 76 - required 77 - value={handle} 78 - onChange={(e) => setHandle(e.currentTarget.value)} 79 - /> 80 - {error && ( 81 - <p className="text-sm font-medium text-destructive"> 82 - {error.message} 83 - </p> 84 - )} 85 - </div> 86 - </CardContent> 87 - <CardFooter className="grid gap-2"> 88 - <Button onClick={() => mutate()} disabled={isPending}> 89 - Log in 90 - </Button> 91 - <p className="text-sm text-muted-foreground text-center"> 92 - Don't have an account?{' '} 93 - <a 94 - className="font-bold text-primary" 95 - href="https://bsky.app/" 96 - target="_blank" 97 - > 98 - Sign up on Bluesky! 99 - </a> 100 - </p> 101 - </CardFooter> 102 - </Card> 103 - </div> 104 - </> 105 - ) 106 - }
-70
apps/web/src/routes/_.tsx
··· 1 - import { Link, createFileRoute, Outlet } from '@tanstack/react-router' 2 - import { Button } from '@/components/ui/button' 3 - import { Card, CardContent, CardFooter, CardHeader, CardTitle } from '@/components/ui/card' 4 - import { SidebarTrigger } from '@/components/ui/sidebar' 5 - 6 - export const Route = createFileRoute('/_')({ 7 - component: RouteComponent, 8 - errorComponent: ({ error }) => { 9 - return ( 10 - <> 11 - <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"> 12 - <div className="flex items-center gap-2 px-4"> 13 - <SidebarTrigger className="-ml-1" /> 14 - </div> 15 - </header> 16 - <div className="flex flex-1 flex-col gap-4 p-4 pt-0"> 17 - <Card className="m-auto max-w-sm"> 18 - <CardHeader> 19 - <CardTitle>Error!</CardTitle> 20 - </CardHeader> 21 - <CardContent> 22 - {error.message} 23 - </CardContent> 24 - <CardFooter> 25 - <Button asChild> 26 - <Link to="/">Go home</Link> 27 - </Button> 28 - </CardFooter> 29 - </Card> 30 - </div> 31 - </> 32 - ); 33 - }, 34 - 35 - notFoundComponent: () => { 36 - return ( 37 - <> 38 - <header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"> 39 - <div className="flex items-center gap-2 px-4"> 40 - <SidebarTrigger className="-ml-1" /> 41 - </div> 42 - </header> 43 - <div className="flex flex-1 flex-col gap-4 p-4 pt-0"> 44 - <Card className="m-auto max-w-sm"> 45 - <CardHeader> 46 - <CardTitle>Not found</CardTitle> 47 - </CardHeader> 48 - <CardContent> 49 - {"The page you tried to view doesn't exist."} 50 - </CardContent> 51 - <CardFooter> 52 - <Button asChild> 53 - <Link to="/">Go home</Link> 54 - </Button> 55 - </CardFooter> 56 - </Card> 57 - </div> 58 - </> 59 - ); 60 - }, 61 - 62 - }) 63 - 64 - function RouteComponent() { 65 - return ( 66 - <> 67 - <Outlet /> 68 - </> 69 - ) 70 - }
+8 -19
apps/web/src/routes/__root.tsx
··· 1 - import { AppSidebar } from '@/components/app-sidebar' 2 - import { 3 - SidebarInset, 4 - SidebarProvider, 5 - } from '@/components/ui/sidebar' 6 - import { AuthContextType } from '@/state/auth'; 7 - import { Outlet, createRootRouteWithContext } from '@tanstack/react-router' 1 + import * as React from 'react' 2 + import { Outlet, createRootRoute } from '@tanstack/react-router' 8 3 9 - type RootContext = { 10 - auth: AuthContextType; 11 - }; 12 - 13 - export const Route = createRootRouteWithContext<RootContext>()({ 4 + export const Route = createRootRoute({ 14 5 component: RootComponent, 15 - }); 6 + }) 16 7 17 8 function RootComponent() { 18 9 return ( 19 - <SidebarProvider> 20 - <AppSidebar /> 21 - <SidebarInset> 22 - <Outlet /> 23 - </SidebarInset> 24 - </SidebarProvider> 10 + <React.Fragment> 11 + <div>Hello "__root"!</div> 12 + <Outlet /> 13 + </React.Fragment> 25 14 ) 26 15 }
-45
apps/web/src/screens/Recipes/RecipeCard.tsx
··· 1 - import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; 2 - import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"; 3 - import { BlueRecipesFeedGetRecipes } from "@atcute/client/lexicons"; 4 - import { Link } from "@tanstack/react-router"; 5 - import { Clock, CookingPot, ListIcon } from "lucide-react"; 6 - 7 - type RecipeCardProps = { 8 - recipe: BlueRecipesFeedGetRecipes.Result; 9 - }; 10 - 11 - export const RecipeCard = ({ recipe }: RecipeCardProps) => { 12 - return ( 13 - <Link to="/recipes/$author/$rkey" params={{ author: recipe.author.handle, rkey: recipe.rkey }} className="w-full"> 14 - <Card className="w-full"> 15 - <CardHeader> 16 - <CardDescription className="flex items-center space-x-2"> 17 - <Avatar className="h-6 w-6 rounded-lg"> 18 - <AvatarImage src={recipe.author.avatarUrl} alt={recipe.author.displayName} /> 19 - <AvatarFallback className="rounded-lg">{recipe.author.displayName}</AvatarFallback> 20 - </Avatar> 21 - 22 - <span>{recipe.author.displayName}</span> 23 - </CardDescription> 24 - <CardTitle>{recipe.title}</CardTitle> 25 - </CardHeader> 26 - <CardContent> 27 - <p>{recipe.description}</p> 28 - </CardContent> 29 - <CardFooter className="flex gap-6 text-sm text-muted-foreground"> 30 - <span className="flex items-center gap-2"> 31 - <ListIcon className="size-4" /> <span>{recipe.steps}</span> 32 - </span> 33 - 34 - <span className="flex items-center gap-2"> 35 - <CookingPot className="size-4" /> <span>{recipe.ingredients}</span> 36 - </span> 37 - 38 - <span className="flex items-center gap-2"> 39 - <Clock className="size-4" /> <span>{recipe.time} mins</span> 40 - </span> 41 - </CardFooter> 42 - </Card> 43 - </Link> 44 - ); 45 - };
apps/web/src/state/auth/client.tsx

This is a binary file and will not be displayed.

-2
apps/web/src/state/auth/index.ts
··· 1 - export * from './client'; 2 - export * from './session';
-104
apps/web/src/state/auth/session.tsx
··· 1 - import { Did, isActorIdentifier, isHandle } from "@atcute/lexicons/syntax"; 2 - import { createAuthorizationUrl, deleteStoredSession, finalizeAuthorization, getSession, OAuthUserAgent, Session } from "@atcute/oauth-browser-client"; 3 - import { SessionState } from "node:http2"; 4 - import { createContext, PropsWithChildren, useContext, useEffect, useState } from "react"; 5 - 6 - export type SessionContext = { 7 - session: null | Session; 8 - isLoading: boolean; 9 - isLoggedIn: boolean; 10 - signIn: (handle: string) => Promise<void>; 11 - signOut: () => Promise<void>; 12 - }; 13 - 14 - const sessionContext = createContext<SessionContext>({ 15 - session: null, 16 - isLoading: false, 17 - isLoggedIn: false, 18 - signIn: async () => { 19 - throw new Error("AuthContext not initialized"); 20 - }, 21 - signOut: async () => { 22 - throw new Error("AuthContext not initialized"); 23 - }, 24 - }); 25 - 26 - export const SessionProvider = ({ children }: PropsWithChildren<{}>) => { 27 - const [initialized, setInitialized] = useState(false); 28 - const [loading, setLoading] = useState(true); 29 - const [session, setSession] = useState<null | Session>(null); 30 - const [agent, setAgent] = useState<null | OAuthUserAgent>(null); 31 - 32 - useEffect(() => { 33 - setInitialized(false); 34 - setSession(null); 35 - setAgent(null); 36 - 37 - const params = new URLSearchParams(location.hash.slice(1)); 38 - if (params.has("state") && params.has("iss") && params.has("code")) { 39 - // If there is an active auth attempt: 40 - history.replaceState(null, "", location.pathname + location.search); 41 - finalizeAuthorization(params) 42 - .then(val => { 43 - setSession(val.session); 44 - setAgent(new OAuthUserAgent(val.session)); 45 - }) 46 - .catch(err => { 47 - console.error("Failed to initialize session:", err); 48 - }) 49 - .finally(() => { 50 - setLoading(false); 51 - setInitialized(true); 52 - }); 53 - } else { 54 - setLoading(false); 55 - setInitialized(true); 56 - } 57 - }, []); 58 - 59 - const signIn = async (handle: string) => { 60 - if (!isActorIdentifier(handle)) throw new Error("Invalid handle or DID!"); 61 - const authUrl = await createAuthorizationUrl({ 62 - target: { type: 'account', identifier: handle }, 63 - scope: 'atproto transition:generic', 64 - }); 65 - window.location.assign(authUrl); 66 - }; 67 - 68 - const signOut = async () => { 69 - if (!agent || !session) return; 70 - 71 - const did = session.info.sub; 72 - try { 73 - const session = await getSession(did, { allowStale: true }); 74 - const agent = new OAuthUserAgent(session); 75 - 76 - await agent.signOut(); 77 - setSession(null); 78 - } catch(err) { 79 - deleteStoredSession(did); 80 - } 81 - }; 82 - 83 - if (!initialized) return ( 84 - <p>Loading...</p> 85 - ); 86 - 87 - return ( 88 - <sessionContext.Provider value={{ 89 - isLoading: loading, 90 - isLoggedIn: session !== null, 91 - session, 92 - signIn, 93 - signOut, 94 - }}> 95 - {children} 96 - </sessionContext.Provider> 97 - ); 98 - }; 99 - 100 - export const useSession = () => { 101 - const ctx = useContext(sessionContext); 102 - if (!ctx) throw new Error("useSession() must be called inside a <SessionProvider />!"); 103 - return ctx; 104 - };
-83
apps/web/src/state/auth.tsx
··· 1 - import { Did } from "@atcute/lexicons"; 2 - import { finalizeAuthorization, getSession, OAuthUserAgent, Session } from "@atcute/oauth-browser-client"; 3 - import { createContext, PropsWithChildren, useContext, useEffect, useState } from "react"; 4 - 5 - export type AuthContextType = { 6 - isLoggedIn: boolean; 7 - hasProfile: boolean; 8 - agent?: OAuthUserAgent; 9 - logOut: () => Promise<void>; 10 - }; 11 - 12 - const AuthContext = createContext<AuthContextType>({ 13 - isLoggedIn: false, 14 - hasProfile: false, 15 - logOut: async () => {}, 16 - }); 17 - 18 - export const AuthProvider = ({ children }: PropsWithChildren) => { 19 - const [isReady, setIsReady] = useState(false); 20 - const [isLoggedIn, setIsLoggedIn] = useState(false); 21 - const [hasProfile, setHasProfile] = useState(false); 22 - const [agent, setAgent] = useState<OAuthUserAgent | undefined>(undefined); 23 - 24 - useEffect(() => { 25 - const init = async () => { 26 - const params = new URLSearchParams(location.hash.slice(1)); 27 - let session: Session | null = null; 28 - 29 - if (params.has("state") && (params.has("code") || params.has("error"))) { 30 - history.replaceState(null, "", location.pathname + location.search); 31 - 32 - const session = await finalizeAuthorization(params); 33 - const did = session.info.sub; 34 - 35 - localStorage.setItem("lastSignedIn", did); 36 - } else { 37 - const lastSignedIn = localStorage.getItem("lastSignedIn"); 38 - 39 - if (lastSignedIn) { 40 - try { 41 - return await getSession(lastSignedIn as Did); 42 - } catch (err) { 43 - localStorage.removeItem("lastSignedIn"); 44 - throw err; 45 - } 46 - } 47 - } 48 - 49 - setAgent(new OAuthUserAgent(session!)); 50 - }; 51 - 52 - init() 53 - .then(session => { 54 - if (session) { 55 - setAgent(new OAuthUserAgent(session)); 56 - setIsLoggedIn(true); 57 - } 58 - 59 - setIsReady(true) 60 - }) 61 - .catch(() => {}); 62 - }, []); 63 - 64 - if (!isReady) return null; 65 - 66 - return ( 67 - <AuthContext.Provider value={{ 68 - isLoggedIn, 69 - hasProfile, 70 - agent, 71 - logOut: async () => { 72 - await agent?.signOut(); 73 - setIsLoggedIn(false); 74 - }, 75 - }}> 76 - {children} 77 - </AuthContext.Provider> 78 - ); 79 - }; 80 - 81 - export const useAuth = () => { 82 - return useContext(AuthContext); 83 - };
apps/web/src/state/client.tsx

This is a binary file and will not be displayed.

+4 -7
apps/web/src/vite-env.d.ts
··· 1 - /// <reference types="vite/client" /> 1 + interface ViteTypeOptions {} 2 2 3 3 interface ImportMetaEnv { 4 - readonly VITE_API_SERVICE: string; 5 - readonly VITE_DEV_SERVER_PORT?: string; 6 - readonly VITE_CLIENT_URI: string; 7 - readonly VITE_OAUTH_CLIENT_ID: string; 8 - readonly VITE_OAUTH_REDIRECT_URL: string; 9 - readonly VITE_OAUTH_SCOPE: string; 4 + readonly VITE_API_URL: string; 5 + readonly VITE_CLIENT_ID: string; 6 + readonly VITE_REDIRECT_URI: string; 10 7 } 11 8 12 9 interface ImportMeta {
-69
apps/web/tailwind.config.js
··· 1 - import animate from 'tailwindcss-animate'; 2 - /** @type {import('tailwindcss').Config} */ 3 - export default { 4 - darkMode: ["class"], 5 - content: ["./index.html", "./src/**/*.{ts,tsx,js,jsx}"], 6 - theme: { 7 - extend: { 8 - borderRadius: { 9 - lg: 'var(--radius)', 10 - md: 'calc(var(--radius) - 2px)', 11 - sm: 'calc(var(--radius) - 4px)' 12 - }, 13 - colors: { 14 - background: 'hsl(var(--background))', 15 - foreground: 'hsl(var(--foreground))', 16 - card: { 17 - DEFAULT: 'hsl(var(--card))', 18 - foreground: 'hsl(var(--card-foreground))' 19 - }, 20 - popover: { 21 - DEFAULT: 'hsl(var(--popover))', 22 - foreground: 'hsl(var(--popover-foreground))' 23 - }, 24 - primary: { 25 - DEFAULT: 'hsl(var(--primary))', 26 - foreground: 'hsl(var(--primary-foreground))' 27 - }, 28 - secondary: { 29 - DEFAULT: 'hsl(var(--secondary))', 30 - foreground: 'hsl(var(--secondary-foreground))' 31 - }, 32 - muted: { 33 - DEFAULT: 'hsl(var(--muted))', 34 - foreground: 'hsl(var(--muted-foreground))' 35 - }, 36 - accent: { 37 - DEFAULT: 'hsl(var(--accent))', 38 - foreground: 'hsl(var(--accent-foreground))' 39 - }, 40 - destructive: { 41 - DEFAULT: 'hsl(var(--destructive))', 42 - foreground: 'hsl(var(--destructive-foreground))' 43 - }, 44 - border: 'hsl(var(--border))', 45 - input: 'hsl(var(--input))', 46 - ring: 'hsl(var(--ring))', 47 - chart: { 48 - '1': 'hsl(var(--chart-1))', 49 - '2': 'hsl(var(--chart-2))', 50 - '3': 'hsl(var(--chart-3))', 51 - '4': 'hsl(var(--chart-4))', 52 - '5': 'hsl(var(--chart-5))' 53 - }, 54 - sidebar: { 55 - DEFAULT: 'hsl(var(--sidebar-background))', 56 - foreground: 'hsl(var(--sidebar-foreground))', 57 - primary: 'hsl(var(--sidebar-primary))', 58 - 'primary-foreground': 'hsl(var(--sidebar-primary-foreground))', 59 - accent: 'hsl(var(--sidebar-accent))', 60 - 'accent-foreground': 'hsl(var(--sidebar-accent-foreground))', 61 - border: 'hsl(var(--sidebar-border))', 62 - ring: 'hsl(var(--sidebar-ring))' 63 - } 64 - } 65 - } 66 - }, 67 - plugins: [animate], 68 - } 69 -
+4 -25
apps/web/tsconfig.app.json
··· 1 1 { 2 + "extends": "@cookware/tsconfig/react.json", 2 3 "compilerOptions": { 3 - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", 4 - "target": "ES2020", 5 - "useDefineForClassFields": true, 6 - "lib": ["ES2020", "DOM", "DOM.Iterable"], 7 - "module": "ESNext", 8 - "skipLibCheck": true, 4 + "types": ["bun", "vite/client"], 9 5 10 - /* Bundler mode */ 11 - "moduleResolution": "bundler", 12 - "allowImportingTsExtensions": true, 13 - "isolatedModules": true, 14 - "moduleDetection": "force", 15 - "noEmit": true, 16 - "jsx": "react-jsx", 17 - 18 - /* Linting */ 19 - "strict": true, 20 - "noUnusedLocals": true, 21 - "noUnusedParameters": true, 22 - "noFallthroughCasesInSwitch": true, 23 - "noUncheckedSideEffectImports": true, 24 - 25 - /* Import aliases */ 6 + /* Path aliasing */ 26 7 "baseUrl": ".", 27 8 "paths": { 28 - "@/*": [ 29 - "./src/*" 30 - ] 9 + "@/*": ["./src/*"] 31 10 } 32 11 }, 33 12 "include": ["src"]
+1
apps/web/tsconfig.json
··· 1 1 { 2 + "extends": "@cookware/tsconfig/react.json", 2 3 "files": [], 3 4 "references": [ 4 5 { "path": "./tsconfig.app.json" },
+1 -21
apps/web/tsconfig.node.json
··· 1 1 { 2 - "compilerOptions": { 3 - "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", 4 - "target": "ES2022", 5 - "lib": ["ES2023"], 6 - "module": "ESNext", 7 - "skipLibCheck": true, 8 - 9 - /* Bundler mode */ 10 - "moduleResolution": "bundler", 11 - "allowImportingTsExtensions": true, 12 - "isolatedModules": true, 13 - "moduleDetection": "force", 14 - "noEmit": true, 15 - 16 - /* Linting */ 17 - "strict": true, 18 - "noUnusedLocals": true, 19 - "noUnusedParameters": true, 20 - "noFallthroughCasesInSwitch": true, 21 - "noUncheckedSideEffectImports": true 22 - }, 2 + "extends": "@cookware/tsconfig/base.json", 23 3 "include": ["vite.config.ts"] 24 4 }
+13 -45
apps/web/vite.config.ts
··· 1 - import { defineConfig } from 'vite' 2 - import react from '@vitejs/plugin-react-swc' 3 - import { tanstackRouter } from '@tanstack/router-plugin/vite' 4 - import path from 'path' 5 - import metadata from "./public/oauth-client-metadata.json" with { type: 'json' }; 1 + import { defineConfig } from 'vite'; 2 + import react from '@vitejs/plugin-react'; 3 + import tailwindcss from '@tailwindcss/vite'; 4 + import { tanstackRouter } from '@tanstack/router-plugin/vite'; 5 + import path from 'node:path'; 6 6 7 - const SERVER_HOST = "127.0.0.1"; 8 - const SERVER_PORT = 5173; 9 - 10 - // https://vite.dev/config/ 11 7 export default defineConfig({ 12 8 plugins: [ 13 - tanstackRouter(), 14 - react(), 15 - { 16 - name: '_config', 17 - config(_conf, { command }) { 18 - if (command === 'build') { 19 - process.env.VITE_OAUTH_CLIENT_ID = metadata.client_id; 20 - process.env.VITE_OAUTH_REDIRECT_URI = metadata.redirect_uris[0]; 21 - } else { 22 - const redirectUri = (() => { 23 - const url = new URL(metadata.redirect_uris[0]); 24 - return `http://${SERVER_HOST}:${SERVER_PORT}${url.pathname}`; 25 - })(); 26 - 27 - const clientId = 28 - `http://localhost` + 29 - `?redirect_uri=${encodeURIComponent(redirectUri)}` + 30 - `&scope=${encodeURIComponent(metadata.scope)}`; 31 - 32 - process.env.VITE_DEV_SERVER_PORT = '' + SERVER_PORT; 33 - process.env.VITE_OAUTH_CLIENT_ID = clientId; 34 - process.env.VITE_OAUTH_REDIRECT_URI = redirectUri; 35 - } 9 + tanstackRouter({ 10 + target: 'react', 11 + autoCodeSplitting: true, 12 + }), 13 + tailwindcss(), 14 + react() 15 + ], 36 16 37 - process.env.VITE_CLIENT_URI = metadata.client_uri; 38 - process.env.VITE_OAUTH_SCOPE = metadata.scope; 39 - }, 40 - }, 41 - ], 42 - server: { 43 - host: SERVER_HOST, 44 - port: SERVER_PORT, 45 - }, 46 - build: { 47 - target: "esnext", 48 - }, 49 17 resolve: { 50 18 alias: { 51 - '@': path.resolve(__dirname, './src'), 19 + "@": path.resolve(__dirname, "./src"), 52 20 } 53 21 } 54 22 })
+704 -582
bun.lock
··· 4 4 "workspaces": { 5 5 "": { 6 6 "name": "@cookware/monorepo", 7 + "dependencies": { 8 + "@atcute/oauth-browser-client": "^2.0.2", 9 + "@tanstack/react-router": "^1.140.0", 10 + }, 7 11 "devDependencies": { 12 + "@tanstack/react-router-devtools": "^1.140.0", 13 + "@tanstack/router-plugin": "^1.140.0", 8 14 "turbo": "^2.3.3", 9 15 "typescript": "^5.9.3", 10 16 }, ··· 22 28 "@cookware/lexicons": "workspace:*", 23 29 "@libsql/client": "^0.14.0", 24 30 "drizzle-orm": "catalog:", 31 + "hono": "^4.10.7", 25 32 "pino": "^9.5.0", 26 33 }, 27 34 "devDependencies": { ··· 29 36 "@cookware/tsconfig": "workspace:*", 30 37 "@types/bun": "catalog:", 31 38 "drizzle-kit": "^0.29.0", 39 + "pino-pretty": "^13.1.2", 32 40 "rimraf": "^6.0.1", 33 41 }, 34 42 }, 43 + "apps/app": { 44 + "name": "app", 45 + "version": "0.1.0", 46 + "dependencies": { 47 + "@atcute/atproto": "catalog:", 48 + "@atcute/client": "catalog:", 49 + "@atcute/identity": "catalog:", 50 + "@atcute/identity-resolver": "catalog:", 51 + "@atcute/lexicons": "catalog:", 52 + "@atproto/oauth-client-node": "^0.3.13", 53 + "@cookware/lexicons": "workspace:*", 54 + "@radix-ui/react-avatar": "^1.1.11", 55 + "@radix-ui/react-dialog": "^1.1.15", 56 + "@radix-ui/react-dropdown-menu": "^2.1.16", 57 + "@radix-ui/react-label": "^2.1.8", 58 + "@radix-ui/react-separator": "^1.1.8", 59 + "@radix-ui/react-slot": "^1.2.4", 60 + "@radix-ui/react-tooltip": "^1.2.8", 61 + "@tabler/icons-react": "^3.35.0", 62 + "@tanstack/react-query": "^5.90.12", 63 + "class-variance-authority": "^0.7.1", 64 + "clsx": "^2.1.1", 65 + "lucide-react": "^0.556.0", 66 + "next": "16.0.7", 67 + "react": "19.2.0", 68 + "react-dom": "19.2.0", 69 + "tailwind-merge": "^3.4.0", 70 + }, 71 + "devDependencies": { 72 + "@tailwindcss/postcss": "^4", 73 + "@tanstack/query-devtools": "^5.91.1", 74 + "@tanstack/react-query-devtools": "^5.91.1", 75 + "@types/node": "^20", 76 + "@types/react": "^19", 77 + "@types/react-dom": "^19", 78 + "eslint": "^9", 79 + "eslint-config-next": "16.0.7", 80 + "tailwindcss": "^4", 81 + "tw-animate-css": "^1.4.0", 82 + "typescript": "^5", 83 + }, 84 + }, 35 85 "apps/ingester": { 36 86 "name": "@cookware/ingester", 37 87 "dependencies": { ··· 56 106 }, 57 107 }, 58 108 "apps/web": { 59 - "name": "@cookware/web", 109 + "name": "web", 60 110 "version": "0.0.0", 61 111 "dependencies": { 62 - "@atcute/atproto": "^3.1.9", 63 - "@atcute/client": "catalog:", 64 - "@atcute/identity-resolver": "^1.1.4", 65 - "@atcute/lexicons": "catalog:", 66 - "@atcute/oauth-browser-client": "^2.0.1", 67 - "@atproto/common": "^0.4.5", 68 - "@atproto/common-web": "^0.3.1", 69 - "@dnd-kit/core": "^6.3.1", 70 - "@dnd-kit/modifiers": "^9.0.0", 71 - "@dnd-kit/sortable": "^10.0.0", 72 - "@dnd-kit/utilities": "^3.2.2", 73 - "@hookform/resolvers": "^3.9.1", 74 - "@radix-ui/react-avatar": "^1.1.1", 75 - "@radix-ui/react-collapsible": "^1.1.1", 76 - "@radix-ui/react-dialog": "^1.1.4", 77 - "@radix-ui/react-dropdown-menu": "^2.1.4", 78 - "@radix-ui/react-icons": "^1.3.2", 79 - "@radix-ui/react-label": "^2.1.0", 80 - "@radix-ui/react-separator": "^1.1.0", 81 - "@radix-ui/react-slot": "^1.1.0", 82 - "@radix-ui/react-tooltip": "^1.1.4", 83 - "@tanstack/react-query": "^5.62.2", 84 - "@tanstack/react-query-devtools": "^5.62.2", 85 - "@tanstack/react-router": "^1.91.2", 86 - "axios": "^1.7.9", 112 + "@radix-ui/react-avatar": "^1.1.11", 113 + "@radix-ui/react-dialog": "^1.1.15", 114 + "@radix-ui/react-dropdown-menu": "^2.1.16", 115 + "@radix-ui/react-label": "^2.1.8", 116 + "@radix-ui/react-separator": "^1.1.8", 117 + "@radix-ui/react-slot": "^1.2.4", 118 + "@radix-ui/react-tooltip": "^1.2.8", 87 119 "class-variance-authority": "^0.7.1", 88 120 "clsx": "^2.1.1", 89 - "lucide-react": "^0.464.0", 90 - "react-dom": "19.0.0", 91 - "react-hook-form": "^7.54.1", 92 - "tailwind-merge": "^2.5.5", 93 - "tailwindcss-animate": "^1.0.7", 94 - "zod": "^3.23.8", 121 + "lucide-react": "^0.556.0", 122 + "react": "^19.2.0", 123 + "react-dom": "^19.2.0", 124 + "tailwind-merge": "^3.4.0", 125 + "tailwindcss": "^4.1.17", 95 126 }, 96 127 "devDependencies": { 97 - "@atcute/bluesky": "^1.0.9", 98 - "@cookware/lexicons": "workspace:*", 99 - "@eslint/js": "^9.15.0", 100 - "@tanstack/eslint-plugin-query": "^5.62.1", 101 - "@tanstack/router-devtools": "^1.85.5", 102 - "@tanstack/router-plugin": "^1.85.3", 103 - "@types/node": "^22.10.1", 104 - "@types/react": "^19.0.0", 105 - "@types/react-dom": "^19.0.0", 106 - "@vitejs/plugin-react-swc": "^3.5.0", 107 - "autoprefixer": "^10.4.20", 108 - "cssnano": "^7.0.6", 109 - "eslint": "^9.15.0", 110 - "eslint-plugin-react-hooks": "^5.0.0", 111 - "eslint-plugin-react-refresh": "^0.4.14", 112 - "globals": "^15.12.0", 113 - "postcss": "^8.4.49", 114 - "react": "19.0.0", 115 - "tailwindcss": "^3.4.16", 116 - "typescript": "~5.6.2", 117 - "typescript-eslint": "^8.15.0", 118 - "vite": "^6.0.1", 128 + "@cookware/tsconfig": "workspace:*", 129 + "@eslint/js": "^9.39.1", 130 + "@tailwindcss/vite": "^4.1.17", 131 + "@types/bun": "^1.3.4", 132 + "@types/react": "^19.2.5", 133 + "@types/react-dom": "^19.2.3", 134 + "@vitejs/plugin-react": "^5.1.1", 135 + "eslint": "^9.39.1", 136 + "eslint-plugin-react-hooks": "^7.0.1", 137 + "eslint-plugin-react-refresh": "^0.4.24", 138 + "globals": "^16.5.0", 139 + "tw-animate-css": "^1.4.0", 140 + "typescript": "~5.9.3", 141 + "typescript-eslint": "^8.46.4", 142 + "vite": "npm:rolldown-vite@7.2.5", 119 143 }, 120 144 }, 121 145 "libs/database": { ··· 124 148 "dependencies": { 125 149 "@libsql/client": "^0.15.15", 126 150 "drizzle-orm": "catalog:", 151 + "pg": "^8.16.3", 127 152 "zod": "^3.23.8", 128 153 }, 129 154 "devDependencies": { ··· 133 158 "@cookware/tsconfig": "workspace:*", 134 159 "@types/bun": "catalog:", 135 160 "@types/node": "^22.10.1", 161 + "@types/pg": "^8.15.6", 136 162 "drizzle-kit": "^0.29.0", 137 163 "typescript": "^5.2.2", 138 164 }, ··· 166 192 "@atcute/atproto": "^3.1.9", 167 193 "@atcute/bluesky": "^3.2.11", 168 194 "@atcute/client": "^4.0.5", 195 + "@atcute/identity": "^1.1.3", 196 + "@atcute/identity-resolver": "^1.1.4", 169 197 "@atcute/lexicons": "^1.2.5", 170 198 "@types/bun": "^1.3.3", 171 199 "drizzle-orm": "^0.44.7", ··· 181 209 182 210 "@atcute/cid": ["@atcute/cid@2.2.6", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5" } }, "sha512-bTAHHbJ24p+E//V4KCS4xdmd39o211jJswvqQOevj7vk+5IYcgDLx1ryZWZ1sEPOo9x875li/kj5gpKL14RDwQ=="], 183 211 184 - "@atcute/client": ["@atcute/client@4.0.5", "", { "dependencies": { "@atcute/identity": "^1.1.1", "@atcute/lexicons": "^1.2.2" } }, "sha512-R8Qen8goGmEkynYGg2m6XFlVmz0GTDvQ+9w+4QqOob+XMk8/WDpF4aImev7WKEde/rV2gjcqW7zM8E6W9NShDA=="], 212 + "@atcute/client": ["@atcute/client@4.1.0", "", { "dependencies": { "@atcute/identity": "^1.1.3", "@atcute/lexicons": "^1.2.5" } }, "sha512-AYhSu3RSDA2VDkVGOmad320NRbUUUf5pCFWJcOzlk25YC/4kyzmMFfpzhf1jjjEcY+anNBXGGhav/kKB1evggQ=="], 185 213 186 214 "@atcute/crypto": ["@atcute/crypto@2.2.6", "", { "dependencies": { "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "@noble/secp256k1": "^3.0.0" } }, "sha512-vkuexF+kmrKE1/Uqzub99Qi4QpnxA2jbu60E6PTgL4XypELQ6rb59MB/J1VbY2gs0kd3ET7+L3+NWpKD5nXyfA=="], 187 215 ··· 199 227 200 228 "@atcute/multibase": ["@atcute/multibase@1.1.6", "", { "dependencies": { "@atcute/uint8array": "^1.0.5" } }, "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg=="], 201 229 202 - "@atcute/oauth-browser-client": ["@atcute/oauth-browser-client@2.0.1", "", { "dependencies": { "@atcute/client": "^4.0.5", "@atcute/identity": "^1.1.1", "@atcute/identity-resolver": "^1.1.4", "@atcute/lexicons": "^1.2.2", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.5", "nanoid": "^5.1.5" } }, "sha512-lG021GkeORG06zfFf4bH85egObjBEKHNgAWHvbtY/E2dX4wxo88hf370pJDx8acdnuUJLJ2VKPikJtZwo4Heeg=="], 230 + "@atcute/oauth-browser-client": ["@atcute/oauth-browser-client@2.0.2", "", { "dependencies": { "@atcute/client": "^4.1.0", "@atcute/identity-resolver": "^1.2.0", "@atcute/lexicons": "^1.2.5", "@atcute/multibase": "^1.1.6", "@atcute/uint8array": "^1.0.6", "nanoid": "^5.1.6" } }, "sha512-F76NZwiRbqZl+5X3Uiw3VPSPvdvRugeW9BZppZWqKawkMTYZQB3iyQKBD6ZI0kOdfLNKBamrd3hmeJs+V1xpww=="], 203 231 204 - "@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 232 + "@atcute/uint8array": ["@atcute/uint8array@1.0.6", "", {}, "sha512-ucfRBQc7BFT8n9eCyGOzDHEMKF/nZwhS2pPao4Xtab1ML3HdFYcX2DM1tadCzas85QTGxHe5urnUAAcNKGRi9A=="], 205 233 206 234 "@atcute/util-fetch": ["@atcute/util-fetch@1.0.3", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-f8zzTb/xlKIwv2OQ31DhShPUNCmIIleX6p7qIXwWwEUjX6x8skUtpdISSjnImq01LXpltGV5y8yhV4/Mlb7CRQ=="], 207 235 ··· 225 253 226 254 "@atproto-labs/simple-store-memory": ["@atproto-labs/simple-store-memory@0.1.3", "", { "dependencies": { "@atproto-labs/simple-store": "0.2.0", "lru-cache": "^10.2.0" } }, "sha512-jkitT9+AtU+0b28DoN92iURLaCt/q/q4yX8q6V+9LSwYlUTqKoj/5NFKvF7x6EBuG+gpUdlcycbH7e60gjOhRQ=="], 227 255 228 - "@atproto/common": ["@atproto/common@0.4.12", "", { "dependencies": { "@atproto/common-web": "^0.4.3", "@ipld/dag-cbor": "^7.0.3", "cbor-x": "^1.5.1", "iso-datestring-validator": "^2.2.2", "multiformats": "^9.9.0", "pino": "^8.21.0" } }, "sha512-NC+TULLQiqs6MvNymhQS5WDms3SlbIKGLf4n33tpftRJcalh507rI+snbcUb7TLIkKw7VO17qMqxEXtIdd5auQ=="], 229 - 230 - "@atproto/common-web": ["@atproto/common-web@0.3.2", "", { "dependencies": { "graphemer": "^1.4.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "zod": "^3.23.8" } }, "sha512-Vx0JtL1/CssJbFAb0UOdvTrkbUautsDfHNOXNTcX2vyPIxH9xOameSqLLunM1hZnOQbJwyjmQCt6TV+bhnanDg=="], 256 + "@atproto/common-web": ["@atproto/common-web@0.4.3", "", { "dependencies": { "graphemer": "^1.4.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "zod": "^3.23.8" } }, "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg=="], 231 257 232 258 "@atproto/did": ["@atproto/did@0.1.5", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-8+1D08QdGE5TF0bB0vV8HLVrVZJeLNITpRTUVEoABNMRaUS7CoYSVb0+JNQDeJIVmqMjOL8dOjvCUDkp3gEaGQ=="], 233 259 ··· 236 262 "@atproto/jwk-jose": ["@atproto/jwk-jose@0.1.8", "", { "dependencies": { "@atproto/jwk": "0.3.0", "jose": "^5.2.0" } }, "sha512-aoU2Q0GpIl388KhCcv9YvAxNscALUv3xzLq5gjVPdJ+zmqw94nGZNcjiNvpnbfS+VQM9e2DrrTuwmDXnxfrrSA=="], 237 263 238 264 "@atproto/jwk-webcrypto": ["@atproto/jwk-webcrypto@0.1.8", "", { "dependencies": { "@atproto/jwk": "0.3.0", "@atproto/jwk-jose": "0.1.8", "zod": "^3.23.8" } }, "sha512-oOW/G40f6M0NbTOo8uZgiSsFtcvlfNFldyxm+V+fVo5yKe6cvgvPNqckpqMsoBe6JYfImdc/zdVak9fCSSh41A=="], 265 + 266 + "@atproto/lex-data": ["@atproto/lex-data@0.0.3", "", { "dependencies": { "@atproto/syntax": "0.4.2", "multiformats": "^9.9.0", "tslib": "^2.8.1", "uint8arrays": "3.0.0", "unicode-segmenter": "^0.14.0" } }, "sha512-ivo1IpY/EX+RIpxPgCf4cPhQo5bfu4nrpa1vJCt8hCm9SfoonJkDFGa0n4SMw4JnXZoUcGcrJ46L+D8bH6GI2g=="], 267 + 268 + "@atproto/lex-json": ["@atproto/lex-json@0.0.3", "", { "dependencies": { "@atproto/lex-data": "0.0.3", "tslib": "^2.8.1" } }, "sha512-ZVcY7XlRfdPYvQQ2WroKUepee0+NCovrSXgXURM3Xv+n5jflJCoczguROeRr8sN0xvT0ZbzMrDNHCUYKNnxcjw=="], 239 269 240 270 "@atproto/lexicon": ["@atproto/lexicon@0.4.14", "", { "dependencies": { "@atproto/common-web": "^0.4.2", "@atproto/syntax": "^0.4.0", "iso-datestring-validator": "^2.2.2", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-jiKpmH1QER3Gvc7JVY5brwrfo+etFoe57tKPQX/SmPwjvUsFnJAow5xLIryuBaJgFAhnTZViXKs41t//pahGHQ=="], 241 271 ··· 295 325 296 326 "@babel/plugin-transform-modules-commonjs": ["@babel/plugin-transform-modules-commonjs@7.27.1", "", { "dependencies": { "@babel/helper-module-transforms": "^7.27.1", "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw=="], 297 327 328 + "@babel/plugin-transform-react-jsx-self": ["@babel/plugin-transform-react-jsx-self@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw=="], 329 + 330 + "@babel/plugin-transform-react-jsx-source": ["@babel/plugin-transform-react-jsx-source@7.27.1", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw=="], 331 + 298 332 "@babel/plugin-transform-typescript": ["@babel/plugin-transform-typescript@7.28.5", "", { "dependencies": { "@babel/helper-annotate-as-pure": "^7.27.3", "@babel/helper-create-class-features-plugin": "^7.28.5", "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-x2Qa+v/CuEoX7Dr31iAfr0IhInrVOWZU/2vJMJ00FOR/2nM0BcBEclpaf9sWCDc+v5e9dMrhSH8/atq/kX7+bA=="], 299 333 300 334 "@babel/preset-typescript": ["@babel/preset-typescript@7.28.5", "", { "dependencies": { "@babel/helper-plugin-utils": "^7.27.1", "@babel/helper-validator-option": "^7.27.1", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-transform-modules-commonjs": "^7.27.1", "@babel/plugin-transform-typescript": "^7.28.5" }, "peerDependencies": { "@babel/core": "^7.0.0-0" } }, "sha512-+bQy5WOI2V6LJZpPVxY+yp66XdZ2yifu0Mc1aP5CQKgjn4QM5IN2i5fAZ4xKop47pr8rpVhiAeu+nDQa12C8+g=="], ··· 307 341 308 342 "@badrap/valita": ["@badrap/valita@0.4.6", "", {}, "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg=="], 309 343 310 - "@cbor-extract/cbor-extract-darwin-arm64": ["@cbor-extract/cbor-extract-darwin-arm64@2.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w=="], 311 - 312 - "@cbor-extract/cbor-extract-darwin-x64": ["@cbor-extract/cbor-extract-darwin-x64@2.2.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w=="], 313 - 314 - "@cbor-extract/cbor-extract-linux-arm": ["@cbor-extract/cbor-extract-linux-arm@2.2.0", "", { "os": "linux", "cpu": "arm" }, "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q=="], 315 - 316 - "@cbor-extract/cbor-extract-linux-arm64": ["@cbor-extract/cbor-extract-linux-arm64@2.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ=="], 317 - 318 - "@cbor-extract/cbor-extract-linux-x64": ["@cbor-extract/cbor-extract-linux-x64@2.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw=="], 319 - 320 - "@cbor-extract/cbor-extract-win32-x64": ["@cbor-extract/cbor-extract-win32-x64@2.2.0", "", { "os": "win32", "cpu": "x64" }, "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w=="], 321 - 322 344 "@cookware/api": ["@cookware/api@workspace:apps/api"], 323 345 324 346 "@cookware/database": ["@cookware/database@workspace:libs/database"], ··· 329 351 330 352 "@cookware/tsconfig": ["@cookware/tsconfig@workspace:libs/tsconfig"], 331 353 332 - "@cookware/web": ["@cookware/web@workspace:apps/web"], 354 + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], 333 355 334 - "@dnd-kit/accessibility": ["@dnd-kit/accessibility@3.1.1", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw=="], 356 + "@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="], 335 357 336 - "@dnd-kit/core": ["@dnd-kit/core@6.3.1", "", { "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0", "react-dom": ">=16.8.0" } }, "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ=="], 358 + "@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="], 337 359 338 - "@dnd-kit/modifiers": ["@dnd-kit/modifiers@9.0.0", "", { "dependencies": { "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@dnd-kit/core": "^6.3.0", "react": ">=16.8.0" } }, "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw=="], 339 - 340 - "@dnd-kit/sortable": ["@dnd-kit/sortable@10.0.0", "", { "dependencies": { "@dnd-kit/utilities": "^3.2.2", "tslib": "^2.0.0" }, "peerDependencies": { "@dnd-kit/core": "^6.3.0", "react": ">=16.8.0" } }, "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg=="], 341 - 342 - "@dnd-kit/utilities": ["@dnd-kit/utilities@3.2.2", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg=="], 343 - 344 - "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], 360 + "@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], 345 361 346 362 "@esbuild-kit/core-utils": ["@esbuild-kit/core-utils@3.3.2", "", { "dependencies": { "esbuild": "~0.18.20", "source-map-support": "^0.5.21" } }, "sha512-sPRAnw9CdSsRmEtnsl2WXWdyquogVpB3yZ3dgwJfe8zrOzTsV7cJvmwrKVa+0ma5BoiGJ+BoqkMvawbayKUsqQ=="], 347 363 ··· 381 397 382 398 "@esbuild/linux-x64": ["@esbuild/linux-x64@0.19.12", "", { "os": "linux", "cpu": "x64" }, "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg=="], 383 399 384 - "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg=="], 400 + "@esbuild/netbsd-arm64": ["@esbuild/netbsd-arm64@0.27.1", "", { "os": "none", "cpu": "arm64" }, "sha512-wzC24DxAvk8Em01YmVXyjl96Mr+ecTPyOuADAvjGg+fyBpGmxmcr2E5ttf7Im8D0sXZihpxzO1isus8MdjMCXQ=="], 385 401 386 402 "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.19.12", "", { "os": "none", "cpu": "x64" }, "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA=="], 387 403 388 - "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.25.12", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A=="], 404 + "@esbuild/openbsd-arm64": ["@esbuild/openbsd-arm64@0.27.1", "", { "os": "openbsd", "cpu": "arm64" }, "sha512-5Z+DzLCrq5wmU7RDaMDe2DVXMRm2tTDvX2KU14JJVBN2CT/qov7XVix85QoJqHltpvAOZUAc3ndU56HSMWrv8g=="], 389 405 390 406 "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.19.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw=="], 391 407 392 - "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.25.12", "", { "os": "none", "cpu": "arm64" }, "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg=="], 408 + "@esbuild/openharmony-arm64": ["@esbuild/openharmony-arm64@0.27.1", "", { "os": "none", "cpu": "arm64" }, "sha512-ajbHrGM/XiK+sXM0JzEbJAen+0E+JMQZ2l4RR4VFwvV9JEERx+oxtgkpoKv1SevhjavK2z2ReHk32pjzktWbGg=="], 393 409 394 410 "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.19.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA=="], 395 411 ··· 425 441 426 442 "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], 427 443 428 - "@hookform/resolvers": ["@hookform/resolvers@3.10.0", "", { "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag=="], 429 - 430 444 "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], 431 445 432 446 "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], ··· 435 449 436 450 "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], 437 451 452 + "@img/colour": ["@img/colour@1.0.0", "", {}, "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw=="], 453 + 454 + "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.2.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w=="], 455 + 456 + "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.2.4" }, "os": "darwin", "cpu": "x64" }, "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw=="], 457 + 458 + "@img/sharp-libvips-darwin-arm64": ["@img/sharp-libvips-darwin-arm64@1.2.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g=="], 459 + 460 + "@img/sharp-libvips-darwin-x64": ["@img/sharp-libvips-darwin-x64@1.2.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg=="], 461 + 462 + "@img/sharp-libvips-linux-arm": ["@img/sharp-libvips-linux-arm@1.2.4", "", { "os": "linux", "cpu": "arm" }, "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A=="], 463 + 464 + "@img/sharp-libvips-linux-arm64": ["@img/sharp-libvips-linux-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw=="], 465 + 466 + "@img/sharp-libvips-linux-ppc64": ["@img/sharp-libvips-linux-ppc64@1.2.4", "", { "os": "linux", "cpu": "ppc64" }, "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA=="], 467 + 468 + "@img/sharp-libvips-linux-riscv64": ["@img/sharp-libvips-linux-riscv64@1.2.4", "", { "os": "linux", "cpu": "none" }, "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA=="], 469 + 470 + "@img/sharp-libvips-linux-s390x": ["@img/sharp-libvips-linux-s390x@1.2.4", "", { "os": "linux", "cpu": "s390x" }, "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ=="], 471 + 472 + "@img/sharp-libvips-linux-x64": ["@img/sharp-libvips-linux-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw=="], 473 + 474 + "@img/sharp-libvips-linuxmusl-arm64": ["@img/sharp-libvips-linuxmusl-arm64@1.2.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw=="], 475 + 476 + "@img/sharp-libvips-linuxmusl-x64": ["@img/sharp-libvips-linuxmusl-x64@1.2.4", "", { "os": "linux", "cpu": "x64" }, "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg=="], 477 + 478 + "@img/sharp-linux-arm": ["@img/sharp-linux-arm@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm": "1.2.4" }, "os": "linux", "cpu": "arm" }, "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw=="], 479 + 480 + "@img/sharp-linux-arm64": ["@img/sharp-linux-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg=="], 481 + 482 + "@img/sharp-linux-ppc64": ["@img/sharp-linux-ppc64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-ppc64": "1.2.4" }, "os": "linux", "cpu": "ppc64" }, "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA=="], 483 + 484 + "@img/sharp-linux-riscv64": ["@img/sharp-linux-riscv64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-riscv64": "1.2.4" }, "os": "linux", "cpu": "none" }, "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw=="], 485 + 486 + "@img/sharp-linux-s390x": ["@img/sharp-linux-s390x@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-s390x": "1.2.4" }, "os": "linux", "cpu": "s390x" }, "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg=="], 487 + 488 + "@img/sharp-linux-x64": ["@img/sharp-linux-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linux-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ=="], 489 + 490 + "@img/sharp-linuxmusl-arm64": ["@img/sharp-linuxmusl-arm64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" }, "os": "linux", "cpu": "arm64" }, "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg=="], 491 + 492 + "@img/sharp-linuxmusl-x64": ["@img/sharp-linuxmusl-x64@0.34.5", "", { "optionalDependencies": { "@img/sharp-libvips-linuxmusl-x64": "1.2.4" }, "os": "linux", "cpu": "x64" }, "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q=="], 493 + 494 + "@img/sharp-wasm32": ["@img/sharp-wasm32@0.34.5", "", { "dependencies": { "@emnapi/runtime": "^1.7.0" }, "cpu": "none" }, "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw=="], 495 + 496 + "@img/sharp-win32-arm64": ["@img/sharp-win32-arm64@0.34.5", "", { "os": "win32", "cpu": "arm64" }, "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g=="], 497 + 498 + "@img/sharp-win32-ia32": ["@img/sharp-win32-ia32@0.34.5", "", { "os": "win32", "cpu": "ia32" }, "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg=="], 499 + 500 + "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], 501 + 438 502 "@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], 439 503 440 504 "@inquirer/checkbox": ["@inquirer/checkbox@4.3.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-VXukHf0RR1doGe6Sm4F0Em7SWYLTHSsbGfJdS9Ja2bX5/D5uwVOEjr07cncLROdBvmnvCATYEWlHqYmXv2IlQA=="], ··· 466 530 "@inquirer/select": ["@inquirer/select@4.4.2", "", { "dependencies": { "@inquirer/ansi": "^1.0.2", "@inquirer/core": "^10.3.2", "@inquirer/figures": "^1.0.15", "@inquirer/type": "^3.0.10", "yoctocolors-cjs": "^2.1.3" }, "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-l4xMuJo55MAe+N7Qr4rX90vypFwCajSakx59qe/tMaC1aEHWLyw68wF4o0A4SLAY4E0nd+Vt+EyskeDIqu1M6w=="], 467 531 468 532 "@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], 469 - 470 - "@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 471 533 472 534 "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], 473 535 ··· 516 578 "@mary-ext/event-iterator": ["@mary-ext/event-iterator@1.0.0", "", { "dependencies": { "yocto-queue": "^1.2.1" } }, "sha512-l6gCPsWJ8aRCe/s7/oCmero70kDHgIK5m4uJvYgwEYTqVxoBOIXbKr5tnkLqUHEg6mNduB4IWvms3h70Hp9ADQ=="], 517 579 518 580 "@mary-ext/simple-event-emitter": ["@mary-ext/simple-event-emitter@1.0.0", "", {}, "sha512-meA/zJZKIN1RVBNEYIbjufkUrW7/tRjHH60FjolpG1ixJKo76TB208qefQLNdOVDA7uIG0CGEDuhmMirtHKLAg=="], 581 + 582 + "@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.0", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" } }, "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA=="], 519 583 520 584 "@neon-rs/load": ["@neon-rs/load@0.0.4", "", {}, "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw=="], 521 585 586 + "@next/env": ["@next/env@16.0.7", "", {}, "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw=="], 587 + 588 + "@next/eslint-plugin-next": ["@next/eslint-plugin-next@16.0.7", "", { "dependencies": { "fast-glob": "3.3.1" } }, "sha512-hFrTNZcMEG+k7qxVxZJq3F32Kms130FAhG8lvw2zkKBgAcNOJIxlljNiCjGygvBshvaGBdf88q2CqWtnqezDHA=="], 589 + 590 + "@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.0.7", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg=="], 591 + 592 + "@next/swc-darwin-x64": ["@next/swc-darwin-x64@16.0.7", "", { "os": "darwin", "cpu": "x64" }, "sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA=="], 593 + 594 + "@next/swc-linux-arm64-gnu": ["@next/swc-linux-arm64-gnu@16.0.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww=="], 595 + 596 + "@next/swc-linux-arm64-musl": ["@next/swc-linux-arm64-musl@16.0.7", "", { "os": "linux", "cpu": "arm64" }, "sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g=="], 597 + 598 + "@next/swc-linux-x64-gnu": ["@next/swc-linux-x64-gnu@16.0.7", "", { "os": "linux", "cpu": "x64" }, "sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA=="], 599 + 600 + "@next/swc-linux-x64-musl": ["@next/swc-linux-x64-musl@16.0.7", "", { "os": "linux", "cpu": "x64" }, "sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w=="], 601 + 602 + "@next/swc-win32-arm64-msvc": ["@next/swc-win32-arm64-msvc@16.0.7", "", { "os": "win32", "cpu": "arm64" }, "sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q=="], 603 + 604 + "@next/swc-win32-x64-msvc": ["@next/swc-win32-x64-msvc@16.0.7", "", { "os": "win32", "cpu": "x64" }, "sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug=="], 605 + 522 606 "@noble/secp256k1": ["@noble/secp256k1@3.0.0", "", {}, "sha512-NJBaR352KyIvj3t6sgT/+7xrNyF9Xk9QlLSIqUGVUYlsnDTAUqY8LOmwpcgEx4AMJXRITQ5XEVHD+mMaPfr3mg=="], 523 607 524 608 "@nodelib/fs.scandir": ["@nodelib/fs.scandir@2.1.5", "", { "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" } }, "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g=="], ··· 527 611 528 612 "@nodelib/fs.walk": ["@nodelib/fs.walk@1.2.8", "", { "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" } }, "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg=="], 529 613 614 + "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="], 615 + 530 616 "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], 531 617 532 618 "@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.57.2", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-uIX52NnTM0iBh84MShlpouI7UKqkZ7MrUszTmaypHBu4r7NofznSnQRfJ+uUeDtQDj6w8eFGg5KBLDAwAPz1+A=="], ··· 599 685 600 686 "@optique/run": ["@optique/run@0.6.2", "", { "dependencies": { "@optique/core": "0.6.2" } }, "sha512-ERksB5bHozwEUVlTPToIc8UjZZBOgLeBhFZYh2lgldUbNDt7LItzgcErsPq5au5i5IBmmyCti4+2A3x+MRI4Xw=="], 601 687 688 + "@oxc-project/runtime": ["@oxc-project/runtime@0.97.0", "", {}, "sha512-yH0zw7z+jEws4dZ4IUKoix5Lh3yhqIJWF9Dc8PWvhpo7U7O+lJrv7ZZL4BeRO0la8LBQFwcCewtLBnVV7hPe/w=="], 689 + 690 + "@oxc-project/types": ["@oxc-project/types@0.97.0", "", {}, "sha512-lxmZK4xFrdvU0yZiDwgVQTCvh2gHWBJCBk5ALsrtsBWhs0uDIi+FTOnXRQeQfs304imdvTdaakT/lqwQ8hkOXQ=="], 691 + 602 692 "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], 603 693 604 694 "@prisma/instrumentation": ["@prisma/instrumentation@5.22.0", "", { "dependencies": { "@opentelemetry/api": "^1.8", "@opentelemetry/instrumentation": "^0.49 || ^0.50 || ^0.51 || ^0.52.0 || ^0.53.0", "@opentelemetry/sdk-trace-base": "^1.22" } }, "sha512-LxccF392NN37ISGxIurUljZSh1YWnphO34V5a0+T7FVQG2u9bhAXRTJpgmQ3483woVhkraQZFF7cbRrpbw/F4Q=="], ··· 608 698 "@radix-ui/react-arrow": ["@radix-ui/react-arrow@1.1.7", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w=="], 609 699 610 700 "@radix-ui/react-avatar": ["@radix-ui/react-avatar@1.1.11", "", { "dependencies": { "@radix-ui/react-context": "1.1.3", "@radix-ui/react-primitive": "2.1.4", "@radix-ui/react-use-callback-ref": "1.1.1", "@radix-ui/react-use-is-hydrated": "0.1.0", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-0Qk603AHGV28BOBO34p7IgD5m+V5Sg/YovfayABkoDDBM5d3NCx0Mp4gGrjzLGes1jV5eNOE1r3itqOR33VC6Q=="], 611 - 612 - "@radix-ui/react-collapsible": ["@radix-ui/react-collapsible@1.1.12", "", { "dependencies": { "@radix-ui/primitive": "1.1.3", "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-id": "1.1.1", "@radix-ui/react-presence": "1.1.5", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-controllable-state": "1.2.2", "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA=="], 613 701 614 702 "@radix-ui/react-collection": ["@radix-ui/react-collection@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-context": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw=="], 615 703 ··· 628 716 "@radix-ui/react-focus-guards": ["@radix-ui/react-focus-guards@1.1.3", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw=="], 629 717 630 718 "@radix-ui/react-focus-scope": ["@radix-ui/react-focus-scope@1.1.7", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2", "@radix-ui/react-primitive": "2.1.3", "@radix-ui/react-use-callback-ref": "1.1.1" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw=="], 631 - 632 - "@radix-ui/react-icons": ["@radix-ui/react-icons@1.3.2", "", { "peerDependencies": { "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" } }, "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g=="], 633 719 634 720 "@radix-ui/react-id": ["@radix-ui/react-id@1.1.1", "", { "dependencies": { "@radix-ui/react-use-layout-effect": "1.1.1" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg=="], 635 721 ··· 673 759 674 760 "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], 675 761 676 - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], 762 + "@rolldown/binding-android-arm64": ["@rolldown/binding-android-arm64@1.0.0-beta.50", "", { "os": "android", "cpu": "arm64" }, "sha512-XlEkrOIHLyGT3avOgzfTFSjG+f+dZMw+/qd+Y3HLN86wlndrB/gSimrJCk4gOhr1XtRtEKfszpadI3Md4Z4/Ag=="], 677 763 678 - "@rollup/rollup-android-arm-eabi": ["@rollup/rollup-android-arm-eabi@4.53.3", "", { "os": "android", "cpu": "arm" }, "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w=="], 764 + "@rolldown/binding-darwin-arm64": ["@rolldown/binding-darwin-arm64@1.0.0-beta.50", "", { "os": "darwin", "cpu": "arm64" }, "sha512-+JRqKJhoFlt5r9q+DecAGPLZ5PxeLva+wCMtAuoFMWPoZzgcYrr599KQ+Ix0jwll4B4HGP43avu9My8KtSOR+w=="], 679 765 680 - "@rollup/rollup-android-arm64": ["@rollup/rollup-android-arm64@4.53.3", "", { "os": "android", "cpu": "arm64" }, "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w=="], 766 + "@rolldown/binding-darwin-x64": ["@rolldown/binding-darwin-x64@1.0.0-beta.50", "", { "os": "darwin", "cpu": "x64" }, "sha512-fFXDjXnuX7/gQZQm/1FoivVtRcyAzdjSik7Eo+9iwPQ9EgtA5/nB2+jmbzaKtMGG3q+BnZbdKHCtOacmNrkIDA=="], 681 767 682 - "@rollup/rollup-darwin-arm64": ["@rollup/rollup-darwin-arm64@4.53.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA=="], 768 + "@rolldown/binding-freebsd-x64": ["@rolldown/binding-freebsd-x64@1.0.0-beta.50", "", { "os": "freebsd", "cpu": "x64" }, "sha512-F1b6vARy49tjmT/hbloplzgJS7GIvwWZqt+tAHEstCh0JIh9sa8FAMVqEmYxDviqKBaAI8iVvUREm/Kh/PD26Q=="], 683 769 684 - "@rollup/rollup-darwin-x64": ["@rollup/rollup-darwin-x64@4.53.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ=="], 770 + "@rolldown/binding-linux-arm-gnueabihf": ["@rolldown/binding-linux-arm-gnueabihf@1.0.0-beta.50", "", { "os": "linux", "cpu": "arm" }, "sha512-U6cR76N8T8M6lHj7EZrQ3xunLPxSvYYxA8vJsBKZiFZkT8YV4kjgCO3KwMJL0NOjQCPGKyiXO07U+KmJzdPGRw=="], 685 771 686 - "@rollup/rollup-freebsd-arm64": ["@rollup/rollup-freebsd-arm64@4.53.3", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w=="], 772 + "@rolldown/binding-linux-arm64-gnu": ["@rolldown/binding-linux-arm64-gnu@1.0.0-beta.50", "", { "os": "linux", "cpu": "arm64" }, "sha512-ONgyjofCrrE3bnh5GZb8EINSFyR/hmwTzZ7oVuyUB170lboza1VMCnb8jgE6MsyyRgHYmN8Lb59i3NKGrxrYjw=="], 687 773 688 - "@rollup/rollup-freebsd-x64": ["@rollup/rollup-freebsd-x64@4.53.3", "", { "os": "freebsd", "cpu": "x64" }, "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q=="], 774 + "@rolldown/binding-linux-arm64-musl": ["@rolldown/binding-linux-arm64-musl@1.0.0-beta.50", "", { "os": "linux", "cpu": "arm64" }, "sha512-L0zRdH2oDPkmB+wvuTl+dJbXCsx62SkqcEqdM+79LOcB+PxbAxxjzHU14BuZIQdXcAVDzfpMfaHWzZuwhhBTcw=="], 689 775 690 - "@rollup/rollup-linux-arm-gnueabihf": ["@rollup/rollup-linux-arm-gnueabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw=="], 776 + "@rolldown/binding-linux-x64-gnu": ["@rolldown/binding-linux-x64-gnu@1.0.0-beta.50", "", { "os": "linux", "cpu": "x64" }, "sha512-gyoI8o/TGpQd3OzkJnh1M2kxy1Bisg8qJ5Gci0sXm9yLFzEXIFdtc4EAzepxGvrT2ri99ar5rdsmNG0zP0SbIg=="], 691 777 692 - "@rollup/rollup-linux-arm-musleabihf": ["@rollup/rollup-linux-arm-musleabihf@4.53.3", "", { "os": "linux", "cpu": "arm" }, "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg=="], 778 + "@rolldown/binding-linux-x64-musl": ["@rolldown/binding-linux-x64-musl@1.0.0-beta.50", "", { "os": "linux", "cpu": "x64" }, "sha512-zti8A7M+xFDpKlghpcCAzyOi+e5nfUl3QhU023ce5NCgUxRG5zGP2GR9LTydQ1rnIPwZUVBWd4o7NjZDaQxaXA=="], 693 779 694 - "@rollup/rollup-linux-arm64-gnu": ["@rollup/rollup-linux-arm64-gnu@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w=="], 780 + "@rolldown/binding-openharmony-arm64": ["@rolldown/binding-openharmony-arm64@1.0.0-beta.50", "", { "os": "none", "cpu": "arm64" }, "sha512-eZUssog7qljrrRU9Mi0eqYEPm3Ch0UwB+qlWPMKSUXHNqhm3TvDZarJQdTevGEfu3EHAXJvBIe0YFYr0TPVaMA=="], 695 781 696 - "@rollup/rollup-linux-arm64-musl": ["@rollup/rollup-linux-arm64-musl@4.53.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A=="], 782 + "@rolldown/binding-wasm32-wasi": ["@rolldown/binding-wasm32-wasi@1.0.0-beta.50", "", { "dependencies": { "@napi-rs/wasm-runtime": "^1.0.7" }, "cpu": "none" }, "sha512-nmCN0nIdeUnmgeDXiQ+2HU6FT162o+rxnF7WMkBm4M5Ds8qTU7Dzv2Wrf22bo4ftnlrb2hKK6FSwAJSAe2FWLg=="], 697 783 698 - "@rollup/rollup-linux-loong64-gnu": ["@rollup/rollup-linux-loong64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g=="], 784 + "@rolldown/binding-win32-arm64-msvc": ["@rolldown/binding-win32-arm64-msvc@1.0.0-beta.50", "", { "os": "win32", "cpu": "arm64" }, "sha512-7kcNLi7Ua59JTTLvbe1dYb028QEPaJPJQHqkmSZ5q3tJueUeb6yjRtx8mw4uIqgWZcnQHAR3PrLN4XRJxvgIkA=="], 699 785 700 - "@rollup/rollup-linux-ppc64-gnu": ["@rollup/rollup-linux-ppc64-gnu@4.53.3", "", { "os": "linux", "cpu": "ppc64" }, "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw=="], 786 + "@rolldown/binding-win32-ia32-msvc": ["@rolldown/binding-win32-ia32-msvc@1.0.0-beta.50", "", { "os": "win32", "cpu": "ia32" }, "sha512-lL70VTNvSCdSZkDPPVMwWn/M2yQiYvSoXw9hTLgdIWdUfC3g72UaruezusR6ceRuwHCY1Ayu2LtKqXkBO5LIwg=="], 701 787 702 - "@rollup/rollup-linux-riscv64-gnu": ["@rollup/rollup-linux-riscv64-gnu@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g=="], 788 + "@rolldown/binding-win32-x64-msvc": ["@rolldown/binding-win32-x64-msvc@1.0.0-beta.50", "", { "os": "win32", "cpu": "x64" }, "sha512-4qU4x5DXWB4JPjyTne/wBNPqkbQU8J45bl21geERBKtEittleonioACBL1R0PsBu0Aq21SwMK5a9zdBkWSlQtQ=="], 703 789 704 - "@rollup/rollup-linux-riscv64-musl": ["@rollup/rollup-linux-riscv64-musl@4.53.3", "", { "os": "linux", "cpu": "none" }, "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A=="], 790 + "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.47", "", {}, "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw=="], 705 791 706 - "@rollup/rollup-linux-s390x-gnu": ["@rollup/rollup-linux-s390x-gnu@4.53.3", "", { "os": "linux", "cpu": "s390x" }, "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg=="], 792 + "@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="], 707 793 708 - "@rollup/rollup-linux-x64-gnu": ["@rollup/rollup-linux-x64-gnu@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w=="], 794 + "@sentry/core": ["@sentry/core@8.55.0", "", {}, "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA=="], 709 795 710 - "@rollup/rollup-linux-x64-musl": ["@rollup/rollup-linux-x64-musl@4.53.3", "", { "os": "linux", "cpu": "x64" }, "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q=="], 796 + "@sentry/node": ["@sentry/node@8.55.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.1", "@opentelemetry/instrumentation-amqplib": "^0.46.0", "@opentelemetry/instrumentation-connect": "0.43.0", "@opentelemetry/instrumentation-dataloader": "0.16.0", "@opentelemetry/instrumentation-express": "0.47.0", "@opentelemetry/instrumentation-fastify": "0.44.1", "@opentelemetry/instrumentation-fs": "0.19.0", "@opentelemetry/instrumentation-generic-pool": "0.43.0", "@opentelemetry/instrumentation-graphql": "0.47.0", "@opentelemetry/instrumentation-hapi": "0.45.1", "@opentelemetry/instrumentation-http": "0.57.1", "@opentelemetry/instrumentation-ioredis": "0.47.0", "@opentelemetry/instrumentation-kafkajs": "0.7.0", "@opentelemetry/instrumentation-knex": "0.44.0", "@opentelemetry/instrumentation-koa": "0.47.0", "@opentelemetry/instrumentation-lru-memoizer": "0.44.0", "@opentelemetry/instrumentation-mongodb": "0.51.0", "@opentelemetry/instrumentation-mongoose": "0.46.0", "@opentelemetry/instrumentation-mysql": "0.45.0", "@opentelemetry/instrumentation-mysql2": "0.45.0", "@opentelemetry/instrumentation-nestjs-core": "0.44.0", "@opentelemetry/instrumentation-pg": "0.50.0", "@opentelemetry/instrumentation-redis-4": "0.46.0", "@opentelemetry/instrumentation-tedious": "0.18.0", "@opentelemetry/instrumentation-undici": "0.10.0", "@opentelemetry/resources": "^1.30.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.28.0", "@prisma/instrumentation": "5.22.0", "@sentry/core": "8.55.0", "@sentry/opentelemetry": "8.55.0", "import-in-the-middle": "^1.11.2" } }, "sha512-h10LJLDTRAzYgay60Oy7moMookqqSZSviCWkkmHZyaDn+4WURnPp5SKhhfrzPRQcXKrweiOwDSHBgn1tweDssg=="], 711 797 712 - "@rollup/rollup-openharmony-arm64": ["@rollup/rollup-openharmony-arm64@4.53.3", "", { "os": "none", "cpu": "arm64" }, "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw=="], 798 + "@sentry/opentelemetry": ["@sentry/opentelemetry@8.55.0", "", { "dependencies": { "@sentry/core": "8.55.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.28.0" } }, "sha512-UvatdmSr3Xf+4PLBzJNLZ2JjG1yAPWGe/VrJlJAqyTJ2gKeTzgXJJw8rp4pbvNZO8NaTGEYhhO+scLUj0UtLAQ=="], 713 799 714 - "@rollup/rollup-win32-arm64-msvc": ["@rollup/rollup-win32-arm64-msvc@4.53.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw=="], 800 + "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], 715 801 716 - "@rollup/rollup-win32-ia32-msvc": ["@rollup/rollup-win32-ia32-msvc@4.53.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA=="], 802 + "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], 717 803 718 - "@rollup/rollup-win32-x64-gnu": ["@rollup/rollup-win32-x64-gnu@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg=="], 804 + "@swc/helpers": ["@swc/helpers@0.5.15", "", { "dependencies": { "tslib": "^2.8.0" } }, "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g=="], 719 805 720 - "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.53.3", "", { "os": "win32", "cpu": "x64" }, "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ=="], 806 + "@tabler/icons": ["@tabler/icons@3.35.0", "", {}, "sha512-yYXe+gJ56xlZFiXwV9zVoe3FWCGuZ/D7/G4ZIlDtGxSx5CGQK110wrnT29gUj52kEZoxqF7oURTk97GQxELOFQ=="], 807 + 808 + "@tabler/icons-react": ["@tabler/icons-react@3.35.0", "", { "dependencies": { "@tabler/icons": "3.35.0" }, "peerDependencies": { "react": ">= 16" } }, "sha512-XG7t2DYf3DyHT5jxFNp5xyLVbL4hMJYJhiSdHADzAjLRYfL7AnjlRfiHDHeXxkb2N103rEIvTsBRazxXtAUz2g=="], 809 + 810 + "@tailwindcss/node": ["@tailwindcss/node@4.1.17", "", { "dependencies": { "@jridgewell/remapping": "^2.3.4", "enhanced-resolve": "^5.18.3", "jiti": "^2.6.1", "lightningcss": "1.30.2", "magic-string": "^0.30.21", "source-map-js": "^1.2.1", "tailwindcss": "4.1.17" } }, "sha512-csIkHIgLb3JisEFQ0vxr2Y57GUNYh447C8xzwj89U/8fdW8LhProdxvnVH6U8M2Y73QKiTIH+LWbK3V2BBZsAg=="], 721 811 722 - "@sentry/core": ["@sentry/core@8.55.0", "", {}, "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA=="], 812 + "@tailwindcss/oxide": ["@tailwindcss/oxide@4.1.17", "", { "optionalDependencies": { "@tailwindcss/oxide-android-arm64": "4.1.17", "@tailwindcss/oxide-darwin-arm64": "4.1.17", "@tailwindcss/oxide-darwin-x64": "4.1.17", "@tailwindcss/oxide-freebsd-x64": "4.1.17", "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.17", "@tailwindcss/oxide-linux-arm64-gnu": "4.1.17", "@tailwindcss/oxide-linux-arm64-musl": "4.1.17", "@tailwindcss/oxide-linux-x64-gnu": "4.1.17", "@tailwindcss/oxide-linux-x64-musl": "4.1.17", "@tailwindcss/oxide-wasm32-wasi": "4.1.17", "@tailwindcss/oxide-win32-arm64-msvc": "4.1.17", "@tailwindcss/oxide-win32-x64-msvc": "4.1.17" } }, "sha512-F0F7d01fmkQhsTjXezGBLdrl1KresJTcI3DB8EkScCldyKp3Msz4hub4uyYaVnk88BAS1g5DQjjF6F5qczheLA=="], 723 813 724 - "@sentry/node": ["@sentry/node@8.55.0", "", { "dependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.1", "@opentelemetry/instrumentation-amqplib": "^0.46.0", "@opentelemetry/instrumentation-connect": "0.43.0", "@opentelemetry/instrumentation-dataloader": "0.16.0", "@opentelemetry/instrumentation-express": "0.47.0", "@opentelemetry/instrumentation-fastify": "0.44.1", "@opentelemetry/instrumentation-fs": "0.19.0", "@opentelemetry/instrumentation-generic-pool": "0.43.0", "@opentelemetry/instrumentation-graphql": "0.47.0", "@opentelemetry/instrumentation-hapi": "0.45.1", "@opentelemetry/instrumentation-http": "0.57.1", "@opentelemetry/instrumentation-ioredis": "0.47.0", "@opentelemetry/instrumentation-kafkajs": "0.7.0", "@opentelemetry/instrumentation-knex": "0.44.0", "@opentelemetry/instrumentation-koa": "0.47.0", "@opentelemetry/instrumentation-lru-memoizer": "0.44.0", "@opentelemetry/instrumentation-mongodb": "0.51.0", "@opentelemetry/instrumentation-mongoose": "0.46.0", "@opentelemetry/instrumentation-mysql": "0.45.0", "@opentelemetry/instrumentation-mysql2": "0.45.0", "@opentelemetry/instrumentation-nestjs-core": "0.44.0", "@opentelemetry/instrumentation-pg": "0.50.0", "@opentelemetry/instrumentation-redis-4": "0.46.0", "@opentelemetry/instrumentation-tedious": "0.18.0", "@opentelemetry/instrumentation-undici": "0.10.0", "@opentelemetry/resources": "^1.30.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.28.0", "@prisma/instrumentation": "5.22.0", "@sentry/core": "8.55.0", "@sentry/opentelemetry": "8.55.0", "import-in-the-middle": "^1.11.2" } }, "sha512-h10LJLDTRAzYgay60Oy7moMookqqSZSviCWkkmHZyaDn+4WURnPp5SKhhfrzPRQcXKrweiOwDSHBgn1tweDssg=="], 814 + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.17", "", { "os": "android", "cpu": "arm64" }, "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ=="], 725 815 726 - "@sentry/opentelemetry": ["@sentry/opentelemetry@8.55.0", "", { "dependencies": { "@sentry/core": "8.55.0" }, "peerDependencies": { "@opentelemetry/api": "^1.9.0", "@opentelemetry/context-async-hooks": "^1.30.1", "@opentelemetry/core": "^1.30.1", "@opentelemetry/instrumentation": "^0.57.1", "@opentelemetry/sdk-trace-base": "^1.30.1", "@opentelemetry/semantic-conventions": "^1.28.0" } }, "sha512-UvatdmSr3Xf+4PLBzJNLZ2JjG1yAPWGe/VrJlJAqyTJ2gKeTzgXJJw8rp4pbvNZO8NaTGEYhhO+scLUj0UtLAQ=="], 816 + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg=="], 727 817 728 - "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], 818 + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog=="], 729 819 730 - "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], 820 + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g=="], 731 821 732 - "@swc/core": ["@swc/core@1.15.3", "", { "dependencies": { "@swc/counter": "^0.1.3", "@swc/types": "^0.1.25" }, "optionalDependencies": { "@swc/core-darwin-arm64": "1.15.3", "@swc/core-darwin-x64": "1.15.3", "@swc/core-linux-arm-gnueabihf": "1.15.3", "@swc/core-linux-arm64-gnu": "1.15.3", "@swc/core-linux-arm64-musl": "1.15.3", "@swc/core-linux-x64-gnu": "1.15.3", "@swc/core-linux-x64-musl": "1.15.3", "@swc/core-win32-arm64-msvc": "1.15.3", "@swc/core-win32-ia32-msvc": "1.15.3", "@swc/core-win32-x64-msvc": "1.15.3" }, "peerDependencies": { "@swc/helpers": ">=0.5.17" }, "optionalPeers": ["@swc/helpers"] }, "sha512-Qd8eBPkUFL4eAONgGjycZXj1jFCBW8Fd+xF0PzdTlBCWQIV1xnUT7B93wUANtW3KGjl3TRcOyxwSx/u/jyKw/Q=="], 822 + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17", "", { "os": "linux", "cpu": "arm" }, "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ=="], 733 823 734 - "@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.15.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-AXfeQn0CvcQ4cndlIshETx6jrAM45oeUrK8YeEY6oUZU/qzz0Id0CyvlEywxkWVC81Ajpd8TQQ1fW5yx6zQWkQ=="], 824 + "@tailwindcss/oxide-linux-arm64-gnu": ["@tailwindcss/oxide-linux-arm64-gnu@4.1.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-HVDOm/mxK6+TbARwdW17WrgDYEGzmoYayrCgmLEw7FxTPLcp/glBisuyWkFz/jb7ZfiAXAXUACfyItn+nTgsdQ=="], 735 825 736 - "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.15.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-p68OeCz1ui+MZYG4wmfJGvcsAcFYb6Sl25H9TxWl+GkBgmNimIiRdnypK9nBGlqMZAcxngNPtnG3kEMNnvoJ2A=="], 826 + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg=="], 737 827 738 - "@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.15.3", "", { "os": "linux", "cpu": "arm" }, "sha512-Nuj5iF4JteFgwrai97mUX+xUOl+rQRHqTvnvHMATL/l9xE6/TJfPBpd3hk/PVpClMXG3Uvk1MxUFOEzM1JrMYg=="], 828 + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ=="], 739 829 740 - "@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.15.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-2Nc/s8jE6mW2EjXWxO/lyQuLKShcmTrym2LRf5Ayp3ICEMX6HwFqB1EzDhwoMa2DcUgmnZIalesq2lG3krrUNw=="], 830 + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ=="], 741 831 742 - "@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.15.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-j4SJniZ/qaZ5g8op+p1G9K1z22s/EYGg1UXIb3+Cg4nsxEpF5uSIGEE4mHUfA70L0BR9wKT2QF/zv3vkhfpX4g=="], 832 + "@tailwindcss/oxide-wasm32-wasi": ["@tailwindcss/oxide-wasm32-wasi@4.1.17", "", { "dependencies": { "@emnapi/core": "^1.6.0", "@emnapi/runtime": "^1.6.0", "@emnapi/wasi-threads": "^1.1.0", "@napi-rs/wasm-runtime": "^1.0.7", "@tybys/wasm-util": "^0.10.1", "tslib": "^2.4.0" }, "cpu": "none" }, "sha512-cEytGqSSoy7zK4JRWiTCx43FsKP/zGr0CsuMawhH67ONlH+T79VteQeJQRO/X7L0juEUA8ZyuYikcRBf0vsxhg=="], 743 833 744 - "@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.15.3", "", { "os": "linux", "cpu": "x64" }, "sha512-aKttAZnz8YB1VJwPQZtyU8Uk0BfMP63iDMkvjhJzRZVgySmqt/apWSdnoIcZlUoGheBrcqbMC17GGUmur7OT5A=="], 834 + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A=="], 745 835 746 - "@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.15.3", "", { "os": "linux", "cpu": "x64" }, "sha512-oe8FctPu1gnUsdtGJRO2rvOUIkkIIaHqsO9xxN0bTR7dFTlPTGi2Fhk1tnvXeyAvCPxLIcwD8phzKg6wLv9yug=="], 836 + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.17", "", { "os": "win32", "cpu": "x64" }, "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw=="], 747 837 748 - "@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.15.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-L9AjzP2ZQ/Xh58e0lTRMLvEDrcJpR7GwZqAtIeNLcTK7JVE+QineSyHp0kLkO1rttCHyCy0U74kDTj0dRz6raA=="], 838 + "@tailwindcss/postcss": ["@tailwindcss/postcss@4.1.17", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "@tailwindcss/node": "4.1.17", "@tailwindcss/oxide": "4.1.17", "postcss": "^8.4.41", "tailwindcss": "4.1.17" } }, "sha512-+nKl9N9mN5uJ+M7dBOOCzINw94MPstNR/GtIhz1fpZysxL/4a+No64jCBD6CPN+bIHWFx3KWuu8XJRrj/572Dw=="], 749 839 750 - "@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.15.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-B8UtogMzErUPDWUoKONSVBdsgKYd58rRyv2sHJWKOIMCHfZ22FVXICR4O/VwIYtlnZ7ahERcjayBHDlBZpR0aw=="], 840 + "@tailwindcss/vite": ["@tailwindcss/vite@4.1.17", "", { "dependencies": { "@tailwindcss/node": "4.1.17", "@tailwindcss/oxide": "4.1.17", "tailwindcss": "4.1.17" }, "peerDependencies": { "vite": "^5.2.0 || ^6 || ^7" } }, "sha512-4+9w8ZHOiGnpcGI6z1TVVfWaX/koK7fKeSYF3qlYg2xpBtbteP2ddBxiarL+HVgfSJGeK5RIxRQmKm4rTJJAwA=="], 751 841 752 - "@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.15.3", "", { "os": "win32", "cpu": "x64" }, "sha512-SpZKMR9QBTecHeqpzJdYEfgw30Oo8b/Xl6rjSzBt1g0ZsXyy60KLXrp6IagQyfTYqNYE/caDvwtF2FPn7pomog=="], 842 + "@tanstack/history": ["@tanstack/history@1.140.0", "", {}, "sha512-u+/dChlWlT3kYa/RmFP+E7xY5EnzvKEKcvKk+XrgWMpBWExQIh3RQX/eUqhqwCXJPNc4jfm1Coj8umnm/hDgyA=="], 753 843 754 - "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="], 844 + "@tanstack/query-core": ["@tanstack/query-core@5.90.12", "", {}, "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg=="], 755 845 756 - "@swc/types": ["@swc/types@0.1.25", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g=="], 846 + "@tanstack/query-devtools": ["@tanstack/query-devtools@5.91.1", "", {}, "sha512-l8bxjk6BMsCaVQH6NzQEE/bEgFy1hAs5qbgXl0xhzezlaQbPk6Mgz9BqEg2vTLPOHD8N4k+w/gdgCbEzecGyNg=="], 757 847 758 - "@tanstack/eslint-plugin-query": ["@tanstack/eslint-plugin-query@5.91.2", "", { "dependencies": { "@typescript-eslint/utils": "^8.44.1" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0" } }, "sha512-UPeWKl/Acu1IuuHJlsN+eITUHqAaa9/04geHHPedY8siVarSaWprY0SVMKrkpKfk5ehRT7+/MZ5QwWuEtkWrFw=="], 848 + "@tanstack/react-query": ["@tanstack/react-query@5.90.12", "", { "dependencies": { "@tanstack/query-core": "5.90.12" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-graRZspg7EoEaw0a8faiUASCyJrqjKPdqJ9EwuDRUF9mEYJ1YPczI9H+/agJ0mOJkPCJDk0lsz5QTrLZ/jQ2rg=="], 759 849 760 - "@tanstack/history": ["@tanstack/history@1.139.0", "", {}, "sha512-l6wcxwDBeh/7Dhles23U1O8lp9kNJmAb2yNjekR6olZwCRNAVA8TCXlVCrueELyFlYZqvQkh0ofxnzG62A1Kkg=="], 850 + "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.91.1", "", { "dependencies": { "@tanstack/query-devtools": "5.91.1" }, "peerDependencies": { "@tanstack/react-query": "^5.90.10", "react": "^18 || ^19" } }, "sha512-tRnJYwEbH0kAOuToy8Ew7bJw1lX3AjkkgSlf/vzb+NpnqmHPdWM+lA2DSdGQSLi1SU0PDRrrCI1vnZnci96CsQ=="], 761 851 762 - "@tanstack/query-core": ["@tanstack/query-core@5.90.10", "", {}, "sha512-EhZVFu9rl7GfRNuJLJ3Y7wtbTnENsvzp+YpcAV7kCYiXni1v8qZh++lpw4ch4rrwC0u/EZRnBHIehzCGzwXDSQ=="], 852 + "@tanstack/react-router": ["@tanstack/react-router@1.140.0", "", { "dependencies": { "@tanstack/history": "1.140.0", "@tanstack/react-store": "^0.8.0", "@tanstack/router-core": "1.140.0", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-Xe4K1bEtU5h0cAhaKYXDQA2cuITgEs1x6tOognJbcxamlAdzDAkhYBhRg8dKSVAyfGejAUNlUi4utnN0s6R+Yw=="], 763 853 764 - "@tanstack/query-devtools": ["@tanstack/query-devtools@5.91.0", "", {}, "sha512-uNWkqWTiIKCv8Iaahb7bftmDaZVkBetB+l+OQhQeCEZAedyqxw2eyaRUc8sAQ2LzD843tVdYL6bzOtRWJHJSbQ=="], 854 + "@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.140.0", "", { "dependencies": { "@tanstack/router-devtools-core": "1.140.0" }, "peerDependencies": { "@tanstack/react-router": "^1.140.0", "@tanstack/router-core": "^1.140.0", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-11NFwHCG8KphG7Bif570qOxBVwNBTkIOExsf42WNv7cgRhwD6cHjUvfx20/WzkAlvFbEGlV+pp7wiJm3HR56bQ=="], 765 855 766 - "@tanstack/react-query": ["@tanstack/react-query@5.90.10", "", { "dependencies": { "@tanstack/query-core": "5.90.10" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-BKLss9Y8PQ9IUjPYQiv3/Zmlx92uxffUOX8ZZNoQlCIZBJPT5M+GOMQj7xislvVQ6l1BstBjcX0XB/aHfFYVNw=="], 856 + "@tanstack/react-store": ["@tanstack/react-store@0.8.0", "", { "dependencies": { "@tanstack/store": "0.8.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-1vG9beLIuB7q69skxK9r5xiLN3ztzIPfSQSs0GfeqWGO2tGIyInZx0x1COhpx97RKaONSoAb8C3dxacWksm1ow=="], 767 857 768 - "@tanstack/react-query-devtools": ["@tanstack/react-query-devtools@5.91.0", "", { "dependencies": { "@tanstack/query-devtools": "5.91.0" }, "peerDependencies": { "@tanstack/react-query": "^5.90.10", "react": "^18 || ^19" } }, "sha512-s7g8Zn8HN05HNe22n/KdNm8wXaRbkcsVkqpkdYIQuCfjVmEUoTQqtJsN2iZtgd9CU36xNS38trWIofxzyW5vbQ=="], 858 + "@tanstack/router-core": ["@tanstack/router-core@1.140.0", "", { "dependencies": { "@tanstack/history": "1.140.0", "@tanstack/store": "^0.8.0", "cookie-es": "^2.0.0", "seroval": "^1.4.0", "seroval-plugins": "^1.4.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-/Te/mlAzi5FEpZ9NF9RhVw/n+cWYLiCHpvevNKo7JPA8ZYWF58wkalPtNWSocftX4P+OIBNerFAW9UbLgSbvSw=="], 769 859 770 - "@tanstack/react-router": ["@tanstack/react-router@1.139.3", "", { "dependencies": { "@tanstack/history": "1.139.0", "@tanstack/react-store": "^0.8.0", "@tanstack/router-core": "1.139.3", "isbot": "^5.1.22", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" } }, "sha512-lhqK0DnbA7PgHOnmhzOoWVzx8qd8oEpR4cOUbxAjwb3+ExFQWrEvRf9+ZdSxs49ZrtZL2S2UltxBv3vBV4Si5g=="], 860 + "@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.140.0", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "tiny-invariant": "^1.3.3" }, "peerDependencies": { "@tanstack/router-core": "^1.140.0", "csstype": "^3.0.10", "solid-js": ">=1.9.5" }, "optionalPeers": ["csstype"] }, "sha512-jrfJZabe2ndKgoQWd7xLdfLFG/ew6hfPMjCmx2Ep+KBkSqfR19Pww8UtJ8Y0KcfTEFKL3YzVEsRS4EZDX3A1Qw=="], 771 861 772 - "@tanstack/react-router-devtools": ["@tanstack/react-router-devtools@1.139.3", "", { "dependencies": { "@tanstack/router-devtools-core": "1.139.3", "vite": "^7.1.7" }, "peerDependencies": { "@tanstack/react-router": "^1.139.3", "@tanstack/router-core": "^1.139.3", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["@tanstack/router-core"] }, "sha512-taH/Zklh3TOEaGXo3Nmck67J6Cgj7LDY9E7pIwncocWXt/6s91kYKHsiSkCWfAbZ/bLIrj4YWu21ObnvU0PlHw=="], 862 + "@tanstack/router-generator": ["@tanstack/router-generator@1.140.0", "", { "dependencies": { "@tanstack/router-core": "1.140.0", "@tanstack/router-utils": "1.140.0", "@tanstack/virtual-file-routes": "1.140.0", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-YYq/DSn7EkBboCySf87RDH3mNq3AfN18v4qHmre73KOdxUJchTZ4LC1+8vbO/1K/Uus2ZFXUDy7QX5KziNx08g=="], 773 863 774 - "@tanstack/react-store": ["@tanstack/react-store@0.8.0", "", { "dependencies": { "@tanstack/store": "0.8.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-1vG9beLIuB7q69skxK9r5xiLN3ztzIPfSQSs0GfeqWGO2tGIyInZx0x1COhpx97RKaONSoAb8C3dxacWksm1ow=="], 864 + "@tanstack/router-plugin": ["@tanstack/router-plugin@1.140.0", "", { "dependencies": { "@babel/core": "^7.27.7", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.7", "@babel/types": "^7.27.7", "@tanstack/router-core": "1.140.0", "@tanstack/router-generator": "1.140.0", "@tanstack/router-utils": "1.140.0", "@tanstack/virtual-file-routes": "1.140.0", "babel-dead-code-elimination": "^1.0.10", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.140.0", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-hUOOYTPLFS3LvGoPoQNk3BY3ZvPlVIgxnJT3JMJMdstLMT2RUYha3ddsaamZd4ONUSWmt+7N5OXmiG0v4XmzMw=="], 775 865 776 - "@tanstack/router-core": ["@tanstack/router-core@1.139.3", "", { "dependencies": { "@tanstack/history": "1.139.0", "@tanstack/store": "^0.8.0", "cookie-es": "^2.0.0", "seroval": "^1.4.0", "seroval-plugins": "^1.4.0", "tiny-invariant": "^1.3.3", "tiny-warning": "^1.0.3" } }, "sha512-j3v1e739jmozBdtnmA45xHQHjCC2aKqBtfkMT3t2ZPijVrueaVP6qNRIAWmDK4ZSqd67TF5wP8vyqeTShJsEQQ=="], 866 + "@tanstack/router-utils": ["@tanstack/router-utils@1.140.0", "", { "dependencies": { "@babel/core": "^7.27.4", "@babel/generator": "^7.27.5", "@babel/parser": "^7.27.5", "@babel/preset-typescript": "^7.27.1", "ansis": "^4.1.0", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-gobraqMjkR5OO4nNbnwursGo08Idla6Yu30RspIA9IR1hv4WPJlxIyRWJcKjiQeXGyu5TuekLPUOHM46oood7w=="], 777 867 778 - "@tanstack/router-devtools": ["@tanstack/router-devtools@1.139.3", "", { "dependencies": { "@tanstack/react-router-devtools": "1.139.3", "clsx": "^2.1.1", "goober": "^2.1.16", "vite": "^7.1.7" }, "peerDependencies": { "@tanstack/react-router": "^1.139.3", "csstype": "^3.0.10", "react": ">=18.0.0 || >=19.0.0", "react-dom": ">=18.0.0 || >=19.0.0" }, "optionalPeers": ["csstype"] }, "sha512-cJ8mQNMm/4nMFDwQxSMLWP4pk9kAXLl/SkRQqOwEbhzO35enSo7r2UdcM0uTwNEEKGjdjmNrNanFzDIZJnFHCg=="], 868 + "@tanstack/store": ["@tanstack/store@0.8.0", "", {}, "sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ=="], 779 869 780 - "@tanstack/router-devtools-core": ["@tanstack/router-devtools-core@1.139.3", "", { "dependencies": { "clsx": "^2.1.1", "goober": "^2.1.16", "tiny-invariant": "^1.3.3", "vite": "^7.1.7" }, "peerDependencies": { "@tanstack/router-core": "^1.139.3", "csstype": "^3.0.10", "solid-js": ">=1.9.5" }, "optionalPeers": ["csstype"] }, "sha512-dqjL9QroVORlLC283uwwMB7CLMWAfn9rgKwwcXdaSQlPcuSVScFzyFI4Iz7l6A4jGC0ALtNPQoHJ52+mvTzY5Q=="], 870 + "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.140.0", "", {}, "sha512-LVmd19QkxV3x40oHkuTii9ey3l5XDV+X8locO2p5zfVDUC+N58H2gA7cDUtVc9qtImncnz3WxQkO/6kM3PMx2w=="], 781 871 782 - "@tanstack/router-generator": ["@tanstack/router-generator@1.139.3", "", { "dependencies": { "@tanstack/router-core": "1.139.3", "@tanstack/router-utils": "1.139.0", "@tanstack/virtual-file-routes": "1.139.0", "prettier": "^3.5.0", "recast": "^0.23.11", "source-map": "^0.7.4", "tsx": "^4.19.2", "zod": "^3.24.2" } }, "sha512-zq/ZC+1rx7pGNqYOthHSm0jxioNqm7JszYDcZPAZVhHT2Qhen02b7PzW8M7Qx4FU+ldXgnhpenDN5/jqYYClfQ=="], 872 + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], 783 873 784 - "@tanstack/router-plugin": ["@tanstack/router-plugin@1.139.3", "", { "dependencies": { "@babel/core": "^7.27.7", "@babel/plugin-syntax-jsx": "^7.27.1", "@babel/plugin-syntax-typescript": "^7.27.1", "@babel/template": "^7.27.2", "@babel/traverse": "^7.27.7", "@babel/types": "^7.27.7", "@tanstack/router-core": "1.139.3", "@tanstack/router-generator": "1.139.3", "@tanstack/router-utils": "1.139.0", "@tanstack/virtual-file-routes": "1.139.0", "babel-dead-code-elimination": "^1.0.10", "chokidar": "^3.6.0", "unplugin": "^2.1.2", "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", "@tanstack/react-router": "^1.139.3", "vite": ">=5.0.0 || >=6.0.0 || >=7.0.0", "vite-plugin-solid": "^2.11.10", "webpack": ">=5.92.0" }, "optionalPeers": ["@rsbuild/core", "@tanstack/react-router", "vite", "vite-plugin-solid", "webpack"] }, "sha512-ymv5mr2IULgrZblzYeYUVZXzz3fzW1OzoDZh5cs5gEetRcEpXQ6XL8KG4pCkIQ04AJcrtXEWt1yZxi01XjZWxw=="], 874 + "@typelex/emitter": ["@typelex/emitter@0.4.0", "", { "dependencies": { "@typespec/compiler": "^1.4.0" } }, "sha512-BaKny+8TA0yX5jZibkAodHHKLJ6l6xVe5ut7KeoUyTD63lSSuB9OXe8tWXrs2DbeR/hialCimHFZQ3xANleMow=="], 785 875 786 - "@tanstack/router-utils": ["@tanstack/router-utils@1.139.0", "", { "dependencies": { "@babel/core": "^7.27.4", "@babel/generator": "^7.27.5", "@babel/parser": "^7.27.5", "@babel/preset-typescript": "^7.27.1", "ansis": "^4.1.0", "diff": "^8.0.2", "pathe": "^2.0.3", "tinyglobby": "^0.2.15" } }, "sha512-jT7D6NimWqoFSkid4vCno8gvTyfL1+NHpgm3es0B2UNhKKRV3LngOGilm1m6v8Qvk/gy6Fh/tvB+s+hBl6GhOg=="], 876 + "@types/babel__core": ["@types/babel__core@7.20.5", "", { "dependencies": { "@babel/parser": "^7.20.7", "@babel/types": "^7.20.7", "@types/babel__generator": "*", "@types/babel__template": "*", "@types/babel__traverse": "*" } }, "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA=="], 787 877 788 - "@tanstack/store": ["@tanstack/store@0.8.0", "", {}, "sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ=="], 878 + "@types/babel__generator": ["@types/babel__generator@7.27.0", "", { "dependencies": { "@babel/types": "^7.0.0" } }, "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg=="], 789 879 790 - "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.139.0", "", {}, "sha512-9PImF1d1tovTUIpjFVa0W7Fwj/MHif7BaaczgJJfbv3sDt1Gh+oW9W9uCw9M3ndEJynnp5ZD/TTs0RGubH5ssg=="], 880 + "@types/babel__template": ["@types/babel__template@7.4.4", "", { "dependencies": { "@babel/parser": "^7.1.0", "@babel/types": "^7.0.0" } }, "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A=="], 791 881 792 - "@typelex/emitter": ["@typelex/emitter@0.4.0", "", { "dependencies": { "@typespec/compiler": "^1.4.0" } }, "sha512-BaKny+8TA0yX5jZibkAodHHKLJ6l6xVe5ut7KeoUyTD63lSSuB9OXe8tWXrs2DbeR/hialCimHFZQ3xANleMow=="], 882 + "@types/babel__traverse": ["@types/babel__traverse@7.28.0", "", { "dependencies": { "@babel/types": "^7.28.2" } }, "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q=="], 793 883 794 884 "@types/bun": ["@types/bun@1.3.3", "", { "dependencies": { "bun-types": "1.3.3" } }, "sha512-ogrKbJ2X5N0kWLLFKeytG0eHDleBYtngtlbu9cyBKFtNL3cnpDZkNdQj8flVf6WTZUX5ulI9AY1oa7ljhSrp+g=="], 795 885 ··· 799 889 800 890 "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], 801 891 892 + "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], 893 + 802 894 "@types/mysql": ["@types/mysql@2.15.26", "", { "dependencies": { "@types/node": "*" } }, "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ=="], 803 895 804 896 "@types/node": ["@types/node@22.19.1", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ=="], 805 897 806 - "@types/pg": ["@types/pg@8.6.1", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w=="], 898 + "@types/pg": ["@types/pg@8.15.6", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-NoaMtzhxOrubeL/7UZuNTrejB4MPAJ0RpxZqXQf2qXuVlTPuG6Y8p4u9dKRaue4yjmC7ZhzVO2/Yyyn25znrPQ=="], 807 899 808 900 "@types/pg-pool": ["@types/pg-pool@2.0.6", "", { "dependencies": { "@types/pg": "*" } }, "sha512-TaAUE5rq2VQYxab5Ts7WZhKNmuN78Q6PiFonTDdpbx8a1H0M1vhy3rhiMjl+e2iHmogyMw7jZF4FrE6eJUy5HQ=="], 809 901 ··· 839 931 840 932 "@typespec/compiler": ["@typespec/compiler@1.6.0", "", { "dependencies": { "@babel/code-frame": "~7.27.1", "@inquirer/prompts": "^7.4.0", "ajv": "~8.17.1", "change-case": "~5.4.4", "env-paths": "^3.0.0", "globby": "~15.0.0", "is-unicode-supported": "^2.1.0", "mustache": "~4.2.0", "picocolors": "~1.1.1", "prettier": "~3.6.2", "semver": "^7.7.1", "tar": "^7.5.2", "temporal-polyfill": "^0.3.0", "vscode-languageserver": "~9.0.1", "vscode-languageserver-textdocument": "~1.0.12", "yaml": "~2.8.0", "yargs": "~18.0.0" }, "bin": { "tsp": "cmd/tsp.js", "tsp-server": "cmd/tsp-server.js" } }, "sha512-yxyV+ch8tnqiuU2gClv/mQEESoFwpkjo6177UkYfV0nVA9PzTg4zVVc7+WIMZk04wiLRRT3H1uc11FB1cwLY3g=="], 841 933 842 - "@vitejs/plugin-react-swc": ["@vitejs/plugin-react-swc@3.11.0", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-beta.27", "@swc/core": "^1.12.11" }, "peerDependencies": { "vite": "^4 || ^5 || ^6 || ^7" } }, "sha512-YTJCGFdNMHCMfjODYtxRNVAYmTWQ1Lb8PulP/2/f/oEEtglw8oKxKIZmmRkyXrVrHfsKOaVkAc3NT9/dMutO5w=="], 934 + "@unrs/resolver-binding-android-arm-eabi": ["@unrs/resolver-binding-android-arm-eabi@1.11.1", "", { "os": "android", "cpu": "arm" }, "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw=="], 935 + 936 + "@unrs/resolver-binding-android-arm64": ["@unrs/resolver-binding-android-arm64@1.11.1", "", { "os": "android", "cpu": "arm64" }, "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g=="], 937 + 938 + "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="], 939 + 940 + "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="], 843 941 844 - "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], 942 + "@unrs/resolver-binding-freebsd-x64": ["@unrs/resolver-binding-freebsd-x64@1.11.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw=="], 943 + 944 + "@unrs/resolver-binding-linux-arm-gnueabihf": ["@unrs/resolver-binding-linux-arm-gnueabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw=="], 945 + 946 + "@unrs/resolver-binding-linux-arm-musleabihf": ["@unrs/resolver-binding-linux-arm-musleabihf@1.11.1", "", { "os": "linux", "cpu": "arm" }, "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw=="], 947 + 948 + "@unrs/resolver-binding-linux-arm64-gnu": ["@unrs/resolver-binding-linux-arm64-gnu@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ=="], 949 + 950 + "@unrs/resolver-binding-linux-arm64-musl": ["@unrs/resolver-binding-linux-arm64-musl@1.11.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w=="], 951 + 952 + "@unrs/resolver-binding-linux-ppc64-gnu": ["@unrs/resolver-binding-linux-ppc64-gnu@1.11.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA=="], 953 + 954 + "@unrs/resolver-binding-linux-riscv64-gnu": ["@unrs/resolver-binding-linux-riscv64-gnu@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ=="], 955 + 956 + "@unrs/resolver-binding-linux-riscv64-musl": ["@unrs/resolver-binding-linux-riscv64-musl@1.11.1", "", { "os": "linux", "cpu": "none" }, "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew=="], 957 + 958 + "@unrs/resolver-binding-linux-s390x-gnu": ["@unrs/resolver-binding-linux-s390x-gnu@1.11.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg=="], 959 + 960 + "@unrs/resolver-binding-linux-x64-gnu": ["@unrs/resolver-binding-linux-x64-gnu@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w=="], 961 + 962 + "@unrs/resolver-binding-linux-x64-musl": ["@unrs/resolver-binding-linux-x64-musl@1.11.1", "", { "os": "linux", "cpu": "x64" }, "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA=="], 963 + 964 + "@unrs/resolver-binding-wasm32-wasi": ["@unrs/resolver-binding-wasm32-wasi@1.11.1", "", { "dependencies": { "@napi-rs/wasm-runtime": "^0.2.11" }, "cpu": "none" }, "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ=="], 965 + 966 + "@unrs/resolver-binding-win32-arm64-msvc": ["@unrs/resolver-binding-win32-arm64-msvc@1.11.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw=="], 967 + 968 + "@unrs/resolver-binding-win32-ia32-msvc": ["@unrs/resolver-binding-win32-ia32-msvc@1.11.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ=="], 969 + 970 + "@unrs/resolver-binding-win32-x64-msvc": ["@unrs/resolver-binding-win32-x64-msvc@1.11.1", "", { "os": "win32", "cpu": "x64" }, "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g=="], 971 + 972 + "@vitejs/plugin-react": ["@vitejs/plugin-react@5.1.1", "", { "dependencies": { "@babel/core": "^7.28.5", "@babel/plugin-transform-react-jsx-self": "^7.27.1", "@babel/plugin-transform-react-jsx-source": "^7.27.1", "@rolldown/pluginutils": "1.0.0-beta.47", "@types/babel__core": "^7.20.5", "react-refresh": "^0.18.0" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, "sha512-WQfkSw0QbQ5aJ2CHYw23ZGkqnRwqKHD/KYsMeTkZzPT4Jcf0DcBxBtwMJxnu6E7oxw5+JC6ZAiePgh28uJ1HBA=="], 845 973 846 974 "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], 847 975 ··· 857 985 858 986 "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], 859 987 860 - "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], 861 - 862 988 "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], 863 989 864 - "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], 990 + "app": ["app@workspace:apps/app"], 865 991 866 992 "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], 867 993 868 994 "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], 869 995 996 + "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], 997 + 998 + "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], 999 + 1000 + "array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="], 1001 + 1002 + "array.prototype.findlast": ["array.prototype.findlast@1.2.5", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ=="], 1003 + 1004 + "array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="], 1005 + 1006 + "array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="], 1007 + 1008 + "array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="], 1009 + 1010 + "array.prototype.tosorted": ["array.prototype.tosorted@1.1.4", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3", "es-errors": "^1.3.0", "es-shim-unscopables": "^1.0.2" } }, "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA=="], 1011 + 1012 + "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], 1013 + 870 1014 "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], 871 1015 872 - "asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="], 1016 + "ast-types-flow": ["ast-types-flow@0.0.8", "", {}, "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ=="], 1017 + 1018 + "async-function": ["async-function@1.0.0", "", {}, "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA=="], 873 1019 874 1020 "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], 875 1021 876 - "autoprefixer": ["autoprefixer@10.4.22", "", { "dependencies": { "browserslist": "^4.27.0", "caniuse-lite": "^1.0.30001754", "fraction.js": "^5.3.4", "normalize-range": "^0.1.2", "picocolors": "^1.1.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.1.0" }, "bin": { "autoprefixer": "bin/autoprefixer" } }, "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg=="], 1022 + "available-typed-arrays": ["available-typed-arrays@1.0.7", "", { "dependencies": { "possible-typed-array-names": "^1.0.0" } }, "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ=="], 877 1023 878 - "axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="], 1024 + "axe-core": ["axe-core@4.11.0", "", {}, "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ=="], 1025 + 1026 + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], 879 1027 880 1028 "babel-dead-code-elimination": ["babel-dead-code-elimination@1.0.10", "", { "dependencies": { "@babel/core": "^7.23.7", "@babel/parser": "^7.23.6", "@babel/traverse": "^7.23.7", "@babel/types": "^7.23.6" } }, "sha512-DV5bdJZTzZ0zn0DC24v3jD7Mnidh6xhKa4GfKCbq3sfW8kaWhDdZjP3i81geA8T33tdYqWKw4D3fVv0CwEgKVA=="], 881 1029 882 - "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], 1030 + "babel-plugin-react-compiler": ["babel-plugin-react-compiler@1.0.0", "", { "dependencies": { "@babel/types": "^7.26.0" } }, "sha512-Ixm8tFfoKKIPYdCCKYTsqv+Fd4IJ0DQqMyEimo+pxUOMUR9cVPlwTrFt9Avu+3cb6Zp3mAzl+t1MrG2fxxKsxw=="], 883 1031 884 - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], 1032 + "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], 885 1033 886 1034 "baseline-browser-mapping": ["baseline-browser-mapping@2.8.31", "", { "bin": { "baseline-browser-mapping": "dist/cli.js" } }, "sha512-a28v2eWrrRWPpJSzxc+mKwm0ZtVx/G8SepdQZDArnXYU/XS+IF6mp8aB/4E+hH1tyGCoDo3KlUCdlSxGDsRkAw=="], 887 1035 888 1036 "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], 889 - 890 - "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], 891 1037 892 1038 "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], 893 1039 894 1040 "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], 895 1041 896 1042 "browserslist": ["browserslist@4.28.0", "", { "dependencies": { "baseline-browser-mapping": "^2.8.25", "caniuse-lite": "^1.0.30001754", "electron-to-chromium": "^1.5.249", "node-releases": "^2.0.27", "update-browserslist-db": "^1.1.4" }, "bin": { "browserslist": "cli.js" } }, "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ=="], 897 - 898 - "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], 899 1043 900 1044 "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], 901 1045 ··· 903 1047 904 1048 "bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="], 905 1049 1050 + "call-bind": ["call-bind@1.0.8", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.0", "es-define-property": "^1.0.0", "get-intrinsic": "^1.2.4", "set-function-length": "^1.2.2" } }, "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww=="], 1051 + 906 1052 "call-bind-apply-helpers": ["call-bind-apply-helpers@1.0.2", "", { "dependencies": { "es-errors": "^1.3.0", "function-bind": "^1.1.2" } }, "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ=="], 907 1053 1054 + "call-bound": ["call-bound@1.0.4", "", { "dependencies": { "call-bind-apply-helpers": "^1.0.2", "get-intrinsic": "^1.3.0" } }, "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg=="], 1055 + 908 1056 "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], 909 1057 910 - "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], 911 - 912 - "caniuse-api": ["caniuse-api@3.0.0", "", { "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw=="], 913 - 914 1058 "caniuse-lite": ["caniuse-lite@1.0.30001757", "", {}, "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ=="], 915 - 916 - "cbor-extract": ["cbor-extract@2.2.0", "", { "dependencies": { "node-gyp-build-optional-packages": "5.1.1" }, "optionalDependencies": { "@cbor-extract/cbor-extract-darwin-arm64": "2.2.0", "@cbor-extract/cbor-extract-darwin-x64": "2.2.0", "@cbor-extract/cbor-extract-linux-arm": "2.2.0", "@cbor-extract/cbor-extract-linux-arm64": "2.2.0", "@cbor-extract/cbor-extract-linux-x64": "2.2.0", "@cbor-extract/cbor-extract-win32-x64": "2.2.0" }, "bin": { "download-cbor-prebuilds": "bin/download-prebuilds.js" } }, "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA=="], 917 - 918 - "cbor-x": ["cbor-x@1.6.0", "", { "optionalDependencies": { "cbor-extract": "^2.2.0" } }, "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg=="], 919 - 920 - "cborg": ["cborg@1.10.2", "", { "bin": { "cborg": "cli.js" } }, "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug=="], 921 1059 922 1060 "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], 923 1061 ··· 935 1073 936 1074 "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], 937 1075 1076 + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], 1077 + 938 1078 "cliui": ["cliui@9.0.1", "", { "dependencies": { "string-width": "^7.2.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" } }, "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w=="], 939 1079 940 1080 "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], ··· 943 1083 944 1084 "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 945 1085 946 - "colord": ["colord@2.9.3", "", {}, "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="], 947 - 948 1086 "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], 949 1087 950 - "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], 951 - 952 - "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], 953 - 954 1088 "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], 955 1089 956 1090 "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], 957 1091 958 1092 "cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], 959 1093 960 - "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], 961 - 962 - "css-declaration-sorter": ["css-declaration-sorter@7.3.0", "", { "peerDependencies": { "postcss": "^8.0.9" } }, "sha512-LQF6N/3vkAMYF4xoHLJfG718HRJh34Z8BnNhd6bosOMIVjMlhuZK5++oZa3uYAgrI5+7x2o27gUqTR2U/KjUOQ=="], 963 - 964 - "css-select": ["css-select@5.2.2", "", { "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.1.0", "domhandler": "^5.0.2", "domutils": "^3.0.1", "nth-check": "^2.0.1" } }, "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw=="], 965 - 966 - "css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="], 967 - 968 - "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], 1094 + "core-js": ["core-js@3.47.0", "", {}, "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg=="], 969 1095 970 - "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], 1096 + "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], 971 1097 972 - "cssnano": ["cssnano@7.1.2", "", { "dependencies": { "cssnano-preset-default": "^7.0.10", "lilconfig": "^3.1.3" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-HYOPBsNvoiFeR1eghKD5C3ASm64v9YVyJB4Ivnl2gqKoQYvjjN/G0rztvKQq8OxocUtC6sjqY8jwYngIB4AByA=="], 1098 + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], 973 1099 974 - "cssnano-preset-default": ["cssnano-preset-default@7.0.10", "", { "dependencies": { "browserslist": "^4.27.0", "css-declaration-sorter": "^7.2.0", "cssnano-utils": "^5.0.1", "postcss-calc": "^10.1.1", "postcss-colormin": "^7.0.5", "postcss-convert-values": "^7.0.8", "postcss-discard-comments": "^7.0.5", "postcss-discard-duplicates": "^7.0.2", "postcss-discard-empty": "^7.0.1", "postcss-discard-overridden": "^7.0.1", "postcss-merge-longhand": "^7.0.5", "postcss-merge-rules": "^7.0.7", "postcss-minify-font-values": "^7.0.1", "postcss-minify-gradients": "^7.0.1", "postcss-minify-params": "^7.0.5", "postcss-minify-selectors": "^7.0.5", "postcss-normalize-charset": "^7.0.1", "postcss-normalize-display-values": "^7.0.1", "postcss-normalize-positions": "^7.0.1", "postcss-normalize-repeat-style": "^7.0.1", "postcss-normalize-string": "^7.0.1", "postcss-normalize-timing-functions": "^7.0.1", "postcss-normalize-unicode": "^7.0.5", "postcss-normalize-url": "^7.0.1", "postcss-normalize-whitespace": "^7.0.1", "postcss-ordered-values": "^7.0.2", "postcss-reduce-initial": "^7.0.5", "postcss-reduce-transforms": "^7.0.1", "postcss-svgo": "^7.1.0", "postcss-unique-selectors": "^7.0.4" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-6ZBjW0Lf1K1Z+0OKUAUpEN62tSXmYChXWi2NAA0afxEVsj9a+MbcB1l5qel6BHJHmULai2fCGRthCeKSFbScpA=="], 1100 + "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="], 975 1101 976 - "cssnano-utils": ["cssnano-utils@5.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-ZIP71eQgG9JwjVZsTPSqhc6GHgEr53uJ7tK5///VfyWj6Xp2DBmixWHqJgPno+PqATzn48pL42ww9x5SSGmhZg=="], 1102 + "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], 977 1103 978 - "csso": ["csso@5.0.5", "", { "dependencies": { "css-tree": "~2.2.0" } }, "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ=="], 1104 + "data-view-buffer": ["data-view-buffer@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ=="], 979 1105 980 - "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], 1106 + "data-view-byte-length": ["data-view-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-data-view": "^1.0.2" } }, "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ=="], 981 1107 982 - "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], 1108 + "data-view-byte-offset": ["data-view-byte-offset@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-data-view": "^1.0.1" } }, "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ=="], 983 1109 984 1110 "dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="], 985 1111 ··· 987 1113 988 1114 "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], 989 1115 990 - "delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="], 1116 + "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], 1117 + 1118 + "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], 991 1119 992 1120 "detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], 993 1121 994 1122 "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], 995 1123 996 - "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], 997 - 998 1124 "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], 999 1125 1000 - "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], 1001 - 1002 - "dom-serializer": ["dom-serializer@2.0.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.2", "entities": "^4.2.0" } }, "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg=="], 1003 - 1004 - "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], 1005 - 1006 - "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], 1007 - 1008 - "domutils": ["domutils@3.2.2", "", { "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", "domhandler": "^5.0.3" } }, "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw=="], 1126 + "doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="], 1009 1127 1010 1128 "drizzle-kit": ["drizzle-kit@0.29.1", "", { "dependencies": { "@drizzle-team/brocli": "^0.10.2", "@esbuild-kit/esm-loader": "^2.5.5", "esbuild": "^0.19.7", "esbuild-register": "^3.5.0" }, "bin": { "drizzle-kit": "bin.cjs" } }, "sha512-OvHL8RVyYiPR3LLRE3SHdcON8xGXl+qMfR9uTTnFWBPIqVk/3NWYZPb7nfpM1Bhix3H+BsxqPyyagG7YZ+Z63A=="], 1011 1129 ··· 1015 1133 1016 1134 "electron-to-chromium": ["electron-to-chromium@1.5.259", "", {}, "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ=="], 1017 1135 1018 - "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], 1136 + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], 1019 1137 1020 1138 "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], 1021 1139 1022 - "entities": ["entities@4.5.0", "", {}, "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="], 1140 + "enhanced-resolve": ["enhanced-resolve@5.18.3", "", { "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" } }, "sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww=="], 1023 1141 1024 1142 "env-paths": ["env-paths@3.0.0", "", {}, "sha512-dtJUTepzMW3Lm/NPxRf3wP4642UWhjL2sQxc+ym2YMj1m/H2zDNQOlezafzkHwn6sMstjHTwG6iQQsctDW/b1A=="], 1143 + 1144 + "es-abstract": ["es-abstract@1.24.0", "", { "dependencies": { "array-buffer-byte-length": "^1.0.2", "arraybuffer.prototype.slice": "^1.0.4", "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "data-view-buffer": "^1.0.2", "data-view-byte-length": "^1.0.2", "data-view-byte-offset": "^1.0.1", "es-define-property": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-set-tostringtag": "^2.1.0", "es-to-primitive": "^1.3.0", "function.prototype.name": "^1.1.8", "get-intrinsic": "^1.3.0", "get-proto": "^1.0.1", "get-symbol-description": "^1.1.0", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "hasown": "^2.0.2", "internal-slot": "^1.1.0", "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", "is-data-view": "^1.0.2", "is-negative-zero": "^2.0.3", "is-regex": "^1.2.1", "is-set": "^2.0.3", "is-shared-array-buffer": "^1.0.4", "is-string": "^1.1.1", "is-typed-array": "^1.1.15", "is-weakref": "^1.1.1", "math-intrinsics": "^1.1.0", "object-inspect": "^1.13.4", "object-keys": "^1.1.1", "object.assign": "^4.1.7", "own-keys": "^1.0.1", "regexp.prototype.flags": "^1.5.4", "safe-array-concat": "^1.1.3", "safe-push-apply": "^1.0.0", "safe-regex-test": "^1.1.0", "set-proto": "^1.0.0", "stop-iteration-iterator": "^1.1.0", "string.prototype.trim": "^1.2.10", "string.prototype.trimend": "^1.0.9", "string.prototype.trimstart": "^1.0.8", "typed-array-buffer": "^1.0.3", "typed-array-byte-length": "^1.0.3", "typed-array-byte-offset": "^1.0.4", "typed-array-length": "^1.0.7", "unbox-primitive": "^1.1.0", "which-typed-array": "^1.1.19" } }, "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg=="], 1025 1145 1026 1146 "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], 1027 1147 1028 1148 "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], 1149 + 1150 + "es-iterator-helpers": ["es-iterator-helpers@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-set-tostringtag": "^2.0.3", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.6", "globalthis": "^1.0.4", "gopd": "^1.2.0", "has-property-descriptors": "^1.0.2", "has-proto": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "iterator.prototype": "^1.1.4", "safe-array-concat": "^1.1.3" } }, "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w=="], 1029 1151 1030 1152 "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], 1031 1153 1032 1154 "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], 1033 1155 1156 + "es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="], 1157 + 1158 + "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], 1159 + 1034 1160 "esbuild": ["esbuild@0.19.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.19.12", "@esbuild/android-arm": "0.19.12", "@esbuild/android-arm64": "0.19.12", "@esbuild/android-x64": "0.19.12", "@esbuild/darwin-arm64": "0.19.12", "@esbuild/darwin-x64": "0.19.12", "@esbuild/freebsd-arm64": "0.19.12", "@esbuild/freebsd-x64": "0.19.12", "@esbuild/linux-arm": "0.19.12", "@esbuild/linux-arm64": "0.19.12", "@esbuild/linux-ia32": "0.19.12", "@esbuild/linux-loong64": "0.19.12", "@esbuild/linux-mips64el": "0.19.12", "@esbuild/linux-ppc64": "0.19.12", "@esbuild/linux-riscv64": "0.19.12", "@esbuild/linux-s390x": "0.19.12", "@esbuild/linux-x64": "0.19.12", "@esbuild/netbsd-x64": "0.19.12", "@esbuild/openbsd-x64": "0.19.12", "@esbuild/sunos-x64": "0.19.12", "@esbuild/win32-arm64": "0.19.12", "@esbuild/win32-ia32": "0.19.12", "@esbuild/win32-x64": "0.19.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg=="], 1035 1161 1036 1162 "esbuild-register": ["esbuild-register@3.6.0", "", { "dependencies": { "debug": "^4.3.4" }, "peerDependencies": { "esbuild": ">=0.12 <1" } }, "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg=="], ··· 1041 1167 1042 1168 "eslint": ["eslint@9.39.1", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.21.1", "@eslint/config-helpers": "^0.4.2", "@eslint/core": "^0.17.0", "@eslint/eslintrc": "^3.3.1", "@eslint/js": "9.39.1", "@eslint/plugin-kit": "^0.4.1", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", "@humanwhocodes/retry": "^0.4.2", "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.6", "debug": "^4.3.2", "escape-string-regexp": "^4.0.0", "eslint-scope": "^8.4.0", "eslint-visitor-keys": "^4.2.1", "espree": "^10.4.0", "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "json-stable-stringify-without-jsonify": "^1.0.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", "optionator": "^0.9.3" }, "peerDependencies": { "jiti": "*" }, "optionalPeers": ["jiti"], "bin": { "eslint": "bin/eslint.js" } }, "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g=="], 1043 1169 1044 - "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@5.2.0", "", { "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg=="], 1170 + "eslint-config-next": ["eslint-config-next@16.0.7", "", { "dependencies": { "@next/eslint-plugin-next": "16.0.7", "eslint-import-resolver-node": "^0.3.6", "eslint-import-resolver-typescript": "^3.5.2", "eslint-plugin-import": "^2.32.0", "eslint-plugin-jsx-a11y": "^6.10.0", "eslint-plugin-react": "^7.37.0", "eslint-plugin-react-hooks": "^7.0.0", "globals": "16.4.0", "typescript-eslint": "^8.46.0" }, "peerDependencies": { "eslint": ">=9.0.0", "typescript": ">=3.3.1" }, "optionalPeers": ["typescript"] }, "sha512-WubFGLFHfk2KivkdRGfx6cGSFhaQqhERRfyO8BRx+qiGPGp7WLKcPvYC4mdx1z3VhVRcrfFzczjjTrbJZOpnEQ=="], 1171 + 1172 + "eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="], 1173 + 1174 + "eslint-import-resolver-typescript": ["eslint-import-resolver-typescript@3.10.1", "", { "dependencies": { "@nolyfill/is-core-module": "1.0.39", "debug": "^4.4.0", "get-tsconfig": "^4.10.0", "is-bun-module": "^2.0.0", "stable-hash": "^0.0.5", "tinyglobby": "^0.2.13", "unrs-resolver": "^1.6.2" }, "peerDependencies": { "eslint": "*", "eslint-plugin-import": "*", "eslint-plugin-import-x": "*" }, "optionalPeers": ["eslint-plugin-import", "eslint-plugin-import-x"] }, "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ=="], 1175 + 1176 + "eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="], 1177 + 1178 + "eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="], 1179 + 1180 + "eslint-plugin-jsx-a11y": ["eslint-plugin-jsx-a11y@6.10.2", "", { "dependencies": { "aria-query": "^5.3.2", "array-includes": "^3.1.8", "array.prototype.flatmap": "^1.3.2", "ast-types-flow": "^0.0.8", "axe-core": "^4.10.0", "axobject-query": "^4.1.0", "damerau-levenshtein": "^1.0.8", "emoji-regex": "^9.2.2", "hasown": "^2.0.2", "jsx-ast-utils": "^3.3.5", "language-tags": "^1.0.9", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "safe-regex-test": "^1.0.3", "string.prototype.includes": "^2.0.1" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" } }, "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q=="], 1181 + 1182 + "eslint-plugin-react": ["eslint-plugin-react@7.37.5", "", { "dependencies": { "array-includes": "^3.1.8", "array.prototype.findlast": "^1.2.5", "array.prototype.flatmap": "^1.3.3", "array.prototype.tosorted": "^1.1.4", "doctrine": "^2.1.0", "es-iterator-helpers": "^1.2.1", "estraverse": "^5.3.0", "hasown": "^2.0.2", "jsx-ast-utils": "^2.4.1 || ^3.0.0", "minimatch": "^3.1.2", "object.entries": "^1.1.9", "object.fromentries": "^2.0.8", "object.values": "^1.2.1", "prop-types": "^15.8.1", "resolve": "^2.0.0-next.5", "semver": "^6.3.1", "string.prototype.matchall": "^4.0.12", "string.prototype.repeat": "^1.0.0" }, "peerDependencies": { "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" } }, "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA=="], 1183 + 1184 + "eslint-plugin-react-hooks": ["eslint-plugin-react-hooks@7.0.1", "", { "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", "hermes-parser": "^0.25.1", "zod": "^3.25.0 || ^4.0.0", "zod-validation-error": "^3.5.0 || ^4.0.0" }, "peerDependencies": { "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" } }, "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA=="], 1045 1185 1046 1186 "eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.24", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w=="], 1047 1187 ··· 1065 1205 1066 1206 "event-target-polyfill": ["event-target-polyfill@0.0.4", "", {}, "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ=="], 1067 1207 1068 - "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], 1069 - 1070 - "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], 1071 - 1072 1208 "fast-copy": ["fast-copy@3.0.2", "", {}, "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ=="], 1073 1209 1074 1210 "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], ··· 1079 1215 1080 1216 "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], 1081 1217 1082 - "fast-redact": ["fast-redact@3.5.0", "", {}, "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="], 1083 - 1084 1218 "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], 1085 1219 1086 1220 "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], ··· 1101 1235 1102 1236 "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], 1103 1237 1104 - "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], 1105 - 1106 - "form-data": ["form-data@4.0.5", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.2", "mime-types": "^2.1.12" } }, "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w=="], 1238 + "for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="], 1107 1239 1108 1240 "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], 1109 1241 1110 1242 "forwarded-parse": ["forwarded-parse@2.1.2", "", {}, "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw=="], 1111 1243 1112 - "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="], 1113 - 1114 1244 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 1115 1245 1116 1246 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], 1117 1247 1248 + "function.prototype.name": ["function.prototype.name@1.1.8", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "functions-have-names": "^1.2.3", "hasown": "^2.0.2", "is-callable": "^1.2.7" } }, "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q=="], 1249 + 1250 + "functions-have-names": ["functions-have-names@1.2.3", "", {}, "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ=="], 1251 + 1252 + "generator-function": ["generator-function@2.0.1", "", {}, "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g=="], 1253 + 1118 1254 "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], 1119 1255 1120 1256 "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], ··· 1126 1262 "get-nonce": ["get-nonce@1.0.1", "", {}, "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q=="], 1127 1263 1128 1264 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], 1265 + 1266 + "get-symbol-description": ["get-symbol-description@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6" } }, "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg=="], 1129 1267 1130 1268 "get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="], 1131 1269 ··· 1133 1271 1134 1272 "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], 1135 1273 1136 - "globals": ["globals@15.15.0", "", {}, "sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg=="], 1274 + "globals": ["globals@16.5.0", "", {}, "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ=="], 1275 + 1276 + "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], 1137 1277 1138 1278 "globby": ["globby@15.0.0", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "fast-glob": "^3.3.3", "ignore": "^7.0.5", "path-type": "^6.0.0", "slash": "^5.1.0", "unicorn-magic": "^0.3.0" } }, "sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw=="], 1139 1279 ··· 1141 1281 1142 1282 "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], 1143 1283 1284 + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], 1285 + 1144 1286 "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], 1287 + 1288 + "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], 1145 1289 1146 1290 "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], 1147 1291 1292 + "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], 1293 + 1294 + "has-proto": ["has-proto@1.2.0", "", { "dependencies": { "dunder-proto": "^1.0.0" } }, "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ=="], 1295 + 1148 1296 "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], 1149 1297 1150 1298 "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], ··· 1153 1301 1154 1302 "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], 1155 1303 1156 - "iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], 1304 + "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="], 1157 1305 1158 - "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], 1306 + "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], 1307 + 1308 + "hono": ["hono@4.10.7", "", {}, "sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw=="], 1309 + 1310 + "iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], 1159 1311 1160 1312 "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], 1161 1313 ··· 1165 1317 1166 1318 "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], 1167 1319 1320 + "internal-slot": ["internal-slot@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "hasown": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw=="], 1321 + 1168 1322 "ipaddr.js": ["ipaddr.js@2.2.0", "", {}, "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA=="], 1169 1323 1324 + "is-array-buffer": ["is-array-buffer@3.0.5", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A=="], 1325 + 1326 + "is-async-function": ["is-async-function@2.1.1", "", { "dependencies": { "async-function": "^1.0.0", "call-bound": "^1.0.3", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ=="], 1327 + 1328 + "is-bigint": ["is-bigint@1.1.0", "", { "dependencies": { "has-bigints": "^1.0.2" } }, "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ=="], 1329 + 1170 1330 "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], 1171 1331 1332 + "is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="], 1333 + 1334 + "is-bun-module": ["is-bun-module@2.0.0", "", { "dependencies": { "semver": "^7.7.1" } }, "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ=="], 1335 + 1336 + "is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="], 1337 + 1172 1338 "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], 1173 1339 1340 + "is-data-view": ["is-data-view@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "is-typed-array": "^1.1.13" } }, "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw=="], 1341 + 1342 + "is-date-object": ["is-date-object@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "has-tostringtag": "^1.0.2" } }, "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg=="], 1343 + 1174 1344 "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], 1345 + 1346 + "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], 1175 1347 1176 1348 "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], 1177 1349 1350 + "is-generator-function": ["is-generator-function@1.1.2", "", { "dependencies": { "call-bound": "^1.0.4", "generator-function": "^2.0.0", "get-proto": "^1.0.1", "has-tostringtag": "^1.0.2", "safe-regex-test": "^1.1.0" } }, "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA=="], 1351 + 1178 1352 "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], 1179 1353 1354 + "is-map": ["is-map@2.0.3", "", {}, "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw=="], 1355 + 1356 + "is-negative-zero": ["is-negative-zero@2.0.3", "", {}, "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw=="], 1357 + 1180 1358 "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], 1181 1359 1360 + "is-number-object": ["is-number-object@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw=="], 1361 + 1362 + "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], 1363 + 1364 + "is-set": ["is-set@2.0.3", "", {}, "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg=="], 1365 + 1366 + "is-shared-array-buffer": ["is-shared-array-buffer@1.0.4", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A=="], 1367 + 1368 + "is-string": ["is-string@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA=="], 1369 + 1370 + "is-symbol": ["is-symbol@1.1.1", "", { "dependencies": { "call-bound": "^1.0.2", "has-symbols": "^1.1.0", "safe-regex-test": "^1.1.0" } }, "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w=="], 1371 + 1372 + "is-typed-array": ["is-typed-array@1.1.15", "", { "dependencies": { "which-typed-array": "^1.1.16" } }, "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ=="], 1373 + 1182 1374 "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], 1183 1375 1376 + "is-weakmap": ["is-weakmap@2.0.2", "", {}, "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w=="], 1377 + 1378 + "is-weakref": ["is-weakref@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew=="], 1379 + 1380 + "is-weakset": ["is-weakset@2.0.4", "", { "dependencies": { "call-bound": "^1.0.3", "get-intrinsic": "^1.2.6" } }, "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ=="], 1381 + 1382 + "isarray": ["isarray@2.0.5", "", {}, "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="], 1383 + 1184 1384 "isbot": ["isbot@5.1.32", "", {}, "sha512-VNfjM73zz2IBZmdShMfAUg10prm6t7HFUQmNAEOAVS4YH92ZrZcvkMcGX6cIgBJAzWDzPent/EeAtYEHNPNPBQ=="], 1185 1385 1186 1386 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], 1187 1387 1188 1388 "iso-datestring-validator": ["iso-datestring-validator@2.2.2", "", {}, "sha512-yLEMkBbLZTlVQqOnQ4FiMujR6T4DEcCb1xizmvXS+OxuhwcbtynoosRzdMA69zZCShCNAbi+gJ71FxZBBXx1SA=="], 1389 + 1390 + "iterator.prototype": ["iterator.prototype@1.1.5", "", { "dependencies": { "define-data-property": "^1.1.4", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "get-proto": "^1.0.0", "has-symbols": "^1.1.0", "set-function-name": "^2.0.2" } }, "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g=="], 1189 1391 1190 1392 "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], 1191 1393 ··· 1209 1411 1210 1412 "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], 1211 1413 1414 + "jsx-ast-utils": ["jsx-ast-utils@3.3.5", "", { "dependencies": { "array-includes": "^3.1.6", "array.prototype.flat": "^1.3.1", "object.assign": "^4.1.4", "object.values": "^1.1.6" } }, "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ=="], 1415 + 1212 1416 "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], 1417 + 1418 + "language-subtag-registry": ["language-subtag-registry@0.3.23", "", {}, "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ=="], 1419 + 1420 + "language-tags": ["language-tags@1.0.9", "", { "dependencies": { "language-subtag-registry": "^0.3.20" } }, "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA=="], 1213 1421 1214 1422 "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], 1215 1423 1216 1424 "libsql": ["libsql@0.4.7", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.4.7", "@libsql/darwin-x64": "0.4.7", "@libsql/linux-arm64-gnu": "0.4.7", "@libsql/linux-arm64-musl": "0.4.7", "@libsql/linux-x64-gnu": "0.4.7", "@libsql/linux-x64-musl": "0.4.7", "@libsql/win32-x64-msvc": "0.4.7" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "x64", "arm64", ] }, "sha512-T9eIRCs6b0J1SHKYIvD8+KCJMcWZ900iZyxdnSCdqxN12Z1ijzT+jY5nrk72Jw4B0HGzms2NgpryArlJqvc3Lw=="], 1217 1425 1218 - "lilconfig": ["lilconfig@3.1.3", "", {}, "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw=="], 1426 + "lightningcss": ["lightningcss@1.30.2", "", { "dependencies": { "detect-libc": "^2.0.3" }, "optionalDependencies": { "lightningcss-android-arm64": "1.30.2", "lightningcss-darwin-arm64": "1.30.2", "lightningcss-darwin-x64": "1.30.2", "lightningcss-freebsd-x64": "1.30.2", "lightningcss-linux-arm-gnueabihf": "1.30.2", "lightningcss-linux-arm64-gnu": "1.30.2", "lightningcss-linux-arm64-musl": "1.30.2", "lightningcss-linux-x64-gnu": "1.30.2", "lightningcss-linux-x64-musl": "1.30.2", "lightningcss-win32-arm64-msvc": "1.30.2", "lightningcss-win32-x64-msvc": "1.30.2" } }, "sha512-utfs7Pr5uJyyvDETitgsaqSyjCb2qNRAtuqUeWIAKztsOYdcACf2KtARYXg2pSvhkt+9NfoaNY7fxjl6nuMjIQ=="], 1427 + 1428 + "lightningcss-android-arm64": ["lightningcss-android-arm64@1.30.2", "", { "os": "android", "cpu": "arm64" }, "sha512-BH9sEdOCahSgmkVhBLeU7Hc9DWeZ1Eb6wNS6Da8igvUwAe0sqROHddIlvU06q3WyXVEOYDZ6ykBZQnjTbmo4+A=="], 1429 + 1430 + "lightningcss-darwin-arm64": ["lightningcss-darwin-arm64@1.30.2", "", { "os": "darwin", "cpu": "arm64" }, "sha512-ylTcDJBN3Hp21TdhRT5zBOIi73P6/W0qwvlFEk22fkdXchtNTOU4Qc37SkzV+EKYxLouZ6M4LG9NfZ1qkhhBWA=="], 1431 + 1432 + "lightningcss-darwin-x64": ["lightningcss-darwin-x64@1.30.2", "", { "os": "darwin", "cpu": "x64" }, "sha512-oBZgKchomuDYxr7ilwLcyms6BCyLn0z8J0+ZZmfpjwg9fRVZIR5/GMXd7r9RH94iDhld3UmSjBM6nXWM2TfZTQ=="], 1433 + 1434 + "lightningcss-freebsd-x64": ["lightningcss-freebsd-x64@1.30.2", "", { "os": "freebsd", "cpu": "x64" }, "sha512-c2bH6xTrf4BDpK8MoGG4Bd6zAMZDAXS569UxCAGcA7IKbHNMlhGQ89eRmvpIUGfKWNVdbhSbkQaWhEoMGmGslA=="], 1435 + 1436 + "lightningcss-linux-arm-gnueabihf": ["lightningcss-linux-arm-gnueabihf@1.30.2", "", { "os": "linux", "cpu": "arm" }, "sha512-eVdpxh4wYcm0PofJIZVuYuLiqBIakQ9uFZmipf6LF/HRj5Bgm0eb3qL/mr1smyXIS1twwOxNWndd8z0E374hiA=="], 1437 + 1438 + "lightningcss-linux-arm64-gnu": ["lightningcss-linux-arm64-gnu@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-UK65WJAbwIJbiBFXpxrbTNArtfuznvxAJw4Q2ZGlU8kPeDIWEX1dg3rn2veBVUylA2Ezg89ktszWbaQnxD/e3A=="], 1439 + 1440 + "lightningcss-linux-arm64-musl": ["lightningcss-linux-arm64-musl@1.30.2", "", { "os": "linux", "cpu": "arm64" }, "sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA=="], 1441 + 1442 + "lightningcss-linux-x64-gnu": ["lightningcss-linux-x64-gnu@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w=="], 1443 + 1444 + "lightningcss-linux-x64-musl": ["lightningcss-linux-x64-musl@1.30.2", "", { "os": "linux", "cpu": "x64" }, "sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA=="], 1445 + 1446 + "lightningcss-win32-arm64-msvc": ["lightningcss-win32-arm64-msvc@1.30.2", "", { "os": "win32", "cpu": "arm64" }, "sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ=="], 1219 1447 1220 - "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], 1448 + "lightningcss-win32-x64-msvc": ["lightningcss-win32-x64-msvc@1.30.2", "", { "os": "win32", "cpu": "x64" }, "sha512-5g1yc73p+iAkid5phb4oVFMB45417DkRevRbt/El/gKXJk4jid+vPFF/AXbxn05Aky8PapwzZrdJShv5C0avjw=="], 1221 1449 1222 1450 "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], 1223 1451 1224 - "lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="], 1225 - 1226 1452 "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], 1227 1453 1228 - "lodash.uniq": ["lodash.uniq@4.5.0", "", {}, "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="], 1454 + "loose-envify": ["loose-envify@1.4.0", "", { "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, "bin": { "loose-envify": "cli.js" } }, "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q=="], 1229 1455 1230 - "lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="], 1456 + "lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], 1231 1457 1232 - "lucide-react": ["lucide-react@0.464.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc" } }, "sha512-eCx1qClbnw5qRqB2Z1AFFp71wdJXEwhPp5ii8LviyvHb7o/7eMXFiTyDHh7JpjM9BO9pC6ZUp/c7mCwwxbPIcg=="], 1458 + "lucide-react": ["lucide-react@0.556.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-iOb8dRk7kLaYBZhR2VlV1CeJGxChBgUthpSP8wom9jfj79qovgG6qcSdiy6vkoREKPnbUYzJsCn4o4PtG3Iy+A=="], 1233 1459 1234 - "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], 1460 + "magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="], 1235 1461 1236 - "mdn-data": ["mdn-data@2.12.2", "", {}, "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA=="], 1462 + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], 1237 1463 1238 1464 "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], 1239 1465 1240 1466 "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], 1241 - 1242 - "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], 1243 - 1244 - "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], 1245 1467 1246 1468 "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], 1247 1469 ··· 1261 1483 1262 1484 "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="], 1263 1485 1264 - "mz": ["mz@2.7.0", "", { "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", "thenify-all": "^1.0.0" } }, "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q=="], 1486 + "nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="], 1265 1487 1266 - "nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="], 1488 + "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="], 1267 1489 1268 1490 "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], 1269 1491 1492 + "next": ["next@16.0.7", "", { "dependencies": { "@next/env": "16.0.7", "@swc/helpers": "0.5.15", "caniuse-lite": "^1.0.30001579", "postcss": "8.4.31", "styled-jsx": "5.1.6" }, "optionalDependencies": { "@next/swc-darwin-arm64": "16.0.7", "@next/swc-darwin-x64": "16.0.7", "@next/swc-linux-arm64-gnu": "16.0.7", "@next/swc-linux-arm64-musl": "16.0.7", "@next/swc-linux-x64-gnu": "16.0.7", "@next/swc-linux-x64-musl": "16.0.7", "@next/swc-win32-arm64-msvc": "16.0.7", "@next/swc-win32-x64-msvc": "16.0.7", "sharp": "^0.34.4" }, "peerDependencies": { "@opentelemetry/api": "^1.1.0", "@playwright/test": "^1.51.1", "babel-plugin-react-compiler": "*", "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", "sass": "^1.3.0" }, "optionalPeers": ["@opentelemetry/api", "@playwright/test", "babel-plugin-react-compiler", "sass"], "bin": { "next": "dist/bin/next" } }, "sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A=="], 1493 + 1270 1494 "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], 1271 1495 1272 1496 "node-fetch": ["node-fetch@3.3.2", "", { "dependencies": { "data-uri-to-buffer": "^4.0.0", "fetch-blob": "^3.1.4", "formdata-polyfill": "^4.0.10" } }, "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA=="], 1273 1497 1274 1498 "node-gyp-build": ["node-gyp-build@4.8.4", "", { "bin": { "node-gyp-build": "bin.js", "node-gyp-build-optional": "optional.js", "node-gyp-build-test": "build-test.js" } }, "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ=="], 1275 - 1276 - "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.1.1", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-test": "build-test.js", "node-gyp-build-optional-packages-optional": "optional.js" } }, "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw=="], 1277 1499 1278 1500 "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], 1279 1501 1280 1502 "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], 1281 1503 1282 - "normalize-range": ["normalize-range@0.1.2", "", {}, "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA=="], 1504 + "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], 1283 1505 1284 - "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], 1506 + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], 1507 + 1508 + "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], 1509 + 1510 + "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], 1511 + 1512 + "object.entries": ["object.entries@1.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-object-atoms": "^1.1.1" } }, "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw=="], 1513 + 1514 + "object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="], 1285 1515 1286 - "object-assign": ["object-assign@4.1.1", "", {}, "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="], 1516 + "object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="], 1287 1517 1288 - "object-hash": ["object-hash@3.0.0", "", {}, "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw=="], 1518 + "object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="], 1289 1519 1290 1520 "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], 1291 1521 1292 1522 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], 1293 1523 1294 1524 "optionator": ["optionator@0.9.4", "", { "dependencies": { "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", "type-check": "^0.4.0", "word-wrap": "^1.2.5" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="], 1525 + 1526 + "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], 1295 1527 1296 1528 "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], 1297 1529 ··· 1315 1547 1316 1548 "pathe": ["pathe@2.0.3", "", {}, "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w=="], 1317 1549 1550 + "pg": ["pg@8.16.3", "", { "dependencies": { "pg-connection-string": "^2.9.1", "pg-pool": "^3.10.1", "pg-protocol": "^1.10.3", "pg-types": "2.2.0", "pgpass": "1.0.5" }, "optionalDependencies": { "pg-cloudflare": "^1.2.7" }, "peerDependencies": { "pg-native": ">=3.0.1" }, "optionalPeers": ["pg-native"] }, "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw=="], 1551 + 1552 + "pg-cloudflare": ["pg-cloudflare@1.2.7", "", {}, "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg=="], 1553 + 1554 + "pg-connection-string": ["pg-connection-string@2.9.1", "", {}, "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w=="], 1555 + 1318 1556 "pg-int8": ["pg-int8@1.0.1", "", {}, "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="], 1319 1557 1558 + "pg-pool": ["pg-pool@3.10.1", "", { "peerDependencies": { "pg": ">=8.0" } }, "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg=="], 1559 + 1320 1560 "pg-protocol": ["pg-protocol@1.10.3", "", {}, "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ=="], 1321 1561 1322 1562 "pg-types": ["pg-types@2.2.0", "", { "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", "postgres-bytea": "~1.0.0", "postgres-date": "~1.0.4", "postgres-interval": "^1.1.0" } }, "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA=="], 1323 1563 1564 + "pgpass": ["pgpass@1.0.5", "", { "dependencies": { "split2": "^4.1.0" } }, "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug=="], 1565 + 1324 1566 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], 1325 1567 1326 1568 "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], 1327 - 1328 - "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], 1329 1569 1330 1570 "pino": ["pino@9.14.0", "", { "dependencies": { "@pinojs/redact": "^0.4.0", "atomic-sleep": "^1.0.0", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^2.0.0", "pino-std-serializers": "^7.0.0", "process-warning": "^5.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^4.0.1", "thread-stream": "^3.0.0" }, "bin": { "pino": "bin.js" } }, "sha512-8OEwKp5juEvb/MjpIc4hjqfgCNysrS94RIOMXYvpYCdm/jglrKEiAYmiumbmGhCvs+IcInsphYDFwqrjr7398w=="], 1331 1571 ··· 1335 1575 1336 1576 "pino-std-serializers": ["pino-std-serializers@7.0.0", "", {}, "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="], 1337 1577 1338 - "pirates": ["pirates@4.0.7", "", {}, "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA=="], 1578 + "possible-typed-array-names": ["possible-typed-array-names@1.1.0", "", {}, "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg=="], 1339 1579 1340 1580 "postcss": ["postcss@8.5.6", "", { "dependencies": { "nanoid": "^3.3.11", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg=="], 1341 1581 1342 - "postcss-calc": ["postcss-calc@10.1.1", "", { "dependencies": { "postcss-selector-parser": "^7.0.0", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.38" } }, "sha512-NYEsLHh8DgG/PRH2+G9BTuUdtf9ViS+vdoQ0YA5OQdGsfN4ztiwtDWNtBl9EKeqNMFnIu8IKZ0cLxEQ5r5KVMw=="], 1343 - 1344 - "postcss-colormin": ["postcss-colormin@7.0.5", "", { "dependencies": { "browserslist": "^4.27.0", "caniuse-api": "^3.0.0", "colord": "^2.9.3", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-ekIBP/nwzRWhEMmIxHHbXHcMdzd1HIUzBECaj5KEdLz9DVP2HzT065sEhvOx1dkLjYW7jyD0CngThx6bpFi2fA=="], 1345 - 1346 - "postcss-convert-values": ["postcss-convert-values@7.0.8", "", { "dependencies": { "browserslist": "^4.27.0", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-+XNKuPfkHTCEo499VzLMYn94TiL3r9YqRE3Ty+jP7UX4qjewUONey1t7CG21lrlTLN07GtGM8MqFVp86D4uKJg=="], 1347 - 1348 - "postcss-discard-comments": ["postcss-discard-comments@7.0.5", "", { "dependencies": { "postcss-selector-parser": "^7.1.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-IR2Eja8WfYgN5n32vEGSctVQ1+JARfu4UH8M7bgGh1bC+xI/obsPJXaBpQF7MAByvgwZinhpHpdrmXtvVVlKcQ=="], 1349 - 1350 - "postcss-discard-duplicates": ["postcss-discard-duplicates@7.0.2", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-eTonaQvPZ/3i1ASDHOKkYwAybiM45zFIc7KXils4mQmHLqIswXD9XNOKEVxtTFnsmwYzF66u4LMgSr0abDlh5w=="], 1351 - 1352 - "postcss-discard-empty": ["postcss-discard-empty@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-cFrJKZvcg/uxB6Ijr4l6qmn3pXQBna9zyrPC+sK0zjbkDUZew+6xDltSF7OeB7rAtzaaMVYSdbod+sZOCWnMOg=="], 1353 - 1354 - "postcss-discard-overridden": ["postcss-discard-overridden@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-7c3MMjjSZ/qYrx3uc1940GSOzN1Iqjtlqe8uoSg+qdVPYyRb0TILSqqmtlSFuE4mTDECwsm397Ya7iXGzfF7lg=="], 1355 - 1356 - "postcss-import": ["postcss-import@15.1.0", "", { "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "peerDependencies": { "postcss": "^8.0.0" } }, "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew=="], 1357 - 1358 - "postcss-js": ["postcss-js@4.1.0", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw=="], 1359 - 1360 - "postcss-load-config": ["postcss-load-config@6.0.1", "", { "dependencies": { "lilconfig": "^3.1.1" }, "peerDependencies": { "jiti": ">=1.21.0", "postcss": ">=8.0.9", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["jiti", "postcss", "tsx", "yaml"] }, "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g=="], 1361 - 1362 - "postcss-merge-longhand": ["postcss-merge-longhand@7.0.5", "", { "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^7.0.5" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-Kpu5v4Ys6QI59FxmxtNB/iHUVDn9Y9sYw66D6+SZoIk4QTz1prC4aYkhIESu+ieG1iylod1f8MILMs1Em3mmIw=="], 1363 - 1364 - "postcss-merge-rules": ["postcss-merge-rules@7.0.7", "", { "dependencies": { "browserslist": "^4.27.0", "caniuse-api": "^3.0.0", "cssnano-utils": "^5.0.1", "postcss-selector-parser": "^7.1.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-njWJrd/Ms6XViwowaaCc+/vqhPG3SmXn725AGrnl+BgTuRPEacjiLEaGq16J6XirMJbtKkTwnt67SS+e2WGoew=="], 1365 - 1366 - "postcss-minify-font-values": ["postcss-minify-font-values@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-2m1uiuJeTplll+tq4ENOQSzB8LRnSUChBv7oSyFLsJRtUgAAJGP6LLz0/8lkinTgxrmJSPOEhgY1bMXOQ4ZXhQ=="], 1367 - 1368 - "postcss-minify-gradients": ["postcss-minify-gradients@7.0.1", "", { "dependencies": { "colord": "^2.9.3", "cssnano-utils": "^5.0.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-X9JjaysZJwlqNkJbUDgOclyG3jZEpAMOfof6PUZjPnPrePnPG62pS17CjdM32uT1Uq1jFvNSff9l7kNbmMSL2A=="], 1369 - 1370 - "postcss-minify-params": ["postcss-minify-params@7.0.5", "", { "dependencies": { "browserslist": "^4.27.0", "cssnano-utils": "^5.0.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-FGK9ky02h6Ighn3UihsyeAH5XmLEE2MSGH5Tc4tXMFtEDx7B+zTG6hD/+/cT+fbF7PbYojsmmWjyTwFwW1JKQQ=="], 1371 - 1372 - "postcss-minify-selectors": ["postcss-minify-selectors@7.0.5", "", { "dependencies": { "cssesc": "^3.0.0", "postcss-selector-parser": "^7.1.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-x2/IvofHcdIrAm9Q+p06ZD1h6FPcQ32WtCRVodJLDR+WMn8EVHI1kvLxZuGKz/9EY5nAmI6lIQIrpo4tBy5+ug=="], 1373 - 1374 - "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], 1375 - 1376 - "postcss-normalize-charset": ["postcss-normalize-charset@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-sn413ofhSQHlZFae//m9FTOfkmiZ+YQXsbosqOWRiVQncU2BA3daX3n0VF3cG6rGLSFVc5Di/yns0dFfh8NFgQ=="], 1377 - 1378 - "postcss-normalize-display-values": ["postcss-normalize-display-values@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-E5nnB26XjSYz/mGITm6JgiDpAbVuAkzXwLzRZtts19jHDUBFxZ0BkXAehy0uimrOjYJbocby4FVswA/5noOxrQ=="], 1379 - 1380 - "postcss-normalize-positions": ["postcss-normalize-positions@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-pB/SzrIP2l50ZIYu+yQZyMNmnAcwyYb9R1fVWPRxm4zcUFCY2ign7rcntGFuMXDdd9L2pPNUgoODDk91PzRZuQ=="], 1381 - 1382 - "postcss-normalize-repeat-style": ["postcss-normalize-repeat-style@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-NsSQJ8zj8TIDiF0ig44Byo3Jk9e4gNt9x2VIlJudnQQ5DhWAHJPF4Tr1ITwyHio2BUi/I6Iv0HRO7beHYOloYQ=="], 1383 - 1384 - "postcss-normalize-string": ["postcss-normalize-string@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-QByrI7hAhsoze992kpbMlJSbZ8FuCEc1OT9EFbZ6HldXNpsdpZr+YXC5di3UEv0+jeZlHbZcoCADgb7a+lPmmQ=="], 1385 - 1386 - "postcss-normalize-timing-functions": ["postcss-normalize-timing-functions@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-bHifyuuSNdKKsnNJ0s8fmfLMlvsQwYVxIoUBnowIVl2ZAdrkYQNGVB4RxjfpvkMjipqvbz0u7feBZybkl/6NJg=="], 1387 - 1388 - "postcss-normalize-unicode": ["postcss-normalize-unicode@7.0.5", "", { "dependencies": { "browserslist": "^4.27.0", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-X6BBwiRxVaFHrb2WyBMddIeB5HBjJcAaUHyhLrM2FsxSq5TFqcHSsK7Zu1otag+o0ZphQGJewGH1tAyrD0zX1Q=="], 1389 - 1390 - "postcss-normalize-url": ["postcss-normalize-url@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-sUcD2cWtyK1AOL/82Fwy1aIVm/wwj5SdZkgZ3QiUzSzQQofrbq15jWJ3BA7Z+yVRwamCjJgZJN0I9IS7c6tgeQ=="], 1391 - 1392 - "postcss-normalize-whitespace": ["postcss-normalize-whitespace@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-vsbgFHMFQrJBJKrUFJNZ2pgBeBkC2IvvoHjz1to0/0Xk7sII24T0qFOiJzG6Fu3zJoq/0yI4rKWi7WhApW+EFA=="], 1393 - 1394 - "postcss-ordered-values": ["postcss-ordered-values@7.0.2", "", { "dependencies": { "cssnano-utils": "^5.0.1", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-AMJjt1ECBffF7CEON/Y0rekRLS6KsePU6PRP08UqYW4UGFRnTXNrByUzYK1h8AC7UWTZdQ9O3Oq9kFIhm0SFEw=="], 1395 - 1396 - "postcss-reduce-initial": ["postcss-reduce-initial@7.0.5", "", { "dependencies": { "browserslist": "^4.27.0", "caniuse-api": "^3.0.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-RHagHLidG8hTZcnr4FpyMB2jtgd/OcyAazjMhoy5qmWJOx1uxKh4ntk0Pb46ajKM0rkf32lRH4C8c9qQiPR6IA=="], 1397 - 1398 - "postcss-reduce-transforms": ["postcss-reduce-transforms@7.0.1", "", { "dependencies": { "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-MhyEbfrm+Mlp/36hvZ9mT9DaO7dbncU0CvWI8V93LRkY6IYlu38OPg3FObnuKTUxJ4qA8HpurdQOo5CyqqO76g=="], 1399 - 1400 - "postcss-selector-parser": ["postcss-selector-parser@6.1.2", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg=="], 1401 - 1402 - "postcss-svgo": ["postcss-svgo@7.1.0", "", { "dependencies": { "postcss-value-parser": "^4.2.0", "svgo": "^4.0.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-KnAlfmhtoLz6IuU3Sij2ycusNs4jPW+QoFE5kuuUOK8awR6tMxZQrs5Ey3BUz7nFCzT3eqyFgqkyrHiaU2xx3w=="], 1403 - 1404 - "postcss-unique-selectors": ["postcss-unique-selectors@7.0.4", "", { "dependencies": { "postcss-selector-parser": "^7.1.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-pmlZjsmEAG7cHd7uK3ZiNSW6otSZ13RHuZ/4cDN/bVglS5EpF2r2oxY99SuOHa8m7AWoBCelTS3JPpzsIs8skQ=="], 1405 - 1406 - "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], 1407 - 1408 1582 "postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="], 1409 1583 1410 1584 "postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="], ··· 1417 1591 1418 1592 "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], 1419 1593 1420 - "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], 1421 - 1422 1594 "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], 1423 1595 1424 1596 "promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="], 1425 1597 1426 - "proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="], 1598 + "prop-types": ["prop-types@15.8.1", "", { "dependencies": { "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.13.1" } }, "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg=="], 1427 1599 1428 1600 "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], 1429 1601 ··· 1433 1605 1434 1606 "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], 1435 1607 1436 - "react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], 1608 + "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="], 1437 1609 1438 - "react-dom": ["react-dom@19.0.0", "", { "dependencies": { "scheduler": "^0.25.0" }, "peerDependencies": { "react": "^19.0.0" } }, "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ=="], 1610 + "react-dom": ["react-dom@19.2.0", "", { "dependencies": { "scheduler": "^0.27.0" }, "peerDependencies": { "react": "^19.2.0" } }, "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ=="], 1439 1611 1440 - "react-hook-form": ["react-hook-form@7.66.1", "", { "peerDependencies": { "react": "^16.8.0 || ^17 || ^18 || ^19" } }, "sha512-2KnjpgG2Rhbi+CIiIBQQ9Df6sMGH5ExNyFl4Hw9qO7pIqMBR8Bvu9RQyjl3JM4vehzCh9soiNUM/xYMswb2EiA=="], 1612 + "react-is": ["react-is@16.13.1", "", {}, "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="], 1613 + 1614 + "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="], 1441 1615 1442 1616 "react-remove-scroll": ["react-remove-scroll@2.7.1", "", { "dependencies": { "react-remove-scroll-bar": "^2.3.7", "react-style-singleton": "^2.2.3", "tslib": "^2.1.0", "use-callback-ref": "^1.3.3", "use-sidecar": "^1.1.3" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA=="], 1443 1617 ··· 1445 1619 1446 1620 "react-style-singleton": ["react-style-singleton@2.2.3", "", { "dependencies": { "get-nonce": "^1.0.0", "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ=="], 1447 1621 1448 - "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], 1449 - 1450 - "readable-stream": ["readable-stream@4.7.0", "", { "dependencies": { "abort-controller": "^3.0.0", "buffer": "^6.0.3", "events": "^3.3.0", "process": "^0.11.10", "string_decoder": "^1.3.0" } }, "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg=="], 1451 - 1452 1622 "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], 1453 1623 1454 1624 "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], 1455 1625 1456 1626 "recast": ["recast@0.23.11", "", { "dependencies": { "ast-types": "^0.16.1", "esprima": "~4.0.0", "source-map": "~0.6.1", "tiny-invariant": "^1.3.3", "tslib": "^2.0.1" } }, "sha512-YTUo+Flmw4ZXiWfQKGcwwc11KnoRAYgzAE2E7mXKCjSviTKShtxBsN6YUUBB2gtaBzKzeKunxhUwNHQuRryhWA=="], 1627 + 1628 + "reflect.getprototypeof": ["reflect.getprototypeof@1.0.10", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.7", "get-proto": "^1.0.1", "which-builtin-type": "^1.2.1" } }, "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw=="], 1629 + 1630 + "regexp.prototype.flags": ["regexp.prototype.flags@1.5.4", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-errors": "^1.3.0", "get-proto": "^1.0.1", "gopd": "^1.2.0", "set-function-name": "^2.0.2" } }, "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA=="], 1457 1631 1458 1632 "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], 1459 1633 ··· 1469 1643 1470 1644 "rimraf": ["rimraf@6.1.2", "", { "dependencies": { "glob": "^13.0.0", "package-json-from-dist": "^1.0.1" }, "bin": { "rimraf": "dist/esm/bin.mjs" } }, "sha512-cFCkPslJv7BAXJsYlK1dZsbP8/ZNLkCAQ0bi1hf5EKX2QHegmDFEFA6QhuYJlk7UDdc+02JjO80YSOrWPpw06g=="], 1471 1645 1472 - "rollup": ["rollup@4.53.3", "", { "dependencies": { "@types/estree": "1.0.8" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.53.3", "@rollup/rollup-android-arm64": "4.53.3", "@rollup/rollup-darwin-arm64": "4.53.3", "@rollup/rollup-darwin-x64": "4.53.3", "@rollup/rollup-freebsd-arm64": "4.53.3", "@rollup/rollup-freebsd-x64": "4.53.3", "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", "@rollup/rollup-linux-arm-musleabihf": "4.53.3", "@rollup/rollup-linux-arm64-gnu": "4.53.3", "@rollup/rollup-linux-arm64-musl": "4.53.3", "@rollup/rollup-linux-loong64-gnu": "4.53.3", "@rollup/rollup-linux-ppc64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-gnu": "4.53.3", "@rollup/rollup-linux-riscv64-musl": "4.53.3", "@rollup/rollup-linux-s390x-gnu": "4.53.3", "@rollup/rollup-linux-x64-gnu": "4.53.3", "@rollup/rollup-linux-x64-musl": "4.53.3", "@rollup/rollup-openharmony-arm64": "4.53.3", "@rollup/rollup-win32-arm64-msvc": "4.53.3", "@rollup/rollup-win32-ia32-msvc": "4.53.3", "@rollup/rollup-win32-x64-gnu": "4.53.3", "@rollup/rollup-win32-x64-msvc": "4.53.3", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA=="], 1646 + "rolldown": ["rolldown@1.0.0-beta.50", "", { "dependencies": { "@oxc-project/types": "=0.97.0", "@rolldown/pluginutils": "1.0.0-beta.50" }, "optionalDependencies": { "@rolldown/binding-android-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-arm64": "1.0.0-beta.50", "@rolldown/binding-darwin-x64": "1.0.0-beta.50", "@rolldown/binding-freebsd-x64": "1.0.0-beta.50", "@rolldown/binding-linux-arm-gnueabihf": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-arm64-musl": "1.0.0-beta.50", "@rolldown/binding-linux-x64-gnu": "1.0.0-beta.50", "@rolldown/binding-linux-x64-musl": "1.0.0-beta.50", "@rolldown/binding-openharmony-arm64": "1.0.0-beta.50", "@rolldown/binding-wasm32-wasi": "1.0.0-beta.50", "@rolldown/binding-win32-arm64-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-ia32-msvc": "1.0.0-beta.50", "@rolldown/binding-win32-x64-msvc": "1.0.0-beta.50" }, "bin": { "rolldown": "bin/cli.mjs" } }, "sha512-JFULvCNl/anKn99eKjOSEubi0lLmNqQDAjyEMME2T4CwezUDL0i6t1O9xZsu2OMehPnV2caNefWpGF+8TnzB6A=="], 1473 1647 1474 1648 "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], 1475 1649 1476 - "safe-buffer": ["safe-buffer@5.2.1", "", {}, "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="], 1650 + "safe-array-concat": ["safe-array-concat@1.1.3", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "get-intrinsic": "^1.2.6", "has-symbols": "^1.1.0", "isarray": "^2.0.5" } }, "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q=="], 1651 + 1652 + "safe-push-apply": ["safe-push-apply@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "isarray": "^2.0.5" } }, "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA=="], 1653 + 1654 + "safe-regex-test": ["safe-regex-test@1.1.0", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "is-regex": "^1.2.1" } }, "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw=="], 1477 1655 1478 1656 "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], 1479 1657 1480 1658 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], 1481 1659 1482 - "sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], 1483 - 1484 - "scheduler": ["scheduler@0.25.0", "", {}, "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA=="], 1660 + "scheduler": ["scheduler@0.27.0", "", {}, "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="], 1485 1661 1486 1662 "secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="], 1487 1663 ··· 1491 1667 1492 1668 "seroval-plugins": ["seroval-plugins@1.4.0", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-zir1aWzoiax6pbBVjoYVd0O1QQXgIL3eVGBMsBsNmM8Ukq90yGaWlfx0AB9dTS8GPqrOrbXn79vmItCUP9U3BQ=="], 1493 1669 1670 + "set-function-length": ["set-function-length@1.2.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "function-bind": "^1.1.2", "get-intrinsic": "^1.2.4", "gopd": "^1.0.1", "has-property-descriptors": "^1.0.2" } }, "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg=="], 1671 + 1672 + "set-function-name": ["set-function-name@2.0.2", "", { "dependencies": { "define-data-property": "^1.1.4", "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", "has-property-descriptors": "^1.0.2" } }, "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ=="], 1673 + 1674 + "set-proto": ["set-proto@1.0.0", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0" } }, "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw=="], 1675 + 1676 + "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], 1677 + 1494 1678 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], 1495 1679 1496 1680 "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], 1497 1681 1498 1682 "shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="], 1499 1683 1684 + "side-channel": ["side-channel@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3", "side-channel-list": "^1.0.0", "side-channel-map": "^1.0.1", "side-channel-weakmap": "^1.0.2" } }, "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw=="], 1685 + 1686 + "side-channel-list": ["side-channel-list@1.0.0", "", { "dependencies": { "es-errors": "^1.3.0", "object-inspect": "^1.13.3" } }, "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA=="], 1687 + 1688 + "side-channel-map": ["side-channel-map@1.0.1", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3" } }, "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA=="], 1689 + 1690 + "side-channel-weakmap": ["side-channel-weakmap@1.0.2", "", { "dependencies": { "call-bound": "^1.0.2", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.5", "object-inspect": "^1.13.3", "side-channel-map": "^1.0.1" } }, "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A=="], 1691 + 1500 1692 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], 1501 1693 1502 1694 "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], ··· 1513 1705 1514 1706 "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], 1515 1707 1708 + "stable-hash": ["stable-hash@0.0.5", "", {}, "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA=="], 1709 + 1710 + "stop-iteration-iterator": ["stop-iteration-iterator@1.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "internal-slot": "^1.1.0" } }, "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ=="], 1711 + 1516 1712 "string-width": ["string-width@7.2.0", "", { "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", "strip-ansi": "^7.1.0" } }, "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ=="], 1517 1713 1518 - "string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="], 1714 + "string.prototype.includes": ["string.prototype.includes@2.0.1", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.3" } }, "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg=="], 1715 + 1716 + "string.prototype.matchall": ["string.prototype.matchall@4.0.12", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-abstract": "^1.23.6", "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", "get-intrinsic": "^1.2.6", "gopd": "^1.2.0", "has-symbols": "^1.1.0", "internal-slot": "^1.1.0", "regexp.prototype.flags": "^1.5.3", "set-function-name": "^2.0.2", "side-channel": "^1.1.0" } }, "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA=="], 1717 + 1718 + "string.prototype.repeat": ["string.prototype.repeat@1.0.0", "", { "dependencies": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" } }, "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w=="], 1719 + 1720 + "string.prototype.trim": ["string.prototype.trim@1.2.10", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-data-property": "^1.1.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-object-atoms": "^1.0.0", "has-property-descriptors": "^1.0.2" } }, "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA=="], 1721 + 1722 + "string.prototype.trimend": ["string.prototype.trimend@1.0.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.2", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ=="], 1723 + 1724 + "string.prototype.trimstart": ["string.prototype.trimstart@1.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg=="], 1519 1725 1520 1726 "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], 1521 1727 1522 - "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], 1728 + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], 1523 1729 1524 - "stylehacks": ["stylehacks@7.0.7", "", { "dependencies": { "browserslist": "^4.27.0", "postcss-selector-parser": "^7.1.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-bJkD0JkEtbRrMFtwgpJyBbFIwfDDONQ1Ov3sDLZQP8HuJ73kBOyx66H4bOcAbVWmnfLdvQ0AJwXxOMkpujcO6g=="], 1730 + "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], 1525 1731 1526 - "sucrase": ["sucrase@3.35.1", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", "lines-and-columns": "^1.1.6", "mz": "^2.7.0", "pirates": "^4.0.1", "tinyglobby": "^0.2.11", "ts-interface-checker": "^0.1.9" }, "bin": { "sucrase": "bin/sucrase", "sucrase-node": "bin/sucrase-node" } }, "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw=="], 1732 + "styled-jsx": ["styled-jsx@5.1.6", "", { "dependencies": { "client-only": "0.0.1" }, "peerDependencies": { "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" } }, "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA=="], 1527 1733 1528 1734 "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], 1529 1735 1530 1736 "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], 1531 1737 1532 - "svgo": ["svgo@4.0.0", "", { "dependencies": { "commander": "^11.1.0", "css-select": "^5.1.0", "css-tree": "^3.0.1", "css-what": "^6.1.0", "csso": "^5.0.5", "picocolors": "^1.1.1", "sax": "^1.4.1" }, "bin": "./bin/svgo.js" }, "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw=="], 1738 + "tailwind-merge": ["tailwind-merge@3.4.0", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="], 1533 1739 1534 - "tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], 1740 + "tailwindcss": ["tailwindcss@4.1.17", "", {}, "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q=="], 1535 1741 1536 - "tailwindcss": ["tailwindcss@3.4.18", "", { "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", "chokidar": "^3.6.0", "didyoumean": "^1.2.2", "dlv": "^1.1.3", "fast-glob": "^3.3.2", "glob-parent": "^6.0.2", "is-glob": "^4.0.3", "jiti": "^1.21.7", "lilconfig": "^3.1.3", "micromatch": "^4.0.8", "normalize-path": "^3.0.0", "object-hash": "^3.0.0", "picocolors": "^1.1.1", "postcss": "^8.4.47", "postcss-import": "^15.1.0", "postcss-js": "^4.0.1", "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", "postcss-nested": "^6.2.0", "postcss-selector-parser": "^6.1.2", "resolve": "^1.22.8", "sucrase": "^3.35.0" }, "bin": { "tailwind": "lib/cli.js", "tailwindcss": "lib/cli.js" } }, "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ=="], 1537 - 1538 - "tailwindcss-animate": ["tailwindcss-animate@1.0.7", "", { "peerDependencies": { "tailwindcss": ">=3.0.0 || insiders" } }, "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA=="], 1742 + "tapable": ["tapable@2.3.0", "", {}, "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg=="], 1539 1743 1540 1744 "tar": ["tar@7.5.2", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg=="], 1541 1745 ··· 1543 1747 1544 1748 "temporal-spec": ["temporal-spec@0.3.0", "", {}, "sha512-n+noVpIqz4hYgFSMOSiINNOUOMFtV5cZQNCmmszA6GiVFVRt3G7AqVyhXjhCSmowvQn+NsGn+jMDMKJYHd3bSQ=="], 1545 1749 1546 - "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], 1547 - 1548 - "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], 1549 - 1550 1750 "thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="], 1551 1751 1552 1752 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], ··· 1559 1759 1560 1760 "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], 1561 1761 1562 - "ts-interface-checker": ["ts-interface-checker@0.1.13", "", {}, "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA=="], 1762 + "tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="], 1563 1763 1564 1764 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], 1565 1765 1566 - "tsx": ["tsx@4.20.6", "", { "dependencies": { "esbuild": "~0.25.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-ytQKuwgmrrkDTFP4LjR0ToE2nqgy886GpvRSpU0JAnrdBYppuY5rLkRUYPU1yCryb24SsKBTL/hlDQAEFVwtZg=="], 1766 + "tsx": ["tsx@4.21.0", "", { "dependencies": { "esbuild": "~0.27.0", "get-tsconfig": "^4.7.5" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "bin": { "tsx": "dist/cli.mjs" } }, "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw=="], 1567 1767 1568 1768 "turbo": ["turbo@2.6.1", "", { "optionalDependencies": { "turbo-darwin-64": "2.6.1", "turbo-darwin-arm64": "2.6.1", "turbo-linux-64": "2.6.1", "turbo-linux-arm64": "2.6.1", "turbo-windows-64": "2.6.1", "turbo-windows-arm64": "2.6.1" }, "bin": { "turbo": "bin/turbo" } }, "sha512-qBwXXuDT3rA53kbNafGbT5r++BrhRgx3sAo0cHoDAeG9g1ItTmUMgltz3Hy7Hazy1ODqNpR+C7QwqL6DYB52yA=="], 1569 1769 ··· 1579 1779 1580 1780 "turbo-windows-arm64": ["turbo-windows-arm64@2.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-7w+AD5vJp3R+FB0YOj1YJcNcOOvBior7bcHTodqp90S3x3bLgpr7tE6xOea1e8JkP7GK6ciKVUpQvV7psiwU5Q=="], 1581 1781 1782 + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], 1783 + 1582 1784 "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], 1583 1785 1584 1786 "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], 1585 1787 1788 + "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], 1789 + 1790 + "typed-array-byte-length": ["typed-array-byte-length@1.0.3", "", { "dependencies": { "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.14" } }, "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg=="], 1791 + 1792 + "typed-array-byte-offset": ["typed-array-byte-offset@1.0.4", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "for-each": "^0.3.3", "gopd": "^1.2.0", "has-proto": "^1.2.0", "is-typed-array": "^1.1.15", "reflect.getprototypeof": "^1.0.9" } }, "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ=="], 1793 + 1794 + "typed-array-length": ["typed-array-length@1.0.7", "", { "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", "is-typed-array": "^1.1.13", "possible-typed-array-names": "^1.0.0", "reflect.getprototypeof": "^1.0.6" } }, "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg=="], 1795 + 1586 1796 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], 1587 1797 1588 1798 "typescript-eslint": ["typescript-eslint@8.48.0", "", { "dependencies": { "@typescript-eslint/eslint-plugin": "8.48.0", "@typescript-eslint/parser": "8.48.0", "@typescript-eslint/typescript-estree": "8.48.0", "@typescript-eslint/utils": "8.48.0" }, "peerDependencies": { "eslint": "^8.57.0 || ^9.0.0", "typescript": ">=4.8.4 <6.0.0" } }, "sha512-fcKOvQD9GUn3Xw63EgiDqhvWJ5jsyZUaekl3KVpGsDJnN46WJTe3jWxtQP9lMZm1LJNkFLlTaWAxK2vUQR+cqw=="], 1589 1799 1590 1800 "uint8arrays": ["uint8arrays@3.0.0", "", { "dependencies": { "multiformats": "^9.4.2" } }, "sha512-HRCx0q6O9Bfbp+HHSfQQKD7wU70+lydKVt4EghkdOvlK/NlrF90z+eXV34mUd48rNvVJXwkrMSPpCATkct8fJA=="], 1801 + 1802 + "unbox-primitive": ["unbox-primitive@1.1.0", "", { "dependencies": { "call-bound": "^1.0.3", "has-bigints": "^1.0.2", "has-symbols": "^1.1.0", "which-boxed-primitive": "^1.1.1" } }, "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw=="], 1591 1803 1592 1804 "undici": ["undici@6.22.0", "", {}, "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw=="], 1593 1805 1594 1806 "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], 1807 + 1808 + "unicode-segmenter": ["unicode-segmenter@0.14.1", "", {}, "sha512-yHedxlEpUyD+u1UE8qAuCMXVdMLn7yUdlmd8WN7FGmO1ICnpE7LJfnmuXBB+T0zkie3qHsy8fSucqceI/MylOg=="], 1595 1809 1596 1810 "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], 1597 1811 1598 1812 "unplugin": ["unplugin@2.3.11", "", { "dependencies": { "@jridgewell/remapping": "^2.3.5", "acorn": "^8.15.0", "picomatch": "^4.0.3", "webpack-virtual-modules": "^0.6.2" } }, "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww=="], 1599 1813 1814 + "unrs-resolver": ["unrs-resolver@1.11.1", "", { "dependencies": { "napi-postinstall": "^0.3.0" }, "optionalDependencies": { "@unrs/resolver-binding-android-arm-eabi": "1.11.1", "@unrs/resolver-binding-android-arm64": "1.11.1", "@unrs/resolver-binding-darwin-arm64": "1.11.1", "@unrs/resolver-binding-darwin-x64": "1.11.1", "@unrs/resolver-binding-freebsd-x64": "1.11.1", "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", "@unrs/resolver-binding-linux-x64-musl": "1.11.1", "@unrs/resolver-binding-wasm32-wasi": "1.11.1", "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" } }, "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg=="], 1815 + 1600 1816 "update-browserslist-db": ["update-browserslist-db@1.1.4", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A=="], 1601 1817 1602 1818 "uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="], ··· 1607 1823 1608 1824 "use-sync-external-store": ["use-sync-external-store@1.6.0", "", { "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w=="], 1609 1825 1610 - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], 1611 - 1612 - "vite": ["vite@6.4.1", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", "picomatch": "^4.0.2", "postcss": "^8.5.3", "rollup": "^4.34.9", "tinyglobby": "^0.2.13" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", "jiti": ">=1.21.0", "less": "*", "lightningcss": "^1.21.0", "sass": "*", "sass-embedded": "*", "stylus": "*", "sugarss": "*", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g=="], 1826 + "vite": ["rolldown-vite@7.2.5", "", { "dependencies": { "@oxc-project/runtime": "0.97.0", "fdir": "^6.5.0", "lightningcss": "^1.30.2", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rolldown": "1.0.0-beta.50", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "esbuild": "^0.25.0", "jiti": ">=1.21.0", "less": "^4.0.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "esbuild", "jiti", "less", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA=="], 1613 1827 1614 1828 "vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], 1615 1829 ··· 1621 1835 1622 1836 "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], 1623 1837 1838 + "web": ["web@workspace:apps/web"], 1839 + 1624 1840 "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], 1625 1841 1626 1842 "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], 1627 1843 1628 1844 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], 1629 1845 1846 + "which-boxed-primitive": ["which-boxed-primitive@1.1.1", "", { "dependencies": { "is-bigint": "^1.1.0", "is-boolean-object": "^1.2.1", "is-number-object": "^1.1.1", "is-string": "^1.1.1", "is-symbol": "^1.1.1" } }, "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA=="], 1847 + 1848 + "which-builtin-type": ["which-builtin-type@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "function.prototype.name": "^1.1.6", "has-tostringtag": "^1.0.2", "is-async-function": "^2.0.0", "is-date-object": "^1.1.0", "is-finalizationregistry": "^1.1.0", "is-generator-function": "^1.0.10", "is-regex": "^1.2.1", "is-weakref": "^1.0.2", "isarray": "^2.0.5", "which-boxed-primitive": "^1.1.0", "which-collection": "^1.0.2", "which-typed-array": "^1.1.16" } }, "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q=="], 1849 + 1850 + "which-collection": ["which-collection@1.0.2", "", { "dependencies": { "is-map": "^2.0.3", "is-set": "^2.0.3", "is-weakmap": "^2.0.2", "is-weakset": "^2.0.3" } }, "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw=="], 1851 + 1852 + "which-typed-array": ["which-typed-array@1.1.19", "", { "dependencies": { "available-typed-arrays": "^1.0.7", "call-bind": "^1.0.8", "call-bound": "^1.0.4", "for-each": "^0.3.5", "get-proto": "^1.0.1", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2" } }, "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw=="], 1853 + 1630 1854 "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], 1631 1855 1632 1856 "wrap-ansi": ["wrap-ansi@9.0.2", "", { "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", "strip-ansi": "^7.1.0" } }, "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww=="], ··· 1653 1877 1654 1878 "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], 1655 1879 1656 - "@atproto-labs/simple-store-memory/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 1880 + "zod-validation-error": ["zod-validation-error@4.0.2", "", { "peerDependencies": { "zod": "^3.25.0 || ^4.0.0" } }, "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ=="], 1881 + 1882 + "@atcute/cbor/@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 1657 1883 1658 - "@atproto/common/@atproto/common-web": ["@atproto/common-web@0.4.3", "", { "dependencies": { "graphemer": "^1.4.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "zod": "^3.23.8" } }, "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg=="], 1884 + "@atcute/cid/@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 1885 + 1886 + "@atcute/crypto/@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 1887 + 1888 + "@atcute/multibase/@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 1659 1889 1660 - "@atproto/common/pino": ["pino@8.21.0", "", { "dependencies": { "atomic-sleep": "^1.0.0", "fast-redact": "^3.1.1", "on-exit-leak-free": "^2.1.0", "pino-abstract-transport": "^1.2.0", "pino-std-serializers": "^6.0.0", "process-warning": "^3.0.0", "quick-format-unescaped": "^4.0.3", "real-require": "^0.2.0", "safe-stable-stringify": "^2.3.1", "sonic-boom": "^3.7.0", "thread-stream": "^2.6.0" }, "bin": { "pino": "bin.js" } }, "sha512-ip4qdzjkAyDDZklUaZkcRFb2iA118H9SgRh8yzTkSQK8HilsOJF7rSY8HoW5+I0M46AZgX/pxbprf2vvzQCE0Q=="], 1890 + "@atcute/oauth-browser-client/@atcute/identity-resolver": ["@atcute/identity-resolver@1.2.0", "", { "dependencies": { "@atcute/lexicons": "^1.2.5", "@atcute/util-fetch": "^1.0.4", "@badrap/valita": "^0.4.6" }, "peerDependencies": { "@atcute/identity": "^1.0.0" } }, "sha512-5UbSJfdV3JIkF8ksXz7g4nKBWasf2wROvzM66cfvTIWydWFO6/oS1KZd+zo9Eokje5Scf5+jsY9ZfgVARLepXg=="], 1661 1891 1662 - "@atproto/lexicon/@atproto/common-web": ["@atproto/common-web@0.4.3", "", { "dependencies": { "graphemer": "^1.4.0", "multiformats": "^9.9.0", "uint8arrays": "3.0.0", "zod": "^3.23.8" } }, "sha512-nRDINmSe4VycJzPo6fP/hEltBcULFxt9Kw7fQk6405FyAWZiTluYHlXOnU7GkQfeUK44OENG1qFTBcmCJ7e8pg=="], 1892 + "@atcute/xrpc-server/@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 1663 1893 1664 - "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1894 + "@atproto-labs/simple-store-memory/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 1665 1895 1666 - "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], 1896 + "@atproto/lex-data/@atproto/syntax": ["@atproto/syntax@0.4.2", "", {}, "sha512-X9XSRPinBy/0VQ677j8VXlBsYSsUXaiqxWVpGGxJYsAhugdQRb0jqaVKJFtm6RskeNkV6y9xclSUi9UYG/COrA=="], 1897 + 1898 + "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1667 1899 1668 1900 "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1669 1901 ··· 1671 1903 1672 1904 "@cookware/database/@libsql/client": ["@libsql/client@0.15.15", "", { "dependencies": { "@libsql/core": "^0.15.14", "@libsql/hrana-client": "^0.7.0", "js-base64": "^3.7.5", "libsql": "^0.5.22", "promise-limit": "^2.7.0" } }, "sha512-twC0hQxPNHPKfeOv3sNT6u2pturQjLcI+CnpTM0SjRpocEGgfiZ7DWKXLNnsothjyJmDqEsBQJ5ztq9Wlu470w=="], 1673 1905 1674 - "@cookware/web/@atcute/bluesky": ["@atcute/bluesky@1.0.15", "", { "peerDependencies": { "@atcute/client": "^1.0.0 || ^2.0.0" } }, "sha512-+EFiybmKQ97aBAgtaD+cKRJER5AMn3cZMkEwEg/pDdWyzxYJ9m1UgemmLdTgI8VrxPufKqdXS2nl7uO7TY6BPA=="], 1675 - 1676 - "@cookware/web/typescript": ["typescript@5.6.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw=="], 1906 + "@cookware/tsconfig/@types/bun": ["@types/bun@1.3.4", "", { "dependencies": { "bun-types": "1.3.4" } }, "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA=="], 1677 1907 1678 1908 "@esbuild-kit/core-utils/esbuild": ["esbuild@0.18.20", "", { "optionalDependencies": { "@esbuild/android-arm": "0.18.20", "@esbuild/android-arm64": "0.18.20", "@esbuild/android-x64": "0.18.20", "@esbuild/darwin-arm64": "0.18.20", "@esbuild/darwin-x64": "0.18.20", "@esbuild/freebsd-arm64": "0.18.20", "@esbuild/freebsd-x64": "0.18.20", "@esbuild/linux-arm": "0.18.20", "@esbuild/linux-arm64": "0.18.20", "@esbuild/linux-ia32": "0.18.20", "@esbuild/linux-loong64": "0.18.20", "@esbuild/linux-mips64el": "0.18.20", "@esbuild/linux-ppc64": "0.18.20", "@esbuild/linux-riscv64": "0.18.20", "@esbuild/linux-s390x": "0.18.20", "@esbuild/linux-x64": "0.18.20", "@esbuild/netbsd-x64": "0.18.20", "@esbuild/openbsd-x64": "0.18.20", "@esbuild/sunos-x64": "0.18.20", "@esbuild/win32-arm64": "0.18.20", "@esbuild/win32-ia32": "0.18.20", "@esbuild/win32-x64": "0.18.20" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA=="], 1679 1909 ··· 1687 1917 1688 1918 "@inquirer/core/wrap-ansi": ["wrap-ansi@6.2.0", "", { "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" } }, "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA=="], 1689 1919 1920 + "@next/eslint-plugin-next/fast-glob": ["fast-glob@3.3.1", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" } }, "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg=="], 1921 + 1690 1922 "@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], 1691 1923 1692 1924 "@opentelemetry/instrumentation-http/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.57.1", "", { "dependencies": { "@opentelemetry/api-logs": "0.57.1", "@types/shimmer": "^1.2.0", "import-in-the-middle": "^1.8.1", "require-in-the-middle": "^7.1.1", "semver": "^7.5.2", "shimmer": "^1.2.1" }, "peerDependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-SgHEKXoVxOjc20ZYusPG3Fh+RLIZTSa4x8QtD3NfgAUDyqdFFS9W1F2ZVbZkqDCdyMcQG02Ok4duUGLHJXHgbA=="], ··· 1695 1927 1696 1928 "@opentelemetry/instrumentation-pg/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.27.0", "", {}, "sha512-sAay1RrB+ONOem0OZanAR1ZI/k7yDpnOQSQmTMuGImUQb2y8EbSaCJ94FQluM74xoU03vlb2d2U90hZluL6nQg=="], 1697 1929 1930 + "@opentelemetry/instrumentation-pg/@types/pg": ["@types/pg@8.6.1", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w=="], 1931 + 1698 1932 "@opentelemetry/resources/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], 1699 1933 1700 1934 "@opentelemetry/sdk-trace-base/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], ··· 1703 1937 1704 1938 "@radix-ui/react-arrow/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], 1705 1939 1706 - "@radix-ui/react-collapsible/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], 1707 - 1708 - "@radix-ui/react-collapsible/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], 1709 - 1710 1940 "@radix-ui/react-collection/@radix-ui/react-context": ["@radix-ui/react-context@1.1.2", "", { "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA=="], 1711 1941 1712 1942 "@radix-ui/react-collection/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], ··· 1751 1981 1752 1982 "@radix-ui/react-visually-hidden/@radix-ui/react-primitive": ["@radix-ui/react-primitive@2.1.3", "", { "dependencies": { "@radix-ui/react-slot": "1.2.3" }, "peerDependencies": { "@types/react": "*", "@types/react-dom": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react", "@types/react-dom"] }, "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ=="], 1753 1983 1754 - "@tanstack/react-router-devtools/vite": ["vite@7.2.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w=="], 1984 + "@tailwindcss/node/jiti": ["jiti@2.6.1", "", { "bin": { "jiti": "lib/jiti-cli.mjs" } }, "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ=="], 1985 + 1986 + "@tailwindcss/oxide-wasm32-wasi/@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" }, "bundled": true }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="], 1987 + 1988 + "@tailwindcss/oxide-wasm32-wasi/@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="], 1989 + 1990 + "@tailwindcss/oxide-wasm32-wasi/@emnapi/wasi-threads": ["@emnapi/wasi-threads@1.1.0", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ=="], 1991 + 1992 + "@tailwindcss/oxide-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@1.1.0", "", { "dependencies": { "@emnapi/core": "^1.7.1", "@emnapi/runtime": "^1.7.1", "@tybys/wasm-util": "^0.10.1" }, "bundled": true }, "sha512-Fq6DJW+Bb5jaWE69/qOE0D1TUN9+6uWhCeZpdnSBk14pjLcCWR7Q8n49PTSPHazM37JqrsdpEthXy2xn6jWWiA=="], 1755 1993 1756 - "@tanstack/router-devtools/vite": ["vite@7.2.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w=="], 1994 + "@tailwindcss/oxide-wasm32-wasi/@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" }, "bundled": true }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], 1995 + 1996 + "@tailwindcss/oxide-wasm32-wasi/tslib": ["tslib@2.8.1", "", { "bundled": true }, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], 1757 1997 1758 - "@tanstack/router-devtools-core/vite": ["vite@7.2.4", "", { "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.5.0", "picomatch": "^4.0.3", "postcss": "^8.5.6", "rollup": "^4.43.0", "tinyglobby": "^0.2.15" }, "optionalDependencies": { "fsevents": "~2.3.3" }, "peerDependencies": { "@types/node": "^20.19.0 || >=22.12.0", "jiti": ">=1.21.0", "less": "^4.0.0", "lightningcss": "^1.21.0", "sass": "^1.70.0", "sass-embedded": "^1.70.0", "stylus": ">=0.54.8", "sugarss": "^5.0.0", "terser": "^5.16.0", "tsx": "^4.8.1", "yaml": "^2.4.2" }, "optionalPeers": ["@types/node", "jiti", "less", "lightningcss", "sass", "sass-embedded", "stylus", "sugarss", "terser", "tsx", "yaml"], "bin": { "vite": "bin/vite.js" } }, "sha512-NL8jTlbo0Tn4dUEXEsUg8KeyG/Lkmc4Fnzb8JXN/Ykm9G4HNImjtABMJgkQoVjOBN/j2WAwDTRytdqJbZsah7w=="], 1998 + "@types/pg-pool/@types/pg": ["@types/pg@8.6.1", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w=="], 1759 1999 1760 2000 "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], 1761 2001 1762 2002 "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], 2003 + 2004 + "@unrs/resolver-binding-wasm32-wasi/@napi-rs/wasm-runtime": ["@napi-rs/wasm-runtime@0.2.12", "", { "dependencies": { "@emnapi/core": "^1.4.3", "@emnapi/runtime": "^1.4.3", "@tybys/wasm-util": "^0.10.0" } }, "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ=="], 1763 2005 1764 2006 "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 1765 2007 2008 + "app/@atcute/identity-resolver": ["@atcute/identity-resolver@1.2.0", "", { "dependencies": { "@atcute/lexicons": "^1.2.5", "@atcute/util-fetch": "^1.0.4", "@badrap/valita": "^0.4.6" }, "peerDependencies": { "@atcute/identity": "^1.0.0" } }, "sha512-5UbSJfdV3JIkF8ksXz7g4nKBWasf2wROvzM66cfvTIWydWFO6/oS1KZd+zo9Eokje5Scf5+jsY9ZfgVARLepXg=="], 2009 + 2010 + "app/@atproto/oauth-client-node": ["@atproto/oauth-client-node@0.3.13", "", { "dependencies": { "@atproto-labs/did-resolver": "0.2.4", "@atproto-labs/handle-resolver-node": "0.1.23", "@atproto-labs/simple-store": "0.3.0", "@atproto/did": "0.2.3", "@atproto/jwk": "0.6.0", "@atproto/jwk-jose": "0.1.11", "@atproto/jwk-webcrypto": "0.2.0", "@atproto/oauth-client": "0.5.11", "@atproto/oauth-types": "0.5.2" } }, "sha512-k2qT5QM6Mj5I412IZOnktShmI1A5YbwLmLM4BkeEcbcOm7kU1Cr/H/zUC/zniCIj641ZudiXU80Bsyw4A6tejA=="], 2011 + 2012 + "app/@types/node": ["@types/node@20.19.25", "", { "dependencies": { "undici-types": "~6.21.0" } }, "sha512-ZsJzA5thDQMSQO788d7IocwwQbI8B5OPzmqNvpf3NY/+MHDAS759Wo0gd2WQeXYt5AAAQjzcrTVC6SKCuYgoCQ=="], 2013 + 1766 2014 "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], 1767 2015 1768 - "csso/css-tree": ["css-tree@2.2.1", "", { "dependencies": { "mdn-data": "2.0.28", "source-map-js": "^1.0.1" } }, "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA=="], 2016 + "eslint/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], 2017 + 2018 + "eslint-config-next/globals": ["globals@16.4.0", "", {}, "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw=="], 2019 + 2020 + "eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], 2021 + 2022 + "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], 1769 2023 1770 - "eslint/ajv": ["ajv@6.12.6", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="], 2024 + "eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], 2025 + 2026 + "eslint-plugin-import/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 2027 + 2028 + "eslint-plugin-react/resolve": ["resolve@2.0.0-next.5", "", { "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" } }, "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA=="], 2029 + 2030 + "eslint-plugin-react/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1771 2031 1772 2032 "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], 1773 2033 ··· 1775 2035 1776 2036 "globby/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], 1777 2037 1778 - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 2038 + "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], 1779 2039 1780 - "p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], 2040 + "lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], 1781 2041 1782 - "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], 2042 + "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 1783 2043 1784 - "postcss-calc/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], 2044 + "next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="], 1785 2045 1786 - "postcss-discard-comments/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], 2046 + "p-limit/yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="], 1787 2047 1788 - "postcss-merge-rules/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], 1789 - 1790 - "postcss-minify-selectors/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], 2048 + "path-scurry/lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="], 1791 2049 1792 - "postcss-unique-selectors/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], 2050 + "postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], 1793 2051 1794 2052 "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 1795 2053 1796 2054 "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 1797 2055 2056 + "rolldown/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.50", "", {}, "sha512-5e76wQiQVeL1ICOZVUg4LSOVYg9jyhGCin+icYozhsUzM+fHE7kddi1bdiE0jwVqTfkjba3jUFbEkoC9WkdvyA=="], 2057 + 2058 + "sharp/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], 2059 + 1798 2060 "solid-js/seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="], 1799 2061 1800 2062 "solid-js/seroval-plugins": ["seroval-plugins@1.3.3", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-16OL3NnUBw8JG1jBLUoZJsLnQq0n5Ua6aHalhJK4fMQkz1lqR7Osz1sA30trBtd9VUDc2NgkuRCn8+/pBwqZ+w=="], 1801 2063 1802 2064 "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 1803 2065 1804 - "stylehacks/postcss-selector-parser": ["postcss-selector-parser@7.1.0", "", { "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" } }, "sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA=="], 2066 + "string-width/emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], 1805 2067 1806 - "svgo/commander": ["commander@11.1.0", "", {}, "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ=="], 2068 + "tsconfig-paths/json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="], 1807 2069 1808 - "tsx/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], 2070 + "tsx/esbuild": ["esbuild@0.27.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.1", "@esbuild/android-arm": "0.27.1", "@esbuild/android-arm64": "0.27.1", "@esbuild/android-x64": "0.27.1", "@esbuild/darwin-arm64": "0.27.1", "@esbuild/darwin-x64": "0.27.1", "@esbuild/freebsd-arm64": "0.27.1", "@esbuild/freebsd-x64": "0.27.1", "@esbuild/linux-arm": "0.27.1", "@esbuild/linux-arm64": "0.27.1", "@esbuild/linux-ia32": "0.27.1", "@esbuild/linux-loong64": "0.27.1", "@esbuild/linux-mips64el": "0.27.1", "@esbuild/linux-ppc64": "0.27.1", "@esbuild/linux-riscv64": "0.27.1", "@esbuild/linux-s390x": "0.27.1", "@esbuild/linux-x64": "0.27.1", "@esbuild/netbsd-arm64": "0.27.1", "@esbuild/netbsd-x64": "0.27.1", "@esbuild/openbsd-arm64": "0.27.1", "@esbuild/openbsd-x64": "0.27.1", "@esbuild/openharmony-arm64": "0.27.1", "@esbuild/sunos-x64": "0.27.1", "@esbuild/win32-arm64": "0.27.1", "@esbuild/win32-ia32": "0.27.1", "@esbuild/win32-x64": "0.27.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-yY35KZckJJuVVPXpvjgxiCuVEJT67F6zDeVTv4rizyPrfGBUpZQsvmxnN+C371c2esD/hNMjj4tpBhuueLN7aA=="], 1809 2071 1810 - "vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], 2072 + "web/@types/bun": ["@types/bun@1.3.4", "", { "dependencies": { "bun-types": "1.3.4" } }, "sha512-EEPTKXHP+zKGPkhRLv+HI0UEX8/o+65hqARxLy8Ov5rIxMBPNTjeZww00CIihrIQGEQBYg+0roO5qOnS/7boGA=="], 1811 2073 1812 2074 "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], 1813 2075 1814 - "@atproto/common/pino/pino-abstract-transport": ["pino-abstract-transport@1.2.0", "", { "dependencies": { "readable-stream": "^4.0.0", "split2": "^4.0.0" } }, "sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q=="], 1815 - 1816 - "@atproto/common/pino/pino-std-serializers": ["pino-std-serializers@6.2.2", "", {}, "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="], 1817 - 1818 - "@atproto/common/pino/process-warning": ["process-warning@3.0.0", "", {}, "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="], 1819 - 1820 - "@atproto/common/pino/sonic-boom": ["sonic-boom@3.8.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg=="], 1821 - 1822 - "@atproto/common/pino/thread-stream": ["thread-stream@2.7.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw=="], 1823 - 1824 - "@babel/helper-compilation-targets/lru-cache/yallist": ["yallist@3.1.1", "", {}, "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="], 2076 + "@atcute/oauth-browser-client/@atcute/identity-resolver/@atcute/util-fetch": ["@atcute/util-fetch@1.0.4", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-sIU9Qk0dE8PLEXSfhy+gIJV+HpiiknMytCI2SqLlqd0vgZUtEKI/EQfP+23LHWvP+CLCzVDOa6cpH045OlmNBg=="], 1825 2077 1826 2078 "@cookware/database/@libsql/client/@libsql/core": ["@libsql/core@0.15.15", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-C88Z6UKl+OyuKKPwz224riz02ih/zHYI3Ho/LAcVOgjsunIRZoBw7fjRfaH9oPMmSNeQfhGklSG2il1URoOIsA=="], 1827 2079 1828 2080 "@cookware/database/@libsql/client/libsql": ["libsql@0.5.22", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.22", "@libsql/darwin-x64": "0.5.22", "@libsql/linux-arm-gnueabihf": "0.5.22", "@libsql/linux-arm-musleabihf": "0.5.22", "@libsql/linux-arm64-gnu": "0.5.22", "@libsql/linux-arm64-musl": "0.5.22", "@libsql/linux-x64-gnu": "0.5.22", "@libsql/linux-x64-musl": "0.5.22", "@libsql/win32-x64-msvc": "0.5.22" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-NscWthMQt7fpU8lqd7LXMvT9pi+KhhmTHAJWUB/Lj6MWa0MKFv0F2V4C6WKKpjCVZl0VwcDz4nOI3CyaT1DDiA=="], 2081 + 2082 + "@cookware/tsconfig/@types/bun/bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="], 1829 2083 1830 2084 "@esbuild-kit/core-utils/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.18.20", "", { "os": "android", "cpu": "arm" }, "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw=="], 1831 2085 ··· 1877 2131 1878 2132 "@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], 1879 2133 2134 + "@next/eslint-plugin-next/fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], 2135 + 1880 2136 "@opentelemetry/instrumentation-http/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.57.1", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-I4PHczeujhQAQv6ZBzqHYEUiggZL4IdSMixtVD3EYqbdrjujE7kRfI5QohjlPoJm8BvenoW5YaTMWRrbpot6tg=="], 1881 2137 1882 2138 "@prisma/instrumentation/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.53.0", "", { "dependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw=="], 1883 2139 1884 2140 "@radix-ui/react-arrow/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], 1885 - 1886 - "@radix-ui/react-collapsible/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], 1887 2141 1888 2142 "@radix-ui/react-dismissable-layer/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], 1889 2143 ··· 1899 2153 1900 2154 "@radix-ui/react-visually-hidden/@radix-ui/react-primitive/@radix-ui/react-slot": ["@radix-ui/react-slot@1.2.3", "", { "dependencies": { "@radix-ui/react-compose-refs": "1.1.2" }, "peerDependencies": { "@types/react": "*", "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A=="], 1901 2155 1902 - "@tanstack/react-router-devtools/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], 1903 - 1904 - "@tanstack/router-devtools-core/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], 1905 - 1906 - "@tanstack/router-devtools/vite/esbuild": ["esbuild@0.25.12", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.12", "@esbuild/android-arm": "0.25.12", "@esbuild/android-arm64": "0.25.12", "@esbuild/android-x64": "0.25.12", "@esbuild/darwin-arm64": "0.25.12", "@esbuild/darwin-x64": "0.25.12", "@esbuild/freebsd-arm64": "0.25.12", "@esbuild/freebsd-x64": "0.25.12", "@esbuild/linux-arm": "0.25.12", "@esbuild/linux-arm64": "0.25.12", "@esbuild/linux-ia32": "0.25.12", "@esbuild/linux-loong64": "0.25.12", "@esbuild/linux-mips64el": "0.25.12", "@esbuild/linux-ppc64": "0.25.12", "@esbuild/linux-riscv64": "0.25.12", "@esbuild/linux-s390x": "0.25.12", "@esbuild/linux-x64": "0.25.12", "@esbuild/netbsd-arm64": "0.25.12", "@esbuild/netbsd-x64": "0.25.12", "@esbuild/openbsd-arm64": "0.25.12", "@esbuild/openbsd-x64": "0.25.12", "@esbuild/openharmony-arm64": "0.25.12", "@esbuild/sunos-x64": "0.25.12", "@esbuild/win32-arm64": "0.25.12", "@esbuild/win32-ia32": "0.25.12", "@esbuild/win32-x64": "0.25.12" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg=="], 1907 - 1908 2156 "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], 1909 2157 1910 - "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], 1911 - 1912 - "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], 1913 - 1914 - "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 2158 + "app/@atcute/identity-resolver/@atcute/util-fetch": ["@atcute/util-fetch@1.0.4", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-sIU9Qk0dE8PLEXSfhy+gIJV+HpiiknMytCI2SqLlqd0vgZUtEKI/EQfP+23LHWvP+CLCzVDOa6cpH045OlmNBg=="], 1915 2159 1916 - "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], 2160 + "app/@atproto/oauth-client-node/@atproto-labs/did-resolver": ["@atproto-labs/did-resolver@0.2.4", "", { "dependencies": { "@atproto-labs/fetch": "0.2.3", "@atproto-labs/pipe": "0.1.1", "@atproto-labs/simple-store": "0.3.0", "@atproto-labs/simple-store-memory": "0.1.4", "@atproto/did": "0.2.3", "zod": "^3.23.8" } }, "sha512-sbXxBnAJWsKv/FEGG6a/WLz7zQYUr1vA2TXvNnPwwJQJCjPwEJMOh1vM22wBr185Phy7D2GD88PcRokn7eUVyw=="], 1917 2161 1918 - "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], 2162 + "app/@atproto/oauth-client-node/@atproto-labs/handle-resolver-node": ["@atproto-labs/handle-resolver-node@0.1.23", "", { "dependencies": { "@atproto-labs/fetch-node": "0.2.0", "@atproto-labs/handle-resolver": "0.3.4", "@atproto/did": "0.2.3" } }, "sha512-tBRr2LCgzn3klk+DL0xrTFv4zg5tEszdeW6vSIFVebBYSb3MLdfhievmSqZdIQ4c9UCC4hN7YXTlZCXj8+2YmQ=="], 1919 2163 1920 - "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], 2164 + "app/@atproto/oauth-client-node/@atproto-labs/simple-store": ["@atproto-labs/simple-store@0.3.0", "", {}, "sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ=="], 1921 2165 1922 - "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], 2166 + "app/@atproto/oauth-client-node/@atproto/did": ["@atproto/did@0.2.3", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-VI8JJkSizvM2cHYJa37WlbzeCm5tWpojyc1/Zy8q8OOjyoy6X4S4BEfoP941oJcpxpMTObamibQIXQDo7tnIjg=="], 1923 2167 1924 - "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], 2168 + "app/@atproto/oauth-client-node/@atproto/jwk": ["@atproto/jwk@0.6.0", "", { "dependencies": { "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-bDoJPvt7TrQVi/rBfBrSSpGykhtIriKxeYCYQTiPRKFfyRhbgpElF0wPXADjIswnbzZdOwbY63az4E/CFVT3Tw=="], 1925 2169 1926 - "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], 2170 + "app/@atproto/oauth-client-node/@atproto/jwk-jose": ["@atproto/jwk-jose@0.1.11", "", { "dependencies": { "@atproto/jwk": "0.6.0", "jose": "^5.2.0" } }, "sha512-i4Fnr2sTBYmMmHXl7NJh8GrCH+tDQEVWrcDMDnV5DjJfkgT17wIqvojIw9SNbSL4Uf0OtfEv6AgG0A+mgh8b5Q=="], 1927 2171 1928 - "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], 2172 + "app/@atproto/oauth-client-node/@atproto/jwk-webcrypto": ["@atproto/jwk-webcrypto@0.2.0", "", { "dependencies": { "@atproto/jwk": "0.6.0", "@atproto/jwk-jose": "0.1.11", "zod": "^3.23.8" } }, "sha512-UmgRrrEAkWvxwhlwe30UmDOdTEFidlIzBC7C3cCbeJMcBN1x8B3KH+crXrsTqfWQBG58mXgt8wgSK3Kxs2LhFg=="], 1929 2173 1930 - "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], 2174 + "app/@atproto/oauth-client-node/@atproto/oauth-client": ["@atproto/oauth-client@0.5.11", "", { "dependencies": { "@atproto-labs/did-resolver": "0.2.4", "@atproto-labs/fetch": "0.2.3", "@atproto-labs/handle-resolver": "0.3.4", "@atproto-labs/identity-resolver": "0.3.4", "@atproto-labs/simple-store": "0.3.0", "@atproto-labs/simple-store-memory": "0.1.4", "@atproto/did": "0.2.3", "@atproto/jwk": "0.6.0", "@atproto/oauth-types": "0.5.2", "@atproto/xrpc": "0.7.7", "core-js": "^3", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-KyxKpnF988BI3m+4NNYDgkN6a2sPORD9uaOEGP4tnJLOvhMVHyATWwq3Jx4LOYotTFDOvLdheWcI1G9DozE88w=="], 1931 2175 1932 - "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], 2176 + "app/@atproto/oauth-client-node/@atproto/oauth-types": ["@atproto/oauth-types@0.5.2", "", { "dependencies": { "@atproto/did": "0.2.3", "@atproto/jwk": "0.6.0", "zod": "^3.23.8" } }, "sha512-9DCDvtvCanTwAaU5UakYDO0hzcOITS3RutK5zfLytE5Y9unj0REmTDdN8Xd8YCfUJl7T/9pYpf04Uyq7bFTASg=="], 1933 2177 1934 - "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], 2178 + "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], 1935 2179 1936 - "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], 2180 + "next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], 1937 2181 1938 - "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], 2182 + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA=="], 1939 2183 1940 - "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], 2184 + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.1", "", { "os": "android", "cpu": "arm" }, "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg=="], 1941 2185 1942 - "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], 2186 + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.1", "", { "os": "android", "cpu": "arm64" }, "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ=="], 1943 2187 1944 - "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], 2188 + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.1", "", { "os": "android", "cpu": "x64" }, "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ=="], 1945 2189 1946 - "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], 2190 + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ=="], 1947 2191 1948 - "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], 2192 + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ=="], 1949 2193 1950 - "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], 2194 + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg=="], 1951 2195 1952 - "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], 2196 + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ=="], 1953 2197 1954 - "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], 2198 + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.1", "", { "os": "linux", "cpu": "arm" }, "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA=="], 1955 2199 1956 - "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 2200 + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q=="], 1957 2201 1958 - "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 2202 + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw=="], 1959 2203 1960 - "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 2204 + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg=="], 1961 2205 1962 - "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], 2206 + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA=="], 1963 2207 1964 - "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], 2208 + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ=="], 1965 2209 1966 - "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], 2210 + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ=="], 1967 2211 1968 - "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], 2212 + "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.27.1", "", { "os": "linux", "cpu": "s390x" }, "sha512-cGj5wli+G+nkVQdZo3+7FDKC25Uh4ZVwOAK6A06Hsvgr8WqBBuOy/1s+PUEd/6Je+vjfm6stX0kmib5b/O2Ykw=="], 1969 2213 1970 - "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], 2214 + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.1", "", { "os": "linux", "cpu": "x64" }, "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA=="], 1971 2215 1972 - "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], 2216 + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.1", "", { "os": "none", "cpu": "x64" }, "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg=="], 1973 2217 1974 - "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], 2218 + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg=="], 1975 2219 1976 - "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], 2220 + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA=="], 1977 2221 1978 - "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], 2222 + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg=="], 1979 2223 1980 - "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], 2224 + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ=="], 1981 2225 1982 - "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], 2226 + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.1", "", { "os": "win32", "cpu": "x64" }, "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw=="], 1983 2227 1984 - "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], 1985 - 1986 - "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], 1987 - 1988 - "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], 1989 - 1990 - "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], 1991 - 1992 - "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], 1993 - 1994 - "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], 1995 - 1996 - "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], 1997 - 1998 - "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], 1999 - 2000 - "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], 2001 - 2002 - "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 2003 - 2004 - "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 2228 + "web/@types/bun/bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="], 2005 2229 2006 2230 "@cookware/database/@libsql/client/libsql/@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.22", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA=="], 2007 2231 ··· 2017 2241 2018 2242 "@cookware/database/@libsql/client/libsql/@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.22", "", { "os": "win32", "cpu": "x64" }, "sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA=="], 2019 2243 2244 + "@cookware/tsconfig/@types/bun/bun-types/@types/node": ["@types/node@24.10.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA=="], 2245 + 2020 2246 "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], 2021 2247 2022 2248 "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], 2023 2249 2024 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 2025 - 2026 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], 2027 - 2028 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], 2029 - 2030 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], 2031 - 2032 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], 2033 - 2034 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], 2035 - 2036 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], 2037 - 2038 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], 2039 - 2040 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], 2041 - 2042 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], 2043 - 2044 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], 2045 - 2046 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], 2047 - 2048 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], 2049 - 2050 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], 2051 - 2052 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], 2053 - 2054 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], 2055 - 2056 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], 2057 - 2058 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], 2059 - 2060 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], 2061 - 2062 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], 2063 - 2064 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], 2065 - 2066 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 2067 - 2068 - "@tanstack/react-router-devtools/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 2069 - 2070 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 2071 - 2072 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], 2073 - 2074 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], 2075 - 2076 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], 2077 - 2078 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], 2079 - 2080 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], 2081 - 2082 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], 2083 - 2084 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], 2085 - 2086 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], 2087 - 2088 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], 2089 - 2090 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], 2091 - 2092 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], 2093 - 2094 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], 2095 - 2096 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], 2097 - 2098 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], 2099 - 2100 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], 2101 - 2102 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], 2103 - 2104 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], 2105 - 2106 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], 2107 - 2108 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], 2109 - 2110 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], 2111 - 2112 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 2113 - 2114 - "@tanstack/router-devtools-core/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 2115 - 2116 - "@tanstack/router-devtools/vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 2117 - 2118 - "@tanstack/router-devtools/vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], 2119 - 2120 - "@tanstack/router-devtools/vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], 2121 - 2122 - "@tanstack/router-devtools/vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], 2123 - 2124 - "@tanstack/router-devtools/vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], 2125 - 2126 - "@tanstack/router-devtools/vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], 2250 + "app/@atproto/oauth-client-node/@atproto-labs/did-resolver/@atproto-labs/simple-store-memory": ["@atproto-labs/simple-store-memory@0.1.4", "", { "dependencies": { "@atproto-labs/simple-store": "0.3.0", "lru-cache": "^10.2.0" } }, "sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw=="], 2127 2251 2128 - "@tanstack/router-devtools/vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], 2129 - 2130 - "@tanstack/router-devtools/vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], 2252 + "app/@atproto/oauth-client-node/@atproto-labs/handle-resolver-node/@atproto-labs/fetch-node": ["@atproto-labs/fetch-node@0.2.0", "", { "dependencies": { "@atproto-labs/fetch": "0.2.3", "@atproto-labs/pipe": "0.1.1", "ipaddr.js": "^2.1.0", "undici": "^6.14.1" } }, "sha512-Krq09nH/aeoiU2s9xdHA0FjTEFWG9B5FFenipv1iRixCcPc7V3DhTNDawxG9gI8Ny0k4dBVS9WTRN/IDzBx86Q=="], 2131 2253 2132 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], 2254 + "app/@atproto/oauth-client-node/@atproto-labs/handle-resolver-node/@atproto-labs/handle-resolver": ["@atproto-labs/handle-resolver@0.3.4", "", { "dependencies": { "@atproto-labs/simple-store": "0.3.0", "@atproto-labs/simple-store-memory": "0.1.4", "@atproto/did": "0.2.3", "zod": "^3.23.8" } }, "sha512-wsNopfzfgO3uPvfnFDgNeXgDufXxSXhjBjp2WEiSzEiLrMy0Jodnqggw4OzD9MJKf0a4Iu2/ydd537qdy91LrQ=="], 2133 2255 2134 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], 2256 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto-labs/handle-resolver": ["@atproto-labs/handle-resolver@0.3.4", "", { "dependencies": { "@atproto-labs/simple-store": "0.3.0", "@atproto-labs/simple-store-memory": "0.1.4", "@atproto/did": "0.2.3", "zod": "^3.23.8" } }, "sha512-wsNopfzfgO3uPvfnFDgNeXgDufXxSXhjBjp2WEiSzEiLrMy0Jodnqggw4OzD9MJKf0a4Iu2/ydd537qdy91LrQ=="], 2135 2257 2136 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], 2258 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto-labs/identity-resolver": ["@atproto-labs/identity-resolver@0.3.4", "", { "dependencies": { "@atproto-labs/did-resolver": "0.2.4", "@atproto-labs/handle-resolver": "0.3.4" } }, "sha512-HNUEFQIo2ws6iATxmgHd5D5rAsWYupgxZucgwolVHPiMjE1SY+EmxEsfbEN1wDEzM8/u9AKUg/jrxxPEwsgbew=="], 2137 2259 2138 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], 2260 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto-labs/simple-store-memory": ["@atproto-labs/simple-store-memory@0.1.4", "", { "dependencies": { "@atproto-labs/simple-store": "0.3.0", "lru-cache": "^10.2.0" } }, "sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw=="], 2139 2261 2140 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], 2262 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto/xrpc": ["@atproto/xrpc@0.7.7", "", { "dependencies": { "@atproto/lexicon": "^0.6.0", "zod": "^3.23.8" } }, "sha512-K1ZyO/BU8JNtXX5dmPp7b5UrkLMMqpsIa/Lrj5D3Su+j1Xwq1m6QJ2XJ1AgjEjkI1v4Muzm7klianLE6XGxtmA=="], 2141 2263 2142 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], 2264 + "web/@types/bun/bun-types/@types/node": ["@types/node@24.10.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA=="], 2143 2265 2144 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], 2266 + "@cookware/tsconfig/@types/bun/bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], 2145 2267 2146 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], 2268 + "app/@atproto/oauth-client-node/@atproto-labs/did-resolver/@atproto-labs/simple-store-memory/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 2147 2269 2148 - "@tanstack/router-devtools/vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], 2270 + "app/@atproto/oauth-client-node/@atproto-labs/handle-resolver-node/@atproto-labs/handle-resolver/@atproto-labs/simple-store-memory": ["@atproto-labs/simple-store-memory@0.1.4", "", { "dependencies": { "@atproto-labs/simple-store": "0.3.0", "lru-cache": "^10.2.0" } }, "sha512-3mKY4dP8I7yKPFj9VKpYyCRzGJOi5CEpOLPlRhoJyLmgs3J4RzDrjn323Oakjz2Aj2JzRU/AIvWRAZVhpYNJHw=="], 2149 2271 2150 - "@tanstack/router-devtools/vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], 2272 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto-labs/simple-store-memory/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 2151 2273 2152 - "@tanstack/router-devtools/vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], 2274 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto/xrpc/@atproto/lexicon": ["@atproto/lexicon@0.6.0", "", { "dependencies": { "@atproto/common-web": "^0.4.7", "@atproto/syntax": "^0.4.2", "iso-datestring-validator": "^2.2.2", "multiformats": "^9.9.0", "zod": "^3.23.8" } }, "sha512-5veb8aD+J5M0qszLJ+73KSFsFrJBgAY/nM1TSAJvGY7fNc9ZAT+PSUlmIyrdye9YznAZ07yktalls/TwNV7cHQ=="], 2153 2275 2154 - "@tanstack/router-devtools/vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], 2276 + "web/@types/bun/bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], 2155 2277 2156 - "@tanstack/router-devtools/vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], 2278 + "app/@atproto/oauth-client-node/@atproto-labs/handle-resolver-node/@atproto-labs/handle-resolver/@atproto-labs/simple-store-memory/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 2157 2279 2158 - "@tanstack/router-devtools/vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 2280 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto/xrpc/@atproto/lexicon/@atproto/common-web": ["@atproto/common-web@0.4.7", "", { "dependencies": { "@atproto/lex-data": "0.0.3", "@atproto/lex-json": "0.0.3", "zod": "^3.23.8" } }, "sha512-vjw2+81KPo2/SAbbARGn64Ln+6JTI0FTI4xk8if0ebBfDxFRmHb2oSN1y77hzNq/ybGHqA2mecfhS03pxC5+lg=="], 2159 2281 2160 - "@tanstack/router-devtools/vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 2282 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto/xrpc/@atproto/lexicon/@atproto/syntax": ["@atproto/syntax@0.4.2", "", {}, "sha512-X9XSRPinBy/0VQ677j8VXlBsYSsUXaiqxWVpGGxJYsAhugdQRb0jqaVKJFtm6RskeNkV6y9xclSUi9UYG/COrA=="], 2161 2283 } 2162 2284 }
+13
config/dev/db/compose.yaml
··· 1 + --- 2 + volumes: 3 + postgres: {} 4 + 5 + services: 6 + postgres: 7 + image: postgres:18 8 + environment: 9 + POSTGRES_PASSWORD: postgres 10 + ports: 11 + - 5432:5432 12 + volumes: 13 + - postgres:/var/lib/postgresql/18/docker
-13
config/dev/libsql/compose.yaml
··· 1 - --- 2 - volumes: 3 - libsql: {} 4 - 5 - services: 6 - libsql: 7 - image: ghcr.io/tursodatabase/libsql-server:latest 8 - environment: 9 - SQLD_NODE: primary 10 - ports: 11 - - 4001:8080 12 - volumes: 13 - - libsql:/var/lib/sqld
+12
config/dev/redis/compose.yaml
··· 1 + --- 2 + volumes: 3 + redis: 4 + 5 + services: 6 + redis: 7 + image: redis:8 8 + command: redis-server --save 60 1 --loglevel warning 9 + ports: 10 + - 6379:6379 11 + volumes: 12 + - redis:/data
+2 -32
docker-compose.yaml
··· 1 1 --- 2 2 include: 3 - - path: config/dev/caddy/compose.yaml 4 - - path: config/dev/libsql/compose.yaml 3 + - path: config/dev/db/compose.yaml 4 + - path: config/dev/redis/compose.yaml 5 5 6 6 networks: 7 7 recipesblue: 8 - 9 - services: 10 - redis: 11 - image: redis:8 12 - ports: [6379:6379] 13 - 14 - api: 15 - build: 16 - context: . 17 - dockerfile: apps/api/Dockerfile 18 - restart: unless-stopped 19 - networks: [recipesblue] 20 - ports: 21 - - "3000:3000" 22 - environment: 23 - - DATABASE_URL=http://libsql:8080 24 - - PORT=3000 25 - depends_on: 26 - - libsql 27 - 28 - ingester: 29 - build: 30 - context: . 31 - dockerfile: apps/ingester/Dockerfile 32 - restart: unless-stopped 33 - networks: [recipesblue] 34 - environment: 35 - - DATABASE_URL=http://libsql:8080 36 - depends_on: 37 - - libsql
+2 -3
libs/database/drizzle.config.ts
··· 3 3 export default { 4 4 schema: "./lib/schema.ts", 5 5 out: "./migrations", 6 - dialect: "turso", 6 + dialect: "postgresql", 7 7 dbCredentials: { 8 - url: process.env.DATABASE_URL || "http://localhost:4001", 9 - authToken: process.env.DATABASE_AUTH_TOKEN 8 + url: process.env.DATABASE_URL || 'postgres://postgres:postgres@localhost:5432/postgres', 10 9 } 11 10 } satisfies Config;
+5 -6
libs/database/lib/index.ts
··· 1 - import { drizzle } from 'drizzle-orm/libsql'; 2 - import { createClient } from '@libsql/client'; 1 + import { drizzle } from 'drizzle-orm/node-postgres'; 2 + import { Pool } from 'pg'; 3 3 4 - const client = createClient({ 5 - url: process.env.TURSO_CONNECTION_URL || 'http://localhost:4001', 6 - authToken: process.env.TURSO_AUTH_TOKEN || '', 4 + const pool = new Pool({ 5 + connectionString: process.env.DATABASE_URL || 'postgres://postgres:postgres@localhost:5432/postgres', 7 6 }); 8 7 9 8 import * as schema from './schema.js'; 10 - export const db = drizzle(client, { schema }); 9 + export const db = drizzle(pool, { schema }); 11 10 12 11 // Re-export drizzle-orm functions to ensure single instance 13 12 export { eq, and, or, desc, asc, sql } from 'drizzle-orm';
+16 -15
libs/database/lib/schema.ts
··· 1 - import { customType, index, int, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core"; 2 - import { BlueRecipesFeedRecipe, BlueRecipesActorProfile } from "@cookware/lexicons"; 3 - import { Cid, isCid, ResourceUri, type AtprotoDid } from "@atcute/lexicons/syntax"; 4 - import { Blob, LegacyBlob } from "@atcute/lexicons"; 1 + import { customType, index, integer, primaryKey, pgTable, text, jsonb, varchar } from "drizzle-orm/pg-core"; 2 + import { BlueRecipesFeedRecipe } from "@cookware/lexicons"; 3 + import { type Cid, isCid, type ResourceUri, type AtprotoDid } from "@atcute/lexicons/syntax"; 4 + import type { Blob, LegacyBlob } from "@atcute/lexicons"; 5 5 import { relations, sql, type SQL } from "drizzle-orm"; 6 6 import { isBlob, isCidLink, isLegacyBlob } from "@atcute/lexicons/interfaces"; 7 7 ··· 53 53 }, 54 54 }); 55 55 56 - export const profilesTable = sqliteTable("profiles", { 56 + export const profilesTable = pgTable("profiles", { 57 57 uri: text('uri') 58 58 .generatedAlwaysAs((): SQL => sql`'at://' || ${profilesTable.did} || '/blue.recipes.actor.profile/self'`) 59 59 .$type<ResourceUri>(), 60 + 60 61 cid: text("cid").$type<Cid>().notNull(), 61 62 did: text("did").$type<AtprotoDid>().notNull().primaryKey(), 62 63 ingestedAt: dateIsoText("ingested_at").notNull().default(sql`CURRENT_TIMESTAMP`), 63 64 64 - displayName: text('display_name', { length: 640 }).notNull(), 65 - description: text('description', { length: 2500 }), 66 - pronouns: text('pronouns', { length: 200 }), 65 + displayName: varchar('display_name', { length: 640 }).notNull(), 66 + description: varchar('description', { length: 2500 }), 67 + pronouns: varchar('pronouns', { length: 200 }), 67 68 website: text('website'), 68 69 avatarRef: atBlob('avatar'), 69 70 bannerRef: atBlob('banner'), ··· 74 75 index('profiles_iat_idx').on(t.ingestedAt), 75 76 ])); 76 77 77 - export const recipeTable = sqliteTable("recipes", { 78 + export const recipeTable = pgTable("recipes", { 78 79 uri: text('uri') 79 80 .generatedAlwaysAs((): SQL => sql`'at://' || ${recipeTable.did} || '/blue.recipes.feed.recipe/' || ${recipeTable.rkey}`), 80 81 ··· 88 89 imageRef: atBlob('image'), 89 90 90 91 title: text('title').notNull(), 91 - time: int('time').notNull().default(0), 92 - serves: int('serves'), 92 + time: integer('time').notNull().default(0), 93 + serves: integer('serves'), 93 94 description: text('description'), 94 95 95 - ingredients: text('ingredients', { mode: 'json' }).$type<BlueRecipesFeedRecipe.Main['ingredients']>().notNull(), 96 - ingredientsCount: int('ingredients_count').generatedAlwaysAs((): SQL => sql`json_array_length(${recipeTable.ingredients})`), 96 + ingredients: jsonb('ingredients').$type<BlueRecipesFeedRecipe.Main['ingredients']>().notNull(), 97 + ingredientsCount: integer('ingredients_count').generatedAlwaysAs((): SQL => sql`jsonb_array_length(${recipeTable.ingredients})`), 97 98 98 - steps: text('steps', { mode: 'json' }).$type<BlueRecipesFeedRecipe.Main['steps']>().notNull(), 99 - stepsCount: int('steps_count').generatedAlwaysAs((): SQL => sql`json_array_length(${recipeTable.steps})`), 99 + steps: jsonb('steps').$type<BlueRecipesFeedRecipe.Main['steps']>().notNull(), 100 + stepsCount: integer('steps_count').generatedAlwaysAs((): SQL => sql`jsonb_array_length(${recipeTable.steps})`), 100 101 101 102 createdAt: dateIsoText("created_at").notNull(), 102 103 ingestedAt: dateIsoText("ingested_at").notNull().default(sql`CURRENT_TIMESTAMP`),
-16
libs/database/migrations/0000_kind_ultron.sql
··· 1 - CREATE TABLE `recipes` ( 2 - `uri` text GENERATED ALWAYS AS ("author_did" || '/' || "rkey") VIRTUAL, 3 - `author_did` text NOT NULL, 4 - `rkey` text NOT NULL, 5 - `image_ref` text, 6 - `title` text NOT NULL, 7 - `time` integer DEFAULT 0 NOT NULL, 8 - `serves` integer, 9 - `description` text, 10 - `ingredients` text NOT NULL, 11 - `ingredients_count` integer GENERATED ALWAYS AS (json_array_length("ingredients")) VIRTUAL, 12 - `steps` text NOT NULL, 13 - `steps_count` integer GENERATED ALWAYS AS (json_array_length("steps")) VIRTUAL, 14 - `created_at` text NOT NULL, 15 - PRIMARY KEY(`author_did`, `rkey`) 16 - );
+46
libs/database/migrations/0000_young_hellcat.sql
··· 1 + CREATE TABLE IF NOT EXISTS "profiles" ( 2 + "uri" text GENERATED ALWAYS AS ('at://' || "profiles"."did" || '/blue.recipes.actor.profile/self') STORED, 3 + "cid" text NOT NULL, 4 + "did" text PRIMARY KEY NOT NULL, 5 + "ingested_at" text DEFAULT CURRENT_TIMESTAMP NOT NULL, 6 + "display_name" varchar(640) NOT NULL, 7 + "description" varchar(2500), 8 + "pronouns" varchar(200), 9 + "website" text, 10 + "avatar" text, 11 + "banner" text, 12 + "created_at" text NOT NULL 13 + ); 14 + --> statement-breakpoint 15 + CREATE TABLE IF NOT EXISTS "recipes" ( 16 + "uri" text GENERATED ALWAYS AS ('at://' || "recipes"."author_did" || '/blue.recipes.feed.recipe/' || "recipes"."rkey") STORED, 17 + "cid" text NOT NULL, 18 + "author_did" text NOT NULL, 19 + "rkey" text NOT NULL, 20 + "image" text, 21 + "title" text NOT NULL, 22 + "time" integer DEFAULT 0 NOT NULL, 23 + "serves" integer, 24 + "description" text, 25 + "ingredients" jsonb NOT NULL, 26 + "ingredients_count" integer GENERATED ALWAYS AS (jsonb_array_length("recipes"."ingredients")) STORED, 27 + "steps" jsonb NOT NULL, 28 + "steps_count" integer GENERATED ALWAYS AS (jsonb_array_length("recipes"."steps")) STORED, 29 + "created_at" text NOT NULL, 30 + "ingested_at" text DEFAULT CURRENT_TIMESTAMP NOT NULL, 31 + CONSTRAINT "recipes_author_did_rkey_pk" PRIMARY KEY("author_did","rkey") 32 + ); 33 + --> statement-breakpoint 34 + DO $$ BEGIN 35 + ALTER TABLE "recipes" ADD CONSTRAINT "recipes_author_did_profiles_did_fk" FOREIGN KEY ("author_did") REFERENCES "public"."profiles"("did") ON DELETE cascade ON UPDATE no action; 36 + EXCEPTION 37 + WHEN duplicate_object THEN null; 38 + END $$; 39 + --> statement-breakpoint 40 + CREATE INDEX IF NOT EXISTS "profiles_cid_idx" ON "profiles" USING btree ("cid");--> statement-breakpoint 41 + CREATE INDEX IF NOT EXISTS "profiles_cat_idx" ON "profiles" USING btree ("created_at");--> statement-breakpoint 42 + CREATE INDEX IF NOT EXISTS "profiles_iat_idx" ON "profiles" USING btree ("ingested_at");--> statement-breakpoint 43 + CREATE INDEX IF NOT EXISTS "recipes_title_idx" ON "recipes" USING btree ("title");--> statement-breakpoint 44 + CREATE INDEX IF NOT EXISTS "recipes_cid_idx" ON "recipes" USING btree ("cid");--> statement-breakpoint 45 + CREATE INDEX IF NOT EXISTS "recipes_cat_idx" ON "recipes" USING btree ("created_at");--> statement-breakpoint 46 + CREATE INDEX IF NOT EXISTS "recipes_iat_idx" ON "recipes" USING btree ("ingested_at");
-23
libs/database/migrations/0001_past_umar.sql
··· 1 - ALTER TABLE `recipes` RENAME COLUMN "image_ref" TO "image";--> statement-breakpoint 2 - CREATE TABLE `profiles` ( 3 - `uri` text GENERATED ALWAYS AS ('at://' || "did" || '/?/self') VIRTUAL, 4 - `did` text PRIMARY KEY NOT NULL, 5 - `ingested_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL, 6 - `display_name` text(640) NOT NULL, 7 - `description` text(2500), 8 - `pronouns` text(200), 9 - `website` text, 10 - `avatar` text, 11 - `banner` text, 12 - `created_at` text NOT NULL 13 - ); 14 - --> statement-breakpoint 15 - CREATE INDEX `profiles_cat_idx` ON `profiles` (`created_at`);--> statement-breakpoint 16 - CREATE INDEX `profiles_iat_idx` ON `profiles` (`ingested_at`);--> statement-breakpoint 17 - ALTER TABLE `recipes` DROP COLUMN `uri`;--> statement-breakpoint 18 - ALTER TABLE `recipes` ADD `uri` text GENERATED ALWAYS AS ('at://' || "author_did" || '/?/' || "rkey") VIRTUAL;--> statement-breakpoint 19 - ALTER TABLE `recipes` ADD `ingested_at` text DEFAULT CURRENT_TIMESTAMP NOT NULL;--> statement-breakpoint 20 - CREATE INDEX `recipes_title_idx` ON `recipes` (`title`);--> statement-breakpoint 21 - CREATE INDEX `recipes_cat_idx` ON `recipes` (`created_at`);--> statement-breakpoint 22 - CREATE INDEX `recipes_iat_idx` ON `recipes` (`ingested_at`);--> statement-breakpoint 23 - ALTER TABLE `recipes` ALTER COLUMN "author_did" TO "author_did" text NOT NULL REFERENCES profiles(did) ON DELETE cascade ON UPDATE no action;
-4
libs/database/migrations/0002_cheerful_venom.sql
··· 1 - ALTER TABLE `profiles` DROP COLUMN `uri`;--> statement-breakpoint 2 - ALTER TABLE `profiles` ADD `uri` text GENERATED ALWAYS AS ('at://' || "did" || '/blue.recipes.actor.profile/self') VIRTUAL;--> statement-breakpoint 3 - ALTER TABLE `recipes` DROP COLUMN `uri`;--> statement-breakpoint 4 - ALTER TABLE `recipes` ADD `uri` text GENERATED ALWAYS AS ('at://' || "author_did" || '/blue.recipes.feed.recipe/' || "rkey") VIRTUAL;
-4
libs/database/migrations/0003_long_blue_marvel.sql
··· 1 - ALTER TABLE `profiles` ADD `cid` text NOT NULL;--> statement-breakpoint 2 - CREATE INDEX `profiles_cid_idx` ON `profiles` (`cid`);--> statement-breakpoint 3 - ALTER TABLE `recipes` ADD `cid` text NOT NULL;--> statement-breakpoint 4 - CREATE INDEX `recipes_cid_idx` ON `recipes` (`cid`);
+255 -46
libs/database/migrations/meta/0000_snapshot.json
··· 1 1 { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "7b2675f9-5d97-4fac-983e-978efd250faf", 2 + "id": "5d896b70-087b-421e-8d94-c100476cd926", 5 3 "prevId": "00000000-0000-0000-0000-000000000000", 4 + "version": "7", 5 + "dialect": "postgresql", 6 6 "tables": { 7 - "recipes": { 7 + "public.profiles": { 8 + "name": "profiles", 9 + "schema": "", 10 + "columns": { 11 + "uri": { 12 + "name": "uri", 13 + "type": "text", 14 + "primaryKey": false, 15 + "notNull": false, 16 + "generated": { 17 + "as": "'at://' || \"profiles\".\"did\" || '/blue.recipes.actor.profile/self'", 18 + "type": "stored" 19 + } 20 + }, 21 + "cid": { 22 + "name": "cid", 23 + "type": "text", 24 + "primaryKey": false, 25 + "notNull": true 26 + }, 27 + "did": { 28 + "name": "did", 29 + "type": "text", 30 + "primaryKey": true, 31 + "notNull": true 32 + }, 33 + "ingested_at": { 34 + "name": "ingested_at", 35 + "type": "text", 36 + "primaryKey": false, 37 + "notNull": true, 38 + "default": "CURRENT_TIMESTAMP" 39 + }, 40 + "display_name": { 41 + "name": "display_name", 42 + "type": "varchar(640)", 43 + "primaryKey": false, 44 + "notNull": true 45 + }, 46 + "description": { 47 + "name": "description", 48 + "type": "varchar(2500)", 49 + "primaryKey": false, 50 + "notNull": false 51 + }, 52 + "pronouns": { 53 + "name": "pronouns", 54 + "type": "varchar(200)", 55 + "primaryKey": false, 56 + "notNull": false 57 + }, 58 + "website": { 59 + "name": "website", 60 + "type": "text", 61 + "primaryKey": false, 62 + "notNull": false 63 + }, 64 + "avatar": { 65 + "name": "avatar", 66 + "type": "text", 67 + "primaryKey": false, 68 + "notNull": false 69 + }, 70 + "banner": { 71 + "name": "banner", 72 + "type": "text", 73 + "primaryKey": false, 74 + "notNull": false 75 + }, 76 + "created_at": { 77 + "name": "created_at", 78 + "type": "text", 79 + "primaryKey": false, 80 + "notNull": true 81 + } 82 + }, 83 + "indexes": { 84 + "profiles_cid_idx": { 85 + "name": "profiles_cid_idx", 86 + "columns": [ 87 + { 88 + "expression": "cid", 89 + "isExpression": false, 90 + "asc": true, 91 + "nulls": "last" 92 + } 93 + ], 94 + "isUnique": false, 95 + "concurrently": false, 96 + "method": "btree", 97 + "with": {} 98 + }, 99 + "profiles_cat_idx": { 100 + "name": "profiles_cat_idx", 101 + "columns": [ 102 + { 103 + "expression": "created_at", 104 + "isExpression": false, 105 + "asc": true, 106 + "nulls": "last" 107 + } 108 + ], 109 + "isUnique": false, 110 + "concurrently": false, 111 + "method": "btree", 112 + "with": {} 113 + }, 114 + "profiles_iat_idx": { 115 + "name": "profiles_iat_idx", 116 + "columns": [ 117 + { 118 + "expression": "ingested_at", 119 + "isExpression": false, 120 + "asc": true, 121 + "nulls": "last" 122 + } 123 + ], 124 + "isUnique": false, 125 + "concurrently": false, 126 + "method": "btree", 127 + "with": {} 128 + } 129 + }, 130 + "foreignKeys": {}, 131 + "compositePrimaryKeys": {}, 132 + "uniqueConstraints": {}, 133 + "policies": {}, 134 + "checkConstraints": {}, 135 + "isRLSEnabled": false 136 + }, 137 + "public.recipes": { 8 138 "name": "recipes", 139 + "schema": "", 9 140 "columns": { 10 141 "uri": { 11 142 "name": "uri", 12 143 "type": "text", 13 144 "primaryKey": false, 14 145 "notNull": false, 15 - "autoincrement": false, 16 146 "generated": { 17 - "as": "(\"author_did\" || '/' || \"rkey\")", 18 - "type": "virtual" 147 + "as": "'at://' || \"recipes\".\"author_did\" || '/blue.recipes.feed.recipe/' || \"recipes\".\"rkey\"", 148 + "type": "stored" 19 149 } 20 150 }, 151 + "cid": { 152 + "name": "cid", 153 + "type": "text", 154 + "primaryKey": false, 155 + "notNull": true 156 + }, 21 157 "author_did": { 22 158 "name": "author_did", 23 159 "type": "text", 24 160 "primaryKey": false, 25 - "notNull": true, 26 - "autoincrement": false 161 + "notNull": true 27 162 }, 28 163 "rkey": { 29 164 "name": "rkey", 30 165 "type": "text", 31 166 "primaryKey": false, 32 - "notNull": true, 33 - "autoincrement": false 167 + "notNull": true 34 168 }, 35 - "image_ref": { 36 - "name": "image_ref", 169 + "image": { 170 + "name": "image", 37 171 "type": "text", 38 172 "primaryKey": false, 39 - "notNull": false, 40 - "autoincrement": false 173 + "notNull": false 41 174 }, 42 175 "title": { 43 176 "name": "title", 44 177 "type": "text", 45 178 "primaryKey": false, 46 - "notNull": true, 47 - "autoincrement": false 179 + "notNull": true 48 180 }, 49 181 "time": { 50 182 "name": "time", 51 183 "type": "integer", 52 184 "primaryKey": false, 53 185 "notNull": true, 54 - "autoincrement": false, 55 186 "default": 0 56 187 }, 57 188 "serves": { 58 189 "name": "serves", 59 190 "type": "integer", 60 191 "primaryKey": false, 61 - "notNull": false, 62 - "autoincrement": false 192 + "notNull": false 63 193 }, 64 194 "description": { 65 195 "name": "description", 66 196 "type": "text", 67 197 "primaryKey": false, 68 - "notNull": false, 69 - "autoincrement": false 198 + "notNull": false 70 199 }, 71 200 "ingredients": { 72 201 "name": "ingredients", 73 - "type": "text", 202 + "type": "jsonb", 74 203 "primaryKey": false, 75 - "notNull": true, 76 - "autoincrement": false 204 + "notNull": true 77 205 }, 78 206 "ingredients_count": { 79 207 "name": "ingredients_count", 80 208 "type": "integer", 81 209 "primaryKey": false, 82 210 "notNull": false, 83 - "autoincrement": false, 84 211 "generated": { 85 - "as": "(json_array_length(\"ingredients\"))", 86 - "type": "virtual" 212 + "as": "jsonb_array_length(\"recipes\".\"ingredients\")", 213 + "type": "stored" 87 214 } 88 215 }, 89 216 "steps": { 90 217 "name": "steps", 91 - "type": "text", 218 + "type": "jsonb", 92 219 "primaryKey": false, 93 - "notNull": true, 94 - "autoincrement": false 220 + "notNull": true 95 221 }, 96 222 "steps_count": { 97 223 "name": "steps_count", 98 224 "type": "integer", 99 225 "primaryKey": false, 100 226 "notNull": false, 101 - "autoincrement": false, 102 227 "generated": { 103 - "as": "(json_array_length(\"steps\"))", 104 - "type": "virtual" 228 + "as": "jsonb_array_length(\"recipes\".\"steps\")", 229 + "type": "stored" 105 230 } 106 231 }, 107 232 "created_at": { 108 233 "name": "created_at", 234 + "type": "text", 235 + "primaryKey": false, 236 + "notNull": true 237 + }, 238 + "ingested_at": { 239 + "name": "ingested_at", 109 240 "type": "text", 110 241 "primaryKey": false, 111 242 "notNull": true, 112 - "autoincrement": false 243 + "default": "CURRENT_TIMESTAMP" 113 244 } 114 245 }, 115 - "indexes": {}, 116 - "foreignKeys": {}, 246 + "indexes": { 247 + "recipes_title_idx": { 248 + "name": "recipes_title_idx", 249 + "columns": [ 250 + { 251 + "expression": "title", 252 + "isExpression": false, 253 + "asc": true, 254 + "nulls": "last" 255 + } 256 + ], 257 + "isUnique": false, 258 + "concurrently": false, 259 + "method": "btree", 260 + "with": {} 261 + }, 262 + "recipes_cid_idx": { 263 + "name": "recipes_cid_idx", 264 + "columns": [ 265 + { 266 + "expression": "cid", 267 + "isExpression": false, 268 + "asc": true, 269 + "nulls": "last" 270 + } 271 + ], 272 + "isUnique": false, 273 + "concurrently": false, 274 + "method": "btree", 275 + "with": {} 276 + }, 277 + "recipes_cat_idx": { 278 + "name": "recipes_cat_idx", 279 + "columns": [ 280 + { 281 + "expression": "created_at", 282 + "isExpression": false, 283 + "asc": true, 284 + "nulls": "last" 285 + } 286 + ], 287 + "isUnique": false, 288 + "concurrently": false, 289 + "method": "btree", 290 + "with": {} 291 + }, 292 + "recipes_iat_idx": { 293 + "name": "recipes_iat_idx", 294 + "columns": [ 295 + { 296 + "expression": "ingested_at", 297 + "isExpression": false, 298 + "asc": true, 299 + "nulls": "last" 300 + } 301 + ], 302 + "isUnique": false, 303 + "concurrently": false, 304 + "method": "btree", 305 + "with": {} 306 + } 307 + }, 308 + "foreignKeys": { 309 + "recipes_author_did_profiles_did_fk": { 310 + "name": "recipes_author_did_profiles_did_fk", 311 + "tableFrom": "recipes", 312 + "tableTo": "profiles", 313 + "columnsFrom": [ 314 + "author_did" 315 + ], 316 + "columnsTo": [ 317 + "did" 318 + ], 319 + "onDelete": "cascade", 320 + "onUpdate": "no action" 321 + } 322 + }, 117 323 "compositePrimaryKeys": { 118 324 "recipes_author_did_rkey_pk": { 325 + "name": "recipes_author_did_rkey_pk", 119 326 "columns": [ 120 327 "author_did", 121 328 "rkey" 122 - ], 123 - "name": "recipes_author_did_rkey_pk" 329 + ] 124 330 } 125 331 }, 126 332 "uniqueConstraints": {}, 127 - "checkConstraints": {} 333 + "policies": {}, 334 + "checkConstraints": {}, 335 + "isRLSEnabled": false 128 336 } 129 337 }, 130 - "views": {}, 131 338 "enums": {}, 339 + "schemas": {}, 340 + "sequences": {}, 341 + "roles": {}, 342 + "policies": {}, 343 + "views": {}, 132 344 "_meta": { 345 + "columns": {}, 133 346 "schemas": {}, 134 - "tables": {}, 135 - "columns": {} 136 - }, 137 - "internal": { 138 - "indexes": {} 347 + "tables": {} 139 348 } 140 349 }
-286
libs/database/migrations/meta/0001_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "d6f06b7d-9822-43ee-b96c-3b980a5e4953", 5 - "prevId": "7b2675f9-5d97-4fac-983e-978efd250faf", 6 - "tables": { 7 - "profiles": { 8 - "name": "profiles", 9 - "columns": { 10 - "uri": { 11 - "name": "uri", 12 - "type": "text", 13 - "primaryKey": false, 14 - "notNull": false, 15 - "autoincrement": false, 16 - "generated": { 17 - "as": "('at://' || \"did\" || '/?/self')", 18 - "type": "virtual" 19 - } 20 - }, 21 - "did": { 22 - "name": "did", 23 - "type": "text", 24 - "primaryKey": true, 25 - "notNull": true, 26 - "autoincrement": false 27 - }, 28 - "ingested_at": { 29 - "name": "ingested_at", 30 - "type": "text", 31 - "primaryKey": false, 32 - "notNull": true, 33 - "autoincrement": false, 34 - "default": "CURRENT_TIMESTAMP" 35 - }, 36 - "display_name": { 37 - "name": "display_name", 38 - "type": "text(640)", 39 - "primaryKey": false, 40 - "notNull": true, 41 - "autoincrement": false 42 - }, 43 - "description": { 44 - "name": "description", 45 - "type": "text(2500)", 46 - "primaryKey": false, 47 - "notNull": false, 48 - "autoincrement": false 49 - }, 50 - "pronouns": { 51 - "name": "pronouns", 52 - "type": "text(200)", 53 - "primaryKey": false, 54 - "notNull": false, 55 - "autoincrement": false 56 - }, 57 - "website": { 58 - "name": "website", 59 - "type": "text", 60 - "primaryKey": false, 61 - "notNull": false, 62 - "autoincrement": false 63 - }, 64 - "avatar": { 65 - "name": "avatar", 66 - "type": "text", 67 - "primaryKey": false, 68 - "notNull": false, 69 - "autoincrement": false 70 - }, 71 - "banner": { 72 - "name": "banner", 73 - "type": "text", 74 - "primaryKey": false, 75 - "notNull": false, 76 - "autoincrement": false 77 - }, 78 - "created_at": { 79 - "name": "created_at", 80 - "type": "text", 81 - "primaryKey": false, 82 - "notNull": true, 83 - "autoincrement": false 84 - } 85 - }, 86 - "indexes": { 87 - "profiles_cat_idx": { 88 - "name": "profiles_cat_idx", 89 - "columns": [ 90 - "created_at" 91 - ], 92 - "isUnique": false 93 - }, 94 - "profiles_iat_idx": { 95 - "name": "profiles_iat_idx", 96 - "columns": [ 97 - "ingested_at" 98 - ], 99 - "isUnique": false 100 - } 101 - }, 102 - "foreignKeys": {}, 103 - "compositePrimaryKeys": {}, 104 - "uniqueConstraints": {}, 105 - "checkConstraints": {} 106 - }, 107 - "recipes": { 108 - "name": "recipes", 109 - "columns": { 110 - "uri": { 111 - "name": "uri", 112 - "type": "text", 113 - "primaryKey": false, 114 - "notNull": false, 115 - "autoincrement": false, 116 - "generated": { 117 - "as": "('at://' || \"author_did\" || '/?/' || \"rkey\")", 118 - "type": "virtual" 119 - } 120 - }, 121 - "author_did": { 122 - "name": "author_did", 123 - "type": "text", 124 - "primaryKey": false, 125 - "notNull": true, 126 - "autoincrement": false 127 - }, 128 - "rkey": { 129 - "name": "rkey", 130 - "type": "text", 131 - "primaryKey": false, 132 - "notNull": true, 133 - "autoincrement": false 134 - }, 135 - "image": { 136 - "name": "image", 137 - "type": "text", 138 - "primaryKey": false, 139 - "notNull": false, 140 - "autoincrement": false 141 - }, 142 - "title": { 143 - "name": "title", 144 - "type": "text", 145 - "primaryKey": false, 146 - "notNull": true, 147 - "autoincrement": false 148 - }, 149 - "time": { 150 - "name": "time", 151 - "type": "integer", 152 - "primaryKey": false, 153 - "notNull": true, 154 - "autoincrement": false, 155 - "default": 0 156 - }, 157 - "serves": { 158 - "name": "serves", 159 - "type": "integer", 160 - "primaryKey": false, 161 - "notNull": false, 162 - "autoincrement": false 163 - }, 164 - "description": { 165 - "name": "description", 166 - "type": "text", 167 - "primaryKey": false, 168 - "notNull": false, 169 - "autoincrement": false 170 - }, 171 - "ingredients": { 172 - "name": "ingredients", 173 - "type": "text", 174 - "primaryKey": false, 175 - "notNull": true, 176 - "autoincrement": false 177 - }, 178 - "ingredients_count": { 179 - "name": "ingredients_count", 180 - "type": "integer", 181 - "primaryKey": false, 182 - "notNull": false, 183 - "autoincrement": false, 184 - "generated": { 185 - "as": "(json_array_length(\"ingredients\"))", 186 - "type": "virtual" 187 - } 188 - }, 189 - "steps": { 190 - "name": "steps", 191 - "type": "text", 192 - "primaryKey": false, 193 - "notNull": true, 194 - "autoincrement": false 195 - }, 196 - "steps_count": { 197 - "name": "steps_count", 198 - "type": "integer", 199 - "primaryKey": false, 200 - "notNull": false, 201 - "autoincrement": false, 202 - "generated": { 203 - "as": "(json_array_length(\"steps\"))", 204 - "type": "virtual" 205 - } 206 - }, 207 - "created_at": { 208 - "name": "created_at", 209 - "type": "text", 210 - "primaryKey": false, 211 - "notNull": true, 212 - "autoincrement": false 213 - }, 214 - "ingested_at": { 215 - "name": "ingested_at", 216 - "type": "text", 217 - "primaryKey": false, 218 - "notNull": true, 219 - "autoincrement": false, 220 - "default": "CURRENT_TIMESTAMP" 221 - } 222 - }, 223 - "indexes": { 224 - "recipes_title_idx": { 225 - "name": "recipes_title_idx", 226 - "columns": [ 227 - "title" 228 - ], 229 - "isUnique": false 230 - }, 231 - "recipes_cat_idx": { 232 - "name": "recipes_cat_idx", 233 - "columns": [ 234 - "created_at" 235 - ], 236 - "isUnique": false 237 - }, 238 - "recipes_iat_idx": { 239 - "name": "recipes_iat_idx", 240 - "columns": [ 241 - "ingested_at" 242 - ], 243 - "isUnique": false 244 - } 245 - }, 246 - "foreignKeys": { 247 - "recipes_author_did_profiles_did_fk": { 248 - "name": "recipes_author_did_profiles_did_fk", 249 - "tableFrom": "recipes", 250 - "tableTo": "profiles", 251 - "columnsFrom": [ 252 - "author_did" 253 - ], 254 - "columnsTo": [ 255 - "did" 256 - ], 257 - "onDelete": "cascade", 258 - "onUpdate": "no action" 259 - } 260 - }, 261 - "compositePrimaryKeys": { 262 - "recipes_author_did_rkey_pk": { 263 - "columns": [ 264 - "author_did", 265 - "rkey" 266 - ], 267 - "name": "recipes_author_did_rkey_pk" 268 - } 269 - }, 270 - "uniqueConstraints": {}, 271 - "checkConstraints": {} 272 - } 273 - }, 274 - "views": {}, 275 - "enums": {}, 276 - "_meta": { 277 - "schemas": {}, 278 - "tables": {}, 279 - "columns": { 280 - "\"recipes\".\"image_ref\"": "\"recipes\".\"image\"" 281 - } 282 - }, 283 - "internal": { 284 - "indexes": {} 285 - } 286 - }
-284
libs/database/migrations/meta/0002_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "25f6fc02-0357-4a4a-a43c-6fc138a21401", 5 - "prevId": "d6f06b7d-9822-43ee-b96c-3b980a5e4953", 6 - "tables": { 7 - "profiles": { 8 - "name": "profiles", 9 - "columns": { 10 - "uri": { 11 - "name": "uri", 12 - "type": "text", 13 - "primaryKey": false, 14 - "notNull": false, 15 - "autoincrement": false, 16 - "generated": { 17 - "as": "('at://' || \"did\" || '/blue.recipes.actor.profile/self')", 18 - "type": "virtual" 19 - } 20 - }, 21 - "did": { 22 - "name": "did", 23 - "type": "text", 24 - "primaryKey": true, 25 - "notNull": true, 26 - "autoincrement": false 27 - }, 28 - "ingested_at": { 29 - "name": "ingested_at", 30 - "type": "text", 31 - "primaryKey": false, 32 - "notNull": true, 33 - "autoincrement": false, 34 - "default": "CURRENT_TIMESTAMP" 35 - }, 36 - "display_name": { 37 - "name": "display_name", 38 - "type": "text(640)", 39 - "primaryKey": false, 40 - "notNull": true, 41 - "autoincrement": false 42 - }, 43 - "description": { 44 - "name": "description", 45 - "type": "text(2500)", 46 - "primaryKey": false, 47 - "notNull": false, 48 - "autoincrement": false 49 - }, 50 - "pronouns": { 51 - "name": "pronouns", 52 - "type": "text(200)", 53 - "primaryKey": false, 54 - "notNull": false, 55 - "autoincrement": false 56 - }, 57 - "website": { 58 - "name": "website", 59 - "type": "text", 60 - "primaryKey": false, 61 - "notNull": false, 62 - "autoincrement": false 63 - }, 64 - "avatar": { 65 - "name": "avatar", 66 - "type": "text", 67 - "primaryKey": false, 68 - "notNull": false, 69 - "autoincrement": false 70 - }, 71 - "banner": { 72 - "name": "banner", 73 - "type": "text", 74 - "primaryKey": false, 75 - "notNull": false, 76 - "autoincrement": false 77 - }, 78 - "created_at": { 79 - "name": "created_at", 80 - "type": "text", 81 - "primaryKey": false, 82 - "notNull": true, 83 - "autoincrement": false 84 - } 85 - }, 86 - "indexes": { 87 - "profiles_cat_idx": { 88 - "name": "profiles_cat_idx", 89 - "columns": [ 90 - "created_at" 91 - ], 92 - "isUnique": false 93 - }, 94 - "profiles_iat_idx": { 95 - "name": "profiles_iat_idx", 96 - "columns": [ 97 - "ingested_at" 98 - ], 99 - "isUnique": false 100 - } 101 - }, 102 - "foreignKeys": {}, 103 - "compositePrimaryKeys": {}, 104 - "uniqueConstraints": {}, 105 - "checkConstraints": {} 106 - }, 107 - "recipes": { 108 - "name": "recipes", 109 - "columns": { 110 - "uri": { 111 - "name": "uri", 112 - "type": "text", 113 - "primaryKey": false, 114 - "notNull": false, 115 - "autoincrement": false, 116 - "generated": { 117 - "as": "('at://' || \"author_did\" || '/blue.recipes.feed.recipe/' || \"rkey\")", 118 - "type": "virtual" 119 - } 120 - }, 121 - "author_did": { 122 - "name": "author_did", 123 - "type": "text", 124 - "primaryKey": false, 125 - "notNull": true, 126 - "autoincrement": false 127 - }, 128 - "rkey": { 129 - "name": "rkey", 130 - "type": "text", 131 - "primaryKey": false, 132 - "notNull": true, 133 - "autoincrement": false 134 - }, 135 - "image": { 136 - "name": "image", 137 - "type": "text", 138 - "primaryKey": false, 139 - "notNull": false, 140 - "autoincrement": false 141 - }, 142 - "title": { 143 - "name": "title", 144 - "type": "text", 145 - "primaryKey": false, 146 - "notNull": true, 147 - "autoincrement": false 148 - }, 149 - "time": { 150 - "name": "time", 151 - "type": "integer", 152 - "primaryKey": false, 153 - "notNull": true, 154 - "autoincrement": false, 155 - "default": 0 156 - }, 157 - "serves": { 158 - "name": "serves", 159 - "type": "integer", 160 - "primaryKey": false, 161 - "notNull": false, 162 - "autoincrement": false 163 - }, 164 - "description": { 165 - "name": "description", 166 - "type": "text", 167 - "primaryKey": false, 168 - "notNull": false, 169 - "autoincrement": false 170 - }, 171 - "ingredients": { 172 - "name": "ingredients", 173 - "type": "text", 174 - "primaryKey": false, 175 - "notNull": true, 176 - "autoincrement": false 177 - }, 178 - "ingredients_count": { 179 - "name": "ingredients_count", 180 - "type": "integer", 181 - "primaryKey": false, 182 - "notNull": false, 183 - "autoincrement": false, 184 - "generated": { 185 - "as": "(json_array_length(\"ingredients\"))", 186 - "type": "virtual" 187 - } 188 - }, 189 - "steps": { 190 - "name": "steps", 191 - "type": "text", 192 - "primaryKey": false, 193 - "notNull": true, 194 - "autoincrement": false 195 - }, 196 - "steps_count": { 197 - "name": "steps_count", 198 - "type": "integer", 199 - "primaryKey": false, 200 - "notNull": false, 201 - "autoincrement": false, 202 - "generated": { 203 - "as": "(json_array_length(\"steps\"))", 204 - "type": "virtual" 205 - } 206 - }, 207 - "created_at": { 208 - "name": "created_at", 209 - "type": "text", 210 - "primaryKey": false, 211 - "notNull": true, 212 - "autoincrement": false 213 - }, 214 - "ingested_at": { 215 - "name": "ingested_at", 216 - "type": "text", 217 - "primaryKey": false, 218 - "notNull": true, 219 - "autoincrement": false, 220 - "default": "CURRENT_TIMESTAMP" 221 - } 222 - }, 223 - "indexes": { 224 - "recipes_title_idx": { 225 - "name": "recipes_title_idx", 226 - "columns": [ 227 - "title" 228 - ], 229 - "isUnique": false 230 - }, 231 - "recipes_cat_idx": { 232 - "name": "recipes_cat_idx", 233 - "columns": [ 234 - "created_at" 235 - ], 236 - "isUnique": false 237 - }, 238 - "recipes_iat_idx": { 239 - "name": "recipes_iat_idx", 240 - "columns": [ 241 - "ingested_at" 242 - ], 243 - "isUnique": false 244 - } 245 - }, 246 - "foreignKeys": { 247 - "recipes_author_did_profiles_did_fk": { 248 - "name": "recipes_author_did_profiles_did_fk", 249 - "tableFrom": "recipes", 250 - "tableTo": "profiles", 251 - "columnsFrom": [ 252 - "author_did" 253 - ], 254 - "columnsTo": [ 255 - "did" 256 - ], 257 - "onDelete": "cascade", 258 - "onUpdate": "no action" 259 - } 260 - }, 261 - "compositePrimaryKeys": { 262 - "recipes_author_did_rkey_pk": { 263 - "columns": [ 264 - "author_did", 265 - "rkey" 266 - ], 267 - "name": "recipes_author_did_rkey_pk" 268 - } 269 - }, 270 - "uniqueConstraints": {}, 271 - "checkConstraints": {} 272 - } 273 - }, 274 - "views": {}, 275 - "enums": {}, 276 - "_meta": { 277 - "schemas": {}, 278 - "tables": {}, 279 - "columns": {} 280 - }, 281 - "internal": { 282 - "indexes": {} 283 - } 284 - }
-312
libs/database/migrations/meta/0003_snapshot.json
··· 1 - { 2 - "version": "6", 3 - "dialect": "sqlite", 4 - "id": "ca3337d9-69a0-468d-8364-0f05e91a0233", 5 - "prevId": "25f6fc02-0357-4a4a-a43c-6fc138a21401", 6 - "tables": { 7 - "profiles": { 8 - "name": "profiles", 9 - "columns": { 10 - "uri": { 11 - "name": "uri", 12 - "type": "text", 13 - "primaryKey": false, 14 - "notNull": false, 15 - "autoincrement": false, 16 - "generated": { 17 - "as": "('at://' || \"did\" || '/blue.recipes.actor.profile/self')", 18 - "type": "virtual" 19 - } 20 - }, 21 - "cid": { 22 - "name": "cid", 23 - "type": "text", 24 - "primaryKey": false, 25 - "notNull": true, 26 - "autoincrement": false 27 - }, 28 - "did": { 29 - "name": "did", 30 - "type": "text", 31 - "primaryKey": true, 32 - "notNull": true, 33 - "autoincrement": false 34 - }, 35 - "ingested_at": { 36 - "name": "ingested_at", 37 - "type": "text", 38 - "primaryKey": false, 39 - "notNull": true, 40 - "autoincrement": false, 41 - "default": "CURRENT_TIMESTAMP" 42 - }, 43 - "display_name": { 44 - "name": "display_name", 45 - "type": "text(640)", 46 - "primaryKey": false, 47 - "notNull": true, 48 - "autoincrement": false 49 - }, 50 - "description": { 51 - "name": "description", 52 - "type": "text(2500)", 53 - "primaryKey": false, 54 - "notNull": false, 55 - "autoincrement": false 56 - }, 57 - "pronouns": { 58 - "name": "pronouns", 59 - "type": "text(200)", 60 - "primaryKey": false, 61 - "notNull": false, 62 - "autoincrement": false 63 - }, 64 - "website": { 65 - "name": "website", 66 - "type": "text", 67 - "primaryKey": false, 68 - "notNull": false, 69 - "autoincrement": false 70 - }, 71 - "avatar": { 72 - "name": "avatar", 73 - "type": "text", 74 - "primaryKey": false, 75 - "notNull": false, 76 - "autoincrement": false 77 - }, 78 - "banner": { 79 - "name": "banner", 80 - "type": "text", 81 - "primaryKey": false, 82 - "notNull": false, 83 - "autoincrement": false 84 - }, 85 - "created_at": { 86 - "name": "created_at", 87 - "type": "text", 88 - "primaryKey": false, 89 - "notNull": true, 90 - "autoincrement": false 91 - } 92 - }, 93 - "indexes": { 94 - "profiles_cid_idx": { 95 - "name": "profiles_cid_idx", 96 - "columns": [ 97 - "cid" 98 - ], 99 - "isUnique": false 100 - }, 101 - "profiles_cat_idx": { 102 - "name": "profiles_cat_idx", 103 - "columns": [ 104 - "created_at" 105 - ], 106 - "isUnique": false 107 - }, 108 - "profiles_iat_idx": { 109 - "name": "profiles_iat_idx", 110 - "columns": [ 111 - "ingested_at" 112 - ], 113 - "isUnique": false 114 - } 115 - }, 116 - "foreignKeys": {}, 117 - "compositePrimaryKeys": {}, 118 - "uniqueConstraints": {}, 119 - "checkConstraints": {} 120 - }, 121 - "recipes": { 122 - "name": "recipes", 123 - "columns": { 124 - "uri": { 125 - "name": "uri", 126 - "type": "text", 127 - "primaryKey": false, 128 - "notNull": false, 129 - "autoincrement": false, 130 - "generated": { 131 - "as": "('at://' || \"author_did\" || '/blue.recipes.feed.recipe/' || \"rkey\")", 132 - "type": "virtual" 133 - } 134 - }, 135 - "cid": { 136 - "name": "cid", 137 - "type": "text", 138 - "primaryKey": false, 139 - "notNull": true, 140 - "autoincrement": false 141 - }, 142 - "author_did": { 143 - "name": "author_did", 144 - "type": "text", 145 - "primaryKey": false, 146 - "notNull": true, 147 - "autoincrement": false 148 - }, 149 - "rkey": { 150 - "name": "rkey", 151 - "type": "text", 152 - "primaryKey": false, 153 - "notNull": true, 154 - "autoincrement": false 155 - }, 156 - "image": { 157 - "name": "image", 158 - "type": "text", 159 - "primaryKey": false, 160 - "notNull": false, 161 - "autoincrement": false 162 - }, 163 - "title": { 164 - "name": "title", 165 - "type": "text", 166 - "primaryKey": false, 167 - "notNull": true, 168 - "autoincrement": false 169 - }, 170 - "time": { 171 - "name": "time", 172 - "type": "integer", 173 - "primaryKey": false, 174 - "notNull": true, 175 - "autoincrement": false, 176 - "default": 0 177 - }, 178 - "serves": { 179 - "name": "serves", 180 - "type": "integer", 181 - "primaryKey": false, 182 - "notNull": false, 183 - "autoincrement": false 184 - }, 185 - "description": { 186 - "name": "description", 187 - "type": "text", 188 - "primaryKey": false, 189 - "notNull": false, 190 - "autoincrement": false 191 - }, 192 - "ingredients": { 193 - "name": "ingredients", 194 - "type": "text", 195 - "primaryKey": false, 196 - "notNull": true, 197 - "autoincrement": false 198 - }, 199 - "ingredients_count": { 200 - "name": "ingredients_count", 201 - "type": "integer", 202 - "primaryKey": false, 203 - "notNull": false, 204 - "autoincrement": false, 205 - "generated": { 206 - "as": "(json_array_length(\"ingredients\"))", 207 - "type": "virtual" 208 - } 209 - }, 210 - "steps": { 211 - "name": "steps", 212 - "type": "text", 213 - "primaryKey": false, 214 - "notNull": true, 215 - "autoincrement": false 216 - }, 217 - "steps_count": { 218 - "name": "steps_count", 219 - "type": "integer", 220 - "primaryKey": false, 221 - "notNull": false, 222 - "autoincrement": false, 223 - "generated": { 224 - "as": "(json_array_length(\"steps\"))", 225 - "type": "virtual" 226 - } 227 - }, 228 - "created_at": { 229 - "name": "created_at", 230 - "type": "text", 231 - "primaryKey": false, 232 - "notNull": true, 233 - "autoincrement": false 234 - }, 235 - "ingested_at": { 236 - "name": "ingested_at", 237 - "type": "text", 238 - "primaryKey": false, 239 - "notNull": true, 240 - "autoincrement": false, 241 - "default": "CURRENT_TIMESTAMP" 242 - } 243 - }, 244 - "indexes": { 245 - "recipes_title_idx": { 246 - "name": "recipes_title_idx", 247 - "columns": [ 248 - "title" 249 - ], 250 - "isUnique": false 251 - }, 252 - "recipes_cid_idx": { 253 - "name": "recipes_cid_idx", 254 - "columns": [ 255 - "cid" 256 - ], 257 - "isUnique": false 258 - }, 259 - "recipes_cat_idx": { 260 - "name": "recipes_cat_idx", 261 - "columns": [ 262 - "created_at" 263 - ], 264 - "isUnique": false 265 - }, 266 - "recipes_iat_idx": { 267 - "name": "recipes_iat_idx", 268 - "columns": [ 269 - "ingested_at" 270 - ], 271 - "isUnique": false 272 - } 273 - }, 274 - "foreignKeys": { 275 - "recipes_author_did_profiles_did_fk": { 276 - "name": "recipes_author_did_profiles_did_fk", 277 - "tableFrom": "recipes", 278 - "tableTo": "profiles", 279 - "columnsFrom": [ 280 - "author_did" 281 - ], 282 - "columnsTo": [ 283 - "did" 284 - ], 285 - "onDelete": "cascade", 286 - "onUpdate": "no action" 287 - } 288 - }, 289 - "compositePrimaryKeys": { 290 - "recipes_author_did_rkey_pk": { 291 - "columns": [ 292 - "author_did", 293 - "rkey" 294 - ], 295 - "name": "recipes_author_did_rkey_pk" 296 - } 297 - }, 298 - "uniqueConstraints": {}, 299 - "checkConstraints": {} 300 - } 301 - }, 302 - "views": {}, 303 - "enums": {}, 304 - "_meta": { 305 - "schemas": {}, 306 - "tables": {}, 307 - "columns": {} 308 - }, 309 - "internal": { 310 - "indexes": {} 311 - } 312 - }
+4 -25
libs/database/migrations/meta/_journal.json
··· 1 1 { 2 2 "version": "7", 3 - "dialect": "sqlite", 3 + "dialect": "postgresql", 4 4 "entries": [ 5 5 { 6 6 "idx": 0, 7 - "version": "6", 8 - "when": 1764024817179, 9 - "tag": "0000_kind_ultron", 10 - "breakpoints": true 11 - }, 12 - { 13 - "idx": 1, 14 - "version": "6", 15 - "when": 1764102063385, 16 - "tag": "0001_past_umar", 17 - "breakpoints": true 18 - }, 19 - { 20 - "idx": 2, 21 - "version": "6", 22 - "when": 1764113357363, 23 - "tag": "0002_cheerful_venom", 24 - "breakpoints": true 25 - }, 26 - { 27 - "idx": 3, 28 - "version": "6", 29 - "when": 1764113735823, 30 - "tag": "0003_long_blue_marvel", 7 + "version": "7", 8 + "when": 1764420650497, 9 + "tag": "0000_young_hellcat", 31 10 "breakpoints": true 32 11 } 33 12 ]
+2
libs/database/package.json
··· 27 27 "@cookware/tsconfig": "workspace:*", 28 28 "@types/bun": "catalog:", 29 29 "@types/node": "^22.10.1", 30 + "@types/pg": "^8.15.6", 30 31 "drizzle-kit": "^0.29.0", 31 32 "typescript": "^5.2.2" 32 33 }, 33 34 "dependencies": { 34 35 "@libsql/client": "^0.15.15", 35 36 "drizzle-orm": "catalog:", 37 + "pg": "^8.16.3", 36 38 "zod": "^3.23.8" 37 39 } 38 40 }
+2
libs/lexicons/lexicons/feed/defs.tsp
··· 6 6 model RecipeView { 7 7 @required uri: atUri; 8 8 @required cid: cid; 9 + @required rkey: string; 10 + imageUrl?: url; 9 11 @required author: blue.recipes.actor.defs.ProfileViewBasic; 10 12 @required record: blue.recipes.feed.recipe.Main; 11 13 @required indexedAt: datetime;
+1 -1
libs/lexicons/lexicons/profiles/defs.tsp
··· 10 10 displayName?: string; 11 11 12 12 pronouns?: string; 13 - avatar?: uri; 13 + avatar?: url; 14 14 15 15 @format("datetime") 16 16 createdAt?: string;
+1 -1
libs/lexicons/lib/types/blue/recipes/actor/defs.ts
··· 5 5 $type: /*#__PURE__*/ v.optional( 6 6 /*#__PURE__*/ v.literal("blue.recipes.actor.defs#profileViewBasic"), 7 7 ), 8 - avatar: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.genericUriString()), 8 + avatar: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), 9 9 createdAt: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), 10 10 did: /*#__PURE__*/ v.didString(), 11 11 /**
+2
libs/lexicons/lib/types/blue/recipes/feed/defs.ts
··· 18 18 return BlueRecipesActorDefs.profileViewBasicSchema; 19 19 }, 20 20 cid: /*#__PURE__*/ v.cidString(), 21 + imageUrl: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.string()), 21 22 indexedAt: /*#__PURE__*/ v.datetimeString(), 22 23 get record() { 23 24 return BlueRecipesFeedRecipe.mainSchema; 24 25 }, 26 + rkey: /*#__PURE__*/ v.string(), 25 27 uri: /*#__PURE__*/ v.resourceUriString(), 26 28 }); 27 29
+2 -1
libs/lexicons/tsconfig.json
··· 2 2 "extends": "@cookware/tsconfig/base.json", 3 3 "include": ["lib", "scripts"], 4 4 "compilerOptions": { 5 - "noEmit": true 5 + "noEmit": true, 6 + "types": ["bun"] 6 7 } 7 8 }
+13 -5
libs/tsconfig/base.json
··· 1 + /* vim:ft=jsonc */ 1 2 { 2 3 "$schema": "https://json.schemastore.org/tsconfig", 3 4 "display": "Default", ··· 8 9 "incremental": false, 9 10 "isolatedModules": true, 10 11 "lib": ["es2022", "DOM", "DOM.Iterable"], 11 - "module": "NodeNext", 12 - "moduleDetection": "force", 13 - "moduleResolution": "NodeNext", 14 - "noUncheckedIndexedAccess": true, 12 + "module": "nodenext", 13 + "moduleResolution": "nodenext", 14 + "verbatimModuleSyntax": true, 15 15 "resolveJsonModule": true, 16 16 "skipLibCheck": true, 17 17 "strict": true, 18 - "target": "ES2022" 18 + "target": "ES2022", 19 + 20 + /* Rules */ 21 + "noUncheckedIndexedAccess": true, 22 + "noUnusedLocals": true, 23 + "noUnusedParameters": true, 24 + "erasableSyntaxOnly": true, 25 + "noFallthroughCasesInSwitch": true, 26 + "noUncheckedSideEffectImports": true 19 27 } 20 28 }
+3 -3
libs/tsconfig/react.json
··· 1 + /* vim:ft=jsonc */ 1 2 { 2 3 "$schema": "https://json.schemastore.org/tsconfig", 3 - "display": "Next.js", 4 4 "extends": "./base.json", 5 5 "compilerOptions": { 6 6 "module": "ESNext", 7 7 "moduleResolution": "Bundler", 8 8 "allowJs": true, 9 - "jsx": "preserve", 10 - "noEmit": true 9 + "jsx": "react-jsx", 10 + "noEmit": true, 11 11 } 12 12 }
+8
package.json
··· 3 3 "private": true, 4 4 "packageManager": "bun@1.3.3", 5 5 "devDependencies": { 6 + "@tanstack/react-router-devtools": "^1.140.0", 7 + "@tanstack/router-plugin": "^1.140.0", 6 8 "turbo": "^2.3.3", 7 9 "typescript": "^5.9.3" 8 10 }, ··· 19 21 "@atcute/atproto": "^3.1.9", 20 22 "@atcute/bluesky": "^3.2.11", 21 23 "@atcute/client": "^4.0.5", 24 + "@atcute/identity": "^1.1.3", 25 + "@atcute/identity-resolver": "^1.1.4", 22 26 "@atcute/lexicons": "^1.2.5", 23 27 "drizzle-orm": "^0.44.7" 24 28 } 29 + }, 30 + "dependencies": { 31 + "@atcute/oauth-browser-client": "^2.0.2", 32 + "@tanstack/react-router": "^1.140.0" 25 33 } 26 34 }