diff --git a/app/components/elements/Toast.module.css b/app/components/elements/Toast.module.css new file mode 100644 index 000000000..b339c1255 --- /dev/null +++ b/app/components/elements/Toast.module.css @@ -0,0 +1,85 @@ +.toastRegion { + flex-direction: column; + gap: 8px; + display: flex; + position: fixed; + top: 55px; + right: 8px; + z-index: 1; +} + +.toast { + background: var(--bg-lighter-solid); + border-radius: var(--rounded); + padding: var(--s-1-5) var(--s-3); + align-items: center; + justify-content: center; + font-size: var(--fonts-xsm); + font-weight: var(--semi-bold); + gap: var(--s-1); + border: 2px solid var(--border); + width: 250px; + outline: none; + /* biome-ignore lint/correctness/noUnknownProperty: it exists */ + view-transition-class: toast; +} + +::view-transition-new(.toast):only-child { + animation: appear 400ms; +} + +::view-transition-old(.toast):only-child { + animation: disappear 400ms; +} + +@keyframes disappear { + to { + opacity: 0; + } +} + +@keyframes appear { + from { + opacity: 0; + } +} + +.errorToast { + border-color: var(--theme-error); +} + +.topRow { + display: flex; + text-transform: uppercase; + color: var(--text-lighter); + font-size: var(--fonts-xxsm); + gap: var(--s-2); + align-items: center; + margin-block-end: var(--s-1-5); +} + +.closeButton { + margin-inline-start: auto; + outline-color: var(--text-lighter) !important; +} + +.closeButton svg { + width: 1rem; + fill: var(--text-lighter); +} + +.alertIcon { + width: 1.25rem; +} + +.errorToast .alertIcon { + fill: var(--theme-error); +} + +.infoToast .alertIcon { + fill: var(--theme-info); +} + +.successToast .alertIcon { + fill: var(--theme-success); +} diff --git a/app/components/elements/Toast.tsx b/app/components/elements/Toast.tsx new file mode 100644 index 000000000..cfcd433df --- /dev/null +++ b/app/components/elements/Toast.tsx @@ -0,0 +1,70 @@ +import clsx from "clsx"; +import { + Text, + UNSTABLE_Toast as Toast, + UNSTABLE_ToastContent as ToastContent, + UNSTABLE_ToastQueue as ToastQueue, + UNSTABLE_ToastRegion as ToastRegion, +} from "react-aria-components"; +import { flushSync } from "react-dom"; +import { useTranslation } from "react-i18next"; +import { AlertIcon } from "../icons/Alert"; +import { CheckmarkIcon } from "../icons/Checkmark"; +import { CrossIcon } from "../icons/Cross"; +import { SendouButton } from "./Button"; +import styles from "./Toast.module.css"; + +export interface SendouToast { + message: string; + variant: "error" | "success" | "info"; +} + +export const toastQueue = new ToastQueue({ + wrapUpdate(fn) { + if ("startViewTransition" in document) { + document.startViewTransition(() => { + flushSync(fn); + }); + } else { + fn(); + } + }, +}); + +export function SendouToastRegion() { + const { t } = useTranslation(["common"]); + + return ( + + {({ toast }) => ( + + +
+ {toast.content.variant === "success" ? ( + + ) : ( + + )} + {t(`common:toasts.${toast.content.variant}`)} + } + className={styles.closeButton} + slot="close" + /> +
+ {toast.content.message} +
+
+ )} +
+ ); +} diff --git a/app/features/admin/actions/admin.server.ts b/app/features/admin/actions/admin.server.ts index 14e5f74eb..1aae50689 100644 --- a/app/features/admin/actions/admin.server.ts +++ b/app/features/admin/actions/admin.server.ts @@ -7,7 +7,11 @@ import { refreshBannedCache } from "~/features/ban/core/banned.server"; import * as UserRepository from "~/features/user-page/UserRepository.server"; import { isAdmin, isMod } from "~/permissions"; import { logger } from "~/utils/logger"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { + errorToastIfFalsy, + parseRequestPayload, + successToast, +} from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { _action, actualNumber, friendCode } from "~/utils/zod"; import { plusTiersFromVotingAndLeaderboard } from "../core/plus-tier.server"; @@ -19,26 +23,31 @@ export const action = async ({ request }: ActionFunctionArgs) => { }); const user = await requireUserId(request); + let message: string; switch (data._action) { case "MIGRATE": { - validate(isMod(user), "Admin needed", 401); + errorToastIfFalsy(isMod(user), "Admin needed"); await AdminRepository.migrate({ oldUserId: data["old-user"], newUserId: data["new-user"], }); + + message = "Account migrated"; break; } case "REFRESH": { - validate(isAdmin(user)); + errorToastIfFalsy(isAdmin(user), "Admin needed"); await AdminRepository.replacePlusTiers( await plusTiersFromVotingAndLeaderboard(), ); + + message = "Plus tiers refreshed"; break; } case "FORCE_PATRON": { - validate(isAdmin(user), "Admin needed", 401); + errorToastIfFalsy(isAdmin(user), "Admin needed"); await AdminRepository.forcePatron({ id: data.user, @@ -46,45 +55,56 @@ export const action = async ({ request }: ActionFunctionArgs) => { patronTier: data.patronTier, patronTill: new Date(data.patronTill), }); + + message = "Patron status updated"; break; } case "CLEAN_UP": { - validate(isAdmin(user), "Admin needed", 401); + errorToastIfFalsy(isAdmin(user), "Admin needed"); // on purpose sync AdminRepository.cleanUp(); + + message = "Clean up done"; break; } case "ARTIST": { - validate(isMod(user), "Mod needed", 401); + errorToastIfFalsy(isMod(user), "Mod needed"); makeArtist(data.user); + + message = "Artist permissions given"; break; } case "VIDEO_ADDER": { - validate(isMod(user), "Mod needed", 401); + errorToastIfFalsy(isMod(user), "Mod needed"); await AdminRepository.makeVideoAdderByUserId(data.user); + + message = "VoD adder permissions given"; break; } case "TOURNAMENT_ORGANIZER": { - validate(isMod(user), "Mod needed", 401); + errorToastIfFalsy(isMod(user), "Mod needed"); await AdminRepository.makeTournamentOrganizerByUserId(data.user); + + message = "Tournament permissions given"; break; } case "LINK_PLAYER": { - validate(isMod(user), "Mod needed", 401); + errorToastIfFalsy(isMod(user), "Mod needed"); await AdminRepository.linkUserAndPlayer({ userId: data.user, playerId: data.playerId, }); + message = "Linked user and player"; break; } case "BAN_USER": { - validate(isMod(user), "Mod needed", 401); + errorToastIfFalsy(isMod(user), "Mod needed"); await AdminRepository.banUser({ bannedReason: data.reason ?? null, @@ -103,10 +123,11 @@ export const action = async ({ request }: ActionFunctionArgs) => { : undefined, }); + message = "User banned"; break; } case "UNBAN_USER": { - validate(isMod(user), "Mod needed", 401); + errorToastIfFalsy(isMod(user), "Mod needed"); await AdminRepository.unbanUser(data.user); @@ -117,10 +138,11 @@ export const action = async ({ request }: ActionFunctionArgs) => { byUserId: user.id, }); + message = "User unbanned"; break; } case "UPDATE_FRIEND_CODE": { - validate(isMod(user), "Mod needed", 401); + errorToastIfFalsy(isMod(user), "Mod needed"); await UserRepository.insertFriendCode({ friendCode: data.friendCode, @@ -128,6 +150,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { userId: data.user, }); + message = "Friend code updated"; break; } default: { @@ -135,7 +158,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { } } - return { ok: true }; + return successToast(message); }; export const adminActionSchema = z.union([ diff --git a/app/features/api-private/routes/patrons.tsx b/app/features/api-private/routes/patrons.tsx index 78518daea..757ff4672 100644 --- a/app/features/api-private/routes/patrons.tsx +++ b/app/features/api-private/routes/patrons.tsx @@ -3,7 +3,7 @@ import { getUserId } from "~/features/auth/core/user.server"; import * as UserRepository from "~/features/user-page/UserRepository.server"; import { updatePatreonData } from "~/modules/patreon"; import { canAccessLohiEndpoint, canPerformAdminActions } from "~/permissions"; -import { validate } from "~/utils/remix.server"; +import { unauthorizedIfFalsy } from "~/utils/remix.server"; export const action: ActionFunction = async ({ request }) => { const user = await getUserId(request); @@ -18,7 +18,7 @@ export const action: ActionFunction = async ({ request }) => { }; export const loader = ({ request }: LoaderFunctionArgs) => { - validate(canAccessLohiEndpoint(request), "Invalid token", 403); + unauthorizedIfFalsy(canAccessLohiEndpoint(request)); return UserRepository.findAllPatrons(); }; diff --git a/app/features/art/routes/art.new.tsx b/app/features/art/routes/art.new.tsx index 0ffd7797c..9e0801577 100644 --- a/app/features/art/routes/art.new.tsx +++ b/app/features/art/routes/art.new.tsx @@ -33,9 +33,10 @@ import { dateToDatabaseTimestamp } from "~/utils/dates"; import invariant from "~/utils/invariant"; import { type SendouRouteHandle, + errorToastIfFalsy, parseFormData, parseRequestPayload, - validate, + unauthorizedIfFalsy, } from "~/utils/remix.server"; import { artPage, @@ -68,7 +69,7 @@ export const meta: MetaFunction = () => { export const action: ActionFunction = async ({ request }) => { const user = await requireUser(request); - validate(user.isArtist, "Lacking artist role", 403); + errorToastIfFalsy(user.isArtist, "Lacking artist role"); const searchParams = new URL(request.url).searchParams; const artIdRaw = searchParams.get(NEW_ART_EXISTING_SEARCH_PARAM_KEY); @@ -78,10 +79,9 @@ export const action: ActionFunction = async ({ request }) => { const artId = Number(artIdRaw); const existingArt = findArtById(artId); - validate( + errorToastIfFalsy( existingArt?.authorId === user.id, - "Insufficient permissions", - 401, + "Art author is someone else", ); const data = await parseRequestPayload({ @@ -158,7 +158,7 @@ export const action: ActionFunction = async ({ request }) => { export const loader = async ({ request }: LoaderFunctionArgs) => { const user = await requireUser(request); - validate(user.isArtist, "Lacking artist role", 403); + unauthorizedIfFalsy(user.isArtist); const artIdRaw = new URL(request.url).searchParams.get( NEW_ART_EXISTING_SEARCH_PARAM_KEY, diff --git a/app/features/auth/core/routes.server.ts b/app/features/auth/core/routes.server.ts index ef24abc54..91303ac5d 100644 --- a/app/features/auth/core/routes.server.ts +++ b/app/features/auth/core/routes.server.ts @@ -5,7 +5,7 @@ import { z } from "zod"; import * as UserRepository from "~/features/user-page/UserRepository.server"; import { canAccessLohiEndpoint, canPerformAdminActions } from "~/permissions"; import { logger } from "~/utils/logger"; -import { parseSearchParams, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseSearchParams } from "~/utils/remix.server"; import { ADMIN_PAGE, authErrorUrl } from "~/utils/urls"; import { createLogInLink } from "../queries/createLogInLink.server"; import { deleteLogInLinkByCode } from "../queries/deleteLogInLinkByCode.server"; @@ -61,7 +61,7 @@ export const logOutAction: ActionFunction = async ({ request }) => { }; export const logInAction: ActionFunction = async ({ request }) => { - validate( + errorToastIfFalsy( process.env.LOGIN_DISABLED !== "true", "Login is temporarily disabled", ); diff --git a/app/features/badges/routes/badges.$id.edit.tsx b/app/features/badges/routes/badges.$id.edit.tsx index 75ff71041..8b8796170 100644 --- a/app/features/badges/routes/badges.$id.edit.tsx +++ b/app/features/badges/routes/badges.$id.edit.tsx @@ -15,9 +15,9 @@ import { notify } from "~/features/notifications/core/notify.server"; import { canEditBadgeManagers, canEditBadgeOwners } from "~/permissions"; import { atOrError, diff } from "~/utils/arrays"; import { + errorToastIfFalsy, notFoundIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { badgePage } from "~/utils/urls"; @@ -38,7 +38,10 @@ export const action: ActionFunction = async ({ request, params }) => { switch (data._action) { case "MANAGERS": { - validate(canEditBadgeManagers(user)); + errorToastIfFalsy( + canEditBadgeManagers(user), + "No permissions to edit managers", + ); const oldManagers = await BadgeRepository.findManagersByBadgeId(badgeId); @@ -65,11 +68,12 @@ export const action: ActionFunction = async ({ request, params }) => { break; } case "OWNERS": { - validate( + errorToastIfFalsy( canEditBadgeOwners({ user, managers: await BadgeRepository.findManagersByBadgeId(badgeId), }), + "No permissions to edit owners", ); const oldOwners = await BadgeRepository.findOwnersByBadgeId(badgeId); diff --git a/app/features/calendar/actions/calendar.new.server.ts b/app/features/calendar/actions/calendar.new.server.ts index bb7a68a40..355f51c39 100644 --- a/app/features/calendar/actions/calendar.new.server.ts +++ b/app/features/calendar/actions/calendar.new.server.ts @@ -21,9 +21,9 @@ import { } from "~/utils/dates"; import { badRequestIfFalsy, + errorToastIfFalsy, parseFormData, uploadImageIfSubmitted, - validate, } from "~/utils/remix.server"; import { calendarEventPage } from "~/utils/urls"; import { @@ -58,7 +58,7 @@ export const action: ActionFunction = async ({ request }) => { parseAsync: true, }); - validate(canAddNewEvent(user), "Not authorized", 401); + errorToastIfFalsy(canAddNewEvent(user), "Not authorized"); const startTimes = data.date.map((date) => dateToDatabaseTimestamp(date)); const commonArgs = { @@ -109,7 +109,7 @@ export const action: ActionFunction = async ({ request }) => { ) : undefined, }; - validate( + errorToastIfFalsy( !commonArgs.toToolsEnabled || commonArgs.bracketProgression, "Bracket progression must be set for tournaments", ); @@ -129,15 +129,17 @@ export const action: ActionFunction = async ({ request }) => { tournamentId: eventToEdit.tournamentId, user, }); - validate(!tournament.hasStarted, "Tournament has already started", 400); + errorToastIfFalsy( + !tournament.hasStarted, + "Tournament has already started", + ); - validate(tournament.isAdmin(user), "Not authorized", 401); + errorToastIfFalsy(tournament.isAdmin(user), "Not authorized"); } else { // editing regular calendar event - validate( + errorToastIfFalsy( canEditCalendarEvent({ user, event: eventToEdit }), "Not authorized", - 401, ); } diff --git a/app/features/calendar/loaders/calendar.new.server.ts b/app/features/calendar/loaders/calendar.new.server.ts index 7f755241b..86b3c823f 100644 --- a/app/features/calendar/loaders/calendar.new.server.ts +++ b/app/features/calendar/loaders/calendar.new.server.ts @@ -6,7 +6,7 @@ import * as CalendarRepository from "~/features/calendar/CalendarRepository.serv import { tournamentData } from "~/features/tournament-bracket/core/Tournament.server"; import * as TournamentOrganizationRepository from "~/features/tournament-organization/TournamentOrganizationRepository.server"; import { canEditCalendarEvent } from "~/permissions"; -import { validate } from "~/utils/remix.server"; +import { unauthorizedIfFalsy } from "~/utils/remix.server"; import { tournamentBracketsPage } from "~/utils/urls"; import { canAddNewEvent } from "../calendar-utils"; @@ -14,7 +14,7 @@ export const loader = async ({ request }: LoaderFunctionArgs) => { const user = await requireUser(request); const url = new URL(request.url); - validate(canAddNewEvent(user), "Not authorized", 401); + unauthorizedIfFalsy(canAddNewEvent(user)); const eventWithTournament = async (key: string) => { const eventId = Number(url.searchParams.get(key)); diff --git a/app/features/calendar/routes/calendar.$id.report-winners.tsx b/app/features/calendar/routes/calendar.$id.report-winners.tsx index 6f6cff3c5..fbf72ce9f 100644 --- a/app/features/calendar/routes/calendar.$id.report-winners.tsx +++ b/app/features/calendar/routes/calendar.$id.report-winners.tsx @@ -21,9 +21,10 @@ import * as CalendarRepository from "~/features/calendar/CalendarRepository.serv import { canReportCalendarEventWinners } from "~/permissions"; import { type SendouRouteHandle, + errorToastIfFalsy, notFoundIfFalsy, safeParseRequestFormData, - validate, + unauthorizedIfFalsy, } from "~/utils/remix.server"; import type { Unpacked } from "~/utils/types"; import { calendarEventPage } from "~/utils/urls"; @@ -111,14 +112,13 @@ export const action: ActionFunction = async ({ request, params }) => { const event = notFoundIfFalsy( await CalendarRepository.findById({ id: parsedParams.id }), ); - validate( + errorToastIfFalsy( canReportCalendarEventWinners({ user, event, startTimes: event.startTimes, }), "Unauthorized", - 401, ); await CalendarRepository.upsertReportedScores({ @@ -148,7 +148,7 @@ export const loader = async ({ request, params }: LoaderFunctionArgs) => { await CalendarRepository.findById({ id: parsedParams.id }), ); - validate( + unauthorizedIfFalsy( canReportCalendarEventWinners({ user, event, diff --git a/app/features/calendar/routes/calendar.$id.tsx b/app/features/calendar/routes/calendar.$id.tsx index 74f5314ca..da54d9a75 100644 --- a/app/features/calendar/routes/calendar.$id.tsx +++ b/app/features/calendar/routes/calendar.$id.tsx @@ -38,8 +38,8 @@ import { import { databaseTimestampToDate } from "~/utils/dates"; import { type SendouRouteHandle, + errorToastIfFalsy, notFoundIfFalsy, - validate, } from "~/utils/remix.server"; import { CALENDAR_PAGE, @@ -69,17 +69,18 @@ export const action: ActionFunction = async ({ params, request }) => { ); if (event.tournamentId) { - validate( + errorToastIfFalsy( tournamentManagerData(event.tournamentId).stage.length === 0, "Tournament has already started", ); } else { - validate( + errorToastIfFalsy( canDeleteCalendarEvent({ user, event, startTime: databaseTimestampToDate(event.startTimes[0]), }), + "Cannot delete event", ); } diff --git a/app/features/img-upload/actions/upload.server.ts b/app/features/img-upload/actions/upload.server.ts index d32bd4da6..a754fa14d 100644 --- a/app/features/img-upload/actions/upload.server.ts +++ b/app/features/img-upload/actions/upload.server.ts @@ -15,9 +15,9 @@ import { dateToDatabaseTimestamp } from "~/utils/dates"; import invariant from "~/utils/invariant"; import { badRequestIfFalsy, + errorToastIfFalsy, parseSearchParams, unauthorizedIfFalsy, - validate, } from "~/utils/remix.server"; import { teamPage, tournamentOrganizationPage } from "~/utils/urls"; import { addNewImage } from "../queries/addNewImage"; @@ -30,7 +30,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { const user = await requireUser(request); const validatedType = requestToImgType(request); - validate(validatedType, "Invalid image type"); + errorToastIfFalsy(validatedType, "Invalid image type"); const team = validatedType === "team-pfp" || validatedType === "team-banner" @@ -41,8 +41,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { ? await validatedOrg({ user, request }) : undefined; - // TODO: graceful error handling when uploading many images - validate( + errorToastIfFalsy( countUnvalidatedImg(user.id) < MAX_UNVALIDATED_IMG_COUNT, "Too many unvalidated images", ); @@ -97,8 +96,8 @@ async function validatedTeam({ }); const team = await TeamRepository.findByCustomUrl(teamCustomUrl); - validate(team, "Team not found"); - validate( + errorToastIfFalsy(team, "Team not found"); + errorToastIfFalsy( isTeamManager({ team, user }), "You must be the team manager to upload images", ); diff --git a/app/features/img-upload/routes/upload.admin.tsx b/app/features/img-upload/routes/upload.admin.tsx index a2b64f45f..3093b1ab4 100644 --- a/app/features/img-upload/routes/upload.admin.tsx +++ b/app/features/img-upload/routes/upload.admin.tsx @@ -7,9 +7,9 @@ import { clearTournamentDataCache } from "~/features/tournament-bracket/core/Tou import { isMod } from "~/permissions"; import { badRequestIfFalsy, + errorToastIfFalsy, notFoundIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { userSubmittedImage } from "~/utils/urls"; import * as ImageRepository from "../ImageRepository.server"; @@ -25,7 +25,7 @@ export const action: ActionFunction = async ({ request }) => { request, }); - validate(isMod(user), "Only admins can validate images"); + errorToastIfFalsy(isMod(user), "Only admins can validate images"); const image = badRequestIfFalsy(await ImageRepository.findById(data.imageId)); diff --git a/app/features/lfg/actions/lfg.new.server.ts b/app/features/lfg/actions/lfg.new.server.ts index ec1af1026..c31b36666 100644 --- a/app/features/lfg/actions/lfg.new.server.ts +++ b/app/features/lfg/actions/lfg.new.server.ts @@ -3,7 +3,7 @@ import { redirect } from "@remix-run/node"; import { z } from "zod"; import { requireUser } from "~/features/auth/core/user.server"; import * as UserRepository from "~/features/user-page/UserRepository.server"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { LFG_PAGE } from "~/utils/urls"; import { falsyToNull, id } from "~/utils/zod"; import * as LFGRepository from "../LFGRepository.server"; @@ -22,7 +22,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { const shouldIncludeTeam = TEAM_POST_TYPES.includes(data.type); - validate( + errorToastIfFalsy( !shouldIncludeTeam || team, "Team needs to be set for this type of post", ); @@ -74,6 +74,9 @@ const validateCanUpdatePost = async ({ }) => { const posts = await LFGRepository.posts(user); const post = posts.find((post) => post.id === postId); - validate(post, "Post to update not found"); - validate(post.author.id === user.id, "You can only update your own posts"); + errorToastIfFalsy(post, "Post to update not found"); + errorToastIfFalsy( + post.author.id === user.id, + "You can only update your own posts", + ); }; diff --git a/app/features/lfg/actions/lfg.server.ts b/app/features/lfg/actions/lfg.server.ts index 43e20a3da..5fd28abd2 100644 --- a/app/features/lfg/actions/lfg.server.ts +++ b/app/features/lfg/actions/lfg.server.ts @@ -2,7 +2,7 @@ import type { ActionFunctionArgs } from "@remix-run/node"; import { z } from "zod"; import { requireUser } from "~/features/auth/core/user.server"; import { isAdmin } from "~/permissions"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { _action, id } from "~/utils/zod"; import * as LFGRepository from "../LFGRepository.server"; @@ -15,8 +15,11 @@ export const action = async ({ request }: ActionFunctionArgs) => { const posts = await LFGRepository.posts(user); const post = posts.find((post) => post.id === data.id); - validate(post, "Post not found"); - validate(isAdmin(user) || post.author.id === user.id, "Not your own post"); + errorToastIfFalsy(post, "Post not found"); + errorToastIfFalsy( + isAdmin(user) || post.author.id === user.id, + "Not your own post", + ); switch (data._action) { case "DELETE_POST": { diff --git a/app/features/plus-suggestions/routes/plus.suggestions.comment.$tier.$userId.tsx b/app/features/plus-suggestions/routes/plus.suggestions.comment.$tier.$userId.tsx index ff9660be9..78773d730 100644 --- a/app/features/plus-suggestions/routes/plus.suggestions.comment.$tier.$userId.tsx +++ b/app/features/plus-suggestions/routes/plus.suggestions.comment.$tier.$userId.tsx @@ -20,8 +20,8 @@ import { import { atOrError } from "~/utils/arrays"; import { badRequestIfFalsy, + errorToastIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { plusSuggestionPage } from "~/utils/urls"; import { actualNumber, trimmedString } from "~/utils/zod"; @@ -57,14 +57,14 @@ export const action: ActionFunction = async ({ request }) => { const suggestions = await PlusSuggestionRepository.findAllByMonth(votingMonthYear); - validate(suggestions); - validate( + errorToastIfFalsy( canAddCommentToSuggestionBE({ suggestions, user, suggested: { id: data.suggestedId }, targetPlusTier: data.tier, }), + "No permissions to add this comment", ); await PlusSuggestionRepository.create({ diff --git a/app/features/plus-suggestions/routes/plus.suggestions.new.tsx b/app/features/plus-suggestions/routes/plus.suggestions.new.tsx index 6ed49220c..f933b70e3 100644 --- a/app/features/plus-suggestions/routes/plus.suggestions.new.tsx +++ b/app/features/plus-suggestions/routes/plus.suggestions.new.tsx @@ -33,8 +33,8 @@ import { import { atOrError } from "~/utils/arrays"; import { badRequestIfFalsy, + errorToastIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { plusSuggestionPage } from "~/utils/urls"; import { actualNumber, trimmedString } from "~/utils/zod"; @@ -73,14 +73,14 @@ export const action: ActionFunction = async ({ request }) => { const suggestions = await PlusSuggestionRepository.findAllByMonth(votingMonthYear); - validate(suggestions); - validate( + errorToastIfFalsy( canSuggestNewUserBE({ user, suggested, targetPlusTier: data.tier, suggestions, }), + "No permissions to make this suggestion", ); await PlusSuggestionRepository.create({ diff --git a/app/features/plus-suggestions/routes/plus.suggestions.tsx b/app/features/plus-suggestions/routes/plus.suggestions.tsx index 0ce2d3ccc..b63cb5c8c 100644 --- a/app/features/plus-suggestions/routes/plus.suggestions.tsx +++ b/app/features/plus-suggestions/routes/plus.suggestions.tsx @@ -35,8 +35,8 @@ import invariant from "~/utils/invariant"; import { metaTags } from "~/utils/remix"; import { badRequestIfFalsy, + errorToastIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { userPage } from "~/utils/urls"; @@ -96,14 +96,14 @@ export const action: ActionFunction = async ({ request }) => { ); invariant(subSuggestion); - validate(suggestionToDelete); - validate( + errorToastIfFalsy( canDeleteComment({ user, author: subSuggestion.author, suggestionId: data.suggestionId, suggestions, }), + "No permissions to delete this comment", ); const suggestionHasComments = suggestionToDelete.suggestions.length > 1; diff --git a/app/features/sendouq/routes/q.looking.tsx b/app/features/sendouq/routes/q.looking.tsx index 9b76092b8..20f8af61d 100644 --- a/app/features/sendouq/routes/q.looking.tsx +++ b/app/features/sendouq/routes/q.looking.tsx @@ -31,8 +31,8 @@ import invariant from "~/utils/invariant"; import { metaTags } from "~/utils/remix"; import { type SendouRouteHandle, + errorToastIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { errorIsSqliteForeignKeyConstraintFailure } from "~/utils/sql"; import { assertUnreachable } from "~/utils/types"; @@ -117,7 +117,7 @@ export const action: ActionFunction = async ({ request }) => { // this throws because there should normally be no way user loses ownership by the action of some other user const validateIsGroupOwner = () => - validate(currentGroup.role === "OWNER", "Not owner"); + errorToastIfFalsy(currentGroup.role === "OWNER", "Not owner"); const isGroupManager = () => currentGroup.role === "MANAGER" || currentGroup.role === "OWNER"; @@ -268,17 +268,20 @@ export const action: ActionFunction = async ({ request }) => { ); if (!theirGroup) return null; - validate( + errorToastIfFalsy( ourGroup.members.length === FULL_GROUP_SIZE, - "'ourGroup' is not full", + "Our group is not full", ); - validate( + errorToastIfFalsy( theirGroup.members.length === FULL_GROUP_SIZE, - "'theirGroup' is not full", + "Their group is not full", ); - validate(!groupHasMatch(ourGroup.id), "Our group already has a match"); - validate( + errorToastIfFalsy( + !groupHasMatch(ourGroup.id), + "Our group already has a match", + ); + errorToastIfFalsy( !groupHasMatch(theirGroup.id), "Their group already has a match", ); @@ -364,7 +367,10 @@ export const action: ActionFunction = async ({ request }) => { break; } case "LEAVE_GROUP": { - validate(!currentGroup.matchId, "Can't leave group while in a match"); + errorToastIfFalsy( + !currentGroup.matchId, + "Can't leave group while in a match", + ); let newOwnerId: number | null = null; if (currentGroup.role === "OWNER") { newOwnerId = groupSuccessorOwner(currentGroup.id); @@ -390,7 +396,7 @@ export const action: ActionFunction = async ({ request }) => { } case "KICK_FROM_GROUP": { validateIsGroupOwner(); - validate(data.userId !== user.id, "Can't kick yourself"); + errorToastIfFalsy(data.userId !== user.id, "Can't kick yourself"); leaveGroup({ groupId: currentGroup.id, diff --git a/app/features/sendouq/routes/q.match.$id.tsx b/app/features/sendouq/routes/q.match.$id.tsx index ffdfeb514..b6cf7be07 100644 --- a/app/features/sendouq/routes/q.match.$id.tsx +++ b/app/features/sendouq/routes/q.match.$id.tsx @@ -63,10 +63,10 @@ import { logger } from "~/utils/logger"; import { safeNumberParse } from "~/utils/number"; import type { SendouRouteHandle } from "~/utils/remix.server"; import { + errorToastIfFalsy, notFoundIfFalsy, parseParams, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { inGameNameWithoutDiscriminator } from "~/utils/strings"; import type { Unpacked } from "~/utils/types"; @@ -177,7 +177,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => { return null; } - validate( + errorToastIfFalsy( !data.adminReport || isMod(user), "Only mods can report scores as admin", ); @@ -339,18 +339,18 @@ export const action = async ({ request, params }: ActionFunctionArgs) => { } case "LOOK_AGAIN": { const season = currentSeason(new Date()); - validate(season, "Season is not active"); + errorToastIfFalsy(season, "Season is not active"); const previousGroup = await QMatchRepository.findGroupById({ groupId: data.previousGroupId, }); - validate(previousGroup, "Previous group not found"); + errorToastIfFalsy(previousGroup, "Previous group not found"); for (const member of previousGroup.members) { const currentGroup = findCurrentGroupByUserId(member.id); - validate(!currentGroup, "Member is already in a group"); + errorToastIfFalsy(!currentGroup, "Member is already in a group"); if (member.id === user.id) { - validate( + errorToastIfFalsy( member.role === "OWNER", "You are not the owner of the group", ); @@ -366,7 +366,7 @@ export const action = async ({ request, params }: ActionFunctionArgs) => { } case "REPORT_WEAPONS": { const match = notFoundIfFalsy(findMatchById(matchId)); - validate(match.reportedAt, "Match has not been reported yet"); + errorToastIfFalsy(match.reportedAt, "Match has not been reported yet"); const oldReportedWeapons = reportedWeaponsByMatchId(matchId) ?? []; diff --git a/app/features/sendouq/routes/q.preparing.tsx b/app/features/sendouq/routes/q.preparing.tsx index 25f6e4f83..3a6df47f4 100644 --- a/app/features/sendouq/routes/q.preparing.tsx +++ b/app/features/sendouq/routes/q.preparing.tsx @@ -17,7 +17,7 @@ import { useAutoRefresh } from "~/hooks/useAutoRefresh"; import invariant from "~/utils/invariant"; import { metaTags } from "~/utils/remix"; import type { SendouRouteHandle } from "~/utils/remix.server"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { SENDOUQ_LOOKING_PAGE, @@ -65,14 +65,14 @@ export const action = async ({ request }: ActionFunctionArgs) => { }); const currentGroup = findCurrentGroupByUserId(user.id); - validate(currentGroup, "No group found"); + errorToastIfFalsy(currentGroup, "No group found"); if (!hasGroupManagerPerms(currentGroup.role)) { return null; } const season = currentSeason(new Date()); - validate(season, "Season is not active"); + errorToastIfFalsy(season, "Season is not active"); switch (data._action) { case "JOIN_QUEUE": { @@ -91,7 +91,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { return { error: "taken" } as const; } - validate( + errorToastIfFalsy( (await QRepository.usersThatTrusted(user.id)).trusters.some( (trusterUser) => trusterUser.id === data.id, ), @@ -102,7 +102,7 @@ export const action = async ({ request }: ActionFunctionArgs) => { groupId: currentGroup.id, }); invariant(ownGroupWithMembers, "No own group found"); - validate( + errorToastIfFalsy( ownGroupWithMembers.members.length < FULL_GROUP_SIZE, "Group is full", ); diff --git a/app/features/sendouq/routes/q.tsx b/app/features/sendouq/routes/q.tsx index 0abf46545..58d16402f 100644 --- a/app/features/sendouq/routes/q.tsx +++ b/app/features/sendouq/routes/q.tsx @@ -35,8 +35,8 @@ import { joinListToNaturalString } from "~/utils/arrays"; import invariant from "~/utils/invariant"; import { type SendouRouteHandle, + errorToastIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { @@ -89,12 +89,12 @@ export const meta: MetaFunction = (args) => { const validateCanJoinQ = async (user: { id: number; discordId: string }) => { const friendCode = await UserRepository.currentFriendCodeByUserId(user.id); - validate(friendCode, "No friend code"); + errorToastIfFalsy(friendCode, "No friend code"); const canJoinQueue = userCanJoinQueueAt(user, friendCode) === "NOW"; - validate(currentSeason(new Date()), "Season is not active"); - validate(!findCurrentGroupByUserId(user.id), "Already in a group"); - validate(canJoinQueue, "Can't join queue right now"); + errorToastIfFalsy(currentSeason(new Date()), "Season is not active"); + errorToastIfFalsy(!findCurrentGroupByUserId(user.id), "Already in a group"); + errorToastIfFalsy(canJoinQueue, "Can't join queue right now"); }; export const action: ActionFunction = async ({ request }) => { @@ -127,8 +127,14 @@ export const action: ActionFunction = async ({ request }) => { const groupInvitedTo = code && user ? findGroupByInviteCode(code) : undefined; - validate(groupInvitedTo, "Invite code doesn't match any active team"); - validate(groupInvitedTo.members.length < FULL_GROUP_SIZE, "Team is full"); + errorToastIfFalsy( + groupInvitedTo, + "Invite code doesn't match any active team", + ); + errorToastIfFalsy( + groupInvitedTo.members.length < FULL_GROUP_SIZE, + "Team is full", + ); sql.transaction(() => { addMember({ @@ -156,7 +162,7 @@ export const action: ActionFunction = async ({ request }) => { ); } case "ADD_FRIEND_CODE": { - validate( + errorToastIfFalsy( !(await UserRepository.currentFriendCodeByUserId(user.id)), "Friend code already set", ); diff --git a/app/features/team/actions/t.$customUrl.edit.server.test.ts b/app/features/team/actions/t.$customUrl.edit.server.test.ts index a330cfb19..fbaca1ffe 100644 --- a/app/features/team/actions/t.$customUrl.edit.server.test.ts +++ b/app/features/team/actions/t.$customUrl.edit.server.test.ts @@ -1,5 +1,10 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { dbInsertUsers, dbReset, wrappedAction } from "~/utils/Test"; +import { + assertResponseErrored, + dbInsertUsers, + dbReset, + wrappedAction, +} from "~/utils/Test"; import { action as teamIndexPageAction } from "../actions/t.server"; import type { editTeamSchema } from "../team-schemas.server"; import type { createTeamSchema } from "../team-schemas.server"; @@ -42,30 +47,30 @@ describe("team page editing", () => { }); it("prevents adding custom css var of unknown property", async () => { - await expect( - editTeamProfileAction( - { - css: JSON.stringify({ - "backdrop-filter": "#fff", - }), - ...DEFAULT_FIELDS, - }, - { user: "regular", params: { customUrl: "team-1" } }, - ), - ).rejects.toThrow("status code: 400"); + const response = await editTeamProfileAction( + { + css: JSON.stringify({ + "backdrop-filter": "#fff", + }), + ...DEFAULT_FIELDS, + }, + { user: "regular", params: { customUrl: "team-1" } }, + ); + + assertResponseErrored(response); }); it("prevents adding custom css var of unknown value", async () => { - await expect( - editTeamProfileAction( - { - css: JSON.stringify({ - bg: "url(https://sendou.ink/u?q=1&_data=features%2Fuser-search%2Froutes%2Fu)", - }), - ...DEFAULT_FIELDS, - }, - { user: "regular", params: { customUrl: "team-1" } }, - ), - ).rejects.toThrow("status code: 400"); + const response = await editTeamProfileAction( + { + css: JSON.stringify({ + bg: "url(https://sendou.ink/u?q=1&_data=features%2Fuser-search%2Froutes%2Fu)", + }), + ...DEFAULT_FIELDS, + }, + { user: "regular", params: { customUrl: "team-1" } }, + ); + + assertResponseErrored(response); }); }); diff --git a/app/features/team/actions/t.$customUrl.edit.server.ts b/app/features/team/actions/t.$customUrl.edit.server.ts index 08ab099db..fb9d79b3e 100644 --- a/app/features/team/actions/t.$customUrl.edit.server.ts +++ b/app/features/team/actions/t.$customUrl.edit.server.ts @@ -3,9 +3,9 @@ import { redirect } from "@remix-run/node"; import { requireUserId } from "~/features/auth/core/user.server"; import { isAdmin } from "~/permissions"; import { + errorToastIfFalsy, notFoundIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { TEAM_SEARCH_PAGE, mySlugify, teamPage } from "~/utils/urls"; @@ -19,7 +19,7 @@ export const action: ActionFunction = async ({ request, params }) => { const team = notFoundIfFalsy(await TeamRepository.findByCustomUrl(customUrl)); - validate( + errorToastIfFalsy( isTeamManager({ team, user }) || isAdmin(user), "You are not a team manager", ); @@ -31,7 +31,10 @@ export const action: ActionFunction = async ({ request, params }) => { switch (data._action) { case "DELETE": { - validate(isTeamOwner({ team, user }), "You are not the team owner"); + errorToastIfFalsy( + isTeamOwner({ team, user }), + "You are not the team owner", + ); await TeamRepository.del(team.id); @@ -41,7 +44,7 @@ export const action: ActionFunction = async ({ request, params }) => { const newCustomUrl = mySlugify(data.name); const existingTeam = await TeamRepository.findByCustomUrl(newCustomUrl); - validate( + errorToastIfFalsy( newCustomUrl.length > 0, "Team name can't be only special characters", ); diff --git a/app/features/team/actions/t.$customUrl.join.server.ts b/app/features/team/actions/t.$customUrl.join.server.ts index fd7d6b316..1fd4abaf7 100644 --- a/app/features/team/actions/t.$customUrl.join.server.ts +++ b/app/features/team/actions/t.$customUrl.join.server.ts @@ -1,6 +1,6 @@ import { type ActionFunction, redirect } from "@remix-run/node"; import { requireUser } from "~/features/auth/core/user.server"; -import { notFoundIfFalsy, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, notFoundIfFalsy } from "~/utils/remix.server"; import { teamPage } from "~/utils/urls"; import * as TeamRepository from "../TeamRepository.server"; import { validateInviteCode } from "../loaders/t.$customUrl.join.server"; @@ -20,7 +20,7 @@ export const action: ActionFunction = async ({ request, params }) => { const inviteCode = new URL(request.url).searchParams.get("code") ?? ""; const realInviteCode = team.inviteCode!; - validate( + errorToastIfFalsy( validateInviteCode({ inviteCode, realInviteCode, diff --git a/app/features/team/actions/t.$customUrl.roster.server.ts b/app/features/team/actions/t.$customUrl.roster.server.ts index f331b1830..8beb039a9 100644 --- a/app/features/team/actions/t.$customUrl.roster.server.ts +++ b/app/features/team/actions/t.$customUrl.roster.server.ts @@ -2,9 +2,9 @@ import type { ActionFunction } from "@remix-run/node"; import { requireUserId } from "~/features/auth/core/user.server"; import { isAdmin } from "~/permissions"; import { + errorToastIfFalsy, notFoundIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import * as TeamMemberRepository from "../TeamMemberRepository.server"; @@ -17,7 +17,7 @@ export const action: ActionFunction = async ({ request, params }) => { const { customUrl } = teamParamsSchema.parse(params); const team = notFoundIfFalsy(await TeamRepository.findByCustomUrl(customUrl)); - validate( + errorToastIfFalsy( isTeamManager({ team, user }) || isAdmin(user), "Only team manager or owner can manage roster", ); @@ -31,9 +31,9 @@ export const action: ActionFunction = async ({ request, params }) => { case "DELETE_MEMBER": { const member = team.members.find((m) => m.id === data.userId); - validate(member, "Member not found"); - validate(member.id !== user.id, "Can't delete yourself"); - validate(!member.isOwner, "Can't delete owner"); + errorToastIfFalsy(member, "Member not found"); + errorToastIfFalsy(member.id !== user.id, "Can't delete yourself"); + errorToastIfFalsy(!member.isOwner, "Can't delete owner"); await TeamRepository.handleMemberLeaving({ teamId: team.id, @@ -58,8 +58,11 @@ export const action: ActionFunction = async ({ request, params }) => { } case "REMOVE_MANAGER": { const member = team.members.find((m) => m.id === data.userId); - validate(member, "Member not found"); - validate(member.id !== user.id, "Can't remove yourself as manager"); + errorToastIfFalsy(member, "Member not found"); + errorToastIfFalsy( + member.id !== user.id, + "Can't remove yourself as manager", + ); await TeamMemberRepository.update( { teamId: team.id, userId: data.userId }, diff --git a/app/features/team/actions/t.$customUrl.server.ts b/app/features/team/actions/t.$customUrl.server.ts index ac35e00ea..e5b29d177 100644 --- a/app/features/team/actions/t.$customUrl.server.ts +++ b/app/features/team/actions/t.$customUrl.server.ts @@ -1,9 +1,9 @@ import type { ActionFunction } from "@remix-run/node"; import { requireUserId } from "~/features/auth/core/user.server"; import { + errorToastIfFalsy, notFoundIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import * as TeamRepository from "../TeamRepository.server"; @@ -25,7 +25,7 @@ export const action: ActionFunction = async ({ request, params }) => { switch (data._action) { case "LEAVE_TEAM": { - validate( + errorToastIfFalsy( isTeamMember({ user, team }), "You are not a member of this team", ); @@ -33,7 +33,7 @@ export const action: ActionFunction = async ({ request, params }) => { const newOwner = isTeamOwner({ user, team }) ? resolveNewOwner(team.members) : null; - validate( + errorToastIfFalsy( !isTeamOwner({ user, team }) || newOwner, "You can't leave the team if you are the owner and there is no other member to become the owner", ); diff --git a/app/features/team/actions/t.server.test.ts b/app/features/team/actions/t.server.test.ts index 65a25aee5..0207d1813 100644 --- a/app/features/team/actions/t.server.test.ts +++ b/app/features/team/actions/t.server.test.ts @@ -1,5 +1,10 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { dbInsertUsers, dbReset, wrappedAction } from "~/utils/Test"; +import { + assertResponseErrored, + dbInsertUsers, + dbReset, + wrappedAction, +} from "~/utils/Test"; import { action as teamIndexPageAction } from "../actions/t.server"; import type { createTeamSchema } from "../team-schemas.server"; @@ -23,8 +28,8 @@ describe("team creation", () => { }); it("prevents creating a team whose name is only special characters", async () => { - await expect(action({ name: "𝓢𝓲𝓵" }, { user: "regular" })).rejects.toThrow( - "status code: 400", - ); + const response = await action({ name: "𝓢𝓲𝓵" }, { user: "regular" }); + + assertResponseErrored(response); }); }); diff --git a/app/features/team/actions/t.server.ts b/app/features/team/actions/t.server.ts index 073155190..b34492d08 100644 --- a/app/features/team/actions/t.server.ts +++ b/app/features/team/actions/t.server.ts @@ -1,7 +1,7 @@ import type { ActionFunction } from "@remix-run/node"; import { redirect } from "@remix-run/node"; import { requireUser } from "~/features/auth/core/user.server"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { mySlugify, teamPage } from "~/utils/urls"; import { isAtLeastFiveDollarTierPatreon } from "~/utils/users"; import * as TeamRepository from "../TeamRepository.server"; @@ -17,22 +17,25 @@ export const action: ActionFunction = async ({ request }) => { const teams = await TeamRepository.findAllUndisbanded(); - const teamMemberOfCount = teams.filter((team) => + const currentTeamCount = teams.filter((team) => team.members.some((m) => m.id === user.id), ).length; - const maxMemberCount = isAtLeastFiveDollarTierPatreon(user) + const maxTeamCount = isAtLeastFiveDollarTierPatreon(user) ? TEAM.MAX_TEAM_COUNT_PATRON : TEAM.MAX_TEAM_COUNT_NON_PATRON; - validate( - teamMemberOfCount < maxMemberCount, + errorToastIfFalsy( + currentTeamCount < maxTeamCount, "Already in max amount of teams", ); // two teams can't have same customUrl const customUrl = mySlugify(data.name); - validate(customUrl.length > 0, "Team name can't be only special characters"); + errorToastIfFalsy( + customUrl.length > 0, + "Team name can't be only special characters", + ); if (teams.some((team) => team.customUrl === customUrl)) { return { @@ -44,7 +47,7 @@ export const action: ActionFunction = async ({ request }) => { ownerUserId: user.id, name: data.name, customUrl, - isMainTeam: teamMemberOfCount === 0, + isMainTeam: currentTeamCount === 0, }); throw redirect(teamPage(customUrl)); diff --git a/app/features/team/routes/t.$customUrl.edit.test.ts b/app/features/team/routes/t.$customUrl.edit.test.ts index 8c2bdc31a..585ed7f78 100644 --- a/app/features/team/routes/t.$customUrl.edit.test.ts +++ b/app/features/team/routes/t.$customUrl.edit.test.ts @@ -1,5 +1,10 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; -import { dbInsertUsers, dbReset, wrappedAction } from "~/utils/Test"; +import { + assertResponseErrored, + dbInsertUsers, + dbReset, + wrappedAction, +} from "~/utils/Test"; import { action as teamIndexPageAction } from "../actions/t.server"; import { action as _editTeamAction } from "../routes/t.$customUrl.edit"; import type { createTeamSchema, editTeamSchema } from "../team-schemas.server"; @@ -43,15 +48,15 @@ describe("team creation", () => { it("prevents editing team name to only special characters", async () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); - await expect( - editTeamAction( - { - _action: "EDIT", - name: "𝓢𝓲𝓵", - ...DEFAULT_FIELDS, - }, - { user: "regular", params: { customUrl: "team-1" } }, - ), - ).rejects.toThrow("status code: 400"); + const response = await editTeamAction( + { + _action: "EDIT", + name: "𝓢𝓲𝓵", + ...DEFAULT_FIELDS, + }, + { user: "regular", params: { customUrl: "team-1" } }, + ); + + assertResponseErrored(response); }); }); diff --git a/app/features/team/routes/t.$customUrl.test.ts b/app/features/team/routes/t.$customUrl.test.ts index 624187615..02af1649a 100644 --- a/app/features/team/routes/t.$customUrl.test.ts +++ b/app/features/team/routes/t.$customUrl.test.ts @@ -3,6 +3,7 @@ import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { REGULAR_USER_TEST_ID } from "~/db/seed/constants"; import { db } from "~/db/sql"; import { + assertResponseErrored, dbInsertUsers, dbReset, wrappedAction, @@ -159,9 +160,12 @@ describe("Secondary teams", () => { await createTeamAction({ name: "Team 1" }, { user: "regular" }); await createTeamAction({ name: "Team 2" }, { user: "regular" }); - await expect( - createTeamAction({ name: "Team 3" }, { user: "regular" }), - ).rejects.toThrow("status code: 400"); + const response = await createTeamAction( + { name: "Team 3" }, + { user: "regular" }, + ); + + assertResponseErrored(response); }); const makeUserPatron = () => diff --git a/app/features/tournament-bracket/routes/to.$id.brackets.tsx b/app/features/tournament-bracket/routes/to.$id.brackets.tsx index 737553e36..f20887b97 100644 --- a/app/features/tournament-bracket/routes/to.$id.brackets.tsx +++ b/app/features/tournament-bracket/routes/to.$id.brackets.tsx @@ -40,7 +40,7 @@ import { useSearchParamState } from "~/hooks/useSearchParamState"; import { useVisibilityChange } from "~/hooks/useVisibilityChange"; import invariant from "~/utils/invariant"; import { logger } from "~/utils/logger"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { SENDOU_INK_BASE_URL, @@ -87,7 +87,7 @@ export const action: ActionFunction = async ({ params, request }) => { switch (data._action) { case "START_BRACKET": { - validate(tournament.isOrganizer(user)); + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); const bracket = tournament.bracketByIdx(data.bracketIdx); invariant(bracket, "Bracket not found"); @@ -95,12 +95,15 @@ export const action: ActionFunction = async ({ params, request }) => { const seeding = bracket.seeding; invariant(seeding, "Seeding not found"); - validate(bracket.canBeStarted, "Bracket is not ready to be started"); + errorToastIfFalsy( + bracket.canBeStarted, + "Bracket is not ready to be started", + ); const groupCount = new Set(bracket.data.round.map((r) => r.group_id)) .size; - validate( + errorToastIfFalsy( bracket.type === "round_robin" || bracket.type === "swiss" ? bracket.data.round.length / groupCount === data.maps.length : bracket.data.round.length === data.maps.length, @@ -176,16 +179,16 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "PREPARE_MAPS": { - validate(tournament.isOrganizer(user)); + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); const bracket = tournament.bracketByIdx(data.bracketIdx); invariant(bracket, "Bracket not found"); - validate( + errorToastIfFalsy( !bracket.canBeStarted, "Bracket can already be started, preparing maps no longer possible", ); - validate( + errorToastIfFalsy( bracket.preview, "Bracket has started, preparing maps no longer possible", ); @@ -203,11 +206,14 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "ADVANCE_BRACKET": { - validate(tournament.isOrganizer(user)); + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); const bracket = tournament.bracketByIdx(data.bracketIdx); - validate(bracket, "Bracket not found"); - validate(bracket.type === "swiss", "Can't advance non-swiss bracket"); + errorToastIfFalsy(bracket, "Bracket not found"); + errorToastIfFalsy( + bracket.type === "swiss", + "Can't advance non-swiss bracket", + ); const matches = Swiss.generateMatchUps({ bracket, @@ -219,11 +225,14 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "UNADVANCE_BRACKET": { - validate(tournament.isOrganizer(user)); + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); const bracket = tournament.bracketByIdx(data.bracketIdx); - validate(bracket, "Bracket not found"); - validate(bracket.type === "swiss", "Can't unadvance non-swiss bracket"); + errorToastIfFalsy(bracket, "Bracket not found"); + errorToastIfFalsy( + bracket.type === "swiss", + "Can't unadvance non-swiss bracket", + ); validateNoFollowUpBrackets(tournament); await TournamentRepository.deleteSwissMatches({ @@ -234,7 +243,10 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "FINALIZE_TOURNAMENT": { - validate(tournament.canFinalize(user), "Can't finalize tournament"); + errorToastIfFalsy( + tournament.canFinalize(user), + "Can't finalize tournament", + ); const _finalStandings = tournament.standings; @@ -293,7 +305,10 @@ export const action: ActionFunction = async ({ params, request }) => { const ownTeam = tournament.ownedTeamByUser(user); invariant(ownTeam, "User doesn't have owned team"); - validate(bracket.canCheckIn(user)); + errorToastIfFalsy( + bracket.canCheckIn(user), + "Can't check in to this bracket right now", + ); await TournamentRepository.checkIn({ bracketIdx: data.bracketIdx, @@ -302,18 +317,18 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "OVERRIDE_BRACKET_PROGRESSION": { - validate(tournament.isOrganizer(user)); + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); const allDestinationBrackets = Progression.destinationsFromBracketIdx( data.sourceBracketIdx, tournament.ctx.settings.bracketProgression, ); - validate( + errorToastIfFalsy( data.destinationBracketIdx === -1 || allDestinationBrackets.includes(data.destinationBracketIdx), "Invalid destination bracket", ); - validate( + errorToastIfFalsy( allDestinationBrackets.every( (bracketIdx) => tournament.bracketByIdx(bracketIdx)!.preview, ), @@ -343,7 +358,7 @@ function validateNoFollowUpBrackets(tournament: Tournament) { b.sources?.some((source) => source.bracketIdx === 0), ); - validate( + errorToastIfFalsy( followUpBrackets.every((b) => b.preview), "Follow-up brackets are already started", ); diff --git a/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx b/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx index 6589726e7..bc595e539 100644 --- a/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx +++ b/app/features/tournament-bracket/routes/to.$id.matches.$mid.tsx @@ -21,10 +21,10 @@ import { canReportTournamentScore } from "~/permissions"; import invariant from "~/utils/invariant"; import { logger } from "~/utils/logger"; import { + errorToastIfFalsy, notFoundIfFalsy, parseParams, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { @@ -88,14 +88,13 @@ export const action: ActionFunction = async ({ params, request }) => { (p) => p.id === user?.id, ); - validate( + errorToastIfFalsy( canReportTournamentScore({ match, isMemberOfATeamInTheMatch, isOrganizer: tournament.isOrganizer(user), }), "Unauthorized", - 401, ); }; @@ -134,13 +133,16 @@ export const action: ActionFunction = async ({ params, request }) => { } validateCanReportScore(); - validate( + errorToastIfFalsy( match.opponentOne?.id === data.winnerTeamId || match.opponentTwo?.id === data.winnerTeamId, "Winner team id is invalid", ); - validate(match.opponentOne && match.opponentTwo, "Teams are missing"); - validate( + errorToastIfFalsy( + match.opponentOne && match.opponentTwo, + "Teams are missing", + ); + errorToastIfFalsy( !matchIsLocked({ matchId: match.id, tournament, scores }), "Match is locked", ); @@ -154,10 +156,10 @@ export const action: ActionFunction = async ({ params, request }) => { if (data.winnerTeamId === match.opponentOne?.id) return 0; if (data.winnerTeamId === match.opponentTwo?.id) return 1; - validate(false, "Winner team id is invalid"); + errorToastIfFalsy(false, "Winner team id is invalid"); }; - validate( + errorToastIfFalsy( !data.points || (scoreToIncrement() === 0 && data.points[0] > data.points[1]) || (scoreToIncrement() === 1 && data.points[1] > data.points[0]), @@ -183,10 +185,10 @@ export const action: ActionFunction = async ({ params, request }) => { tournament.minMembersPerTeam, ); - validate(teamOneRoster, "Team one has no active roster"); - validate(teamTwoRoster, "Team two has no active roster"); + errorToastIfFalsy(teamOneRoster, "Team one has no active roster"); + errorToastIfFalsy(teamTwoRoster, "Team two has no active roster"); - validate( + errorToastIfFalsy( new Set([...teamOneRoster, ...teamTwoRoster]).size === tournament.minMembersPerTeam * 2, "Duplicate user in rosters", @@ -239,20 +241,19 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "SET_ACTIVE_ROSTER": { - validate(!tournament.everyBracketOver, "Tournament is over"); - validate( + errorToastIfFalsy(!tournament.everyBracketOver, "Tournament is over"); + errorToastIfFalsy( tournament.isOrganizer(user) || tournament.teamMemberOfByUser(user)?.id === data.teamId, "Unauthorized", - 401, ); - validate( + errorToastIfFalsy( data.roster.length === tournament.minMembersPerTeam, "Invalid roster length", ); const team = tournament.teamById(data.teamId)!; - validate( + errorToastIfFalsy( data.roster.every((userId) => team.members.some((m) => m.userId === userId), ), @@ -339,14 +340,14 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "UPDATE_REPORTED_SCORE": { - validate(tournament.isOrganizer(user)); - validate(!tournament.ctx.isFinalized, "Tournament is finalized"); + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); + errorToastIfFalsy(!tournament.ctx.isFinalized, "Tournament is finalized"); const result = await TournamentMatchRepository.findResultById( data.resultId, ); - validate(result, "Result not found"); - validate( + errorToastIfFalsy(result, "Result not found"); + errorToastIfFalsy( data.rosters[0].length === tournament.minMembersPerTeam && data.rosters[1].length === tournament.minMembersPerTeam, "Invalid roster length", @@ -354,7 +355,7 @@ export const action: ActionFunction = async ({ params, request }) => { const hadPoints = typeof result.opponentOnePoints === "number"; const willHavePoints = typeof data.points?.[0] === "number"; - validate( + errorToastIfFalsy( (hadPoints && willHavePoints) || (!hadPoints && !willHavePoints), "Points mismatch", ); @@ -362,19 +363,19 @@ export const action: ActionFunction = async ({ params, request }) => { if (data.points) { if (data.points[0] !== result.opponentOnePoints) { // changing points at this point could retroactively change who advanced from the group - validate( + errorToastIfFalsy( tournament.matchCanBeReopened(match.id), "Bracket has progressed", ); } if (result.opponentOnePoints! > result.opponentTwoPoints!) { - validate( + errorToastIfFalsy( data.points[0] > data.points[1], "Winner must have more points than loser", ); } else { - validate( + errorToastIfFalsy( data.points[0] < data.points[1], "Winner must have more points than loser", ); @@ -434,15 +435,14 @@ export const action: ActionFunction = async ({ params, request }) => { teams: [match.opponentOne.id, match.opponentTwo.id], mapList, }); - validate(pickerTeamId, "Not time to pick/ban"); - validate( + errorToastIfFalsy(pickerTeamId, "Not time to pick/ban"); + errorToastIfFalsy( tournament.isOrganizer(user) || tournament.ownedTeamByUser(user)?.id === pickerTeamId, "Unauthorized", - 401, ); - validate( + errorToastIfFalsy( PickBan.isLegal({ results, map: data, @@ -482,8 +482,8 @@ export const action: ActionFunction = async ({ params, request }) => { invariant(typeof scoreTwo === "number", "Score two is missing"); invariant(scoreOne !== scoreTwo, "Scores are equal"); - validate(tournament.isOrganizer(user)); - validate( + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); + errorToastIfFalsy( tournament.matchCanBeReopened(match.id), "Match can't be reopened, bracket has progressed", ); @@ -527,7 +527,10 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "SET_AS_CASTED": { - validate(tournament.isOrganizerOrStreamer(user)); + errorToastIfFalsy( + tournament.isOrganizerOrStreamer(user), + "Not an organizer or streamer", + ); await TournamentRepository.setMatchAsCasted({ matchId: match.id, @@ -540,7 +543,10 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "LOCK": { - validate(tournament.isOrganizerOrStreamer(user)); + errorToastIfFalsy( + tournament.isOrganizerOrStreamer(user), + "Not an organizer or streamer", + ); // can't lock, let's update their view to reflect that if (match.opponentOne?.id && match.opponentTwo?.id) { @@ -557,7 +563,10 @@ export const action: ActionFunction = async ({ params, request }) => { break; } case "UNLOCK": { - validate(tournament.isOrganizerOrStreamer(user)); + errorToastIfFalsy( + tournament.isOrganizerOrStreamer(user), + "Not an organizer or streamer", + ); await TournamentRepository.unlockMatch({ matchId: match.id, diff --git a/app/features/tournament-subs/routes/to.$id.subs.new.tsx b/app/features/tournament-subs/routes/to.$id.subs.new.tsx index 57f605753..98b450509 100644 --- a/app/features/tournament-subs/routes/to.$id.subs.new.tsx +++ b/app/features/tournament-subs/routes/to.$id.subs.new.tsx @@ -24,8 +24,8 @@ import { import type { MainWeaponId } from "~/modules/in-game-lists"; import { type SendouRouteHandle, + errorToastIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { tournamentSubsPage } from "~/utils/urls"; import { findSubsByTournamentId } from "../queries/findSubsByTournamentId.server"; @@ -48,12 +48,12 @@ export const action: ActionFunction = async ({ params, request }) => { const tournamentId = tournamentIdFromParams(params); const tournament = await tournamentFromDB({ tournamentId, user }); - validate(!tournament.everyBracketOver, "Tournament is over"); - validate( + errorToastIfFalsy(!tournament.everyBracketOver, "Tournament is over"); + errorToastIfFalsy( tournament.canAddNewSubPost, "Registration is closed or subs feature disabled", ); - validate( + errorToastIfFalsy( !tournament.teamMemberOfByUser(user), "Can't register as a sub and be in a team at the same time", ); diff --git a/app/features/tournament-subs/routes/to.$id.subs.tsx b/app/features/tournament-subs/routes/to.$id.subs.tsx index 5225d8d5f..0ff038ce1 100644 --- a/app/features/tournament-subs/routes/to.$id.subs.tsx +++ b/app/features/tournament-subs/routes/to.$id.subs.tsx @@ -24,7 +24,7 @@ import { tournamentFromDB, } from "~/features/tournament-bracket/core/Tournament.server"; import { useTournament } from "~/features/tournament/routes/to.$id"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { tournamentRegisterPage, userPage } from "~/utils/urls"; import { deleteSub } from "../queries/deleteSub.server"; @@ -45,10 +45,9 @@ export const action: ActionFunction = async ({ request, params }) => { schema: deleteSubSchema, }); - validate( + errorToastIfFalsy( user.id === data.userId || tournament.isOrganizer(user), "You can only delete your own sub post", - 401, ); deleteSub({ diff --git a/app/features/tournament/actions/to.$id.admin.server.ts b/app/features/tournament/actions/to.$id.admin.server.ts index bbc9869e7..dd499d26c 100644 --- a/app/features/tournament/actions/to.$id.admin.server.ts +++ b/app/features/tournament/actions/to.$id.admin.server.ts @@ -14,8 +14,9 @@ import invariant from "~/utils/invariant"; import { logger } from "~/utils/logger"; import { badRequestIfFalsy, + errorToastIfFalsy, parseRequestPayload, - validate, + successToast, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { USER } from "../../../constants"; @@ -41,18 +42,19 @@ export const action: ActionFunction = async ({ request, params }) => { const tournament = await tournamentFromDB({ tournamentId, user }); const validateIsTournamentAdmin = () => - validate(tournament.isAdmin(user), "Unauthorized", 401); + errorToastIfFalsy(tournament.isAdmin(user), "Unauthorized"); const validateIsTournamentOrganizer = () => - validate(tournament.isOrganizer(user), "Unauthorized", 401); + errorToastIfFalsy(tournament.isOrganizer(user), "Unauthorized"); + let message: string; switch (data._action) { case "ADD_TEAM": { validateIsTournamentOrganizer(); - validate( + errorToastIfFalsy( tournament.ctx.teams.every((t) => t.name !== data.teamName), "Team name taken", ); - validate( + errorToastIfFalsy( !tournament.teamMemberOfByUser({ id: data.userId }), "User already on a team", ); @@ -78,16 +80,17 @@ export const action: ActionFunction = async ({ request, params }) => { userId: data.userId, }); + message = "Team added"; break; } case "CHANGE_TEAM_OWNER": { validateIsTournamentOrganizer(); const team = tournament.teamById(data.teamId); - validate(team, "Invalid team id"); + errorToastIfFalsy(team, "Invalid team id"); const oldCaptain = team.members.find((m) => m.isOwner); invariant(oldCaptain, "Team has no captain"); const newCaptain = team.members.find((m) => m.userId === data.memberId); - validate(newCaptain, "Invalid member id"); + errorToastIfFalsy(newCaptain, "Invalid member id"); changeTeamOwner({ newCaptainId: data.memberId, @@ -95,56 +98,61 @@ export const action: ActionFunction = async ({ request, params }) => { tournamentTeamId: data.teamId, }); + message = "Team owner changed"; break; } case "CHANGE_TEAM_NAME": { validateIsTournamentOrganizer(); const team = tournament.teamById(data.teamId); - validate(team, "Invalid team id"); + errorToastIfFalsy(team, "Invalid team id"); await TournamentRepository.updateTeamName({ tournamentTeamId: data.teamId, name: data.teamName, }); + + message = "Team name changed"; break; } case "CHECK_IN": { validateIsTournamentOrganizer(); const team = tournament.teamById(data.teamId); - validate(team, "Invalid team id"); - validate( + errorToastIfFalsy(team, "Invalid team id"); + errorToastIfFalsy( data.bracketIdx !== 0 || tournament.checkInConditionsFulfilledByTeamId(team.id), "Can't check-in", ); - validate( + errorToastIfFalsy( team.checkIns.length > 0 || data.bracketIdx === 0, "Can't check-in to follow up bracket if not checked in for the event itself", ); const bracket = tournament.bracketByIdx(data.bracketIdx); invariant(bracket, "Invalid bracket idx"); - validate(bracket.preview, "Bracket has been started"); + errorToastIfFalsy(bracket.preview, "Bracket has been started"); await TournamentRepository.checkIn({ tournamentTeamId: data.teamId, // no sources = regular check in bracketIdx: !bracket.sources ? null : data.bracketIdx, }); + + message = "Checked team in"; break; } case "CHECK_OUT": { validateIsTournamentOrganizer(); const team = tournament.teamById(data.teamId); - validate(team, "Invalid team id"); - validate( + errorToastIfFalsy(team, "Invalid team id"); + errorToastIfFalsy( data.bracketIdx !== 0 || !tournament.hasStarted, "Tournament has started", ); const bracket = tournament.bracketByIdx(data.bracketIdx); invariant(bracket, "Invalid bracket idx"); - validate(bracket.preview, "Bracket has been started"); + errorToastIfFalsy(bracket.preview, "Bracket has been started"); await TournamentRepository.checkOut({ tournamentTeamId: data.teamId, @@ -154,22 +162,24 @@ export const action: ActionFunction = async ({ request, params }) => { logger.info( `Checked out: tournament team id: ${data.teamId} - user id: ${user.id} - tournament id: ${tournamentId} - bracket idx: ${data.bracketIdx}`, ); + + message = "Checked team out"; break; } case "REMOVE_MEMBER": { validateIsTournamentOrganizer(); const team = tournament.teamById(data.teamId); - validate(team, "Invalid team id"); - validate( + errorToastIfFalsy(team, "Invalid team id"); + errorToastIfFalsy( team.checkIns.length === 0 || team.members.length > tournament.minMembersPerTeam, "Can't remove last member from checked in team", ); - validate( + errorToastIfFalsy( !team.members.find((m) => m.userId === data.memberId)?.isOwner, "Cannot remove team owner", ); - validate( + errorToastIfFalsy( !tournament.hasStarted || !tournament .participatedPlayersByTeamId(data.teamId) @@ -188,21 +198,22 @@ export const action: ActionFunction = async ({ request, params }) => { userId: data.memberId, }); + message = "Member removed"; break; } case "ADD_MEMBER": { validateIsTournamentOrganizer(); const team = tournament.teamById(data.teamId); - validate(team, "Invalid team id"); + errorToastIfFalsy(team, "Invalid team id"); const previousTeam = tournament.teamMemberOfByUser({ id: data.userId }); - validate( + errorToastIfFalsy( tournament.hasStarted || !previousTeam, "User is already in a team", ); - validate( + errorToastIfFalsy( !userIsBanned(data.userId), "User trying to be added currently has an active ban from sendou.ink", ); @@ -247,18 +258,20 @@ export const action: ActionFunction = async ({ request, params }) => { }, }); + message = "Member added"; break; } case "DELETE_TEAM": { validateIsTournamentOrganizer(); const team = tournament.teamById(data.teamId); - validate(team, "Invalid team id"); - validate(!tournament.hasStarted, "Tournament has started"); + errorToastIfFalsy(team, "Invalid team id"); + errorToastIfFalsy(!tournament.hasStarted, "Tournament has started"); deleteTeam(team.id); ShowcaseTournaments.clearParticipationInfoMap(); + message = "Team deleted from tournament"; break; } case "ADD_STAFF": { @@ -278,6 +291,7 @@ export const action: ActionFunction = async ({ request, params }) => { }); } + message = "Staff member added"; break; } case "REMOVE_STAFF": { @@ -294,6 +308,7 @@ export const action: ActionFunction = async ({ request, params }) => { userId: data.userId, }); + message = "Staff member removed"; break; } case "UPDATE_CAST_TWITCH_ACCOUNTS": { @@ -302,6 +317,8 @@ export const action: ActionFunction = async ({ request, params }) => { tournamentId: tournament.ctx.id, castTwitchAccounts: data.castTwitchAccounts, }); + + message = "Cast account updated"; break; } case "DROP_TEAM_OUT": { @@ -312,27 +329,31 @@ export const action: ActionFunction = async ({ request, params }) => { b.preview ? idx : [], ), }); + + message = "Team dropped out"; break; } case "UNDO_DROP_TEAM_OUT": { validateIsTournamentOrganizer(); await TournamentRepository.undoDropTeamOut(data.teamId); + + message = "Team drop out undone"; break; } case "RESET_BRACKET": { validateIsTournamentOrganizer(); - validate(!tournament.ctx.isFinalized, "Tournament is finalized"); + errorToastIfFalsy(!tournament.ctx.isFinalized, "Tournament is finalized"); const bracketToResetIdx = tournament.brackets.findIndex( (b) => b.id === data.stageId, ); const bracketToReset = tournament.brackets[bracketToResetIdx]; - validate(bracketToReset, "Invalid bracket id"); - validate(!bracketToReset.preview, "Bracket has not started"); + errorToastIfFalsy(bracketToReset, "Invalid bracket id"); + errorToastIfFalsy(!bracketToReset.preview, "Bracket has not started"); const inProgressBrackets = tournament.brackets.filter((b) => !b.preview); - validate( + errorToastIfFalsy( inProgressBrackets.every( (b) => !b.sources || @@ -343,6 +364,7 @@ export const action: ActionFunction = async ({ request, params }) => { await TournamentRepository.resetBracket(data.stageId); + message = "Bracket reset"; break; } case "UPDATE_IN_GAME_NAME": { @@ -357,6 +379,8 @@ export const action: ActionFunction = async ({ request, params }) => { inGameName: `${data.inGameNameText}#${data.inGameNameDiscriminator}`, tournamentTeamId: teamMemberOf.id, }); + + message = "Player in-game name updated"; break; } case "DELETE_LOGO": { @@ -364,13 +388,14 @@ export const action: ActionFunction = async ({ request, params }) => { await TournamentTeamRepository.deleteLogo(data.teamId); + message = "Logo deleted"; break; } case "UPDATE_TOURNAMENT_PROGRESSION": { validateIsTournamentOrganizer(); - validate(!tournament.ctx.isFinalized, "Tournament is finalized"); + errorToastIfFalsy(!tournament.ctx.isFinalized, "Tournament is finalized"); - validate( + errorToastIfFalsy( Progression.changedBracketProgression( tournament.ctx.settings.bracketProgression, data.bracketProgression, @@ -386,6 +411,7 @@ export const action: ActionFunction = async ({ request, params }) => { bracketProgression: data.bracketProgression, }); + message = "Tournament progression updated"; break; } default: { @@ -395,7 +421,7 @@ export const action: ActionFunction = async ({ request, params }) => { clearTournamentDataCache(tournamentId); - return null; + return successToast(message); }; export const adminActionSchema = z.union([ diff --git a/app/features/tournament/actions/to.$id.register.server.ts b/app/features/tournament/actions/to.$id.register.server.ts index bb922110e..c04c37476 100644 --- a/app/features/tournament/actions/to.$id.register.server.ts +++ b/app/features/tournament/actions/to.$id.register.server.ts @@ -13,10 +13,10 @@ import * as TournamentTeamRepository from "~/features/tournament/TournamentTeamR import * as UserRepository from "~/features/user-page/UserRepository.server"; import { logger } from "~/utils/logger"; import { + errorToastIfFalsy, notFoundIfFalsy, parseFormData, uploadImageIfSubmitted, - validate, } from "~/utils/remix.server"; import { booleanToInt } from "~/utils/sql"; import { assertUnreachable } from "~/utils/types"; @@ -50,7 +50,7 @@ export const action: ActionFunction = async ({ request, params }) => { const tournament = await tournamentFromDB({ tournamentId, user }); const event = notFoundIfFalsy(findByIdentifier(tournamentId)); - validate( + errorToastIfFalsy( !tournament.hasStarted, "Tournament has started, cannot make edits to registration", ); @@ -60,7 +60,7 @@ export const action: ActionFunction = async ({ request, params }) => { switch (data._action) { case "UPSERT_TEAM": { - validate( + errorToastIfFalsy( !data.teamId || (await TeamRepository.findAllMemberOfByUserId(user.id)).some( (team) => team.id === data.teamId, @@ -68,7 +68,7 @@ export const action: ActionFunction = async ({ request, params }) => { "Team id does not match any of the teams you are in", ); - validate( + errorToastIfFalsy( !tournament.ctx.teams.some( (team) => team.name === data.teamName && team.id !== data.teamId, ), @@ -76,7 +76,7 @@ export const action: ActionFunction = async ({ request, params }) => { ); if (ownTeam) { - validate( + errorToastIfFalsy( tournament.registrationOpen || data.teamName === ownTeam.name, "Can't change team name after registration has closed", ); @@ -93,16 +93,19 @@ export const action: ActionFunction = async ({ request, params }) => { }, }); } else { - validate(!tournament.isInvitational, "Event is invite only"); - validate( + errorToastIfFalsy(!tournament.isInvitational, "Event is invite only"); + errorToastIfFalsy( (await UserRepository.findLeanById(user.id))?.friendCode, "No friend code", ); - validate( + errorToastIfFalsy( !tournament.teamMemberOfByUser(user), "You are already in a team that you aren't captain of", ); - validate(tournament.registrationOpen, "Registration is closed"); + errorToastIfFalsy( + tournament.registrationOpen, + "Registration is closed", + ); await TournamentTeamRepository.create({ ownerInGameName: await inGameNameIfNeeded({ @@ -129,9 +132,12 @@ export const action: ActionFunction = async ({ request, params }) => { break; } case "DELETE_TEAM_MEMBER": { - validate(ownTeam); - validate(ownTeam.members.some((member) => member.userId === data.userId)); - validate(data.userId !== user.id); + errorToastIfFalsy(ownTeam, "You are not registered to this tournament"); + errorToastIfFalsy( + ownTeam.members.some((member) => member.userId === data.userId), + "User is not in your team", + ); + errorToastIfFalsy(data.userId !== user.id, "Can't kick yourself"); const detailedOwnTeam = findOwnTournamentTeam({ tournamentId, @@ -139,10 +145,11 @@ export const action: ActionFunction = async ({ request, params }) => { }); // making sure they aren't unfilling one checking in condition i.e. having full roster // and then having members kicked without it affecting the checking in status - validate( + errorToastIfFalsy( detailedOwnTeam && (!detailedOwnTeam.checkedInAt || ownTeam.members.length > tournament.minMembersPerTeam), + "Can't kick a member after checking in", ); deleteTeamMember({ tournamentTeamId: ownTeam.id, userId: data.userId }); @@ -155,11 +162,11 @@ export const action: ActionFunction = async ({ request, params }) => { break; } case "LEAVE_TEAM": { - validate(!ownTeam, "Can't leave a team as the owner"); + errorToastIfFalsy(!ownTeam, "Can't leave a team as the owner"); const teamMemberOf = tournament.teamMemberOfByUser(user); - validate(teamMemberOf, "You are not in a team"); - validate( + errorToastIfFalsy(teamMemberOf, "You are not in a team"); + errorToastIfFalsy( teamMemberOf.checkIns.length === 0, "You cannot leave after checking in", ); @@ -179,13 +186,14 @@ export const action: ActionFunction = async ({ request, params }) => { } case "UPDATE_MAP_POOL": { const mapPool = new MapPool(data.mapPool); - validate(ownTeam); - validate( + errorToastIfFalsy(ownTeam, "You are not registered to this tournament"); + errorToastIfFalsy( validateCounterPickMapPool( mapPool, isOneModeTournamentOf(event), tournament.ctx.tieBreakerMapPool, ) === "VALID", + "Invalid map pool", ); upsertCounterpickMaps({ @@ -200,14 +208,17 @@ export const action: ActionFunction = async ({ request, params }) => { ); const teamMemberOf = tournament.teamMemberOfByUser(user); - validate(teamMemberOf, "You are not in a team"); - validate( + errorToastIfFalsy(teamMemberOf, "You are not in a team"); + errorToastIfFalsy( teamMemberOf.checkIns.length === 0, "You have already checked in", ); - validate(tournament.regularCheckInIsOpen, "Check in is not open"); - validate( + errorToastIfFalsy( + tournament.regularCheckInIsOpen, + "Check in is not open", + ); + errorToastIfFalsy( tournament.checkInConditionsFulfilledByTeamId(teamMemberOf.id), "Check in conditions not fulfilled", ); @@ -219,24 +230,24 @@ export const action: ActionFunction = async ({ request, params }) => { break; } case "ADD_PLAYER": { - validate( + errorToastIfFalsy( tournament.ctx.teams.every((team) => team.members.every((member) => member.userId !== data.userId), ), "User is already in a team", ); - validate(ownTeam); - validate( + errorToastIfFalsy(ownTeam, "You are not registered to this tournament"); + errorToastIfFalsy( (await QRepository.usersThatTrusted(user.id)).trusters.some( (trusterPlayer) => trusterPlayer.id === data.userId, ), "No trust given from this user", ); - validate( + errorToastIfFalsy( (await UserRepository.findLeanById(user.id))?.friendCode, "No friend code", ); - validate(tournament.registrationOpen, "Registration is closed"); + errorToastIfFalsy(tournament.registrationOpen, "Registration is closed"); joinTeam({ userId: data.userId, @@ -276,9 +287,12 @@ export const action: ActionFunction = async ({ request, params }) => { break; } case "UNREGISTER": { - validate(ownTeam, "You are not registered to this tournament"); - validate(!ownTeamCheckedIn, "You cannot unregister after checking in"); - validate( + errorToastIfFalsy(ownTeam, "You are not registered to this tournament"); + errorToastIfFalsy( + !ownTeamCheckedIn, + "You cannot unregister after checking in", + ); + errorToastIfFalsy( !tournament.isLeagueSignup || tournament.registrationOpen, "Unregistering from leagues is not possible after registration has closed", ); @@ -290,7 +304,7 @@ export const action: ActionFunction = async ({ request, params }) => { break; } case "DELETE_LOGO": { - validate(ownTeam, "You are not registered to this tournament"); + errorToastIfFalsy(ownTeam, "You are not registered to this tournament"); await TournamentTeamRepository.deleteLogo(ownTeam.id); diff --git a/app/features/tournament/routes/to.$id.join.tsx b/app/features/tournament/routes/to.$id.join.tsx index 35edc1c7b..9dff32ed3 100644 --- a/app/features/tournament/routes/to.$id.join.tsx +++ b/app/features/tournament/routes/to.$id.join.tsx @@ -18,9 +18,9 @@ import { import * as UserRepository from "~/features/user-page/UserRepository.server"; import invariant from "~/utils/invariant"; import { + errorToastIfFalsy, notFoundIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { tournamentPage, userEditProfilePage } from "~/utils/urls"; @@ -52,16 +52,16 @@ export const action: ActionFunction = async ({ request, params }) => { ); if (tournament.hasStarted) { - validate( + errorToastIfFalsy( !previousTeam || previousTeam.checkIns.length === 0, "Can't leave checked in team mid tournament", ); - validate(tournament.autonomousSubs, "Subs are not allowed"); + errorToastIfFalsy(tournament.autonomousSubs, "Subs are not allowed"); } else { - validate(tournament.registrationOpen, "Registration is closed"); + errorToastIfFalsy(tournament.registrationOpen, "Registration is closed"); } - validate(teamToJoin, "Not team of this tournament"); - validate( + errorToastIfFalsy(teamToJoin, "Not team of this tournament"); + errorToastIfFalsy( validateCanJoin({ inviteCode, teamToJoin, @@ -70,7 +70,7 @@ export const action: ActionFunction = async ({ request, params }) => { }) === "VALID", "Cannot join this team or invite code is invalid", ); - validate( + errorToastIfFalsy( (await UserRepository.findLeanById(user.id))?.friendCode, "No friend code", ); diff --git a/app/features/tournament/routes/to.$id.seeds.tsx b/app/features/tournament/routes/to.$id.seeds.tsx index aebb86d79..38e086aa0 100644 --- a/app/features/tournament/routes/to.$id.seeds.tsx +++ b/app/features/tournament/routes/to.$id.seeds.tsx @@ -34,7 +34,7 @@ import { } from "~/features/tournament-bracket/core/Tournament.server"; import { useTimeoutState } from "~/hooks/useTimeoutState"; import invariant from "~/utils/invariant"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { tournamentBracketsPage, userResultsPage } from "~/utils/urls"; import { Avatar } from "../../../components/Avatar"; import { InfoPopover } from "../../../components/InfoPopover"; @@ -54,8 +54,8 @@ export const action: ActionFunction = async ({ request, params }) => { const tournamentId = tournamentIdFromParams(params); const tournament = await tournamentFromDB({ tournamentId, user }); - validate(tournament.isOrganizer(user)); - validate(!tournament.hasStarted, "Tournament has started"); + errorToastIfFalsy(tournament.isOrganizer(user), "Not an organizer"); + errorToastIfFalsy(!tournament.hasStarted, "Tournament has started"); switch (data._action) { case "UPDATE_SEEDS": { @@ -68,7 +68,7 @@ export const action: ActionFunction = async ({ request, params }) => { (bracket, bracketIdx) => (!bracket.sources ? [bracketIdx] : []), ); - validate( + errorToastIfFalsy( data.startingBrackets.every((t) => validBracketIdxs.includes(t.startingBracketIdx), ), diff --git a/app/features/tournament/tournament-utils.server.ts b/app/features/tournament/tournament-utils.server.ts index 53f08b118..26b4b86b5 100644 --- a/app/features/tournament/tournament-utils.server.ts +++ b/app/features/tournament/tournament-utils.server.ts @@ -1,5 +1,5 @@ import * as UserRepository from "~/features/user-page/UserRepository.server"; -import { validate } from "~/utils/remix.server"; +import { errorToastIfFalsy } from "~/utils/remix.server"; import type { Tournament } from "../tournament-bracket/core/Tournament"; export const inGameNameIfNeeded = async ({ @@ -13,7 +13,7 @@ export const inGameNameIfNeeded = async ({ const inGameName = await UserRepository.inGameNameByUserId(userId); - validate(inGameName, "No in-game name"); + errorToastIfFalsy(inGameName, "No in-game name"); return inGameName; }; diff --git a/app/features/user-page/actions/u.$identifier.builds.new.server.ts b/app/features/user-page/actions/u.$identifier.builds.new.server.ts index 75a2878ae..2a34358a1 100644 --- a/app/features/user-page/actions/u.$identifier.builds.new.server.ts +++ b/app/features/user-page/actions/u.$identifier.builds.new.server.ts @@ -18,7 +18,7 @@ import type { import { removeDuplicates } from "~/utils/arrays"; import { unJsonify } from "~/utils/kysely.server"; import { logger } from "~/utils/logger"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import type { Nullish } from "~/utils/types"; import { userBuildsPage } from "~/utils/urls"; import { @@ -54,9 +54,10 @@ export const action: ActionFunction = async ({ request }) => { if (usersBuilds.length >= BUILD.MAX_COUNT) { throw new Response("Max amount of builds reached", { status: 400 }); } - validate( + errorToastIfFalsy( !data.buildToEditId || usersBuilds.some((build) => build.id === data.buildToEditId), + "Build to edit not found", ); const someGearIsMissing = diff --git a/app/features/user-page/actions/u.$identifier.builds.server.ts b/app/features/user-page/actions/u.$identifier.builds.server.ts index 1e0c990f9..fcf598c94 100644 --- a/app/features/user-page/actions/u.$identifier.builds.server.ts +++ b/app/features/user-page/actions/u.$identifier.builds.server.ts @@ -6,7 +6,7 @@ import * as BuildRepository from "~/features/builds/BuildRepository.server"; import { refreshBuildsCacheByWeaponSplIds } from "~/features/builds/core/cached-builds.server"; import * as UserRepository from "~/features/user-page/UserRepository.server"; import { logger } from "~/utils/logger"; -import { parseRequestPayload, validate } from "~/utils/remix.server"; +import { errorToastIfFalsy, parseRequestPayload } from "~/utils/remix.server"; import { assertUnreachable } from "~/utils/types"; import { userBuildsPage } from "~/utils/urls"; import { @@ -37,7 +37,7 @@ export const action: ActionFunction = async ({ request }) => { (build) => build.id === data.buildToDeleteId, ); - validate(buildToDelete); + errorToastIfFalsy(buildToDelete, "Build to delete not found"); await BuildRepository.deleteById(data.buildToDeleteId); diff --git a/app/features/user-page/routes/u.$identifier.art.tsx b/app/features/user-page/routes/u.$identifier.art.tsx index 7c520c180..8c273f8db 100644 --- a/app/features/user-page/routes/u.$identifier.art.tsx +++ b/app/features/user-page/routes/u.$identifier.art.tsx @@ -15,9 +15,9 @@ import { useSearchParamState } from "~/hooks/useSearchParamState"; import invariant from "~/utils/invariant"; import { type SendouRouteHandle, + errorToastIfFalsy, notFoundIfFalsy, parseRequestPayload, - validate, } from "~/utils/remix.server"; import { userParamsSchema } from "../user-page-schemas.server"; import type { UserPageLoaderData } from "./u.$identifier"; @@ -37,7 +37,10 @@ export const action: ActionFunction = async ({ request }) => { // but the idea is that storage is cheap anyway and if needed later // then we can have a routine that checks all the images still current and nukes the rest const artToDelete = findArtById(data.id); - validate(artToDelete?.authorId === user.id, "Insufficient permissions", 401); + errorToastIfFalsy( + artToDelete?.authorId === user.id, + "Insufficient permissions", + ); deleteArt(data.id); diff --git a/app/root.tsx b/app/root.tsx index 917df15a6..8dbe63b3f 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -13,8 +13,10 @@ import { type ShouldRevalidateFunction, useLoaderData, useMatches, + useNavigate, useNavigation, useRevalidator, + useSearchParams, } from "@remix-run/react"; import generalI18next from "i18next"; import NProgress from "nprogress"; @@ -25,6 +27,7 @@ import { useTranslation } from "react-i18next"; import { useChangeLanguage } from "remix-i18next/react"; import type { SendouRouteHandle } from "~/utils/remix.server"; import { Catcher } from "./components/Catcher"; +import { SendouToastRegion, toastQueue } from "./components/elements/Toast"; import { Layout } from "./components/layout"; import { Ramp } from "./components/ramp/Ramp"; import { CUSTOMIZED_CSS_VARS_NAME } from "./constants"; @@ -142,6 +145,7 @@ function Document({ useChangeLanguage(locale); usePreloadTranslation(); useLoadingIndicator(); + useTriggerToasts(); const customizedCSSVars = useCustomizedCSSVars(); return ( @@ -170,19 +174,55 @@ function Document({ {process.env.NODE_ENV === "development" && } + {children} - + { + return location.pathname; + }} + /> ); } +function useTriggerToasts() { + const [searchParams] = useSearchParams(); + const navigate = useNavigate(); + + const error = searchParams.get("__error"); + const success = searchParams.get("__success"); + + React.useEffect(() => { + if (!error && !success) return; + + if (error) { + toastQueue.add({ + message: error, + variant: "error", + }); + } else if (success) { + toastQueue.add( + { + message: success, + variant: "success", + }, + { + timeout: 5000, + }, + ); + } + + navigate({ search: "" }, { replace: true }); + }, [error, success, navigate]); +} + function useLoadingIndicator() { const transition = useNavigation(); diff --git a/app/utils/Test.ts b/app/utils/Test.ts index 59b12b090..58ffda831 100644 --- a/app/utils/Test.ts +++ b/app/utils/Test.ts @@ -1,5 +1,6 @@ import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node"; import type { Params } from "@remix-run/react"; +import { expect } from "vitest"; import type { z } from "zod"; import { ADMIN_ID } from "~/constants"; import { REGULAR_USER_TEST_ID } from "~/db/seed/constants"; @@ -87,6 +88,13 @@ export function wrappedLoader({ }; } +/** + * Asserts that the given response errored out (with a toast message, via `validate(cond)` call) + */ +export function assertResponseErrored(response: Response) { + expect(response.headers.get("Location")).toContain("?__error="); +} + async function authHeader(user?: "admin" | "regular"): Promise { if (!user) return []; diff --git a/app/utils/remix.server.ts b/app/utils/remix.server.ts index 71d6f238c..4b5d2335e 100644 --- a/app/utils/remix.server.ts +++ b/app/utils/remix.server.ts @@ -1,4 +1,4 @@ -import { json } from "@remix-run/node"; +import { json, redirect } from "@remix-run/node"; import { unstable_composeUploadHandlers as composeUploadHandlers, unstable_createMemoryUploadHandler as createMemoryUploadHandler, @@ -7,10 +7,11 @@ import { import type { Params, UIMatch } from "@remix-run/react"; import type { Namespace, TFunction } from "i18next"; import { nanoid } from "nanoid"; -import { z } from "zod"; +import type { z } from "zod"; import type { navItems } from "~/components/layout/nav-items"; import { s3UploadHandler } from "~/features/img-upload"; import invariant from "./invariant"; +import { logger } from "./logger"; export function notFoundIfFalsy(value: T | null | undefined): T { if (!value) throw new Response(null, { status: 404 }); @@ -52,12 +53,9 @@ export function parseSearchParams({ try { return schema.parse(searchParams); } catch (e) { - if (e instanceof z.ZodError) { - console.error(e); - throw new Response(JSON.stringify(e), { status: 400 }); - } + logger.error("Error parsing search params", e); - throw e; + throw errorToast("Validation failed"); } } @@ -93,16 +91,13 @@ export async function parseRequestPayload({ return parsed; } catch (e) { - if (e instanceof z.ZodError) { - console.error(e); - throw new Response(JSON.stringify(e), { status: 400 }); - } + logger.error("Error parsing request payload", e); - throw e; + throw errorToast("Validation failed"); } } -/** Parse formData with the given schema. Throws HTTP 400 response if fails. */ +/** Parse formData with the given schema. Throws a request to show an error toast if it fails. */ export async function parseFormData({ formData, schema, @@ -120,12 +115,9 @@ export async function parseFormData({ return parsed; } catch (e) { - if (e instanceof z.ZodError) { - console.error(e); - throw new Response(JSON.stringify(e), { status: 400 }); - } + logger.error("Error parsing form data", e); - throw e; + throw errorToast("Validation failed"); } } @@ -189,20 +181,24 @@ function formDataToObject(formData: FormData) { return result; } -/** Asserts condition is truthy. Throws a new `Response` with given status code if falsy. */ -export function validate( +// TODO: investigate better solution to toasts when middlewares land (current one has a problem of clearing search params) + +export function errorToast(message: string) { + return redirect(`?__error=${message}`); +} + +/** Asserts condition is truthy. Throws a redirect triggering an error toast with given message otherwise. */ +export function errorToastIfFalsy( condition: any, - message?: string, - status = 400, + message: string, ): asserts condition { if (condition) return; - throw new Response( - message ? JSON.stringify({ validationError: message }) : undefined, - { - status, - }, - ); + throw errorToast(message); +} + +export function successToast(message: string) { + return redirect(`?__success=${message}`); } export type ActionError = { field: string; msg: string; isError: true }; diff --git a/locales/en/common.json b/locales/en/common.json index 006b3269a..80395446d 100644 --- a/locales/en/common.json +++ b/locales/en/common.json @@ -75,6 +75,10 @@ "auth.errors.discordPermissions": "For your sendou.ink profile, the site needs access to your Discord profile's name, avatar and social connections.", "auth.errors.unknown": "Unknown error, try again a bit later. Verify also that your Discord account has a verified email. For help please reach out to us via the #helpdesk channel on our Discord:", + "toasts.error": "Error", + "toasts.success": "Success", + "toasts.info": "Info", + "footer.github.subtitle": "Source code", "footer.discord.subtitle": "Help & feedback", "footer.patreon.subtitle": "Support", diff --git a/package-lock.json b/package-lock.json index 8201cc184..43534d5a4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,7 +48,7 @@ "openskill": "^4.1.0", "p-limit": "^6.2.0", "react": "^18.3.1", - "react-aria-components": "^1.6.0", + "react-aria-components": "^1.7.0", "react-charts": "^3.0.0-beta.57", "react-dom": "^18.3.1", "react-error-boundary": "^5.0.0", @@ -3293,23 +3293,24 @@ "license": "MIT" }, "node_modules/@react-aria/autocomplete": { - "version": "3.0.0-alpha.37", - "resolved": "https://registry.npmjs.org/@react-aria/autocomplete/-/autocomplete-3.0.0-alpha.37.tgz", - "integrity": "sha512-a7awFG3hshJ/kX7Qti/cJAKOG0XU5F/XW6fQffKGfEge7PmiWIvaLTrT5her79/v8v/bRBykIkpEgDCFE7WGzg==", + "version": "3.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@react-aria/autocomplete/-/autocomplete-3.0.0-beta.0.tgz", + "integrity": "sha512-8uqLicU2QlAtXspqIPbG2H2dqndFOnEwOf1bfmqI+9EjIBjQTQKbd4YBle++ZdhSTLKTOK6DM3ZkzfsoNk5DsQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/combobox": "^3.11.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/listbox": "^3.14.0", - "@react-aria/searchfield": "^3.8.0", - "@react-aria/textfield": "^3.16.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/autocomplete": "3.0.0-alpha.0", - "@react-stately/combobox": "^3.10.2", - "@react-types/autocomplete": "3.0.0-alpha.28", - "@react-types/button": "^3.10.2", - "@react-types/shared": "^3.27.0", + "@react-aria/combobox": "^3.12.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/listbox": "^3.14.1", + "@react-aria/searchfield": "^3.8.1", + "@react-aria/textfield": "^3.17.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/autocomplete": "3.0.0-beta.0", + "@react-stately/combobox": "^3.10.3", + "@react-types/autocomplete": "3.0.0-alpha.29", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3318,16 +3319,16 @@ } }, "node_modules/@react-aria/breadcrumbs": { - "version": "3.5.20", - "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.20.tgz", - "integrity": "sha512-xqVSSDPpQuUFpJyIXMQv8L7zumk5CeGX7qTzo4XRvqm5T9qnNAX4XpYEMdktnLrQRY/OemCBScbx7SEwr0B3Kg==", + "version": "3.5.21", + "resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.21.tgz", + "integrity": "sha512-Sg9nQIcKqHInXqTPml4uuf/2goEi9emPa9z/IGk6nw4kkZJuQYiqYvd5nCpcSqDfB2cWiJ5QZ50JIsKuTdBQpw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", - "@react-aria/link": "^3.7.8", - "@react-aria/utils": "^3.27.0", - "@react-types/breadcrumbs": "^3.7.10", - "@react-types/shared": "^3.27.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/link": "^3.7.9", + "@react-aria/utils": "^3.28.0", + "@react-types/breadcrumbs": "^3.7.11", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3336,18 +3337,17 @@ } }, "node_modules/@react-aria/button": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.11.1.tgz", - "integrity": "sha512-NSs2HxHSSPSuYy5bN+PMJzsCNDVsbm1fZ/nrWM2WWWHTBrx9OqyrEXZVV9ebzQCN9q0nzhwpf6D42zHIivWtJA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@react-aria/button/-/button-3.12.0.tgz", + "integrity": "sha512-obnK2vjQQdoOXMIPFy8PZSI8vET+LIeQeh3gjQfRcbtcVE6xT1drDARm6e36cunI2Up99e0yVBBWqqegNqKGQw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/interactions": "^3.23.0", - "@react-aria/toolbar": "3.0.0-beta.12", - "@react-aria/utils": "^3.27.0", - "@react-stately/toggle": "^3.8.1", - "@react-types/button": "^3.10.2", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.0", + "@react-aria/toolbar": "3.0.0-beta.13", + "@react-aria/utils": "^3.28.0", + "@react-stately/toggle": "^3.8.2", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3356,20 +3356,20 @@ } }, "node_modules/@react-aria/calendar": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.7.0.tgz", - "integrity": "sha512-9YUbgcox7cQgvZfQtL2BLLRsIuX4mJeclk9HkFoOsAu3RGO5HNsteah8FV54W8BMjm/bNRXIPUxtjTTP+1L6jg==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-aria/calendar/-/calendar-3.7.1.tgz", + "integrity": "sha512-0GN2MJNExA5rJbciVdEysmFfmcSEeGfIcFMid1xp82nhJTyWoSpdJG76Q/bLO8ADoBEhRPHsnItyVwKdHMSVsA==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/utils": "^3.27.0", - "@react-stately/calendar": "^3.7.0", - "@react-types/button": "^3.10.2", - "@react-types/calendar": "^3.6.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/calendar": "^3.7.1", + "@react-types/button": "^3.11.0", + "@react-types/calendar": "^3.6.1", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3378,21 +3378,21 @@ } }, "node_modules/@react-aria/checkbox": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.15.1.tgz", - "integrity": "sha512-ETgsMDZ0IZzRXy/OVlGkazm8T+PcMHoTvsxp0c+U82c8iqdITA+VJ615eBPOQh6OkkYIIn4cRn/e+69RmGzXng==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/@react-aria/checkbox/-/checkbox-3.15.2.tgz", + "integrity": "sha512-vJf91ToLN+BHfJUbulKBxN2POB7XzIb/3whF+fSk6wSld2vtFjQ80SQfz5HktYG/Af5VccxyCg70dp4moLvsTw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/form": "^3.0.12", - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/toggle": "^3.10.11", - "@react-aria/utils": "^3.27.0", - "@react-stately/checkbox": "^3.6.11", - "@react-stately/form": "^3.1.1", - "@react-stately/toggle": "^3.8.1", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-aria/form": "^3.0.13", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/toggle": "^3.11.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/checkbox": "^3.6.12", + "@react-stately/form": "^3.1.2", + "@react-stately/toggle": "^3.8.2", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3401,16 +3401,17 @@ } }, "node_modules/@react-aria/collections": { - "version": "3.0.0-alpha.7", - "resolved": "https://registry.npmjs.org/@react-aria/collections/-/collections-3.0.0-alpha.7.tgz", - "integrity": "sha512-JR2Ro33Chlf26NM12zJsK+MOs5/k+PQallT5+4YawndYmbxqlDLADcoFdcORJqh0pKf9OnluWtANobCkQGd0aQ==", + "version": "3.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@react-aria/collections/-/collections-3.0.0-beta.0.tgz", + "integrity": "sha512-2ra5nq44Dri8BhjhPEgA2f27WJVFCXnOqJhvRYGnLA/qmPnPprkzdAStug5+JXzogcvcZQ+Msk2nku4zprGQlw==", "license": "Apache-2.0", "dependencies": { + "@react-aria/interactions": "^3.24.0", "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", - "use-sync-external-store": "^1.2.0" + "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", @@ -3418,23 +3419,23 @@ } }, "node_modules/@react-aria/color": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@react-aria/color/-/color-3.0.3.tgz", - "integrity": "sha512-DDVma2107VHBfSuEnnmy+KJvXvxEXWSAooii2vlHHmQNb5x4rv4YTk+dP5GZl/7MgT8OgPTB9UHoC83bXFMDRA==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@react-aria/color/-/color-3.0.4.tgz", + "integrity": "sha512-enKb+TXAtqP0+UUIxX9Ss/5aLU2i6IF1pmTxsjIYT/RfM52eaP+o088KPDlmVFx3HYQxjK85XmAlBlSwm859Qg==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/numberfield": "^3.11.10", - "@react-aria/slider": "^3.7.15", - "@react-aria/spinbutton": "^3.6.11", - "@react-aria/textfield": "^3.16.0", - "@react-aria/utils": "^3.27.0", - "@react-aria/visually-hidden": "^3.8.19", - "@react-stately/color": "^3.8.2", - "@react-stately/form": "^3.1.1", - "@react-types/color": "^3.0.2", - "@react-types/shared": "^3.27.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/numberfield": "^3.11.11", + "@react-aria/slider": "^3.7.16", + "@react-aria/spinbutton": "^3.6.12", + "@react-aria/textfield": "^3.17.0", + "@react-aria/utils": "^3.28.0", + "@react-aria/visually-hidden": "^3.8.20", + "@react-stately/color": "^3.8.3", + "@react-stately/form": "^3.1.2", + "@react-types/color": "^3.0.3", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3443,25 +3444,26 @@ } }, "node_modules/@react-aria/combobox": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.11.1.tgz", - "integrity": "sha512-TTNbGhUuqxzPcJzd6hufOxuHzX0UARkw+0bl+TuCwNPQnqrcPf20EoOZvd3MHZwGq6GCP4QV+qo0uGx83RpUvA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@react-aria/combobox/-/combobox-3.12.0.tgz", + "integrity": "sha512-p4WBfmtigEL+MwAKa4wdTnLl4kTnGvek/WjhUDdSF2vcRJi7NmvN4HwzgE4L4TcGISfbOc+OUh6jGemu1uV4lA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", - "@react-aria/listbox": "^3.14.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/listbox": "^3.14.1", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/menu": "^3.17.0", - "@react-aria/overlays": "^3.25.0", - "@react-aria/selection": "^3.22.0", - "@react-aria/textfield": "^3.16.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/collections": "^3.12.1", - "@react-stately/combobox": "^3.10.2", - "@react-stately/form": "^3.1.1", - "@react-types/button": "^3.10.2", - "@react-types/combobox": "^3.13.2", - "@react-types/shared": "^3.27.0", + "@react-aria/menu": "^3.18.0", + "@react-aria/overlays": "^3.26.0", + "@react-aria/selection": "^3.23.0", + "@react-aria/textfield": "^3.17.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/combobox": "^3.10.3", + "@react-stately/form": "^3.1.2", + "@react-types/button": "^3.11.0", + "@react-types/combobox": "^3.13.3", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3470,28 +3472,28 @@ } }, "node_modules/@react-aria/datepicker": { - "version": "3.13.0", - "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.13.0.tgz", - "integrity": "sha512-TmJan65P3Vk7VDBNW5rH9Z25cAn0vk8TEtaP3boCs8wJFE+HbEuB8EqLxBFu47khtuKTEqDP3dTlUh2Vt/f7Xw==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@react-aria/datepicker/-/datepicker-3.14.0.tgz", + "integrity": "sha512-jRyymreuDy6/BbGrLHiaATGjZZhdnkEUujZuolU+8FXmCKkEQwxZKa9KfjK4UA3h2sytypK1vU7cQjQH4b36cA==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", "@internationalized/number": "^3.6.0", "@internationalized/string": "^3.2.5", - "@react-aria/focus": "^3.19.1", - "@react-aria/form": "^3.0.12", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/spinbutton": "^3.6.11", - "@react-aria/utils": "^3.27.0", - "@react-stately/datepicker": "^3.12.0", - "@react-stately/form": "^3.1.1", - "@react-types/button": "^3.10.2", - "@react-types/calendar": "^3.6.0", - "@react-types/datepicker": "^3.10.0", - "@react-types/dialog": "^3.5.15", - "@react-types/shared": "^3.27.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/form": "^3.0.13", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/spinbutton": "^3.6.12", + "@react-aria/utils": "^3.28.0", + "@react-stately/datepicker": "^3.13.0", + "@react-stately/form": "^3.1.2", + "@react-types/button": "^3.11.0", + "@react-types/calendar": "^3.6.1", + "@react-types/datepicker": "^3.11.0", + "@react-types/dialog": "^3.5.16", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3500,16 +3502,16 @@ } }, "node_modules/@react-aria/dialog": { - "version": "3.5.21", - "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.21.tgz", - "integrity": "sha512-tBsn9swBhcptJ9QIm0+ur0PVR799N6qmGguva3rUdd+gfitknFScyT08d7AoMr9AbXYdJ+2R9XNSZ3H3uIWQMw==", + "version": "3.5.22", + "resolved": "https://registry.npmjs.org/@react-aria/dialog/-/dialog-3.5.22.tgz", + "integrity": "sha512-mW1cnfy+mQUKXmyXD27z4S8Yvs1HCmum15yy76UNQv6KVFO26zVZ12jkT7pDeDl3YpR6hCeT+kD47j1lDDX/qg==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/overlays": "^3.25.0", - "@react-aria/utils": "^3.27.0", - "@react-types/dialog": "^3.5.15", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.0", + "@react-aria/overlays": "^3.26.0", + "@react-aria/utils": "^3.28.0", + "@react-types/dialog": "^3.5.16", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3518,15 +3520,15 @@ } }, "node_modules/@react-aria/disclosure": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@react-aria/disclosure/-/disclosure-3.0.1.tgz", - "integrity": "sha512-rNH8RFcePoAQizcqB7KuHbBOr7sPsysFKCUwbVSOXLPgvCfXKafIhjgFJVqekfsbn5zWvkcTupnzGVJj/F9p+g==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@react-aria/disclosure/-/disclosure-3.0.2.tgz", + "integrity": "sha512-5+PBPGZkPStMYzz1dQsUHORiOG3vLRdv4Q4kfsd6ZKRIqEsRLKL+lciw8kjb7E9ixt+2r0gjearkqG2vVPf33w==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-stately/disclosure": "^3.0.1", - "@react-types/button": "^3.10.2", + "@react-aria/utils": "^3.28.0", + "@react-stately/disclosure": "^3.0.2", + "@react-types/button": "^3.11.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3535,20 +3537,20 @@ } }, "node_modules/@react-aria/dnd": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@react-aria/dnd/-/dnd-3.8.1.tgz", - "integrity": "sha512-FoXYQ4z33E9YBzIGRJM1B1oZep6CvEWgXvjCZGURatjr3qG7vf95mOqA5kVd9bjLL7QK4w0ujJWEBfog3WmufA==", + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/@react-aria/dnd/-/dnd-3.9.0.tgz", + "integrity": "sha512-vQrcNpDlFCjICD3hO7iugDblAw8+n/1Kka2hubRbsrignNIHlMJNs5/TpK2Id6xgz37LmBaf7lEwkH87x1tZmQ==", "license": "Apache-2.0", "dependencies": { "@internationalized/string": "^3.2.5", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/overlays": "^3.25.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/dnd": "^3.5.1", - "@react-types/button": "^3.10.2", - "@react-types/shared": "^3.27.0", + "@react-aria/overlays": "^3.26.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/dnd": "^3.5.2", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3557,14 +3559,14 @@ } }, "node_modules/@react-aria/focus": { - "version": "3.19.1", - "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.19.1.tgz", - "integrity": "sha512-bix9Bu1Ue7RPcYmjwcjhB14BMu2qzfJ3tMQLqDc9pweJA66nOw8DThy3IfVr8Z7j2PHktOLf9kcbiZpydKHqzg==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.20.0.tgz", + "integrity": "sha512-KXZCwWzwnmtUo6xhnyV26ptxlxmqd0Reez7axduqqqeDDgDZOVscoo/5gFg71fdPZmnDC8MyUK1vxSbMhOTrGg==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -3574,15 +3576,15 @@ } }, "node_modules/@react-aria/form": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.0.12.tgz", - "integrity": "sha512-8uvPYEd3GDyGt5NRJIzdWW1Ry5HLZq37vzRZKUW8alZ2upFMH3KJJG55L9GP59KiF6zBrYBebvI/YK1Ye1PE1g==", + "version": "3.0.13", + "resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.0.13.tgz", + "integrity": "sha512-f7zoFMQYBRWhKFX14rlFjSUDbNAvNMLpWRKVP3O0rUYTxh95iF5tcfUk5+lxWkVfmVj8S4O8du0ccv/ZQjPsYg==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/form": "^3.1.1", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/form": "^3.1.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3591,23 +3593,23 @@ } }, "node_modules/@react-aria/grid": { - "version": "3.11.1", - "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.11.1.tgz", - "integrity": "sha512-Wg8m68RtNWfkhP3Qjrrsl1q1et8QCjXPMRsYgKBahYRS0kq2MDcQ+UBdG1fiCQn/MfNImhTUGVeQX276dy1lww==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@react-aria/grid/-/grid-3.12.0.tgz", + "integrity": "sha512-w1hVZP73QX/9YCc9pXBJzT71m3mKAHcNI68Z25NbQqwr774b5g1fdcO8o7knnlKXZVsM+Vz30kdRP8iG5GqY6A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/collections": "^3.12.1", - "@react-stately/grid": "^3.10.1", - "@react-stately/selection": "^3.19.0", - "@react-types/checkbox": "^3.9.1", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/grid": "^3.11.0", + "@react-stately/selection": "^3.20.0", + "@react-types/checkbox": "^3.9.2", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3616,21 +3618,21 @@ } }, "node_modules/@react-aria/gridlist": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-aria/gridlist/-/gridlist-3.10.1.tgz", - "integrity": "sha512-11FlupBg5C9ehs7R6OjqMPWEOLK/4IuSrq7D1xU+Hnm7ZYI/KKcCXvNMjMmnOz/gGzOmfgVwz5PIKaY9aZarEg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-aria/gridlist/-/gridlist-3.11.0.tgz", + "integrity": "sha512-B4wt/2t6BD3TEAj4lycpT3On3TeFG+T9bmsdz0jeMVnIu4HLL0XX4owBKaNQ7qkTDhlgKn96VotQV/ZAiTi1bA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/grid": "^3.11.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/collections": "^3.12.1", - "@react-stately/list": "^3.11.2", - "@react-stately/tree": "^3.8.7", - "@react-types/shared": "^3.27.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/grid": "^3.12.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/list": "^3.12.0", + "@react-stately/tree": "^3.8.8", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3639,9 +3641,9 @@ } }, "node_modules/@react-aria/i18n": { - "version": "3.12.5", - "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.5.tgz", - "integrity": "sha512-ooeop2pTG94PuaHoN2OTk2hpkqVuoqgEYxRvnc1t7DVAtsskfhS/gVOTqyWGsxvwAvRi7m/CnDu6FYdeQ/bK5w==", + "version": "3.12.6", + "resolved": "https://registry.npmjs.org/@react-aria/i18n/-/i18n-3.12.6.tgz", + "integrity": "sha512-I2Qz1vAlgdeW2GUMLhHucYhk514/BRuEzvH1iih8qeqvv0gEbKdSIjPJUomW+WzYVmJ2/bwKQAr7otr2fNcbrw==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", @@ -3649,8 +3651,8 @@ "@internationalized/number": "^3.6.0", "@internationalized/string": "^3.2.5", "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3659,14 +3661,15 @@ } }, "node_modules/@react-aria/interactions": { - "version": "3.23.0", - "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.23.0.tgz", - "integrity": "sha512-0qR1atBIWrb7FzQ+Tmr3s8uH5mQdyRH78n0krYaG8tng9+u1JlSi8DGRSaC9ezKyNB84m7vHT207xnHXGeJ3Fg==", + "version": "3.24.0", + "resolved": "https://registry.npmjs.org/@react-aria/interactions/-/interactions-3.24.0.tgz", + "integrity": "sha512-6Zdhp1pswyPgbwEWzvXARdKAWPjP7mACczoIUvlEQiMsX04fuizBiBLAA+W/5mPe17pbJYHA/rxZF5Y5m+M0Ng==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/flags": "^3.1.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3675,13 +3678,13 @@ } }, "node_modules/@react-aria/label": { - "version": "3.7.14", - "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.14.tgz", - "integrity": "sha512-EN1Md2YvcC4sMqBoggsGYUEGlTNqUfJZWzduSt29fbQp1rKU2KlybTe+TWxKq/r2fFd+4JsRXxMeJiwB3w2AQA==", + "version": "3.7.15", + "resolved": "https://registry.npmjs.org/@react-aria/label/-/label-3.7.15.tgz", + "integrity": "sha512-jbSxijCLHdQ/HX0yyhrsY0ypZled5omAK7Eh+Z6vW0qpoqvM1rR/ChaoUje9tW5FmMDjafbt905RUxy0xnMQ1A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3689,17 +3692,32 @@ "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, - "node_modules/@react-aria/link": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.7.8.tgz", - "integrity": "sha512-oiXUPQLZmf9Q9Xehb/sG1QRxfo28NFKdh9w+unD12sHI6NdLMETl5MA4CYyTgI0dfMtTjtfrF68GCnWfc7JvXQ==", + "node_modules/@react-aria/landmark": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-aria/landmark/-/landmark-3.0.0.tgz", + "integrity": "sha512-2rJwAQkk0HeAtvI7b47f4esRt9XYeP7GnMYGaILBBSy5aUi85B57ZyqF6RmrKq0z61ZyH5+zW/YK+9Wb/ZK7aA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-types/link": "^3.5.10", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", + "@swc/helpers": "^0.5.0", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/link": { + "version": "3.7.9", + "resolved": "https://registry.npmjs.org/@react-aria/link/-/link-3.7.9.tgz", + "integrity": "sha512-2LE3p5Gqp1Tl/3JF4CmeJT3RsdDBawBaIMlqiOT7t505z1TZI8ygHHq5FFok8FMwpy2yxpqRNW9jDa3gZj575w==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-types/link": "^3.5.11", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3708,19 +3726,19 @@ } }, "node_modules/@react-aria/listbox": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.14.0.tgz", - "integrity": "sha512-pyVbKavh8N8iyiwOx6I3JIcICvAzFXkKSFni1yarfgngJsJV3KSyOkzLomOfN9UhbjcV4sX61/fccwJuvlurlA==", + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/@react-aria/listbox/-/listbox-3.14.1.tgz", + "integrity": "sha512-4uiY7HG4ekF37wNX5hHEMhshkXrU1U4593LVNYjUZHizcB1ZahXzo/F0T3qpeNo+/j89ls8qhDHx/bGIWNj1aQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/collections": "^3.12.1", - "@react-stately/list": "^3.11.2", - "@react-types/listbox": "^3.5.4", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/list": "^3.12.0", + "@react-types/listbox": "^3.5.5", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3738,24 +3756,24 @@ } }, "node_modules/@react-aria/menu": { - "version": "3.17.0", - "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.17.0.tgz", - "integrity": "sha512-aiFvSv3G1YvPC0klJQ/9quB05xIDZzJ5Lt6/CykP0UwGK5i8GCqm6/cyFLwEXsS5ooUPxS3bqmdOsgdADSSgqg==", + "version": "3.18.0", + "resolved": "https://registry.npmjs.org/@react-aria/menu/-/menu-3.18.0.tgz", + "integrity": "sha512-UvcGwx5mGWpZF/d1cQsvCzt0gG5NKbrgAe9B5pumzMfWyXpbkRB0v90GnUlPShbemLhYmWCnTXlN9ogEdAV1dw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/overlays": "^3.25.0", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/collections": "^3.12.1", - "@react-stately/menu": "^3.9.1", - "@react-stately/selection": "^3.19.0", - "@react-stately/tree": "^3.8.7", - "@react-types/button": "^3.10.2", - "@react-types/menu": "^3.9.14", - "@react-types/shared": "^3.27.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/overlays": "^3.26.0", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/menu": "^3.9.2", + "@react-stately/selection": "^3.20.0", + "@react-stately/tree": "^3.8.8", + "@react-types/button": "^3.11.0", + "@react-types/menu": "^3.9.15", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3764,36 +3782,37 @@ } }, "node_modules/@react-aria/meter": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@react-aria/meter/-/meter-3.4.19.tgz", - "integrity": "sha512-IIA+gTHrNVbMuBgcqdGLEKd/ZiKM2hOUqS6uztbT15dwPJTmtfJiTWA2872PiY52p+gqPSanZuTc2TXYJa+rew==", + "version": "3.4.20", + "resolved": "https://registry.npmjs.org/@react-aria/meter/-/meter-3.4.20.tgz", + "integrity": "sha512-JiDKZMs4W1eqJoUQvhY15pRFluh15JPiU9iNbqKOnV5nXdQSIAfGBe6jXGVVE8yb54v6OHG0Gcltl89iN2oFzQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/progress": "^3.4.19", - "@react-types/meter": "^3.4.6", - "@react-types/shared": "^3.27.0", + "@react-aria/progress": "^3.4.20", + "@react-types/meter": "^3.4.7", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/numberfield": { - "version": "3.11.10", - "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.11.10.tgz", - "integrity": "sha512-bYbTfO9NbAKMFOfEGGs+lvlxk0I9L0lU3WD2PFQZWdaoBz9TCkL+vK0fJk1zsuKaVjeGsmHP9VesBPRmaP0MiA==", + "version": "3.11.11", + "resolved": "https://registry.npmjs.org/@react-aria/numberfield/-/numberfield-3.11.11.tgz", + "integrity": "sha512-LKPU+l4YzZMcfuBs06G3+FIagvW3ZxYy7g5s7VRfktGAQkbCMQt3e8felk2aSdEK0kD6fXh/EiATxSgKNKnNAA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/spinbutton": "^3.6.11", - "@react-aria/textfield": "^3.16.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/form": "^3.1.1", - "@react-stately/numberfield": "^3.9.9", - "@react-types/button": "^3.10.2", - "@react-types/numberfield": "^3.8.8", - "@react-types/shared": "^3.27.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/spinbutton": "^3.6.12", + "@react-aria/textfield": "^3.17.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/form": "^3.1.2", + "@react-stately/numberfield": "^3.9.10", + "@react-types/button": "^3.11.0", + "@react-types/numberfield": "^3.8.9", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3802,21 +3821,21 @@ } }, "node_modules/@react-aria/overlays": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.25.0.tgz", - "integrity": "sha512-UEqJJ4duowrD1JvwXpPZreBuK79pbyNjNxFUVpFSskpGEJe3oCWwsSDKz7P1O7xbx5OYp+rDiY8fk/sE5rkaKw==", + "version": "3.26.0", + "resolved": "https://registry.npmjs.org/@react-aria/overlays/-/overlays-3.26.0.tgz", + "integrity": "sha512-Rr3yoyGwXzp446QK6CwnjJl9ZfH/Cq2o01XQmMjya2gmk5N4aefRORg7eRoVy5EVfecIH/HJVg0BKEjXQOp4nA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", "@react-aria/ssr": "^3.9.7", - "@react-aria/utils": "^3.27.0", - "@react-aria/visually-hidden": "^3.8.19", - "@react-stately/overlays": "^3.6.13", - "@react-types/button": "^3.10.2", - "@react-types/overlays": "^3.8.12", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-aria/visually-hidden": "^3.8.20", + "@react-stately/overlays": "^3.6.14", + "@react-types/button": "^3.11.0", + "@react-types/overlays": "^3.8.13", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3825,16 +3844,16 @@ } }, "node_modules/@react-aria/progress": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.19.tgz", - "integrity": "sha512-5HHnBJHqEUuY+dYsjIZDYsENeKr49VCuxeaDZ0OSahbOlloIOB1baCo/6jLBv1O1rwrAzZ2gCCPcVGed/cjrcw==", + "version": "3.4.20", + "resolved": "https://registry.npmjs.org/@react-aria/progress/-/progress-3.4.20.tgz", + "integrity": "sha512-N3X8R5G+/CPMnRqNZ1f68t2d5nGUqJH9GDw67tBUzr2Bti/0hcC6euGTOZWAQw1EDX8rZdkLY7qM7n9sX9GTJQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", - "@react-aria/label": "^3.7.14", - "@react-aria/utils": "^3.27.0", - "@react-types/progress": "^3.5.9", - "@react-types/shared": "^3.27.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/label": "^3.7.15", + "@react-aria/utils": "^3.28.0", + "@react-types/progress": "^3.5.10", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3843,20 +3862,20 @@ } }, "node_modules/@react-aria/radio": { - "version": "3.10.11", - "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.10.11.tgz", - "integrity": "sha512-R150HsBFPr1jLMShI4aBM8heCa1k6h0KEvnFRfTAOBu+B9hMSZOPB+d6GQOwGPysNlbset90Kej8G15FGHjqiA==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-aria/radio/-/radio-3.11.0.tgz", + "integrity": "sha512-twaJlT4prn1jSK9Wq5JDX+ywQ6hVnt8eea5cwe33bU87aQxCoz1PZAp5/cqEA8CT7jJUCM3wPQ8eBRtpHnjYNQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/form": "^3.0.12", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/utils": "^3.27.0", - "@react-stately/radio": "^3.10.10", - "@react-types/radio": "^3.8.6", - "@react-types/shared": "^3.27.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/form": "^3.0.13", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/utils": "^3.28.0", + "@react-stately/radio": "^3.10.11", + "@react-types/radio": "^3.8.7", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3865,18 +3884,18 @@ } }, "node_modules/@react-aria/searchfield": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/@react-aria/searchfield/-/searchfield-3.8.0.tgz", - "integrity": "sha512-AaZuH9YIWlMyE1m7cSjHCfOuQmlWN+w8HVW32TxeGGGL1kJsYAlSYWYHUyYFIKh245kq/m5zUxAxmw5Ygmnx5w==", + "version": "3.8.1", + "resolved": "https://registry.npmjs.org/@react-aria/searchfield/-/searchfield-3.8.1.tgz", + "integrity": "sha512-KMY6slZTM940Jk/kimeh0Lw/VxP0PSDBdjoYLzOjQkUDBlvybDj5jSXnT7ZFr/NXX67/lDNulJgCrVxRoYnI6Q==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", - "@react-aria/textfield": "^3.16.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/searchfield": "^3.5.9", - "@react-types/button": "^3.10.2", - "@react-types/searchfield": "^3.5.11", - "@react-types/shared": "^3.27.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/textfield": "^3.17.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/searchfield": "^3.5.10", + "@react-types/button": "^3.11.0", + "@react-types/searchfield": "^3.6.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3885,24 +3904,24 @@ } }, "node_modules/@react-aria/select": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/@react-aria/select/-/select-3.15.1.tgz", - "integrity": "sha512-FOtY1tuHt0YTHwOEy/sf7LEIL+Nnkho3wJmfpWQuTxsvMCF7UJdQPYPd6/jGCcCdiqW7H4iqyjUkSp6nk/XRWQ==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/@react-aria/select/-/select-3.15.2.tgz", + "integrity": "sha512-DO8KRopzoBOtbixcXfo7meKTAg4IUyW1lPxo4esfot7OZCNvzbH+Mkx0aDgfQfItd8+7Xj8rhQPL58aauJKw9A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/form": "^3.0.12", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/listbox": "^3.14.0", - "@react-aria/menu": "^3.17.0", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-aria/visually-hidden": "^3.8.19", - "@react-stately/select": "^3.6.10", - "@react-types/button": "^3.10.2", - "@react-types/select": "^3.9.9", - "@react-types/shared": "^3.27.0", + "@react-aria/form": "^3.0.13", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/listbox": "^3.14.1", + "@react-aria/menu": "^3.18.0", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-aria/visually-hidden": "^3.8.20", + "@react-stately/select": "^3.6.11", + "@react-types/button": "^3.11.0", + "@react-types/select": "^3.9.10", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3911,17 +3930,17 @@ } }, "node_modules/@react-aria/selection": { - "version": "3.22.0", - "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.22.0.tgz", - "integrity": "sha512-XFOrK525HX2eeWeLZcZscUAs5qsuC1ZxsInDXMjvLeAaUPtQNEhUKHj3psDAl6XDU4VV1IJo0qCmFTVqTTMZSg==", + "version": "3.23.0", + "resolved": "https://registry.npmjs.org/@react-aria/selection/-/selection-3.23.0.tgz", + "integrity": "sha512-m/sq3UuaTFRiEU9S6K+nkn9ONcpCtFskeJH/IZ9l/583X08KEoW/A3Vehrf3dlL8CNbkKKPfkUdKh1X6gTmHzA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/selection": "^3.19.0", - "@react-types/shared": "^3.27.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/selection": "^3.20.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3930,13 +3949,13 @@ } }, "node_modules/@react-aria/separator": { - "version": "3.4.5", - "resolved": "https://registry.npmjs.org/@react-aria/separator/-/separator-3.4.5.tgz", - "integrity": "sha512-RQA9sKZdAEjP1Yrv0GpDdXgmXd56kXDE8atPDHEC0/A4lpYh/YFLfXcv1JW0Hlg4kBocdX2pB2INyDGhiD+yfw==", + "version": "3.4.6", + "resolved": "https://registry.npmjs.org/@react-aria/separator/-/separator-3.4.6.tgz", + "integrity": "sha512-V6qVI03vzDhFfj3uDurSxtuEXpAJFntQgvaYXrdZ35lhHJDmuo1iCXqRrXkd4g21wvdidQ6WWeVl650ewxirpA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3945,19 +3964,18 @@ } }, "node_modules/@react-aria/slider": { - "version": "3.7.15", - "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.7.15.tgz", - "integrity": "sha512-v9tujsuvJYRX0vE/vMYBzTT9FXbzrLsjkOrouNq+UdBIr7wRjIWTHHM0j+khb2swyCWNTbdv6Ce316Zqx2qWFg==", + "version": "3.7.16", + "resolved": "https://registry.npmjs.org/@react-aria/slider/-/slider-3.7.16.tgz", + "integrity": "sha512-SBcEbQWv1gDxx6TsNPVMOA4hNAsvPgMC9MuQQrXR1azIDlraU7A8tIMfs7BfEomiSaaZjxBso/xiZMuEJc7trQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/utils": "^3.27.0", - "@react-stately/slider": "^3.6.1", - "@react-types/shared": "^3.27.0", - "@react-types/slider": "^3.7.8", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/utils": "^3.28.0", + "@react-stately/slider": "^3.6.2", + "@react-types/shared": "^3.28.0", + "@react-types/slider": "^3.7.9", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3966,16 +3984,16 @@ } }, "node_modules/@react-aria/spinbutton": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.11.tgz", - "integrity": "sha512-RM+gYS9tf9Wb+GegV18n4ArK3NBKgcsak7Nx1CkEgX9BjJ0yayWUHdfEjRRvxGXl+1z1n84cJVkZ6FUlWOWEZA==", + "version": "3.6.12", + "resolved": "https://registry.npmjs.org/@react-aria/spinbutton/-/spinbutton-3.6.12.tgz", + "integrity": "sha512-MtYYWl6wvUv+sUcEucTiHMoSRs2GsSNh+awEBJ5/boqQKU+bLjZ/9j/qIJO8Iueet2535HtLMKz1IsM0Pltrng==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", + "@react-aria/i18n": "^3.12.6", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/utils": "^3.27.0", - "@react-types/button": "^3.10.2", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -3999,41 +4017,42 @@ } }, "node_modules/@react-aria/switch": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.6.11.tgz", - "integrity": "sha512-paYCpH+oeL+8rgQK+cBJ+IaZ1sXSh3+50WPlg2LvLBta0QVfQhPR4juPvfXRpfHHhCjFBgF4/RGbV8q5zpl3vA==", + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/@react-aria/switch/-/switch-3.7.0.tgz", + "integrity": "sha512-TwTKz9qO6FUg/szH/uqODvlXM8BKSXuFQMct3Tp/FsILFqfX9FQcD5jwbclmN5tywCVdeJU/OkICldxMx4gFeA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/toggle": "^3.10.11", - "@react-stately/toggle": "^3.8.1", - "@react-types/shared": "^3.27.0", - "@react-types/switch": "^3.5.8", + "@react-aria/toggle": "^3.11.0", + "@react-stately/toggle": "^3.8.2", + "@react-types/shared": "^3.28.0", + "@react-types/switch": "^3.5.9", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-aria/table": { - "version": "3.16.1", - "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.16.1.tgz", - "integrity": "sha512-T28TIGnKnPBunyErDBmm5jUX7AyzT7NVWBo9pDSt9wUuEnz0rVNd7p9sjmP2+u7I645feGG9klcdpCvFeqrk8A==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@react-aria/table/-/table-3.17.0.tgz", + "integrity": "sha512-x6jW3r0AIIbcGxra0yrecndA0kSnyEQWC16kVXmceLo0F4UCSmRRomWxEtvM3TZoesKlNpDYzipJJLT4HpbPVw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/grid": "^3.11.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/grid": "^3.12.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/utils": "^3.27.0", - "@react-aria/visually-hidden": "^3.8.19", - "@react-stately/collections": "^3.12.1", - "@react-stately/flags": "^3.0.5", - "@react-stately/table": "^3.13.1", - "@react-types/checkbox": "^3.9.1", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", - "@react-types/table": "^3.10.4", + "@react-aria/utils": "^3.28.0", + "@react-aria/visually-hidden": "^3.8.20", + "@react-stately/collections": "^3.12.2", + "@react-stately/flags": "^3.1.0", + "@react-stately/table": "^3.14.0", + "@react-types/checkbox": "^3.9.2", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", + "@react-types/table": "^3.11.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4042,18 +4061,18 @@ } }, "node_modules/@react-aria/tabs": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.9.9.tgz", - "integrity": "sha512-oXPtANs16xu6MdMGLHjGV/2Zupvyp9CJEt7ORPLv5xAzSY5hSjuQHJLZ0te3Lh/KSG5/0o3RW/W5yEqo7pBQQQ==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/@react-aria/tabs/-/tabs-3.10.0.tgz", + "integrity": "sha512-1wGB4CtkP/F0/4YTDoB7XoPr4Ea6dbLTpLHQiS0cxf0kA3NZCxRguIffRbigE/D6fHArzWyKedSo6FzJR/WPZw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/tabs": "^3.7.1", - "@react-types/shared": "^3.27.0", - "@react-types/tabs": "^3.3.12", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/tabs": "^3.8.0", + "@react-types/shared": "^3.28.0", + "@react-types/tabs": "^3.3.13", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4062,20 +4081,20 @@ } }, "node_modules/@react-aria/tag": { - "version": "3.4.9", - "resolved": "https://registry.npmjs.org/@react-aria/tag/-/tag-3.4.9.tgz", - "integrity": "sha512-Vnps+zk8vYyjevv2Bc6vc9kSp9HFLKrKUDmrWMc0DfseypwJMc3Ya6F965ZVTjF9nuWrojNmvgusNu7qyXFShQ==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/@react-aria/tag/-/tag-3.5.0.tgz", + "integrity": "sha512-VqYbctlV5Slhy3rT+HVwkyts1z5KTdOvlM/MNzYExMiSbKXq8KkwQNq10gNKLNE5c5BdOAZ5MwWIIfnASf+c1A==", "license": "Apache-2.0", "dependencies": { - "@react-aria/gridlist": "^3.10.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/list": "^3.11.2", - "@react-types/button": "^3.10.2", - "@react-types/shared": "^3.27.0", + "@react-aria/gridlist": "^3.11.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/list": "^3.12.0", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4084,19 +4103,39 @@ } }, "node_modules/@react-aria/textfield": { - "version": "3.16.0", - "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.16.0.tgz", - "integrity": "sha512-53RVpMeMDN/QoabqnYZ1lxTh1xTQ3IBYQARuayq5EGGMafyxoFHzttxUdSqkZGK/+zdSF2GfmjOYJVm2nDKuDQ==", + "version": "3.17.0", + "resolved": "https://registry.npmjs.org/@react-aria/textfield/-/textfield-3.17.0.tgz", + "integrity": "sha512-asvbf0xC17qSQ51OojRELUtbTfVe42YE26KUZ/dtxkj+Ln20nj1F3UWXU3hDCn36hbj3vnJ2Zp8X6aGOfJP0qQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/form": "^3.0.12", - "@react-aria/label": "^3.7.14", - "@react-aria/utils": "^3.27.0", - "@react-stately/form": "^3.1.1", + "@react-aria/form": "^3.0.13", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/utils": "^3.28.0", + "@react-stately/form": "^3.1.2", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", - "@react-types/textfield": "^3.11.0", + "@react-types/shared": "^3.28.0", + "@react-types/textfield": "^3.12.0", + "@swc/helpers": "^0.5.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, + "node_modules/@react-aria/toast": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-aria/toast/-/toast-3.0.0.tgz", + "integrity": "sha512-KDbJy8BFNTjc9ABEVWrgiAFRtGHSkRPv2AK4b7Yv1sQ3ePuZ0BIUtn2DQODNAFbLs/Z/OgoqLYMOORqL3Ti7pQ==", + "license": "Apache-2.0", + "dependencies": { + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/landmark": "^3.0.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/toast": "^3.0.0", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4105,17 +4144,16 @@ } }, "node_modules/@react-aria/toggle": { - "version": "3.10.11", - "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.10.11.tgz", - "integrity": "sha512-J3jO3KJiUbaYVDEpeXSBwqcyKxpi9OreiHRGiaxb6VwB+FWCj7Gb2WKajByXNyfs8jc6kX9VUFaXa7jze60oEQ==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-aria/toggle/-/toggle-3.11.0.tgz", + "integrity": "sha512-LQcuGxkoHIb79phsGVzLVWlA25Uj14fRMEo4r/DRB9xE+IiOgO8g3gaA5oWNT3kpM898lTxaIv1yVxhWZEksrQ==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/toggle": "^3.8.1", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/toggle": "^3.8.2", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4124,15 +4162,15 @@ } }, "node_modules/@react-aria/toolbar": { - "version": "3.0.0-beta.12", - "resolved": "https://registry.npmjs.org/@react-aria/toolbar/-/toolbar-3.0.0-beta.12.tgz", - "integrity": "sha512-a+Be27BtM2lzEdTzm19FikPbitfW65g/JZln3kyAvgpswhU6Ljl8lztaVw4ixjG4H0nqnKvVggMy4AlWwDUaVQ==", + "version": "3.0.0-beta.13", + "resolved": "https://registry.npmjs.org/@react-aria/toolbar/-/toolbar-3.0.0-beta.13.tgz", + "integrity": "sha512-aj5lWdk/yp2Tmuuofu1rdkvhiYPCXihuPFbs+9HHz88kyezM7bkhmQRIf0w47tiPIKUA0UuwJucBjDZfl9EQFw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4141,17 +4179,16 @@ } }, "node_modules/@react-aria/tooltip": { - "version": "3.7.11", - "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.7.11.tgz", - "integrity": "sha512-mhZgAWUj7bUWipDeJXaVPZdqnzoBCd/uaEbdafnvgETmov1udVqPTh9w4ZKX2Oh1wa2+OdLFrBOk+8vC6QbWag==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@react-aria/tooltip/-/tooltip-3.8.0.tgz", + "integrity": "sha512-Tal09bWgursZ3v1qUuB/0z4Cz+jcDIfe8G5TECMtr0vbfYh2u7RIjBNZnsRcxZ2syXDxhHrPNeh8mrp4vKCAKg==", "license": "Apache-2.0", "dependencies": { - "@react-aria/focus": "^3.19.1", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/tooltip": "^3.5.1", - "@react-types/shared": "^3.27.0", - "@react-types/tooltip": "^3.4.14", + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/tooltip": "^3.5.2", + "@react-types/shared": "^3.28.0", + "@react-types/tooltip": "^3.4.15", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4160,18 +4197,18 @@ } }, "node_modules/@react-aria/tree": { - "version": "3.0.0-beta.3", - "resolved": "https://registry.npmjs.org/@react-aria/tree/-/tree-3.0.0-beta.3.tgz", - "integrity": "sha512-eQnCtvDgpunCHInIT+Da3qdgzDzKEFW9REX2j1vMqWTsbM1YikVlBzB9AJOd9KIAWyn+p4TYdL8zzPWxvuSdfA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-aria/tree/-/tree-3.0.0.tgz", + "integrity": "sha512-utWVgR7Tmq7lPDRL+ud2nzNhv3GPtFnCE52ACQOUR8D8YL2EJhVKt8kMzrf92aQgTZPq6zWI6kRkxFJ/HORDvg==", "license": "Apache-2.0", "dependencies": { - "@react-aria/gridlist": "^3.10.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/selection": "^3.22.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/tree": "^3.8.7", - "@react-types/button": "^3.10.2", - "@react-types/shared": "^3.27.0", + "@react-aria/gridlist": "^3.11.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/selection": "^3.23.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/tree": "^3.8.8", + "@react-types/button": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4180,14 +4217,15 @@ } }, "node_modules/@react-aria/utils": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.27.0.tgz", - "integrity": "sha512-p681OtApnKOdbeN8ITfnnYqfdHS0z7GE+4l8EXlfLnr70Rp/9xicBO6d2rU+V/B3JujDw2gPWxYKEnEeh0CGCw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-aria/utils/-/utils-3.28.0.tgz", + "integrity": "sha512-FfpvpADk61OvEnFe37k6jF1zr5gtafIPN9ccJRnPCTqrzuExag01mGi+wX/hWyFK0zAe1OjWf1zFOX3FsFvikg==", "license": "Apache-2.0", "dependencies": { "@react-aria/ssr": "^3.9.7", + "@react-stately/flags": "^3.1.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0", "clsx": "^2.0.0" }, @@ -4197,16 +4235,16 @@ } }, "node_modules/@react-aria/virtualizer": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@react-aria/virtualizer/-/virtualizer-4.1.1.tgz", - "integrity": "sha512-AYQmC/S9HhxGOj8HkQdxDW8/+sUEmmfcGpjkInzXB8UZCB1FQLC0LpvA8fOP7AfzLaAL+HVcYF5BvnGMPijHTQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/@react-aria/virtualizer/-/virtualizer-4.1.2.tgz", + "integrity": "sha512-IZyV7yhxcMjzoTgVvQ6gmS8PFiVhwXVQ93X+l87bwR2K/z3z+hvhR4JNuA8qsqK5Lr0yUUlY06iM/h2yZRv7Nw==", "license": "Apache-2.0", "dependencies": { - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-stately/virtualizer": "^4.2.1", - "@react-types/shared": "^3.27.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-stately/virtualizer": "^4.3.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4215,14 +4253,14 @@ } }, "node_modules/@react-aria/visually-hidden": { - "version": "3.8.19", - "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.19.tgz", - "integrity": "sha512-MZgCCyQ3sdG94J5iJz7I7Ai3IxoN0U5d/+EaUnA1mfK7jf2fSYQBqi6Eyp8sWUYzBTLw4giXB5h0RGAnWzk9hA==", + "version": "3.8.20", + "resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.20.tgz", + "integrity": "sha512-Y7JbrpheUhNgnJWogDWxuxxiWAnuaW9MKOUY5vD3KOa+vEWuc2IBOGSzOOUkAGnVP4L2rvaHeZIuR5flqyeskA==", "license": "Apache-2.0", "dependencies": { - "@react-aria/interactions": "^3.23.0", - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/interactions": "^3.24.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4231,9 +4269,9 @@ } }, "node_modules/@react-stately/autocomplete": { - "version": "3.0.0-alpha.0", - "resolved": "https://registry.npmjs.org/@react-stately/autocomplete/-/autocomplete-3.0.0-alpha.0.tgz", - "integrity": "sha512-as4si0pBcnGnggwpvemMwCLTeV0h9GS9e5eHSR3RFg14eqUHZBEzYJ0kh9oTugpsGuf1TSM/HDizo8GQk3EtPA==", + "version": "3.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@react-stately/autocomplete/-/autocomplete-3.0.0-beta.0.tgz", + "integrity": "sha512-nWRbDzqHzdZySIqwoEBMIdineoQxR1Wzmb86r+NICBX9cNv0tZBLNnHywHsul/MN61/TthdOpay1QwZUoQSrXw==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.4", @@ -4244,15 +4282,15 @@ } }, "node_modules/@react-stately/calendar": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.7.0.tgz", - "integrity": "sha512-N15zKubP2S7eWfPSJjKVlmJA7YpWzrIGx52BFhwLSQAZcV+OPcMgvOs71WtB7PLwl6DUYQGsgc0B3tcHzzvdvQ==", + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/@react-stately/calendar/-/calendar-3.7.1.tgz", + "integrity": "sha512-DXsJv2Xm1BOqJAx5846TmTG1IZ0oKrBqYAzWZG7hiDq3rPjYGgKtC/iJg9MUev6pHhoZlP9fdRCNFiCfzm5bLQ==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", "@react-stately/utils": "^3.10.5", - "@react-types/calendar": "^3.6.0", - "@react-types/shared": "^3.27.0", + "@react-types/calendar": "^3.6.1", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4260,15 +4298,15 @@ } }, "node_modules/@react-stately/checkbox": { - "version": "3.6.11", - "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.11.tgz", - "integrity": "sha512-jApdBis+Q1sXLivg+f7krcVaP/AMMMiQcVqcz5gwxlweQN+dRZ/NpL0BYaDOuGc26Mp0lcuVaET3jIZeHwtyxA==", + "version": "3.6.12", + "resolved": "https://registry.npmjs.org/@react-stately/checkbox/-/checkbox-3.6.12.tgz", + "integrity": "sha512-gMxrWBl+styUD+2ntNIcviVpGt2Y+cHUGecAiNI3LM8/K6weI7938DWdLdK7i0gDmgSJwhoNRSavMPI1W6aMZQ==", "license": "Apache-2.0", "dependencies": { - "@react-stately/form": "^3.1.1", + "@react-stately/form": "^3.1.2", "@react-stately/utils": "^3.10.5", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4276,12 +4314,12 @@ } }, "node_modules/@react-stately/collections": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.1.tgz", - "integrity": "sha512-8QmFBL7f+P64dEP4o35pYH61/lP0T/ziSdZAvNMrCqaM+fXcMfUp2yu1E63kADVX7WRDsFJWE3CVMeqirPH6Xg==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-stately/collections/-/collections-3.12.2.tgz", + "integrity": "sha512-RoehfGwrsYJ/WGtyGSLZNYysszajnq0Q3iTXg7plfW1vNEzom/A31vrLjOSOHJWAtwW339SDGGRpymDtLo4GWA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4289,19 +4327,19 @@ } }, "node_modules/@react-stately/color": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@react-stately/color/-/color-3.8.2.tgz", - "integrity": "sha512-GXwLmv1Eos2OwOiRsGFrXBKx8+uZh2q0qzLZEVYrWsedNhIdTm7nnpwO68nCYZPHkqhv6rhhVSlOOFmDLY++ow==", + "version": "3.8.3", + "resolved": "https://registry.npmjs.org/@react-stately/color/-/color-3.8.3.tgz", + "integrity": "sha512-0KaVN2pIOxdAKanFxkx/8zl+73tCoUn2+k7nvK7SpAsFpWScteEHW6hMdmQVwQ2+X+OtQRYHyhhTXULMIIY6iw==", "license": "Apache-2.0", "dependencies": { "@internationalized/number": "^3.6.0", "@internationalized/string": "^3.2.5", - "@react-stately/form": "^3.1.1", - "@react-stately/numberfield": "^3.9.9", - "@react-stately/slider": "^3.6.1", + "@react-stately/form": "^3.1.2", + "@react-stately/numberfield": "^3.9.10", + "@react-stately/slider": "^3.6.2", "@react-stately/utils": "^3.10.5", - "@react-types/color": "^3.0.2", - "@react-types/shared": "^3.27.0", + "@react-types/color": "^3.0.3", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4309,19 +4347,19 @@ } }, "node_modules/@react-stately/combobox": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.10.2.tgz", - "integrity": "sha512-uT642Dool4tQBh+8UQjlJnTisrJVtg3LqmiP/HqLQ4O3pW0O+ImbG+2r6c9dUzlAnH4kEfmEwCp9dxkBkmFWsg==", + "version": "3.10.3", + "resolved": "https://registry.npmjs.org/@react-stately/combobox/-/combobox-3.10.3.tgz", + "integrity": "sha512-l4yr8lSHfwFdA+ZpY15w98HkgF1iHytjerdQkMa4C0dCl4NWUyyWMOcgmHA8G56QEdbFo5dXyW6hzF2PJnUOIg==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/form": "^3.1.1", - "@react-stately/list": "^3.11.2", - "@react-stately/overlays": "^3.6.13", - "@react-stately/select": "^3.6.10", + "@react-stately/collections": "^3.12.2", + "@react-stately/form": "^3.1.2", + "@react-stately/list": "^3.12.0", + "@react-stately/overlays": "^3.6.14", + "@react-stately/select": "^3.6.11", "@react-stately/utils": "^3.10.5", - "@react-types/combobox": "^3.13.2", - "@react-types/shared": "^3.27.0", + "@react-types/combobox": "^3.13.3", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4329,12 +4367,12 @@ } }, "node_modules/@react-stately/data": { - "version": "3.12.1", - "resolved": "https://registry.npmjs.org/@react-stately/data/-/data-3.12.1.tgz", - "integrity": "sha512-/Nc8X1FmrJ53QU4rN/1i1JtNir4iqo+39Xn5ZOJ74Nng7T+xVVuEuWSo+OEGaycCJf2eZRsomauPxUnnZgCM1A==", + "version": "3.12.2", + "resolved": "https://registry.npmjs.org/@react-stately/data/-/data-3.12.2.tgz", + "integrity": "sha512-u0yQkISnPyR5RjpNJCSxyC28bx/UvUKtVYRH5yx/MtXbP+2Byn7ItQ+evRqpJB5XsWFlyohGebgbXvL3JSBVsg==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4342,18 +4380,18 @@ } }, "node_modules/@react-stately/datepicker": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.12.0.tgz", - "integrity": "sha512-AfJEP36d+QgQ30GfacXtYdGsJvqY2yuCJ+JrjHct+m1nYuTkMvMMnhwNBFasgDJPLCDyHzyANlWkl2kQGfsBFw==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/@react-stately/datepicker/-/datepicker-3.13.0.tgz", + "integrity": "sha512-I0Y/aQraQyRLMWnh5tBZMiZ0xlmvPjFErXnQaeD7SdOYUHNtQS4BAQsMByQrMfg8uhOqUTKlIh7xEZusuqYWOA==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", "@internationalized/string": "^3.2.5", - "@react-stately/form": "^3.1.1", - "@react-stately/overlays": "^3.6.13", + "@react-stately/form": "^3.1.2", + "@react-stately/overlays": "^3.6.14", "@react-stately/utils": "^3.10.5", - "@react-types/datepicker": "^3.10.0", - "@react-types/shared": "^3.27.0", + "@react-types/datepicker": "^3.11.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4361,13 +4399,13 @@ } }, "node_modules/@react-stately/disclosure": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@react-stately/disclosure/-/disclosure-3.0.1.tgz", - "integrity": "sha512-afpNy5b0UcqRGjU/W5OD0xkx4PbymvhMrgQZ4o4OdtDVMMvr9T5UqMF8/j3J591DxgQfXM872tJu0kotqT0L6Q==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@react-stately/disclosure/-/disclosure-3.0.2.tgz", + "integrity": "sha512-hiArGiJY2y9HcLaGaO1WaXgrTsowd64ZMh8ADVSmxr9drqiMSZ1GXmKuf3DDRHfqKMXX96HNkx5nbv2pczWCsg==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4375,13 +4413,13 @@ } }, "node_modules/@react-stately/dnd": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@react-stately/dnd/-/dnd-3.5.1.tgz", - "integrity": "sha512-N18wt6fka9ngJJqxfAzmdtyrk9whAnqWUxZn22CatjNQsqukI4a6KRYwZTXM9x/wm7KamhVOp+GBl85zM8GLdA==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@react-stately/dnd/-/dnd-3.5.2.tgz", + "integrity": "sha512-W3Q3O3eIMPHGVKSvkswY8+WCXEli6Wr+LLXYizwAl0dt2+dKKE4r91YugSVnJxXq3cw1/Z4nccmsAPRZa31plQ==", "license": "Apache-2.0", "dependencies": { - "@react-stately/selection": "^3.19.0", - "@react-types/shared": "^3.27.0", + "@react-stately/selection": "^3.20.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4389,21 +4427,21 @@ } }, "node_modules/@react-stately/flags": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.0.5.tgz", - "integrity": "sha512-6wks4csxUwPCp23LgJSnkBRhrWpd9jGd64DjcCTNB2AHIFu7Ab1W59pJpUL6TW7uAxVxdNKjgn6D1hlBy8qWsA==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@react-stately/flags/-/flags-3.1.0.tgz", + "integrity": "sha512-KSHOCxTFpBtxhIRcKwsD1YDTaNxFtCYuAUb0KEihc16QwqZViq4hasgPBs2gYm7fHRbw7WYzWKf6ZSo/+YsFlg==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" } }, "node_modules/@react-stately/form": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.1.1.tgz", - "integrity": "sha512-qavrz5X5Mdf/Q1v/QJRxc0F8UTNEyRCNSM1we/nnF7GV64+aYSDLOtaRGmzq+09RSwo1c8ZYnIkK5CnwsPhTsQ==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@react-stately/form/-/form-3.1.2.tgz", + "integrity": "sha512-sKgkV+rxeqM1lf0dCq2wWzdYa5Z0wz/MB3yxjodffy8D43PjFvUOMWpgw/752QHPGCd1XIxA3hE58Dw9FFValg==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4411,15 +4449,15 @@ } }, "node_modules/@react-stately/grid": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.10.1.tgz", - "integrity": "sha512-MOIy//AdxZxIXIzvWSKpvMvaPEMZGQNj+/cOsElHepv/Veh0psNURZMh2TP6Mr0+MnDTZbX+5XIeinGkWYO3JQ==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-stately/grid/-/grid-3.11.0.tgz", + "integrity": "sha512-Wp6kza+2MzNybls9pRWvIwAHwMnSV1eUZXZxLwJy+JVS5lghkr731VvT+YD79z70osJKmgxgmiQGm4/yfetXdA==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/selection": "^3.19.0", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/selection": "^3.20.0", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4427,33 +4465,34 @@ } }, "node_modules/@react-stately/layout": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@react-stately/layout/-/layout-4.1.1.tgz", - "integrity": "sha512-kXeo7HKYTOcqMKru1sKFoMoZA+YywSUqHeIA90MptzRugbFhQGq4nUbIYM2p3FeHAX9HU1JAXThuLcwDOHhB8Q==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@react-stately/layout/-/layout-4.2.0.tgz", + "integrity": "sha512-qeEEwFqhaESIwimLKSWIDoxw40jUj4DjNjs+g18W4+qBBo8aH/cQQqxYQmemscD41gqirRk3HkdqPkXqMBiFIw==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/table": "^3.13.1", - "@react-stately/virtualizer": "^4.2.1", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", - "@react-types/table": "^3.10.4", + "@react-stately/collections": "^3.12.2", + "@react-stately/table": "^3.14.0", + "@react-stately/virtualizer": "^4.3.0", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", + "@react-types/table": "^3.11.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { - "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", + "react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-stately/list": { - "version": "3.11.2", - "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.11.2.tgz", - "integrity": "sha512-eU2tY3aWj0SEeC7lH9AQoeAB4LL9mwS54FvTgHHoOgc1ZIwRJUaZoiuETyWQe98AL8KMgR1nrnDJ1I+CcT1Y7g==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@react-stately/list/-/list-3.12.0.tgz", + "integrity": "sha512-6niQWJ6TZwOKLAOn2wIsxtOvWenh3rKiKdOh4L4O4f7U+h1Hu000Mu4lyIQm2P9uZAkF2Y5QNh6dHN+hSd6h3A==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/selection": "^3.19.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/selection": "^3.20.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4461,14 +4500,14 @@ } }, "node_modules/@react-stately/menu": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.9.1.tgz", - "integrity": "sha512-WRjGGImhQlQaer/hhahGytwd1BDq3fjpTkY/04wv3cQJPJR6lkVI5nSvGFMHfCaErsA1bNyB8/T9Y5F5u4u9ng==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-stately/menu/-/menu-3.9.2.tgz", + "integrity": "sha512-mVCFMUQnEMs6djOqgHC2d46k/5Mv5f6UYa4TMnNDSiY8QlHG4eIdmhBmuYpOwWuOOHJ0xKmLQ4PWLzma/mBorg==", "license": "Apache-2.0", "dependencies": { - "@react-stately/overlays": "^3.6.13", - "@react-types/menu": "^3.9.14", - "@react-types/shared": "^3.27.0", + "@react-stately/overlays": "^3.6.14", + "@react-types/menu": "^3.9.15", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4476,15 +4515,15 @@ } }, "node_modules/@react-stately/numberfield": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.9.9.tgz", - "integrity": "sha512-hZsLiGGHTHmffjFymbH1qVmA633rU2GNjMFQTuSsN4lqqaP8fgxngd5pPCoTCUFEkUgWjdHenw+ZFByw8lIE+g==", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-stately/numberfield/-/numberfield-3.9.10.tgz", + "integrity": "sha512-47ta1GyfLsSaDJIdH6A0ARttPV32nu8a5zUSE2hTfRqwgAd3ksWW5ZEf6qIhDuhnE9GtaIuacsctD8C7M3EOPw==", "license": "Apache-2.0", "dependencies": { "@internationalized/number": "^3.6.0", - "@react-stately/form": "^3.1.1", + "@react-stately/form": "^3.1.2", "@react-stately/utils": "^3.10.5", - "@react-types/numberfield": "^3.8.8", + "@react-types/numberfield": "^3.8.9", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4492,13 +4531,13 @@ } }, "node_modules/@react-stately/overlays": { - "version": "3.6.13", - "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.13.tgz", - "integrity": "sha512-WsU85Gf/b+HbWsnnYw7P/Ila3wD+C37Uk/WbU4/fHgJ26IEOWsPE6wlul8j54NZ1PnLNhV9Fn+Kffi+PaJMQXQ==", + "version": "3.6.14", + "resolved": "https://registry.npmjs.org/@react-stately/overlays/-/overlays-3.6.14.tgz", + "integrity": "sha512-RRalTuHdwrKO1BmXKaqBtE1GGUXU4VUAWwgh4lsP2EFSixDHmOVLxHFDWYvOPChBhpi8KXfLEgm6DEgPBvLBZQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/overlays": "^3.8.12", + "@react-types/overlays": "^3.8.13", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4506,15 +4545,15 @@ } }, "node_modules/@react-stately/radio": { - "version": "3.10.10", - "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.10.tgz", - "integrity": "sha512-9x3bpq87uV8iYA4NaioTTWjriQSlSdp+Huqlxll0T3W3okpyraTTejE91PbIoRTUmL5qByIh2WzxYmr4QdBgAA==", + "version": "3.10.11", + "resolved": "https://registry.npmjs.org/@react-stately/radio/-/radio-3.10.11.tgz", + "integrity": "sha512-dclixp3fwNBbgpbi66x36YGaNwN7hI1nbuhkcnLAE0hWkTO8/wtKBgGqRKSfNV7MSiWlhBhhcdPcQ+V7q7AQIQ==", "license": "Apache-2.0", "dependencies": { - "@react-stately/form": "^3.1.1", + "@react-stately/form": "^3.1.2", "@react-stately/utils": "^3.10.5", - "@react-types/radio": "^3.8.6", - "@react-types/shared": "^3.27.0", + "@react-types/radio": "^3.8.7", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4522,13 +4561,13 @@ } }, "node_modules/@react-stately/searchfield": { - "version": "3.5.9", - "resolved": "https://registry.npmjs.org/@react-stately/searchfield/-/searchfield-3.5.9.tgz", - "integrity": "sha512-7/aO/oLJ4czKEji0taI/lbHKqPJRag9p3YmRaZ4yqjIMpKxzmJCWQcov5lzWeFhG/1hINKndYlxFnVIKV/urpg==", + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@react-stately/searchfield/-/searchfield-3.5.10.tgz", + "integrity": "sha512-6K0+k/8BO/Iq+ODC5mUSIb+tymemliSiSG6B5auWWOZjnnQ0+9M0MYCUdsiJDPk5aUml5aNYI6rlMZO13uHmVw==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/searchfield": "^3.5.11", + "@react-types/searchfield": "^3.6.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4536,16 +4575,16 @@ } }, "node_modules/@react-stately/select": { - "version": "3.6.10", - "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.10.tgz", - "integrity": "sha512-V7V0FCL9T+GzLjyfnJB6PUaKldFyT/8Rj6M+R9ura1A0O+s/FEOesy0pdMXFoL1l5zeUpGlCnhJrsI5HFWHfDw==", + "version": "3.6.11", + "resolved": "https://registry.npmjs.org/@react-stately/select/-/select-3.6.11.tgz", + "integrity": "sha512-8pD4PNbZQNWg33D4+Fa0mrajUCYV3aA5YIwW3GY8NSRwBspaW4PKSZJtDT5ieN0WAO44YkAmX4idRaMAvqRusA==", "license": "Apache-2.0", "dependencies": { - "@react-stately/form": "^3.1.1", - "@react-stately/list": "^3.11.2", - "@react-stately/overlays": "^3.6.13", - "@react-types/select": "^3.9.9", - "@react-types/shared": "^3.27.0", + "@react-stately/form": "^3.1.2", + "@react-stately/list": "^3.12.0", + "@react-stately/overlays": "^3.6.14", + "@react-types/select": "^3.9.10", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4553,14 +4592,14 @@ } }, "node_modules/@react-stately/selection": { - "version": "3.19.0", - "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.19.0.tgz", - "integrity": "sha512-AvbUqnWjqVQC48RD39S9BpMKMLl55Zo5l/yx5JQFPl55cFwe9Tpku1KY0wzt3fXXiXWaqjDn/7Gkg1VJYy8esQ==", + "version": "3.20.0", + "resolved": "https://registry.npmjs.org/@react-stately/selection/-/selection-3.20.0.tgz", + "integrity": "sha512-woUSHMTyQiNmCf63Dyot1WXFfWnm6PFYkI9kymcq1qrrly4g/j27U+5PaRWOHawMiJwn1e1GTogk8B+K5ahshQ==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", + "@react-stately/collections": "^3.12.2", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4568,14 +4607,14 @@ } }, "node_modules/@react-stately/slider": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.6.1.tgz", - "integrity": "sha512-8kij5O82Xe233vZZ6qNGqPXidnlNQiSnyF1q613c7ktFmzAyGjkIWVUapHi23T1fqm7H2Rs3RWlmwE9bo2KecA==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/@react-stately/slider/-/slider-3.6.2.tgz", + "integrity": "sha512-5S9omr29Viv2PRyZ056ZlazGBM8wYNNHakxsTHcSdG/G8WQLrWspWIMiCd4B37cCTkt9ik6AQ6Y3muHGXJI0IQ==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", - "@react-types/slider": "^3.7.8", + "@react-types/shared": "^3.28.0", + "@react-types/slider": "^3.7.9", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4583,19 +4622,19 @@ } }, "node_modules/@react-stately/table": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.13.1.tgz", - "integrity": "sha512-Im8W+F8o9EhglY5kqRa3xcMGXl8zBi6W5phGpAjXb+UGDL1tBIlAcYj733bw8g/ITCnaSz9ubsmON0HekPd6Jg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@react-stately/table/-/table-3.14.0.tgz", + "integrity": "sha512-ALHIgAgSyHeyUiBDWIxmIEl9P4Gy5jlGybcT/rDBM8x7Ik/C/0Hd9f9Y5ubiZSpUGeAXlIaeEdSm0HBfYtQVRw==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/flags": "^3.0.5", - "@react-stately/grid": "^3.10.1", - "@react-stately/selection": "^3.19.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/flags": "^3.1.0", + "@react-stately/grid": "^3.11.0", + "@react-stately/selection": "^3.20.0", "@react-stately/utils": "^3.10.5", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", - "@react-types/table": "^3.10.4", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", + "@react-types/table": "^3.11.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4603,29 +4642,42 @@ } }, "node_modules/@react-stately/tabs": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.7.1.tgz", - "integrity": "sha512-gr9ACyuWrYuc727h7WaHdmNw8yxVlUyQlguziR94MdeRtFGQnf3V6fNQG3kxyB77Ljko69tgDF7Nf6kfPUPAQQ==", + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/@react-stately/tabs/-/tabs-3.8.0.tgz", + "integrity": "sha512-I8ctOsUKPviJ82xWAcZMvWqz5/VZurkE+W9n9wrFbCgHAGK/37bx+PM1uU/Lk4yKp8WrPYSFOEPil5liD+M+ew==", "license": "Apache-2.0", "dependencies": { - "@react-stately/list": "^3.11.2", - "@react-types/shared": "^3.27.0", - "@react-types/tabs": "^3.3.12", + "@react-stately/list": "^3.12.0", + "@react-types/shared": "^3.28.0", + "@react-types/tabs": "^3.3.13", "@swc/helpers": "^0.5.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, + "node_modules/@react-stately/toast": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@react-stately/toast/-/toast-3.0.0.tgz", + "integrity": "sha512-g7e4hNO9E6kOqyBeLRAfZBihp1EIQikmaH3Uj/OZJXKvIDKJlNlpvwstUIcmEuEzqA1Uru78ozxIVWh3pg9ubg==", + "license": "Apache-2.0", + "dependencies": { + "@swc/helpers": "^0.5.0", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" + } + }, "node_modules/@react-stately/toggle": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.8.1.tgz", - "integrity": "sha512-MVpe79ghVQiwLmVzIPhF/O/UJAUc9B+ZSylVTyJiEPi0cwhbkKGQv9thOF0ebkkRkace5lojASqUAYtSTZHQJA==", + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/@react-stately/toggle/-/toggle-3.8.2.tgz", + "integrity": "sha512-5KPpT6zvt8H+WC9UbubhCTZltREeYb/3hKdl4YkS7BbSOQlHTFC0pOk8SsQU70Pwk26jeVHbl5le/N8cw00x8w==", "license": "Apache-2.0", "dependencies": { "@react-stately/utils": "^3.10.5", - "@react-types/checkbox": "^3.9.1", - "@react-types/shared": "^3.27.0", + "@react-types/checkbox": "^3.9.2", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4633,13 +4685,13 @@ } }, "node_modules/@react-stately/tooltip": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.5.1.tgz", - "integrity": "sha512-0aI3U5kB7Cop9OCW9/Bag04zkivFSdUcQgy/TWL4JtpXidVWmOha8txI1WySawFSjZhH83KIyPc+wKm1msfLMQ==", + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/@react-stately/tooltip/-/tooltip-3.5.2.tgz", + "integrity": "sha512-z81kwZWnnf2SE5/rHMrejH5uQu3dXUjrhIa2AGT038DNOmRyS9TkFBywPCiiE7tHpUg/rxZrPxx01JFGvOkmgg==", "license": "Apache-2.0", "dependencies": { - "@react-stately/overlays": "^3.6.13", - "@react-types/tooltip": "^3.4.14", + "@react-stately/overlays": "^3.6.14", + "@react-types/tooltip": "^3.4.15", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4647,15 +4699,15 @@ } }, "node_modules/@react-stately/tree": { - "version": "3.8.7", - "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.8.7.tgz", - "integrity": "sha512-hpc3pyuXWeQV5ufQ02AeNQg/MYhnzZ4NOznlY5OOUoPzpLYiI3ZJubiY3Dot4jw5N/LR7CqvDLHmrHaJPmZlHg==", + "version": "3.8.8", + "resolved": "https://registry.npmjs.org/@react-stately/tree/-/tree-3.8.8.tgz", + "integrity": "sha512-21WB9kKT9+/tr6B8Q4G53tZXl/3dftg5sZqCR6x055FGd2wGVbkxsLhQLmC+XVkTiLU9pB3BjvZ9eaSj1D8Wmg==", "license": "Apache-2.0", "dependencies": { - "@react-stately/collections": "^3.12.1", - "@react-stately/selection": "^3.19.0", + "@react-stately/collections": "^3.12.2", + "@react-stately/selection": "^3.20.0", "@react-stately/utils": "^3.10.5", - "@react-types/shared": "^3.27.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4675,13 +4727,13 @@ } }, "node_modules/@react-stately/virtualizer": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-4.2.1.tgz", - "integrity": "sha512-GHGEXV0ZRhq34U/P3LzkByCBfy2IDynYlV1SE4njkUWWGE/0AH56UegM6w2l3GeiNpXsXCgXl7jpAKeIGMEnrQ==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/@react-stately/virtualizer/-/virtualizer-4.3.0.tgz", + "integrity": "sha512-iU/nns19Ou2Mxr8OhjCQ+NvkOck4uhUZta/WyZmJZ3ynMY8503IwuEF2n+AHg81LiS83/XK8SXq3NTn61Trpgg==", "license": "Apache-2.0", "dependencies": { - "@react-aria/utils": "^3.27.0", - "@react-types/shared": "^3.27.0", + "@react-aria/utils": "^3.28.0", + "@react-types/shared": "^3.28.0", "@swc/helpers": "^0.5.0" }, "peerDependencies": { @@ -4690,346 +4742,346 @@ } }, "node_modules/@react-types/autocomplete": { - "version": "3.0.0-alpha.28", - "resolved": "https://registry.npmjs.org/@react-types/autocomplete/-/autocomplete-3.0.0-alpha.28.tgz", - "integrity": "sha512-meHxBVS5H2L7lVOX99jiAfhcvtG0s7EE7iF7X20/yqEnkwWSpyeMKcDKFpvx/bLGUSmRTVFCBLgvPpwUyhcFkg==", + "version": "3.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/@react-types/autocomplete/-/autocomplete-3.0.0-alpha.29.tgz", + "integrity": "sha512-brP6fb7RAdfu/liaE4gFZIZQJLXksgtOzdu/I5cmcHfpqScAFmgedZHkJoeutK9wTWtNnfuKAFQ2w9KKlIBj9w==", "license": "Apache-2.0", "dependencies": { - "@react-types/combobox": "^3.13.2", - "@react-types/searchfield": "^3.5.11", - "@react-types/shared": "^3.27.0" + "@react-types/combobox": "^3.13.3", + "@react-types/searchfield": "^3.6.0", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/breadcrumbs": { - "version": "3.7.10", - "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.10.tgz", - "integrity": "sha512-5HhRxkKHfAQBoyOYzyf4HT+24HgPE/C/QerxJLNNId303LXO03yeYrbvRqhYZSlD1ACLJW9OmpPpREcw5iSqgw==", + "version": "3.7.11", + "resolved": "https://registry.npmjs.org/@react-types/breadcrumbs/-/breadcrumbs-3.7.11.tgz", + "integrity": "sha512-pMvMLPFr7qs4SSnQ0GyX7i3DkWVs9wfm1lGPFbBO7pJLrHTSK/6Ii4cTEvP6d5o2VgjOVkvce9xCLWW5uosuEQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/link": "^3.5.10", - "@react-types/shared": "^3.27.0" + "@react-types/link": "^3.5.11", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/button": { - "version": "3.10.2", - "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.10.2.tgz", - "integrity": "sha512-h8SB/BLoCgoBulCpyzaoZ+miKXrolK9XC48+n1dKJXT8g4gImrficurDW6+PRTQWaRai0Q0A6bu8UibZOU4syg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-types/button/-/button-3.11.0.tgz", + "integrity": "sha512-gJh5i0JiBiZGZGDo+tXMp6xbixPM7IKZ0sDuxTYBG49qNzzWJq0uNYltO3emwSVXFSsBgRV/Wu8kQGhfuN7wIw==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/calendar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.6.0.tgz", - "integrity": "sha512-BtFh4BFwvsYlsaSqUOVxlqXZSlJ6u4aozgO3PwHykhpemwidlzNwm9qDZhcMWPioNF/w2cU/6EqhvEKUHDnFZg==", + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@react-types/calendar/-/calendar-3.6.1.tgz", + "integrity": "sha512-EMbFJX/3gD5j+R0qZEGqK+wlhBxMSHhGP8GqP9XGbpuJPE3w9/M/PVWdh8FUdzf9srYxPOq5NgiGI1JUJvdZqw==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/checkbox": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.1.tgz", - "integrity": "sha512-0x/KQcipfNM9Nvy6UMwYG25roRLvsiqf0J3woTYylNNWzF+72XT0iI5FdJkE3w2wfa0obmSoeq4WcbFREQrH/A==", + "version": "3.9.2", + "resolved": "https://registry.npmjs.org/@react-types/checkbox/-/checkbox-3.9.2.tgz", + "integrity": "sha512-BruOLjr9s0BS2+G1Q2ZZ0ubnSTG54hZWr59lCHXaLxMdA/+KVsR6JVMQuYKsW0P8RDDlQXE/QGz3n9yB/Ara4A==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/color": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@react-types/color/-/color-3.0.2.tgz", - "integrity": "sha512-4k9c0l5SACwTtkHV0dQ0GrF0Kktk/NChkxtyu58BamyUQOsCe8sqny+uul2nPrqQvuVof/dkRjKhv/DVyyx2mw==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@react-types/color/-/color-3.0.3.tgz", + "integrity": "sha512-oIVdluqe4jYW6tHEHX80tuhhjCA93HElTzbzIGhDezgEbC/EEhWnoC3sGlkUTqIGdzhZG0T+HAkf3AZbCrXqZA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", - "@react-types/slider": "^3.7.8" + "@react-types/shared": "^3.28.0", + "@react-types/slider": "^3.7.9" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/combobox": { - "version": "3.13.2", - "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.13.2.tgz", - "integrity": "sha512-yl2yMcM5/v3lJiNZWjpAhQ9vRW6dD55CD4rYmO2K7XvzYJaFVT4WYI/AymPYD8RqomMp7coBmBHfHW0oupk8gg==", + "version": "3.13.3", + "resolved": "https://registry.npmjs.org/@react-types/combobox/-/combobox-3.13.3.tgz", + "integrity": "sha512-ASPLWuHke4XbnoOWUkNTguUa2cnpIsHPV0bcnfushC0yMSC4IEOlthstEbcdzjVUpWXSyaoI1R4POXmdIP53Nw==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/datepicker": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.10.0.tgz", - "integrity": "sha512-Att7y4NedNH1CogMDIX9URXgMLxGbZgnFCZ8oxgFAVndWzbh3TBcc4s7uoJDPvgRMAalq+z+SrlFFeoBeJmvvg==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-types/datepicker/-/datepicker-3.11.0.tgz", + "integrity": "sha512-GAYgPzqKvd1lR2sLYYMlUkNg2+QoM2uVUmpeQLP1SbYpDr1y8lG5cR54em1G4X/qY4+nCWGiwhRC2veP0D0kfA==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", - "@react-types/calendar": "^3.6.0", - "@react-types/overlays": "^3.8.12", - "@react-types/shared": "^3.27.0" + "@react-types/calendar": "^3.6.1", + "@react-types/overlays": "^3.8.13", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/dialog": { - "version": "3.5.15", - "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.15.tgz", - "integrity": "sha512-BX1+mV35Oa0aIlhu98OzJaSB7uiCWDPQbr0AkpFBajSSlESUoAjntN+4N+QJmj24z2v6UE9zxGQ85/U/0Le+bw==", + "version": "3.5.16", + "resolved": "https://registry.npmjs.org/@react-types/dialog/-/dialog-3.5.16.tgz", + "integrity": "sha512-2D16XjuW9fG3LkVIXu3RzUp3zcK2IZOWlAl+r5i0aLw2Q0QHyYMfGbmgvhxVeAhxhEj/57/ziSl/8rJ9pzmFnw==", "license": "Apache-2.0", "dependencies": { - "@react-types/overlays": "^3.8.12", - "@react-types/shared": "^3.27.0" + "@react-types/overlays": "^3.8.13", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/form": { - "version": "3.7.9", - "resolved": "https://registry.npmjs.org/@react-types/form/-/form-3.7.9.tgz", - "integrity": "sha512-+qGDrQFdIh8umU82zmnYJ0V2rLoGSQ3yApFT02URz//NWeTA7qo0Oab2veKvXUkcBb47oSvytZYmkExPikxIEg==", + "version": "3.7.10", + "resolved": "https://registry.npmjs.org/@react-types/form/-/form-3.7.10.tgz", + "integrity": "sha512-PPn1OH/QlQLPaoFqp9EMVSlNk41aiNLwPaMyRhzYvFBGLmtbuX+7JCcH2DgV1peq3KAuUKRDdI2M1iVdHYwMPw==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/grid": { - "version": "3.2.11", - "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.2.11.tgz", - "integrity": "sha512-Mww9nrasppvPbsBi+uUqFnf7ya8fXN0cTVzDNG+SveD8mhW+sbtuy+gPtEpnFD2Oyi8qLuObefzt4gdekJX2Yw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@react-types/grid/-/grid-3.3.0.tgz", + "integrity": "sha512-9IXgD5qXXxz+S9RK+zT8umuTCEcE4Yfdl0zUGyTCB8LVcPEeZuarLGXZY/12Rkbd8+r6MUIKTxMVD3Nq9X5Ksg==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/link": { - "version": "3.5.10", - "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.5.10.tgz", - "integrity": "sha512-IM2mbSpB0qP44Jh1Iqpevo7bQdZAr0iDyDi13OhsiUYJeWgPMHzGEnQqdBMkrfQeOTXLtZtUyOYLXE2v39bhzQ==", + "version": "3.5.11", + "resolved": "https://registry.npmjs.org/@react-types/link/-/link-3.5.11.tgz", + "integrity": "sha512-aX9sJod9msdQaOT0NUTYNaBKSkXGPazSPvUJ/Oe4/54T3sYkWeRqmgJ84RH55jdBzpbObBTg8qxKiPA26a1q9Q==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/listbox": { - "version": "3.5.4", - "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.5.4.tgz", - "integrity": "sha512-5otTes0zOwRZwNtqysPD/aW4qFJSxd5znjwoWTLnzDXXOBHXPyR83IJf8ITgvIE5C0y+EFadsWR/BBO3k9Pj7g==", + "version": "3.5.5", + "resolved": "https://registry.npmjs.org/@react-types/listbox/-/listbox-3.5.5.tgz", + "integrity": "sha512-6cUjbYZVa0X2UMsenQ50ZaAssTUfzX3D0Q0Wd5nNf4W7ntBroDg6aBfNQoPDZikPUy8u+Y3uc/xZQfv30si7NA==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/menu": { - "version": "3.9.14", - "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.14.tgz", - "integrity": "sha512-RJW/S8IPwbRuohJ/A9HJ7W8QaAY816tm7Nv6+H/TLXG76zu2AS5vEgq+0TcCAWvJJwUdLDpJWJMlo0iIoIBtcg==", + "version": "3.9.15", + "resolved": "https://registry.npmjs.org/@react-types/menu/-/menu-3.9.15.tgz", + "integrity": "sha512-vNEeGxKLYBJc3rwImnEhSVzeIrhUSSRYRk617oGZowX3NkWxnixFGBZNy0w8j0z8KeNz3wRM4xqInRord1mDbw==", "license": "Apache-2.0", "dependencies": { - "@react-types/overlays": "^3.8.12", - "@react-types/shared": "^3.27.0" + "@react-types/overlays": "^3.8.13", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/meter": { - "version": "3.4.6", - "resolved": "https://registry.npmjs.org/@react-types/meter/-/meter-3.4.6.tgz", - "integrity": "sha512-YczAht1VXy3s4fR6Dq0ibGsjulGHzS/A/K4tOruSNTL6EkYH9ktHX62Xk/OhCiKHxV315EbZ136WJaCeO4BgHw==", + "version": "3.4.7", + "resolved": "https://registry.npmjs.org/@react-types/meter/-/meter-3.4.7.tgz", + "integrity": "sha512-2GwNJ65+jd8lvrHMel/kiU8o7oPAOt1Sd+kezaeGBTbzKxUhCOAAlp9+zMha8vHQwmMvqcmfAHAqIBGaaCfh5w==", "license": "Apache-2.0", "dependencies": { - "@react-types/progress": "^3.5.9" + "@react-types/progress": "^3.5.10" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/numberfield": { - "version": "3.8.8", - "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.8.tgz", - "integrity": "sha512-825JPppxDaWh0Zxb0Q+wSslgRQYOtQPCAuhszPuWEy6d2F/M+hLR+qQqvQm9+LfMbdwiTg6QK5wxdWFCp2t7jw==", + "version": "3.8.9", + "resolved": "https://registry.npmjs.org/@react-types/numberfield/-/numberfield-3.8.9.tgz", + "integrity": "sha512-YqhawYUULiZnUba0/9Vaps8WAT2lto4V6CD/X7s048jiOrHiiIX03RDEAQuKOt1UYdzBJDHfSew9uGMyf/nC0g==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/overlays": { - "version": "3.8.12", - "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.12.tgz", - "integrity": "sha512-ZvR1t0YV7/6j+6OD8VozKYjvsXT92+C/2LOIKozy7YUNS5KI4MkXbRZzJvkuRECVZOmx8JXKTUzhghWJM/3QuQ==", + "version": "3.8.13", + "resolved": "https://registry.npmjs.org/@react-types/overlays/-/overlays-3.8.13.tgz", + "integrity": "sha512-xgT843KIh1otvYPQ6kCGTVUICiMF5UQ7SZUQZd4Zk3VtiFIunFVUvTvL03cpt0026UmY7tbv7vFrPKcT6xjsjw==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/progress": { - "version": "3.5.9", - "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.9.tgz", - "integrity": "sha512-zFxOzx3G8XUmHgpm037Hcayls5bqzXVa182E3iM7YWTmrjxJPKZ58XL0WWBgpTd+mJD7fTpnFdAZqSmFbtDOdA==", + "version": "3.5.10", + "resolved": "https://registry.npmjs.org/@react-types/progress/-/progress-3.5.10.tgz", + "integrity": "sha512-YDQExymdgORnSvXTtOW7SMhVOinlrD3bAlyCxO+hSAVaI1Ax38pW5dUFf6H85Jn7hLpjPQmQJvNsfsJ09rDFjQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/radio": { - "version": "3.8.6", - "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.8.6.tgz", - "integrity": "sha512-woTQYdRFjPzuml4qcIf+2zmycRuM5w3fDS5vk6CQmComVUjOFPtD28zX3Z9kc9lSNzaBQz9ONZfFqkZ1gqfICA==", + "version": "3.8.7", + "resolved": "https://registry.npmjs.org/@react-types/radio/-/radio-3.8.7.tgz", + "integrity": "sha512-K620hnDmSR7u9cZfwJIfoLvmZS1j9liD7nDXBm+N6aiq9E+8sw312sIEX5iR2TrQ4xovvJQZN7DWxPVr+1LfWw==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/searchfield": { - "version": "3.5.11", - "resolved": "https://registry.npmjs.org/@react-types/searchfield/-/searchfield-3.5.11.tgz", - "integrity": "sha512-MX8d9pgvxZxmgDwI0tiDaf6ijOY8XcRj0HM8Ocfttlk7PEFJK44p51WsUC+fPX1GmZni2JpFkx/haPOSLUECdw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@react-types/searchfield/-/searchfield-3.6.0.tgz", + "integrity": "sha512-eHQSP85j0hWhWEauPDdr+4kmLB3hUEWxU4ANNubalkupXKhGeRge5/ysHrWjEsLmoodfQ+RS6QIRLQRDsQF/4g==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0", - "@react-types/textfield": "^3.11.0" + "@react-types/shared": "^3.28.0", + "@react-types/textfield": "^3.12.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/select": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.9.tgz", - "integrity": "sha512-/hCd0o+ztn29FKCmVec+v7t4JpOzz56o+KrG7NDq2pcRWqUR9kNwCjrPhSbJIIEDm4ubtrfPu41ysIuDvRd2Bg==", + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/@react-types/select/-/select-3.9.10.tgz", + "integrity": "sha512-vvC5+cBSOu6J6lm74jhhP3Zvo1JO8m0FNX+Q95wapxrhs2aYYeMIgVuvNKeOuhVqzpBZxWmblBjCVNzCArZOaQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/shared": { - "version": "3.27.0", - "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.27.0.tgz", - "integrity": "sha512-gvznmLhi6JPEf0bsq7SwRYTHAKKq/wcmKqFez9sRdbED+SPMUmK5omfZ6w3EwUFQHbYUa4zPBYedQ7Knv70RMw==", + "version": "3.28.0", + "resolved": "https://registry.npmjs.org/@react-types/shared/-/shared-3.28.0.tgz", + "integrity": "sha512-9oMEYIDc3sk0G5rysnYvdNrkSg7B04yTKl50HHSZVbokeHpnU0yRmsDaWb9B/5RprcKj8XszEk5guBO8Sa/Q+Q==", "license": "Apache-2.0", "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/slider": { - "version": "3.7.8", - "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.8.tgz", - "integrity": "sha512-utW1o9KT70hqFwu1zqMtyEWmP0kSATk4yx+Fm/peSR4iZa+BasRqH83yzir5GKc8OfqfE1kmEsSlO98/k986+w==", + "version": "3.7.9", + "resolved": "https://registry.npmjs.org/@react-types/slider/-/slider-3.7.9.tgz", + "integrity": "sha512-MxCIVkrBSbN3AxIYW4hOpTcwPmIuY4841HF36sDLFWR3wx06z70IY3GFwV7Cbp814vhc84d4ABnPMwtE+AZRGQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/switch": { - "version": "3.5.8", - "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.8.tgz", - "integrity": "sha512-sL7jmh8llF8BxzY4HXkSU4bwU8YU6gx45P85D0AdYXgRHxU9Cp7BQPOMF4pJoQ8TTej05MymY5q7xvJVmxUTAQ==", + "version": "3.5.9", + "resolved": "https://registry.npmjs.org/@react-types/switch/-/switch-3.5.9.tgz", + "integrity": "sha512-7XIS5qycIKhdfcWfzl8n458/7tkZKCNfMfZmIREgozKOtTBirjmtRRsefom2hlFT8VIlG7COmY4btK3oEuEhnQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/table": { - "version": "3.10.4", - "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.10.4.tgz", - "integrity": "sha512-d0tLz/whxVteqr1rophtuuxqyknHHfTKeXrCgDjt8pAyd9U8GPDbfcFSfYPUhWdELRt7aLVyQw6VblZHioVEgQ==", + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/@react-types/table/-/table-3.11.0.tgz", + "integrity": "sha512-83cGyszL+sQ0uFNZvrnvDMg2KIxpe3l5U48IH9lvq2NC41Y4lGG0d7sBU6wgcc3vnQ/qhOE5LcbceGKEi2YSyw==", "license": "Apache-2.0", "dependencies": { - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0" + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/tabs": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.12.tgz", - "integrity": "sha512-E9O9G+wf9kaQ8UbDEDliW/oxYlJnh7oDCW1zaMOySwnG4yeCh7Wu02EOCvlQW4xvgn/i+lbEWgirf7L+yj5nRg==", + "version": "3.3.13", + "resolved": "https://registry.npmjs.org/@react-types/tabs/-/tabs-3.3.13.tgz", + "integrity": "sha512-jqaK2U+WKChAmYBMO8QxQlFaIM8zDRY9+ignA1HwIyRw7vli4Mycc4RcMxTPm8krvgo+zuVrped9QB+hsDjCsQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/textfield": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.11.0.tgz", - "integrity": "sha512-YORBgr6wlu2xfvr4MqjKFHGpj+z8LBzk14FbWDbYnnhGnv0I10pj+m2KeOHgDNFHrfkDdDOQmMIKn1UCqeUuEg==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@react-types/textfield/-/textfield-3.12.0.tgz", + "integrity": "sha512-B0vzCIBUbYWrlFk+odVXrSmPYwds9G+G+HiOO/sJr4eZ4RYiIqnFbZ7qiWhWXaou7vi71iXVqKQ8mxA6bJwPEQ==", "license": "Apache-2.0", "dependencies": { - "@react-types/shared": "^3.27.0" + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" } }, "node_modules/@react-types/tooltip": { - "version": "3.4.14", - "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.14.tgz", - "integrity": "sha512-J7CeYL2yPeKIasx1rPaEefyCHGEx2DOCx+7bM3XcKGmCxvNdVQLjimNJOt8IHlUA0nFJQOjmSW/mz9P0f2/kUw==", + "version": "3.4.15", + "resolved": "https://registry.npmjs.org/@react-types/tooltip/-/tooltip-3.4.15.tgz", + "integrity": "sha512-qiYwQLiEwYqrt/m8iQA8abl9k/9LrbtMNoEevL4jN4H0I5NrG55E78GYTkSzBBYmhBO4KnPVT0SfGM1tYaQx/A==", "license": "Apache-2.0", "dependencies": { - "@react-types/overlays": "^3.8.12", - "@react-types/shared": "^3.27.0" + "@react-types/overlays": "^3.8.13", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" @@ -13355,50 +13407,53 @@ } }, "node_modules/react-aria": { - "version": "3.37.0", - "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.37.0.tgz", - "integrity": "sha512-u3WUEMTcbQFaoHauHO3KhPaBYzEv1o42EdPcLAs05GBw9Q6Axlqwo73UFgMrsc2ElwLAZ4EKpSdWHLo1R5gfiw==", + "version": "3.38.0", + "resolved": "https://registry.npmjs.org/react-aria/-/react-aria-3.38.0.tgz", + "integrity": "sha512-OsnfXaYR/QaQSgky/95DiwNP5tuDX904Had71cbs48VNBYl7P/VpPQvdZMqrlYRbCupifkPaEEV/tThyRDHNbg==", "license": "Apache-2.0", "dependencies": { "@internationalized/string": "^3.2.5", - "@react-aria/breadcrumbs": "^3.5.20", - "@react-aria/button": "^3.11.1", - "@react-aria/calendar": "^3.7.0", - "@react-aria/checkbox": "^3.15.1", - "@react-aria/color": "^3.0.3", - "@react-aria/combobox": "^3.11.1", - "@react-aria/datepicker": "^3.13.0", - "@react-aria/dialog": "^3.5.21", - "@react-aria/disclosure": "^3.0.1", - "@react-aria/dnd": "^3.8.1", - "@react-aria/focus": "^3.19.1", - "@react-aria/gridlist": "^3.10.1", - "@react-aria/i18n": "^3.12.5", - "@react-aria/interactions": "^3.23.0", - "@react-aria/label": "^3.7.14", - "@react-aria/link": "^3.7.8", - "@react-aria/listbox": "^3.14.0", - "@react-aria/menu": "^3.17.0", - "@react-aria/meter": "^3.4.19", - "@react-aria/numberfield": "^3.11.10", - "@react-aria/overlays": "^3.25.0", - "@react-aria/progress": "^3.4.19", - "@react-aria/radio": "^3.10.11", - "@react-aria/searchfield": "^3.8.0", - "@react-aria/select": "^3.15.1", - "@react-aria/selection": "^3.22.0", - "@react-aria/separator": "^3.4.5", - "@react-aria/slider": "^3.7.15", + "@react-aria/breadcrumbs": "^3.5.21", + "@react-aria/button": "^3.12.0", + "@react-aria/calendar": "^3.7.1", + "@react-aria/checkbox": "^3.15.2", + "@react-aria/color": "^3.0.4", + "@react-aria/combobox": "^3.12.0", + "@react-aria/datepicker": "^3.14.0", + "@react-aria/dialog": "^3.5.22", + "@react-aria/disclosure": "^3.0.2", + "@react-aria/dnd": "^3.9.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/gridlist": "^3.11.0", + "@react-aria/i18n": "^3.12.6", + "@react-aria/interactions": "^3.24.0", + "@react-aria/label": "^3.7.15", + "@react-aria/landmark": "^3.0.0", + "@react-aria/link": "^3.7.9", + "@react-aria/listbox": "^3.14.1", + "@react-aria/menu": "^3.18.0", + "@react-aria/meter": "^3.4.20", + "@react-aria/numberfield": "^3.11.11", + "@react-aria/overlays": "^3.26.0", + "@react-aria/progress": "^3.4.20", + "@react-aria/radio": "^3.11.0", + "@react-aria/searchfield": "^3.8.1", + "@react-aria/select": "^3.15.2", + "@react-aria/selection": "^3.23.0", + "@react-aria/separator": "^3.4.6", + "@react-aria/slider": "^3.7.16", "@react-aria/ssr": "^3.9.7", - "@react-aria/switch": "^3.6.11", - "@react-aria/table": "^3.16.1", - "@react-aria/tabs": "^3.9.9", - "@react-aria/tag": "^3.4.9", - "@react-aria/textfield": "^3.16.0", - "@react-aria/tooltip": "^3.7.11", - "@react-aria/utils": "^3.27.0", - "@react-aria/visually-hidden": "^3.8.19", - "@react-types/shared": "^3.27.0" + "@react-aria/switch": "^3.7.0", + "@react-aria/table": "^3.17.0", + "@react-aria/tabs": "^3.10.0", + "@react-aria/tag": "^3.5.0", + "@react-aria/textfield": "^3.17.0", + "@react-aria/toast": "^3.0.0", + "@react-aria/tooltip": "^3.8.0", + "@react-aria/tree": "^3.0.0", + "@react-aria/utils": "^3.28.0", + "@react-aria/visually-hidden": "^3.8.20", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", @@ -13406,45 +13461,37 @@ } }, "node_modules/react-aria-components": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/react-aria-components/-/react-aria-components-1.6.0.tgz", - "integrity": "sha512-YfG9PUE7XrXtDDAqT4pLTGyYQaiHHTBFdAK/wNgGsypVnQSdzmyYlV3Ty8aHlZJI6hP9RWkbywvosXkU7KcPHg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/react-aria-components/-/react-aria-components-1.7.0.tgz", + "integrity": "sha512-WE3iZ4Ubkoh6GdqfXAC3f68Q4rvebmHXMtMJL57hJ/ZM+l1my3omigRzZczRwSQS2hOjPbhFGWrulq/rVwCITw==", "license": "Apache-2.0", "dependencies": { "@internationalized/date": "^3.7.0", "@internationalized/string": "^3.2.5", - "@react-aria/autocomplete": "3.0.0-alpha.37", - "@react-aria/collections": "3.0.0-alpha.7", - "@react-aria/color": "^3.0.3", - "@react-aria/disclosure": "^3.0.1", - "@react-aria/dnd": "^3.8.1", - "@react-aria/focus": "^3.19.1", - "@react-aria/interactions": "^3.23.0", + "@react-aria/autocomplete": "3.0.0-beta.0", + "@react-aria/collections": "3.0.0-beta.0", + "@react-aria/dnd": "^3.9.0", + "@react-aria/focus": "^3.20.0", + "@react-aria/interactions": "^3.24.0", "@react-aria/live-announcer": "^3.4.1", - "@react-aria/menu": "^3.17.0", - "@react-aria/toolbar": "3.0.0-beta.12", - "@react-aria/tree": "3.0.0-beta.3", - "@react-aria/utils": "^3.27.0", - "@react-aria/virtualizer": "^4.1.1", - "@react-stately/autocomplete": "3.0.0-alpha.0", - "@react-stately/color": "^3.8.2", - "@react-stately/disclosure": "^3.0.1", - "@react-stately/layout": "^4.1.1", - "@react-stately/menu": "^3.9.1", - "@react-stately/selection": "^3.19.0", - "@react-stately/table": "^3.13.1", + "@react-aria/toolbar": "3.0.0-beta.13", + "@react-aria/utils": "^3.28.0", + "@react-aria/virtualizer": "^4.1.2", + "@react-stately/autocomplete": "3.0.0-beta.0", + "@react-stately/layout": "^4.2.0", + "@react-stately/selection": "^3.20.0", + "@react-stately/table": "^3.14.0", "@react-stately/utils": "^3.10.5", - "@react-stately/virtualizer": "^4.2.1", - "@react-types/color": "^3.0.2", - "@react-types/form": "^3.7.9", - "@react-types/grid": "^3.2.11", - "@react-types/shared": "^3.27.0", - "@react-types/table": "^3.10.4", + "@react-stately/virtualizer": "^4.3.0", + "@react-types/form": "^3.7.10", + "@react-types/grid": "^3.3.0", + "@react-types/shared": "^3.28.0", + "@react-types/table": "^3.11.0", "@swc/helpers": "^0.5.0", "client-only": "^0.0.1", - "react-aria": "^3.37.0", - "react-stately": "^3.35.0", - "use-sync-external-store": "^1.2.0" + "react-aria": "^3.38.0", + "react-stately": "^3.36.0", + "use-sync-external-store": "^1.4.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1", @@ -13684,36 +13731,37 @@ } }, "node_modules/react-stately": { - "version": "3.35.0", - "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.35.0.tgz", - "integrity": "sha512-1BH21J/TOHpyZe7c+f1BU2bnRWaBDTjLH0WdBuzNfPOXu7RBG3ebPIRvqd7UkPaVfIcol2QJnxe8S0a314JWKA==", + "version": "3.36.0", + "resolved": "https://registry.npmjs.org/react-stately/-/react-stately-3.36.0.tgz", + "integrity": "sha512-xeoGuzZWUf6WjcmfT4x13R/BKVIF7DY/T7wGOfvpG4Pdy0p5eG6vyv1hJjk6ZxiOkwdeWKkRLXoypgZdlCavIQ==", "license": "Apache-2.0", "dependencies": { - "@react-stately/calendar": "^3.7.0", - "@react-stately/checkbox": "^3.6.11", - "@react-stately/collections": "^3.12.1", - "@react-stately/color": "^3.8.2", - "@react-stately/combobox": "^3.10.2", - "@react-stately/data": "^3.12.1", - "@react-stately/datepicker": "^3.12.0", - "@react-stately/disclosure": "^3.0.1", - "@react-stately/dnd": "^3.5.1", - "@react-stately/form": "^3.1.1", - "@react-stately/list": "^3.11.2", - "@react-stately/menu": "^3.9.1", - "@react-stately/numberfield": "^3.9.9", - "@react-stately/overlays": "^3.6.13", - "@react-stately/radio": "^3.10.10", - "@react-stately/searchfield": "^3.5.9", - "@react-stately/select": "^3.6.10", - "@react-stately/selection": "^3.19.0", - "@react-stately/slider": "^3.6.1", - "@react-stately/table": "^3.13.1", - "@react-stately/tabs": "^3.7.1", - "@react-stately/toggle": "^3.8.1", - "@react-stately/tooltip": "^3.5.1", - "@react-stately/tree": "^3.8.7", - "@react-types/shared": "^3.27.0" + "@react-stately/calendar": "^3.7.1", + "@react-stately/checkbox": "^3.6.12", + "@react-stately/collections": "^3.12.2", + "@react-stately/color": "^3.8.3", + "@react-stately/combobox": "^3.10.3", + "@react-stately/data": "^3.12.2", + "@react-stately/datepicker": "^3.13.0", + "@react-stately/disclosure": "^3.0.2", + "@react-stately/dnd": "^3.5.2", + "@react-stately/form": "^3.1.2", + "@react-stately/list": "^3.12.0", + "@react-stately/menu": "^3.9.2", + "@react-stately/numberfield": "^3.9.10", + "@react-stately/overlays": "^3.6.14", + "@react-stately/radio": "^3.10.11", + "@react-stately/searchfield": "^3.5.10", + "@react-stately/select": "^3.6.11", + "@react-stately/selection": "^3.20.0", + "@react-stately/slider": "^3.6.2", + "@react-stately/table": "^3.14.0", + "@react-stately/tabs": "^3.8.0", + "@react-stately/toast": "^3.0.0", + "@react-stately/toggle": "^3.8.2", + "@react-stately/tooltip": "^3.5.2", + "@react-stately/tree": "^3.8.8", + "@react-types/shared": "^3.28.0" }, "peerDependencies": { "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1" diff --git a/package.json b/package.json index e3a7e44e1..87b01cc71 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "openskill": "^4.1.0", "p-limit": "^6.2.0", "react": "^18.3.1", - "react-aria-components": "^1.6.0", + "react-aria-components": "^1.7.0", "react-charts": "^3.0.0-beta.57", "react-dom": "^18.3.1", "react-error-boundary": "^5.0.0",