diff --git a/app/(home)/layout.tsx b/app/(home)/layout.tsx index aa4d83a48bc..a69569f9c6e 100644 --- a/app/(home)/layout.tsx +++ b/app/(home)/layout.tsx @@ -4,8 +4,10 @@ import type { ReactNode } from "react"; import { Footer } from "@/components/navigation/footer"; import { baseOptions } from "@/app/layout.config"; import { SessionProvider, useSession } from "next-auth/react"; -import { useEffect, Suspense } from "react"; +import { useEffect, Suspense, useState } from "react"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; +import Modal from "@/components/ui/Modal"; +import { Button } from "@/components/ui/button"; import { LayoutWrapper } from "@/app/layout-wrapper.client"; import { NavbarDropdownInjector } from "@/components/navigation/navbar-dropdown-injector"; @@ -33,6 +35,7 @@ function RedirectIfNewUser() { const pathname = usePathname(); const router = useRouter(); const searchParams = useSearchParams(); + const [showModal, setShowModal] = useState(false); useEffect(() => { if ( @@ -45,9 +48,38 @@ function RedirectIfNewUser() { if (typeof window !== "undefined") { localStorage.setItem("redirectAfterProfile", originalUrl); } + + // Show confirmation modal and redirect immediately + setShowModal(true); router.replace("/profile"); } }, [session, status, pathname, router, searchParams]); - return null; + const handleContinue = () => { + setShowModal(false); + }; + + return ( + <> + {showModal && ( + + + + } + /> + )} + + ); } diff --git a/app/(home)/showcase/[id]/page.tsx b/app/(home)/showcase/[id]/page.tsx index 79f9c1fc371..3d1c46e6b0e 100644 --- a/app/(home)/showcase/[id]/page.tsx +++ b/app/(home)/showcase/[id]/page.tsx @@ -2,6 +2,7 @@ import React from "react"; import ProjectOverview from "../../../../components/showcase/ProjectOverview"; import { getProject } from "@/server/services/projects"; import { Project } from "@/types/showcase"; +import { getProjectBadges, getUserBadgesByProjectId } from "@/server/services/project-badge"; export default async function ProjectPage({ params, }: { @@ -9,9 +10,11 @@ export default async function ProjectPage({ }) { const { id } = await params; const project = await getProject(id); + const badges = await getUserBadgesByProjectId(id); + return (
- +
); } diff --git a/app/api/badge/assign/route.ts b/app/api/badge/assign/route.ts new file mode 100644 index 00000000000..f9b97a53791 --- /dev/null +++ b/app/api/badge/assign/route.ts @@ -0,0 +1,48 @@ +import { withAuth } from "@/lib/protectedRoute"; +import { badgeAssignmentService } from "@/server/services/badgeAssignmentService"; +import { getAuthSession } from "@/lib/auth/authSession"; + +import { NextRequest, NextResponse } from "next/server"; + +export const POST = withAuth(async (req: NextRequest) => { + try { + const body = await req.json(); + const session = await getAuthSession(); + + // Check authorization based on badge type + const userRole = session?.user.role || "user"; + const customAttributes = session?.user.custom_attributes??[]; + const hasPermission = badgeAssignmentService.hasRequiredRole(body, customAttributes); + + if (!hasPermission) { + const requiredRole = badgeAssignmentService.getRequiredRoleForAssignment(body); + return NextResponse.json( + { + error: { + message: `Insufficient permissions. Required role: ${requiredRole || 'none'}, User role: ${userRole}` + } + }, + { status: 403 } + ); + } + + // Use the user's name as awardedBy + const badge = await badgeAssignmentService.assignBadge(body, session?.user.name || undefined); + + return NextResponse.json({ result: badge }, { status: 200 }); + } catch (error: any) { + console.error('Error POST /api/badge/assign:', error.message); + const wrappedError = error as Error; + return NextResponse.json( + { + error: { + message: wrappedError.message, + stack: wrappedError.stack, + cause: wrappedError.cause, + name: wrappedError.name, + }, + }, + { status: wrappedError.cause == "ValidationError" ? 400 : 500 } + ); + } +}); diff --git a/app/api/badge/get-all/route.ts b/app/api/badge/get-all/route.ts new file mode 100644 index 00000000000..142935a6c09 --- /dev/null +++ b/app/api/badge/get-all/route.ts @@ -0,0 +1,17 @@ +import { withAuth } from "@/lib/protectedRoute"; +import { getAllBadges, getBadgeByCourseId } from "@/server/services/badge"; + +import { NextResponse } from "next/server"; + +export const GET = withAuth(async () => { + try { + const badges = await getAllBadges(); + return NextResponse.json(badges, { status: 200 }); + } catch (error) { + console.error("Error getting badge:", error); + return NextResponse.json( + { error: "Internal server error" }, + { status: 500 } + ); + } +}); diff --git a/app/api/badge/project-badge/route.ts b/app/api/badge/project-badge/route.ts new file mode 100644 index 00000000000..aac43077d63 --- /dev/null +++ b/app/api/badge/project-badge/route.ts @@ -0,0 +1,27 @@ +import { withAuth } from "@/lib/protectedRoute"; + +import { getProjectBadges } from "@/server/services/project-badge"; + +import { NextResponse } from "next/server"; + +export const GET = withAuth(async (request) => { + const { searchParams } = new URL(request.url); + const project_id = searchParams.get("project_id"); + if (!project_id) { + return NextResponse.json( + { error: "project_id parameter is required" }, + { status: 400 } + ); + } + + try { + const badge = await getProjectBadges(project_id); + return NextResponse.json(badge, { status: 200 }); + } catch (error) { + console.error("Error getting badge:", error); + return NextResponse.json( + { error: "Internal server error" }, + { status: 500 } + ); + } +}); diff --git a/app/api/badge/route.ts b/app/api/badge/route.ts index a303845ebff..0e645ae3434 100644 --- a/app/api/badge/route.ts +++ b/app/api/badge/route.ts @@ -1,5 +1,6 @@ import { withAuth } from "@/lib/protectedRoute"; -import { getBadgeByCourseId } from "@/server/services/rewardBoard"; +import { getBadgeByCourseId } from "@/server/services/badge"; + import { NextResponse } from "next/server"; export const GET = withAuth(async (request) => { diff --git a/app/api/badge/validate/route.ts b/app/api/badge/validate/route.ts new file mode 100644 index 00000000000..96640fc070e --- /dev/null +++ b/app/api/badge/validate/route.ts @@ -0,0 +1,33 @@ +import { withAuth } from "@/lib/protectedRoute"; +import { getBadgeByCourseId } from "@/server/services/badge"; + +import { NextResponse } from "next/server"; + +export const GET = withAuth(async (request) => { + const { searchParams } = new URL(request.url); + const course_id = searchParams.get("course_id"); + const user_id = searchParams.get("user_id"); + if (!course_id) { + return NextResponse.json( + { error: "course_id parameter is required" }, + { status: 400 } + ); + } + if (!user_id) { + return NextResponse.json( + { error: "user_id parameter is required" }, + { status: 400 } + ); + } + + try { + const badge = await getBadgeByCourseId(course_id); + return NextResponse.json(badge, { status: 200 }); + } catch (error) { + console.error("Error getting badge:", error); + return NextResponse.json( + { error: "Internal server error" }, + { status: 500 } + ); + } +}); diff --git a/app/api/project/set-winner/route.ts b/app/api/project/set-winner/route.ts new file mode 100644 index 00000000000..af9f53d3160 --- /dev/null +++ b/app/api/project/set-winner/route.ts @@ -0,0 +1,34 @@ +import { getAuthSession } from "@/lib/auth/authSession"; +import { withAuthRole } from "@/lib/protectedRoute"; +import { SetWinner } from "@/server/services/set-project-winner"; +import { NextRequest, NextResponse } from "next/server"; + +export const PUT = withAuthRole("badge_admin", async (req: NextRequest) => { + const body = await req.json(); + const session = await getAuthSession(); + const name = session?.user.name || "user"; + + try { + if (!body.project_id) { + return NextResponse.json( + { error: "project_id parameter is required" }, + { status: 400 } + ); + } + if (!body.isWinner) { + return NextResponse.json( + { error: "IsWinner parameter is required" }, + { status: 400 } + ); + } + const badge = await SetWinner(body.project_id, body.isWinner, name); + + return NextResponse.json(badge, { status: 200 }); + } catch (error) { + console.error("Error checking user by email:", error); + return NextResponse.json( + { error: "Internal server error" }, + { status: 500 } + ); + } +}); diff --git a/app/api/projects/export/route.ts b/app/api/projects/export/route.ts new file mode 100644 index 00000000000..8b2791be2bc --- /dev/null +++ b/app/api/projects/export/route.ts @@ -0,0 +1,33 @@ +import { withAuthRole } from "@/lib/protectedRoute"; +import { exportShowcase } from "@/server/services/exportShowcase"; +import { NextRequest, NextResponse } from "next/server"; + +export const POST = withAuthRole('hackathonCreator', async (req: NextRequest) => { + try { + const body = await req.json(); + const buffer = await exportShowcase(body); + if (!buffer) { + return NextResponse.json( + { message: 'No projects found' }, + { status: 404 } + ); + } + return new NextResponse(buffer, { + headers: { 'Content-Type': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }, + }); + } catch (error: any) { + console.error('Error POST /api/projects/export:', error.message); + const wrappedError = error as Error; + return NextResponse.json( + { + error: { + message: wrappedError.message, + stack: wrappedError.stack, + cause: wrappedError.cause, + name: wrappedError.name + } + }, + { status: wrappedError.cause == 'ValidationError' ? 400 : 500 } + ); + } +}); \ No newline at end of file diff --git a/components/hackathons/project-submission/General.tsx b/components/hackathons/project-submission/General.tsx deleted file mode 100644 index dc1eaf3b8ca..00000000000 --- a/components/hackathons/project-submission/General.tsx +++ /dev/null @@ -1,47 +0,0 @@ -// import { useState, useEffect } from 'react'; -// import { ProjectMemberWarningDialog } from './components/ProjectMemberWarningDialog'; -// import { getInvitation } from '@/lib/actions/invitation'; -// import { getHackathonProject } from '@/lib/actions/hackathon'; - -// interface GeneralProps { -// searchParams: { -// invitationId?: string; -// }; -// } - -// export default function General({ searchParams }: GeneralProps) { -// const { invitationId } = searchParams; -// const [showWarningDialog, setShowWarningDialog] = useState(false); -// const [currentProjectName, setCurrentProjectName] = useState(''); - -// useEffect(() => { -// const checkInvitation = async () => { -// if (invitationId) { -// try { -// const invitation = await getInvitation(invitationId); -// if (invitation) { -// const currentProject = await getHackathonProject(invitation.projectId); -// if (currentProject) { -// setCurrentProjectName(currentProject.name); -// setShowWarningDialog(true); -// } -// } -// } catch (error) { -// console.error('Error checking invitation:', error); -// } -// } -// }; - -// checkInvitation(); -// }, [invitationId]); - -// return ( -// <> -// -// -// ); -// } \ No newline at end of file diff --git a/components/hackathons/project-submission/SubmissionWrapperSecure.tsx b/components/hackathons/project-submission/SubmissionWrapperSecure.tsx index 5a26e72d9a7..393596624cf 100644 --- a/components/hackathons/project-submission/SubmissionWrapperSecure.tsx +++ b/components/hackathons/project-submission/SubmissionWrapperSecure.tsx @@ -1,17 +1,30 @@ -'use client'; +"use client"; -import React from 'react'; -import { ProjectSubmissionProvider } from './context/ProjectSubmissionContext'; -import GeneralSecureComponent from './components/GeneralSecure'; +import React, { useState } from "react"; +import { ProjectSubmissionProvider } from "./context/ProjectSubmissionContext"; +import GeneralSecureComponent from "./components/GeneralSecure"; +import { UserNotRegistered } from "./components/UserNotRegistered"; export function SubmissionWrapperSecure({ searchParams, }: { searchParams: { [key: string]: string | string[] | undefined }; }) { + const [showComponent, setShowComponent] = useState(false); + + const handleShowComponent = (show: boolean) => { + setShowComponent(show); + }; + return ( - + {!showComponent && ( + + )} + {showComponent && } ); -} \ No newline at end of file +} diff --git a/components/hackathons/project-submission/components/GeneralSecure.tsx b/components/hackathons/project-submission/components/GeneralSecure.tsx index 711d38e4b7a..1c154a9ed14 100644 --- a/components/hackathons/project-submission/components/GeneralSecure.tsx +++ b/components/hackathons/project-submission/components/GeneralSecure.tsx @@ -21,6 +21,7 @@ import { Alert, AlertDescription } from "@/components/ui/alert"; import { JoinTeamDialog } from "./JoinTeamDialog"; import { ProjectMemberWarningDialog } from "./ProjectMemberWarningDialog"; import InvalidInvitationComponent from "./InvalidInvitationDialog"; +import Modal from "@/components/ui/Modal"; export default function GeneralSecureComponent({ searchParams, @@ -335,7 +336,6 @@ export default function GeneralSecureComponent({ dispatch({ type: "SET_OPEN_INVALID_INVITATION", payload: open }) } /> - {error && (
diff --git a/components/hackathons/project-submission/components/Members.tsx b/components/hackathons/project-submission/components/Members.tsx index cc9addffd86..9a2edf98b23 100644 --- a/components/hackathons/project-submission/components/Members.tsx +++ b/components/hackathons/project-submission/components/Members.tsx @@ -312,7 +312,7 @@ export default function MembersComponent({ spellCheck="false" onChange={(e) => setNewEmail(e.target.value)} onKeyDown={async (e) => { - if (e.key === "Enter" || e.key === " ") { + if (e.key === "Enter" || e.key === " " || e.key === "Tab") { e.preventDefault(); await handleAddEmail(); } diff --git a/components/hackathons/project-submission/components/UserNotRegistered.tsx b/components/hackathons/project-submission/components/UserNotRegistered.tsx new file mode 100644 index 00000000000..3ea2b7ffe46 --- /dev/null +++ b/components/hackathons/project-submission/components/UserNotRegistered.tsx @@ -0,0 +1,62 @@ +import Modal from "@/components/ui/Modal"; +import { useSession } from "next-auth/react"; +import { useRouter } from "next/navigation"; +import React, { useEffect, useState } from "react"; +import axios from "axios"; +import { Button } from "@/components/ui/button"; +import { set } from "date-fns"; + +interface UserNotRegisteredProps { + hackathonId: string; + onToggle: (open: boolean) => void; +} + +export const UserNotRegistered = ({ + hackathonId, + onToggle, +}: UserNotRegisteredProps) => { + const [isOpen, setIsOpen] = useState(false); + const router = useRouter(); + const { data: session } = useSession(); + const currentUser = session?.user; + + const lookForRegistration = async () => { + if (!hackathonId || !currentUser?.email) return; + const response = await axios.get( + `/api/register-form?hackathonId=${hackathonId}&email=${currentUser?.email}` + ); + const loadedData = response.data; + if (loadedData) { + onToggle(true); + return; + } + onToggle(false); + setIsOpen(true); + setTimeout(() => { + router.push( + `/hackathons/registration-form?hackathon=${hackathonId}&utm=invitation-link` + ); + }, 4000); + }; + + useEffect(() => { + lookForRegistration(); + }, [hackathonId, currentUser?.email]); + + return ( + + +
+ } + /> + ); +}; diff --git a/components/login/user-button/UserButton.tsx b/components/login/user-button/UserButton.tsx index 699fc788e44..137087d6a17 100644 --- a/components/login/user-button/UserButton.tsx +++ b/components/login/user-button/UserButton.tsx @@ -76,35 +76,35 @@ export function UserButton() { - - Profile - - {/* - Reward Board + + Profile - */} - setIsDialogOpen(true)} - className='cursor-pointer' - > - Sign Out - - - - ) : ( - - )} + + Achievements Board + + + setIsDialogOpen(true)} + className='cursor-pointer' + > + Sign Out + + + + ) : ( + + )} (null); + const badgeDefaultImage = "/wolfie/wolfie-hack.png"; + const [badgeImage, setBadgeImage] = useState(badgeDefaultImage); + + useEffect(() => { + if (image && image !== '') { + setBadgeImage(image); + } + }, [image]); + + useFrame((state, delta) => { + const g = groupRef.current; + + if (!g) return; + g.rotation.y += delta; + g.rotation.x = Math.sin(state.clock.elapsedTime * 0.25) * 0.25; + }); + + return ( + + + + + + ); +} diff --git a/components/profile/reward-board/component/back-face.tsx b/components/profile/reward-board/component/back-face.tsx new file mode 100644 index 00000000000..2bbc038f59a --- /dev/null +++ b/components/profile/reward-board/component/back-face.tsx @@ -0,0 +1,100 @@ +import * as React from "react"; +import { Text } from "@react-three/drei"; + +export function BackFace({ + name, + description, + DISC, + fontUrl, +}: { + name: string; + description?: string; + DISC: { radius: number; segments: number }; + fontUrl?: string; +}) { + const R = DISC.radius; + const plateRadius = R * 0.94; + + const titleFs = R * 0.22; + const descFs = R * 0.13; + const [titleHeight, setTitleHeight] = React.useState(0); + const TITLE_TOP_Y = plateRadius * 0.45; + const GAP_Y = R * 0.06; + + return ( + + + + + + + + + { + + const b = troika.textRenderInfo?.blockBounds; + if (b) { + const h = b[3] - b[1]; // maxY - minY + if (h > 0 && Math.abs(h - titleHeight) > 1e-3) setTitleHeight(h); + } + }} + font={fontUrl} + > + {name} + + + + {description && ( + + {description} + + )} + + ); +} diff --git a/components/profile/reward-board/component/circular-frame.tsx b/components/profile/reward-board/component/circular-frame.tsx new file mode 100644 index 00000000000..4b9b0ec06b4 --- /dev/null +++ b/components/profile/reward-board/component/circular-frame.tsx @@ -0,0 +1,28 @@ +export function CircularFrame({ color = "#999B9B" }: { color?: string }) { + const FRAME = { + majorRadius: 1.3, + tubeRadius: 0.09, + tubularSegments: 200, + radialSegments: 200, + }; + return ( + + + + + ); + } \ No newline at end of file diff --git a/components/profile/reward-board/component/image-disc.tsx b/components/profile/reward-board/component/image-disc.tsx new file mode 100644 index 00000000000..84917f89d8c --- /dev/null +++ b/components/profile/reward-board/component/image-disc.tsx @@ -0,0 +1,82 @@ +import React from "react"; +import { useTexture } from "@react-three/drei"; +import * as THREE from "three"; + +type DiscSpec = { radius: number; segments: number }; + +export function ImageDisc({ + url, + isUnlocked, + Disc, + showBackground = true, + backgroundColor = "#52525B", + backgroundOpacity = 1, + backgroundMetalness = 0, + backgroundRoughness = 1, +}: { + url: string; + isUnlocked: boolean; + Disc: DiscSpec; + showBackground?: boolean; + backgroundColor?: THREE.ColorRepresentation; + backgroundOpacity?: number; + backgroundMetalness?: number; + backgroundRoughness?: number +}) { + const texture = useTexture(url); + texture.colorSpace = THREE.SRGBColorSpace; + texture.anisotropy = 2; + + return ( + + {showBackground && ( + + + + + )} + + + + + + + + + + + + ); +} diff --git a/components/profile/reward-board/component/requirement-panel.tsx b/components/profile/reward-board/component/requirement-panel.tsx new file mode 100644 index 00000000000..024ea872335 --- /dev/null +++ b/components/profile/reward-board/component/requirement-panel.tsx @@ -0,0 +1,79 @@ +import { Card, CardContent, CardTitle } from "@/components/ui/card"; +import { Separator } from "@/components/ui/separator"; +import { Check } from "lucide-react"; + +type Requirement = { + id: string | number; + description: string; + points?: number; + unlocked?: boolean; +}; + +export function RequirementsPanel({ + requirements = [], + title +}: { + requirements?: Requirement[]; + title?: string; +}) { + // COMMENTED OUT: Points feature disabled + // const total = requirements.reduce( + // (acc, r) => acc + Number(r.points ?? 0), + // 0 + // ); + + return ( +
+ + + + + + {title} + + +
+

+ Requirements +

+
+ +
+
    + {requirements.map((requirement) => ( +
  • + + + + {(requirement.unlocked) && ( + + )} + + {requirement.description} + {/* COMMENTED OUT: Points feature disabled */} + {/* :{" "} + + {Number(requirement.points ?? 0)} points + */} + + +
  • + ))} +
+ + {/* COMMENTED OUT: Points feature disabled */} + {/* + + {total} points */} +
+
+
+
+ ); +} diff --git a/components/profile/reward-board/component/reward-board.tsx b/components/profile/reward-board/component/reward-board.tsx index 7c5ce8dca07..ea52b68840a 100644 --- a/components/profile/reward-board/component/reward-board.tsx +++ b/components/profile/reward-board/component/reward-board.tsx @@ -1,11 +1,12 @@ + import React from "react"; import { RewardCard } from "./reward-card"; -import rewardsData from "../rewardsData"; import { getAuthSession } from "@/lib/auth/authSession"; import { getRewardBoard } from "@/server/services/rewardBoard"; -import { getLucideIcon } from "./get-lucide-icon"; import { Separator } from "@/components/ui/separator"; -import { UserBadge } from "@/types/badge"; +import { Badge, UserBadge, BadgeAwardStatus } from "@/types/badge"; +import { getAllBadges } from "@/server/services/badge"; +import Link from "next/link"; export default async function RewardBoard() { const session = await getAuthSession(); @@ -13,19 +14,51 @@ export default async function RewardBoard() { if (!user_id) { return
Loading...
; } - const data:UserBadge[] = await getRewardBoard(user_id); - const rewards = data.filter((reward) => reward.metadata?.type == "hackathon").map((reward) => ( - - )); - const academyRewards = data.filter((reward) => reward.metadata?.type == "course").map((reward) => ( + const userBadges: UserBadge[] = await getRewardBoard(user_id); + const badges = await getAllBadges(); + + const academyBadges = badges.filter((badge) => badge.category == "academy")?.sort((a, b) => a.id.localeCompare(b.id)); + // COMMENTED OUT: Hackathon badges feature disabled + // const hackathonBadges: Badge[] = badges.filter((badge) => badge.category == "hackathon")?.sort((a, b) => a.id.localeCompare(b.id)); + // COMMENTED OUT: Points feature disabled + // const totalPoints = userBadges.reduce((acc, userBadge) => acc + userBadge.points, 0); + // const hackathonBadgesUnlocked = hackathonBadges.map((badge) => { + // const userBadge = userBadges.find((userBadge) => userBadge.badge_id == badge.id); + // return { + // ...badge, + // is_unlocked: !!userBadge, + // requirements: userBadge?.requirements || badge.requirements, + // }; + // }); + + const academyBadgesUnlocked = academyBadges.map((badge) => { + const userBadge = userBadges.find((userBadge) => userBadge.badge_id == badge.id); + // Only consider badge unlocked if status is approved (not pending) + const isUnlocked = userBadge?.status === BadgeAwardStatus.approved; + return { + ...badge, + is_unlocked: isUnlocked, + requirements: userBadge?.requirements || badge.requirements, + }; + + }).sort(element=>element.is_unlocked ? -1 : 1); + // COMMENTED OUT: Hackathon badges feature disabled + // const rewards = hackathonBadgesUnlocked.map((reward) => ( + // + // )); + + const academyRewards = academyBadgesUnlocked.map((reward) => ( + )); return ( -
-
+
+ {/* COMMENTED OUT: Hackathon badges feature disabled */} + {/*
-

- Hackathon Badges -

+
+

+ Hackathon Badges +

+ COMMENTED OUT: Points feature disabled +
+

+ Total Points: {totalPoints} +

+
+
{rewards.length === 0 ? (
- No rewards available yet. Keep contributing to earn rewards! + + Your contributions matter. Explore our dev events here
) : ( -
+
{rewards}
)} -
+
*/} -
+

Academy Badges

@@ -68,11 +114,11 @@ export default async function RewardBoard() { {academyRewards.length === 0 ? (
- Your contributions matter. Keep going to start earning rewards! + Your contributions matter. Explore our dev events here
) : ( -
+
{academyRewards}
)} diff --git a/components/profile/reward-board/component/reward-card.tsx b/components/profile/reward-board/component/reward-card.tsx index b31479d464f..63d22993845 100644 --- a/components/profile/reward-board/component/reward-card.tsx +++ b/components/profile/reward-board/component/reward-card.tsx @@ -1,61 +1,107 @@ -import React from "react"; -import Image from "next/image"; -import { BadgeCardProps } from "../types/badgeCard"; -import { getLucideIcon } from "./get-lucide-icon"; +"use client"; +import React, { useState } from "react"; +import { Canvas } from "@react-three/fiber"; +import * as THREE from "three"; +import type { BadgeCardProps } from "../types/badgeCard"; +import { RequirementsPanel } from "./requirement-panel"; +import { Dialog, DialogContent, DialogTitle } from "@/components/ui/dialog"; +import { VisuallyHidden } from "@radix-ui/react-visually-hidden"; +import { StaticMedal } from "./static-metal"; +import { AutoRotateMedal } from "./auto-rotate-badge"; + +const DISC = { radius: 1.3, segments: 200 }; export const RewardCard = ({ - icon, name, description, className, - category, image, + is_unlocked, + requirements, }: BadgeCardProps) => { + const [open, setOpen] = useState(false); + return ( -
-
-
- {name +
+
setOpen(true)} + > + -
- {/* Top right category icon */} - {/* TODO: we have to decide if we want to show the category icon or not */} - {/*
- - {getLucideIcon(category.trim(), { - size: 16, - strokeWidth: 2.5, - absoluteStrokeWidth: true, - })} - -
*/} -
-
-
- {name} -
-
- {description} + > + + + + +
-
+ + + + {name ?? "Badge details"} + + e.preventDefault()} + onCloseAutoFocus={(e) => e.preventDefault()} + className="max-w-lg bg-transparent shadow-none border-none p-0 flex flex-col items-center" + style={{ filter: "none", WebkitFilter: "none" }} + > +
+ + + + + + +
+ + {requirements && requirements.length > 0 && ( +
+ +
+ )} +
+
+ ); }; diff --git a/components/profile/reward-board/component/static-metal.tsx b/components/profile/reward-board/component/static-metal.tsx new file mode 100644 index 00000000000..a4c455d664c --- /dev/null +++ b/components/profile/reward-board/component/static-metal.tsx @@ -0,0 +1,31 @@ +"use client"; +import React, { useEffect, useState } from "react"; +import { CircularFrame } from "./circular-frame"; +import { ImageDisc } from "./image-disc"; + + +export function StaticMedal({ + image, + is_unlocked, + Disc, + }: { + image: string; + is_unlocked?: boolean; + Disc: { radius: number; segments: number } + }) { + const badgeDefaultImage = "/wolfie/wolfie-hack.png"; + const [badgeImage, setBadgeImage] = useState(badgeDefaultImage); + + useEffect(() => { + if (image && image !== '') { + setBadgeImage(image); + } + }, [image]); + + return ( + + + + + ); + } \ No newline at end of file diff --git a/components/profile/reward-board/types/badgeCard.ts b/components/profile/reward-board/types/badgeCard.ts index 00bbce60426..07a92e40363 100644 --- a/components/profile/reward-board/types/badgeCard.ts +++ b/components/profile/reward-board/types/badgeCard.ts @@ -1,10 +1,14 @@ +import { Requirement } from "@/types/badge"; import { ReactNode } from "react"; export type BadgeCardProps = { + id:string; icon: ReactNode | string; image: string; name: string; description: string; className?: string; category: string; + is_unlocked?: boolean; + requirements?: Requirement[]; }; \ No newline at end of file diff --git a/components/quizzes/certificates.tsx b/components/quizzes/certificates.tsx index 6a51624ae69..7a0859e2e6b 100644 --- a/components/quizzes/certificates.tsx +++ b/components/quizzes/certificates.tsx @@ -7,7 +7,7 @@ import quizDataImport from '@/components/quizzes/quizData.json'; import Quiz from '@/components/quizzes/quiz'; import { Accordion, Accordions } from 'fumadocs-ui/components/accordion'; import { Linkedin, Twitter, Award, Share2 } from 'lucide-react'; -import { AwardBadgeWrapper } from './components/awardBadgeWrapper'; +import { AwardBadgeWrapper } from '@/components/quizzes/components/awardBadgeWrapper'; import { useRouter } from 'next/navigation'; import { useCertificates } from '@/hooks/useCertificates'; import { toast } from '@/hooks/use-toast'; @@ -97,10 +97,8 @@ const CertificatePage: React.FC = ({ courseId }) => { } }, [quizzes]); - useEffect(() => { if (totalQuizzes > 0 && correctlyAnsweredQuizzes === totalQuizzes) { - setShouldShowCertificate(true); setTimeout(() => { @@ -193,7 +191,6 @@ const CertificatePage: React.FC = ({ courseId }) => { {allQuizzesCompleted && ( -
@@ -264,6 +261,7 @@ const CertificatePage: React.FC = ({ courseId }) => {
)} + {!allQuizzesCompleted && (
diff --git a/components/quizzes/components/BadgeNotification.tsx b/components/quizzes/components/BadgeNotification.tsx index 9460c51b3c8..ff16a1295cc 100644 --- a/components/quizzes/components/BadgeNotification.tsx +++ b/components/quizzes/components/BadgeNotification.tsx @@ -5,7 +5,8 @@ import { Fireworks } from "@fireworks-js/react"; import type { FireworksHandlers } from "@fireworks-js/react"; import { Badge } from "@/types/badge"; import Image from "next/image"; -// components/quizzes/badge-notification.tsx +import { BadgeData } from "@/server/services/badge"; + export const BadgeNotification = ({ courseId, isCompleted, @@ -17,41 +18,37 @@ export const BadgeNotification = ({ const ref = useRef(null); const [showFireworks, setShowFireworks] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false); - - const [badge, setBadge] = useState(null); + + const [badges, setBadges] = useState([]); useEffect(() => { if (isCompleted && session) { - getBadge(courseId).then((badge) => { - if (badge) { - console.log("Badge obtenido", badge); - setBadge(badge); - awardBadge(); - console.log("Badge awarded"); - setShowFireworks(true); - setIsModalOpen(true); - // small delay for fade in - - - const timer = setTimeout(() => { - setShowFireworks(false); - setIsModalOpen(false); - handleModalClose(); - }, 15000); - - return () => clearTimeout(timer); - } - }); + awardBadge() + .then((badge) => { + + if ( + badge.result && + Array.isArray(badge.result.badges) && + badge.result.badges.length > 0 + ) { + + setBadges(badge.result.badges); + setShowFireworks(true); + setIsModalOpen(true); + + } + }) + .catch((error) => { + console.error("Error awarding badge:", error); + }); } }, [isCompleted, session]); const handleModalClose = () => { - // delay for fade out before closing setTimeout(() => { setIsModalOpen(false); setShowFireworks(false); - }, 300); }; @@ -80,20 +77,66 @@ export const BadgeNotification = ({

{"Congratulations!"}

- {"badge"} -

- {"You have been awarded with a new badge"} -

-

{badge?.name}

+ {Array.isArray(badges) && badges.length === 1 ? ( + // Mostrar un solo badge +
+ {"badge"} +

+ {"You have been awarded with a new badge"} +

+

+ {badges[0]?.name} +

+

+ {badges[0]?.completed_requirement.description} + {/* COMMENTED OUT: Points feature disabled */} + {/* : {badges[0]?.completed_requirement.points} points */} +

+
+ ) : Array.isArray(badges) && badges.length > 1 ? ( + // Mostrar múltiples badges en mosaico +
+

+ {`You have been awarded with ${badges.length} new badges!`} +

+
2 ? 'grid-cols-3' : 'grid-cols-2'} gap-4 `}> + {badges.map((badge, index) => ( +
+ {badge.name} +

+ {badge.name} +

+

+ {badge.completed_requirement.description} + {/* COMMENTED OUT: Points feature disabled */} + {/* : {badge.completed_requirement.points} points */} +

+
+ ))} +
+
+ ) : ( + // No hay badges para mostrar +
+

+ No badges available +

+
+ )}
} - className="border border-red-500 z-50 w-[20%]! " + className="z-50 inline-block! w-auto! max-w-[75vw]! border border-red-500" />
); diff --git a/components/quizzes/hooks/useBadgeAward.ts b/components/quizzes/hooks/useBadgeAward.ts index c41d49273fa..16d6fdaaaa1 100644 --- a/components/quizzes/hooks/useBadgeAward.ts +++ b/components/quizzes/hooks/useBadgeAward.ts @@ -1,5 +1,4 @@ - -import { getBadgeByCourseId } from "@/server/services/rewardBoard"; +import { BadgeCategory } from "@/server/services/badge"; import { Badge } from "@/types/badge"; import { useSession } from "next-auth/react"; import { useState } from "react"; @@ -9,63 +8,63 @@ export const useBadgeAward = (courseId: string) => { let session = null; try { const { data } = useSession(); - + session = data; } catch (error) { - console.log("Error obteniendo la sesión",error); + // Si no hay SessionProvider, session será null - console.warn('SessionProvider not available, badge award will be disabled'); + console.warn("SessionProvider not available, badge award will be disabled"); } const [isLoading, setIsLoading] = useState(false); const [error, setError] = useState(null); const [isAwarded, setIsAwarded] = useState(false); - + const awardBadge = async () => { // Si no hay sesión, no hacer nada if (!session?.user?.id) { - setError('User not authenticated'); + setError("User not authenticated"); return; } setIsLoading(true); setError(null); - + try { - return; - const response = await fetch('/api/award-badge', { - method: 'POST', + const response = await fetch("/api/badge/assign", { + method: "POST", headers: { - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, - body: JSON.stringify({ courseId, userId: session.user.id }) + body: JSON.stringify({ + courseId, + userId: session.user.id, + category: BadgeCategory.academy, + }), }); - - if (!response.ok) { - throw new Error('Failed to award badge'); - } - + const data = await response.json(); setIsAwarded(true); + return data; } catch (err) { - setError(err instanceof Error ? err.message : 'Unknown error'); + setError(err instanceof Error ? err.message : "Unknown error"); } finally { setIsLoading(false); } }; - const getBadge = async (courseId: string):Promise => { + const getBadge = async (courseId: string): Promise => { const response = await fetch(`/api/badge?course_id=${courseId}`); const data = await response.json(); return data as Badge; }; - return { - session, + return { + session, awardBadge, getBadge, - isLoading, - error, + isLoading, + error, isAwarded, - isAuthenticated: !!session?.user?.id + isAuthenticated: !!session?.user?.id, }; -}; \ No newline at end of file +}; diff --git a/components/showcase/ProjectCard.tsx b/components/showcase/ProjectCard.tsx index 12bc550d360..985c56647c7 100644 --- a/components/showcase/ProjectCard.tsx +++ b/components/showcase/ProjectCard.tsx @@ -11,81 +11,107 @@ import { TooltipProvider, TooltipTrigger, } from "@/components/ui/tooltip"; +import { useRouter } from "next/navigation"; +import { ProjectOptions } from "./ProjectOptions"; +import { useState } from "react"; -type Props = { +export type Props = { project: Project; }; export function ProjectCard({ project }: Props) { + const router = useRouter(); const eventInfo = `${project.hackathon?.title ?? ""}`; - console.log(project.prizes) - return ( - -
-

- {project.project_name.slice(0, 25)} - {project.project_name.length > 25 ? "..." : ""} -

- - {project.prizes?.length > 0 && ( -
- -
- )} -
-
- 0 - ? project.cover_url - : "https://qizat5l3bwvomkny.public.blob.vercel-storage.com/builders-hub/hackathon-images/project-banner-2whUMzkW6ABHW5GjIAH3NbBHLQIJzw.png" - } - alt={`${project.project_name} banner`} - width={306} - height={153} - className="w-full h-[153px] object-cover" - /> -
+ const [confirmOpen, setConfirmOpen] = useState(false); + const [isAssignBadgeOpen, setIsAssignBadgeOpen] = useState(false); -
-

- {project.short_description.slice(0, 100)} - {project.short_description.length > 100 ? "..." : ""} -

-
-
- -

- {eventInfo.slice(0, 30)} - {eventInfo.length > 30 ? "..." : ""} -

+ const handleCardClick = (e: React.MouseEvent) => { + if (confirmOpen || isAssignBadgeOpen) return; + const isInteractive = (e.target as HTMLElement).closest( + '[data-interactive="true"]' + ); + if (isInteractive) return; + router.push(`/showcase/${project.id}`); + }; + return ( + +
+

+ {project.project_name.slice(0, 25)} + {project.project_name.length > 25 ? "..." : ""} +

+
+
+ +
+ {project.prizes?.length > 0 && ( +
+ +
+ )}
- -
- {project.tracks.slice(0, 2).map((track) => ( - - - - - {track} - - - -

{track}

-
-
-
- ))} +
+
+ 0 + ? project.cover_url + : "https://qizat5l3bwvomkny.public.blob.vercel-storage.com/builders-hub/hackathon-images/project-banner-2whUMzkW6ABHW5GjIAH3NbBHLQIJzw.png" + } + alt={`${project.project_name} banner`} + width={306} + height={153} + className="w-full h-[153px] object-cover" + /> +
+ +
+

+ {project.short_description.slice(0, 100)} + {project.short_description.length > 100 ? "..." : ""} +

+
+
+ +

+ {eventInfo.slice(0, 30)} + {eventInfo.length > 30 ? "..." : ""} +

+
+ +
+ {project.tracks.slice(0, 2).map((track) => ( + + + + + {track} + + + +

{track}

+
+
+
+ ))} +
-
-
- + ); } diff --git a/components/showcase/ProjectOptions.tsx b/components/showcase/ProjectOptions.tsx new file mode 100644 index 00000000000..b1af9bc26c2 --- /dev/null +++ b/components/showcase/ProjectOptions.tsx @@ -0,0 +1,152 @@ +import React, { useState } from "react"; +import { Props } from "./ProjectCard"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "../ui/dropdown-menu"; +import { Button } from "../ui/button"; +import { EllipsisVertical } from "lucide-react"; +import { + AlertDialog, + AlertDialogFooter, + AlertDialogDescription, + AlertDialogContent, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogCancel, + AlertDialogAction, +} from "../ui/alert-dialog"; +import axios from "axios"; +import { useToast } from "@/hooks/use-toast"; +import { Toaster } from "../ui/toaster"; +import { AssignBadge } from "./assign-badge"; + +export const ProjectOptions = ({ + project, + confirmOpen, + setConfirmOpen, + isAssignBadgeOpen, + setIsAssignBadgeOpen, +}: Props & { + confirmOpen: boolean; + setConfirmOpen: React.Dispatch>; + isAssignBadgeOpen: boolean; + setIsAssignBadgeOpen: React.Dispatch>; +}) => { + const [isDropdownOpen, setIsDropdownOpen] = useState(false); + const { toast } = useToast(); + const handleSetWinner = async (e: React.MouseEvent) => { + e.stopPropagation(); + const response = await axios.put(`/api/project/set-winner`, { + project_id: project.id, + isWinner: true, + }); + + if (response.data.success) { + toast({ + title: "Project winner set successfully", + description: "The project has been marked as the winner", + duration: 3000, + }); + } else { + toast({ + title: "Failed to set project winner", + description: "Unable to mark project as winner. Please try again.", + variant: "destructive", + duration: 3000, + }); + } + setConfirmOpen(false); + }; + + const handleAssignBadge = (e: React.MouseEvent) => { + e.stopPropagation(); + e.preventDefault(); + + setIsAssignBadgeOpen(true); + }; + + return ( + <> + + + + + + + e.stopPropagation()} + > + { + e.stopPropagation(); + }} + onSelect={(e) => { + e.stopPropagation(); + setIsDropdownOpen(false); + setConfirmOpen(true); + }} + > + Set Winner + + + { + e.stopPropagation(); + }} + onSelect={(e) => { + setIsDropdownOpen(false); + handleAssignBadge(e as any); + }} + > + Assign Badge + + + + + + e.stopPropagation()}> + + Confirm Winner? + + Do you want to mark "{project.project_name}" as winner? This + action cannot be undone. + + + + e.stopPropagation()}> + Cancel + + { + e.stopPropagation(); + handleSetWinner(e); + }} + > + Confirm + + + + + + + ); +}; diff --git a/components/showcase/ProjectOverview.tsx b/components/showcase/ProjectOverview.tsx index 2f8ea055c8a..77919ffc608 100644 --- a/components/showcase/ProjectOverview.tsx +++ b/components/showcase/ProjectOverview.tsx @@ -8,11 +8,15 @@ import TeamMembers from "./sections/TeamMembers"; import { Project } from "@/types/showcase"; import VideoRenderer from "./DemoVideoRenderer"; import { TeamBadge } from "./sections/TeamBadge"; +import { UserBadge } from "@/types/badge"; + type Props = { project: Project; + badges?: UserBadge[]; }; -export default function ProjectOverview({ project }: Props) { +export default function ProjectOverview({ project, badges }: Props) { + return (
@@ -54,13 +58,15 @@ export default function ProjectOverview({ project }: Props) { {project.full_description && ( )} + {project.members && ( )} - {/* */} + {/* {resources && } */}
diff --git a/components/showcase/ShowCaseCard.tsx b/components/showcase/ShowCaseCard.tsx index a0eb15cb0a5..cf340fd117e 100644 --- a/components/showcase/ShowCaseCard.tsx +++ b/components/showcase/ShowCaseCard.tsx @@ -25,12 +25,15 @@ import { } from '../ui/pagination'; import React from 'react'; import { ProjectCard } from './ProjectCard'; -import Link from 'next/link'; import { ProjectFilters } from '@/types/project'; import { useRouter } from 'next/navigation'; import { HackathonHeader } from '@/types/hackathons'; +import { useExports } from './hooks/useExports'; +import { LoadingButton } from '../ui/loading-button'; +import { useSession } from 'next-auth/react'; const tracks = ['AI', 'DeFi', 'RWA', 'Gaming', 'SocialFi', 'Tooling']; - +import { useToast } from "@/hooks/use-toast"; +import { Toaster } from "../ui/toaster"; type Props = { projects: Project[]; events: HackathonHeader[]; @@ -47,17 +50,66 @@ export default function ShowCaseCard({ const [searchValue, setSearchValue] = useState(''); const [filters, setFilters] = useState(initialFilters); const [currentPage, setCurrentPage] = useState(initialFilters.page ?? 1); + const { data: session } = useSession(); const [recordsByPage, setRecordsByPage] = useState( initialFilters.recordsByPage ?? 12 ); const [totalPages, setTotalPages] = useState( Math.ceil(totalProjects / recordsByPage) || 1 ); + const [isExporting, setIsExporting] = useState(false); const router = useRouter(); - + const { exportToExcel, isLoading, error } = useExports(); const selectedHackathon = events.find(event => event.id === filters.event); const availableTracks = selectedHackathon?.content?.tracks?.map(track => track.name) ?? []; - + const [hasRole, setHasRole] = useState(false); + const { toast } = useToast(); + const handleExport = async () => { + const exportFilters: Record = {}; + + if (filters.event) { + exportFilters.event = filters.event; + } + + if (filters.track) { + exportFilters.track = filters.track; + } + + if (filters.search) { + exportFilters.search = filters.search; + } + + if (typeof filters.winningProjecs === 'boolean') { + exportFilters.winningProjects = filters.winningProjecs; + } + + try { + setIsExporting(true); + await exportToExcel(exportFilters); + } catch (err) { + console.error('Error exporting:', error); + toast({ + title: "Error exporting projects", + description: error, + variant: "default", + duration: 3000, + }); + } finally { + setIsExporting(false); + } + }; + + useEffect(() => { + if (session?.user) { + if (session?.user?.custom_attributes?.includes('hackathonCreator')) { + setHasRole(true); + } + } + else { + setHasRole(false); + } + }, [session]); + const handleFilterChange = (type: keyof ProjectFilters, value: string) => { const newFilters = { @@ -101,7 +153,9 @@ export default function ShowCaseCard({ }; return ( + + Showcase @@ -112,6 +166,14 @@ export default function ShowCaseCard({ +
+ {hasRole && + Export Projects + } +
handleFilterChange('winningProjecs', 'false')} value='allProjects' - className={`${ - filters.winningProjecs + className={`${filters.winningProjecs ? '!bg-transparent' : 'bg-zinc-50 dark:!bg-zinc-950' - } border-none`} + } border-none`} > All Projects handleFilterChange('winningProjecs', 'true')} value='winingProjects' - className={`${ - filters.winningProjecs + className={`${filters.winningProjecs ? 'bg-zinc-50 dark:!bg-zinc-950' : '!bg-transparent' - } border-none`} + } border-none`} > Winning Projects
+
1 ? 'Projects' : totalProjects == 0 - ? 'No projects found' - : 'Project'}{' '} + ? 'No projects found' + : 'Project'}{' '} found
{projects.map((project, index) => ( - - - + + + ))}
diff --git a/components/showcase/assign-badge.tsx b/components/showcase/assign-badge.tsx new file mode 100644 index 00000000000..3534985f568 --- /dev/null +++ b/components/showcase/assign-badge.tsx @@ -0,0 +1,118 @@ +import React, { useEffect, useState } from "react"; +import Modal from "../ui/Modal"; +import { Project } from "@/types/showcase"; +import { MultiSelect } from "../ui/multi-select"; +import axios from "axios"; +import { Badge } from "@/types/badge"; +import { BadgeCategory } from "@/server/services/badge"; +import { useToast } from "@/hooks/use-toast"; +import { LoadingButton } from "../ui/loading-button"; +import { Toaster } from "../ui/toaster"; +type showAssignBadgeProps = { + isOpen: boolean; + onOpenChange: (open: boolean) => void; + project: Project; +}; +export const AssignBadge = ({ + isOpen, + onOpenChange, + project, +}: showAssignBadgeProps) => { + const [optionsWithLabel, setOptionsWithLabel] = useState< + { label: string; value: string }[] + >([]); + const { toast } = useToast(); + const [selectedBadges, setSelectedBadges] = useState([]); + const [isLoading, setIsLoading] = useState(false); + useEffect(() => { + const fetchBadges = async () => { + // COMMENTED OUT: Hackathon badges feature disabled + // const response = await axios.get("/api/badge/get-all"); + // const filteredBadges = response.data.filter( + // (badge: Badge) => badge.category == "hackathon" + // ); + // setOptionsWithLabel( + // filteredBadges.map((option: Badge) => ({ + // label: option.name, + // value: option.id, + // })) + // ); + // Return empty array since hackathon badges are disabled + setOptionsWithLabel([]); + }; + fetchBadges(); + }, []); + + const handleClose = () => { + setSelectedBadges([]); + setIsLoading(false); + onOpenChange(false); + }; + + const handleAssignBadges = async () => { + setIsLoading(true); + const response = await axios.post("/api/badge/assign", { + badgesId: selectedBadges, + projectId: project.id, + category: BadgeCategory.project, + }); + if (response.status == 200) { + toast({ + title: "Badges assigned successfully", + description: "The badges have been assigned to the project", + duration: 3000, + }); + } else { + toast({ + title: "Failed to assign badges", + description: "The badges have not been assigned to the project", + variant: "destructive", + duration: 3000, + }); + } + handleClose(); + }; + + const multiSelectCard = ( +
+ + { + setSelectedBadges(values); + }} + /> + { + handleAssignBadges(); + }} + > + Assign Badges + +
+ ); + + return ( + <> + { + onOpenChange(event); + if (!event) { + handleClose(); + } + }} + title="Assign Badge" + className="border-red-500" + content={ +
e.stopPropagation()}> + {multiSelectCard} +
+ } + /> + + ); +}; diff --git a/components/showcase/hooks/useExports.tsx b/components/showcase/hooks/useExports.tsx new file mode 100644 index 00000000000..695f4d1a8d0 --- /dev/null +++ b/components/showcase/hooks/useExports.tsx @@ -0,0 +1,105 @@ +import { useState, useCallback } from 'react'; +import axios, { AxiosError } from 'axios'; + +interface ExportFilters { + [key: string]: any; +} + +interface UseExportsReturn { + isLoading: boolean; + error: string | null; + exportToExcel: (filters?: ExportFilters) => Promise; +} + + +export const useExports = (): UseExportsReturn => { + const [isLoading, setIsLoading] = useState(false); + const [error, setError] = useState(null); + + + const generateFileName = (): string => { + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const day = String(now.getDate()).padStart(2, '0'); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + + return `showcase_${year}${month}${day}${hours}${minutes}${seconds}.xlsx`; + }; + + + const downloadFile = (blob: Blob, fileName: string): void => { + const url = window.URL.createObjectURL(blob); + const link = document.createElement('a'); + link.href = url; + link.download = fileName; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + window.URL.revokeObjectURL(url); + }; + + + const exportToExcel = useCallback(async (filters?: ExportFilters): Promise => { + setIsLoading(true); + setError(null); + + try { + const response = await axios.post( + '/api/projects/export', + filters || {}, + { + responseType: 'blob', + headers: { + 'Content-Type': 'application/json', + }, + } + ); + + const contentType = response.headers['content-type']; + + if (contentType && contentType.includes('application/json')) { + const text = await response.data.text(); + const errorData = JSON.parse(text); + throw new Error(errorData.message || 'Error exporting data'); + } + + const fileName = generateFileName(); + downloadFile(response.data, fileName); + } catch (err) { + const axiosError = err as AxiosError<{ message?: string }>; + + let errorMessage = 'Error exporting data'; + + if (axiosError.response?.data) { + if (axiosError.response.data instanceof Blob) { + try { + const text = await axiosError.response.data.text(); + const errorData = JSON.parse(text); + errorMessage = errorData.message || errorMessage; + } catch { + errorMessage = 'An error occurred while processing the server response'; + } + } else if (axiosError.response.data.message) { + errorMessage = axiosError.response.data.message; + } + } else if (axiosError.message) { + errorMessage = axiosError.message; + } + + setError(errorMessage); + throw new Error(errorMessage); + } finally { + setIsLoading(false); + } + }, []); + + return { + isLoading, + error, + exportToExcel, + }; +}; + diff --git a/components/showcase/sections/Info.tsx b/components/showcase/sections/Info.tsx index f406f4be172..194c296d60e 100644 --- a/components/showcase/sections/Info.tsx +++ b/components/showcase/sections/Info.tsx @@ -1,13 +1,26 @@ +"use client"; import { Badge } from "@/components/ui/badge"; import { Button } from "@/components/ui/button"; import { Project } from "@/types/showcase"; import { MapPin, Trophy } from "lucide-react"; import Link from "next/link"; +import { useEffect, useState } from "react"; type Props = { project: Project; }; export default function Info({ project }: Props) { + const parseLinks = (linkString: string | null | undefined): string[] => { + if (!linkString) return []; + return linkString.split(',').map(link => link.trim()).filter(link => link.length > 0); + }; + const [demoLinks, setDemoLinks] = useState([]); + const [githubLinks, setGithubLinks] = useState([]); + + useEffect(() => { + setDemoLinks(parseLinks(project.demo_link)); + setGithubLinks(parseLinks(project.github_repository)); + }, [project.demo_link, project.github_repository]); return (
@@ -52,28 +65,28 @@ export default function Info({ project }: Props) { ))}
- -
- {project.demo_link && ( - + +
+ {demoLinks.map((link, index) => ( + - )} - {project.github_repository && ( - + ))} + {githubLinks.map((link, index) => ( + - )} + ))}
); diff --git a/components/showcase/sections/MemberBadge.tsx b/components/showcase/sections/MemberBadge.tsx new file mode 100644 index 00000000000..6ff060ebd40 --- /dev/null +++ b/components/showcase/sections/MemberBadge.tsx @@ -0,0 +1,68 @@ +"use client" +import { UserBadge } from '@/types/badge'; +import { Member } from '@/types/showcase'; +import Image from 'next/image'; +import React, { useState } from 'react' + +export default function MemberBadge({badges, member}: {badges: UserBadge[], member: Member}) { + + const badgesFiltered = badges?.filter((badge) => badge.user_id === member.user_id); + const [showAll, setShowAll] = useState(false); + const maxBadges = 12; + + const initialBadges = badgesFiltered?.slice(0, maxBadges) || []; + const hasMore = badgesFiltered && badgesFiltered.length > maxBadges; + const remainingCount = badgesFiltered ? badgesFiltered.length - maxBadges : 0; + + const displayBadges = showAll ? badgesFiltered : initialBadges; + + return ( + <> + {badgesFiltered && badgesFiltered.length > 0 ? ( +
+

Badges

+ +
+ {displayBadges.map((badge) => ( + +
+ + {badge.name +
+ ))} +
+ + {hasMore && ( + + )} +
+ ) : ( +
+

No badges

+
+ )} + + ) +} \ No newline at end of file diff --git a/components/showcase/sections/TeamBadge.tsx b/components/showcase/sections/TeamBadge.tsx index 83c7de1e797..fbe44299085 100644 --- a/components/showcase/sections/TeamBadge.tsx +++ b/components/showcase/sections/TeamBadge.tsx @@ -1,116 +1,46 @@ +"use client"; + import { Separator } from "@/components/ui/separator"; -import { BadgesByTeam } from "@/types/badgesByTeam"; import Image from "next/image"; -import React from "react"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "@/components/ui/tooltip"; -import { Avatar } from "@/components/ui/avatar"; +import React, { useState, useEffect } from "react"; +import { ProjectBadge } from "@/types/badge"; +import axios from "axios"; type Props = { - Badge: BadgesByTeam[]; + projectId: string; }; -export const TeamBadge = ({ Badge }: Props) => { - const DataDummy = [ - { - Badge: { - name: "Best UI/UX", - description: "For the best UI/UX design", - points: 100, - image_path: - "https://49ci7gswyprqetfg.public.blob.vercel-storage.com/badges/badgeWinner.png", - category: "UI/UX", - metadata: null, - }, - quantity: 1, - owner: "John Doe", - }, - { - Badge: { - name: "BUG HUNTER", - description: "For the best UI/UX design", - points: 100, - image_path: - "https://49ci7gswyprqetfg.public.blob.vercel-storage.com/badges/badge_Exterminador_bugs.png", - category: "UI/UX", - metadata: null, - }, - quantity: 2, - owner: "Joan Mosquera,Sebastian Ortiz", - }, - { - Badge: { - name: "BORN TO BE A HACKER", - description: "For the best UI/UX design", - points: 100, - image_path: - "https://49ci7gswyprqetfg.public.blob.vercel-storage.com/badges/badge_born_to_code.png", - category: "UI/UX", - metadata: null, - }, - quantity: 3, - owner: "Joan Mosquera,Sebastian Ortiz,John Doe", - }, - { - Badge: { - name: "Best Team", - description: "For the best UI/UX design", - points: 100, - image_path: - "https://49ci7gswyprqetfg.public.blob.vercel-storage.com/badges/BestTeamEN.png", - category: "UI/UX", - metadata: null, - }, - quantity: 3, - owner: "Joan Mosquera,Sebastian Ortiz,John Doe", - }, - ]; + +export const TeamBadge = ({ projectId }: Props) => { + const [badges, setBadges] = useState([]); + useEffect(() => { + if (!projectId) return; + const bad = axios.get(`/api/badge/project-badge?project_id=${projectId}`); + bad.then((res) => { + setBadges(res.data); + }); + }, [projectId]); return (
-

Team Reward Board

+

Project Reward Board

- {DataDummy.map((item, index) => ( + {badges.map((item: ProjectBadge, index: number) => (
- - - - {item.Badge.name} - - -
-

{item.Badge.name}

-

awarded to:

-
-
    - {item.owner.split(",").map((owner, ownerIndex) => ( -
  • - {owner.trim()} -
  • - ))} -
-
-
-
-
-
+ {item.name} +

{item.name}

))} -
); diff --git a/components/showcase/sections/TeamMembers.tsx b/components/showcase/sections/TeamMembers.tsx index 1f627fb067e..5f6ea1044d6 100644 --- a/components/showcase/sections/TeamMembers.tsx +++ b/components/showcase/sections/TeamMembers.tsx @@ -1,35 +1,60 @@ import { Separator } from "@/components/ui/separator"; import { Member } from "@/types/showcase"; import Image from "next/image"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import MemberBadge from "./MemberBadge"; +import { UserBadge } from "@/types/badge"; type Props = { members: Member[]; projectName: string; + badges?: UserBadge[]; }; -export default function TeamMembers({ members, projectName }: Props) { +export default function TeamMembers({ members, projectName, badges }: Props) { + return (

Team

Meet the minds behind {projectName}

-
- {members.filter((member) => member.status === "Confirmed").map((member, index) => ( -
- {member.user.user_name -
-

{member.user.user_name}

-

{member.role}

-
-
- ))} -
+ + +
+ {members.filter((member) => member.status === "Confirmed").map((member, index) => ( + + +
+ {member.user.user_name +
+

{member.user.user_name}

+

{member.role}

+
+
+
+ + + + +
+ ))} +
+
); } diff --git a/components/ui/calendar.tsx b/components/ui/calendar.tsx index b8df044d5aa..5a09e9e7fc0 100644 --- a/components/ui/calendar.tsx +++ b/components/ui/calendar.tsx @@ -60,12 +60,10 @@ function Calendar({ ...classNames, }} components={{ - IconLeft: ({ className, ...props }) => ( - - ), - IconRight: ({ className, ...props }) => ( - - ), + Chevron: ({ orientation, ...props }) => { + const Icon = orientation === "left" ? ChevronLeft : ChevronRight; + return ; + }, }} {...props} /> diff --git a/lib/auth/authOptions.ts b/lib/auth/authOptions.ts index 35f85770de1..a1d59c6cb21 100644 --- a/lib/auth/authOptions.ts +++ b/lib/auth/authOptions.ts @@ -7,6 +7,9 @@ import { prisma } from '../../prisma/prisma'; import { JWT } from 'next-auth/jwt'; import type { VerifyOTPResult } from '@/types/verifyOTPResult'; import { upsertUser } from '@/server/services/auth'; +import { badgeAssignmentService } from '@/server/services/badgeAssignmentService'; +import { BadgeCategory } from '@/server/services/badge'; + declare module 'next-auth' { export interface Session { @@ -123,6 +126,16 @@ export const AuthOptions: NextAuthOptions = { try { const dbUser = await upsertUser(user, account, profile); user.id = dbUser.id; + + if (account?.provider == 'github') { + await badgeAssignmentService.assignBadge({ + userId: dbUser.id, + requirementId: 'GitHub', + category: BadgeCategory.requirement, + }); + + } + return true; } catch (error) { console.error('Error processing user:', error); diff --git a/lib/protectedRoute.ts b/lib/protectedRoute.ts index 441121871ec..05ba51e6f46 100644 --- a/lib/protectedRoute.ts +++ b/lib/protectedRoute.ts @@ -11,4 +11,14 @@ export function withAuth(handler: (request: NextRequest, context: any, session: return handler(request, context, session); }; } +export function withAuthRole(role: string, handler: (request: NextRequest, context: any, session: any) => Promise) { + return async function (request: NextRequest, context: any) { + const session = await getAuthSession(); + const hasRole= session?.user.custom_attributes.includes(role) + if (!session || !hasRole) { + return NextResponse.json({ error: 'Forbidden' }, { status: 401 }); + } + return handler(request, context, session); + }; +} diff --git a/package.json b/package.json index 5140668c8fc..675abad9470 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,8 @@ "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", + "@react-three/drei": "^10.7.6", + "@react-three/fiber": "^9.3.0", "@safe-global/api-kit": "^4.0.0", "@safe-global/protocol-kit": "^6.1.1", "@safe-global/types-kit": "^3.0.0", @@ -77,7 +79,9 @@ "cmdk": "^1.1.1", "date-fns": "^4.1.0", "embla-carousel-auto-scroll": "^8.6.0", + "embla-carousel-autoplay": "^8.5.2", "embla-carousel-react": "^8.6.0", + "exceljs": "^4.4.0", "framer-motion": "^12.23.12", "fumadocs-core": "^16.0.9", "fumadocs-mdx": "^13.0.5", @@ -102,7 +106,7 @@ "posthog-js": "^1.266.0", "prismjs": "^1.30.0", "react": "^19.2.0", - "react-day-picker": "8.10.1", + "react-day-picker": "^9.11.1", "react-dom": "^19.2.0", "react-error-boundary": "^5.0.0", "react-hook-form": "^7.62.0", @@ -119,6 +123,10 @@ "sonner": "^2.0.7", "tailwind-merge": "^3.3.1", "tailwindcss-animate": "^1.0.7", + "three": "^0.180.0", + "trieve-fumadocs-adapter": "^1.3.1", + "trieve-ts-sdk": "^0.0.124", + "troika-three-text": "^0.52.4", "tsx": "^4.20.5", "twoslash": "^0.3.4", "uuid": "^11.1.0", @@ -132,6 +140,7 @@ "@tailwindcss/postcss": "^4.1.13", "@tailwindcss/typography": "^0.5.16", "@types/canvas-confetti": "^1.9.0", + "@types/exceljs": "^1.3.2", "@types/mdx": "^2.0.13", "@types/node": "^24.5.0", "@types/prismjs": "^1.26.5", diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 04fee70e7a3..1a88dbafe8a 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -22,8 +22,8 @@ model Hackathon { icon String @default("") small_banner String @default("") participants Int - top_most Boolean? @default(false) organizers String? + top_most Boolean? @default(false) custom_link String? created_by String? updated_by String? @@ -35,9 +35,9 @@ model Hackathon { } model User { - id String @id @default(cuid()) + id String @id @default(cuid()) name String? - email String? @unique + email String? @unique image String? authentication_mode String? integration String? @@ -45,19 +45,19 @@ model User { user_name String? bio String? notification_email String? - profile_privacy String? @default("public") - social_media String[] notifications Boolean? + profile_privacy String? @default("public") + social_media String[] custom_attributes String[] telegram_user String? - created_at DateTime @default(now()) @db.Timestamptz(3) + created_at DateTime @default(now()) @db.Timestamptz(3) updated_hackathons Hackathon[] @relation("HackathonUpdatedBy") memberships Member[] registrations RegisterForm[] - hackathons Hackathon[] badges UserBadge[] managedTestnetNodes NodeRegistration[] consoleLog ConsoleLog[] + hackathons Hackathon[] } model VerificationToken { @@ -172,17 +172,17 @@ model UserBadge { } model ProjectBadge { - id String @id @default(uuid()) - project Project @relation(fields: [project_id], references: [id], onDelete: Cascade) - project_id String - badge Badge @relation(fields: [badge_id], references: [id], onDelete: Cascade) - badge_id String - awarded_at DateTime @default(now()) - awarded_by String? + id String @id @default(uuid()) + project_id String + badge_id String + awarded_at DateTime @default(now()) + awarded_by String? evidence Json? requirements_snapshot Json @default("{}") requirements_version Int @default(1) status Int @db.SmallInt + badge Badge @relation(fields: [badge_id], references: [id], onDelete: Cascade) + project Project @relation(fields: [project_id], references: [id], onDelete: Cascade) @@unique([project_id, badge_id]) } @@ -193,16 +193,17 @@ model NodeRegistration { subnet_id String blockchain_id String node_id String - node_index Int? // Node index from BuilderHub API + node_index Int? public_key String proof_of_possession String rpc_url String chain_name String? - status String @default("active") // active, expired, terminated + status String @default("active") created_at DateTime @default(now()) @db.Timestamptz(3) expires_at DateTime @db.Timestamptz(3) updated_at DateTime @updatedAt @db.Timestamptz(3) user User @relation(fields: [user_id], references: [id], onDelete: Cascade) + @@unique([user_id, subnet_id, node_index]) @@index([user_id]) @@index([status]) @@ -212,12 +213,12 @@ model NodeRegistration { model ConsoleLog { id String @id @default(uuid()) user_id String - status String // success, error, warning, info - action_path String? // Full path context (e.g., "permissioned-l1s/validator-manager-setup/deploy/validator_manager") - data Json? // Flexible JSON data + status String + action_path String? + data Json? created_at DateTime @default(now()) @db.Timestamptz(3) user User @relation(fields: [user_id], references: [id], onDelete: Cascade) @@index([user_id]) @@index([created_at]) -} \ No newline at end of file +} diff --git a/scripts/versions.json b/scripts/versions.json index 59a52ad6d9a..244fc147c36 100644 --- a/scripts/versions.json +++ b/scripts/versions.json @@ -2,12 +2,12 @@ "mainnet": { "avaplatform/avalanchego": "v1.14.0", "avaplatform/subnet-evm_avalanchego": "v0.8.0_v1.14.0", - "avaplatform/icm-relayer": "v1.7.3" + "avaplatform/icm-relayer": "v1.7.4" }, "testnet": { - "avaplatform/avalanchego": "v1.14.0", - "avaplatform/subnet-evm_avalanchego": "v0.8.0_v1.14.0", - "avaplatform/icm-relayer": "v1.7.3" + "avaplatform/avalanchego": "v1.14.0-fuji", + "avaplatform/subnet-evm_avalanchego": "v0.8.0-fuji_v1.14.0-fuji", + "avaplatform/icm-relayer": "v1.7.2-fuji" }, "ava-labs/icm-contracts": "4d5ab0b6dbc653770cfe9709878c9406eb28b71c" -} +} \ No newline at end of file diff --git a/server/services/badge.ts b/server/services/badge.ts new file mode 100644 index 00000000000..49c094a6814 --- /dev/null +++ b/server/services/badge.ts @@ -0,0 +1,252 @@ +import { prisma } from "@/prisma/prisma"; +import { Badge, BadgeAwardStatus, Requirement } from "@/types/badge"; +import { parseBadgeMetadata } from "./rewardBoard"; + +export enum BadgeCategory { + academy, + project, + requirement, + +} + +export interface AssignBadgeBody { + category?: BadgeCategory; + courseId?: string; + userId: string; + hackathonId?: string; + projectId?: string; + requirementId?: string; // For social badges - specific requirement to fulfill + badgesId?: string[]; +} + +export interface AssignBadgeResult { + success: boolean; + message: string; + badge_id: string; + user_id: string; + badges: BadgeData[] | []; +} + +export interface BadgeData { + name: string; + image_path: string; + completed_requirement: Requirement; +} + +export async function getAllBadges(): Promise { + const badges = await prisma.badge.findMany({}); + + return badges.map((badge) => ({ + ...badge, + requirements: badge.requirements.map((requirement) => + parseBadgeMetadata(requirement) + ) as Requirement[], + })); +} + +export async function assignBadgeAcademy( + body: AssignBadgeBody +): Promise { + const badgesAcademy = await getBadgeByCourseId(body.courseId!); + let badgeToReturn: AssignBadgeResult = { + success: false, + message: "Badges not found", + badge_id: "", + user_id: "", + badges: [], + }; + if (!badgesAcademy) { + return badgeToReturn; + } + for (const badge of badgesAcademy) { + const isBadgeAlreadyAwarded = await validateBadge(badge.id, body.userId); + if (isBadgeAlreadyAwarded) { + continue; + } + const badgeRequirements = badge.requirements; + const badgeImage: string = badge.image_path as string; + const existingUserBadge = await prisma.userBadge.findUnique({ + where: { + user_id_badge_id: { + user_id: body.userId, + badge_id: badge.id, + }, + }, + }); + + const completedRequirements = + (existingUserBadge?.evidence as Requirement[]) || []; + const currentRequirement = badgeRequirements?.find( + (req: any) => req.course_id === body.courseId + ); + + let isNewRequirement = false; + if ( + currentRequirement && + currentRequirement.id && + !completedRequirements.some((req: any) => + req && req.id && String(req.id) === String(currentRequirement.id) + ) + ) { + completedRequirements.push(currentRequirement); + isNewRequirement = true; + } + + // Check if all requirements are completed by comparing IDs + const allRequirementsCompleted = badgeRequirements?.every((req: any) => { + if (!req || !req.id) return false; + return completedRequirements.some((completed: any) => + completed && completed.id && String(completed.id) === String(req.id) + ); + }); + + const someRequirementsCompleted = completedRequirements.length > 0; + let badgeStatus = BadgeAwardStatus.pending; + + if (allRequirementsCompleted) { + badgeStatus = BadgeAwardStatus.approved; + // Only add badge to return array when all requirements are completed + (badgeToReturn.badges as BadgeData[]).push({ + name: badge.name, + image_path: badgeImage, + completed_requirement: currentRequirement || (badgeRequirements && badgeRequirements[0]) || ({} as Requirement), + }); + badgeToReturn.success = true; + badgeToReturn.message = "Badge assigned successfully"; + badgeToReturn.badge_id = badge.id; + badgeToReturn.user_id = body.userId; + } else if (someRequirementsCompleted) { + badgeStatus = BadgeAwardStatus.pending; + } + + if (someRequirementsCompleted) { + await prisma.userBadge.upsert({ + where: { + user_id_badge_id: { + user_id: body.userId, + badge_id: badge.id, + }, + }, + update: { + awarded_at: + badgeStatus == BadgeAwardStatus.approved + ? new Date() + : existingUserBadge?.awarded_at, + awarded_by: "system", + status: badgeStatus, + requirements_version: 1, + evidence: completedRequirements, + }, + create: { + user_id: body.userId, + badge_id: badge.id, + awarded_at: + badgeStatus == BadgeAwardStatus.approved ? new Date() : undefined, + awarded_by: "system", + status: badgeStatus, + requirements_version: 1, + evidence: completedRequirements, + }, + }); + } + } + + return badgeToReturn; +} + +export async function validateBadge( + badgeId: string, + userId: string +): Promise { + const existingUserBadge = await prisma.userBadge.findUnique({ + where: { + user_id_badge_id: { + user_id: userId, + badge_id: badgeId, + }, + }, + }); + return existingUserBadge?.status == BadgeAwardStatus.approved; +} + +export async function getBadgeByCourseId(courseId: string): Promise { + const badges = await prisma.badge.findMany({ + where: { + category: "academy", + }, + }); + + const filteredBadges = badges.filter((badge) => + badge.requirements?.some((req: any) => req.course_id === courseId) + ); + + if (filteredBadges.length === 0) { + throw new Error(`Badge not found for course ID: ${courseId}`); + } + + return filteredBadges.map((badge) => ({ + id: badge.id, + name: badge.name, + description: badge.description, + points: 0, + image_path: badge.image_path, + category: badge.category, + requirements: badge.requirements.map((requirement) => + parseBadgeMetadata(requirement) + ) as Requirement[], + })); +} + +export async function getBadgesByHackathonId( + hackathonId: string +): Promise { + const badges = await prisma.badge.findMany({ + where: { + category: "hackathon", + }, + }); + + const filteredBadges = badges.filter((badge) => + badge.requirements?.some((req: any) => req.hackathon == hackathonId) + ); + if (filteredBadges.length === 0) { + throw new Error(`Badge not found for hackathon ID: ${hackathonId}`); + } + + return filteredBadges.map((badge) => ({ + id: badge.id, + name: badge.name, + description: badge.description, + + image_path: badge.image_path, + category: badge.category, + requirements: badge.requirements.map((requirement) => + parseBadgeMetadata(requirement) + ) as Requirement[], + })); +} + + +export async function getBadgesByIds( + badgesIds: string[] +): Promise { + const badges = await prisma.badge.findMany({ + where: { + id: { + in: badgesIds, + }, + }, + }); + + return badges.map((badge) => ({ + id: badge.id, + name: badge.name, + description: badge.description, + + image_path: badge.image_path, + category: badge.category, + requirements: badge.requirements.map((requirement) => + parseBadgeMetadata(requirement) + ) as Requirement[], + })); +} \ No newline at end of file diff --git a/server/services/badgeAssignmentService.ts b/server/services/badgeAssignmentService.ts new file mode 100644 index 00000000000..14e8c18cdd4 --- /dev/null +++ b/server/services/badgeAssignmentService.ts @@ -0,0 +1,186 @@ +import { AssignBadgeBody, AssignBadgeResult, BadgeCategory } from "./badge"; +import { BadgeAssignmentContext, BadgeStrategyFactory } from "./badgeStrategy"; + +export class BadgeAssignmentService { + private context: BadgeAssignmentContext; + + constructor() { + // Initialize with a default strategy (will be changed dynamically) + this.context = new BadgeAssignmentContext( + BadgeStrategyFactory.createStrategy(BadgeCategory.academy) + ); + } + + /** + * Assigns a badge based on the category specified in the body + * @param body - Badge assignment data + * @param awardedBy - User who is awarding the badge (optional) + * @returns Assignment result + */ + async assignBadge( + body: AssignBadgeBody, + awardedBy?: string + ): Promise { + try { + // Determine the badge category + const category = this.determineBadgeCategory(body); + + if (category === null) { + return { + success: false, + message: + "Unable to determine badge category. Please provide courseId, hackathonId, or projectId", + badge_id: "", + user_id: body.userId, + badges: [], + }; + } + + // Create the appropriate strategy + const strategy = BadgeStrategyFactory.createStrategy(category); + this.context.setStrategy(strategy); + + // Execute the assignment using the selected strategy + return await this.context.assignBadge(body, awardedBy); + } catch (error) { + console.error("Error in BadgeAssignmentService:", error); + return { + success: false, + message: `Error assigning badge: ${ + error instanceof Error ? error.message : "Unknown error" + }`, + badge_id: "", + user_id: body.userId, + badges: [], + }; + } + } + + /** + * Assigns a badge using a specific strategy + * @param body - Badge assignment data + * @param category - Specific badge category + * @param awardedBy - User who is awarding the badge (optional) + * @returns Assignment result + */ + async assignBadgeWithCategory( + body: AssignBadgeBody, + category: BadgeCategory, + awardedBy?: string + ): Promise { + try { + // Create the specific strategy + const strategy = BadgeStrategyFactory.createStrategy(category); + this.context.setStrategy(strategy); + + // Execute the assignment + return await this.context.assignBadge(body, awardedBy); + } catch (error) { + console.error("Error in BadgeAssignmentService with category:", error); + return { + success: false, + message: `Error assigning badge: ${ + error instanceof Error ? error.message : "Unknown error" + }`, + badge_id: "", + user_id: body.userId, + badges: [], + }; + } + } + + /** + * Determines the badge category based on the body data + * @param body - Badge assignment data + * @returns Badge category or null if cannot be determined + */ + private determineBadgeCategory(body: AssignBadgeBody): BadgeCategory | null { + // If category is already specified, use it + + if (body.category !== undefined) { + return body.category; + } + + // Determine category based on provided IDs + if (body.courseId) { + return BadgeCategory.academy; + } + + if (body.projectId) { + return BadgeCategory.project; + } + + return BadgeCategory.requirement; + } + + /** + * Gets all available badge categories + * @returns Array of available categories + */ + getAvailableCategories(): BadgeCategory[] { + return Object.values(BadgeCategory).filter( + (value) => typeof value === "number" + ) as BadgeCategory[]; + } + + /** + * Validates if a body has the required data for a specific category + * @param body - Badge assignment data + * @param category - Category to validate + * @returns true if the body is valid for the category + */ + validateBodyForCategory( + body: AssignBadgeBody, + category: BadgeCategory + ): boolean { + switch (category) { + case BadgeCategory.academy: + return !!(body.userId && body.courseId); + case BadgeCategory.project: + return !!(body.userId && body.projectId); + + default: + return false; + } + } + + /** + * Gets the required role for a specific badge category + * @param category - Badge category + * @returns Required role or null if no role required + */ + getRequiredRoleForCategory(category: BadgeCategory): string | null { + const strategy = BadgeStrategyFactory.createStrategy(category); + return strategy.getRequiredRole(); + } + + /** + * Gets the required role for a badge assignment based on body data + * @param body - Badge assignment data + * @returns Required role or null if no role required + */ + getRequiredRoleForAssignment(body: AssignBadgeBody): string | null { + const category = this.determineBadgeCategory(body); + if (!category) { + return null; + } + return this.getRequiredRoleForCategory(category); + } + + /** + * Checks if a user has the required role for a badge assignment + * @param body - Badge assignment data + * @param userRole - User's role + * @returns true if user has required role + */ + hasRequiredRole(body: AssignBadgeBody, roles: string[]): boolean { + const requiredRole = this.getRequiredRoleForAssignment(body); + if (!requiredRole) { + return true; // No role required + } + return roles.includes(requiredRole); + } +} + +// Singleton instance of the service +export const badgeAssignmentService = new BadgeAssignmentService(); diff --git a/server/services/badgeStrategy.ts b/server/services/badgeStrategy.ts new file mode 100644 index 00000000000..8e0f619a5cf --- /dev/null +++ b/server/services/badgeStrategy.ts @@ -0,0 +1,121 @@ +import { AssignBadgeBody, AssignBadgeResult, BadgeCategory } from "./badge"; + +/** + * Strategy interface for badge assignment + */ +export interface BadgeAssignmentStrategy { + assignBadge(body: AssignBadgeBody, awardedBy?: string): Promise; + getRequiredRole(): string | null; +} + +/** + * Strategy for Academy badges + */ +export class AcademyBadgeStrategy implements BadgeAssignmentStrategy { + async assignBadge(body: AssignBadgeBody, awardedBy?: string): Promise { + // Import the existing academy badge logic + const { assignBadgeAcademy } = await import("./badge"); + + // Use the existing service + return await assignBadgeAcademy(body); + } + + getRequiredRole(): string | null { + // Academy badges can be assigned by any authenticated user + return null; + } +} +/** + * Strategy for Project badges + */ +export class ProjectBadgeStrategy implements BadgeAssignmentStrategy { + async assignBadge(body: AssignBadgeBody, awardedBy?: string): Promise { + // Import the existing project badge logic + const { assignBadgeProject } = await import("./project-badge"); + + // Use the existing service with provided awardedBy or "system" as fallback + return await assignBadgeProject(body, awardedBy || "system"); + } + + getRequiredRole(): string | null { + // Project badges require hackathon_judge role + return "badge_admin"; + } +} + +/** + * Strategy for Social badges + */ +export class BadgeByRequirementStrategy implements BadgeAssignmentStrategy { + async assignBadge(body: AssignBadgeBody, awardedBy?: string): Promise { + // Import the social badge logic + const { assignBadgeByRequirement } = await import("./socialBadge"); + + // Validate that requirementId is provided + if (!body.requirementId) { + return { + success: false, + message: "Requirement ID is required for social badges", + badge_id: "", + user_id: body.userId, + badges: [], + }; + } + + // Assign social badges based on requirement + const result = await assignBadgeByRequirement( + body.userId, + body.requirementId, + awardedBy || "system" + ); + + return { + success: result.success, + message: result.message, + badge_id: result.badges.length > 0 ? result.badges[0].name : "", + user_id: body.userId, + badges: result.badges, + }; + } + + getRequiredRole(): string | null { + return null; + } +} + +/** + * Factory to create badge assignment strategies + */ +export class BadgeStrategyFactory { + public static createStrategy(category: BadgeCategory): BadgeAssignmentStrategy { + switch (category) { + case BadgeCategory.academy: + return new AcademyBadgeStrategy(); + case BadgeCategory.project: + return new ProjectBadgeStrategy(); + case BadgeCategory.requirement: + return new BadgeByRequirementStrategy(); + default: + throw new Error(`Unsupported badge category: ${category}`); + } + } +} + +/** + * Main context that uses the Strategy pattern + */ +export class BadgeAssignmentContext { + private strategy: BadgeAssignmentStrategy; + + constructor(strategy: BadgeAssignmentStrategy) { + this.strategy = strategy; + } + + setStrategy(strategy: BadgeAssignmentStrategy): void { + this.strategy = strategy; + } + + async assignBadge(body: AssignBadgeBody, awardedBy?: string): Promise { + return await this.strategy.assignBadge(body, awardedBy); + } +} diff --git a/server/services/exportShowcase.ts b/server/services/exportShowcase.ts new file mode 100644 index 00000000000..9299d7e9a0e --- /dev/null +++ b/server/services/exportShowcase.ts @@ -0,0 +1,255 @@ +import { prisma } from "@/prisma/prisma"; +import { Prisma } from "@prisma/client"; + +import ExcelJS from 'exceljs'; + +interface ProjectExport { + project_name: string; + short_description: string; + full_description: string; + tech_stack: string; + github_repository: string; + demo_link: string; + demo_video_link: string; + tracks: string; + tags: string; + members: string; + prizes: string; + hackathon: string; +} + +type ExportShowcaseFilters = { + event?: string; + track?: string; + search?: string; + winningProjects?: boolean; +}; + +export async function exportShowcase(rawFilters: unknown) { + const filters = normalizeFilters(rawFilters); + const where = buildProjectWhere(filters); + + const projects = await prisma.project.findMany({ + include: { + members: true, + hackathon: true, + prizes: true, + }, + where, + }); + + if (!projects.length) { + return null; + } + + const projectsExport: ProjectExport[] = projects.map((project) => ({ + project_name: project.project_name, + short_description: project.short_description, + full_description: project.full_description ?? '', + tech_stack: project.tech_stack ?? '', + github_repository: project.github_repository ?? '', + demo_link: project.demo_link ?? '', + demo_video_link: project.demo_video_link ?? '', + tracks: (project.tracks ?? []).join(', '), + tags: (project.tags ?? []).join(', '), + members: project.members + .map((member) => member.email ?? member.user_id ?? '') + .filter(Boolean) + .join(', '), + prizes: project.prizes.map((prize) => prize.prize).join(', '), + hackathon: project.hackathon?.title ?? '', + })); + const buffer = await createWorkbook(projectsExport); + return buffer; +} + +function normalizeFilters(body: unknown): ExportShowcaseFilters { + if (!body || typeof body !== 'object') { + return {}; + } + + const filters = body as Record; + + return { + event: typeof filters.event === 'string' ? filters.event : undefined, + track: typeof filters.track === 'string' ? filters.track : undefined, + search: typeof filters.search === 'string' ? filters.search : undefined, + winningProjects: parseBoolean(filters.winningProjects ?? filters.winningProjecs), + }; +} + +function parseBoolean(value: unknown): boolean | undefined { + if (typeof value === 'boolean') { + return value; + } + + if (typeof value === 'string') { + const lowered = value.trim().toLowerCase(); + if (lowered === 'true') { + return true; + } + if (lowered === 'false') { + return false; + } + } + + return undefined; +} + +function buildProjectWhere(filters: ExportShowcaseFilters): Prisma.ProjectWhereInput { + const where: Prisma.ProjectWhereInput = {}; + + if (filters.event) { + where.hackaton_id = filters.event; + } + + if (filters.track) { + where.tracks = { + has: filters.track, + }; + } + + if (filters.winningProjects) { + where.is_winner = true; + } + + if (filters.search) { + const searchTerms = filters.search + .split(/\s+/) + .map((term) => term.trim()) + .filter((term) => term.length > 0); + + if (searchTerms.length > 0) { + const orConditions: Prisma.ProjectWhereInput[] = []; + + searchTerms.forEach((term) => { + orConditions.push( + { + project_name: { + contains: term, + mode: 'insensitive', + }, + }, + { + full_description: { + contains: term, + mode: 'insensitive', + }, + } + ); + }); + + orConditions.push({ + tracks: { + has: filters.search, + }, + }); + + where.OR = orConditions; + } + } + + return where; +} + + async function createWorkbook(projects: ProjectExport[]) { + const workbook = new ExcelJS.Workbook(); + const worksheet = workbook.addWorksheet('Projects'); + worksheet.columns = [ + { header: 'Project Name', key: 'project_name', width: 25 }, + { header: 'Short Description', key: 'short_description', width: 35 }, + { header: 'Full Description', key: 'full_description', width: 50 }, + { header: 'Tech Stack', key: 'tech_stack', width: 30 }, + { header: 'Github Repository', key: 'github_repository', width: 40 }, + { header: 'Demo Link', key: 'demo_link', width: 40 }, + { header: 'Demo Video Link', key: 'demo_video_link', width: 40 }, + { header: 'Tracks', key: 'tracks', width: 25 }, + { header: 'Tags', key: 'tags', width: 25 }, + { header: 'Members', key: 'members', width: 35 }, + { header: 'Prizes', key: 'prizes', width: 30 }, + { header: 'Hackathon', key: 'hackathon', width: 25 }, + ]; + + projects.forEach(project => { + worksheet.addRow({ + project_name: project.project_name, + short_description: project.short_description, + full_description: project.full_description, + tech_stack: project.tech_stack, + github_repository: project.github_repository, + demo_link: project.demo_link, + demo_video_link: project.demo_video_link, + tracks: project.tracks, + tags: project.tags, + members: project.members, + prizes: project.prizes, + hackathon: project.hackathon, + }); + }); + const headerRow = worksheet.getRow(1); + headerRow.height = 25; + + headerRow.eachCell((cell) => { + cell.fill = { + type: 'pattern', + pattern: 'solid', + fgColor: { argb: 'FFEF4444' } + }; + cell.font = { + name: 'Arial', + size: 11, + bold: true, + color: { argb: 'FFFFFFFF' } + }; + cell.alignment = { + vertical: 'middle', + horizontal: 'left', + wrapText: false + }; + cell.border = { + top: { style: 'thin', color: { argb: 'FFD1D5DB' } }, + left: { style: 'thin', color: { argb: 'FFD1D5DB' } }, + bottom: { style: 'thin', color: { argb: 'FFD1D5DB' } }, + right: { style: 'thin', color: { argb: 'FFD1D5DB' } } + }; + }); + + worksheet.eachRow((row, rowNumber) => { + if (rowNumber > 1) { + row.eachCell((cell) => { + cell.alignment = { + vertical: 'top', + horizontal: 'left', + wrapText: true + }; + cell.border = { + top: { style: 'thin', color: { argb: 'FFE5E7EB' } }, + left: { style: 'thin', color: { argb: 'FFE5E7EB' } }, + bottom: { style: 'thin', color: { argb: 'FFE5E7EB' } }, + right: { style: 'thin', color: { argb: 'FFE5E7EB' } } + }; + }); + + if (rowNumber % 2 === 0) { + row.eachCell((cell) => { + cell.fill = { + type: 'pattern', + pattern: 'solid', + fgColor: { argb: 'FFF9FAFB' } + }; + }); + } + } + }); + + worksheet.autoFilter = { + from: { row: 1, column: 1 }, + to: { row: 1, column: worksheet.columns.length } + }; + + worksheet.views = [ + { state: 'frozen', xSplit: 0, ySplit: 1 } + ]; + const buffer = await workbook.xlsx.writeBuffer(); + return buffer; +} \ No newline at end of file diff --git a/server/services/getRegisterFormByUser.ts b/server/services/getRegisterFormByUser.ts new file mode 100644 index 00000000000..296ecea2935 --- /dev/null +++ b/server/services/getRegisterFormByUser.ts @@ -0,0 +1,6 @@ +import { prisma } from "@/prisma/prisma"; + +export async function getRegisterFormByUserId(userId:string){ + + const registerForm = await prisma.registerForm.findFirst({}) +} \ No newline at end of file diff --git a/server/services/inviteProjectMember.ts b/server/services/inviteProjectMember.ts index e386a76d38c..c766a1456da 100644 --- a/server/services/inviteProjectMember.ts +++ b/server/services/inviteProjectMember.ts @@ -1,12 +1,14 @@ import { prisma } from "@/prisma/prisma"; import { sendInvitation } from "./SendInvitationProjectMember"; import { getUserByEmail } from "./getUser"; +import { Prisma } from "@prisma/client"; interface InvitationResult { Success: boolean; Error?: string; InviteLinks?: invitationLink[]; } + interface invitationLink { User: string; Invitation: string; @@ -23,11 +25,14 @@ export async function generateInvitation( throw new Error("Hackathon ID is required"); } + // Remove duplicate emails to prevent multiple invitations to the same user + const uniqueEmails = [...new Set(emails)]; + const project = await createProject(hackathonId, userId); const invitationLinks: invitationLink[] = []; - for (const email of emails) { + for (const email of uniqueEmails) { const invitationLink = await handleEmailInvitation( email, userId, @@ -39,6 +44,7 @@ export async function generateInvitation( invitationLinks.push(invitationLink); } } + return { Success: invitationLinks.every((link) => link.Success), InviteLinks: invitationLinks, @@ -58,22 +64,18 @@ async function handleEmailInvitation( return; } - const existingMember = await findExistingMember( + // Use atomic upsert to prevent race conditions and duplicate members + const member = await createOrUpdateMemberAtomically( invitedUser, email, project.id ); - if (isConfirmedMember(existingMember)) { + // Skip if member is already confirmed (no need to send invitation again) + if (member.status === "Confirmed") { return; } - const member = await createOrUpdateMember( - invitedUser, - email, - project.id, - existingMember - ); const inviteLink = await sendInvitationEmail( member, email, @@ -81,6 +83,7 @@ async function handleEmailInvitation( hackathonId, inviterName ); + if (inviteLink) { const invitationLink = { User: email, @@ -95,72 +98,46 @@ function isSelfInvitation(invitedUser: any, userId: string): boolean { return invitedUser?.id === userId; } -async function findExistingMember( +/** + * Atomic operation to create or update member using transaction to prevent race conditions + * Since there's no unique constraint at DB level, we use a transaction-based approach + */ +async function createOrUpdateMemberAtomically( invitedUser: any, email: string, projectId: string ) { - if (invitedUser) { - const member = await prisma.member.findFirst({ + return await prisma.$transaction(async (tx: Prisma.TransactionClient) => { + // First, try to find existing member within transaction + const existingMember = await tx.member.findFirst({ where: { - user_id: invitedUser?.id, + email, project_id: projectId, }, }); - return member; - } - const member = await prisma.member.findFirst({ - where: { - email, - project_id: projectId, - }, - }); - - return member; -} - -function isConfirmedMember(member: any): boolean { - return member?.status === "Confirmed"; -} - -async function createOrUpdateMember( - invitedUser: any, - email: string, - projectId: string, - existingMember: any -) { - if (existingMember) { - return updateExistingMember(existingMember, invitedUser); - } - - return createNewMember(invitedUser, email, projectId); -} - -async function updateExistingMember(existingMember: any, invitedUser: any) { - return prisma.member.update({ - where: { id: existingMember.id }, - data: { - role: "Member", - status: "Pending Confirmation", - ...(invitedUser ? { user_id: invitedUser.id } : {}), - }, - }); -} - -async function createNewMember( - invitedUser: any, - email: string, - projectId: string -) { - return prisma.member.create({ - data: { - user_id: invitedUser?.id, - project_id: projectId, - role: "Member", - status: "Pending Confirmation", - email: email, - }, + if (existingMember) { + // Update existing member + return await tx.member.update({ + where: { id: existingMember.id }, + data: { + role: "Member", + status: "Pending Confirmation", + ...(invitedUser ? { user_id: invitedUser.id } : {}), + }, + }); + } else { + // Create new member + return await tx.member.create({ + data: { + user_id: invitedUser?.id, + project_id: projectId, + role: "Member", + status: "Pending Confirmation", + email: email, + }, + }); + } }); } @@ -183,9 +160,9 @@ async function sendInvitationEmail( } async function createProject(hackathonId: string, userId: string) { - // Atomic transaction to prevent race conditions during invitations + // Atomic transaction to prevent race conditions during invitations return await prisma.$transaction( - async (tx) => { + async (tx: Prisma.TransactionClient) => { // Find existing project WITHIN transaction const existingProject = await tx.project.findFirst({ where: { @@ -248,4 +225,4 @@ async function createProject(hackathonId: string, userId: string) { timeout: 10000, // Maximum 10 seconds executing transaction } ); -} +} \ No newline at end of file diff --git a/server/services/project-badge.ts b/server/services/project-badge.ts new file mode 100644 index 00000000000..09e5937e884 --- /dev/null +++ b/server/services/project-badge.ts @@ -0,0 +1,400 @@ +import { prisma } from "@/prisma/prisma"; +import { + AssignBadgeBody, + AssignBadgeResult, + BadgeData, + getBadgesByHackathonId, + getBadgesByIds, + validateBadge, +} from "./badge"; +import { + Badge, + BadgeAwardStatus, + ProjectBadge, + Requirement, + UserBadge, +} from "@/types/badge"; + +export async function assignBadgeProject( + body: AssignBadgeBody, + awarded_by: string +): Promise { + let badgesHackathon: Badge[] = []; + let isValidateRequirements = true; + if (body.badgesId && body.badgesId.length > 0) { + isValidateRequirements = false; + const badges = await getBadgesByIds(body.badgesId!); + badgesHackathon = badges; + } else { + badgesHackathon = await getBadgesByHackathonId(body.hackathonId!); + } + + let badgeToReturn: AssignBadgeResult = { + success: false, + message: "No results", + badge_id: "", + user_id: "", + badges: [], + }; + + if (!badgesHackathon) { + return badgeToReturn; + } + + const userProject = await prisma.project.findUnique({ + where: { + id: body.projectId, + members: { + some: { + status: "Confirmed", + }, + }, + }, + include: { + members: { + where: { + status: "Confirmed", + user_id: { + not: null, + }, + }, + }, + }, + }); + + if (!userProject) { + return badgeToReturn; + } + + const userProjectMembers = userProject.members; + + try { + const result = await prisma.$transaction(async (tx) => { + const awardedBadges: BadgeData[] = []; + + for (const badge of badgesHackathon) { + for (const member of userProjectMembers) { + const modifiedBody: AssignBadgeBody = { + ...body, + userId: member.user_id!, + }; + + const userBadgeResult = await awardBadgeUserWithTransaction( + modifiedBody, + awarded_by, + badge, + tx, + isValidateRequirements + ); + + if (userBadgeResult.success && userBadgeResult.badges) { + awardedBadges.push(...userBadgeResult.badges); + } + } + + const projectBadgeResult = await awardBadgeProjectWithTransaction( + body, + awarded_by, + badge, + tx + ); + + if (projectBadgeResult.success && projectBadgeResult.badges) { + awardedBadges.push(...projectBadgeResult.badges); + } + } + + return { + success: true, + message: "Badges assigned successfully", + badge_id: badgesHackathon[0]?.id || "", + user_id: body.userId, + badges: awardedBadges, + }; + }); + + return result; + } catch (error) { + console.error("Error in transaction:", error); + + return { + success: false, + message: `Transaction failed: ${ + error instanceof Error ? error.message : "Unknown error" + }`, + badge_id: "", + user_id: "", + badges: [], + }; + } +} + +async function awardBadgeUserWithTransaction( + body: AssignBadgeBody, + awarded_by: string, + badge: Badge, + tx: any, + validateRequirements: boolean = true +): Promise { + try { + const isBadgeAlreadyAwarded = await validateBadge(badge.id, body.userId); + + if (isBadgeAlreadyAwarded) { + return { + success: false, + message: "Badge already awarded", + badge_id: badge.id, + user_id: body.userId, + badges: [], + }; + } + + const badgeRequirements = badge.requirements; + const existingUserBadge = await tx.userBadge.findUnique({ + where: { + user_id_badge_id: { + user_id: body.userId, + badge_id: badge.id, + }, + }, + }); + + let completedRequirements: Requirement[] = []; + let badgeStatus = BadgeAwardStatus.pending; + let awardedBadges: BadgeData[] = []; + + if (!validateRequirements) { + completedRequirements = badgeRequirements || []; + badgeStatus = BadgeAwardStatus.approved; + awardedBadges.push({ + name: badge.name, + image_path: badge.image_path as string, + completed_requirement: badgeRequirements?.[0] || ({} as Requirement), + }); + } else { + completedRequirements = + (existingUserBadge?.evidence as Requirement[]) || []; + const currentRequirement = badgeRequirements?.find( + (req: any) => req.hackathon === body.hackathonId + ); + + if ( + currentRequirement && + !completedRequirements.some( + (req: any) => req.id == currentRequirement.id + ) + ) { + completedRequirements.push(currentRequirement); + } + + const allRequirementsCompleted = badgeRequirements?.every((req: any) => + completedRequirements.some((completed: any) => completed.id == req.id) + ); + + const someRequirementsCompleted = completedRequirements.length > 0; + + if (allRequirementsCompleted) { + badgeStatus = BadgeAwardStatus.approved; + awardedBadges.push({ + name: badge.name, + image_path: badge.image_path as string, + completed_requirement: currentRequirement!, + }); + } else if (someRequirementsCompleted) { + badgeStatus = BadgeAwardStatus.pending; + } + } + + if (completedRequirements.length > 0 || !validateRequirements) { + await tx.userBadge.upsert({ + where: { + user_id_badge_id: { + user_id: body.userId, + badge_id: badge.id, + }, + }, + update: { + awarded_at: + badgeStatus == BadgeAwardStatus.approved + ? new Date() + : existingUserBadge?.awarded_at, + awarded_by: awarded_by, + status: badgeStatus, + requirements_version: 1, + evidence: completedRequirements, + }, + create: { + user_id: body.userId, + badge_id: badge.id, + awarded_at: + badgeStatus == BadgeAwardStatus.approved ? new Date() : undefined, + awarded_by: awarded_by, + status: badgeStatus, + requirements_version: 1, + evidence: completedRequirements, + }, + }); + } + + return { + success: true, + message: "User badge assigned successfully", + badge_id: badge.id, + user_id: body.userId, + badges: awardedBadges, + }; + } catch (error) { + console.error("Error in awardBadgeUserWithTransaction:", error); + throw error; // Re-lanzar para que la transacción haga rollback + } +} + +async function awardBadgeProjectWithTransaction( + body: AssignBadgeBody, + awarded_by: string, + badge: Badge, + tx: any +): Promise { + try { + const existingProjectBadge = await tx.projectBadge.findUnique({ + where: { + project_id_badge_id: { + project_id: body.projectId!, + badge_id: badge.id, + }, + }, + }); + + const completedRequirements = + (existingProjectBadge?.evidence as Requirement[]) || []; + const currentRequirement = badge.requirements?.find( + (req: any) => req.hackathon_id === body.hackathonId + ); + + if ( + currentRequirement && + !completedRequirements.some((req: any) => req.id == currentRequirement.id) + ) { + completedRequirements.push(currentRequirement); + } + + const allRequirementsCompleted = badge.requirements?.every((req: any) => + completedRequirements.some((completed: any) => completed.id == req.id) + ); + + const someRequirementsCompleted = completedRequirements.length > 0; + let badgeStatus = BadgeAwardStatus.pending; + let awardedBadges: BadgeData[] = []; + + if (allRequirementsCompleted) { + badgeStatus = BadgeAwardStatus.approved; + awardedBadges.push({ + name: badge.name, + image_path: badge.image_path as string, + completed_requirement: currentRequirement!, + }); + } else if (someRequirementsCompleted) { + badgeStatus = BadgeAwardStatus.pending; + } + + await tx.projectBadge.upsert({ + where: { + project_id_badge_id: { + project_id: body.projectId!, + badge_id: badge.id, + }, + }, + update: { + awarded_at: + badgeStatus == BadgeAwardStatus.approved + ? new Date() + : existingProjectBadge?.awarded_at, + awarded_by: awarded_by, + status: badgeStatus, + requirements_version: 1, + evidence: completedRequirements, + }, + create: { + project_id: body.projectId!, + badge_id: badge.id, + awarded_at: + badgeStatus == BadgeAwardStatus.approved ? new Date() : undefined, + awarded_by: awarded_by, + status: badgeStatus, + requirements_version: 1, + + evidence: completedRequirements, + }, + }); + + return { + success: true, + message: "Project badge assigned successfully", + badge_id: badge.id, + user_id: body.userId, + badges: awardedBadges, + }; + } catch (error) { + console.error("Error in awardBadgeProjectWithTransaction:", error); + throw error; // Re-lanzar para que la transacción haga rollback + } +} + +export async function getProjectBadges( + projectId: string +): Promise { + const projectBadges = await prisma.projectBadge.findMany({ + where: { + project_id: projectId, + }, + include: { + badge: true, + }, + }); + const badges = projectBadges.map((badge) => ({ + ...badge, + name: badge.badge.name, + image_path: badge.badge.image_path, + })); + + return badges as unknown as ProjectBadge[]; +} + +export async function getUserBadgesByProjectId( + projectId: string +): Promise { + const project = await prisma.project.findUnique({ + where: { + id: projectId, + members: { + some: { + status: "Confirmed", + }, + }, + }, + include: { + members: true, + }, + }); + + const userBadges = await prisma.userBadge.findMany({ + where: { + user_id: { + in: project?.members + .map((member) => member.user_id) + .filter((id): id is string => id !== null && id !== undefined), + }, + }, + include: { + badge: true, + }, + }); + + const badgesReturn = userBadges.map((badge) => ({ + ...badge, + name: badge.badge.name, + image_path: badge.badge.image_path, + })); + + return badgesReturn as unknown as UserBadge[]; +} diff --git a/server/services/projects.ts b/server/services/projects.ts index 1dd4832e855..29a0ab87ddc 100644 --- a/server/services/projects.ts +++ b/server/services/projects.ts @@ -44,9 +44,9 @@ export const getFilteredProjects = async (options: GetProjectOptions) => { has: options.track, }; } - // if (options.winningProjects) { - // filters.winningProjects = true - // } + if (options.winningProjects) { + filters.is_winner = true + } if (options.search) { const searchWords = options.search.split(/\s+/); let searchFilters: any[] = []; diff --git a/server/services/rewardBoard.ts b/server/services/rewardBoard.ts index 932034ac3e6..fd13c1197f4 100644 --- a/server/services/rewardBoard.ts +++ b/server/services/rewardBoard.ts @@ -1,14 +1,18 @@ import { prisma } from "@/prisma/prisma"; -import { UserBadge, BadgeMetadata, Badge } from "@/types/badge"; +import { UserBadge, Requirement, Badge } from "@/types/badge"; import { JsonValue } from "@prisma/client/runtime/library"; // Utility function to safely convert JSON metadata -function parseBadgeMetadata(metadata: JsonValue): BadgeMetadata | null { - const metadataObject = metadata as BadgeMetadata; +export function parseBadgeMetadata(metadata: JsonValue): Requirement | null { + const metadataObject = metadata as Requirement; const toReturn = { course_id: metadataObject.course_id || undefined, hackathon: metadataObject.hackathon || null, type: metadataObject.type || undefined, + // points: metadataObject.points || undefined, // COMMENTED OUT: Points feature disabled + description: metadataObject.description || undefined, + id: metadataObject.id || "", + unlocked: false, }; return toReturn; } @@ -21,51 +25,59 @@ export async function getRewardBoard(user_id: string): Promise { include: { badge: true, }, + orderBy: { + badge_id: "desc", + }, }); + let badges = userBadges.map((userBadge) => { + const parsedRequirements = userBadge.badge.requirements.map((requirement) => parseBadgeMetadata(requirement)) as Requirement[]; - // Map the result to the UserBadge type, flattening the badge fields - return userBadges.map((userBadge) => ({ - user_id: userBadge.user_id, - badge_id: userBadge.badge_id, - awarded_at: userBadge.awarded_at, - awarded_by: userBadge.awarded_by, - name: userBadge.badge.name, - description: userBadge.badge.description, - points: (userBadge.badge as any).points || 0, - image_path: userBadge.badge.image_path, - category: userBadge.badge.category, - metadata: parseBadgeMetadata((userBadge.badge as any).metadata || null), - })); -} + if (Array.isArray(userBadge.evidence)) { + const evidenceArray = userBadge.evidence as Requirement[]; + parsedRequirements.forEach((requirement) => { + const isInEvidence = evidenceArray.some((evidenceItem: any) => + evidenceItem && evidenceItem.id === requirement.id + ); + if (isInEvidence) { + requirement.unlocked = true; + } + }); + } -export async function getBadgeByCourseId(courseId: string): Promise { - const badges = await prisma.badge.findMany(); - const badge = badges.find((b: any) => { - if (!b.metadata) return false; - const metadata = b.metadata as any; - return metadata.course_id === courseId; + return { + user_id: userBadge.user_id, + badge_id: userBadge.badge_id, + awarded_at: userBadge.awarded_at, + awarded_by: userBadge.awarded_by, + name: userBadge.badge.name, + description: userBadge.badge.description, + // points: 0, // COMMENTED OUT: Points calculation disabled + image_path: userBadge.badge.image_path, + category: userBadge.badge.category, + evidence: userBadge.evidence, + requirements: parsedRequirements, + status: userBadge.status, + requirements_version: userBadge.requirements_version, + }; }); - /*const badge = await prisma.badge.findFirst({ - where: { - metadata: { - path: ['course_id'], - equals: courseId, - }, - }, - });*/ +// COMMENTED OUT: Points calculation disabled +// badges.forEach((badge) => { +// if (Array.isArray(badge.evidence)) { +// badge.points = badge.evidence.reduce( +// (acc: number, requirement: any) => { +// if (requirement && typeof requirement.points !== "undefined" && requirement.points !== null) { +// return acc + parseInt(requirement.points.toString(), 10); +// } +// return acc; +// }, +// 0 +// ); +// } else { +// badge.points = 0; +// } +// }); - if (!badge) { - throw new Error(`Badge not found for course ID: ${courseId}`); - } - - return { - id: badge.id, - name: badge.name, - description: badge.description, - points: (badge as any).points || 0, - image_path: badge.image_path, - category: badge.category, - metadata: parseBadgeMetadata((badge as any).metadata || null), - }; + return badges as unknown as UserBadge[]; } + diff --git a/server/services/set-project-winner.ts b/server/services/set-project-winner.ts new file mode 100644 index 00000000000..51040ef1715 --- /dev/null +++ b/server/services/set-project-winner.ts @@ -0,0 +1,36 @@ +import { prisma } from "@/prisma/prisma"; +import { badgeAssignmentService } from "./badgeAssignmentService"; +import { AssignBadgeResult, BadgeCategory } from "./badge"; + +export async function SetWinner( + project_id: string, + isWinner: boolean, + awardedBy: string +) { + + const project = await prisma.project.update({ + where: { id: project_id }, + data: { is_winner: isWinner }, + }); + const body = { + projectId: project_id, + userId: "", + hackathonId: project.hackaton_id, + awardedBy: awardedBy, + category: BadgeCategory.project, + }; + let badge: AssignBadgeResult = { + success: false, + message: "No badges assigned", + badge_id: "", + user_id: "", + badges: [], + }; + + if (isWinner===true) { + + badge = await badgeAssignmentService.assignBadge(body, awardedBy); + } + + return badge; +} diff --git a/server/services/socialBadge.ts b/server/services/socialBadge.ts new file mode 100644 index 00000000000..24e5b12d676 --- /dev/null +++ b/server/services/socialBadge.ts @@ -0,0 +1,158 @@ +import { prisma } from "@/prisma/prisma"; +import { Badge, BadgeAwardStatus, Requirement } from "@/types/badge"; +import { parseBadgeMetadata } from "./rewardBoard"; + +/** + * Assigns social badges based on a specific requirement + * @param userId - ID of the user + * @param requirementId - ID of the requirement to fulfill + * @param awardedBy - Who is awarding the badge (optional) + */ +export async function assignBadgeByRequirement( + userId: string, + requirementId: string, + awardedBy: string = "system" +): Promise<{ success: boolean; message: string; badges: any[] }> { + try { + // Find badges that have this specific requirement + const badges = await getBadgesByRequirementId(requirementId); + + if (!badges || badges.length === 0) { + return { + success: false, + message: `No social badges found for requirement: ${requirementId}`, + badges: [] + }; + } + + const awardedBadges: any[] = []; + + for (const badge of badges) { + // Check if the user already has this badge + const existingUserBadge = await prisma.userBadge.findUnique({ + where: { + user_id_badge_id: { + user_id: userId, + badge_id: badge.id, + }, + }, + }); + + // If user already has the badge, skip it + if (existingUserBadge) { + continue; + } + + // Find the specific requirement that was fulfilled + const fulfilledRequirement = badge.requirements?.find((req: any) => req.id === requirementId); + + // Assign the badge to the user + await prisma.userBadge.create({ + data: { + user_id: userId, + badge_id: badge.id, + awarded_at: new Date(), + awarded_by: awardedBy, + status: BadgeAwardStatus.approved, + requirements_version: 1, + + evidence: fulfilledRequirement ? [fulfilledRequirement] : [], + }, + }); + + awardedBadges.push({ + name: badge.name, + image_path: badge.image_path, + completed_requirement: fulfilledRequirement + }); + } + + return { + success: true, + message: `Successfully assigned ${awardedBadges.length} social badge(s) for requirement: ${requirementId}`, + badges: awardedBadges + }; + + } catch (error) { + console.error("Error assigning social badge by requirement:", error); + return { + success: false, + message: `Error assigning social badge: ${error instanceof Error ? error.message : 'Unknown error'}`, + badges: [] + }; + } +} + +/** + * Gets badges by requirement ID and category + * @param requirementId - ID of the requirement + * @returns Array of badges that have the specified requirement + */ +export async function getBadgesByRequirementId( + requirementId: string +): Promise { + // Get all badges and filter those that contain the requirementId + const allBadges = await prisma.badge.findMany(); + + const badges = allBadges.filter((badge) => + badge.requirements?.some((req: any) => req.id === requirementId) + ); + + if (badges.length === 0) { + return []; + } + + const badgesToReturn = badges.map((badge) => ({ + id: badge.id, + name: badge.name, + description: badge.description, + + image_path: badge.image_path, + category: badge.category, + requirements: badge.requirements?.map((requirement) => + parseBadgeMetadata(requirement) + ) as Requirement[] || [], + })); + + return badgesToReturn; +} + +/** + * Checks if a user has a specific social badge by requirement + * @param userId - User ID + * @param requirementId - Requirement ID + * @returns true if user has the badge, false otherwise + */ +export async function hasSocialBadgeByRequirement( + userId: string, + requirementId: string +): Promise { + try { + const badges = await getBadgesByRequirementId(requirementId); + + if (badges.length === 0) { + return false; + } + + // Check if user has any of the badges for this requirement + for (const badge of badges) { + const userBadge = await prisma.userBadge.findUnique({ + where: { + user_id_badge_id: { + user_id: userId, + badge_id: badge.id, + }, + }, + }); + + if (userBadge) { + return true; + } + } + + return false; + } catch (error) { + console.error("Error checking social badge by requirement:", error); + return false; + } +} diff --git a/server/services/userBadge.ts b/server/services/userBadge.ts new file mode 100644 index 00000000000..66726408d55 --- /dev/null +++ b/server/services/userBadge.ts @@ -0,0 +1,19 @@ +import { prisma } from "@/prisma/prisma"; +import { UserBadge } from "@/types/badge"; + +export async function getUserBadges(userId: string): Promise { + const userBadges = await prisma.userBadge.findMany({ + where: { + user_id: userId, + }, + include: { + badge: true, + }, + }); + const badges = userBadges.map((badge) => ({ + ...badge, + name: badge.badge.name, + image_path: badge.badge.image_path, + })); + return badges as unknown as UserBadge[]; +} \ No newline at end of file diff --git a/types/badge.ts b/types/badge.ts index 3fd2d7ad63f..671caf12639 100644 --- a/types/badge.ts +++ b/types/badge.ts @@ -1,19 +1,29 @@ -import { metadata } from '../app/(home)/academy/page'; - -export type BadgeMetadata = { +export enum BadgeAwardStatus { + pending, + approved, + revoked + } + +export type Requirement = { + id: string course_id?: string, hackathon?: 'won' | 'register' | 'submission' | null type?: 'course' | 'hackathon' + points?: number + description?: string + unlocked: boolean + } export type Badge = { id: string name: string description: string - points: number + points?: number image_path: string category: string - metadata: BadgeMetadata | null + requirements?: Requirement[] + is_unlocked?: boolean } export type UserBadge = { @@ -23,8 +33,24 @@ export type UserBadge = { awarded_by: string | null name: string description: string - points: number + // points: number // COMMENTED OUT: Points feature disabled image_path: string category: string - metadata: BadgeMetadata | null + requirements: Requirement[] | null + status?: BadgeAwardStatus + requirements_version?: number + evidence?: Requirement[] +} + +export type ProjectBadge={ + id: string + project_id: string + badge_id: string + awarded_at: Date + awarded_by: string | null + status: BadgeAwardStatus + requirements_version: number + name: string + image_path: string + evidence: Requirement[] } diff --git a/yarn.lock b/yarn.lock index 95355c7263d..7be5a440bec 100644 --- a/yarn.lock +++ b/yarn.lock @@ -250,7 +250,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz#010b6938fab7cb7df74aa2bbc06aa503b8fe5fb4" integrity sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q== -"@babel/runtime@^7.12.5", "@babel/runtime@^7.20.13", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": +"@babel/runtime@^7.12.5", "@babel/runtime@^7.17.8", "@babel/runtime@^7.20.13", "@babel/runtime@^7.26.0", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7": version "7.28.4" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.4.tgz#a70226016fabe25c5783b2f22d3e1c9bc5ca3326" integrity sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ== @@ -314,10 +314,20 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@date-fns/tz@^1.4.1": + version "1.4.1" + resolved "https://registry.yarnpkg.com/@date-fns/tz/-/tz-1.4.1.tgz#2d905f282304630e07bef6d02d2e7dbf3f0cc4e4" + integrity sha512-P5LUNhtbj6YfI3iJjw5EL9eUAG6OitD0W3fWQcpQjDRc/QIsL0tRNuO1PcDvPccWL1fSTXXdE1ds+l95DV/OFA== + +"@dimforge/rapier3d-compat@~0.12.0": + version "0.12.0" + resolved "https://registry.yarnpkg.com/@dimforge/rapier3d-compat/-/rapier3d-compat-0.12.0.tgz#7b3365e1dfdc5cd957b45afe920b4ac06c7cd389" + integrity sha512-uekIGetywIgopfD97oDL5PfeezkFpNhwlzlaEYNOA0N6ghdsOvh/HYjSMek5Q2O1PYvRSDFcqFVJl4r4ZBwOow== + "@emnapi/core@^1.5.0": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.7.0.tgz#135de4e8858763989112281bdf38ca02439db7c3" - integrity sha512-pJdKGq/1iquWYtv1RRSljZklxHCOCAJFJrImO5ZLKPJVJlVUcs8yFwNQlqS0Lo8xT1VAXXTCZocF9n26FWEKsw== + version "1.7.1" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.7.1.tgz#3a79a02dbc84f45884a1806ebb98e5746bdfaac4" + integrity sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg== dependencies: "@emnapi/wasi-threads" "1.1.0" tslib "^2.4.0" @@ -329,6 +339,13 @@ dependencies: tslib "^2.4.0" +"@emnapi/runtime@^1.7.0": + version "1.7.1" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.7.1.tgz#a73784e23f5d57287369c808197288b52276b791" + integrity sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA== + dependencies: + tslib "^2.4.0" + "@emnapi/wasi-threads@1.1.0", "@emnapi/wasi-threads@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" @@ -586,6 +603,31 @@ resolved "https://registry.yarnpkg.com/@ethereumjs/rlp/-/rlp-5.0.0.tgz#dd81b32b2237bc32fb1b54534f8ff246a6c89d9b" integrity sha512-WuS1l7GJmB0n0HsXLozCoEFc9IwYgf3l0gCkKVYgR67puVF1O4OpEaN0hWmm1c+iHUHFCKt1hJrvy5toLg+6ag== +"@fast-csv/format@4.3.5": + version "4.3.5" + resolved "https://registry.yarnpkg.com/@fast-csv/format/-/format-4.3.5.tgz#90d83d1b47b6aaf67be70d6118f84f3e12ee1ff3" + integrity sha512-8iRn6QF3I8Ak78lNAa+Gdl5MJJBM5vRHivFtMRUWINdevNo00K7OXxS2PshawLKTejVwieIlPmK5YlLu6w4u8A== + dependencies: + "@types/node" "^14.0.1" + lodash.escaperegexp "^4.1.2" + lodash.isboolean "^3.0.3" + lodash.isequal "^4.5.0" + lodash.isfunction "^3.0.9" + lodash.isnil "^4.0.0" + +"@fast-csv/parse@4.3.6": + version "4.3.6" + resolved "https://registry.yarnpkg.com/@fast-csv/parse/-/parse-4.3.6.tgz#ee47d0640ca0291034c7aa94039a744cfb019264" + integrity sha512-uRsLYksqpbDmWaSmzvJcuApSEe38+6NQZBUsuAyMZKqHxH0g1wcJgsKUvN3WC8tewaqFjBMMGrkHmC+T7k8LvA== + dependencies: + "@types/node" "^14.0.1" + lodash.escaperegexp "^4.1.2" + lodash.groupby "^4.6.0" + lodash.isfunction "^3.0.9" + lodash.isnil "^4.0.0" + lodash.isundefined "^3.0.1" + lodash.uniq "^4.5.0" + "@fastify/busboy@^2.0.0": version "2.1.1" resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-2.1.1.tgz#b9da6a878a371829a0502c9b6c1c143ef6663f4d" @@ -625,6 +667,13 @@ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c" integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ== +"@formatjs/intl-localematcher@^0.5.10": + version "0.5.10" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz#1e0bd3fc1332c1fe4540cfa28f07e9227b659a58" + integrity sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q== + dependencies: + tslib "2" + "@formatjs/intl-localematcher@^0.6.2": version "0.6.2" resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.6.2.tgz#e9ebe0b4082d7d48e5b2d753579fb7ece4eaefea" @@ -691,135 +740,147 @@ resolved "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz" integrity sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw== -"@img/sharp-darwin-arm64@0.34.4": - version "0.34.4" - resolved "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.4.tgz" - integrity sha512-sitdlPzDVyvmINUdJle3TNHl+AG9QcwiAMsXmccqsCOMZNIdW2/7S26w0LyU8euiLVzFBL3dXPwVCq/ODnf2vA== +"@img/sharp-darwin-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz#6e0732dcade126b6670af7aa17060b926835ea86" + integrity sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w== optionalDependencies: - "@img/sharp-libvips-darwin-arm64" "1.2.3" + "@img/sharp-libvips-darwin-arm64" "1.2.4" -"@img/sharp-darwin-x64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.4.tgz#0ba2bd9dbf07f7300fab73305b787e66156f7752" - integrity sha512-rZheupWIoa3+SOdF/IcUe1ah4ZDpKBGWcsPX6MT0lYniH9micvIU7HQkYTfrx5Xi8u+YqwLtxC/3vl8TQN6rMg== +"@img/sharp-darwin-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz#19bc1dd6eba6d5a96283498b9c9f401180ee9c7b" + integrity sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw== optionalDependencies: - "@img/sharp-libvips-darwin-x64" "1.2.3" + "@img/sharp-libvips-darwin-x64" "1.2.4" -"@img/sharp-libvips-darwin-arm64@1.2.3": - version "1.2.3" - resolved "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.3.tgz" - integrity sha512-QzWAKo7kpHxbuHqUC28DZ9pIKpSi2ts2OJnoIGI26+HMgq92ZZ4vk8iJd4XsxN+tYfNJxzH6W62X5eTcsBymHw== +"@img/sharp-libvips-darwin-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz#2894c0cb87d42276c3889942e8e2db517a492c43" + integrity sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g== -"@img/sharp-libvips-darwin-x64@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.3.tgz#c42ff786d4a1f42ef8929dba4a989dd5df6417f0" - integrity sha512-Ju+g2xn1E2AKO6YBhxjj+ACcsPQRHT0bhpglxcEf+3uyPY+/gL8veniKoo96335ZaPo03bdDXMv0t+BBFAbmRA== +"@img/sharp-libvips-darwin-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz#e63681f4539a94af9cd17246ed8881734386f8cc" + integrity sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg== -"@img/sharp-libvips-linux-arm64@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.3.tgz#c9073e5c4b629ee417f777db21c552910d84ed77" - integrity sha512-I4RxkXU90cpufazhGPyVujYwfIm9Nk1QDEmiIsaPwdnm013F7RIceaCc87kAH+oUB1ezqEvC6ga4m7MSlqsJvQ== +"@img/sharp-libvips-linux-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz#b1b288b36864b3bce545ad91fa6dadcf1a4ad318" + integrity sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw== -"@img/sharp-libvips-linux-arm@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.3.tgz#3cbc333fd6b8f224a14d69b03a1dd11df897c799" - integrity sha512-x1uE93lyP6wEwGvgAIV0gP6zmaL/a0tGzJs/BIDDG0zeBhMnuUPm7ptxGhUbcGs4okDJrk4nxgrmxpib9g6HpA== +"@img/sharp-libvips-linux-arm@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz#b9260dd1ebe6f9e3bdbcbdcac9d2ac125f35852d" + integrity sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A== -"@img/sharp-libvips-linux-ppc64@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.3.tgz#68e0e0076299f43d838468675674fabcc7161d16" - integrity sha512-Y2T7IsQvJLMCBM+pmPbM3bKT/yYJvVtLJGfCs4Sp95SjvnFIjynbjzsa7dY1fRJX45FTSfDksbTp6AGWudiyCg== +"@img/sharp-libvips-linux-ppc64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz#4b83ecf2a829057222b38848c7b022e7b4d07aa7" + integrity sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA== -"@img/sharp-libvips-linux-s390x@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.3.tgz#7da9ab11a50c0ca905979f0aae14a4ccffab27b2" - integrity sha512-RgWrs/gVU7f+K7P+KeHFaBAJlNkD1nIZuVXdQv6S+fNA6syCcoboNjsV2Pou7zNlVdNQoQUpQTk8SWDHUA3y/w== +"@img/sharp-libvips-linux-riscv64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz#880b4678009e5a2080af192332b00b0aaf8a48de" + integrity sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA== -"@img/sharp-libvips-linux-x64@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.3.tgz#3b162d6b190cf77926819040e09fb15eec42135e" - integrity sha512-3JU7LmR85K6bBiRzSUc/Ff9JBVIFVvq6bomKE0e63UXGeRw2HPVEjoJke1Yx+iU4rL7/7kUjES4dZ/81Qjhyxg== +"@img/sharp-libvips-linux-s390x@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz#74f343c8e10fad821b38f75ced30488939dc59ec" + integrity sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ== -"@img/sharp-libvips-linuxmusl-arm64@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.3.tgz#ac99576630dd8e33cb598d7c4586f6e0655912ea" - integrity sha512-F9q83RZ8yaCwENw1GieztSfj5msz7GGykG/BA+MOUefvER69K/ubgFHNeSyUu64amHIYKGDs4sRCMzXVj8sEyw== +"@img/sharp-libvips-linux-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz#df4183e8bd8410f7d61b66859a35edeab0a531ce" + integrity sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw== -"@img/sharp-libvips-linuxmusl-x64@1.2.3": - version "1.2.3" - resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.3.tgz#93e9495af7bf6c4e0d41dd71d0196c35c3753a1c" - integrity sha512-U5PUY5jbc45ANM6tSJpsgqmBF/VsL6LnxJmIf11kB7J5DctHgqm0SkuXzVWtIY90GnJxKnC/JT251TDnk1fu/g== +"@img/sharp-libvips-linuxmusl-arm64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz#c8d6b48211df67137541007ee8d1b7b1f8ca8e06" + integrity sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw== + +"@img/sharp-libvips-linuxmusl-x64@1.2.4": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz#be11c75bee5b080cbee31a153a8779448f919f75" + integrity sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg== + +"@img/sharp-linux-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz#7aa7764ef9c001f15e610546d42fce56911790cc" + integrity sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg== + optionalDependencies: + "@img/sharp-libvips-linux-arm64" "1.2.4" -"@img/sharp-linux-arm64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.4.tgz#0570ff1a4fa6e1d6779456fca8b5e8c18a6a9cf2" - integrity sha512-YXU1F/mN/Wu786tl72CyJjP/Ngl8mGHN1hST4BGl+hiW5jhCnV2uRVTNOcaYPs73NeT/H8Upm3y9582JVuZHrQ== +"@img/sharp-linux-arm@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz#5fb0c3695dd12522d39c3ff7a6bc816461780a0d" + integrity sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw== optionalDependencies: - "@img/sharp-libvips-linux-arm64" "1.2.3" + "@img/sharp-libvips-linux-arm" "1.2.4" -"@img/sharp-linux-arm@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.4.tgz#5f020d933f54f3fc49203d32c3b7dd0ec11ffcdb" - integrity sha512-Xyam4mlqM0KkTHYVSuc6wXRmM7LGN0P12li03jAnZ3EJWZqj83+hi8Y9UxZUbxsgsK1qOEwg7O0Bc0LjqQVtxA== +"@img/sharp-linux-ppc64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz#9c213a81520a20caf66978f3d4c07456ff2e0813" + integrity sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA== optionalDependencies: - "@img/sharp-libvips-linux-arm" "1.2.3" + "@img/sharp-libvips-linux-ppc64" "1.2.4" -"@img/sharp-linux-ppc64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.4.tgz#8d5775f6dc7e30ea3a1efa43798b7690bb5cb344" - integrity sha512-F4PDtF4Cy8L8hXA2p3TO6s4aDt93v+LKmpcYFLAVdkkD3hSxZzee0rh6/+94FpAynsuMpLX5h+LRsSG3rIciUQ== +"@img/sharp-linux-riscv64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz#cdd28182774eadbe04f62675a16aabbccb833f60" + integrity sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw== optionalDependencies: - "@img/sharp-libvips-linux-ppc64" "1.2.3" + "@img/sharp-libvips-linux-riscv64" "1.2.4" -"@img/sharp-linux-s390x@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.4.tgz#740aa5b369188ee2c1913b1015e7f830f4dfdb50" - integrity sha512-qVrZKE9Bsnzy+myf7lFKvng6bQzhNUAYcVORq2P7bDlvmF6u2sCmK2KyEQEBdYk+u3T01pVsPrkj943T1aJAsw== +"@img/sharp-linux-s390x@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz#93eac601b9f329bb27917e0e19098c722d630df7" + integrity sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg== optionalDependencies: - "@img/sharp-libvips-linux-s390x" "1.2.3" + "@img/sharp-libvips-linux-s390x" "1.2.4" -"@img/sharp-linux-x64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.4.tgz#573ce4196b2d0771bba32acc13a37b7adc9b6212" - integrity sha512-ZfGtcp2xS51iG79c6Vhw9CWqQC8l2Ot8dygxoDoIQPTat/Ov3qAa8qpxSrtAEAJW+UjTXc4yxCjNfxm4h6Xm2A== +"@img/sharp-linux-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz#55abc7cd754ffca5002b6c2b719abdfc846819a8" + integrity sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ== optionalDependencies: - "@img/sharp-libvips-linux-x64" "1.2.3" + "@img/sharp-libvips-linux-x64" "1.2.4" -"@img/sharp-linuxmusl-arm64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.4.tgz#3c91bc8348cc3b42b43c6fca14f9dbb5cb47bd0d" - integrity sha512-8hDVvW9eu4yHWnjaOOR8kHVrew1iIX+MUgwxSuH2XyYeNRtLUe4VNioSqbNkB7ZYQJj9rUTT4PyRscyk2PXFKA== +"@img/sharp-linuxmusl-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz#d6515ee971bb62f73001a4829b9d865a11b77086" + integrity sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg== optionalDependencies: - "@img/sharp-libvips-linuxmusl-arm64" "1.2.3" + "@img/sharp-libvips-linuxmusl-arm64" "1.2.4" -"@img/sharp-linuxmusl-x64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.4.tgz#33de7d476ac9e2db7ef654331b54cc679b806bda" - integrity sha512-lU0aA5L8QTlfKjpDCEFOZsTYGn3AEiO6db8W5aQDxj0nQkVrZWmN3ZP9sYKWJdtq3PWPhUNlqehWyXpYDcI9Sg== +"@img/sharp-linuxmusl-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz#d97978aec7c5212f999714f2f5b736457e12ee9f" + integrity sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q== optionalDependencies: - "@img/sharp-libvips-linuxmusl-x64" "1.2.3" + "@img/sharp-libvips-linuxmusl-x64" "1.2.4" -"@img/sharp-wasm32@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.4.tgz#d617f7b3f851f899802298f360667c20605c0198" - integrity sha512-33QL6ZO/qpRyG7woB/HUALz28WnTMI2W1jgX3Nu2bypqLIKx/QKMILLJzJjI+SIbvXdG9fUnmrxR7vbi1sTBeA== +"@img/sharp-wasm32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz#2f15803aa626f8c59dd7c9d0bbc766f1ab52cfa0" + integrity sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw== dependencies: - "@emnapi/runtime" "^1.5.0" + "@emnapi/runtime" "^1.7.0" -"@img/sharp-win32-arm64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.4.tgz#38e2c8a88826eac647f7c3f99efefb39897a8f5c" - integrity sha512-2Q250do/5WXTwxW3zjsEuMSv5sUU4Tq9VThWKlU2EYLm4MB7ZeMwF+SFJutldYODXF6jzc6YEOC+VfX0SZQPqA== +"@img/sharp-win32-arm64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz#3706e9e3ac35fddfc1c87f94e849f1b75307ce0a" + integrity sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g== -"@img/sharp-win32-ia32@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.4.tgz#003a7eb0fdaba600790c3007cfd756e41a9cf749" - integrity sha512-3ZeLue5V82dT92CNL6rsal6I2weKw1cYu+rGKm8fOCCtJTR2gYeUfY3FqUnIJsMUPIH68oS5jmZ0NiJ508YpEw== +"@img/sharp-win32-ia32@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz#0b71166599b049e032f085fb9263e02f4e4788de" + integrity sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg== -"@img/sharp-win32-x64@0.34.4": - version "0.34.4" - resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.4.tgz#b19f1f88ace8bfc20784a0ad31767f3438e025d1" - integrity sha512-xIyj4wpYs8J18sVN3mSQjwrw7fKUqRw+Z5rnHNCy5fYTxigBz81u5mOMPmFumwjcn8+ld1ppptMBCLic1nz6ig== +"@img/sharp-win32-x64@0.34.5": + version "0.34.5" + resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz#a81ffb00e69267cd0a1d626eaedb8a8430b2b2f8" + integrity sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw== "@isaacs/balanced-match@^4.0.1": version "4.0.1" @@ -913,6 +974,11 @@ dependencies: "@types/mdx" "^2.0.0" +"@mediapipe/tasks-vision@0.10.17": + version "0.10.17" + resolved "https://registry.yarnpkg.com/@mediapipe/tasks-vision/-/tasks-vision-0.10.17.tgz#2c1c73ed81902b21d37336a587b96183bb6882d5" + integrity sha512-CZWV/q6TTe8ta61cZXjfnnHsfWIdFhms03M9T7Cnd5y2mdpylJM0rF1qRq+wsQVRMLz1OYPVEBU9ph2Bx8cxrg== + "@mermaid-js/parser@^0.6.3": version "0.6.3" resolved "https://registry.yarnpkg.com/@mermaid-js/parser/-/parser-0.6.3.tgz#3ce92dad2c5d696d29e11e21109c66a7886c824e" @@ -927,6 +993,13 @@ dependencies: minimist "^1.1.0" +"@monogrid/gainmap-js@^3.0.6": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@monogrid/gainmap-js/-/gainmap-js-3.1.0.tgz#4ac1f88abd6affdf0b51d79318109183b499c502" + integrity sha512-Obb0/gEd/HReTlg8ttaYk+0m62gQJmCblMOjHSMHRrBP2zdfKMHLCRbh/6ex9fSUJMKdjjIEiohwkbGD3wj2Nw== + dependencies: + promise-worker-transferable "^1.0.4" + "@napi-rs/wasm-runtime@^1.0.7": version "1.0.7" resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-1.0.7.tgz#dcfea99a75f06209a235f3d941e3460a51e9b14c" @@ -1084,6 +1157,11 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== +"@orama/orama@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@orama/orama/-/orama-2.1.1.tgz#5242d1232dbda3d539a829653628ecc547fb4dc7" + integrity sha512-euTV/2kya290SNkl5m8e/H1na8iDygk74nNtl4E0YZNyYIrEMwE1JwamoroMKGZw2Uz+in/8gH3m1+2YfP0j1w== + "@orama/orama@^3.1.16": version "3.1.16" resolved "https://registry.yarnpkg.com/@orama/orama/-/orama-3.1.16.tgz#55fe28b17e5d8cc21a738694f6c3174bcae92c44" @@ -1183,7 +1261,7 @@ resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.3.tgz#e2dbc13bdc5e4168f4334f75832d7bdd3e2de5ba" integrity sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg== -"@radix-ui/react-accordion@^1.2.12": +"@radix-ui/react-accordion@^1.2.12", "@radix-ui/react-accordion@^1.2.2": version "1.2.12" resolved "https://registry.yarnpkg.com/@radix-ui/react-accordion/-/react-accordion-1.2.12.tgz#1fd70d4ef36018012b9e03324ff186de7a29c13f" integrity sha512-T4nygeh9YE9dLRPhAHSeOZi7HBXo+0kYIPJXayZfvWOWA0+n3dESrZbjfDPUABkUNym6Hd+f2IR113To8D2GPA== @@ -1249,7 +1327,7 @@ "@radix-ui/react-use-previous" "1.1.1" "@radix-ui/react-use-size" "1.1.1" -"@radix-ui/react-collapsible@1.1.12", "@radix-ui/react-collapsible@^1.1.12": +"@radix-ui/react-collapsible@1.1.12", "@radix-ui/react-collapsible@^1.1.12", "@radix-ui/react-collapsible@^1.1.2": version "1.1.12" resolved "https://registry.yarnpkg.com/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz#e2cc69a4490a2920f97c3c3150b0bf21281e3c49" integrity sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA== @@ -1295,7 +1373,7 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.2.tgz#61628ef269a433382c364f6f1e3788a6dc213a36" integrity sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA== -"@radix-ui/react-dialog@1.1.15", "@radix-ui/react-dialog@^1.1.1", "@radix-ui/react-dialog@^1.1.15", "@radix-ui/react-dialog@^1.1.6": +"@radix-ui/react-dialog@1.1.15", "@radix-ui/react-dialog@^1.1.1", "@radix-ui/react-dialog@^1.1.15", "@radix-ui/react-dialog@^1.1.4", "@radix-ui/react-dialog@^1.1.6": version "1.1.15" resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz#1de3d7a7e9a17a9874d29c07f5940a18a119b632" integrity sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw== @@ -1315,7 +1393,7 @@ aria-hidden "^1.2.4" react-remove-scroll "^2.6.3" -"@radix-ui/react-direction@1.1.1", "@radix-ui/react-direction@^1.1.1": +"@radix-ui/react-direction@1.1.1", "@radix-ui/react-direction@^1.1.0", "@radix-ui/react-direction@^1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.1.tgz#39e5a5769e676c753204b792fbe6cf508e550a14" integrity sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw== @@ -1427,7 +1505,7 @@ "@radix-ui/react-roving-focus" "1.1.11" "@radix-ui/react-use-controllable-state" "1.2.2" -"@radix-ui/react-navigation-menu@^1.2.14": +"@radix-ui/react-navigation-menu@^1.2.14", "@radix-ui/react-navigation-menu@^1.2.3": version "1.2.14" resolved "https://registry.yarnpkg.com/@radix-ui/react-navigation-menu/-/react-navigation-menu-1.2.14.tgz#4e6d1172be3c89752e564f8721706f78574ad7dd" integrity sha512-YB9mTFQvCOAQMHU+C/jVl96WmuWeltyUEpRJJky51huhds5W2FQr1J8D/16sQlf0ozxkPK8uF3niQMdUwZPv5w== @@ -1447,7 +1525,7 @@ "@radix-ui/react-use-previous" "1.1.1" "@radix-ui/react-visually-hidden" "1.2.3" -"@radix-ui/react-popover@^1.1.15": +"@radix-ui/react-popover@^1.1.15", "@radix-ui/react-popover@^1.1.4": version "1.1.15" resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.15.tgz#9c852f93990a687ebdc949b2c3de1f37cdc4c5d5" integrity sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA== @@ -1546,7 +1624,7 @@ "@radix-ui/react-use-callback-ref" "1.1.1" "@radix-ui/react-use-controllable-state" "1.2.2" -"@radix-ui/react-scroll-area@^1.2.10": +"@radix-ui/react-scroll-area@^1.2.10", "@radix-ui/react-scroll-area@^1.2.2": version "1.2.10" resolved "https://registry.yarnpkg.com/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz#e4fd3b4a79bb77bec1a52f0c8f26d8f3f1ca4b22" integrity sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A== @@ -1612,7 +1690,7 @@ "@radix-ui/react-use-previous" "1.1.1" "@radix-ui/react-use-size" "1.1.1" -"@radix-ui/react-slot@1.2.3", "@radix-ui/react-slot@^1.2.3": +"@radix-ui/react-slot@1.2.3", "@radix-ui/react-slot@^1.1.1", "@radix-ui/react-slot@^1.2.3": version "1.2.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.3.tgz#502d6e354fc847d4169c3bc5f189de777f68cfe1" integrity sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A== @@ -1639,7 +1717,7 @@ "@radix-ui/react-use-previous" "1.1.1" "@radix-ui/react-use-size" "1.1.1" -"@radix-ui/react-tabs@^1.1.13": +"@radix-ui/react-tabs@^1.1.13", "@radix-ui/react-tabs@^1.1.2": version "1.1.13" resolved "https://registry.yarnpkg.com/@radix-ui/react-tabs/-/react-tabs-1.1.13.tgz#3537ce379d7e7ff4eeb6b67a0973e139c2ac1f15" integrity sha512-7xdcatg7/U+7+Udyoj2zodtI9H/IIopqo+YOIcZOq1nJwXWBZ9p8xiu5llXlekDbZkca79a/fozEYQXIA4sW6A== @@ -1786,6 +1864,51 @@ resolved "https://registry.yarnpkg.com/@react-leaflet/core/-/core-3.0.0.tgz#34ccc280ce7d8ac5c09f2b3d5fffded450bdf1a2" integrity sha512-3EWmekh4Nz+pGcr+xjf0KNyYfC3U2JjnkWsh0zcqaexYqmmB5ZhH37kz41JXGmKzpaMZCnPofBBm64i+YrEvGQ== +"@react-three/drei@^10.7.6": + version "10.7.6" + resolved "https://registry.yarnpkg.com/@react-three/drei/-/drei-10.7.6.tgz#2b00683dfb95a2b5c7fe462701aac89ddd71c7dd" + integrity sha512-ZSFwRlRaa4zjtB7yHO6Q9xQGuyDCzE7whXBhum92JslcMRC3aouivp0rAzszcVymIoJx6PXmibyP+xr+zKdwLg== + dependencies: + "@babel/runtime" "^7.26.0" + "@mediapipe/tasks-vision" "0.10.17" + "@monogrid/gainmap-js" "^3.0.6" + "@use-gesture/react" "^10.3.1" + camera-controls "^3.1.0" + cross-env "^7.0.3" + detect-gpu "^5.0.56" + glsl-noise "^0.0.0" + hls.js "^1.5.17" + maath "^0.10.8" + meshline "^3.3.1" + stats-gl "^2.2.8" + stats.js "^0.17.0" + suspend-react "^0.1.3" + three-mesh-bvh "^0.8.3" + three-stdlib "^2.35.6" + troika-three-text "^0.52.4" + tunnel-rat "^0.1.2" + use-sync-external-store "^1.4.0" + utility-types "^3.11.0" + zustand "^5.0.1" + +"@react-three/fiber@^9.3.0": + version "9.3.0" + resolved "https://registry.yarnpkg.com/@react-three/fiber/-/fiber-9.3.0.tgz#7cf99551017f8a3c6300422aa95ac0d98e1f0bd5" + integrity sha512-myPe3YL/C8+Eq939/4qIVEPBW/uxV0iiUbmjfwrs9sGKYDG8ib8Dz3Okq7BQt8P+0k4igedONbjXMQy84aDFmQ== + dependencies: + "@babel/runtime" "^7.17.8" + "@types/react-reconciler" "^0.32.0" + "@types/webxr" "*" + base64-js "^1.5.1" + buffer "^6.0.3" + its-fine "^2.0.0" + react-reconciler "^0.31.0" + react-use-measure "^2.1.7" + scheduler "^0.25.0" + suspend-react "^0.1.3" + use-sync-external-store "^1.4.0" + zustand "^5.0.3" + "@rollup/rollup-android-arm-eabi@4.52.5": version "4.52.5" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.5.tgz#0f44a2f8668ed87b040b6fe659358ac9239da4db" @@ -2042,6 +2165,28 @@ "@sendgrid/client" "^8.1.5" "@sendgrid/helpers" "^8.0.0" +"@shikijs/core@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-2.5.0.tgz#e14d33961dfa3141393d4a76fc8923d0d1c4b62f" + integrity sha512-uu/8RExTKtavlpH7XqnVYBrfBkUc20ngXiX9NSrBhOVZYv/7XQRKUyhtkeflY5QsxC0GbJThCerruZfsUaSldg== + dependencies: + "@shikijs/engine-javascript" "2.5.0" + "@shikijs/engine-oniguruma" "2.5.0" + "@shikijs/types" "2.5.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.4" + +"@shikijs/core@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.13.0.tgz#73503364a1eb51b65cf904115c62fed7a47df596" + integrity sha512-3P8rGsg2Eh2qIHekwuQjzWhKI4jV97PhvYjYUzGqjvJfqdQPz+nMlfWahU24GZAyW1FxFI1sYjyhfh5CoLmIUA== + dependencies: + "@shikijs/types" "3.13.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.5" + "@shikijs/core@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.14.0.tgz#a1c547794518842fb60bb71932a7bc47de0b4703" @@ -2052,56 +2197,148 @@ "@types/hast" "^3.0.4" hast-util-to-html "^9.0.5" -"@shikijs/engine-javascript@3.14.0": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.14.0.tgz#546c14fcf2654ca3c27f76686e969bf3b1496b53" - integrity sha512-3v1kAXI2TsWQuwv86cREH/+FK9Pjw3dorVEykzQDhwrZj0lwsHYlfyARaKmn6vr5Gasf8aeVpb8JkzeWspxOLQ== +"@shikijs/core@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/core/-/core-3.15.0.tgz#eee251070b4e39b59e108266cbcd50c85d738d54" + integrity sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg== dependencies: - "@shikijs/types" "3.14.0" + "@shikijs/types" "3.15.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + hast-util-to-html "^9.0.5" + +"@shikijs/engine-javascript@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-2.5.0.tgz#e045c6ecfbda6c99137547b0a482e0b87f1053fc" + integrity sha512-VjnOpnQf8WuCEZtNUdjjwGUbtAVKuZkVQ/5cHy/tojVVRIRtlWMYVjyWhxOmIq05AlSOv72z7hRNRGVBgQOl0w== + dependencies: + "@shikijs/types" "2.5.0" + "@shikijs/vscode-textmate" "^10.0.2" + oniguruma-to-es "^3.1.0" + +"@shikijs/engine-javascript@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.13.0.tgz#d25cefdac378216a95fefdf0b3a560550393ea65" + integrity sha512-Ty7xv32XCp8u0eQt8rItpMs6rU9Ki6LJ1dQOW3V/56PKDcpvfHPnYFbsx5FFUP2Yim34m/UkazidamMNVR4vKg== + dependencies: + "@shikijs/types" "3.13.0" "@shikijs/vscode-textmate" "^10.0.2" oniguruma-to-es "^4.3.3" -"@shikijs/engine-oniguruma@3.14.0": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.14.0.tgz#562bcce2f69cc65c92bcf2ccb637b2a7021f3d7b" - integrity sha512-TNcYTYMbJyy+ZjzWtt0bG5y4YyMIWC2nyePz+CFMWqm+HnZZyy9SWMgo8Z6KBJVIZnx8XUXS8U2afO6Y0g1Oug== +"@shikijs/engine-javascript@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-javascript/-/engine-javascript-3.15.0.tgz#478dd4feb3b4b7e91f148cc9e7ebc0b7de5fbb18" + integrity sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg== dependencies: - "@shikijs/types" "3.14.0" + "@shikijs/types" "3.15.0" "@shikijs/vscode-textmate" "^10.0.2" + oniguruma-to-es "^4.3.3" -"@shikijs/langs@3.14.0": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.14.0.tgz#71e6ca44e661b405209eb63d4449b57b9de529d0" - integrity sha512-DIB2EQY7yPX1/ZH7lMcwrK5pl+ZkP/xoSpUzg9YC8R+evRCCiSQ7yyrvEyBsMnfZq4eBzLzBlugMyTAf13+pzg== +"@shikijs/engine-oniguruma@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-2.5.0.tgz#230de5693cc1da6c9d59c7ad83593c2027274817" + integrity sha512-pGd1wRATzbo/uatrCIILlAdFVKdxImWJGQ5rFiB5VZi2ve5xj3Ax9jny8QvkaV93btQEwR/rSz5ERFpC5mKNIw== dependencies: - "@shikijs/types" "3.14.0" + "@shikijs/types" "2.5.0" + "@shikijs/vscode-textmate" "^10.0.2" + +"@shikijs/engine-oniguruma@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.13.0.tgz#ae8efa90c30e2b66c7fd5549ee747f693fbd60df" + integrity sha512-O42rBGr4UDSlhT2ZFMxqM7QzIU+IcpoTMzb3W7AlziI1ZF7R8eS2M0yt5Ry35nnnTX/LTLXFPUjRFCIW+Operg== + dependencies: + "@shikijs/types" "3.13.0" + "@shikijs/vscode-textmate" "^10.0.2" + +"@shikijs/engine-oniguruma@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/engine-oniguruma/-/engine-oniguruma-3.15.0.tgz#bc5fe6484d64b2daacdfbb248f06732fbc78c8e2" + integrity sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA== + dependencies: + "@shikijs/types" "3.15.0" + "@shikijs/vscode-textmate" "^10.0.2" + +"@shikijs/langs@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-2.5.0.tgz#97ab50c495922cc1ca06e192985b28dc73de5d50" + integrity sha512-Qfrrt5OsNH5R+5tJ/3uYBBZv3SuGmnRPejV9IlIbFH3HTGLDlkqgHymAlzklVmKBjAaVmkPkyikAV/sQ1wSL+w== + dependencies: + "@shikijs/types" "2.5.0" + +"@shikijs/langs@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.13.0.tgz#51a927c8089dffb2560ac8d7549297de9d081b91" + integrity sha512-672c3WAETDYHwrRP0yLy3W1QYB89Hbpj+pO4KhxK6FzIrDI2FoEXNiNCut6BQmEApYLfuYfpgOZaqbY+E9b8wQ== + dependencies: + "@shikijs/types" "3.13.0" + +"@shikijs/langs@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/langs/-/langs-3.15.0.tgz#d8385a9ca66ce9923149c650336444b1d25fc248" + integrity sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A== + dependencies: + "@shikijs/types" "3.15.0" + +"@shikijs/rehype@^2.0.3": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/rehype/-/rehype-2.5.0.tgz#14c8399db32b4bcdd9076efb73895d3ff3ca229c" + integrity sha512-BO/QRsuQVdzQdoQLq//zcex8K6w57kD9zT8KhSs9kNBJFVDsxm6mTmi6OiRIxysZqhvVrEpY5Mh9IOv1NnjGFg== + dependencies: + "@shikijs/types" "2.5.0" + "@types/hast" "^3.0.4" + hast-util-to-string "^3.0.1" + shiki "2.5.0" + unified "^11.0.5" + unist-util-visit "^5.0.0" "@shikijs/rehype@^3.14.0": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@shikijs/rehype/-/rehype-3.14.0.tgz#58b0f205d5a02b30742f9ce7d76fee7613e19dd6" - integrity sha512-In2G6yvT0ZFDqNGbJumd7gEAwtxuaXuchCc0O3qOytIUTlpzs8/D0CQF3wktdfOB6B869eab6Z6EIJr4Td4hQQ== + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/rehype/-/rehype-3.15.0.tgz#69710ea29eb71c6b47821657a10417aab457627d" + integrity sha512-U+tqD1oxL+85N8FaW5XYIlMZ8KAa2g9IdplEZxPWflGRJf2gQRiBMMrpdG1USz3PN350YnMUHWcz9Twt3wJjXQ== dependencies: - "@shikijs/types" "3.14.0" + "@shikijs/types" "3.15.0" "@types/hast" "^3.0.4" hast-util-to-string "^3.0.1" - shiki "3.14.0" + shiki "3.15.0" unified "^11.0.5" unist-util-visit "^5.0.0" -"@shikijs/themes@3.14.0": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.14.0.tgz#2b516c19caf63f78f81f5df9c087800c3b2c7404" - integrity sha512-fAo/OnfWckNmv4uBoUu6dSlkcBc+SA1xzj5oUSaz5z3KqHtEbUypg/9xxgJARtM6+7RVm0Q6Xnty41xA1ma1IA== +"@shikijs/themes@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-2.5.0.tgz#8c6aecf73f5455681c8bec15797cf678162896cb" + integrity sha512-wGrk+R8tJnO0VMzmUExHR+QdSaPUl/NKs+a4cQQRWyoc3YFbUzuLEi/KWK1hj+8BfHRKm2jNhhJck1dfstJpiw== dependencies: - "@shikijs/types" "3.14.0" + "@shikijs/types" "2.5.0" + +"@shikijs/themes@3.13.0": + version "3.13.0" + resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.13.0.tgz#ee92780f0580d4ffa8ed619b52c5eb4a95d012a3" + integrity sha512-Vxw1Nm1/Od8jyA7QuAenaV78BG2nSr3/gCGdBkLpfLscddCkzkL36Q5b67SrLLfvAJTOUzW39x4FHVCFriPVgg== + dependencies: + "@shikijs/types" "3.13.0" + +"@shikijs/themes@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/themes/-/themes-3.15.0.tgz#6093a90191b89654045c72636ddd35c04273658f" + integrity sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ== + dependencies: + "@shikijs/types" "3.15.0" + +"@shikijs/transformers@^2.0.3": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/transformers/-/transformers-2.5.0.tgz#190c84786ff06c417580ab79177338a947168c55" + integrity sha512-SI494W5X60CaUwgi8u4q4m4s3YAFSxln3tzNjOSYqq54wlVgz0/NbbXEb3mdLbqMBztcmS7bVTaEd2w0qMmfeg== + dependencies: + "@shikijs/core" "2.5.0" + "@shikijs/types" "2.5.0" "@shikijs/transformers@^3.14.0": - version "3.14.0" - resolved "https://registry.yarnpkg.com/@shikijs/transformers/-/transformers-3.14.0.tgz#441b87394463faa89a86b1cfa5de2f12e9f6dbd3" - integrity sha512-i67zQnY9wLMMnKasonVW1L9fKneSLZDj1ePsA4o0AZWU4uUobmJY9baRDa36z+a9/g0aG76/2tybQvm4hrwxIQ== + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/transformers/-/transformers-3.15.0.tgz#d7544b00dc7be94f70002580e95384d01768d5ff" + integrity sha512-Hmwip5ovvSkg+Kc41JTvSHHVfCYF+C8Cp1omb5AJj4Xvd+y9IXz2rKJwmFRGsuN0vpHxywcXJ1+Y4B9S7EG1/A== dependencies: - "@shikijs/core" "3.14.0" - "@shikijs/types" "3.14.0" + "@shikijs/core" "3.15.0" + "@shikijs/types" "3.15.0" "@shikijs/twoslash@^3.13.0": version "3.14.0" @@ -2112,6 +2349,22 @@ "@shikijs/types" "3.14.0" twoslash "^0.3.4" +"@shikijs/types@2.5.0": + version "2.5.0" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-2.5.0.tgz#e949c7384802703a48b9d6425dd41673c164df69" + integrity sha512-ygl5yhxki9ZLNuNpPitBWvcy9fsSKKaRuO4BAlMyagszQidxcpLAr0qiW/q43DtSIDxO6hEbtYLiFZNXO/hdGw== + dependencies: + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + +"@shikijs/types@3.13.0": + version "3.13.0" + resolved "https://registry.npmjs.org/@shikijs/types/-/types-3.13.0.tgz" + integrity sha512-oM9P+NCFri/mmQ8LoFGVfVyemm5Hi27330zuOBp0annwJdKH1kOLndw3zCtAVDehPLg9fKqoEx3Ht/wNZxolfw== + dependencies: + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + "@shikijs/types@3.14.0": version "3.14.0" resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.14.0.tgz#4e666f8d31e319494daf23efcc19a32a5fdaa341" @@ -2120,6 +2373,14 @@ "@shikijs/vscode-textmate" "^10.0.2" "@types/hast" "^3.0.4" +"@shikijs/types@3.15.0": + version "3.15.0" + resolved "https://registry.yarnpkg.com/@shikijs/types/-/types-3.15.0.tgz#4e025b4dea98e1603243b1f00677854e07e5eda1" + integrity sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw== + dependencies: + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + "@shikijs/vscode-textmate@^10.0.2": version "10.0.2" resolved "https://registry.yarnpkg.com/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz#a90ab31d0cc1dfb54c66a69e515bf624fa7b2224" @@ -2276,6 +2537,11 @@ minimatch "^10.0.1" path-browserify "^1.0.1" +"@tweenjs/tween.js@~23.1.3": + version "23.1.3" + resolved "https://registry.yarnpkg.com/@tweenjs/tween.js/-/tween.js-23.1.3.tgz#eff0245735c04a928bb19c026b58c2a56460539d" + integrity sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA== + "@tybys/wasm-util@^0.10.1": version "0.10.1" resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.1.tgz#ecddd3205cf1e2d5274649ff0eedd2991ed7f414" @@ -2510,6 +2776,11 @@ resolved "https://registry.yarnpkg.com/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz#dcef10a69d357fe9d43ac4ff2eca6b85dbf466af" integrity sha512-xFdR6tkm0MWvBfO8xXCSsinYxHcqkQUlcHeSpMC2ukzOb6lwQAfDmW+Qt0AvlGd8HpsS28qKsB+oPeJn9I39jg== +"@types/draco3d@^1.4.0": + version "1.4.10" + resolved "https://registry.yarnpkg.com/@types/draco3d/-/draco3d-1.4.10.tgz#63ec0ba78b30bd58203ec031f4e4f0198c596dca" + integrity sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw== + "@types/estree-jsx@^1.0.0": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree-jsx/-/estree-jsx-1.0.5.tgz#858a88ea20f34fe65111f005a689fa1ebf70dc18" @@ -2522,6 +2793,13 @@ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== +"@types/exceljs@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@types/exceljs/-/exceljs-1.3.2.tgz#90b5deef9f92f154d407638505032a89a50e4368" + integrity sha512-etq4LpmL5vZKzf29U5u7cWjoCWGc67hTc2WrvwmcBUyRiHydUPg5ZXGFwBHcEkTLinyT6fRmJiVSRwf4RdnjUA== + dependencies: + exceljs "*" + "@types/geojson@*": version "7946.0.16" resolved "https://registry.yarnpkg.com/@types/geojson/-/geojson-7946.0.16.tgz#8ebe53d69efada7044454e3305c19017d97ced2a" @@ -2573,6 +2851,11 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== +"@types/node@^14.0.1": + version "14.18.63" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" + integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ== + "@types/node@^24.5.0": version "24.10.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-24.10.0.tgz#6b79086b0dfc54e775a34ba8114dcc4e0221f31f" @@ -2580,6 +2863,11 @@ dependencies: undici-types "~7.16.0" +"@types/offscreencanvas@^2019.6.4": + version "2019.7.3" + resolved "https://registry.yarnpkg.com/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz#90267db13f64d6e9ccb5ae3eac92786a7c77a516" + integrity sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A== + "@types/prismjs@^1.26.5": version "1.26.5" resolved "https://registry.yarnpkg.com/@types/prismjs/-/prismjs-1.26.5.tgz#72499abbb4c4ec9982446509d2f14fb8483869d6" @@ -2590,6 +2878,16 @@ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.2.2.tgz#a4cc874797b7ddc9cb180ef0d5dc23f596fc2332" integrity sha512-9KQPoO6mZCi7jcIStSnlOWn2nEF3mNmyr3rIAsGnAbQKYbRLyqmeSc39EVgtxXVia+LMT8j3knZLAZAh+xLmrw== +"@types/react-reconciler@^0.28.9": + version "0.28.9" + resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.28.9.tgz#d24b4864c384e770c83275b3fe73fba00269c83b" + integrity sha512-HHM3nxyUZ3zAylX8ZEyrDNd2XZOnQ0D5XfunJF5FLQnZbHHYq4UWvW1QfelQNXv1ICNkwYhfxjwfnqivYB6bFg== + +"@types/react-reconciler@^0.32.0": + version "0.32.1" + resolved "https://registry.yarnpkg.com/@types/react-reconciler/-/react-reconciler-0.32.1.tgz#6cb1d9bf85449a357517daf975d3d32149c1b2a7" + integrity sha512-RsqPttsBQ+6af0nATFXJJpemYQH7kL9+xLNm1z+0MjQFDKBZDM2R6SBrjdvRmHu9i9fM6povACj57Ft+pKRNOA== + "@types/react@^19.1.13": version "19.2.2" resolved "https://registry.yarnpkg.com/@types/react/-/react-19.2.2.tgz#ba123a75d4c2a51158697160a4ea2ff70aa6bf36" @@ -2597,6 +2895,24 @@ dependencies: csstype "^3.0.2" +"@types/stats.js@*": + version "0.17.4" + resolved "https://registry.yarnpkg.com/@types/stats.js/-/stats.js-0.17.4.tgz#1933e5ff153a23c7664487833198d685c22e791e" + integrity sha512-jIBvWWShCvlBqBNIZt0KAshWpvSjhkwkEu4ZUcASoAvhmrgAUI2t1dXrjSL4xXVLB4FznPrIsX3nKXFl/Dt4vA== + +"@types/three@*": + version "0.180.0" + resolved "https://registry.yarnpkg.com/@types/three/-/three-0.180.0.tgz#c9525a744e55c43f720185710c5dc33e6ff67b53" + integrity sha512-ykFtgCqNnY0IPvDro7h+9ZeLY+qjgUWv+qEvUt84grhenO60Hqd4hScHE7VTB9nOQ/3QM8lkbNE+4vKjEpUxKg== + dependencies: + "@dimforge/rapier3d-compat" "~0.12.0" + "@tweenjs/tween.js" "~23.1.3" + "@types/stats.js" "*" + "@types/webxr" "*" + "@webgpu/types" "*" + fflate "~0.8.2" + meshoptimizer "~0.22.0" + "@types/trusted-types@^2.0.7": version "2.0.7" resolved "https://registry.yarnpkg.com/@types/trusted-types/-/trusted-types-2.0.7.tgz#baccb07a970b91707df3a3e8ba6896c57ead2d11" @@ -2612,6 +2928,11 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== +"@types/webxr@*", "@types/webxr@^0.5.2": + version "0.5.23" + resolved "https://registry.yarnpkg.com/@types/webxr/-/webxr-0.5.23.tgz#fe2b76ffa9600d118f2fcdf855fa93bcf8e79f8c" + integrity sha512-GPe4AsfOSpqWd3xA/0gwoKod13ChcfV67trvxaW2krUbgb9gxQjnCx8zGshzMl8LSHZlNH5gQ8LNScsDuc7nGQ== + "@typescript/vfs@^1.6.1": version "1.6.2" resolved "https://registry.yarnpkg.com/@typescript/vfs/-/vfs-1.6.2.tgz#e66883c5a8dcc5d2794dfa05c8f9749d767219f8" @@ -2624,6 +2945,18 @@ resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.3.0.tgz#d06bbb384ebcf6c505fde1c3d0ed4ddffe0aaff8" integrity sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g== +"@use-gesture/core@10.3.1": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@use-gesture/core/-/core-10.3.1.tgz#976c9421e905f0079d49822cfd5c2e56b808fc56" + integrity sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw== + +"@use-gesture/react@^10.3.1": + version "10.3.1" + resolved "https://registry.yarnpkg.com/@use-gesture/react/-/react-10.3.1.tgz#17a743a894d9bd9a0d1980c618f37f0164469867" + integrity sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g== + dependencies: + "@use-gesture/core" "10.3.1" + "@vercel/blob@^0.27.3": version "0.27.3" resolved "https://registry.yarnpkg.com/@vercel/blob/-/blob-0.27.3.tgz#313ec62b17cb982739929bc0002485df58775ab9" @@ -2694,6 +3027,11 @@ loupe "^3.1.2" tinyrainbow "^1.2.0" +"@webgpu/types@*": + version "0.1.66" + resolved "https://registry.yarnpkg.com/@webgpu/types/-/types-0.1.66.tgz#afba7a8f32494416643d6077ce0445fc45df4346" + integrity sha512-YA2hLrwLpDsRueNDXIMqN9NTzD6bCDkuXbOSe0heS+f8YE8usA6Gbv1prj81pzVHrbaAma7zObnIC+I6/sXJgA== + abitype@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.1.0.tgz#510c5b3f92901877977af5e864841f443bf55406" @@ -2780,6 +3118,51 @@ ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +archiver-utils@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-2.1.0.tgz#e8a460e94b693c3e3da182a098ca6285ba9249e2" + integrity sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw== + dependencies: + glob "^7.1.4" + graceful-fs "^4.2.0" + lazystream "^1.0.0" + lodash.defaults "^4.2.0" + lodash.difference "^4.5.0" + lodash.flatten "^4.4.0" + lodash.isplainobject "^4.0.6" + lodash.union "^4.6.0" + normalize-path "^3.0.0" + readable-stream "^2.0.0" + +archiver-utils@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/archiver-utils/-/archiver-utils-3.0.4.tgz#a0d201f1cf8fce7af3b5a05aea0a337329e96ec7" + integrity sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw== + dependencies: + glob "^7.2.3" + graceful-fs "^4.2.0" + lazystream "^1.0.0" + lodash.defaults "^4.2.0" + lodash.difference "^4.5.0" + lodash.flatten "^4.4.0" + lodash.isplainobject "^4.0.6" + lodash.union "^4.6.0" + normalize-path "^3.0.0" + readable-stream "^3.6.0" + +archiver@^5.0.0: + version "5.3.2" + resolved "https://registry.yarnpkg.com/archiver/-/archiver-5.3.2.tgz#99991d5957e53bd0303a392979276ac4ddccf3b0" + integrity sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw== + dependencies: + archiver-utils "^2.1.0" + async "^3.2.4" + buffer-crc32 "^0.2.1" + readable-stream "^3.6.0" + readdir-glob "^1.1.2" + tar-stream "^2.2.0" + zip-stream "^4.1.0" + argparse@^1.0.7: version "1.0.10" resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" @@ -2825,6 +3208,11 @@ async-retry@^1.3.3: dependencies: retry "0.13.1" +async@^3.2.4: + version "3.2.6" + resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" + integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== + asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -2885,11 +3273,45 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base64-js@^1.2.0, base64-js@^1.3.1: +base64-js@^1.2.0, base64-js@^1.3.1, base64-js@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== +bidi-js@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/bidi-js/-/bidi-js-1.0.3.tgz#6f8bcf3c877c4d9220ddf49b9bb6930c88f877d2" + integrity sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw== + dependencies: + require-from-string "^2.0.2" + +big-integer@^1.6.17: + version "1.6.52" + resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" + integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== + +binary@~0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/binary/-/binary-0.3.0.tgz#9f60553bc5ce8c3386f3b553cff47462adecaa79" + integrity sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg== + dependencies: + buffers "~0.1.1" + chainsaw "~0.1.0" + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +bluebird@~3.4.1: + version "3.4.7" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.4.7.tgz#f72d760be09b7f76d08ed8fae98b289a8d05fab3" + integrity sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA== + boring-name-generator@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/boring-name-generator/-/boring-name-generator-1.0.3.tgz#2c7273834d6c68616cff2b7a12c8cb7f32d360e4" @@ -2898,6 +3320,14 @@ boring-name-generator@^1.0.3: commander "^6.1.0" lodash "^4.17.20" +brace-expansion@^1.1.7: + version "1.1.12" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" + integrity sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + brace-expansion@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.2.tgz#54fc53237a613d854c7bd37463aad17df87214e7" @@ -2912,7 +3342,17 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -buffer@^5.2.1: +buffer-crc32@^0.2.1, buffer-crc32@^0.2.13: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ== + +buffer-indexof-polyfill@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c" + integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A== + +buffer@^5.2.1, buffer@^5.5.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== @@ -2920,6 +3360,19 @@ buffer@^5.2.1: base64-js "^1.3.1" ieee754 "^1.1.13" +buffer@^6.0.3: + version "6.0.3" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" + integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.2.1" + +buffers@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/buffers/-/buffers-0.1.1.tgz#b24579c3bed4d6d396aeee6d9a8ae7f5482ab7bb" + integrity sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ== + c12@3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/c12/-/c12-3.1.0.tgz#9e237970e1d3b74ebae51d25945cb59664c12c89" @@ -2969,6 +3422,11 @@ call-bound@^1.0.2, call-bound@^1.0.4: call-bind-apply-helpers "^1.0.2" get-intrinsic "^1.3.0" +camera-controls@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/camera-controls/-/camera-controls-3.1.0.tgz#06735c0022020a941e813492499e3c110a890b0a" + integrity sha512-w5oULNpijgTRH0ARFJJ0R5ct1nUM3R3WP7/b8A6j9uTGpRfnsypc/RBMPQV8JQDPayUe37p/TZZY1PcUr4czOQ== + caniuse-lite@^1.0.30001579: version "1.0.30001753" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001753.tgz#419f8fc9bab6f1a1d10d9574d0b3374f823c5b00" @@ -2995,6 +3453,13 @@ chai@^5.1.2: loupe "^3.1.0" pathval "^2.0.0" +chainsaw@~0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/chainsaw/-/chainsaw-0.1.0.tgz#5eab50b28afe58074d0d58291388828b5e5fbc98" + integrity sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ== + dependencies: + traverse ">=0.3.0 <0.4" + chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -3166,11 +3631,26 @@ commander@^8.3.0: resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66" integrity sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww== +compress-commons@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/compress-commons/-/compress-commons-4.1.2.tgz#6542e59cb63e1f46a8b21b0e06f9a32e4c8b06df" + integrity sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg== + dependencies: + buffer-crc32 "^0.2.13" + crc32-stream "^4.0.2" + normalize-path "^3.0.0" + readable-stream "^3.6.0" + compute-scroll-into-view@^3.0.2: version "3.1.1" resolved "https://registry.yarnpkg.com/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz#02c3386ec531fb6a9881967388e53e8564f3e9aa" integrity sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw== +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + confbox@^0.1.8: version "0.1.8" resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" @@ -3196,6 +3676,11 @@ core-js@^3.38.1: resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.46.0.tgz#323a092b96381a9184d0cd49ee9083b2f93373bb" integrity sha512-vDMm9B0xnqqZ8uSBpZ8sNtRtOdmfShrvT6h2TuQGLs0Is+cR0DYbj/KWP6ALVNbWPpqA/qPLoOuppJN07humpA== +core-util-is@~1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85" + integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ== + cose-base@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/cose-base/-/cose-base-1.0.3.tgz#650334b41b869578a543358b80cda7e0abe0a60a" @@ -3210,11 +3695,40 @@ cose-base@^2.2.0: dependencies: layout-base "^2.0.0" +crc-32@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff" + integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ== + +crc32-stream@^4.0.2: + version "4.0.3" + resolved "https://registry.yarnpkg.com/crc32-stream/-/crc32-stream-4.0.3.tgz#85dd677eb78fa7cad1ba17cc506a597d41fc6f33" + integrity sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw== + dependencies: + crc-32 "^1.2.0" + readable-stream "^3.4.0" + cross-argv@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/cross-argv/-/cross-argv-2.0.0.tgz#2e7907ba3246f82c967623a3e8525925bbd6c0ad" integrity sha512-YIaY9TR5Nxeb8SMdtrU8asWVM4jqJDNDYlKV21LxtYcfNJhp1kEsgSa6qXwXgzN0WQWGODps0+TlGp2xQSHwOg== +cross-env@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-env/-/cross-env-7.0.3.tgz#865264b29677dc015ba8418918965dd232fc54cf" + integrity sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw== + dependencies: + cross-spawn "^7.0.1" + +cross-spawn@^7.0.1: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + cssesc@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" @@ -3523,12 +4037,22 @@ dagre-d3-es@7.0.13: d3 "^7.9.0" lodash-es "^4.17.21" +date-fns-jalali@^4.1.0-0: + version "4.1.0-0" + resolved "https://registry.yarnpkg.com/date-fns-jalali/-/date-fns-jalali-4.1.0-0.tgz#9c7fb286004fab267a300d3e9f1ada9f10b4b6b0" + integrity sha512-hTIP/z+t+qKwBDcmmsnmjWTduxCg+5KfdqWQvb2X/8C9+knYY6epN/pfxdDuyVlSVeFz0sM5eEfwIUQ70U4ckg== + date-fns@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-4.1.0.tgz#64b3d83fff5aa80438f5b1a633c2e83b8a1c2d14" integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg== dayjs@^1.11.18: + version "1.11.18" + resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.18.tgz" + integrity sha512-zFBQ7WFRvVRhKcWoUh+ZA1g2HVgUbsZm9sbddh8EC5iv93sui8DVVz1Npvz+r6meo9VKfa8NyLWBsQK1VvIKPA== + +dayjs@^1.8.34: version "1.11.19" resolved "https://registry.yarnpkg.com/dayjs/-/dayjs-1.11.19.tgz#15dc98e854bb43917f12021806af897c58ae2938" integrity sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw== @@ -3603,7 +4127,14 @@ destr@^2.0.3: resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.5.tgz#7d112ff1b925fb8d2079fac5bdb4a90973b51fdb" integrity sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA== -detect-libc@^2.0.3, detect-libc@^2.1.0: +detect-gpu@^5.0.56: + version "5.0.70" + resolved "https://registry.yarnpkg.com/detect-gpu/-/detect-gpu-5.0.70.tgz#db2202d3cd440714ba6e789ff8b62d1b584eabf7" + integrity sha512-bqerEP1Ese6nt3rFkwPnGbsUF9a4q+gMmpTVVOEzoCyeCc+y7/RvJnQZJx1JwhgQI5Ntg0Kgat8Uu7XpBqnz1w== + dependencies: + webgl-constants "^1.1.1" + +detect-libc@^2.0.3, detect-libc@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== @@ -3645,6 +4176,11 @@ dotenv@^16.6.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== +draco3d@^1.4.1: + version "1.5.7" + resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.5.7.tgz#94f9bce293eb8920c159dc91a4ce9124a9e899e0" + integrity sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ== + dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" @@ -3654,6 +4190,13 @@ dunder-proto@^1.0.1: es-errors "^1.3.0" gopd "^1.2.0" +duplexer2@~0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/duplexer2/-/duplexer2-0.1.4.tgz#8b12dab878c0d69e3e7891051662a32fc6bddcc1" + integrity sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA== + dependencies: + readable-stream "^2.0.2" + effect@3.18.4: version "3.18.4" resolved "https://registry.yarnpkg.com/effect/-/effect-3.18.4.tgz#e241fde5cc090608c51c5e29e2da357bb5d0e815" @@ -3667,6 +4210,11 @@ embla-carousel-auto-scroll@^8.6.0: resolved "https://registry.yarnpkg.com/embla-carousel-auto-scroll/-/embla-carousel-auto-scroll-8.6.0.tgz#02f648acd8b184a0f3ae0f2b38a983afc16a2648" integrity sha512-WT9fWhNXFpbQ6kP+aS07oF5IHYLZ1Dx4DkwgCY8Hv2ZyYd2KMCPfMV1q/cA3wFGuLO7GMgKiySLX90/pQkcOdQ== +embla-carousel-autoplay@^8.5.2: + version "8.6.0" + resolved "https://registry.yarnpkg.com/embla-carousel-autoplay/-/embla-carousel-autoplay-8.6.0.tgz#bc86c97de00d52ec34b05058736ef50af6e0d0e4" + integrity sha512-OBu5G3nwaSXkZCo1A6LTaFMZ8EpkYbwIaH+bPqdBnDGQ2fh4+NbzjXjs2SktoPNKCtflfVMc75njaDHOYXcrsA== + embla-carousel-react@^8.6.0: version "8.6.0" resolved "https://registry.yarnpkg.com/embla-carousel-react/-/embla-carousel-react-8.6.0.tgz#b737042a32761c38d6614593653b3ac619477bd1" @@ -3685,6 +4233,11 @@ embla-carousel@8.6.0: resolved "https://registry.yarnpkg.com/embla-carousel/-/embla-carousel-8.6.0.tgz#abcedff2bff36992ea8ac27cd30080ca5b6a3f58" integrity sha512-SjWyZBHJPbqxHOzckOfo8lHisEaJWmwd23XppYFYVh10bU66/Pn5tkVkbkCMZVdbUE5eTCI2nD8OyIP4Z+uwkA== +emoji-regex-xs@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex-xs/-/emoji-regex-xs-1.0.0.tgz#e8af22e5d9dbd7f7f22d280af3d19d2aab5b0724" + integrity sha512-LRlerrMYoIDrT6jgpeZ2YYl/L8EulRTt5hQcYjy5AInh7HWXKimpqx68aknBFpGL2+/IcogTcaydJEgaTmOpDg== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -3695,6 +4248,13 @@ empathic@2.0.0: resolved "https://registry.yarnpkg.com/empathic/-/empathic-2.0.0.tgz#71d3c2b94fad49532ef98a6c34be0386659f6131" integrity sha512-i6UzDscO/XfAcNYD75CfICkmfLedpyPDdozrLMmQc5ORaQcdMoc21OnlEylMIqI7U8eniKrPMxxtj8k0vhmJhA== +end-of-stream@^1.4.1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + enhanced-resolve@^5.18.3: version "5.18.3" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz#9b5f4c5c076b8787c78fe540392ce76a88855b44" @@ -3902,6 +4462,21 @@ eventemitter3@^4.0.1: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== +exceljs@*, exceljs@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/exceljs/-/exceljs-4.4.0.tgz#cfb1cb8dcc82c760a9fc9faa9e52dadab66b0156" + integrity sha512-XctvKaEMaj1Ii9oDOqbW/6e1gXknSY4g/aLCDicOXqBE4M0nRWkUu0PTp++UPNzoFY12BNHMfs/VadKIS6llvg== + dependencies: + archiver "^5.0.0" + dayjs "^1.8.34" + fast-csv "^4.3.1" + jszip "^3.10.1" + readable-stream "^3.6.0" + saxes "^5.0.1" + tmp "^0.2.0" + unzipper "^0.10.11" + uuid "^8.3.0" + expect-type@^1.1.0: version "1.2.2" resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.2.2.tgz#c030a329fb61184126c8447585bc75a7ec6fbff3" @@ -3931,6 +4506,14 @@ fast-check@^3.23.1: dependencies: pure-rand "^6.1.0" +fast-csv@^4.3.1: + version "4.3.6" + resolved "https://registry.yarnpkg.com/fast-csv/-/fast-csv-4.3.6.tgz#70349bdd8fe4d66b1130d8c91820b64a21bc4a63" + integrity sha512-2RNSpuwwsJGP0frGsOmTb9oUF+VkFSM4SyLTDgwf2ciHWTarN0lQTC+F2f/t5J9QjW+c65VFIAAu85GsvMIusw== + dependencies: + "@fast-csv/format" "4.3.5" + "@fast-csv/parse" "4.3.6" + fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -3981,6 +4564,16 @@ fflate@^0.4.8: resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.4.8.tgz#f90b82aefbd8ac174213abb338bd7ef848f0f5ae" integrity sha512-FJqqoDBR00Mdj9ppamLa/Y7vxm+PRmNWA67N846RvsoYVMKB4q3y/de5PA7gUmRMYK/8CMz2GDZQmCRN1wBcWA== +fflate@^0.6.9: + version "0.6.10" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz#5f40f9659205936a2d18abf88b2e7781662b6d43" + integrity sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg== + +fflate@~0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/fflate/-/fflate-0.8.2.tgz#fc8631f5347812ad6028bbe4a2308b2792aa1dea" + integrity sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A== + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -4030,12 +4623,77 @@ framer-motion@^12.23.12: motion-utils "^12.23.6" tslib "^2.4.0" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -fumadocs-core@16.0.9, fumadocs-core@^16.0.9: +fstream@^1.0.12: + version "1.0.12" + resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.12.tgz#4e8ba8ee2d48be4f7d0de505455548eae5932045" + integrity sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg== + dependencies: + graceful-fs "^4.1.2" + inherits "~2.0.0" + mkdirp ">=0.5 0" + rimraf "2" + +fumadocs-core@14.7.7: + version "14.7.7" + resolved "https://registry.yarnpkg.com/fumadocs-core/-/fumadocs-core-14.7.7.tgz#f0ad558d6dffa187f16dfc3c81096978ae7eebe9" + integrity sha512-ZP2sFZki291se9R6/K959a6CDNqM+oQKejEygViSTQnkCQ8UWApRQHUZQS670sub8ysBFE8aGlgsnAs+n9HlyA== + dependencies: + "@formatjs/intl-localematcher" "^0.5.10" + "@orama/orama" "^2.1.1" + "@shikijs/rehype" "^2.0.3" + "@shikijs/transformers" "^2.0.3" + github-slugger "^2.0.0" + hast-util-to-estree "^3.1.1" + hast-util-to-jsx-runtime "^2.3.2" + image-size "^1.2.0" + negotiator "^1.0.0" + react-remove-scroll "^2.6.2" + remark "^15.0.0" + remark-gfm "^4.0.0" + scroll-into-view-if-needed "^3.1.0" + shiki "^2.0.3" + unist-util-visit "^5.0.0" + +fumadocs-core@16.0.11, fumadocs-core@^16.0.9: + version "16.0.11" + resolved "https://registry.yarnpkg.com/fumadocs-core/-/fumadocs-core-16.0.11.tgz#88a9ccfb967f2b3af40d38ce33e5e3a7b498f719" + integrity sha512-F+Pq/0Kri2QRO9qCLcFczrSJs2bCXuzsC7IgAN4zN9C00W0kSuSrjveRsZw7G94DiqZl6kWldpI5kToA1UwrPg== + dependencies: + "@formatjs/intl-localematcher" "^0.6.2" + "@orama/orama" "^3.1.16" + "@shikijs/rehype" "^3.14.0" + "@shikijs/transformers" "^3.14.0" + estree-util-value-to-estree "^3.5.0" + github-slugger "^2.0.0" + hast-util-to-estree "^3.1.3" + hast-util-to-jsx-runtime "^2.3.6" + image-size "^2.0.2" + negotiator "^1.0.0" + npm-to-yarn "^3.0.1" + path-to-regexp "^8.3.0" + remark "^15.0.1" + remark-gfm "^4.0.1" + remark-rehype "^11.1.2" + scroll-into-view-if-needed "^3.1.0" + shiki "^3.14.0" + unist-util-visit "^5.0.0" + +fumadocs-core@16.0.9: version "16.0.9" resolved "https://registry.yarnpkg.com/fumadocs-core/-/fumadocs-core-16.0.9.tgz#c0453dd894f0d23134226aadd5939afd1ecc7f41" integrity sha512-yLm2WOwohMNkekS7avrQk5g50B/4HI8mWx2ZAcb+EMbS2oFKQHeL+uL7nvtmuyQg8Z6j1qk8vilsyj0K/BdIoQ== @@ -4139,7 +4797,29 @@ fumadocs-typescript@^3.1.0: ts-morph "^25.0.1" unist-util-visit "^5.0.0" -fumadocs-ui@16.0.9, fumadocs-ui@^16.0.9: +fumadocs-ui@14.7.7: + version "14.7.7" + resolved "https://registry.yarnpkg.com/fumadocs-ui/-/fumadocs-ui-14.7.7.tgz#98f86aa2da9dbe5f6c9ba2c2db682a3aa7d2c152" + integrity sha512-DLx5CT1CQljMzZVJZ5wZ4R8/s1QhMIbKJHaqFpy3mnylilclFqncoyA2BI5YbuqH6g4zywgPKdgZKNTZ0KnS6A== + dependencies: + "@radix-ui/react-accordion" "^1.2.2" + "@radix-ui/react-collapsible" "^1.1.2" + "@radix-ui/react-dialog" "^1.1.4" + "@radix-ui/react-direction" "^1.1.0" + "@radix-ui/react-navigation-menu" "^1.2.3" + "@radix-ui/react-popover" "^1.1.4" + "@radix-ui/react-scroll-area" "^1.2.2" + "@radix-ui/react-slot" "^1.1.1" + "@radix-ui/react-tabs" "^1.1.2" + class-variance-authority "^0.7.1" + lodash.merge "^4.6.2" + lucide-react "^0.473.0" + next-themes "^0.4.4" + postcss-selector-parser "^7.0.0" + react-medium-image-zoom "^5.2.13" + tailwind-merge "^2.6.0" + +fumadocs-ui@16.0.9: version "16.0.9" resolved "https://registry.yarnpkg.com/fumadocs-ui/-/fumadocs-ui-16.0.9.tgz#467520a1167744249de2d3c644af771e1bc50a19" integrity sha512-Ksuc3hi0f3iQmOT8C0XAA69KVKzClI7HDdFFsTpyPlGdEgGGNnqVobvb4tLFBA8dVVCKtL/h4jYggSJr4xMJgA== @@ -4163,6 +4843,30 @@ fumadocs-ui@16.0.9, fumadocs-ui@^16.0.9: scroll-into-view-if-needed "^3.1.0" tailwind-merge "^3.3.1" +fumadocs-ui@^16.0.9: + version "16.0.11" + resolved "https://registry.yarnpkg.com/fumadocs-ui/-/fumadocs-ui-16.0.11.tgz#625c35f8947232e72b6ead0ddfa4ae65da82852c" + integrity sha512-GyuDm4G2t8RJyfzUUOYhQL1mA0i6yE51dEnvtBTGtkZQ1RWIGqLqoNLkIA6gp82mHfvQsbgmIJdfUQ3tDVH1NA== + dependencies: + "@radix-ui/react-accordion" "^1.2.12" + "@radix-ui/react-collapsible" "^1.1.12" + "@radix-ui/react-dialog" "^1.1.15" + "@radix-ui/react-direction" "^1.1.1" + "@radix-ui/react-navigation-menu" "^1.2.14" + "@radix-ui/react-popover" "^1.1.15" + "@radix-ui/react-presence" "^1.1.5" + "@radix-ui/react-scroll-area" "^1.2.10" + "@radix-ui/react-slot" "^1.2.4" + "@radix-ui/react-tabs" "^1.1.13" + class-variance-authority "^0.7.1" + fumadocs-core "16.0.11" + lodash.merge "^4.6.2" + next-themes "^0.4.6" + postcss-selector-parser "^7.1.0" + react-medium-image-zoom "^5.4.0" + scroll-into-view-if-needed "^3.1.0" + tailwind-merge "^3.3.1" + function-bind@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" @@ -4238,17 +4942,34 @@ glob-parent@^5.1.2: dependencies: is-glob "^4.0.1" +glob@^7.1.3, glob@^7.1.4, glob@^7.2.3: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + globals@^15.15.0: version "15.15.0" resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== +glsl-noise@^0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/glsl-noise/-/glsl-noise-0.0.0.tgz#367745f3a33382c0eeec4cb54b7e99cfc1d7670b" + integrity sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w== + gopd@^1.0.1, gopd@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== -graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -4363,7 +5084,7 @@ hast-util-parse-selector@^4.0.0: dependencies: "@types/hast" "^3.0.0" -hast-util-to-estree@^3.0.0, hast-util-to-estree@^3.1.2, hast-util-to-estree@^3.1.3: +hast-util-to-estree@^3.0.0, hast-util-to-estree@^3.1.1, hast-util-to-estree@^3.1.2, hast-util-to-estree@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz#e654c1c9374645135695cc0ab9f70b8fcaf733d7" integrity sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w== @@ -4385,7 +5106,7 @@ hast-util-to-estree@^3.0.0, hast-util-to-estree@^3.1.2, hast-util-to-estree@^3.1 unist-util-position "^5.0.0" zwitch "^2.0.0" -hast-util-to-html@^9.0.5: +hast-util-to-html@^9.0.4, hast-util-to-html@^9.0.5: version "9.0.5" resolved "https://registry.yarnpkg.com/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz#ccc673a55bb8e85775b08ac28380f72d47167005" integrity sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw== @@ -4402,7 +5123,7 @@ hast-util-to-html@^9.0.5: stringify-entities "^4.0.0" zwitch "^2.0.4" -hast-util-to-jsx-runtime@^2.0.0, hast-util-to-jsx-runtime@^2.3.5, hast-util-to-jsx-runtime@^2.3.6: +hast-util-to-jsx-runtime@^2.0.0, hast-util-to-jsx-runtime@^2.3.2, hast-util-to-jsx-runtime@^2.3.5, hast-util-to-jsx-runtime@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz#ff31897aae59f62232e21594eac7ef6b63333e98" integrity sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg== @@ -4472,6 +5193,11 @@ hdr-histogram-percentiles-obj@^3.0.0: resolved "https://registry.yarnpkg.com/hdr-histogram-percentiles-obj/-/hdr-histogram-percentiles-obj-3.0.0.tgz#9409f4de0c2dda78e61de2d9d78b1e9f3cba283c" integrity sha512-7kIufnBqdsBGcSZLPJwqHT3yhk1QTsSlFsVD3kx5ixH/AlgBs9yM1q6DPhXZ8f8gtdqgh7N7/5btRLpQsS2gHw== +hls.js@^1.5.17: + version "1.6.13" + resolved "https://registry.yarnpkg.com/hls.js/-/hls.js-1.6.13.tgz#fcf2823f17aaf9127b9011ef135cae5d2520ab75" + integrity sha512-hNEzjZNHf5bFrUNvdS4/1RjIanuJ6szpWNfTaX5I6WfGynWXGT7K/YQLYtemSvFExzeMdgdE4SsyVLJbd5PcZA== + html-void-elements@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-3.0.0.tgz#fc9dbd84af9e747249034d4d62602def6517f1d7" @@ -4503,17 +5229,37 @@ idb@^8.0.3: resolved "https://registry.yarnpkg.com/idb/-/idb-8.0.3.tgz#c91e558f15a8d53f1d7f53a094d226fc3ad71fd9" integrity sha512-LtwtVyVYO5BqRvcsKuB2iUMnHwPVByPCXFXOpuU96IZPPoPN6xjOGxZQ74pgSVVLQWtUOYgyeL4GE98BY5D3wg== -ieee754@^1.1.13: +ieee754@^1.1.13, ieee754@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== +image-size@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/image-size/-/image-size-1.2.1.tgz#ee118aedfe666db1a6ee12bed5821cde3740276d" + integrity sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw== + dependencies: + queue "6.0.2" + image-size@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/image-size/-/image-size-2.0.2.tgz#84a7b43704db5736f364bf0d1b029821299b4bdc" integrity sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w== -inherits@^2.0.3: +immediate@~3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.0.6.tgz#9db1dbd0faf8de6fbe0f5dd5e56bb606280de69b" + integrity sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.0, inherits@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== @@ -4627,6 +5373,11 @@ is-plain-obj@^4.0.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-4.1.0.tgz#d65025edec3657ce032fd7db63c97883eaed71f0" integrity sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg== +is-promise@^2.1.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" + integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== + is-regex@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" @@ -4644,12 +5395,34 @@ is-typed-array@^1.1.3: dependencies: which-typed-array "^1.1.16" +isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + isows@1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== -jiti@^2.4.2, jiti@^2.6.1: +its-fine@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/its-fine/-/its-fine-2.0.0.tgz#a90b18a3ee4c211a1fb6faac2abcc2b682ce1f21" + integrity sha512-KLViCmWx94zOvpLwSlsx6yOCeMhZYaxrJV87Po5k/FoZzcPSahvK5qJ7fYhS61sZi5ikmh2S3Hz55A2l3U69ng== + dependencies: + "@types/react-reconciler" "^0.28.9" + +jiti@^2.4.2: + version "2.5.1" + resolved "https://registry.npmjs.org/jiti/-/jiti-2.5.1.tgz" + integrity sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w== + +jiti@^2.6.1: version "2.6.1" resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.6.1.tgz#178ef2fc9a1a594248c20627cd820187a4d78d92" integrity sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ== @@ -4715,6 +5488,16 @@ jsonpointer@^5.0.1: resolved "https://registry.yarnpkg.com/jsonpointer/-/jsonpointer-5.0.1.tgz#2110e0af0900fd37467b5907ecd13a7884a1b559" integrity sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ== +jszip@^3.10.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/jszip/-/jszip-3.10.1.tgz#34aee70eb18ea1faec2f589208a157d1feb091c2" + integrity sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g== + dependencies: + lie "~3.3.0" + pako "~1.0.2" + readable-stream "~2.3.6" + setimmediate "^1.0.5" + katex@^0.16.0, katex@^0.16.22: version "0.16.25" resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.25.tgz#61699984277e3bdb3e89e0e446b83cd0a57d87db" @@ -4758,6 +5541,13 @@ layout-base@^2.0.0: resolved "https://registry.yarnpkg.com/layout-base/-/layout-base-2.0.1.tgz#d0337913586c90f9c2c075292069f5c2da5dd285" integrity sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg== +lazystream@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/lazystream/-/lazystream-1.0.1.tgz#494c831062f1f9408251ec44db1cba29242a2638" + integrity sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw== + dependencies: + readable-stream "^2.0.5" + leaflet@^1.9.4: version "1.9.4" resolved "https://registry.yarnpkg.com/leaflet/-/leaflet-1.9.4.tgz#23fae724e282fa25745aff82ca4d394748db7d8d" @@ -4768,6 +5558,13 @@ leven@^4.0.0: resolved "https://registry.yarnpkg.com/leven/-/leven-4.1.0.tgz#1e37150e1711d18bb14e380a5c779995235a710e" integrity sha512-KZ9W9nWDT7rF7Dazg8xyLHGLrmpgq2nVNFUckhqdW3szVP6YhCpp/RAnpmVExA9JvrMynjwSLVrEj3AepHR6ew== +lie@^3.0.2, lie@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/lie/-/lie-3.3.0.tgz#dcf82dee545f46074daf200c7c1c5a08e0f40f6a" + integrity sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ== + dependencies: + immediate "~3.0.5" + lightningcss-android-arm64@1.30.2: version "1.30.2" resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.30.2.tgz#6966b7024d39c94994008b548b71ab360eb3a307" @@ -4842,6 +5639,11 @@ lightningcss@1.30.2: lightningcss-win32-arm64-msvc "1.30.2" lightningcss-win32-x64-msvc "1.30.2" +listenercount@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/listenercount/-/listenercount-1.0.1.tgz#84c8a72ab59c4725321480c975e6508342e70937" + integrity sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ== + local-pkg@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5" @@ -4866,16 +5668,76 @@ lodash.clonedeep@^4.5.0: resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== +lodash.defaults@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ== + +lodash.difference@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.difference/-/lodash.difference-4.5.0.tgz#9ccb4e505d486b91651345772885a2df27fd017c" + integrity sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA== + +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + integrity sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw== + lodash.flatten@^4.4.0: version "4.4.0" resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" integrity sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g== +lodash.groupby@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.groupby/-/lodash.groupby-4.6.0.tgz#0b08a1dcf68397c397855c3239783832df7403d1" + integrity sha512-5dcWxm23+VAoz+awKmBaiBvzox8+RqMgFhi7UvX9DHZr2HdxHXM/Wrf8cfKpsW37RNrvtPn6hSwNqurSILbmJw== + +lodash.isboolean@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6" + integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg== + +lodash.isequal@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" + integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ== + +lodash.isfunction@^3.0.9: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + integrity sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw== + +lodash.isnil@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/lodash.isnil/-/lodash.isnil-4.0.0.tgz#49e28cd559013458c814c5479d3c663a21bfaa6c" + integrity sha512-up2Mzq3545mwVnMhTDMdfoG1OurpA/s5t88JmQX809eH3C8491iu2sfKhTfhQtKY78oPNhiaHJUpT/dUDAAtng== + +lodash.isplainobject@^4.0.6: + version "4.0.6" + resolved "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz" + integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA== + +lodash.isundefined@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/lodash.isundefined/-/lodash.isundefined-3.0.1.tgz#23ef3d9535565203a66cefd5b830f848911afb48" + integrity sha512-MXB1is3s899/cD8jheYYE2V9qTHwKvt+npCwpD+1Sxm3Q3cECXCiYHjeHWXNwr6Q0SOBPrYUDxendrO6goVTEA== + lodash.merge@^4.6.2: version "4.6.2" resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== +lodash.union@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.union/-/lodash.union-4.6.0.tgz#48bb5088409f16f1821666641c44dd1aaae3cd88" + integrity sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw== + +lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== + lodash@^4.17.20, lodash@^4.17.21: version "4.17.21" resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" @@ -4910,12 +5772,29 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +lucide-react@^0.473.0: + version "0.473.0" + resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.473.0.tgz#f01dcde458e55bce766a282f4f5894970a9f24ac" + integrity sha512-KW6u5AKeIjkvrxXZ6WuCu9zHE/gEYSXCay+Gre2ZoInD0Je/e3RBtP4OHpJVJ40nDklSvjVKjgH7VU8/e2dzRw== + lucide-react@^0.544.0: version "0.544.0" resolved "https://registry.yarnpkg.com/lucide-react/-/lucide-react-0.544.0.tgz#4719953c10fd53a64dd8343bb0ed16ec79f3eeef" integrity sha512-t5tS44bqd825zAW45UQxpG2CvcC4urOwn2TrwSH8u+MjeE+1NnWl6QqeQ/6NdjMqdOygyiT9p3Ev0p1NJykxjw== -magic-string@^0.30.12, magic-string@^0.30.19: +maath@^0.10.8: + version "0.10.8" + resolved "https://registry.yarnpkg.com/maath/-/maath-0.10.8.tgz#cf647544430141bf6982da6e878abb6c4b804e24" + integrity sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g== + +magic-string@^0.30.12: + version "0.30.19" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz" + integrity sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +magic-string@^0.30.19: version "0.30.21" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== @@ -5182,6 +6061,16 @@ mermaid@^11.11.0: ts-dedent "^2.2.0" uuid "^11.1.0" +meshline@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/meshline/-/meshline-3.3.1.tgz#20decfd5cdd25c8469e862ddf0ab1ad167759734" + integrity sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ== + +meshoptimizer@~0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/meshoptimizer/-/meshoptimizer-0.22.0.tgz#1ec36b075543e7d661f5ebc21339ae3dab4bc18c" + integrity sha512-IebiK79sqIy+E4EgOr+CAw+Ke8hAspXKzBd0JdgEmPHiAwmvEj2S4h1rfvo+o/BnfEYd/jAOg5IeeIjzlzSnDg== + micro-eth-signer@0.7.2: version "0.7.2" resolved "https://registry.yarnpkg.com/micro-eth-signer/-/micro-eth-signer-0.7.2.tgz#e07b6524ce47a75d80752eaba69823396529b2a2" @@ -5607,6 +6496,20 @@ minimatch@^10.0.1: dependencies: "@isaacs/brace-expansion" "^5.0.0" +minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.1.0: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + minimatch@^9.0.4: version "9.0.5" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" @@ -5614,11 +6517,18 @@ minimatch@^9.0.4: dependencies: brace-expansion "^2.0.1" -minimist@^1.1.0: +minimist@^1.1.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +"mkdirp@>=0.5 0": + version "0.5.6" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" + integrity sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw== + dependencies: + minimist "^1.2.6" + mlly@^1.7.4: version "1.8.0" resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" @@ -5688,7 +6598,7 @@ next-mdx-remote@^5.0.0: vfile "^6.0.1" vfile-matter "^5.0.0" -next-themes@^0.4.6: +next-themes@^0.4.4, next-themes@^0.4.6: version "0.4.6" resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.4.6.tgz#8d7e92d03b8fea6582892a50a928c9b23502e8b6" integrity sha512-pZvgD5L0IEvX5/9GWyHMf3m8BKiVQwsCMHfoFosXtXBMnaS0ZnIJ9ST4b4NqLVKDEm8QBxoNNGNaBv2JNF6XNA== @@ -5726,6 +6636,11 @@ node-fetch@^2.7.0: dependencies: whatwg-url "^5.0.0" +normalize-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + npm-to-yarn@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/npm-to-yarn/-/npm-to-yarn-3.0.1.tgz" @@ -5772,11 +6687,27 @@ on-net-listen@^1.1.1: resolved "https://registry.yarnpkg.com/on-net-listen/-/on-net-listen-1.1.2.tgz#671e55a81c910fa7e5b1e4d506545e9ea0f2e11c" integrity sha512-y1HRYy8s/RlcBvDUwKXSmkODMdx4KSuIvloCnQYJ2LdBBC1asY4HtfhXwe3UWknLakATZDnbzht2Ijw3M1EqFg== +once@^1.3.0, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + oniguruma-parser@^0.12.1: version "0.12.1" resolved "https://registry.yarnpkg.com/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz#82ba2208d7a2b69ee344b7efe0ae930c627dcc4a" integrity sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w== +oniguruma-to-es@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-3.1.1.tgz#480e4bac4d3bc9439ac0d2124f0725e7a0d76d17" + integrity sha512-bUH8SDvPkH3ho3dvwJwfonjlQ4R80vjyvrU8YpxuROddv55vAEJrTuCuCVUhhsHbtlD9tGGbaNApGQckXhS8iQ== + dependencies: + emoji-regex-xs "^1.0.0" + regex "^6.0.1" + regex-recursion "^6.0.2" + oniguruma-to-es@^4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/oniguruma-to-es/-/oniguruma-to-es-4.3.3.tgz#50db2c1e28ec365e102c1863dfd3d1d1ad18613e" @@ -5824,7 +6755,7 @@ package-manager-detector@^1.3.0: resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.5.0.tgz#8dcf7b78554047ddf5da453e6ba07ebc915c507e" integrity sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw== -pako@^1.0.10, pako@^1.0.11, pako@^1.0.3, pako@^1.0.6: +pako@^1.0.10, pako@^1.0.11, pako@^1.0.3, pako@^1.0.6, pako@~1.0.2: version "1.0.11" resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== @@ -5859,6 +6790,16 @@ path-data-parser@0.1.0, path-data-parser@^0.1.0: resolved "https://registry.yarnpkg.com/path-data-parser/-/path-data-parser-0.1.0.tgz#8f5ba5cc70fc7becb3dcefaea08e2659aba60b8c" integrity sha512-NOnmBpt5Y2RWbuv0LMzsayp3lVylAHLPUTut412ZA3l+C4uw4ZVkQbjShYCQ8TCpUMdPapr4YjUqLYD6v68j+w== +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-to-regexp@^8.3.0: version "8.3.0" resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f" @@ -5953,7 +6894,7 @@ postcss-selector-parser@6.0.10: cssesc "^3.0.0" util-deprecate "^1.0.2" -postcss-selector-parser@^7.1.0: +postcss-selector-parser@^7.0.0, postcss-selector-parser@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-7.1.0.tgz#4d6af97eba65d73bc4d84bcb343e865d7dd16262" integrity sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA== @@ -5990,6 +6931,11 @@ posthog-js@^1.266.0: preact "^10.19.3" web-vitals "^4.2.4" +potpack@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/potpack/-/potpack-1.0.2.tgz#23b99e64eb74f5741ffe7656b5b5c4ddce8dfc14" + integrity sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ== + preact-render-to-string@^5.1.19: version "5.2.6" resolved "https://registry.yarnpkg.com/preact-render-to-string/-/preact-render-to-string-5.2.6.tgz#0ff0c86cd118d30affb825193f18e92bd59d0604" @@ -6025,11 +6971,24 @@ prismjs@^1.30.0: resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9" integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + progress@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8" integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA== +promise-worker-transferable@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/promise-worker-transferable/-/promise-worker-transferable-1.0.4.tgz#2c72861ba053e5ae42b487b4a83b1ed3ae3786e8" + integrity sha512-bN+0ehEnrXfxV2ZQvU2PetO0n4gqBD4ulq3MI1WOPLgr7/Mg9yRQkX5+0v1vagr74ZTsl7XtzlaYDo2EuCeYJw== + dependencies: + is-promise "^2.1.0" + lie "^3.0.2" + prop-types@^15.6.2, prop-types@^15.8.1: version "15.8.1" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5" @@ -6076,6 +7035,13 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +queue@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/queue/-/queue-6.0.2.tgz#b91525283e2315c7553d2efa18d83e76432fed65" + integrity sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA== + dependencies: + inherits "~2.0.3" + rc9@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/rc9/-/rc9-2.1.2.tgz#6282ff638a50caa0a91a31d76af4a0b9cbd1080d" @@ -6084,10 +7050,14 @@ rc9@^2.1.2: defu "^6.1.4" destr "^2.0.3" -react-day-picker@8.10.1: - version "8.10.1" - resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-8.10.1.tgz#4762ec298865919b93ec09ba69621580835b8e80" - integrity sha512-TMx7fNbhLk15eqcMt+7Z7S2KF7mfTId/XJDjKE8f+IUcFn0l08/kI4FiYTL/0yuOLmEcbR4Fwe3GJf/NiiMnPA== +react-day-picker@^9.11.1: + version "9.11.1" + resolved "https://registry.yarnpkg.com/react-day-picker/-/react-day-picker-9.11.1.tgz#00ea070eb2c011b038c3332f37cd87d4db251bba" + integrity sha512-l3ub6o8NlchqIjPKrRFUCkTUEq6KwemQlfv3XZzzwpUeGwmDJ+0u0Upmt38hJyd7D/vn2dQoOoLV/qAp0o3uUw== + dependencies: + "@date-fns/tz" "^1.4.1" + date-fns "^4.1.0" + date-fns-jalali "^4.1.0-0" react-dom@^19.2.0: version "19.2.0" @@ -6125,11 +7095,18 @@ react-leaflet@^5.0.0: dependencies: "@react-leaflet/core" "^3.0.0" -react-medium-image-zoom@^5.4.0: +react-medium-image-zoom@^5.2.13, react-medium-image-zoom@^5.4.0: version "5.4.0" resolved "https://registry.npmjs.org/react-medium-image-zoom/-/react-medium-image-zoom-5.4.0.tgz" integrity sha512-BsE+EnFVQzFIlyuuQrZ9iTwyKpKkqdFZV1ImEQN573QPqGrIUuNni7aF+sZwDcxlsuOMayCr6oO/PZR/yJnbRg== +react-reconciler@^0.31.0: + version "0.31.0" + resolved "https://registry.yarnpkg.com/react-reconciler/-/react-reconciler-0.31.0.tgz#6b7390fe8fab59210daf523d7400943973de1458" + integrity sha512-7Ob7Z+URmesIsIVRjnLoDGwBEG/tVitidU0nMsqX/eeJaLY89RISO/10ERe0MqmzuKUUB1rmY+h1itMbUHg9BQ== + dependencies: + scheduler "^0.25.0" + react-remove-scroll-bar@^2.3.7: version "2.3.8" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" @@ -6138,7 +7115,7 @@ react-remove-scroll-bar@^2.3.7: react-style-singleton "^2.2.2" tslib "^2.0.0" -react-remove-scroll@^2.6.3: +react-remove-scroll@^2.6.2, react-remove-scroll@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz#d2101d414f6d81d7d3bf033f3c1cb4785789f753" integrity sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA== @@ -6181,11 +7158,45 @@ react-transition-group@^4.4.5: loose-envify "^1.4.0" prop-types "^15.6.2" +react-use-measure@^2.1.7: + version "2.1.7" + resolved "https://registry.yarnpkg.com/react-use-measure/-/react-use-measure-2.1.7.tgz#36b8a2e7fd2fa58109ab851b3addcb0aad66ad1d" + integrity sha512-KrvcAo13I/60HpwGO5jpW7E9DfusKyLPLvuHlUyP5zqnmAPhNc6qTRjUQrdTADl0lpPpDVU2/Gg51UlOGHXbdg== + react@^19.2.0: version "19.2.0" resolved "https://registry.yarnpkg.com/react/-/react-19.2.0.tgz#d33dd1721698f4376ae57a54098cb47fc75d93a5" integrity sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ== +readable-stream@^2.0.0, readable-stream@^2.0.2, readable-stream@^2.0.5, readable-stream@~2.3.6: + version "2.3.8" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.8.tgz#91125e8042bba1b9887f49345f6277027ce8be9b" + integrity sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdir-glob@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/readdir-glob/-/readdir-glob-1.1.3.tgz#c3d831f51f5e7bfa62fa2ffbe4b508c640f09584" + integrity sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA== + dependencies: + minimatch "^5.1.0" + readdirp@^4.0.1: version "4.1.2" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" @@ -6298,7 +7309,7 @@ reinterval@^1.1.0: resolved "https://registry.yarnpkg.com/reinterval/-/reinterval-1.1.0.tgz#3361ecfa3ca6c18283380dd0bb9546f390f5ece7" integrity sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ== -remark-gfm@^4.0.1: +remark-gfm@^4.0.0, remark-gfm@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/remark-gfm/-/remark-gfm-4.0.1.tgz#33227b2a74397670d357bf05c098eaf8513f0d6b" integrity sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg== @@ -6358,7 +7369,7 @@ remark-stringify@^11.0.0: mdast-util-to-markdown "^2.0.0" unified "^11.0.0" -remark@^15.0.1: +remark@^15.0.0, remark@^15.0.1: version "15.0.1" resolved "https://registry.yarnpkg.com/remark/-/remark-15.0.1.tgz#ac7e7563260513b66426bc47f850e7aa5862c37c" integrity sha512-Eht5w30ruCXgFmxVUSlNWQ9iiimq07URKeFS3hNc8cUWy1llX4KDWfyEDZRycMc+znsN9Ux5/tJ/BFdgdOwA3A== @@ -6393,6 +7404,13 @@ reusify@^1.0.4: resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== +rimraf@2: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + robust-predicates@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/robust-predicates/-/robust-predicates-3.0.2.tgz#d5b28528c4824d20fc48df1928d41d9efa1ad771" @@ -6451,6 +7469,16 @@ rw@1: resolved "https://registry.yarnpkg.com/rw/-/rw-1.3.3.tgz#3f862dfa91ab766b14885ef4d01124bfda074fb4" integrity sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ== +safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-regex-test@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" @@ -6466,9 +7494,21 @@ safe-regex-test@^1.1.0: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sax@^1.2.4: - version "1.4.2" - resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.2.tgz#c5e2f69e013e58bbdb4d8a97de319e236d6c68c6" - integrity sha512-FySGAa0RGcFiN6zfrO9JvK1r7TB59xuzCcTHOBXBNoKgDejlOQCR2KL/FGk3/iDlsqyYg1ELZpOmlg09B01Czw== + version "1.4.3" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.3.tgz#fcebae3b756cdc8428321805f4b70f16ec0ab5db" + integrity sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ== + +saxes@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/saxes/-/saxes-5.0.1.tgz#eebab953fa3b7608dbe94e5dadb15c888fa6696d" + integrity sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw== + dependencies: + xmlchars "^2.2.0" + +scheduler@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.25.0.tgz#336cd9768e8cceebf52d3c80e3dcf5de23e7e015" + integrity sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA== scheduler@^0.27.0: version "0.27.0" @@ -6495,7 +7535,7 @@ secure-json-parse@^2.7.0: resolved "https://registry.yarnpkg.com/secure-json-parse/-/secure-json-parse-2.7.0.tgz#5a5f9cd6ae47df23dba3151edd06855d47e09862" integrity sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw== -semver@^7.3.2, semver@^7.6.2, semver@^7.7.2: +semver@^7.3.2, semver@^7.6.2, semver@^7.7.2, semver@^7.7.3: version "7.7.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.3.tgz#4b5f4143d007633a8dc671cd0a6ef9147b8bb946" integrity sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q== @@ -6512,49 +7552,96 @@ set-function-length@^1.2.2: gopd "^1.0.1" has-property-descriptors "^1.0.2" +setimmediate@^1.0.5, setimmediate@~1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA== + sharp@^0.34.4: - version "0.34.4" - resolved "https://registry.npmjs.org/sharp/-/sharp-0.34.4.tgz" - integrity sha512-FUH39xp3SBPnxWvd5iib1X8XY7J0K0X7d93sie9CJg2PO8/7gmg89Nve6OjItK53/MlAushNNxteBYfM6DEuoA== + version "0.34.5" + resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.34.5.tgz#b6f148e4b8c61f1797bde11a9d1cfebbae2c57b0" + integrity sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg== dependencies: "@img/colour" "^1.0.0" - detect-libc "^2.1.0" - semver "^7.7.2" + detect-libc "^2.1.2" + semver "^7.7.3" optionalDependencies: - "@img/sharp-darwin-arm64" "0.34.4" - "@img/sharp-darwin-x64" "0.34.4" - "@img/sharp-libvips-darwin-arm64" "1.2.3" - "@img/sharp-libvips-darwin-x64" "1.2.3" - "@img/sharp-libvips-linux-arm" "1.2.3" - "@img/sharp-libvips-linux-arm64" "1.2.3" - "@img/sharp-libvips-linux-ppc64" "1.2.3" - "@img/sharp-libvips-linux-s390x" "1.2.3" - "@img/sharp-libvips-linux-x64" "1.2.3" - "@img/sharp-libvips-linuxmusl-arm64" "1.2.3" - "@img/sharp-libvips-linuxmusl-x64" "1.2.3" - "@img/sharp-linux-arm" "0.34.4" - "@img/sharp-linux-arm64" "0.34.4" - "@img/sharp-linux-ppc64" "0.34.4" - "@img/sharp-linux-s390x" "0.34.4" - "@img/sharp-linux-x64" "0.34.4" - "@img/sharp-linuxmusl-arm64" "0.34.4" - "@img/sharp-linuxmusl-x64" "0.34.4" - "@img/sharp-wasm32" "0.34.4" - "@img/sharp-win32-arm64" "0.34.4" - "@img/sharp-win32-ia32" "0.34.4" - "@img/sharp-win32-x64" "0.34.4" - -shiki@3.14.0, shiki@^3.1.0, shiki@^3.13.0, shiki@^3.14.0: - version "3.14.0" - resolved "https://registry.yarnpkg.com/shiki/-/shiki-3.14.0.tgz#fd38c387a41c918d709252d2d7d85ce63351d88d" - integrity sha512-J0yvpLI7LSig3Z3acIuDLouV5UCKQqu8qOArwMx+/yPVC3WRMgrP67beaG8F+j4xfEWE0eVC4GeBCIXeOPra1g== + "@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" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== dependencies: - "@shikijs/core" "3.14.0" - "@shikijs/engine-javascript" "3.14.0" - "@shikijs/engine-oniguruma" "3.14.0" - "@shikijs/langs" "3.14.0" - "@shikijs/themes" "3.14.0" - "@shikijs/types" "3.14.0" + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shiki@2.5.0, shiki@^2.0.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-2.5.0.tgz#09d01ebf3b0b06580431ce3ddc023320442cf223" + integrity sha512-mI//trrsaiCIPsja5CNfsyNOqgAZUb6VpJA+340toL42UpzQlXpwRV9nch69X6gaUxrr9kaOOa6e3y3uAkGFxQ== + dependencies: + "@shikijs/core" "2.5.0" + "@shikijs/engine-javascript" "2.5.0" + "@shikijs/engine-oniguruma" "2.5.0" + "@shikijs/langs" "2.5.0" + "@shikijs/themes" "2.5.0" + "@shikijs/types" "2.5.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + +shiki@3.15.0, shiki@^3.14.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-3.15.0.tgz#27cb37a080f987a4ec3a0402137b72f7400b8ea4" + integrity sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw== + dependencies: + "@shikijs/core" "3.15.0" + "@shikijs/engine-javascript" "3.15.0" + "@shikijs/engine-oniguruma" "3.15.0" + "@shikijs/langs" "3.15.0" + "@shikijs/themes" "3.15.0" + "@shikijs/types" "3.15.0" + "@shikijs/vscode-textmate" "^10.0.2" + "@types/hast" "^3.0.4" + +shiki@^3.1.0, shiki@^3.13.0: + version "3.13.0" + resolved "https://registry.npmjs.org/shiki/-/shiki-3.13.0.tgz" + integrity sha512-aZW4l8Og16CokuCLf8CF8kq+KK2yOygapU5m3+hoGw0Mdosc6fPitjM+ujYarppj5ZIKGyPDPP1vqmQhr+5/0g== + dependencies: + "@shikijs/core" "3.13.0" + "@shikijs/engine-javascript" "3.13.0" + "@shikijs/engine-oniguruma" "3.13.0" + "@shikijs/langs" "3.13.0" + "@shikijs/themes" "3.13.0" + "@shikijs/types" "3.13.0" "@shikijs/vscode-textmate" "^10.0.2" "@types/hast" "^3.0.4" @@ -6598,6 +7685,19 @@ stackback@0.0.2: resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== +stats-gl@^2.2.8: + version "2.4.2" + resolved "https://registry.yarnpkg.com/stats-gl/-/stats-gl-2.4.2.tgz#28a6c869fc3a36a8be608ef21df63c0aad99d1ba" + integrity sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ== + dependencies: + "@types/three" "*" + three "^0.170.0" + +stats.js@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/stats.js/-/stats.js-0.17.0.tgz#b1c3dc46d94498b578b7fd3985b81ace7131cc7d" + integrity sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw== + std-env@^3.8.0: version "3.10.0" resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" @@ -6612,6 +7712,20 @@ string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + stringify-entities@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/stringify-entities/-/stringify-entities-4.0.4.tgz#b3b79ef5f277cc4ac73caeb0236c5ba939b3a4f3" @@ -6670,6 +7784,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +suspend-react@^0.1.3: + version "0.1.3" + resolved "https://registry.yarnpkg.com/suspend-react/-/suspend-react-0.1.3.tgz#a52f49d21cfae9a2fb70bd0c68413d3f9d90768e" + integrity sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ== + swr@^2.2.5: version "2.3.6" resolved "https://registry.yarnpkg.com/swr/-/swr-2.3.6.tgz#5fee0ee8a0762a16871ee371075cb09422b64f50" @@ -6678,6 +7797,11 @@ swr@^2.2.5: dequal "^2.0.3" use-sync-external-store "^1.4.0" +tailwind-merge@^2.6.0: + version "2.6.0" + resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-2.6.0.tgz#ac5fb7e227910c038d458f396b7400d93a3142d5" + integrity sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA== + tailwind-merge@^3.3.1: version "3.3.1" resolved "https://registry.yarnpkg.com/tailwind-merge/-/tailwind-merge-3.3.1.tgz#a7e7db7c714f6020319e626ecfb7e7dac8393a4b" @@ -6694,15 +7818,53 @@ tailwindcss@4.1.16, tailwindcss@^4.1.13: integrity sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA== tapable@^2.2.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.3.0.tgz#7e3ea6d5ca31ba8e078b560f0d83ce9a14aa8be6" - integrity sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg== + version "2.2.3" + resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz" + integrity sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg== + +tar-stream@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" third-party-capital@1.0.20: version "1.0.20" resolved "https://registry.yarnpkg.com/third-party-capital/-/third-party-capital-1.0.20.tgz#e218a929a35bf4d2245da9addb8ab978d2f41685" integrity sha512-oB7yIimd8SuGptespDAZnNkzIz+NWaJCu2RMsbs4Wmp9zSDUM8Nhi3s2OOcqYuv3mN4hitXc8DVx+LyUmbUDiA== +three-mesh-bvh@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/three-mesh-bvh/-/three-mesh-bvh-0.8.3.tgz#c5e72472e7f062ff79084157a25c122d73184163" + integrity sha512-4G5lBaF+g2auKX3P0yqx+MJC6oVt6sB5k+CchS6Ob0qvH0YIhuUk1eYr7ktsIpY+albCqE80/FVQGV190PmiAg== + +three-stdlib@^2.35.6: + version "2.36.0" + resolved "https://registry.yarnpkg.com/three-stdlib/-/three-stdlib-2.36.0.tgz#1d806b8db9156a6c87ed10f61f56f8a3ab634b42" + integrity sha512-kv0Byb++AXztEGsULgMAs8U2jgUdz6HPpAB/wDJnLiLlaWQX2APHhiTJIN7rqW+Of0eRgcp7jn05U1BsCP3xBA== + dependencies: + "@types/draco3d" "^1.4.0" + "@types/offscreencanvas" "^2019.6.4" + "@types/webxr" "^0.5.2" + draco3d "^1.4.1" + fflate "^0.6.9" + potpack "^1.0.1" + +three@^0.170.0: + version "0.170.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.170.0.tgz#6087f97aab79e9e9312f9c89fcef6808642dfbb7" + integrity sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ== + +three@^0.180.0: + version "0.180.0" + resolved "https://registry.yarnpkg.com/three/-/three-0.180.0.tgz#b930cabfb524f6d36bf63e874b4d866888b50487" + integrity sha512-o+qycAMZrh+TsE01GqWUxUIKR1AL0S8pq7zDkYOQw8GqfX8b8VoCKYUoHbhiX5j+7hr8XsuHDVU6+gkQJQKg9w== + throttleit@2.1.0, throttleit@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-2.1.0.tgz#a7e4aa0bf4845a5bd10daa39ea0c783f631a07b4" @@ -6756,6 +7918,11 @@ tinyspy@^3.0.2: resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-3.0.2.tgz#86dd3cf3d737b15adcf17d7887c84a75201df20a" integrity sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q== +tmp@^0.2.0: + version "0.2.5" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.5.tgz#b06bcd23f0f3c8357b426891726d16015abfd8f8" + integrity sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow== + to-regex-range@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" @@ -6768,11 +7935,49 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +"traverse@>=0.3.0 <0.4": + version "0.3.9" + resolved "https://registry.yarnpkg.com/traverse/-/traverse-0.3.9.tgz#717b8f220cc0bb7b44e40514c22b2e8bbc70d8b9" + integrity sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ== + +trieve-fumadocs-adapter@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/trieve-fumadocs-adapter/-/trieve-fumadocs-adapter-1.3.1.tgz#baf904812e4b6b1bd14f266ac1036107cb6e6e71" + integrity sha512-a/zPVgsZgyDopxbIw44HMUrzRUADq3z07dBxD9rAncID0AVB2hFSCUvw9qfbbdH/RObEVqfLh8VlDCUvh26JJg== + dependencies: + fumadocs-core "14.7.7" + fumadocs-ui "14.7.7" + +trieve-ts-sdk@^0.0.124: + version "0.0.124" + resolved "https://registry.yarnpkg.com/trieve-ts-sdk/-/trieve-ts-sdk-0.0.124.tgz#796c158753ef65c0c5d39a4f6fd2dd4d66fc2615" + integrity sha512-oIHuEA5lPE4C1EZGuKLbLlIWYtFCgnrP7Jsd57IhT41MOzzBl3ZqiCYwsUpsu9rPIfSJKa14kdledGOQvPDbKg== + trim-lines@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-3.0.1.tgz#d802e332a07df861c48802c04321017b1bd87338" integrity sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg== +troika-three-text@^0.52.4: + version "0.52.4" + resolved "https://registry.yarnpkg.com/troika-three-text/-/troika-three-text-0.52.4.tgz#f7b2389a2067d9506a5757457771cf4f6356e738" + integrity sha512-V50EwcYGruV5rUZ9F4aNsrytGdKcXKALjEtQXIOBfhVoZU9VAqZNIoGQ3TMiooVqFAbR1w15T+f+8gkzoFzawg== + dependencies: + bidi-js "^1.0.2" + troika-three-utils "^0.52.4" + troika-worker-utils "^0.52.0" + webgl-sdf-generator "1.1.1" + +troika-three-utils@^0.52.4: + version "0.52.4" + resolved "https://registry.yarnpkg.com/troika-three-utils/-/troika-three-utils-0.52.4.tgz#9292019e93cab97582af1cf491c4c895e5c03b66" + integrity sha512-NORAStSVa/BDiG52Mfudk4j1FG4jC4ILutB3foPnfGbOeIs9+G5vZLa0pnmnaftZUGm4UwSoqEpWdqvC7zms3A== + +troika-worker-utils@^0.52.0: + version "0.52.0" + resolved "https://registry.yarnpkg.com/troika-worker-utils/-/troika-worker-utils-0.52.0.tgz#ba5525fc444345006ebab0bc9cabdd66f1561e66" + integrity sha512-W1CpvTHykaPH5brv5VHLfQo9D1OYuo0cSBEUQFFT/nBUzM8iD6Lq2/tgG/f1OelbAS1WtaTPQzE5uM49egnngw== + trough@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/trough/-/trough-2.2.0.tgz#94a60bd6bd375c152c1df911a4b11d5b0256f50f" @@ -6799,16 +8004,16 @@ ts-morph@^26.0.0: "@ts-morph/common" "~0.27.0" code-block-writer "^13.0.3" +tslib@2, tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslib@^1.11.1: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.8.0, tslib@^2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" - integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== - tsx@^4.20.5: version "4.20.6" resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.20.6.tgz#8fb803fd9c1f70e8ccc93b5d7c5e03c3979ccb2e" @@ -6819,6 +8024,13 @@ tsx@^4.20.5: optionalDependencies: fsevents "~2.3.3" +tunnel-rat@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/tunnel-rat/-/tunnel-rat-0.1.2.tgz#1717efbc474ea2d8aa05a91622457a6e201c0aeb" + integrity sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ== + dependencies: + zustand "^4.3.2" + twoslash-protocol@0.3.4: version "0.3.4" resolved "https://registry.yarnpkg.com/twoslash-protocol/-/twoslash-protocol-0.3.4.tgz#276ccd73dbbc99e19d8df7214b28c01a04d2294a" @@ -6952,6 +8164,22 @@ unist-util-visit@^5.0.0: unist-util-is "^6.0.0" unist-util-visit-parents "^6.0.0" +unzipper@^0.10.11: + version "0.10.14" + resolved "https://registry.yarnpkg.com/unzipper/-/unzipper-0.10.14.tgz#d2b33c977714da0fbc0f82774ad35470a7c962b1" + integrity sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g== + dependencies: + big-integer "^1.6.17" + binary "~0.3.0" + bluebird "~3.4.1" + buffer-indexof-polyfill "~1.0.0" + duplexer2 "~0.1.4" + fstream "^1.0.12" + graceful-fs "^4.2.2" + listenercount "~1.0.1" + readable-stream "~2.3.6" + setimmediate "~1.0.4" + use-callback-ref@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" @@ -6967,12 +8195,17 @@ use-sidecar@^1.1.3: detect-node-es "^1.1.0" tslib "^2.0.0" -use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0: +use-sync-external-store@^1.2.2: version "1.6.0" resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz#b174bfa65cb2b526732d9f2ac0a408027876f32d" integrity sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w== -util-deprecate@^1.0.2: +use-sync-external-store@^1.4.0, use-sync-external-store@^1.5.0: + version "1.5.0" + resolved "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz" + integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A== + +util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== @@ -6988,6 +8221,11 @@ util@^0.12.5: is-typed-array "^1.1.3" which-typed-array "^1.1.2" +utility-types@^3.11.0: + version "3.11.0" + resolved "https://registry.yarnpkg.com/utility-types/-/utility-types-3.11.0.tgz#607c40edb4f258915e901ea7995607fdf319424c" + integrity sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw== + uuid-parse@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/uuid-parse/-/uuid-parse-1.1.0.tgz#7061c5a1384ae0e1f943c538094597e1b5f3a65b" @@ -6998,7 +8236,7 @@ uuid@^11.1.0: resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912" integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== -uuid@^8.3.2: +uuid@^8.3.0, uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== @@ -7169,6 +8407,16 @@ web-vitals@^4.2.4: resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.4.tgz#1d20bc8590a37769bd0902b289550936069184b7" integrity sha512-r4DIlprAGwJ7YM11VZp4R884m0Vmgr6EAKe3P+kO0PPj3Unqyvv59rczf6UiGcb9Z8QxZVcqKNwv/g0WNdWwsw== +webgl-constants@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/webgl-constants/-/webgl-constants-1.1.1.tgz#f9633ee87fea56647a60b9ce735cbdfb891c6855" + integrity sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg== + +webgl-sdf-generator@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz#3e1b422b3d87cd3cc77f2602c9db63bc0f6accbd" + integrity sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA== + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -7195,6 +8443,13 @@ which-typed-array@^1.1.16, which-typed-array@^1.1.2: gopd "^1.2.0" has-tostringtag "^1.0.2" +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + why-is-node-running@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04" @@ -7203,6 +8458,11 @@ why-is-node-running@^2.3.0: siginfo "^2.0.0" stackback "0.0.2" +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + ws@8.18.3: version "8.18.3" resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" @@ -7215,6 +8475,11 @@ xml-js@^1.6.11: dependencies: sax "^1.2.4" +xmlchars@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" + integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== + yallist@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" @@ -7230,6 +8495,15 @@ yaml@^2.0.0: resolved "https://registry.yarnpkg.com/yaml/-/yaml-2.8.1.tgz#1870aa02b631f7e8328b93f8bc574fac5d6c4d79" integrity sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw== +zip-stream@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/zip-stream/-/zip-stream-4.1.1.tgz#1337fe974dbaffd2fa9a1ba09662a66932bd7135" + integrity sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ== + dependencies: + archiver-utils "^3.0.4" + compress-commons "^4.1.2" + readable-stream "^3.6.0" + zod-to-json-schema@^3.24.1: version "3.24.6" resolved "https://registry.yarnpkg.com/zod-to-json-schema/-/zod-to-json-schema-3.24.6.tgz#5920f020c4d2647edfbb954fa036082b92c9e12d" @@ -7245,7 +8519,14 @@ zod@4.1.11: resolved "https://registry.yarnpkg.com/zod/-/zod-4.1.12.tgz#64f1ea53d00eab91853195653b5af9eee68970f0" integrity sha512-JInaHOamG8pt5+Ey8kGmdcAcg3OL9reK8ltczgHTAwNhMys/6ThXHityHxVV2p3fkw/c+MAvBHFVYHFZDmjMCQ== -zustand@^5.0.8: +zustand@^4.3.2: + version "4.5.7" + resolved "https://registry.yarnpkg.com/zustand/-/zustand-4.5.7.tgz#7d6bb2026a142415dd8be8891d7870e6dbe65f55" + integrity sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw== + dependencies: + use-sync-external-store "^1.2.2" + +zustand@^5.0.1, zustand@^5.0.3, zustand@^5.0.8: version "5.0.8" resolved "https://registry.yarnpkg.com/zustand/-/zustand-5.0.8.tgz#b998a0c088c7027a20f2709141a91cb07ac57f8a" integrity sha512-gyPKpIaxY9XcO2vSMrLbiER7QMAMGOQZVRdJ6Zi782jkbzZygq5GI9nG8g+sMgitRtndwaBSl7uiqC49o1SSiw==