The recipes.blue monorepo recipes.blue
recipes appview atproto

Compare changes

Choose any two refs to compare.

Changed files
+5377 -4752
apps
api
app
ingester
web
libs
database
lib
lexicons
tsconfig
-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();
+1 -1
apps/api/src/index.ts
··· 50 50 app.route('/xrpc', xrpcApp); 51 51 52 52 const server = Bun.serve({ 53 - port: process.env.PORT || 3000, 53 + port: process.env.PORT || 4000, 54 54 fetch: app.fetch, 55 55 }); 56 56
+4 -4
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 { ProfileViewBasic } from '../../../../libs/lexicons/dist/types/blue/recipes/actor/defs.js'; 8 - import { Blob, LegacyBlob } from '@atcute/lexicons'; 7 + import type { BlueRecipesActorDefs } from '@cookware/lexicons'; 8 + import type { Blob, LegacyBlob } from '@atcute/lexicons'; 9 9 import { buildCdnUrl } from './cdn.js'; 10 10 11 11 const handleResolver = new CompositeHandleResolver({ ··· 53 53 pronouns: string | null; 54 54 avatarRef: Blob | LegacyBlob | null; 55 55 createdAt: Date; 56 - }, redis: RedisClient): Promise<ProfileViewBasic> => ({ 56 + }, redis: RedisClient): Promise<BlueRecipesActorDefs.ProfileViewBasic> => ({ 57 57 did: author.did, 58 58 handle: await getHandle(author.did, redis), 59 59 displayName: author.displayName,
+1 -1
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';
+3 -3
apps/api/src/xrpc/blue.recipes.feed.getRecipe.ts
··· 1 1 import { json, XRPCRouter, XRPCError } from '@atcute/xrpc-server'; 2 - import { BlueRecipesFeedDefs, BlueRecipesFeedGetRecipe, BlueRecipesFeedRecipe } from '@cookware/lexicons'; 2 + import { BlueRecipesFeedGetRecipe, BlueRecipesFeedRecipe } from '@cookware/lexicons'; 3 3 import { db, and, or, eq } from '@cookware/database'; 4 4 import { buildProfileViewBasic, parseDid } from '../util/api.js'; 5 - import { Logger } from 'pino'; 6 - import { parseResourceUri, ResourceUri } from '@atcute/lexicons'; 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';
+2 -2
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 10 import { buildCdnUrl } from '../util/cdn.js';
+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>
+28 -53
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", 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", 30 16 "@radix-ui/react-label": "^2.1.8", 31 17 "@radix-ui/react-separator": "^1.1.8", 32 18 "@radix-ui/react-slot": "^1.2.4", 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", 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", 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", 57 35 "@vitejs/plugin-react": "^5.1.1", 58 - "@vitejs/plugin-react-swc": "^3.5.0", 59 - "autoprefixer": "^10.4.20", 60 - "babel-plugin-react-compiler": "^1.0.0", 61 - "cssnano": "^7.0.6", 62 - "eslint": "^9.15.0", 63 - "eslint-plugin-react-hooks": "^5.0.0", 64 - "eslint-plugin-react-refresh": "^0.4.14", 65 - "globals": "^15.12.0", 66 - "postcss": "^8.4.49", 67 - "react": "19.0.0", 68 - "tailwindcss": "^3.4.16", 69 - "typescript": "~5.6.2", 70 - "typescript-eslint": "^8.15.0", 71 - "vite": "^7.2.4" 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" 72 47 } 73 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 { useSession } 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 } = useSession(); 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 { useSession } 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, signOut } = useSession(); 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={userQuery.data.avatar} 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={userQuery.data.avatar} 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={() => signOut()}> 105 - <LogOut /> 106 - Log out 107 - </DropdownMenuItem> 108 - </DropdownMenuContent> 109 - </DropdownMenu> 110 - </SidebarMenuItem> 111 - </SidebarMenu> 112 - ) 113 - }
-62
apps/web/src/components/query-placeholder.tsx
··· 1 - import type { UseQueryResult } from '@tanstack/react-query'; 2 - import { 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 { isXRPCErrorPayload } from '@atcute/client'; 7 - 8 - type QueryPlaceholderProps<TData, TError> = { 9 - query: UseQueryResult<TData, TError>; 10 - cards?: boolean; 11 - cardsCount?: number; 12 - noData?: ReactNode; 13 - children: ReactNode | ReactNode[] | ((data: TData) => ReactNode | ReactNode[]); 14 - }; 15 - 16 - const QueryPlaceholder = <TData = {}, TError = Error>( 17 - { 18 - query, 19 - children, 20 - cards = false, 21 - cardsCount = 3, 22 - noData = <></>, 23 - }: QueryPlaceholderProps<TData, TError> 24 - ) => { 25 - if (query.isPending || query.isLoading) { 26 - if (cards) { 27 - return [...Array(cardsCount)].map((_, i) => <Skeleton key={i} className="h-[200px] w-full rounded-lg" />); 28 - } 29 - 30 - return ( 31 - <p>Loading...</p> 32 - ) 33 - } else if (query.isError) { 34 - const { error } = query; 35 - let errMsg = 'Unknown'; 36 - if (isXRPCErrorPayload(error)) { 37 - errMsg = error.message ?? `XRPC_${error.error}`; 38 - } if (error instanceof Error) { 39 - errMsg = `${error.message} (${error.name})`; 40 - } 41 - 42 - return ( 43 - <Alert variant="destructive"> 44 - <AlertCircle className="size-4" /> 45 - 46 - <AlertTitle>Error fetching data.</AlertTitle> 47 - <AlertDescription> 48 - The data you were trying to see failed to fetch.<br/> 49 - <b>Error code: {errMsg}</b> 50 - </AlertDescription> 51 - </Alert> 52 - ) 53 - } else if (query.data) { 54 - if (typeof children === 'function') { 55 - return children(query.data); 56 - } 57 - return children; 58 - } 59 - return noData; 60 - }; 61 - 62 - export default QueryPlaceholder;
-72
apps/web/src/components/recipe-card.tsx
··· 1 - import { Card, CardContent, CardFooter, CardHeader } from "./ui/card"; 2 - import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar"; 3 - import { Link } from "@tanstack/react-router"; 4 - import { Clock, ListOrdered, Users, Utensils } from "lucide-react"; 5 - import { BlueRecipesFeedGetRecipes } from "@cookware/lexicons"; 6 - 7 - type RecipeCardProps = { 8 - recipe: BlueRecipesFeedGetRecipes.$output['recipes'][0]; 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.record.image && 22 - <div className="relative h-48 w-full"> 23 - <img 24 - src={recipe.imageUrl} 25 - alt={recipe.record.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.record.title}</h3> 33 - <p className="text-sm text-muted-foreground mb-4"> 34 - {truncateDescription(recipe.record.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.avatar} 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.record.ingredients.length}</span> 50 - </div> 51 - 52 - <div className="flex items-center"> 53 - <ListOrdered className="w-4 h-4 mr-1" /> 54 - <span>{recipe.record.steps.length}</span> 55 - </div> 56 - 57 - <div className="flex items-center"> 58 - <Users className="w-4 h-4 mr-1" /> 59 - <span>{recipe.record.serves}</span> 60 - </div> 61 - 62 - <div className="flex items-center"> 63 - <Clock className="w-4 h-4 mr-1" /> 64 - <span>{recipe.record.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 }
+17 -11
apps/web/src/components/ui/field.tsx
··· 1 + "use client" 2 + 1 3 import { useMemo } from "react" 2 4 import { cva, type VariantProps } from "class-variance-authority" 3 5 ··· 53 55 } 54 56 55 57 const fieldVariants = cva( 56 - "group/field data-[invalid=true]:text-destructive flex w-full gap-3", 58 + "group/field flex w-full gap-3 data-[invalid=true]:text-destructive", 57 59 { 58 60 variants: { 59 61 orientation: { ··· 61 63 horizontal: [ 62 64 "flex-row items-center", 63 65 "[&>[data-slot=field-label]]:flex-auto", 64 - "has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px has-[>[data-slot=field-content]]:items-start", 66 + "has-[>[data-slot=field-content]]:items-start has-[>[data-slot=field-content]]:[&>[role=checkbox],[role=radio]]:mt-px", 65 67 ], 66 68 responsive: [ 67 - "@md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto flex-col [&>*]:w-full [&>.sr-only]:w-auto", 69 + "flex-col [&>*]:w-full [&>.sr-only]:w-auto @md/field-group:flex-row @md/field-group:items-center @md/field-group:[&>*]:w-auto", 68 70 "@md/field-group:[&>[data-slot=field-label]]:flex-auto", 69 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", 70 72 ], ··· 114 116 data-slot="field-label" 115 117 className={cn( 116 118 "group/field-label peer/field-label flex w-fit gap-2 leading-snug group-data-[disabled=true]/field:opacity-50", 117 - "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", 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", 118 120 "has-data-[state=checked]:bg-primary/5 has-data-[state=checked]:border-primary dark:has-data-[state=checked]:bg-primary/10", 119 121 className 120 122 )} ··· 128 130 <div 129 131 data-slot="field-label" 130 132 className={cn( 131 - "flex w-fit items-center gap-2 text-sm font-medium leading-snug group-data-[disabled=true]/field:opacity-50", 133 + "flex w-fit items-center gap-2 text-sm leading-snug font-medium group-data-[disabled=true]/field:opacity-50", 132 134 className 133 135 )} 134 136 {...props} ··· 141 143 <p 142 144 data-slot="field-description" 143 145 className={cn( 144 - "text-muted-foreground text-sm font-normal leading-normal group-has-[[data-orientation=horizontal]]/field:text-balance", 145 - "nth-last-2:-mt-1 last:mt-0 [[data-variant=legend]+&]:-mt-1.5", 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", 146 148 "[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4", 147 149 className 148 150 )} ··· 194 196 return children 195 197 } 196 198 197 - if (!errors) { 199 + if (!errors?.length) { 198 200 return null 199 201 } 200 202 201 - if (errors?.length === 1 && errors[0]?.message) { 202 - return errors[0].message 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 203 209 } 204 210 205 211 return ( 206 212 <ul className="ml-4 flex list-disc flex-col gap-1"> 207 - {errors.map( 213 + {uniqueErrors.map( 208 214 (error, index) => 209 215 error?.message && <li key={index}>{error.message}</li> 210 216 )}
-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 }
+10 -13
apps/web/src/components/ui/separator.tsx
··· 5 5 6 6 import { cn } from "@/lib/utils" 7 7 8 - const Separator = React.forwardRef< 9 - React.ElementRef<typeof SeparatorPrimitive.Root>, 10 - React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root> 11 - >( 12 - ( 13 - { className, orientation = "horizontal", decorative = true, ...props }, 14 - ref 15 - ) => ( 8 + function Separator({ 9 + className, 10 + orientation = "horizontal", 11 + decorative = true, 12 + ...props 13 + }: React.ComponentProps<typeof SeparatorPrimitive.Root>) { 14 + return ( 16 15 <SeparatorPrimitive.Root 17 - ref={ref} 16 + data-slot="separator" 18 17 decorative={decorative} 19 18 orientation={orientation} 20 19 className={cn( 21 - "shrink-0 bg-border", 22 - 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", 23 21 className 24 22 )} 25 23 {...props} 26 24 /> 27 25 ) 28 - ) 29 - Separator.displayName = SeparatorPrimitive.Root.displayName 26 + } 30 27 31 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 - }
-7
apps/web/src/hooks/use-xrpc.tsx
··· 1 - import { useClient } from "@/state/auth"; 2 - 3 - /** @deprecated Use `useClient` from `state/auth/client` instead. */ 4 - export function useXrpc() { 5 - const client = useClient(); 6 - return client; 7 - }
+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 -69
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 { ThemeProvider } from './components/theme-provider'; 10 - import { CompositeDidDocumentResolver, PlcDidDocumentResolver, WebDidDocumentResolver, XrpcHandleResolver } from '@atcute/identity-resolver'; 11 - import { SessionProvider, useSession } from './state/auth/session'; 12 - import { ClientProvider, useClient } from './state/auth'; 4 + import { routeTree } from './routeTree.gen'; 13 5 14 - const router = createRouter({ 15 - routeTree, 16 - context: { 17 - session: undefined!, 18 - client: undefined!, 19 - }, 20 - }); 6 + import './index.css'; 21 7 22 - declare module '@tanstack/react-router' { 23 - interface Register { 24 - router: typeof router 25 - } 8 + const router = createRouter({ routeTree }); 9 + 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 + ); 26 18 } 27 - 28 - configureOAuth({ 29 - metadata: { 30 - client_id: import.meta.env.VITE_OAUTH_CLIENT_ID, 31 - redirect_uri: import.meta.env.VITE_OAUTH_REDIRECT_URI, 32 - }, 33 - identityResolver: defaultIdentityResolver({ 34 - handleResolver: new XrpcHandleResolver({ serviceUrl: 'https://slingshot.microcosm.blue' }), 35 - didDocumentResolver: new CompositeDidDocumentResolver({ 36 - methods: { 37 - plc: new PlcDidDocumentResolver(), 38 - web: new WebDidDocumentResolver(), 39 - }, 40 - }), 41 - }), 42 - }); 43 - 44 - const queryClient = new QueryClient({ 45 - defaultOptions: { 46 - queries: { 47 - refetchOnWindowFocus: false, 48 - structuralSharing: false, 49 - retry: false, 50 - } 51 - } 52 - }); 53 - 54 - const InnerApp = () => { 55 - const session = useSession(); 56 - const client = useClient(); 57 - return <RouterProvider router={router} context={{ session, client }} /> 58 - }; 59 - 60 - createRoot(document.getElementById('root')!).render( 61 - <StrictMode> 62 - <SessionProvider> 63 - <ClientProvider> 64 - <ThemeProvider defaultTheme="dark" storageKey="recipes-theme"> 65 - <QueryClientProvider client={queryClient}> 66 - <InnerApp /> 67 - <ReactQueryDevtools initialIsOpen={false} /> 68 - </QueryClientProvider> 69 - </ThemeProvider> 70 - </ClientProvider> 71 - </SessionProvider> 72 - </StrictMode>, 73 - )
-105
apps/web/src/queries/recipe.ts
··· 1 - import { queryOptions, useMutation, useQuery } from "@tanstack/react-query"; 2 - import { Client } from "@atcute/client"; 3 - import { notFound } from "@tanstack/react-router"; 4 - import { UseFormReturn } from "react-hook-form"; 5 - import { TID } from '@atproto/common-web'; 6 - import { z } from "zod"; 7 - import { ActorIdentifier, Did } from "@atcute/lexicons"; 8 - 9 - import type {} from '@atcute/atproto'; 10 - import type {} from '@cookware/lexicons'; 11 - import { useClient } from "../state/auth/client"; 12 - 13 - const RQKEY_ROOT = 'posts'; 14 - export const RQKEY = (cursor: string, did: string, rkey: string) => [RQKEY_ROOT, cursor, did, rkey]; 15 - 16 - export const useRecipesQuery = (cursor: string, did?: Did) => { 17 - const client = useClient(); 18 - return useQuery({ 19 - queryKey: RQKEY(cursor, did ?? '', ''), 20 - queryFn: async () => { 21 - const res = await client.get('blue.recipes.feed.getRecipes', { 22 - params: { cursor, did }, 23 - }); 24 - if (!res.ok) throw res.data; 25 - return res.data; 26 - }, 27 - }); 28 - }; 29 - 30 - export const recipeQueryOptions = (rpc: Client, actor: ActorIdentifier, rkey: string) => { 31 - return queryOptions({ 32 - queryKey: RQKEY('', actor, rkey), 33 - queryFn: async () => { 34 - const { ok, data } = await rpc.get('blue.recipes.feed.getRecipe', { 35 - params: { uris: [`at://${actor}/blue.recipes.feed.recipe/${rkey}`] }, 36 - }); 37 - 38 - if (!ok) { 39 - switch (data.error) { 40 - case 'RecipeNotFound': 41 - throw notFound({ routeId: '/_' }); 42 - default: 43 - throw new Error(`Error fetching recipe: ${data.error}`); 44 - } 45 - } 46 - 47 - return data; 48 - }, 49 - }); 50 - }; 51 - 52 - export const useRecipeQuery = (did: Did, rkey: string) => { 53 - const rpc = useClient(); 54 - return useQuery(recipeQueryOptions(rpc, did, rkey)); 55 - }; 56 - 57 - export const useNewRecipeMutation = (form: UseFormReturn<z.infer<typeof recipeSchema>>) => { 58 - const rpc = useClient(); 59 - return useMutation({ 60 - mutationKey: ['recipes.new'], 61 - mutationFn: async ({ recipe: { image, ...recipe } }: { recipe: z.infer<typeof recipeSchema> }) => { 62 - let recipeImg = null; 63 - if (image) { 64 - const imageFile = image.item(0) as File; 65 - const { ok, data } = await rpc.post('com.atproto.repo.uploadBlob', { 66 - input: imageFile, 67 - }); 68 - 69 - if (!ok) { 70 - throw new Error(`Image upload failed: ${data.error}`); 71 - } 72 - 73 - recipeImg = data.blob; 74 - } 75 - 76 - const rkey = TID.nextStr(); 77 - const { ok, data } = await rpc.post(`com.atproto.repo.createRecord`, { 78 - input: { 79 - repo: agent?.session.info.sub as ActorIdentifier, 80 - record: { 81 - ...recipe, 82 - image: recipeImg, 83 - }, 84 - collection: 'blue.recipes.feed.recipe', 85 - rkey: rkey, 86 - } 87 - }); 88 - 89 - if (!ok) { 90 - throw new Error(`Recipe creation failed: ${data.error}`); 91 - } 92 - 93 - return { 94 - rkey: rkey, 95 - resp: data, 96 - }; 97 - }, 98 - onError: (error) => { 99 - form.setError('title', error); 100 - }, 101 - onSuccess: ({ rkey }) => { 102 - window.location.assign(`/recipes/${agent?.sub}/${rkey}`); 103 - }, 104 - }); 105 - };
-22
apps/web/src/queries/self.ts
··· 1 - import { useClient, useSession } from "@/state/auth"; 2 - import { BlueRecipesActorDefs } from "@cookware/lexicons"; 3 - import { useQuery } from "@tanstack/react-query"; 4 - 5 - export const useUserQuery = () => { 6 - const { isLoggedIn, agent } = useSession(); 7 - const rpc = useClient(); 8 - 9 - return useQuery({ 10 - queryKey: ['self'], 11 - queryFn: async () => { 12 - const res = await rpc.get('blue.recipes.actor.getProfile', { 13 - params: { 14 - actor: agent?.sub! 15 - }, 16 - }); 17 - 18 - return res.data as BlueRecipesActorDefs.ProfileViewDetailed; 19 - }, 20 - enabled: isLoggedIn, 21 - }); 22 - }
+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 to="/">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 - {data => data.recipes.map(recipe => ( 52 - <RecipeCard 53 - recipe={recipe} 54 - key={`${recipe.author.did}-${recipe.rkey}`} 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 { Badge } from '@/components/ui/badge' 16 - import { Clock, Users } from 'lucide-react' 17 - import { useClient, useSession } from '@/state/auth' 18 - import { Button } from '@/components/ui/button' 19 - import { ActorIdentifier } from '@atcute/lexicons' 20 - 21 - export const Route = createLazyFileRoute('/_/(app)/recipes/$author/$rkey/')({ 22 - component: RouteComponent, 23 - }) 24 - 25 - function RouteComponent() { 26 - const rpc = useClient(); 27 - const { author, rkey } = Route.useParams() 28 - const { 29 - data: { recipes }, 30 - error, 31 - } = useSuspenseQuery(recipeQueryOptions(rpc, author as ActorIdentifier, rkey)) 32 - const { isLoggedIn, agent } = useSession(); 33 - 34 - if (error || !recipes[0]) 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: recipes[0].author.handle }}> 59 - {recipes[0].author.displayName} 60 - </Link> 61 - </BreadcrumbLink> 62 - </BreadcrumbItem> 63 - <BreadcrumbSeparator className="hidden md:block" /> 64 - <BreadcrumbItem> 65 - <BreadcrumbPage>{recipes[0].record.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">{recipes[0].record.title}</CardTitle> 76 - <CardDescription>{recipes[0].record.description}</CardDescription> 77 - </CardHeader> 78 - 79 - <CardContent className="space-y-6"> 80 - { 81 - recipes[0].record.image && 82 - <img 83 - src={recipes[0].record.image.ref.$link} 84 - alt={recipes[0].record.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>{recipes[0].record.time} mins</span> 92 - </Badge> 93 - <Badge variant="secondary" className="flex items-center gap-2"> 94 - <Users className="size-4" /> 95 - <span>Serves {recipes[0].record.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 - {recipes[0].record.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 - {recipes[0].record.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 == recipes[0].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 - }
-341
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 - 13 - export const Route = createFileRoute("/_/(app)/recipes/new")({ 14 - beforeLoad: async ({ context }) => { 15 - if (!context.session.isLoggedIn) { 16 - throw redirect({ 17 - to: '/login', 18 - }); 19 - } 20 - }, 21 - component: RouteComponent, 22 - }); 23 - 24 - function RouteComponent() { 25 - return (<></>); 26 - // const form = useForm<z.infer<typeof recipeSchema>>({ 27 - // resolver: zodResolver(recipeSchema), 28 - // defaultValues: { 29 - // title: "", 30 - // time: 0, 31 - // image: null, 32 - // description: "", 33 - // ingredients: [{ name: "" }], 34 - // steps: [{ text: "" }], 35 - // }, 36 - // }); 37 - // 38 - // const { mutate, isPending } = useNewRecipeMutation(form); 39 - // 40 - // const onSubmit = (values: z.infer<typeof recipeSchema>) => { 41 - // mutate({ recipe: values }); 42 - // }; 43 - // 44 - // const imageRef = form.register("image"); 45 - // 46 - // const ingredients = useFieldArray({ 47 - // control: form.control, 48 - // name: "ingredients", 49 - // }); 50 - // 51 - // const steps = useFieldArray({ 52 - // control: form.control, 53 - // name: "steps", 54 - // }); 55 - // 56 - // return ( 57 - // <> 58 - // <Breadcrumbs /> 59 - // <div className="flex-1 flex-col p-4 pt-0 max-w-xl w-full mx-auto"> 60 - // <Card> 61 - // <CardHeader> 62 - // <CardTitle>New recipe</CardTitle> 63 - // <CardDescription>Share your recipe with the world!</CardDescription> 64 - // </CardHeader> 65 - // <CardContent> 66 - // <Form {...form}> 67 - // <form 68 - // onSubmit={form.handleSubmit(onSubmit)} 69 - // className="space-y-8" 70 - // > 71 - // <FormField 72 - // name="title" 73 - // control={form.control} 74 - // render={({ field }) => ( 75 - // <FormItem> 76 - // <FormLabel>Title</FormLabel> 77 - // <FormControl> 78 - // <Input placeholder="My awesome recipe!" {...field} /> 79 - // </FormControl> 80 - // <FormDescription> 81 - // This is your recipe's name. 82 - // </FormDescription> 83 - // <FormMessage /> 84 - // </FormItem> 85 - // )} 86 - // /> 87 - // 88 - // <FormField 89 - // name="description" 90 - // control={form.control} 91 - // render={({ field: { value, ...field } }) => ( 92 - // <FormItem> 93 - // <FormLabel>Description</FormLabel> 94 - // <FormControl> 95 - // <Textarea 96 - // className="resize-none" 97 - // value={value || ""} 98 - // {...field} 99 - // /> 100 - // </FormControl> 101 - // <FormDescription>Describe your recipe, maybe tell the world how tasty it is? (Optional)</FormDescription> 102 - // <FormMessage /> 103 - // </FormItem> 104 - // )} 105 - // /> 106 - // 107 - // <FormField 108 - // name="image" 109 - // control={form.control} 110 - // render={(_props) => ( 111 - // <FormItem> 112 - // <FormLabel>Image</FormLabel> 113 - // <FormControl> 114 - // <Input 115 - // type="file" 116 - // className="resize-none" 117 - // {...imageRef} 118 - // /> 119 - // </FormControl> 120 - // <FormMessage /> 121 - // </FormItem> 122 - // )} 123 - // /> 124 - // 125 - // <FormField 126 - // name="time" 127 - // control={form.control} 128 - // render={({ field: { value, ...field } }) => ( 129 - // <FormItem> 130 - // <FormLabel>Time</FormLabel> 131 - // <FormControl> 132 - // <Input 133 - // type="number" 134 - // className="resize-none" 135 - // value={value || ""} 136 - // {...field} 137 - // /> 138 - // </FormControl> 139 - // <FormDescription>How long (in minutes) does your recipe take to complete?</FormDescription> 140 - // <FormMessage /> 141 - // </FormItem> 142 - // )} 143 - // /> 144 - // 145 - // <div className="grid gap-2"> 146 - // <Label>Ingredients</Label> 147 - // <Sortable 148 - // value={ingredients.fields} 149 - // onMove={({ activeIndex, overIndex }) => 150 - // ingredients.move(activeIndex, overIndex)} 151 - // > 152 - // <div className="flex w-full flex-col gap-2"> 153 - // {ingredients.fields.map((field, index) => ( 154 - // <SortableItem key={field.id} value={field.id} asChild> 155 - // <div className="grid grid-cols-[2rem_0.3fr_1fr_2rem] items-center gap-2"> 156 - // <SortableDragHandle 157 - // type="button" 158 - // variant="outline" 159 - // size="icon" 160 - // className="size-8 shrink-0" 161 - // > 162 - // <DragHandleDots2Icon 163 - // className="size-4" 164 - // aria-hidden="true" 165 - // /> 166 - // </SortableDragHandle> 167 - // 168 - // <FormField 169 - // control={form.control} 170 - // name={`ingredients.${index}.amount`} 171 - // render={({ field: { value, ...field } }) => ( 172 - // <FormItem> 173 - // <FormControl> 174 - // <Input 175 - // placeholder="Amount" 176 - // value={value || ""} 177 - // className="h-8" 178 - // {...field} 179 - // /> 180 - // </FormControl> 181 - // <FormMessage /> 182 - // </FormItem> 183 - // )} 184 - // /> 185 - // 186 - // <FormField 187 - // control={form.control} 188 - // name={`ingredients.${index}.name`} 189 - // render={({ field }) => ( 190 - // <FormItem> 191 - // <FormControl> 192 - // <Input 193 - // placeholder="Ingredient" 194 - // className="h-8" 195 - // {...field} 196 - // /> 197 - // </FormControl> 198 - // <FormMessage /> 199 - // </FormItem> 200 - // )} 201 - // /> 202 - // 203 - // <Button 204 - // type="button" 205 - // variant="destructive" 206 - // className="size-8" 207 - // onClick={(e) => { 208 - // e.preventDefault(); 209 - // ingredients.remove(index); 210 - // }} 211 - // > 212 - // <TrashIcon /> 213 - // </Button> 214 - // </div> 215 - // </SortableItem> 216 - // ))} 217 - // </div> 218 - // </Sortable> 219 - // <Button 220 - // type="button" 221 - // variant="secondary" 222 - // onClick={(e) => { 223 - // e.preventDefault(); 224 - // ingredients.append({ 225 - // name: "", 226 - // amount: "", 227 - // }); 228 - // }} 229 - // > 230 - // Add 231 - // </Button> 232 - // </div> 233 - // 234 - // <div className="grid gap-2"> 235 - // <Label>Steps</Label> 236 - // <Sortable 237 - // value={steps.fields} 238 - // onMove={({ activeIndex, overIndex }) => 239 - // steps.move(activeIndex, overIndex)} 240 - // > 241 - // <div className="flex w-full flex-col gap-2"> 242 - // {steps.fields.map((field, index) => ( 243 - // <SortableItem key={field.id} value={field.id} asChild> 244 - // <div className="grid grid-cols-[2rem_auto_2rem] items-center gap-2"> 245 - // <SortableDragHandle 246 - // type="button" 247 - // variant="outline" 248 - // size="icon" 249 - // className="size-8 shrink-0" 250 - // > 251 - // <DragHandleDots2Icon 252 - // className="size-4" 253 - // aria-hidden="true" 254 - // /> 255 - // </SortableDragHandle> 256 - // <FormField 257 - // control={form.control} 258 - // name={`steps.${index}.text`} 259 - // render={({ field }) => ( 260 - // <FormItem> 261 - // <FormControl> 262 - // <Input className="h-8" {...field} /> 263 - // </FormControl> 264 - // <FormMessage /> 265 - // </FormItem> 266 - // )} 267 - // /> 268 - // 269 - // <Button 270 - // type="button" 271 - // variant="destructive" 272 - // className="size-8" 273 - // onClick={(e) => { 274 - // e.preventDefault(); 275 - // steps.remove(index); 276 - // }} 277 - // > 278 - // <TrashIcon /> 279 - // </Button> 280 - // </div> 281 - // </SortableItem> 282 - // ))} 283 - // </div> 284 - // </Sortable> 285 - // <Button 286 - // type="button" 287 - // variant="secondary" 288 - // onClick={(e) => { 289 - // e.preventDefault(); 290 - // steps.append({ text: "" }); 291 - // }} 292 - // > 293 - // Add 294 - // </Button> 295 - // </div> 296 - // 297 - // <div className="grid justify-end"> 298 - // <Button 299 - // type="submit" 300 - // className="ml-auto" 301 - // disabled={isPending} 302 - // > 303 - // Submit 304 - // </Button> 305 - // </div> 306 - // </form> 307 - // </Form> 308 - // </CardContent> 309 - // </Card> 310 - // </div> 311 - // </> 312 - // ); 313 - } 314 - 315 - const Breadcrumbs = () => ( 316 - <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"> 317 - <div className="flex items-center gap-2 px-4"> 318 - <SidebarTrigger className="-ml-1" /> 319 - <Separator orientation="vertical" className="mr-2 h-4" /> 320 - <Breadcrumb> 321 - <BreadcrumbList> 322 - <BreadcrumbItem className="hidden md:block"> 323 - <BreadcrumbLink asChild> 324 - <Link href="/">Home</Link> 325 - </BreadcrumbLink> 326 - </BreadcrumbItem> 327 - <BreadcrumbSeparator className="hidden md:block" /> 328 - <BreadcrumbItem className="hidden md:block"> 329 - <BreadcrumbLink asChild> 330 - <Link href="/recipes">Recipes</Link> 331 - </BreadcrumbLink> 332 - </BreadcrumbItem> 333 - <BreadcrumbSeparator className="hidden md:block" /> 334 - <BreadcrumbItem> 335 - <BreadcrumbPage>New</BreadcrumbPage> 336 - </BreadcrumbItem> 337 - </BreadcrumbList> 338 - </Breadcrumb> 339 - </div> 340 - </header> 341 - );
-108
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 { Field, FieldError, FieldGroup, FieldLabel } from '@/components/ui/field' 17 - import { Input } from '@/components/ui/input' 18 - import { Label } from '@/components/ui/label' 19 - import { Separator } from '@/components/ui/separator' 20 - import { SidebarTrigger } from '@/components/ui/sidebar' 21 - import { useSession } from '@/state/auth/session' 22 - import { useMutation } from '@tanstack/react-query' 23 - import { createFileRoute } from '@tanstack/react-router' 24 - import { useState } from 'react' 25 - 26 - export const Route = createFileRoute('/_/(auth)/login')({ 27 - component: RouteComponent, 28 - }) 29 - 30 - function RouteComponent() { 31 - const { signIn } = useSession(); 32 - const [handle, setHandle] = useState('') 33 - 34 - const { mutate, isPending, error } = useMutation({ 35 - mutationKey: ['login'], 36 - mutationFn: async () => { 37 - await signIn(handle); 38 - return; 39 - }, 40 - }) 41 - 42 - return ( 43 - <> 44 - <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"> 45 - <div className="flex items-center gap-2 px-4"> 46 - <SidebarTrigger className="-ml-1" /> 47 - <Separator orientation="vertical" className="mr-2 h-4" /> 48 - <Breadcrumb> 49 - <BreadcrumbList> 50 - <BreadcrumbItem> 51 - <BreadcrumbPage>Log in</BreadcrumbPage> 52 - </BreadcrumbItem> 53 - </BreadcrumbList> 54 - </Breadcrumb> 55 - </div> 56 - </header> 57 - <div className="flex flex-1 flex-col items-center justify-center gap-4 p-4 pt-0"> 58 - <form onSubmit={e => { 59 - e.preventDefault(); 60 - mutate(); 61 - }}> 62 - <Card className="max-w-sm w-full"> 63 - <CardHeader> 64 - <CardTitle>Log in</CardTitle> 65 - <CardDescription> 66 - Enter your Atmosphere handle below to sign in to your account. 67 - </CardDescription> 68 - </CardHeader> 69 - <CardContent> 70 - <FieldGroup> 71 - <Field data-invalid={error ? true : false}> 72 - <FieldLabel htmlFor="handle">Handle</FieldLabel> 73 - <Input 74 - id="handle" 75 - placeholder="johndoe.bsky.social" 76 - required 77 - autoComplete="username" 78 - aria-invalid={error ? 'true' : 'false'} 79 - tabIndex={0} 80 - autoFocus 81 - value={handle} 82 - onChange={(e) => setHandle(e.currentTarget.value)} 83 - /> 84 - {error && <FieldError>{error.message}</FieldError>} 85 - </Field> 86 - </FieldGroup> 87 - </CardContent> 88 - <CardFooter className="grid gap-2"> 89 - <Button type="submit" disabled={isPending}> 90 - Log in 91 - </Button> 92 - <p className="text-sm text-muted-foreground text-center"> 93 - Don't have an account?{' '} 94 - <a 95 - className="font-bold text-primary" 96 - href="https://bsky.app/" 97 - target="_blank" 98 - > 99 - Sign up on Bluesky! 100 - </a> 101 - </p> 102 - </CardFooter> 103 - </Card> 104 - </form> 105 - </div> 106 - </> 107 - ) 108 - }
-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 -20
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 { ClientContext, SessionContext } from '@/state/auth'; 7 - import { Outlet, createRootRouteWithContext } from '@tanstack/react-router' 8 - 9 - type RootContext = { 10 - session: SessionContext; 11 - client: ClientContext['client']; 12 - }; 1 + import * as React from 'react' 2 + import { Outlet, createRootRoute } from '@tanstack/react-router' 13 3 14 - export const Route = createRootRouteWithContext<RootContext>()({ 4 + export const Route = createRootRoute({ 15 5 component: RootComponent, 16 - }); 6 + }) 17 7 18 8 function RootComponent() { 19 9 return ( 20 - <SidebarProvider> 21 - <AppSidebar /> 22 - <SidebarInset> 23 - <Outlet /> 24 - </SidebarInset> 25 - </SidebarProvider> 10 + <React.Fragment> 11 + <div>Hello "__root"!</div> 12 + <Outlet /> 13 + </React.Fragment> 26 14 ) 27 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 { Link } from "@tanstack/react-router"; 4 - import { Clock, CookingPot, ListIcon } from "lucide-react"; 5 - import { BlueRecipesFeedGetRecipes } from "@cookware/lexicons"; 6 - 7 - type RecipeCardProps = { 8 - recipe: BlueRecipesFeedGetRecipes.$output['recipes'][0]; 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 - <CardTitle>{recipe.record.title}</CardTitle> 17 - <CardDescription className="flex items-center space-x-2"> 18 - <Avatar className="h-6 w-6 rounded-lg"> 19 - <AvatarImage src={recipe.author.avatar} alt={recipe.author.displayName} /> 20 - <AvatarFallback className="rounded-lg">{recipe.author.displayName}</AvatarFallback> 21 - </Avatar> 22 - 23 - <span>{recipe.author.displayName}</span> 24 - </CardDescription> 25 - </CardHeader> 26 - <CardContent> 27 - <p>{recipe.record.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.record.steps.length}</span> 32 - </span> 33 - 34 - <span className="flex items-center gap-2"> 35 - <CookingPot className="size-4" /> <span>{recipe.record.ingredients.length}</span> 36 - </span> 37 - 38 - <span className="flex items-center gap-2"> 39 - <Clock className="size-4" /> <span>{recipe.record.time} mins</span> 40 - </span> 41 - </CardFooter> 42 - </Card> 43 - </Link> 44 - ); 45 - };
-38
apps/web/src/state/auth/client.tsx
··· 1 - import { Client, simpleFetchHandler } from "@atcute/client"; 2 - import { createContext, PropsWithChildren, useContext, useEffect, useState } from "react"; 3 - import { useSession } from "./session"; 4 - 5 - export type ClientContext = { 6 - client: Client; 7 - }; 8 - 9 - const clientContext = createContext<ClientContext>({ 10 - client: new Client({ handler: simpleFetchHandler({ service: import.meta.env.VITE_API_SERVICE }) }), 11 - }); 12 - 13 - export const ClientProvider = ({ children }: PropsWithChildren) => { 14 - const { agent } = useSession(); 15 - const [client, setClient] = useState<Client>( 16 - () => new Client({ handler: simpleFetchHandler({ service: import.meta.env.VITE_API_SERVICE }) }) 17 - ); 18 - 19 - useEffect(() => { 20 - setClient(new Client({ 21 - handler: agent ?? simpleFetchHandler({ service: import.meta.env.VITE_API_SERVICE }), 22 - proxy: { 23 - did: 'did:web:localhost', 24 - serviceId: '#api_service' 25 - }, 26 - })); 27 - }, [agent]); 28 - 29 - return ( 30 - <clientContext.Provider value={{ client: client }}> 31 - {children} 32 - </clientContext.Provider> 33 - ); 34 - } 35 - 36 - export const useClient = () => { 37 - return useContext(clientContext).client; 38 - }
-2
apps/web/src/state/auth/index.ts
··· 1 - export * from './client'; 2 - export * from './session';
-121
apps/web/src/state/auth/session.tsx
··· 1 - import { isDid, isActorIdentifier } from "@atcute/lexicons/syntax"; 2 - import { createAuthorizationUrl, deleteStoredSession, finalizeAuthorization, getSession, OAuthUserAgent, Session } from "@atcute/oauth-browser-client"; 3 - import { createContext, PropsWithChildren, useContext, useEffect, useState } from "react"; 4 - 5 - export type SessionContext = { 6 - session: null | Session; 7 - agent: null | OAuthUserAgent; 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 - agent: null, 17 - isLoading: false, 18 - isLoggedIn: false, 19 - signIn: async () => { 20 - throw new Error("AuthContext not initialized"); 21 - }, 22 - signOut: async () => { 23 - throw new Error("AuthContext not initialized"); 24 - }, 25 - }); 26 - 27 - const LS_LAST_SIGNED_IN = "recipes:last-signed-in"; 28 - 29 - export const SessionProvider = ({ children }: PropsWithChildren<{}>) => { 30 - const [initialized, setInitialized] = useState(false); 31 - const [loading, setLoading] = useState(true); 32 - const [session, setSession] = useState<null | Session>(null); 33 - const [agent, setAgent] = useState<null | OAuthUserAgent>(null); 34 - 35 - useEffect(() => { 36 - setInitialized(false); 37 - setSession(null); 38 - setAgent(null); 39 - 40 - const params = new URLSearchParams(location.hash.slice(1)); 41 - if (params.has("state") && params.has("iss") && params.has("code")) { 42 - // If there is an active auth attempt: 43 - history.replaceState(null, "", location.pathname + location.search); 44 - console.log("finalizing authorization..."); 45 - finalizeAuthorization(params) 46 - .then(val => { 47 - setSession(val.session); 48 - setAgent(new OAuthUserAgent(val.session)); 49 - }) 50 - .catch(err => { 51 - console.error("Failed to initialize session:", err); 52 - }) 53 - .finally(() => { 54 - setLoading(false); 55 - setInitialized(true); 56 - }); 57 - } else { 58 - const lastSignedIn = localStorage.getItem(LS_LAST_SIGNED_IN); 59 - if (lastSignedIn && isDid(lastSignedIn)) { 60 - getSession(lastSignedIn, { allowStale: true }) 61 - .then((session) => { 62 - setSession(session); 63 - setAgent(new OAuthUserAgent(session)); 64 - }) 65 - .catch(err => { 66 - console.error("Failed to initialize session:", err); 67 - }) 68 - } 69 - 70 - setLoading(false); 71 - setInitialized(true); 72 - } 73 - }, []); 74 - 75 - const signIn = async (handle: string) => { 76 - if (!isActorIdentifier(handle)) throw new Error("Invalid handle or DID!"); 77 - const authUrl = await createAuthorizationUrl({ 78 - target: { type: 'account', identifier: handle }, 79 - scope: 'atproto transition:generic', 80 - }); 81 - window.location.assign(authUrl); 82 - }; 83 - 84 - const signOut = async () => { 85 - if (!agent || !session) return; 86 - 87 - const did = session.info.sub; 88 - try { 89 - const session = await getSession(did, { allowStale: true }); 90 - const agent = new OAuthUserAgent(session); 91 - 92 - await agent.signOut(); 93 - setSession(null); 94 - } catch(err) { 95 - deleteStoredSession(did); 96 - } 97 - }; 98 - 99 - if (!initialized) return ( 100 - <p>Loading...</p> 101 - ); 102 - 103 - return ( 104 - <sessionContext.Provider value={{ 105 - isLoading: loading, 106 - isLoggedIn: session !== null, 107 - session, 108 - agent, 109 - signIn, 110 - signOut, 111 - }}> 112 - {children} 113 - </sessionContext.Provider> 114 - ); 115 - }; 116 - 117 - export const useSession = () => { 118 - const ctx = useContext(sessionContext); 119 - if (!ctx) throw new Error("useSession() must be called inside a <SessionProvider />!"); 120 - return ctx; 121 - };
apps/web/src/state/auth.tsx

This is a binary file and will not be displayed.

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_URI: 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 -46
apps/web/vite.config.ts
··· 1 - import { defineConfig } from 'vite' 2 - import react from '@vitejs/plugin-react' 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({ babel: { plugins: ['babel-plugin-react-compiler'] } }), 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_API_SERVICE = 'http://localhost:3000'; 33 - process.env.VITE_DEV_SERVER_PORT = '' + SERVER_PORT; 34 - process.env.VITE_OAUTH_CLIENT_ID = clientId; 35 - process.env.VITE_OAUTH_REDIRECT_URI = redirectUri; 36 - } 9 + tanstackRouter({ 10 + target: 'react', 11 + autoCodeSplitting: true, 12 + }), 13 + tailwindcss(), 14 + react() 15 + ], 37 16 38 - process.env.VITE_CLIENT_URI = metadata.client_uri; 39 - process.env.VITE_OAUTH_SCOPE = metadata.scope; 40 - }, 41 - }, 42 - ], 43 - server: { 44 - host: SERVER_HOST, 45 - port: SERVER_PORT, 46 - }, 47 - build: { 48 - target: "esnext", 49 - }, 50 17 resolve: { 51 18 alias: { 52 - '@': path.resolve(__dirname, './src'), 19 + "@": path.resolve(__dirname, "./src"), 53 20 } 54 21 } 55 22 })
+678 -448
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 }, ··· 34 40 "rimraf": "^6.0.1", 35 41 }, 36 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 + }, 37 85 "apps/ingester": { 38 86 "name": "@cookware/ingester", 39 87 "dependencies": { ··· 58 106 }, 59 107 }, 60 108 "apps/web": { 61 - "name": "@cookware/web", 109 + "name": "web", 62 110 "version": "0.0.0", 63 111 "dependencies": { 64 - "@atcute/atproto": "^3.1.9", 65 - "@atcute/client": "catalog:", 66 - "@atcute/identity-resolver": "^1.1.4", 67 - "@atcute/lexicons": "catalog:", 68 - "@atcute/oauth-browser-client": "^2.0.1", 69 - "@atproto/common": "^0.4.5", 70 - "@atproto/common-web": "^0.3.1", 71 - "@dnd-kit/core": "^6.3.1", 72 - "@dnd-kit/modifiers": "^9.0.0", 73 - "@dnd-kit/sortable": "^10.0.0", 74 - "@dnd-kit/utilities": "^3.2.2", 75 - "@hookform/resolvers": "^3.9.1", 76 - "@radix-ui/react-avatar": "^1.1.1", 77 - "@radix-ui/react-collapsible": "^1.1.1", 78 - "@radix-ui/react-dialog": "^1.1.4", 79 - "@radix-ui/react-dropdown-menu": "^2.1.4", 80 - "@radix-ui/react-icons": "^1.3.2", 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", 81 115 "@radix-ui/react-label": "^2.1.8", 82 116 "@radix-ui/react-separator": "^1.1.8", 83 117 "@radix-ui/react-slot": "^1.2.4", 84 - "@radix-ui/react-tooltip": "^1.1.4", 85 - "@tanstack/react-query": "^5.62.2", 86 - "@tanstack/react-query-devtools": "^5.62.2", 87 - "@tanstack/react-router": "^1.91.2", 88 - "axios": "^1.7.9", 118 + "@radix-ui/react-tooltip": "^1.2.8", 89 119 "class-variance-authority": "^0.7.1", 90 120 "clsx": "^2.1.1", 91 - "lucide-react": "^0.464.0", 92 - "react-dom": "19.0.0", 93 - "react-hook-form": "^7.54.1", 94 - "tailwind-merge": "^2.5.5", 95 - "tailwindcss-animate": "^1.0.7", 96 - "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", 97 126 }, 98 127 "devDependencies": { 99 - "@atcute/bluesky": "^1.0.9", 100 - "@cookware/lexicons": "workspace:*", 101 - "@eslint/js": "^9.15.0", 102 - "@tanstack/eslint-plugin-query": "^5.62.1", 103 - "@tanstack/router-devtools": "^1.85.5", 104 - "@tanstack/router-plugin": "^1.85.3", 105 - "@types/node": "^22.10.1", 106 - "@types/react": "^19.0.0", 107 - "@types/react-dom": "^19.0.0", 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", 108 134 "@vitejs/plugin-react": "^5.1.1", 109 - "@vitejs/plugin-react-swc": "^3.5.0", 110 - "autoprefixer": "^10.4.20", 111 - "babel-plugin-react-compiler": "^1.0.0", 112 - "cssnano": "^7.0.6", 113 - "eslint": "^9.15.0", 114 - "eslint-plugin-react-hooks": "^5.0.0", 115 - "eslint-plugin-react-refresh": "^0.4.14", 116 - "globals": "^15.12.0", 117 - "postcss": "^8.4.49", 118 - "react": "19.0.0", 119 - "tailwindcss": "^3.4.16", 120 - "typescript": "~5.6.2", 121 - "typescript-eslint": "^8.15.0", 122 - "vite": "^7.2.4", 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", 123 143 }, 124 144 }, 125 145 "libs/database": { ··· 172 192 "@atcute/atproto": "^3.1.9", 173 193 "@atcute/bluesky": "^3.2.11", 174 194 "@atcute/client": "^4.0.5", 195 + "@atcute/identity": "^1.1.3", 196 + "@atcute/identity-resolver": "^1.1.4", 175 197 "@atcute/lexicons": "^1.2.5", 176 198 "@types/bun": "^1.3.3", 177 199 "drizzle-orm": "^0.44.7", ··· 187 209 188 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=="], 189 211 190 - "@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=="], 191 213 192 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=="], 193 215 ··· 205 227 206 228 "@atcute/multibase": ["@atcute/multibase@1.1.6", "", { "dependencies": { "@atcute/uint8array": "^1.0.5" } }, "sha512-HBxuCgYLKPPxETV0Rot4VP9e24vKl8JdzGCZOVsDaOXJgbRZoRIF67Lp0H/OgnJeH/Xpva8Z5ReoTNJE5dn3kg=="], 207 229 208 - "@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=="], 209 231 210 - "@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 232 + "@atcute/uint8array": ["@atcute/uint8array@1.0.6", "", {}, "sha512-ucfRBQc7BFT8n9eCyGOzDHEMKF/nZwhS2pPao4Xtab1ML3HdFYcX2DM1tadCzas85QTGxHe5urnUAAcNKGRi9A=="], 211 233 212 234 "@atcute/util-fetch": ["@atcute/util-fetch@1.0.3", "", { "dependencies": { "@badrap/valita": "^0.4.6" } }, "sha512-f8zzTb/xlKIwv2OQ31DhShPUNCmIIleX6p7qIXwWwEUjX6x8skUtpdISSjnImq01LXpltGV5y8yhV4/Mlb7CRQ=="], 213 235 ··· 231 253 232 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=="], 233 255 234 - "@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=="], 235 - 236 - "@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=="], 237 257 238 258 "@atproto/did": ["@atproto/did@0.1.5", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-8+1D08QdGE5TF0bB0vV8HLVrVZJeLNITpRTUVEoABNMRaUS7CoYSVb0+JNQDeJIVmqMjOL8dOjvCUDkp3gEaGQ=="], 239 259 ··· 242 262 "@atproto/jwk-jose": ["@atproto/jwk-jose@0.1.8", "", { "dependencies": { "@atproto/jwk": "0.3.0", "jose": "^5.2.0" } }, "sha512-aoU2Q0GpIl388KhCcv9YvAxNscALUv3xzLq5gjVPdJ+zmqw94nGZNcjiNvpnbfS+VQM9e2DrrTuwmDXnxfrrSA=="], 243 263 244 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=="], 245 269 246 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=="], 247 271 ··· 317 341 318 342 "@badrap/valita": ["@badrap/valita@0.4.6", "", {}, "sha512-4kdqcjyxo/8RQ8ayjms47HCWZIF5981oE5nIenbfThKDxWXtEHKipAOWlflpPJzZx9y/JWYQkp18Awr7VuepFg=="], 319 343 320 - "@cbor-extract/cbor-extract-darwin-arm64": ["@cbor-extract/cbor-extract-darwin-arm64@2.2.0", "", { "os": "darwin", "cpu": "arm64" }, "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w=="], 321 - 322 - "@cbor-extract/cbor-extract-darwin-x64": ["@cbor-extract/cbor-extract-darwin-x64@2.2.0", "", { "os": "darwin", "cpu": "x64" }, "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w=="], 323 - 324 - "@cbor-extract/cbor-extract-linux-arm": ["@cbor-extract/cbor-extract-linux-arm@2.2.0", "", { "os": "linux", "cpu": "arm" }, "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q=="], 325 - 326 - "@cbor-extract/cbor-extract-linux-arm64": ["@cbor-extract/cbor-extract-linux-arm64@2.2.0", "", { "os": "linux", "cpu": "arm64" }, "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ=="], 327 - 328 - "@cbor-extract/cbor-extract-linux-x64": ["@cbor-extract/cbor-extract-linux-x64@2.2.0", "", { "os": "linux", "cpu": "x64" }, "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw=="], 329 - 330 - "@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=="], 331 - 332 344 "@cookware/api": ["@cookware/api@workspace:apps/api"], 333 345 334 346 "@cookware/database": ["@cookware/database@workspace:libs/database"], ··· 339 351 340 352 "@cookware/tsconfig": ["@cookware/tsconfig@workspace:libs/tsconfig"], 341 353 342 - "@cookware/web": ["@cookware/web@workspace:apps/web"], 343 - 344 - "@dnd-kit/accessibility": ["@dnd-kit/accessibility@3.1.1", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "react": ">=16.8.0" } }, "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw=="], 345 - 346 - "@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=="], 347 - 348 - "@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=="], 354 + "@drizzle-team/brocli": ["@drizzle-team/brocli@0.10.2", "", {}, "sha512-z33Il7l5dKjUgGULTqBsQBQwckHh5AbIuxhdsIxDDiZAzBOrZO6q9ogcWC65kU382AfynTfgNumVcNIjuIua6w=="], 349 355 350 - "@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=="], 356 + "@emnapi/core": ["@emnapi/core@1.7.1", "", { "dependencies": { "@emnapi/wasi-threads": "1.1.0", "tslib": "^2.4.0" } }, "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg=="], 351 357 352 - "@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=="], 358 + "@emnapi/runtime": ["@emnapi/runtime@1.7.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA=="], 353 359 354 - "@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=="], 355 361 356 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=="], 357 363 ··· 391 397 392 398 "@esbuild/linux-x64": ["@esbuild/linux-x64@0.19.12", "", { "os": "linux", "cpu": "x64" }, "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg=="], 393 399 394 - "@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=="], 395 401 396 402 "@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.19.12", "", { "os": "none", "cpu": "x64" }, "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA=="], 397 403 398 - "@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=="], 399 405 400 406 "@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.19.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw=="], 401 407 402 - "@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=="], 403 409 404 410 "@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.19.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA=="], 405 411 ··· 435 441 436 442 "@floating-ui/utils": ["@floating-ui/utils@0.2.10", "", {}, "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ=="], 437 443 438 - "@hookform/resolvers": ["@hookform/resolvers@3.10.0", "", { "peerDependencies": { "react-hook-form": "^7.0.0" } }, "sha512-79Dv+3mDF7i+2ajj7SkypSKHhl1cbln1OGavqrsF7p6mbUv11xpqpacPsGDCTRvCSjEEIez2ef1NveSVL3b0Ag=="], 439 - 440 444 "@humanfs/core": ["@humanfs/core@0.19.1", "", {}, "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA=="], 441 445 442 446 "@humanfs/node": ["@humanfs/node@0.16.7", "", { "dependencies": { "@humanfs/core": "^0.19.1", "@humanwhocodes/retry": "^0.4.0" } }, "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ=="], ··· 445 449 446 450 "@humanwhocodes/retry": ["@humanwhocodes/retry@0.4.3", "", {}, "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ=="], 447 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 + 448 502 "@inquirer/ansi": ["@inquirer/ansi@1.0.2", "", {}, "sha512-S8qNSZiYzFd0wAcyG5AXCvUHC5Sr7xpZ9wZ2py9XR88jUz8wooStVx5M6dRzczbBWjic9NP7+rY0Xi7qqK/aMQ=="], 449 503 450 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=="], ··· 476 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=="], 477 531 478 532 "@inquirer/type": ["@inquirer/type@3.0.10", "", { "peerDependencies": { "@types/node": ">=18" }, "optionalPeers": ["@types/node"] }, "sha512-BvziSRxfz5Ov8ch0z/n3oijRSEcEsHnhggm4xFZe93DHcUCTlutlq9Ox4SVENAfcRD22UQq7T/atg9Wr3k09eA=="], 479 - 480 - "@ipld/dag-cbor": ["@ipld/dag-cbor@7.0.3", "", { "dependencies": { "cborg": "^1.6.0", "multiformats": "^9.5.4" } }, "sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA=="], 481 533 482 534 "@isaacs/balanced-match": ["@isaacs/balanced-match@4.0.1", "", {}, "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ=="], 483 535 ··· 527 579 528 580 "@mary-ext/simple-event-emitter": ["@mary-ext/simple-event-emitter@1.0.0", "", {}, "sha512-meA/zJZKIN1RVBNEYIbjufkUrW7/tRjHH60FjolpG1ixJKo76TB208qefQLNdOVDA7uIG0CGEDuhmMirtHKLAg=="], 529 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=="], 583 + 530 584 "@neon-rs/load": ["@neon-rs/load@0.0.4", "", {}, "sha512-kTPhdZyTQxB+2wpiRcFWrDcejc4JI6tkPuS7UZCG4l6Zvc5kU/gGQ/ozvHTh1XR5tS+UlfAfGuPajjzQjCiHCw=="], 531 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 + 532 606 "@noble/secp256k1": ["@noble/secp256k1@3.0.0", "", {}, "sha512-NJBaR352KyIvj3t6sgT/+7xrNyF9Xk9QlLSIqUGVUYlsnDTAUqY8LOmwpcgEx4AMJXRITQ5XEVHD+mMaPfr3mg=="], 533 607 534 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=="], ··· 536 610 "@nodelib/fs.stat": ["@nodelib/fs.stat@2.0.5", "", {}, "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A=="], 537 611 538 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=="], 613 + 614 + "@nolyfill/is-core-module": ["@nolyfill/is-core-module@1.0.39", "", {}, "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA=="], 539 615 540 616 "@opentelemetry/api": ["@opentelemetry/api@1.9.0", "", {}, "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg=="], 541 617 ··· 609 685 610 686 "@optique/run": ["@optique/run@0.6.2", "", { "dependencies": { "@optique/core": "0.6.2" } }, "sha512-ERksB5bHozwEUVlTPToIc8UjZZBOgLeBhFZYh2lgldUbNDt7LItzgcErsPq5au5i5IBmmyCti4+2A3x+MRI4Xw=="], 611 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 + 612 692 "@pinojs/redact": ["@pinojs/redact@0.4.0", "", {}, "sha512-k2ENnmBugE/rzQfEcdWHcCY+/FM3VLzH9cYEsbdsoqrvzAKRhUZeRNhAZvB8OitQJ1TBed3yqWtdjzS6wJKBwg=="], 613 693 614 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=="], ··· 618 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=="], 619 699 620 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=="], 621 - 622 - "@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=="], 623 701 624 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=="], 625 703 ··· 639 717 640 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=="], 641 719 642 - "@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=="], 643 - 644 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=="], 645 721 646 722 "@radix-ui/react-label": ["@radix-ui/react-label@2.1.8", "", { "dependencies": { "@radix-ui/react-primitive": "2.1.4" }, "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-FmXs37I6hSBVDlO4y764TNz1rLgKwjJMQ0EGte6F3Cb3f4bIuHB/iLa/8I9VKkmOy+gNHq8rql3j686ACVV21A=="], ··· 683 759 684 760 "@radix-ui/rect": ["@radix-ui/rect@1.1.1", "", {}, "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw=="], 685 761 686 - "@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.47", "", {}, "sha512-8QagwMH3kNCuzD8EWL8R2YPW5e4OrHNSAHRFDdmFqEwEaD/KcNKjVoumo+gP2vW5eKB2UPbM6vTYiGZX0ixLnw=="], 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=="], 687 763 688 - "@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=="], 689 765 690 - "@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=="], 691 767 692 - "@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=="], 693 769 694 - "@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=="], 695 771 696 - "@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=="], 697 773 698 - "@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=="], 699 775 700 - "@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=="], 701 777 702 - "@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=="], 703 779 704 - "@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=="], 705 781 706 - "@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=="], 707 783 708 - "@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=="], 709 785 710 - "@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=="], 711 787 712 - "@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=="], 713 789 714 - "@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=="], 715 791 716 - "@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=="], 717 793 718 - "@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=="], 719 795 720 - "@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=="], 721 797 722 - "@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=="], 723 799 724 - "@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=="], 725 801 726 - "@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=="], 727 803 728 - "@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=="], 729 805 730 - "@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=="], 731 807 732 - "@sentry/core": ["@sentry/core@8.55.0", "", {}, "sha512-6g7jpbefjHYs821Z+EBJ8r4Z7LT5h80YSWRJaylGS4nW5W5Z2KXzpdnyFarv37O7QjauzVC2E+PABmpkw5/JGA=="], 808 + "@tabler/icons-react": ["@tabler/icons-react@3.35.0", "", { "dependencies": { "@tabler/icons": "3.35.0" }, "peerDependencies": { "react": ">= 16" } }, "sha512-XG7t2DYf3DyHT5jxFNp5xyLVbL4hMJYJhiSdHADzAjLRYfL7AnjlRfiHDHeXxkb2N103rEIvTsBRazxXtAUz2g=="], 733 809 734 - "@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=="], 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=="], 735 811 736 - "@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=="], 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=="], 737 813 738 - "@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="], 814 + "@tailwindcss/oxide-android-arm64": ["@tailwindcss/oxide-android-arm64@4.1.17", "", { "os": "android", "cpu": "arm64" }, "sha512-BMqpkJHgOZ5z78qqiGE6ZIRExyaHyuxjgrJ6eBO5+hfrfGkuya0lYfw8fRHG77gdTjWkNWEEm+qeG2cDMxArLQ=="], 739 815 740 - "@standard-schema/spec": ["@standard-schema/spec@1.0.0", "", {}, "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA=="], 816 + "@tailwindcss/oxide-darwin-arm64": ["@tailwindcss/oxide-darwin-arm64@4.1.17", "", { "os": "darwin", "cpu": "arm64" }, "sha512-EquyumkQweUBNk1zGEU/wfZo2qkp/nQKRZM8bUYO0J+Lums5+wl2CcG1f9BgAjn/u9pJzdYddHWBiFXJTcxmOg=="], 741 817 742 - "@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=="], 818 + "@tailwindcss/oxide-darwin-x64": ["@tailwindcss/oxide-darwin-x64@4.1.17", "", { "os": "darwin", "cpu": "x64" }, "sha512-gdhEPLzke2Pog8s12oADwYu0IAw04Y2tlmgVzIN0+046ytcgx8uZmCzEg4VcQh+AHKiS7xaL8kGo/QTiNEGRog=="], 743 819 744 - "@swc/core-darwin-arm64": ["@swc/core-darwin-arm64@1.15.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-AXfeQn0CvcQ4cndlIshETx6jrAM45oeUrK8YeEY6oUZU/qzz0Id0CyvlEywxkWVC81Ajpd8TQQ1fW5yx6zQWkQ=="], 820 + "@tailwindcss/oxide-freebsd-x64": ["@tailwindcss/oxide-freebsd-x64@4.1.17", "", { "os": "freebsd", "cpu": "x64" }, "sha512-hxGS81KskMxML9DXsaXT1H0DyA+ZBIbyG/sSAjWNe2EDl7TkPOBI42GBV3u38itzGUOmFfCzk1iAjDXds8Oh0g=="], 745 821 746 - "@swc/core-darwin-x64": ["@swc/core-darwin-x64@1.15.3", "", { "os": "darwin", "cpu": "x64" }, "sha512-p68OeCz1ui+MZYG4wmfJGvcsAcFYb6Sl25H9TxWl+GkBgmNimIiRdnypK9nBGlqMZAcxngNPtnG3kEMNnvoJ2A=="], 822 + "@tailwindcss/oxide-linux-arm-gnueabihf": ["@tailwindcss/oxide-linux-arm-gnueabihf@4.1.17", "", { "os": "linux", "cpu": "arm" }, "sha512-k7jWk5E3ldAdw0cNglhjSgv501u7yrMf8oeZ0cElhxU6Y2o7f8yqelOp3fhf7evjIS6ujTI3U8pKUXV2I4iXHQ=="], 747 823 748 - "@swc/core-linux-arm-gnueabihf": ["@swc/core-linux-arm-gnueabihf@1.15.3", "", { "os": "linux", "cpu": "arm" }, "sha512-Nuj5iF4JteFgwrai97mUX+xUOl+rQRHqTvnvHMATL/l9xE6/TJfPBpd3hk/PVpClMXG3Uvk1MxUFOEzM1JrMYg=="], 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=="], 749 825 750 - "@swc/core-linux-arm64-gnu": ["@swc/core-linux-arm64-gnu@1.15.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-2Nc/s8jE6mW2EjXWxO/lyQuLKShcmTrym2LRf5Ayp3ICEMX6HwFqB1EzDhwoMa2DcUgmnZIalesq2lG3krrUNw=="], 826 + "@tailwindcss/oxide-linux-arm64-musl": ["@tailwindcss/oxide-linux-arm64-musl@4.1.17", "", { "os": "linux", "cpu": "arm64" }, "sha512-HvZLfGr42i5anKtIeQzxdkw/wPqIbpeZqe7vd3V9vI3RQxe3xU1fLjss0TjyhxWcBaipk7NYwSrwTwK1hJARMg=="], 751 827 752 - "@swc/core-linux-arm64-musl": ["@swc/core-linux-arm64-musl@1.15.3", "", { "os": "linux", "cpu": "arm64" }, "sha512-j4SJniZ/qaZ5g8op+p1G9K1z22s/EYGg1UXIb3+Cg4nsxEpF5uSIGEE4mHUfA70L0BR9wKT2QF/zv3vkhfpX4g=="], 828 + "@tailwindcss/oxide-linux-x64-gnu": ["@tailwindcss/oxide-linux-x64-gnu@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-M3XZuORCGB7VPOEDH+nzpJ21XPvK5PyjlkSFkFziNHGLc5d6g3di2McAAblmaSUNl8IOmzYwLx9NsE7bplNkwQ=="], 753 829 754 - "@swc/core-linux-x64-gnu": ["@swc/core-linux-x64-gnu@1.15.3", "", { "os": "linux", "cpu": "x64" }, "sha512-aKttAZnz8YB1VJwPQZtyU8Uk0BfMP63iDMkvjhJzRZVgySmqt/apWSdnoIcZlUoGheBrcqbMC17GGUmur7OT5A=="], 830 + "@tailwindcss/oxide-linux-x64-musl": ["@tailwindcss/oxide-linux-x64-musl@4.1.17", "", { "os": "linux", "cpu": "x64" }, "sha512-k7f+pf9eXLEey4pBlw+8dgfJHY4PZ5qOUFDyNf7SI6lHjQ9Zt7+NcscjpwdCEbYi6FI5c2KDTDWyf2iHcCSyyQ=="], 755 831 756 - "@swc/core-linux-x64-musl": ["@swc/core-linux-x64-musl@1.15.3", "", { "os": "linux", "cpu": "x64" }, "sha512-oe8FctPu1gnUsdtGJRO2rvOUIkkIIaHqsO9xxN0bTR7dFTlPTGi2Fhk1tnvXeyAvCPxLIcwD8phzKg6wLv9yug=="], 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=="], 757 833 758 - "@swc/core-win32-arm64-msvc": ["@swc/core-win32-arm64-msvc@1.15.3", "", { "os": "win32", "cpu": "arm64" }, "sha512-L9AjzP2ZQ/Xh58e0lTRMLvEDrcJpR7GwZqAtIeNLcTK7JVE+QineSyHp0kLkO1rttCHyCy0U74kDTj0dRz6raA=="], 834 + "@tailwindcss/oxide-win32-arm64-msvc": ["@tailwindcss/oxide-win32-arm64-msvc@4.1.17", "", { "os": "win32", "cpu": "arm64" }, "sha512-JU5AHr7gKbZlOGvMdb4722/0aYbU+tN6lv1kONx0JK2cGsh7g148zVWLM0IKR3NeKLv+L90chBVYcJ8uJWbC9A=="], 759 835 760 - "@swc/core-win32-ia32-msvc": ["@swc/core-win32-ia32-msvc@1.15.3", "", { "os": "win32", "cpu": "ia32" }, "sha512-B8UtogMzErUPDWUoKONSVBdsgKYd58rRyv2sHJWKOIMCHfZ22FVXICR4O/VwIYtlnZ7ahERcjayBHDlBZpR0aw=="], 836 + "@tailwindcss/oxide-win32-x64-msvc": ["@tailwindcss/oxide-win32-x64-msvc@4.1.17", "", { "os": "win32", "cpu": "x64" }, "sha512-SKWM4waLuqx0IH+FMDUw6R66Hu4OuTALFgnleKbqhgGU30DY20NORZMZUKgLRjQXNN2TLzKvh48QXTig4h4bGw=="], 761 837 762 - "@swc/core-win32-x64-msvc": ["@swc/core-win32-x64-msvc@1.15.3", "", { "os": "win32", "cpu": "x64" }, "sha512-SpZKMR9QBTecHeqpzJdYEfgw30Oo8b/Xl6rjSzBt1g0ZsXyy60KLXrp6IagQyfTYqNYE/caDvwtF2FPn7pomog=="], 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=="], 763 839 764 - "@swc/counter": ["@swc/counter@0.1.3", "", {}, "sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ=="], 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=="], 765 841 766 - "@swc/types": ["@swc/types@0.1.25", "", { "dependencies": { "@swc/counter": "^0.1.3" } }, "sha512-iAoY/qRhNH8a/hBvm3zKj9qQ4oc2+3w1unPJa2XvTK3XjeLXtzcCingVPw/9e5mn1+0yPqxcBGp9Jf0pkfMb1g=="], 842 + "@tanstack/history": ["@tanstack/history@1.140.0", "", {}, "sha512-u+/dChlWlT3kYa/RmFP+E7xY5EnzvKEKcvKk+XrgWMpBWExQIh3RQX/eUqhqwCXJPNc4jfm1Coj8umnm/hDgyA=="], 767 843 768 - "@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=="], 844 + "@tanstack/query-core": ["@tanstack/query-core@5.90.12", "", {}, "sha512-T1/8t5DhV/SisWjDnaiU2drl6ySvsHj1bHBCWNXd+/T+Hh1cf6JodyEYMd5sgwm+b/mETT4EV3H+zCVczCU5hg=="], 769 845 770 - "@tanstack/history": ["@tanstack/history@1.139.0", "", {}, "sha512-l6wcxwDBeh/7Dhles23U1O8lp9kNJmAb2yNjekR6olZwCRNAVA8TCXlVCrueELyFlYZqvQkh0ofxnzG62A1Kkg=="], 846 + "@tanstack/query-devtools": ["@tanstack/query-devtools@5.91.1", "", {}, "sha512-l8bxjk6BMsCaVQH6NzQEE/bEgFy1hAs5qbgXl0xhzezlaQbPk6Mgz9BqEg2vTLPOHD8N4k+w/gdgCbEzecGyNg=="], 771 847 772 - "@tanstack/query-core": ["@tanstack/query-core@5.90.10", "", {}, "sha512-EhZVFu9rl7GfRNuJLJ3Y7wtbTnENsvzp+YpcAV7kCYiXni1v8qZh++lpw4ch4rrwC0u/EZRnBHIehzCGzwXDSQ=="], 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=="], 773 849 774 - "@tanstack/query-devtools": ["@tanstack/query-devtools@5.91.0", "", {}, "sha512-uNWkqWTiIKCv8Iaahb7bftmDaZVkBetB+l+OQhQeCEZAedyqxw2eyaRUc8sAQ2LzD843tVdYL6bzOtRWJHJSbQ=="], 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=="], 775 851 776 - "@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=="], 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=="], 777 853 778 - "@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=="], 779 - 780 - "@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=="], 781 - 782 - "@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=="], 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=="], 783 855 784 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=="], 785 857 786 - "@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=="], 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=="], 787 859 788 - "@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=="], 789 - 790 - "@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=="], 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=="], 791 861 792 - "@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=="], 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=="], 793 863 794 - "@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=="], 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=="], 795 865 796 - "@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=="], 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=="], 797 867 798 868 "@tanstack/store": ["@tanstack/store@0.8.0", "", {}, "sha512-Om+BO0YfMZe//X2z0uLF2j+75nQga6TpTJgLJQBiq85aOyZNIhkCgleNcud2KQg4k4v9Y9l+Uhru3qWMPGTOzQ=="], 799 869 800 - "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.139.0", "", {}, "sha512-9PImF1d1tovTUIpjFVa0W7Fwj/MHif7BaaczgJJfbv3sDt1Gh+oW9W9uCw9M3ndEJynnp5ZD/TTs0RGubH5ssg=="], 870 + "@tanstack/virtual-file-routes": ["@tanstack/virtual-file-routes@1.140.0", "", {}, "sha512-LVmd19QkxV3x40oHkuTii9ey3l5XDV+X8locO2p5zfVDUC+N58H2gA7cDUtVc9qtImncnz3WxQkO/6kM3PMx2w=="], 871 + 872 + "@tybys/wasm-util": ["@tybys/wasm-util@0.10.1", "", { "dependencies": { "tslib": "^2.4.0" } }, "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg=="], 801 873 802 874 "@typelex/emitter": ["@typelex/emitter@0.4.0", "", { "dependencies": { "@typespec/compiler": "^1.4.0" } }, "sha512-BaKny+8TA0yX5jZibkAodHHKLJ6l6xVe5ut7KeoUyTD63lSSuB9OXe8tWXrs2DbeR/hialCimHFZQ3xANleMow=="], 803 875 ··· 816 888 "@types/estree": ["@types/estree@1.0.8", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="], 817 889 818 890 "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], 891 + 892 + "@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="], 819 893 820 894 "@types/mysql": ["@types/mysql@2.15.26", "", { "dependencies": { "@types/node": "*" } }, "sha512-DSLCOXhkvfS5WNNPbfn2KdICAmk8lLc+/PNvnPnF7gOdMZCxopXduqv0OQ13y/yA/zXTSikZZqVgybUxOEg6YQ=="], 821 895 ··· 857 931 858 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=="], 859 933 860 - "@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=="], 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=="], 861 937 862 - "@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=="], 938 + "@unrs/resolver-binding-darwin-arm64": ["@unrs/resolver-binding-darwin-arm64@1.11.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g=="], 863 939 864 - "abort-controller": ["abort-controller@3.0.0", "", { "dependencies": { "event-target-shim": "^5.0.0" } }, "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg=="], 940 + "@unrs/resolver-binding-darwin-x64": ["@unrs/resolver-binding-darwin-x64@1.11.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ=="], 941 + 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=="], 865 973 866 974 "acorn": ["acorn@8.15.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg=="], 867 975 ··· 877 985 878 986 "ansis": ["ansis@4.2.0", "", {}, "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig=="], 879 987 880 - "any-promise": ["any-promise@1.3.0", "", {}, "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A=="], 881 - 882 988 "anymatch": ["anymatch@3.1.3", "", { "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" } }, "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw=="], 883 989 884 - "arg": ["arg@5.0.2", "", {}, "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg=="], 990 + "app": ["app@workspace:apps/app"], 885 991 886 992 "argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="], 887 993 888 994 "aria-hidden": ["aria-hidden@1.2.6", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA=="], 889 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 + 890 1014 "ast-types": ["ast-types@0.16.1", "", { "dependencies": { "tslib": "^2.0.1" } }, "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg=="], 891 1015 892 - "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=="], 893 1019 894 1020 "atomic-sleep": ["atomic-sleep@1.0.0", "", {}, "sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ=="], 895 1021 896 - "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=="], 1023 + 1024 + "axe-core": ["axe-core@4.11.0", "", {}, "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ=="], 897 1025 898 - "axios": ["axios@1.13.2", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA=="], 1026 + "axobject-query": ["axobject-query@4.1.0", "", {}, "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ=="], 899 1027 900 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=="], 901 1029 ··· 903 1031 904 1032 "balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="], 905 1033 906 - "base64-js": ["base64-js@1.5.1", "", {}, "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="], 907 - 908 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=="], 909 1035 910 1036 "binary-extensions": ["binary-extensions@2.3.0", "", {}, "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw=="], 911 - 912 - "boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="], 913 1037 914 1038 "brace-expansion": ["brace-expansion@1.1.12", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg=="], 915 1039 ··· 917 1041 918 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=="], 919 1043 920 - "buffer": ["buffer@6.0.3", "", { "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.2.1" } }, "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA=="], 921 - 922 1044 "buffer-from": ["buffer-from@1.1.2", "", {}, "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="], 923 1045 924 1046 "bufferutil": ["bufferutil@4.0.9", "", { "dependencies": { "node-gyp-build": "^4.3.0" } }, "sha512-WDtdLmJvAuNNPzByAYpRo2rF1Mmradw6gvWsQKf63476DDXmomT9zUiGypLcG4ibIM67vhAj8jJRdbmEws2Aqw=="], 925 1047 926 1048 "bun-types": ["bun-types@1.3.3", "", { "dependencies": { "@types/node": "*" } }, "sha512-z3Xwlg7j2l9JY27x5Qn3Wlyos8YAp0kKRlrePAOjgjMGS5IG6E7Jnlx736vH9UVI4wUICwwhC9anYL++XeOgTQ=="], 927 1049 928 - "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=="], 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=="], 929 1051 930 - "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], 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=="], 931 1053 932 - "camelcase-css": ["camelcase-css@2.0.1", "", {}, "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="], 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=="], 933 1055 934 - "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=="], 1056 + "callsites": ["callsites@3.1.0", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="], 935 1057 936 1058 "caniuse-lite": ["caniuse-lite@1.0.30001757", "", {}, "sha512-r0nnL/I28Zi/yjk1el6ilj27tKcdjLsNqAOZr0yVjWPrSQyHgKI2INaEWw21bAQSv2LXRt1XuCS/GomNpWOxsQ=="], 937 - 938 - "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=="], 939 - 940 - "cbor-x": ["cbor-x@1.6.0", "", { "optionalDependencies": { "cbor-extract": "^2.2.0" } }, "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg=="], 941 - 942 - "cborg": ["cborg@1.10.2", "", { "bin": { "cborg": "cli.js" } }, "sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug=="], 943 1059 944 1060 "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="], 945 1061 ··· 957 1073 958 1074 "cli-width": ["cli-width@4.1.0", "", {}, "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ=="], 959 1075 1076 + "client-only": ["client-only@0.0.1", "", {}, "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA=="], 1077 + 960 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=="], 961 1079 962 1080 "clsx": ["clsx@2.1.1", "", {}, "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA=="], ··· 965 1083 966 1084 "color-name": ["color-name@1.1.4", "", {}, "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="], 967 1085 968 - "colord": ["colord@2.9.3", "", {}, "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="], 969 - 970 1086 "colorette": ["colorette@2.0.20", "", {}, "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w=="], 971 1087 972 - "combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="], 973 - 974 - "commander": ["commander@4.1.1", "", {}, "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA=="], 975 - 976 1088 "concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="], 977 1089 978 1090 "convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], 979 1091 980 1092 "cookie-es": ["cookie-es@2.0.0", "", {}, "sha512-RAj4E421UYRgqokKUmotqAwuplYw15qtdXfY+hGzgCJ/MBjCVZcSoHK/kH9kocfjRjcDME7IiDWR/1WX1TM2Pg=="], 1093 + 1094 + "core-js": ["core-js@3.47.0", "", {}, "sha512-c3Q2VVkGAUyupsjRnaNX6u8Dq2vAdzm9iuPj5FW0fRxzlxgq9Q39MDq10IvmQSpLgHQNyQzQmOo6bgGHmH3NNg=="], 981 1095 982 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=="], 983 1097 984 - "css-declaration-sorter": ["css-declaration-sorter@7.3.0", "", { "peerDependencies": { "postcss": "^8.0.9" } }, "sha512-LQF6N/3vkAMYF4xoHLJfG718HRJh34Z8BnNhd6bosOMIVjMlhuZK5++oZa3uYAgrI5+7x2o27gUqTR2U/KjUOQ=="], 1098 + "csstype": ["csstype@3.2.3", "", {}, "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="], 985 1099 986 - "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=="], 1100 + "damerau-levenshtein": ["damerau-levenshtein@1.0.8", "", {}, "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA=="], 987 1101 988 - "css-tree": ["css-tree@3.1.0", "", { "dependencies": { "mdn-data": "2.12.2", "source-map-js": "^1.0.1" } }, "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w=="], 1102 + "data-uri-to-buffer": ["data-uri-to-buffer@4.0.1", "", {}, "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A=="], 989 1103 990 - "css-what": ["css-what@6.2.2", "", {}, "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA=="], 991 - 992 - "cssesc": ["cssesc@3.0.0", "", { "bin": { "cssesc": "bin/cssesc" } }, "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg=="], 993 - 994 - "cssnano": ["cssnano@7.1.2", "", { "dependencies": { "cssnano-preset-default": "^7.0.10", "lilconfig": "^3.1.3" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-HYOPBsNvoiFeR1eghKD5C3ASm64v9YVyJB4Ivnl2gqKoQYvjjN/G0rztvKQq8OxocUtC6sjqY8jwYngIB4AByA=="], 995 - 996 - "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=="], 997 - 998 - "cssnano-utils": ["cssnano-utils@5.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-ZIP71eQgG9JwjVZsTPSqhc6GHgEr53uJ7tK5///VfyWj6Xp2DBmixWHqJgPno+PqATzn48pL42ww9x5SSGmhZg=="], 999 - 1000 - "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=="], 1001 1105 1002 - "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=="], 1003 1107 1004 - "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=="], 1005 1109 1006 1110 "dateformat": ["dateformat@4.6.3", "", {}, "sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA=="], 1007 1111 ··· 1009 1113 1010 1114 "deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="], 1011 1115 1012 - "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=="], 1013 1119 1014 1120 "detect-libc": ["detect-libc@2.0.2", "", {}, "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw=="], 1015 1121 1016 1122 "detect-node-es": ["detect-node-es@1.1.0", "", {}, "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ=="], 1017 1123 1018 - "didyoumean": ["didyoumean@1.2.2", "", {}, "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw=="], 1019 - 1020 1124 "diff": ["diff@8.0.2", "", {}, "sha512-sSuxWU5j5SR9QQji/o2qMvqRNYRDOcBTgsJ/DeCf4iSN4gW+gNMXM7wFIP+fdXZxoNiAnHUTGjCr+TSWXdRDKg=="], 1021 1125 1022 - "dlv": ["dlv@1.1.3", "", {}, "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA=="], 1023 - 1024 - "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=="], 1025 - 1026 - "domelementtype": ["domelementtype@2.3.0", "", {}, "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw=="], 1027 - 1028 - "domhandler": ["domhandler@5.0.3", "", { "dependencies": { "domelementtype": "^2.3.0" } }, "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w=="], 1029 - 1030 - "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=="], 1031 1127 1032 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=="], 1033 1129 ··· 1037 1133 1038 1134 "electron-to-chromium": ["electron-to-chromium@1.5.259", "", {}, "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ=="], 1039 1135 1040 - "emoji-regex": ["emoji-regex@10.6.0", "", {}, "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A=="], 1136 + "emoji-regex": ["emoji-regex@9.2.2", "", {}, "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="], 1041 1137 1042 1138 "end-of-stream": ["end-of-stream@1.4.5", "", { "dependencies": { "once": "^1.4.0" } }, "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg=="], 1043 1139 1044 - "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=="], 1045 1141 1046 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=="], 1047 1145 1048 1146 "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], 1049 1147 1050 1148 "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], 1051 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=="], 1151 + 1052 1152 "es-object-atoms": ["es-object-atoms@1.1.1", "", { "dependencies": { "es-errors": "^1.3.0" } }, "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA=="], 1053 1153 1054 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=="], 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=="], 1055 1159 1056 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=="], 1057 1161 ··· 1063 1167 1064 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=="], 1065 1169 1066 - "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=="], 1067 1185 1068 1186 "eslint-plugin-react-refresh": ["eslint-plugin-react-refresh@0.4.24", "", { "peerDependencies": { "eslint": ">=8.40" } }, "sha512-nLHIW7TEq3aLrEYWpVaJ1dRgFR+wLDPN8e8FpYAql/bMV2oBEfC37K0gLEGgv9fy66juNShSMV8OkTqzltcG/w=="], 1069 1187 ··· 1086 1204 "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], 1087 1205 1088 1206 "event-target-polyfill": ["event-target-polyfill@0.0.4", "", {}, "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ=="], 1089 - 1090 - "event-target-shim": ["event-target-shim@5.0.1", "", {}, "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ=="], 1091 - 1092 - "events": ["events@3.3.0", "", {}, "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q=="], 1093 1207 1094 1208 "fast-copy": ["fast-copy@3.0.2", "", {}, "sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ=="], 1095 1209 ··· 1101 1215 1102 1216 "fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="], 1103 1217 1104 - "fast-redact": ["fast-redact@3.5.0", "", {}, "sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A=="], 1105 - 1106 1218 "fast-safe-stringify": ["fast-safe-stringify@2.1.1", "", {}, "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA=="], 1107 1219 1108 1220 "fast-uri": ["fast-uri@3.1.0", "", {}, "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA=="], ··· 1123 1235 1124 1236 "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], 1125 1237 1126 - "follow-redirects": ["follow-redirects@1.15.11", "", {}, "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ=="], 1127 - 1128 - "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=="], 1129 1239 1130 1240 "formdata-polyfill": ["formdata-polyfill@4.0.10", "", { "dependencies": { "fetch-blob": "^3.1.2" } }, "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g=="], 1131 1241 1132 1242 "forwarded-parse": ["forwarded-parse@2.1.2", "", {}, "sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw=="], 1133 1243 1134 - "fraction.js": ["fraction.js@5.3.4", "", {}, "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ=="], 1135 - 1136 1244 "fsevents": ["fsevents@2.3.3", "", { "os": "darwin" }, "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw=="], 1137 1245 1138 1246 "function-bind": ["function-bind@1.1.2", "", {}, "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="], 1139 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 + 1140 1254 "gensync": ["gensync@1.0.0-beta.2", "", {}, "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg=="], 1141 1255 1142 1256 "get-caller-file": ["get-caller-file@2.0.5", "", {}, "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="], ··· 1149 1263 1150 1264 "get-proto": ["get-proto@1.0.1", "", { "dependencies": { "dunder-proto": "^1.0.1", "es-object-atoms": "^1.0.0" } }, "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g=="], 1151 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=="], 1267 + 1152 1268 "get-tsconfig": ["get-tsconfig@4.13.0", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ=="], 1153 1269 1154 1270 "glob": ["glob@13.0.0", "", { "dependencies": { "minimatch": "^10.1.1", "minipass": "^7.1.2", "path-scurry": "^2.0.0" } }, "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA=="], 1155 1271 1156 1272 "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="], 1157 1273 1158 - "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=="], 1159 1277 1160 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=="], 1161 1279 1162 1280 "goober": ["goober@2.1.18", "", { "peerDependencies": { "csstype": "^3.0.10" } }, "sha512-2vFqsaDVIT9Gz7N6kAL++pLpp41l3PfDuusHcjnGLfR6+huZkl6ziX+zgVC3ZxpqWhzH6pyDdGrCeDhMIvwaxw=="], 1163 1281 1164 1282 "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], 1283 + 1284 + "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], 1165 1285 1166 1286 "graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="], 1167 1287 1288 + "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], 1289 + 1168 1290 "has-flag": ["has-flag@4.0.0", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="], 1169 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 + 1170 1296 "has-symbols": ["has-symbols@1.1.0", "", {}, "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ=="], 1171 1297 1172 1298 "has-tostringtag": ["has-tostringtag@1.0.2", "", { "dependencies": { "has-symbols": "^1.0.3" } }, "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw=="], ··· 1175 1301 1176 1302 "help-me": ["help-me@5.0.0", "", {}, "sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg=="], 1177 1303 1304 + "hermes-estree": ["hermes-estree@0.25.1", "", {}, "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw=="], 1305 + 1306 + "hermes-parser": ["hermes-parser@0.25.1", "", { "dependencies": { "hermes-estree": "0.25.1" } }, "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA=="], 1307 + 1178 1308 "hono": ["hono@4.10.7", "", {}, "sha512-icXIITfw/07Q88nLSkB9aiUrd8rYzSweK681Kjo/TSggaGbOX4RRyxxm71v+3PC8C/j+4rlxGeoTRxQDkaJkUw=="], 1179 1309 1180 1310 "iconv-lite": ["iconv-lite@0.7.0", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-cf6L2Ds3h57VVmkZe+Pn+5APsT7FpqJtEhhieDCvrE2MK5Qk9MyffgQyuxQTm6BChfeZNtcOLHp9IcWRVcIcBQ=="], 1181 - 1182 - "ieee754": ["ieee754@1.2.1", "", {}, "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="], 1183 1311 1184 1312 "ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="], 1185 1313 ··· 1189 1317 1190 1318 "imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="], 1191 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 + 1192 1322 "ipaddr.js": ["ipaddr.js@2.2.0", "", {}, "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA=="], 1193 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 + 1194 1330 "is-binary-path": ["is-binary-path@2.1.0", "", { "dependencies": { "binary-extensions": "^2.0.0" } }, "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw=="], 1195 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 + 1196 1338 "is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="], 1197 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 + 1198 1344 "is-extglob": ["is-extglob@2.1.1", "", {}, "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ=="], 1199 1345 1346 + "is-finalizationregistry": ["is-finalizationregistry@1.1.1", "", { "dependencies": { "call-bound": "^1.0.3" } }, "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg=="], 1347 + 1200 1348 "is-fullwidth-code-point": ["is-fullwidth-code-point@3.0.0", "", {}, "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="], 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=="], 1201 1351 1202 1352 "is-glob": ["is-glob@4.0.3", "", { "dependencies": { "is-extglob": "^2.1.1" } }, "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg=="], 1203 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 + 1204 1358 "is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="], 1205 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 + 1206 1374 "is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="], 1207 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 + 1208 1384 "isbot": ["isbot@5.1.32", "", {}, "sha512-VNfjM73zz2IBZmdShMfAUg10prm6t7HFUQmNAEOAVS4YH92ZrZcvkMcGX6cIgBJAzWDzPent/EeAtYEHNPNPBQ=="], 1209 1385 1210 1386 "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="], 1211 1387 1212 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=="], 1213 1391 1214 1392 "jiti": ["jiti@1.21.7", "", { "bin": { "jiti": "bin/jiti.js" } }, "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A=="], 1215 1393 ··· 1233 1411 1234 1412 "json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], 1235 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 + 1236 1416 "keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="], 1237 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=="], 1421 + 1238 1422 "levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="], 1239 1423 1240 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=="], 1241 1425 1242 - "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=="], 1243 1447 1244 - "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=="], 1245 1449 1246 1450 "locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="], 1247 1451 1248 - "lodash.memoize": ["lodash.memoize@4.1.2", "", {}, "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="], 1249 - 1250 1452 "lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="], 1251 1453 1252 - "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=="], 1253 1455 1254 - "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=="], 1255 1457 1256 - "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=="], 1257 1459 1258 - "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=="], 1259 1461 1260 - "mdn-data": ["mdn-data@2.12.2", "", {}, "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA=="], 1462 + "math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="], 1261 1463 1262 1464 "merge2": ["merge2@1.4.1", "", {}, "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg=="], 1263 1465 1264 1466 "micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="], 1265 - 1266 - "mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="], 1267 - 1268 - "mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="], 1269 1467 1270 1468 "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], 1271 1469 ··· 1284 1482 "mustache": ["mustache@4.2.0", "", { "bin": { "mustache": "bin/mustache" } }, "sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ=="], 1285 1483 1286 1484 "mute-stream": ["mute-stream@2.0.0", "", {}, "sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA=="], 1287 - 1288 - "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=="], 1289 1485 1290 1486 "nanoid": ["nanoid@5.1.6", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg=="], 1291 1487 1488 + "napi-postinstall": ["napi-postinstall@0.3.4", "", { "bin": { "napi-postinstall": "lib/cli.js" } }, "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ=="], 1489 + 1292 1490 "natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="], 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=="], 1293 1493 1294 1494 "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], 1295 1495 ··· 1297 1497 1298 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=="], 1299 1499 1300 - "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=="], 1301 - 1302 1500 "node-releases": ["node-releases@2.0.27", "", {}, "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA=="], 1303 1501 1304 1502 "normalize-path": ["normalize-path@3.0.0", "", {}, "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="], 1305 1503 1306 - "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=="], 1505 + 1506 + "object-inspect": ["object-inspect@1.13.4", "", {}, "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew=="], 1307 1507 1308 - "nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="], 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=="], 1309 1515 1310 - "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=="], 1311 1517 1312 - "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=="], 1313 1519 1314 1520 "on-exit-leak-free": ["on-exit-leak-free@2.1.2", "", {}, "sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA=="], 1315 1521 1316 1522 "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], 1317 1523 1318 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=="], 1319 1527 1320 1528 "p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="], 1321 1529 ··· 1358 1566 "picocolors": ["picocolors@1.1.1", "", {}, "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="], 1359 1567 1360 1568 "picomatch": ["picomatch@4.0.3", "", {}, "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q=="], 1361 - 1362 - "pify": ["pify@2.3.0", "", {}, "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog=="], 1363 1569 1364 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=="], 1365 1571 ··· 1369 1575 1370 1576 "pino-std-serializers": ["pino-std-serializers@7.0.0", "", {}, "sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA=="], 1371 1577 1372 - "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=="], 1373 1579 1374 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=="], 1375 1581 1376 - "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=="], 1377 - 1378 - "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=="], 1379 - 1380 - "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=="], 1381 - 1382 - "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=="], 1383 - 1384 - "postcss-discard-duplicates": ["postcss-discard-duplicates@7.0.2", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-eTonaQvPZ/3i1ASDHOKkYwAybiM45zFIc7KXils4mQmHLqIswXD9XNOKEVxtTFnsmwYzF66u4LMgSr0abDlh5w=="], 1385 - 1386 - "postcss-discard-empty": ["postcss-discard-empty@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-cFrJKZvcg/uxB6Ijr4l6qmn3pXQBna9zyrPC+sK0zjbkDUZew+6xDltSF7OeB7rAtzaaMVYSdbod+sZOCWnMOg=="], 1387 - 1388 - "postcss-discard-overridden": ["postcss-discard-overridden@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-7c3MMjjSZ/qYrx3uc1940GSOzN1Iqjtlqe8uoSg+qdVPYyRb0TILSqqmtlSFuE4mTDECwsm397Ya7iXGzfF7lg=="], 1389 - 1390 - "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=="], 1391 - 1392 - "postcss-js": ["postcss-js@4.1.0", "", { "dependencies": { "camelcase-css": "^2.0.1" }, "peerDependencies": { "postcss": "^8.4.21" } }, "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw=="], 1393 - 1394 - "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=="], 1395 - 1396 - "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=="], 1397 - 1398 - "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=="], 1399 - 1400 - "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=="], 1401 - 1402 - "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=="], 1403 - 1404 - "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=="], 1405 - 1406 - "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=="], 1407 - 1408 - "postcss-nested": ["postcss-nested@6.2.0", "", { "dependencies": { "postcss-selector-parser": "^6.1.1" }, "peerDependencies": { "postcss": "^8.2.14" } }, "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ=="], 1409 - 1410 - "postcss-normalize-charset": ["postcss-normalize-charset@7.0.1", "", { "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-sn413ofhSQHlZFae//m9FTOfkmiZ+YQXsbosqOWRiVQncU2BA3daX3n0VF3cG6rGLSFVc5Di/yns0dFfh8NFgQ=="], 1411 - 1412 - "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=="], 1413 - 1414 - "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=="], 1415 - 1416 - "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=="], 1417 - 1418 - "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=="], 1419 - 1420 - "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=="], 1421 - 1422 - "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=="], 1423 - 1424 - "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=="], 1425 - 1426 - "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=="], 1427 - 1428 - "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=="], 1429 - 1430 - "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=="], 1431 - 1432 - "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=="], 1433 - 1434 - "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=="], 1435 - 1436 - "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=="], 1437 - 1438 - "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=="], 1439 - 1440 - "postcss-value-parser": ["postcss-value-parser@4.2.0", "", {}, "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="], 1441 - 1442 1582 "postgres-array": ["postgres-array@2.0.0", "", {}, "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="], 1443 1583 1444 1584 "postgres-bytea": ["postgres-bytea@1.0.0", "", {}, "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w=="], ··· 1451 1591 1452 1592 "prettier": ["prettier@3.6.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ=="], 1453 1593 1454 - "process": ["process@0.11.10", "", {}, "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A=="], 1455 - 1456 1594 "process-warning": ["process-warning@5.0.0", "", {}, "sha512-a39t9ApHNx2L4+HBnQKqxxHNs1r7KF+Intd8Q/g1bUh6q0WIp9voPXJ/x0j+ZL45KF1pJd9+q2jLIRMfvEshkA=="], 1457 1595 1458 1596 "promise-limit": ["promise-limit@2.7.0", "", {}, "sha512-7nJ6v5lnJsXwGprnGXga4wx6d1POjvi5Qmf1ivTRxTjH4Z/9Czja/UCMLVmB9N93GeWOU93XaFaEt6jbuoagNw=="], 1459 1597 1460 - "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=="], 1461 1599 1462 1600 "pump": ["pump@3.0.3", "", { "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" } }, "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA=="], 1463 1601 ··· 1467 1605 1468 1606 "quick-format-unescaped": ["quick-format-unescaped@4.0.4", "", {}, "sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg=="], 1469 1607 1470 - "react": ["react@19.0.0", "", {}, "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ=="], 1608 + "react": ["react@19.2.0", "", {}, "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ=="], 1471 1609 1472 - "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=="], 1473 1611 1474 - "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=="], 1475 1613 1476 1614 "react-refresh": ["react-refresh@0.18.0", "", {}, "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw=="], 1477 1615 ··· 1481 1619 1482 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=="], 1483 1621 1484 - "read-cache": ["read-cache@1.0.0", "", { "dependencies": { "pify": "^2.3.0" } }, "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA=="], 1485 - 1486 - "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=="], 1487 - 1488 1622 "readdirp": ["readdirp@3.6.0", "", { "dependencies": { "picomatch": "^2.2.1" } }, "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA=="], 1489 1623 1490 1624 "real-require": ["real-require@0.2.0", "", {}, "sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg=="], 1491 1625 1492 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=="], 1493 1631 1494 1632 "require-from-string": ["require-from-string@2.0.2", "", {}, "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="], 1495 1633 ··· 1505 1643 1506 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=="], 1507 1645 1508 - "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=="], 1509 1647 1510 1648 "run-parallel": ["run-parallel@1.2.0", "", { "dependencies": { "queue-microtask": "^1.2.2" } }, "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA=="], 1511 1649 1512 - "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=="], 1513 1655 1514 1656 "safe-stable-stringify": ["safe-stable-stringify@2.5.0", "", {}, "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA=="], 1515 1657 1516 1658 "safer-buffer": ["safer-buffer@2.1.2", "", {}, "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="], 1517 1659 1518 - "sax": ["sax@1.4.3", "", {}, "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ=="], 1519 - 1520 - "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=="], 1521 1661 1522 1662 "secure-json-parse": ["secure-json-parse@4.1.0", "", {}, "sha512-l4KnYfEyqYJxDwlNVyRfO2E4NTHfMKAWdUuA8J0yve2Dz/E/PdBepY03RvyJpssIpRFwJoCD55wA+mEDs6ByWA=="], 1523 1663 ··· 1526 1666 "seroval": ["seroval@1.4.0", "", {}, "sha512-BdrNXdzlofomLTiRnwJTSEAaGKyHHZkbMXIywOh7zlzp4uZnXErEwl9XZ+N1hJSNpeTtNxWvVwN0wUzAIQ4Hpg=="], 1527 1667 1528 1668 "seroval-plugins": ["seroval-plugins@1.4.0", "", { "peerDependencies": { "seroval": "^1.0" } }, "sha512-zir1aWzoiax6pbBVjoYVd0O1QQXgIL3eVGBMsBsNmM8Ukq90yGaWlfx0AB9dTS8GPqrOrbXn79vmItCUP9U3BQ=="], 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=="], 1529 1677 1530 1678 "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], 1531 1679 ··· 1533 1681 1534 1682 "shimmer": ["shimmer@1.2.1", "", {}, "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw=="], 1535 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 + 1536 1692 "signal-exit": ["signal-exit@4.1.0", "", {}, "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw=="], 1537 1693 1538 1694 "slash": ["slash@5.1.0", "", {}, "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg=="], ··· 1549 1705 1550 1706 "split2": ["split2@4.2.0", "", {}, "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg=="], 1551 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 + 1552 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=="], 1553 1713 1554 - "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=="], 1555 1725 1556 1726 "strip-ansi": ["strip-ansi@7.1.2", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA=="], 1557 1727 1728 + "strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="], 1729 + 1558 1730 "strip-json-comments": ["strip-json-comments@5.0.3", "", {}, "sha512-1tB5mhVo7U+ETBKNf92xT4hrQa3pm0MZ0PQvuDnWgAAGHDsfp4lPSpiS6psrSiet87wyGPh9ft6wmhOMQ0hDiw=="], 1559 1731 1560 - "stylehacks": ["stylehacks@7.0.7", "", { "dependencies": { "browserslist": "^4.27.0", "postcss-selector-parser": "^7.1.0" }, "peerDependencies": { "postcss": "^8.4.32" } }, "sha512-bJkD0JkEtbRrMFtwgpJyBbFIwfDDONQ1Ov3sDLZQP8HuJ73kBOyx66H4bOcAbVWmnfLdvQ0AJwXxOMkpujcO6g=="], 1561 - 1562 - "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=="], 1563 1733 1564 1734 "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], 1565 1735 1566 1736 "supports-preserve-symlinks-flag": ["supports-preserve-symlinks-flag@1.0.0", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="], 1567 1737 1568 - "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=="], 1569 1739 1570 - "tailwind-merge": ["tailwind-merge@2.6.0", "", {}, "sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA=="], 1740 + "tailwindcss": ["tailwindcss@4.1.17", "", {}, "sha512-j9Ee2YjuQqYT9bbRTfTZht9W/ytp5H+jJpZKiYdP/bpnXARAuELt9ofP0lPnmHjbga7SNQIxdTAXCmtKVYjN+Q=="], 1571 1741 1572 - "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=="], 1573 - 1574 - "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=="], 1575 1743 1576 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=="], 1577 1745 ··· 1579 1747 1580 1748 "temporal-spec": ["temporal-spec@0.3.0", "", {}, "sha512-n+noVpIqz4hYgFSMOSiINNOUOMFtV5cZQNCmmszA6GiVFVRt3G7AqVyhXjhCSmowvQn+NsGn+jMDMKJYHd3bSQ=="], 1581 1749 1582 - "thenify": ["thenify@3.3.1", "", { "dependencies": { "any-promise": "^1.0.0" } }, "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw=="], 1583 - 1584 - "thenify-all": ["thenify-all@1.6.0", "", { "dependencies": { "thenify": ">= 3.1.0 < 4" } }, "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA=="], 1585 - 1586 1750 "thread-stream": ["thread-stream@3.1.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A=="], 1587 1751 1588 1752 "tiny-invariant": ["tiny-invariant@1.3.3", "", {}, "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="], ··· 1595 1759 1596 1760 "ts-api-utils": ["ts-api-utils@2.1.0", "", { "peerDependencies": { "typescript": ">=4.8.4" } }, "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ=="], 1597 1761 1598 - "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=="], 1599 1763 1600 1764 "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], 1601 1765 1602 - "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=="], 1603 1767 1604 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=="], 1605 1769 ··· 1615 1779 1616 1780 "turbo-windows-arm64": ["turbo-windows-arm64@2.6.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-7w+AD5vJp3R+FB0YOj1YJcNcOOvBior7bcHTodqp90S3x3bLgpr7tE6xOea1e8JkP7GK6ciKVUpQvV7psiwU5Q=="], 1617 1781 1782 + "tw-animate-css": ["tw-animate-css@1.4.0", "", {}, "sha512-7bziOlRqH0hJx80h/3mbicLW7o8qLsH5+RaLR2t+OHM3D0JlWGODQKQ4cxbK7WlvmUxpcj6Kgu6EKqjrGFe3QQ=="], 1783 + 1618 1784 "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="], 1619 1785 1620 1786 "type-fest": ["type-fest@4.41.0", "", {}, "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA=="], 1621 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 + 1622 1796 "typescript": ["typescript@5.9.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw=="], 1623 1797 1624 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=="], 1625 1799 1626 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=="], 1627 1803 1628 1804 "undici": ["undici@6.22.0", "", {}, "sha512-hU/10obOIu62MGYjdskASR3CUAiYaFTtC9Pa6vHyf//mAipSvSQg6od2CnJswq7fvzNS3zJhxoRkgNVaHurWKw=="], 1629 1805 1630 1806 "undici-types": ["undici-types@6.21.0", "", {}, "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="], 1631 1807 1808 + "unicode-segmenter": ["unicode-segmenter@0.14.1", "", {}, "sha512-yHedxlEpUyD+u1UE8qAuCMXVdMLn7yUdlmd8WN7FGmO1ICnpE7LJfnmuXBB+T0zkie3qHsy8fSucqceI/MylOg=="], 1809 + 1632 1810 "unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="], 1633 1811 1634 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=="], 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=="], 1635 1815 1636 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=="], 1637 1817 ··· 1643 1823 1644 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=="], 1645 1825 1646 - "util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="], 1647 - 1648 - "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=="], 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=="], 1649 1827 1650 1828 "vscode-jsonrpc": ["vscode-jsonrpc@8.2.0", "", {}, "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA=="], 1651 1829 ··· 1657 1835 1658 1836 "vscode-languageserver-types": ["vscode-languageserver-types@3.17.5", "", {}, "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg=="], 1659 1837 1838 + "web": ["web@workspace:apps/web"], 1839 + 1660 1840 "web-streams-polyfill": ["web-streams-polyfill@3.3.3", "", {}, "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw=="], 1661 1841 1662 1842 "webpack-virtual-modules": ["webpack-virtual-modules@0.6.2", "", {}, "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ=="], 1663 1843 1664 1844 "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="], 1665 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 + 1666 1854 "word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="], 1667 1855 1668 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=="], ··· 1689 1877 1690 1878 "zod": ["zod@3.25.76", "", {}, "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ=="], 1691 1879 1692 - "@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=="], 1883 + 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=="], 1693 1889 1694 - "@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=="], 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=="], 1891 + 1892 + "@atcute/xrpc-server/@atcute/uint8array": ["@atcute/uint8array@1.0.5", "", {}, "sha512-XLWWxoR2HNl2qU+FCr0rp1APwJXci7HnzbOQLxK55OaMNBXZ19+xNC5ii4QCsThsDxa4JS/JTzuiQLziITWf2Q=="], 1695 1893 1696 - "@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=="], 1894 + "@atproto-labs/simple-store-memory/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 1697 1895 1698 - "@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=="], 1896 + "@atproto/lex-data/@atproto/syntax": ["@atproto/syntax@0.4.2", "", {}, "sha512-X9XSRPinBy/0VQ677j8VXlBsYSsUXaiqxWVpGGxJYsAhugdQRb0jqaVKJFtm6RskeNkV6y9xclSUi9UYG/COrA=="], 1699 1897 1700 1898 "@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1701 1899 1702 - "@babel/helper-compilation-targets/lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="], 1703 - 1704 1900 "@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1705 1901 1706 1902 "@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], 1707 1903 1708 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=="], 1709 1905 1710 - "@cookware/web/@atcute/bluesky": ["@atcute/bluesky@1.0.15", "", { "peerDependencies": { "@atcute/client": "^1.0.0 || ^2.0.0" } }, "sha512-+EFiybmKQ97aBAgtaD+cKRJER5AMn3cZMkEwEg/pDdWyzxYJ9m1UgemmLdTgI8VrxPufKqdXS2nl7uO7TY6BPA=="], 1711 - 1712 - "@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=="], 1713 1907 1714 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=="], 1715 1909 ··· 1722 1916 "@eslint/eslintrc/strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="], 1723 1917 1724 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=="], 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=="], 1725 1921 1726 1922 "@opentelemetry/core/@opentelemetry/semantic-conventions": ["@opentelemetry/semantic-conventions@1.28.0", "", {}, "sha512-lp4qAiMTD4sNWW4DbKLBkfiMZ4jbAboJIGOQr5DvciMRI494OapieI9qiODpOt0XBr1LjIDy1xAGAnVs5supTA=="], 1727 1923 ··· 1740 1936 "@prisma/instrumentation/@opentelemetry/instrumentation": ["@opentelemetry/instrumentation@0.53.0", "", { "dependencies": { "@opentelemetry/api-logs": "0.53.0", "@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-DMwg0hy4wzf7K73JJtl95m/e0boSoWhH07rfvHvYzQtBD3Bmv0Wc1x733vyZBqmFm8OjJD0/pfiUg1W3JjFX0A=="], 1741 1937 1742 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=="], 1743 - 1744 - "@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=="], 1745 - 1746 - "@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=="], 1747 1939 1748 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=="], 1749 1941 ··· 1789 1981 1790 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=="], 1791 1983 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=="], 1993 + 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=="], 1997 + 1792 1998 "@types/pg-pool/@types/pg": ["@types/pg@8.6.1", "", { "dependencies": { "@types/node": "*", "pg-protocol": "*", "pg-types": "^2.2.0" } }, "sha512-1Kc4oAGzAl7uqUStZCDvaLFqZrW9qWSjXOmBfdgyBP5La7Us6Mg4GBvRlSoaZMhQF/zSj1C8CtKMBkoiT8eL8w=="], 1793 1999 1794 2000 "@typescript-eslint/eslint-plugin/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], 1795 2001 1796 2002 "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], 1797 2003 1798 - "@vitejs/plugin-react-swc/@rolldown/pluginutils": ["@rolldown/pluginutils@1.0.0-beta.27", "", {}, "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA=="], 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=="], 1799 2005 1800 2006 "anymatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 1801 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 + 1802 2014 "chokidar/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], 1803 2015 1804 - "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=="], 1805 2021 1806 - "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=="], 2022 + "eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="], 2023 + 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=="], 1807 2031 1808 2032 "fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], 1809 2033 ··· 1811 2035 1812 2036 "globby/ignore": ["ignore@7.0.5", "", {}, "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg=="], 1813 2037 1814 - "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 2038 + "lightningcss/detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], 1815 2039 1816 - "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=="], 1817 2041 1818 - "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=="], 1819 2043 1820 - "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=="], 1821 2045 1822 - "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=="], 1823 2047 1824 - "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=="], 2048 + "path-scurry/lru-cache": ["lru-cache@11.2.2", "", {}, "sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg=="], 1825 2049 1826 - "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=="], 1827 - 1828 - "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=="], 1829 2051 1830 2052 "readdirp/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], 1831 2053 1832 2054 "recast/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 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=="], 1833 2059 1834 2060 "solid-js/seroval": ["seroval@1.3.2", "", {}, "sha512-RbcPH1n5cfwKrru7v7+zrZvjLurgHhGyso3HTyGtRivGWgYjbOmGuivCQaORNELjNONoK35nj28EoWul9sb1zQ=="], 1835 2061 ··· 1837 2063 1838 2064 "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], 1839 2065 1840 - "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=="], 1841 2067 1842 - "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=="], 1843 2069 1844 - "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=="], 1845 2071 1846 - "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=="], 1847 2073 1848 2074 "wrap-ansi/ansi-styles": ["ansi-styles@6.2.3", "", {}, "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg=="], 1849 2075 1850 - "@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=="], 1851 - 1852 - "@atproto/common/pino/pino-std-serializers": ["pino-std-serializers@6.2.2", "", {}, "sha512-cHjPPsE+vhj/tnhCy/wiMh3M3z3h/j15zHQX+S9GkTBgqJuTuJzYJ4gUyACLhDaJ7kk9ba9iRDmbH2tJU03OiA=="], 1853 - 1854 - "@atproto/common/pino/process-warning": ["process-warning@3.0.0", "", {}, "sha512-mqn0kFRl0EoqhnL0GQ0veqFHyIN1yig9RHh/InzORTUiZHFRAur+aMtRkELNwGs9aNwKS6tg/An4NYBPGwvtzQ=="], 1855 - 1856 - "@atproto/common/pino/sonic-boom": ["sonic-boom@3.8.1", "", { "dependencies": { "atomic-sleep": "^1.0.0" } }, "sha512-y4Z8LCDBuum+PBP3lSV7RHrXscqksve/bi0as7mhwVnBW+/wUqKT/2Kb7um8yqcFy0duYbbPxzt89Zy2nOCaxg=="], 1857 - 1858 - "@atproto/common/pino/thread-stream": ["thread-stream@2.7.0", "", { "dependencies": { "real-require": "^0.2.0" } }, "sha512-qQiRWsU/wvNolI6tbbCKd9iKaTnCXsTwVxhhKM6nctPdujTyztjlbUkUTUymidWcMnZ5pWR0ej4a0tjsW021vw=="], 1859 - 1860 - "@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=="], 1861 2077 1862 2078 "@cookware/database/@libsql/client/@libsql/core": ["@libsql/core@0.15.15", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-C88Z6UKl+OyuKKPwz224riz02ih/zHYI3Ho/LAcVOgjsunIRZoBw7fjRfaH9oPMmSNeQfhGklSG2il1URoOIsA=="], 1863 2079 1864 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=="], 1865 2083 1866 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=="], 1867 2085 ··· 1913 2131 1914 2132 "@inquirer/core/wrap-ansi/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], 1915 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 + 1916 2136 "@opentelemetry/instrumentation-http/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.57.1", "", { "dependencies": { "@opentelemetry/api": "^1.3.0" } }, "sha512-I4PHczeujhQAQv6ZBzqHYEUiggZL4IdSMixtVD3EYqbdrjujE7kRfI5QohjlPoJm8BvenoW5YaTMWRrbpot6tg=="], 1917 2137 1918 2138 "@prisma/instrumentation/@opentelemetry/instrumentation/@opentelemetry/api-logs": ["@opentelemetry/api-logs@0.53.0", "", { "dependencies": { "@opentelemetry/api": "^1.0.0" } }, "sha512-8HArjKx+RaAI8uEIgcORbZIPklyh1YLjPSBus8hjRmvLi6DeFzgOcdZ7KwPabKj8mXF8dX0hyfAyGfycz0DbFw=="], 1919 2139 1920 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=="], 1921 - 1922 - "@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=="], 1923 2141 1924 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=="], 1925 2143 ··· 1937 2155 1938 2156 "@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.2", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ=="], 1939 2157 1940 - "csso/css-tree/mdn-data": ["mdn-data@2.0.28", "", {}, "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g=="], 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=="], 1941 2159 1942 - "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], 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=="], 1943 2161 1944 - "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 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=="], 1945 2163 1946 - "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], 2164 + "app/@atproto/oauth-client-node/@atproto-labs/simple-store": ["@atproto-labs/simple-store@0.3.0", "", {}, "sha512-nOb6ONKBRJHRlukW1sVawUkBqReLlLx6hT35VS3imaNPwiXDxLnTK7lxw3Lrl9k5yugSBDQAkZAq3MPTEFSUBQ=="], 1947 2165 1948 - "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], 2166 + "app/@atproto/oauth-client-node/@atproto/did": ["@atproto/did@0.2.3", "", { "dependencies": { "zod": "^3.23.8" } }, "sha512-VI8JJkSizvM2cHYJa37WlbzeCm5tWpojyc1/Zy8q8OOjyoy6X4S4BEfoP941oJcpxpMTObamibQIXQDo7tnIjg=="], 1949 2167 1950 - "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], 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=="], 1951 2169 1952 - "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], 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=="], 1953 2171 1954 - "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], 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=="], 1955 2173 1956 - "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], 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=="], 1957 2175 1958 - "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], 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=="], 1959 2177 1960 - "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], 2178 + "eslint/ajv/json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="], 1961 2179 1962 - "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], 2180 + "next/postcss/nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], 1963 2181 1964 - "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], 2182 + "tsx/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.27.1", "", { "os": "aix", "cpu": "ppc64" }, "sha512-HHB50pdsBX6k47S4u5g/CaLjqS3qwaOVE5ILsq64jyzgMhLuCuZ8rGzM9yhsAjfjkbgUPMzZEPa7DAp7yz6vuA=="], 1965 2183 1966 - "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], 2184 + "tsx/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.27.1", "", { "os": "android", "cpu": "arm" }, "sha512-kFqa6/UcaTbGm/NncN9kzVOODjhZW8e+FRdSeypWe6j33gzclHtwlANs26JrupOntlcWmB0u8+8HZo8s7thHvg=="], 1967 2185 1968 - "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], 2186 + "tsx/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.27.1", "", { "os": "android", "cpu": "arm64" }, "sha512-45fuKmAJpxnQWixOGCrS+ro4Uvb4Re9+UTieUY2f8AEc+t7d4AaZ6eUJ3Hva7dtrxAAWHtlEFsXFMAgNnGU9uQ=="], 1969 2187 1970 - "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], 2188 + "tsx/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.27.1", "", { "os": "android", "cpu": "x64" }, "sha512-LBEpOz0BsgMEeHgenf5aqmn/lLNTFXVfoWMUox8CtWWYK9X4jmQzWjoGoNb8lmAYml/tQ/Ysvm8q7szu7BoxRQ=="], 1971 2189 1972 - "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], 2190 + "tsx/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.27.1", "", { "os": "darwin", "cpu": "arm64" }, "sha512-veg7fL8eMSCVKL7IW4pxb54QERtedFDfY/ASrumK/SbFsXnRazxY4YykN/THYqFnFwJ0aVjiUrVG2PwcdAEqQQ=="], 1973 2191 1974 - "tsx/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], 2192 + "tsx/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.27.1", "", { "os": "darwin", "cpu": "x64" }, "sha512-+3ELd+nTzhfWb07Vol7EZ+5PTbJ/u74nC6iv4/lwIU99Ip5uuY6QoIf0Hn4m2HoV0qcnRivN3KSqc+FyCHjoVQ=="], 1975 2193 1976 - "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], 2194 + "tsx/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.27.1", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-/8Rfgns4XD9XOSXlzUDepG8PX+AVWHliYlUkFI3K3GB6tqbdjYqdhcb4BKRd7C0BhZSoaCxhv8kTcBrcZWP+xg=="], 1977 2195 1978 - "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], 2196 + "tsx/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.27.1", "", { "os": "freebsd", "cpu": "x64" }, "sha512-GITpD8dK9C+r+5yRT/UKVT36h/DQLOHdwGVwwoHidlnA168oD3uxA878XloXebK4Ul3gDBBIvEdL7go9gCUFzQ=="], 1979 2197 1980 - "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], 2198 + "tsx/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.27.1", "", { "os": "linux", "cpu": "arm" }, "sha512-ieMID0JRZY/ZeCrsFQ3Y3NlHNCqIhTprJfDgSB3/lv5jJZ8FX3hqPyXWhe+gvS5ARMBJ242PM+VNz/ctNj//eA=="], 1981 2199 1982 - "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], 2200 + "tsx/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.27.1", "", { "os": "linux", "cpu": "arm64" }, "sha512-W9//kCrh/6in9rWIBdKaMtuTTzNj6jSeG/haWBADqLLa9P8O5YSRDzgD5y9QBok4AYlzS6ARHifAb75V6G670Q=="], 1983 2201 1984 - "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], 2202 + "tsx/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.27.1", "", { "os": "linux", "cpu": "ia32" }, "sha512-VIUV4z8GD8rtSVMfAj1aXFahsi/+tcoXXNYmXgzISL+KB381vbSTNdeZHHHIYqFyXcoEhu9n5cT+05tRv13rlw=="], 1985 2203 1986 - "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 2204 + "tsx/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-l4rfiiJRN7sTNI//ff65zJ9z8U+k6zcCg0LALU5iEWzY+a1mVZ8iWC1k5EsNKThZ7XCQ6YWtsZ8EWYm7r1UEsg=="], 1987 2205 1988 - "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 2206 + "tsx/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-U0bEuAOLvO/DWFdygTHWY8C067FXz+UbzKgxYhXC0fDieFa0kDIra1FAhsAARRJbvEyso8aAqvPdNxzWuStBnA=="], 1989 2207 1990 - "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.12", "", { "os": "aix", "cpu": "ppc64" }, "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA=="], 2208 + "tsx/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.27.1", "", { "os": "linux", "cpu": "ppc64" }, "sha512-NzdQ/Xwu6vPSf/GkdmRNsOfIeSGnh7muundsWItmBsVpMoNPVpM61qNzAVY3pZ1glzzAxLR40UyYM23eaDDbYQ=="], 1991 2209 1992 - "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.12", "", { "os": "android", "cpu": "arm" }, "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg=="], 2210 + "tsx/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.27.1", "", { "os": "linux", "cpu": "none" }, "sha512-7zlw8p3IApcsN7mFw0O1Z1PyEk6PlKMu18roImfl3iQHTnr/yAfYv6s4hXPidbDoI2Q0pW+5xeoM4eTCC0UdrQ=="], 1993 2211 1994 - "vite/esbuild/@esbuild/android-arm64": ["@esbuild/android-arm64@0.25.12", "", { "os": "android", "cpu": "arm64" }, "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg=="], 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=="], 1995 2213 1996 - "vite/esbuild/@esbuild/android-x64": ["@esbuild/android-x64@0.25.12", "", { "os": "android", "cpu": "x64" }, "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg=="], 2214 + "tsx/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.27.1", "", { "os": "linux", "cpu": "x64" }, "sha512-z3H/HYI9MM0HTv3hQZ81f+AKb+yEoCRlUby1F80vbQ5XdzEMyY/9iNlAmhqiBKw4MJXwfgsh7ERGEOhrM1niMA=="], 1997 2215 1998 - "vite/esbuild/@esbuild/darwin-arm64": ["@esbuild/darwin-arm64@0.25.12", "", { "os": "darwin", "cpu": "arm64" }, "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg=="], 2216 + "tsx/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.27.1", "", { "os": "none", "cpu": "x64" }, "sha512-1YQ8ybGi2yIXswu6eNzJsrYIGFpnlzEWRl6iR5gMgmsrR0FcNoV1m9k9sc3PuP5rUBLshOZylc9nqSgymI+TYg=="], 1999 2217 2000 - "vite/esbuild/@esbuild/darwin-x64": ["@esbuild/darwin-x64@0.25.12", "", { "os": "darwin", "cpu": "x64" }, "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA=="], 2218 + "tsx/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.27.1", "", { "os": "openbsd", "cpu": "x64" }, "sha512-Q73ENzIdPF5jap4wqLtsfh8YbYSZ8Q0wnxplOlZUOyZy7B4ZKW8DXGWgTCZmF8VWD7Tciwv5F4NsRf6vYlZtqg=="], 2001 2219 2002 - "vite/esbuild/@esbuild/freebsd-arm64": ["@esbuild/freebsd-arm64@0.25.12", "", { "os": "freebsd", "cpu": "arm64" }, "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg=="], 2220 + "tsx/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.27.1", "", { "os": "sunos", "cpu": "x64" }, "sha512-IPUW+y4VIjuDVn+OMzHc5FV4GubIwPnsz6ubkvN8cuhEqH81NovB53IUlrlBkPMEPxvNnf79MGBoz8rZ2iW8HA=="], 2003 2221 2004 - "vite/esbuild/@esbuild/freebsd-x64": ["@esbuild/freebsd-x64@0.25.12", "", { "os": "freebsd", "cpu": "x64" }, "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ=="], 2222 + "tsx/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.27.1", "", { "os": "win32", "cpu": "arm64" }, "sha512-RIVRWiljWA6CdVu8zkWcRmGP7iRRIIwvhDKem8UMBjPql2TXM5PkDVvvrzMtj1V+WFPB4K7zkIGM7VzRtFkjdg=="], 2005 2223 2006 - "vite/esbuild/@esbuild/linux-arm": ["@esbuild/linux-arm@0.25.12", "", { "os": "linux", "cpu": "arm" }, "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw=="], 2224 + "tsx/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.27.1", "", { "os": "win32", "cpu": "ia32" }, "sha512-2BR5M8CPbptC1AK5JbJT1fWrHLvejwZidKx3UMSF0ecHMa+smhi16drIrCEggkgviBwLYd5nwrFLSl5Kho96RQ=="], 2007 2225 2008 - "vite/esbuild/@esbuild/linux-arm64": ["@esbuild/linux-arm64@0.25.12", "", { "os": "linux", "cpu": "arm64" }, "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ=="], 2226 + "tsx/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.27.1", "", { "os": "win32", "cpu": "x64" }, "sha512-d5X6RMYv6taIymSk8JBP+nxv8DQAMY6A51GPgusqLdK9wBz5wWIXy1KjTck6HnjE9hqJzJRdk+1p/t5soSbCtw=="], 2009 2227 2010 - "vite/esbuild/@esbuild/linux-ia32": ["@esbuild/linux-ia32@0.25.12", "", { "os": "linux", "cpu": "ia32" }, "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA=="], 2228 + "web/@types/bun/bun-types": ["bun-types@1.3.4", "", { "dependencies": { "@types/node": "*" } }, "sha512-5ua817+BZPZOlNaRgGBpZJOSAQ9RQ17pkwPD0yR7CfJg+r8DgIILByFifDTa+IPDDxzf5VNhtNlcKqFzDgJvlQ=="], 2011 2229 2012 - "vite/esbuild/@esbuild/linux-loong64": ["@esbuild/linux-loong64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng=="], 2230 + "@cookware/database/@libsql/client/libsql/@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.22", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA=="], 2013 2231 2014 - "vite/esbuild/@esbuild/linux-mips64el": ["@esbuild/linux-mips64el@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw=="], 2232 + "@cookware/database/@libsql/client/libsql/@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.22", "", { "os": "darwin", "cpu": "x64" }, "sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA=="], 2015 2233 2016 - "vite/esbuild/@esbuild/linux-ppc64": ["@esbuild/linux-ppc64@0.25.12", "", { "os": "linux", "cpu": "ppc64" }, "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA=="], 2234 + "@cookware/database/@libsql/client/libsql/@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-KSdnOMy88c9mpOFKUEzPskSaF3VLflfSUCBwas/pn1/sV3pEhtMF6H8VUCd2rsedwoukeeCSEONqX7LLnQwRMA=="], 2017 2235 2018 - "vite/esbuild/@esbuild/linux-riscv64": ["@esbuild/linux-riscv64@0.25.12", "", { "os": "linux", "cpu": "none" }, "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w=="], 2236 + "@cookware/database/@libsql/client/libsql/@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-mCHSMAsDTLK5YH//lcV3eFEgiR23Ym0U9oEvgZA0667gqRZg/2px+7LshDvErEKv2XZ8ixzw3p1IrBzLQHGSsw=="], 2019 2237 2020 - "vite/esbuild/@esbuild/linux-s390x": ["@esbuild/linux-s390x@0.25.12", "", { "os": "linux", "cpu": "s390x" }, "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg=="], 2238 + "@cookware/database/@libsql/client/libsql/@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-kNBHaIkSg78Y4BqAdgjcR2mBilZXs4HYkAmi58J+4GRwDQZh5fIUWbnQvB9f95DkWUIGVeenqLRFY2pcTmlsew=="], 2021 2239 2022 - "vite/esbuild/@esbuild/linux-x64": ["@esbuild/linux-x64@0.25.12", "", { "os": "linux", "cpu": "x64" }, "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw=="], 2240 + "@cookware/database/@libsql/client/libsql/@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-UZ4Xdxm4pu3pQXjvfJiyCzZop/9j/eA2JjmhMaAhe3EVLH2g11Fy4fwyUp9sT1QJYR1kpc2JLuybPM0kuXv/Tg=="], 2023 2241 2024 - "vite/esbuild/@esbuild/netbsd-x64": ["@esbuild/netbsd-x64@0.25.12", "", { "os": "none", "cpu": "x64" }, "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ=="], 2242 + "@cookware/database/@libsql/client/libsql/@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.22", "", { "os": "win32", "cpu": "x64" }, "sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA=="], 2025 2243 2026 - "vite/esbuild/@esbuild/openbsd-x64": ["@esbuild/openbsd-x64@0.25.12", "", { "os": "openbsd", "cpu": "x64" }, "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw=="], 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=="], 2027 2245 2028 - "vite/esbuild/@esbuild/sunos-x64": ["@esbuild/sunos-x64@0.25.12", "", { "os": "sunos", "cpu": "x64" }, "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w=="], 2246 + "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], 2029 2247 2030 - "vite/esbuild/@esbuild/win32-arm64": ["@esbuild/win32-arm64@0.25.12", "", { "os": "win32", "cpu": "arm64" }, "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg=="], 2248 + "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], 2249 + 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=="], 2251 + 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=="], 2031 2253 2032 - "vite/esbuild/@esbuild/win32-ia32": ["@esbuild/win32-ia32@0.25.12", "", { "os": "win32", "cpu": "ia32" }, "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ=="], 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=="], 2033 2255 2034 - "vite/esbuild/@esbuild/win32-x64": ["@esbuild/win32-x64@0.25.12", "", { "os": "win32", "cpu": "x64" }, "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA=="], 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=="], 2035 2257 2036 - "@cookware/database/@libsql/client/libsql/@libsql/darwin-arm64": ["@libsql/darwin-arm64@0.5.22", "", { "os": "darwin", "cpu": "arm64" }, "sha512-4B8ZlX3nIDPndfct7GNe0nI3Yw6ibocEicWdC4fvQbSs/jdq/RC2oCsoJxJ4NzXkvktX70C1J4FcmmoBy069UA=="], 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=="], 2259 + 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=="], 2261 + 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=="], 2263 + 2264 + "web/@types/bun/bun-types/@types/node": ["@types/node@24.10.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-WOhQTZ4G8xZ1tjJTvKOpyEVSGgOTvJAfDK3FNFgELyaTpzhdgHVHeqW8V+UJvzF5BT+/B54T/1S2K6gd9c7bbA=="], 2265 + 2266 + "@cookware/tsconfig/@types/bun/bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], 2037 2267 2038 - "@cookware/database/@libsql/client/libsql/@libsql/darwin-x64": ["@libsql/darwin-x64@0.5.22", "", { "os": "darwin", "cpu": "x64" }, "sha512-ny2HYWt6lFSIdNFzUFIJ04uiW6finXfMNJ7wypkAD8Pqdm6nAByO+Fdqu8t7sD0sqJGeUCiOg480icjyQ2/8VA=="], 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=="], 2039 2269 2040 - "@cookware/database/@libsql/client/libsql/@libsql/linux-arm64-gnu": ["@libsql/linux-arm64-gnu@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-KSdnOMy88c9mpOFKUEzPskSaF3VLflfSUCBwas/pn1/sV3pEhtMF6H8VUCd2rsedwoukeeCSEONqX7LLnQwRMA=="], 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=="], 2041 2271 2042 - "@cookware/database/@libsql/client/libsql/@libsql/linux-arm64-musl": ["@libsql/linux-arm64-musl@0.5.22", "", { "os": "linux", "cpu": "arm64" }, "sha512-mCHSMAsDTLK5YH//lcV3eFEgiR23Ym0U9oEvgZA0667gqRZg/2px+7LshDvErEKv2XZ8ixzw3p1IrBzLQHGSsw=="], 2272 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto-labs/simple-store-memory/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], 2043 2273 2044 - "@cookware/database/@libsql/client/libsql/@libsql/linux-x64-gnu": ["@libsql/linux-x64-gnu@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-kNBHaIkSg78Y4BqAdgjcR2mBilZXs4HYkAmi58J+4GRwDQZh5fIUWbnQvB9f95DkWUIGVeenqLRFY2pcTmlsew=="], 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=="], 2045 2275 2046 - "@cookware/database/@libsql/client/libsql/@libsql/linux-x64-musl": ["@libsql/linux-x64-musl@0.5.22", "", { "os": "linux", "cpu": "x64" }, "sha512-UZ4Xdxm4pu3pQXjvfJiyCzZop/9j/eA2JjmhMaAhe3EVLH2g11Fy4fwyUp9sT1QJYR1kpc2JLuybPM0kuXv/Tg=="], 2276 + "web/@types/bun/bun-types/@types/node/undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], 2047 2277 2048 - "@cookware/database/@libsql/client/libsql/@libsql/win32-x64-msvc": ["@libsql/win32-x64-msvc@0.5.22", "", { "os": "win32", "cpu": "x64" }, "sha512-Fj0j8RnBpo43tVZUVoNK6BV/9AtDUM5S7DF3LB4qTYg1LMSZqi3yeCneUTLJD6XomQJlZzbI4mst89yspVSAnA=="], 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=="], 2049 2279 2050 - "@inquirer/core/wrap-ansi/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], 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=="], 2051 2281 2052 - "@inquirer/core/wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], 2282 + "app/@atproto/oauth-client-node/@atproto/oauth-client/@atproto/xrpc/@atproto/lexicon/@atproto/syntax": ["@atproto/syntax@0.4.2", "", {}, "sha512-X9XSRPinBy/0VQ677j8VXlBsYSsUXaiqxWVpGGxJYsAhugdQRb0jqaVKJFtm6RskeNkV6y9xclSUi9UYG/COrA=="], 2053 2283 } 2054 2284 }
+2 -2
libs/database/lib/schema.ts
··· 1 1 import { customType, index, integer, primaryKey, pgTable, text, jsonb, varchar } from "drizzle-orm/pg-core"; 2 2 import { BlueRecipesFeedRecipe } from "@cookware/lexicons"; 3 - import { Cid, isCid, ResourceUri, type AtprotoDid } from "@atcute/lexicons/syntax"; 4 - import { Blob, LegacyBlob } from "@atcute/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
+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 }