diff --git a/apps/recnet/src/app/Headerbar.tsx b/apps/recnet/src/app/Headerbar.tsx index 7d09bc70..fd4c567c 100644 --- a/apps/recnet/src/app/Headerbar.tsx +++ b/apps/recnet/src/app/Headerbar.tsx @@ -17,6 +17,7 @@ import { useState, useRef, useEffect, useCallback } from "react"; import { useAuth } from "@recnet/recnet-web/app/AuthContext"; import { Avatar } from "@recnet/recnet-web/components/Avatar"; +import { useUserSettingDialogContext } from "@recnet/recnet-web/components/setting/UserSettingDialog"; import { UserRole } from "@recnet/recnet-web/constant"; import { logout, useGoogleLogin } from "@recnet/recnet-web/firebase/auth"; import { cn } from "@recnet/recnet-web/utils/cn"; @@ -29,6 +30,8 @@ export function UserDropdown({ user }: { user: User }) { await logout(); router.push("/"); }; + const { setOpen: setUserSettingDialogOpen } = useUserSettingDialogContext(); + return ( @@ -43,6 +46,9 @@ export function UserDropdown({ user }: { user: User }) { Profile + setUserSettingDialogOpen(true)}> + Settings + {user.role && user.role === UserRole.ADMIN ? ( Admin Panel diff --git a/apps/recnet/src/app/[handle]/Profile.tsx b/apps/recnet/src/app/[handle]/Profile.tsx index f33d8b93..5d2088a8 100644 --- a/apps/recnet/src/app/[handle]/Profile.tsx +++ b/apps/recnet/src/app/[handle]/Profile.tsx @@ -11,11 +11,10 @@ import { Avatar } from "@recnet/recnet-web/components/Avatar"; import { FollowButton } from "@recnet/recnet-web/components/FollowButton"; import { RecNetLink } from "@recnet/recnet-web/components/Link"; import { Skeleton, SkeletonText } from "@recnet/recnet-web/components/Skeleton"; +import { useUserSettingDialogContext } from "@recnet/recnet-web/components/setting/UserSettingDialog"; import { cn } from "@recnet/recnet-web/utils/cn"; import { interleaveWithValue } from "@recnet/recnet-web/utils/interleaveWithValue"; -import { UserSettingDialog } from "./UserSettingDialog"; - function StatDivider() { return
; } @@ -28,6 +27,7 @@ export function Profile(props: { handle: string }) { }); const { user: me } = useAuth(); const isMe = !!me && !!data?.user && me.handle === data.user.handle; + const { setOpen: setUserSettingDialogOpen } = useUserSettingDialogContext(); const userUrl = useMemo( () => (data?.user?.url ? new URL(data.user.url) : null), @@ -184,7 +184,15 @@ export function Profile(props: { handle: string }) { {isMe ? ( - + ) : ( )} @@ -196,7 +204,15 @@ export function Profile(props: { handle: string }) {
{userInfo}
{isMe ? ( - + ) : ( )} diff --git a/apps/recnet/src/app/layout.tsx b/apps/recnet/src/app/layout.tsx index bfae990e..40e25e6b 100644 --- a/apps/recnet/src/app/layout.tsx +++ b/apps/recnet/src/app/layout.tsx @@ -7,6 +7,7 @@ import { Toaster } from "sonner"; import { Footer } from "@recnet/recnet-web/app/Footer"; import { Headerbar } from "@recnet/recnet-web/app/Headerbar"; import { clientEnv } from "@recnet/recnet-web/clientEnv"; +import { UserSettingDialogProvider } from "@recnet/recnet-web/components/setting/UserSettingDialog"; import { getUserServerSide } from "@recnet/recnet-web/utils/getUserServerSide"; import { ApiErrorBoundary } from "./ApiErrorBoundary"; @@ -43,15 +44,17 @@ export default async function RootLayout({ - - - -
- {children} -
-
-
- + + + + +
+ {children} +
+
+
+ + diff --git a/apps/recnet/src/components/setting/UserSettingDialog.tsx b/apps/recnet/src/components/setting/UserSettingDialog.tsx new file mode 100644 index 00000000..45063a94 --- /dev/null +++ b/apps/recnet/src/components/setting/UserSettingDialog.tsx @@ -0,0 +1,127 @@ +"use client"; + +import { + PersonIcon, + Cross1Icon, + EnvelopeClosedIcon, +} from "@radix-ui/react-icons"; +import { Dialog, Button, Text } from "@radix-ui/themes"; +import { Settings } from "lucide-react"; +import React, { useMemo, useState, createContext, useContext } from "react"; + +import { useAuth } from "@recnet/recnet-web/app/AuthContext"; +import { cn } from "@recnet/recnet-web/utils/cn"; + +import { AccountSetting } from "./account/AccountSetting"; +import { ProfileEditForm } from "./profile/ProfileEditForm"; +import { SubscriptionSetting } from "./subscription/SubscriptionSetting"; + +const tabs = { + PROFILE: { + label: "Profile", + icon: , + component: ProfileEditForm, + }, + ACCOUNT: { + label: "Account", + icon: , + component: AccountSetting, + }, + SUBSCRIPTION: { + label: "Subscription", + icon: , + component: SubscriptionSetting, + }, +} as const; +type TabKey = keyof typeof tabs; + +const UserSettingDialogContext = createContext<{ + open: boolean; + setOpen: (open: boolean) => void; + activeTab: TabKey; + setActiveTab: (tab: TabKey) => void; +} | null>(null); + +export function useUserSettingDialogContext() { + const context = useContext(UserSettingDialogContext); + if (!context) { + throw new Error( + "useUserSettingDialog must be used within a UserSettingDialogProvider" + ); + } + return context; +} + +interface UserSettingDialogProps { + children: React.ReactNode; +} + +export function UserSettingDialogProvider(props: UserSettingDialogProps) { + const { children } = props; + const { user } = useAuth(); + const [open, setOpen] = useState(false); + const [activeTab, setActiveTab] = useState("PROFILE"); + + const TabComponent = useMemo(() => tabs[activeTab].component, [activeTab]); + + if (!user) { + return children; + } + + return ( + + + + + + +
+
+ {Object.entries(tabs).map(([key, { label }]) => ( +
setActiveTab(key as TabKey)} + > + {tabs[key as TabKey].icon} + + {label} + +
+ ))} +
+
+ +
+
+
+
+ {children} +
+ ); +} diff --git a/apps/recnet/src/components/setting/account/AccountSetting.tsx b/apps/recnet/src/components/setting/account/AccountSetting.tsx new file mode 100644 index 00000000..320514d3 --- /dev/null +++ b/apps/recnet/src/components/setting/account/AccountSetting.tsx @@ -0,0 +1,49 @@ +"use client"; + +import { Dialog, Button, Text } from "@radix-ui/themes"; +import { useRouter } from "next/navigation"; + +import { trpc } from "@recnet/recnet-web/app/_trpc/client"; +import { DoubleConfirmButton } from "@recnet/recnet-web/components/DoubleConfirmButton"; +import { logout } from "@recnet/recnet-web/firebase/auth"; + +export function AccountSetting() { + const deactivateMutation = trpc.deactivate.useMutation(); + const router = useRouter(); + + return ( +
+ Account Setting + + Make changes to account settings. + + + + Deactivate Account + + + { + "Your account will be deactivated and you will be logged out. You can reactivate your account by logging in again." + } + { + " While your account is deactivated, your profile will be hidden from other users. You will not receive any weekly digest emails." + } + +
+ { + await deactivateMutation.mutateAsync(); + await logout(); + router.replace("/"); + }} + title="Deactivate Account" + description="Are you sure you want to deactivate your account?" + > + + +
+
+ ); +} diff --git a/apps/recnet/src/app/[handle]/UserSettingDialog.tsx b/apps/recnet/src/components/setting/profile/ProfileEditForm.tsx similarity index 63% rename from apps/recnet/src/app/[handle]/UserSettingDialog.tsx rename to apps/recnet/src/components/setting/profile/ProfileEditForm.tsx index 06e00caf..fe7a5f02 100644 --- a/apps/recnet/src/app/[handle]/UserSettingDialog.tsx +++ b/apps/recnet/src/components/setting/profile/ProfileEditForm.tsx @@ -1,7 +1,6 @@ "use client"; import { zodResolver } from "@hookform/resolvers/zod"; -import { PersonIcon, Cross1Icon } from "@radix-ui/react-icons"; import { Dialog, Button, @@ -11,27 +10,18 @@ import { TextArea, } from "@radix-ui/themes"; import { TRPCClientError } from "@trpc/client"; -import { Settings } from "lucide-react"; -import { useRouter } from "next/navigation"; -import React, { useMemo, useState } from "react"; +import { useRouter, usePathname } from "next/navigation"; import { useForm, useFormState } from "react-hook-form"; import { toast } from "sonner"; import * as z from "zod"; import { useAuth } from "@recnet/recnet-web/app/AuthContext"; import { trpc } from "@recnet/recnet-web/app/_trpc/client"; -import { DoubleConfirmButton } from "@recnet/recnet-web/components/DoubleConfirmButton"; import { RecNetLink } from "@recnet/recnet-web/components/Link"; import { ErrorMessages } from "@recnet/recnet-web/constant"; -import { logout } from "@recnet/recnet-web/firebase/auth"; import { cn } from "@recnet/recnet-web/utils/cn"; -import { User } from "@recnet/recnet-api-model"; - -interface TabProps { - onSuccess?: (user: User) => void; - setOpen: (open: boolean) => void; -} +import { useUserSettingDialogContext } from "../UserSettingDialog"; const HandleBlacklist = [ "about", @@ -44,7 +34,7 @@ const HandleBlacklist = [ "user", ]; -const EditUserProfileSchema = z.object({ +const ProfileEditSchema = z.object({ displayName: z.string().min(1, "Name cannot be blank."), handle: z .string() @@ -76,13 +66,17 @@ const EditUserProfileSchema = z.object({ openReviewUserName: z.string().nullable(), }); -function EditProfileForm(props: TabProps) { - const { onSuccess = () => {}, setOpen } = props; +export function ProfileEditForm() { + const utils = trpc.useUtils(); + const router = useRouter(); + const { setOpen } = useUserSettingDialogContext(); const { user, revalidateUser } = useAuth(); + const oldHandle = user?.handle; + const pathname = usePathname(); const { register, handleSubmit, formState, setError, control, watch } = useForm({ - resolver: zodResolver(EditUserProfileSchema), + resolver: zodResolver(ProfileEditSchema), defaultValues: { displayName: user?.displayName ?? null, handle: user?.handle ?? null, @@ -104,7 +98,7 @@ function EditProfileForm(props: TabProps) { className="w-full" onSubmit={handleSubmit(async (data, e) => { e?.preventDefault(); - const res = EditUserProfileSchema.safeParse(data); + const res = ProfileEditSchema.safeParse(data); if (!res.success || !user?.id) { // should not happen, just in case and for typescript to narrow down type console.error("Invalid form data."); @@ -138,15 +132,25 @@ function EditProfileForm(props: TabProps) { toast.success("Profile updated successfully!"); // revaildate user profile revalidateUser(); - // fire onSuccess callback - onSuccess(updatedData.user); + // revalidate cache for user profile or redirect to new user profile if handle changed + const updatedUser = updatedData.user; + if (updatedUser.handle !== oldHandle) { + // if user currently at their profile page, + // and if user change user handle, redirect to new user profile + if (pathname === `/${oldHandle}`) { + router.replace(`/${updatedUser.handle}`); + } + } else { + utils.getUserByHandle.invalidate({ handle: oldHandle }); + } + setOpen(false); } catch (error) { console.log(error); } })} > Edit profile - + Make changes to your profile. @@ -301,11 +305,6 @@ function EditProfileForm(props: TabProps) { - - - - -
- - ); -} - -const tabs = { - PROFILE: { - label: "Profile", - icon: , - component: EditProfileForm, - }, - ACCOUNT: { - label: "Account", - icon: , - component: AccountSetting, - }, -} as const; -type TabKey = keyof typeof tabs; - -export function UserSettingDialog(props: { handle: string }) { - const { handle } = props; - const utils = trpc.useUtils(); - const router = useRouter(); - const [open, setOpen] = useState(false); - const { user } = useAuth(); - const oldHandle = user?.handle; - - const tabsProps = useMemo(() => { - return { - ACCOUNT: { - onSuccess: (updatedUser: User) => { - // redirect to home page after deactivating account - router.replace("/"); - }, - setOpen: setOpen, - }, - PROFILE: { - onSuccess: (updatedUser: User) => { - if (updatedUser.handle !== oldHandle) { - // if user change user handle, redirect to new user profile - router.replace(`/${updatedUser.handle}`); - } else { - utils.getUserByHandle.invalidate({ handle: handle }); - setOpen(false); - } - }, - setOpen: setOpen, - }, - }; - }, [handle, oldHandle, router, utils]); - const [activeTab, setActiveTab] = useState("PROFILE"); - - const TabComponent = useMemo(() => tabs[activeTab].component, [activeTab]); - - return ( - - - - - - - - -
-
- {Object.entries(tabs).map(([key, { label }]) => ( -
setActiveTab(key as TabKey)} - > - {tabs[key as TabKey].icon} - - {label} - -
- ))} -
-
- -
-
-
-
- ); -} diff --git a/apps/recnet/src/components/setting/subscription/SubscriptionSetting.tsx b/apps/recnet/src/components/setting/subscription/SubscriptionSetting.tsx new file mode 100644 index 00000000..6293d31b --- /dev/null +++ b/apps/recnet/src/components/setting/subscription/SubscriptionSetting.tsx @@ -0,0 +1,237 @@ +"use client"; + +import { zodResolver } from "@hookform/resolvers/zod"; +import * as Accordion from "@radix-ui/react-accordion"; +import { + Card, + Dialog, + Flex, + Text, + CheckboxCards, + Badge, + Button, +} from "@radix-ui/themes"; +import { ChevronDown } from "lucide-react"; +import { useState } from "react"; +import { Controller, useForm, useFormState } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; + +import { trpc } from "@recnet/recnet-web/app/_trpc/client"; +import { LoadingBox } from "@recnet/recnet-web/components/LoadingBox"; +import { cn } from "@recnet/recnet-web/utils/cn"; + +import { + SubscriptionChannel, + SubscriptionType, + subscriptionTypeSchema, + subscriptionChannelSchema, +} from "@recnet/recnet-api-model"; + +const transformSubscriptionEnum = (subType: string): string => { + return subType + .replace(/_/g, " ") + .split(" ") + .map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) + .join(" "); +}; + +const subscriptionChannelEditSchema = z.object({ + channels: subscriptionChannelSchema.array(), +}); + +function SubscriptionTypeCard(props: { + type: SubscriptionType; + selectedChannels: SubscriptionChannel[]; +}) { + const { type, selectedChannels } = props; + const title = transformSubscriptionEnum(type); + const isActivated = selectedChannels.length > 0; + const [isSubmitting, setIsSubmitting] = useState(false); + const utils = trpc.useUtils(); + + const { handleSubmit, control, reset, setError, formState } = useForm({ + resolver: zodResolver(subscriptionChannelEditSchema), + defaultValues: { + channels: selectedChannels, + }, + mode: "onTouched", + }); + const { isDirty } = useFormState({ control }); + + const updateSubscriptionMutation = trpc.updateSubscription.useMutation(); + + return ( + + + + + {title} + + Channels:{" "} + {selectedChannels + .map((channel) => channel.toLowerCase()) + .join(", ")} + + + + + + +
{ + setIsSubmitting(true); + // handle special case for WEEKLY DIGEST + // for weekly digest, at least one channel must be selected + // if no, then show error message + if (type === "WEEKLY_DIGEST" && data.channels.length === 0) { + setError("channels", { + type: "manual", + message: + "At least one channel must be selected for Weekly Digest", + }); + setIsSubmitting(false); + return; + } + await updateSubscriptionMutation.mutateAsync({ + type, + channels: data.channels, + }); + utils.getSubscriptions.invalidate(); + toast.success("Subscription updated successfully"); + setIsSubmitting(false); + }, + (e) => { + console.log(e); + } + )} + > +
+ + Distribution Channels: + + { + return ( +
+ field.onChange(value)} + > + {subscriptionChannelSchema.options.map((channel) => { + return ( + + {channel.charAt(0).toUpperCase() + + channel.slice(1).toLowerCase()} + + ); + })} + + {formState.errors.channels && ( + + {`${formState.errors.channels.message}`} + + )} +
+ ); + }} + /> +
+ + + BETA + + + Distribute by Slack is currently in beta version. Only people in + Cornell-NLP slack workspace can use this feature. And the email + account of the slack account must match the RecNet account. + + + + + + +
+
+
+ ); +} + +export function SubscriptionSetting() { + const { data, isFetching } = trpc.getSubscriptions.useQuery(); + const [openedType, setOpenType] = useState( + undefined + ); + + return ( +
+ Subscription Setting + + Customize the subscription types and channels that best fits your needs. + + + + Subscriptions + + {isFetching ? ( + + ) : ( + setOpenType(value as SubscriptionType)} + > + {subscriptionTypeSchema.options.map((subType) => { + const subscriptionTypeObj = (data?.subscriptions ?? []).find( + (sub) => sub.type === subType + ); + return ( + + ); + })} + + )} +
+ ); +} diff --git a/apps/recnet/src/server/index.ts b/apps/recnet/src/server/index.ts index 7bdc8e9d..916e2e11 100644 --- a/apps/recnet/src/server/index.ts +++ b/apps/recnet/src/server/index.ts @@ -3,6 +3,7 @@ import { articleRouter } from "./routers/article"; import { inviteCodeRouter } from "./routers/inviteCode"; import { publicRouter } from "./routers/public"; import { recRouter } from "./routers/rec"; +import { subscriptionRouter } from "./routers/subscription"; import { userRouter } from "./routers/user"; import { mergeRouters } from "./trpc"; @@ -12,7 +13,8 @@ export const appRouter = mergeRouters( recRouter, inviteCodeRouter, articleRouter, - announcementRouter + announcementRouter, + subscriptionRouter ); export type AppRouter = typeof appRouter; diff --git a/apps/recnet/src/server/routers/subscription.ts b/apps/recnet/src/server/routers/subscription.ts new file mode 100644 index 00000000..6e7da4b6 --- /dev/null +++ b/apps/recnet/src/server/routers/subscription.ts @@ -0,0 +1,30 @@ +import { + getUsersSubscriptionsResponseSchema, + postUsersSubscriptionsRequestSchema, + postUsersSubscriptionsResponseSchema, +} from "@recnet/recnet-api-model"; + +import { checkRecnetJWTProcedure } from "./middleware"; + +import { router } from "../trpc"; + +export const subscriptionRouter = router({ + getSubscriptions: checkRecnetJWTProcedure + .output(getUsersSubscriptionsResponseSchema) + .query(async (opts) => { + const { recnetApi } = opts.ctx; + const { data } = await recnetApi.get("/users/subscriptions"); + return getUsersSubscriptionsResponseSchema.parse(data); + }), + updateSubscription: checkRecnetJWTProcedure + .input(postUsersSubscriptionsRequestSchema) + .output(postUsersSubscriptionsResponseSchema) + .mutation(async (opts) => { + const subscription = opts.input; + const { recnetApi } = opts.ctx; + const { data } = await recnetApi.post("/users/subscriptions", { + ...postUsersSubscriptionsRequestSchema.parse(subscription), + }); + return postUsersSubscriptionsResponseSchema.parse(data); + }), +}); diff --git a/libs/recnet-api-model/src/lib/api/user.ts b/libs/recnet-api-model/src/lib/api/user.ts index 1d8b63c3..65059e86 100644 --- a/libs/recnet-api-model/src/lib/api/user.ts +++ b/libs/recnet-api-model/src/lib/api/user.ts @@ -123,3 +123,10 @@ export const postUsersSubscriptionsRequestSchema = subscriptionSchema; export type PostUsersSubscriptionsRequest = z.infer< typeof postUsersSubscriptionsRequestSchema >; + +export const postUsersSubscriptionsResponseSchema = z.object({ + subscription: subscriptionSchema, +}); +export type PostUsersSubscriptionsResponse = z.infer< + typeof postUsersSubscriptionsResponseSchema +>; diff --git a/libs/recnet-api-model/src/lib/model.ts b/libs/recnet-api-model/src/lib/model.ts index 9ac43a49..c97558a6 100644 --- a/libs/recnet-api-model/src/lib/model.ts +++ b/libs/recnet-api-model/src/lib/model.ts @@ -20,6 +20,11 @@ export const reactionTypeSchema = z.enum([ ]); export type ReactionType = z.infer; +export const subscriptionTypeSchema = z.enum(["WEEKLY_DIGEST"]); +export type SubscriptionType = z.infer; +export const subscriptionChannelSchema = z.enum(["EMAIL", "SLACK"]); +export type SubscriptionChannel = z.infer; + export const userPreviewSchema = z.object({ id: z.string(), handle: z.string(), @@ -108,7 +113,7 @@ export const digitalLibrarySchema = z.object({ export type DigitalLibrary = z.infer; export const subscriptionSchema = z.object({ - type: z.enum(["WEEKLY_DIGEST"]), - channels: z.array(z.enum(["EMAIL", "SLACK"])), + type: subscriptionTypeSchema, + channels: z.array(subscriptionChannelSchema), }); export type Subscription = z.infer; diff --git a/package.json b/package.json index 39b0a787..1bd91729 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "@next/third-parties": "^14.1.0", "@octokit/core": "^6.1.2", "@prisma/client": "5.12.1", + "@radix-ui/react-accordion": "^1.2.1", "@radix-ui/react-icons": "^1.3.0", "@radix-ui/react-select": "^2.0.0", "@radix-ui/themes": "^3.0.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ffbf62dc..cb488afd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1,9 +1,5 @@ lockfileVersion: '6.0' -settings: - autoInstallPeers: true - excludeLinksFromLockfile: false - dependencies: '@actions/core': specifier: ^1.10.1 @@ -47,6 +43,9 @@ dependencies: '@prisma/client': specifier: 5.12.1 version: 5.12.1(prisma@5.12.1) + '@radix-ui/react-accordion': + specifier: ^1.2.1 + version: 1.2.1(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) '@radix-ui/react-icons': specifier: ^1.3.0 version: 1.3.0(react@18.2.0) @@ -1920,7 +1919,6 @@ packages: cpu: [ppc64] os: [aix] requiresBuild: true - dev: false optional: true /@esbuild/aix-ppc64@0.19.12: @@ -1938,7 +1936,6 @@ packages: cpu: [arm64] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/android-arm64@0.19.12: @@ -1956,7 +1953,6 @@ packages: cpu: [arm] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/android-arm@0.19.12: @@ -1974,7 +1970,6 @@ packages: cpu: [x64] os: [android] requiresBuild: true - dev: false optional: true /@esbuild/android-x64@0.19.12: @@ -1992,7 +1987,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: false optional: true /@esbuild/darwin-arm64@0.19.12: @@ -2010,7 +2004,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: false optional: true /@esbuild/darwin-x64@0.19.12: @@ -2028,7 +2021,6 @@ packages: cpu: [arm64] os: [freebsd] requiresBuild: true - dev: false optional: true /@esbuild/freebsd-arm64@0.19.12: @@ -2046,7 +2038,6 @@ packages: cpu: [x64] os: [freebsd] requiresBuild: true - dev: false optional: true /@esbuild/freebsd-x64@0.19.12: @@ -2064,7 +2055,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-arm64@0.19.12: @@ -2082,7 +2072,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-arm@0.19.12: @@ -2100,7 +2089,6 @@ packages: cpu: [ia32] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-ia32@0.19.12: @@ -2118,7 +2106,6 @@ packages: cpu: [loong64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-loong64@0.19.12: @@ -2136,7 +2123,6 @@ packages: cpu: [mips64el] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-mips64el@0.19.12: @@ -2154,7 +2140,6 @@ packages: cpu: [ppc64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-ppc64@0.19.12: @@ -2172,7 +2157,6 @@ packages: cpu: [riscv64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-riscv64@0.19.12: @@ -2190,7 +2174,6 @@ packages: cpu: [s390x] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-s390x@0.19.12: @@ -2208,7 +2191,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@esbuild/linux-x64@0.19.12: @@ -2226,7 +2208,6 @@ packages: cpu: [x64] os: [netbsd] requiresBuild: true - dev: false optional: true /@esbuild/netbsd-x64@0.19.12: @@ -2244,7 +2225,6 @@ packages: cpu: [x64] os: [openbsd] requiresBuild: true - dev: false optional: true /@esbuild/openbsd-x64@0.19.12: @@ -2262,7 +2242,6 @@ packages: cpu: [x64] os: [sunos] requiresBuild: true - dev: false optional: true /@esbuild/sunos-x64@0.19.12: @@ -2280,7 +2259,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true /@esbuild/win32-arm64@0.19.12: @@ -2298,7 +2276,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true /@esbuild/win32-ia32@0.19.12: @@ -2316,7 +2293,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true /@esbuild/win32-x64@0.19.12: @@ -4616,11 +4592,11 @@ packages: style-loader: 3.3.4(webpack@5.91.0) stylus: 0.59.0 stylus-loader: 7.1.3(stylus@0.59.0)(webpack@5.91.0) - terser-webpack-plugin: 5.3.10(@swc/core@1.3.85)(webpack@5.91.0) + terser-webpack-plugin: 5.3.10(@swc/core@1.3.101)(esbuild@0.19.11)(webpack@5.91.0) ts-loader: 9.5.1(typescript@5.4.5)(webpack@5.91.0) tsconfig-paths-webpack-plugin: 4.0.0 tslib: 2.6.2 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-dev-server: 4.15.2(webpack-cli@5.1.4)(webpack@5.91.0) webpack-node-externals: 3.0.0 webpack-subresource-integrity: 5.1.0(webpack@5.91.0) @@ -4879,6 +4855,10 @@ packages: '@babel/runtime': 7.24.4 dev: false + /@radix-ui/primitive@1.1.0: + resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==} + dev: false + /@radix-ui/react-accessible-icon@1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-duVGKeWPSUILr/MdlPxV+GeULTc2rS1aihGdQ3N2qCUPMgxYLxvAsHJM3mCVLF8d5eK+ympmB22mb1F3a5biNw==} peerDependencies: @@ -4900,6 +4880,34 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-accordion@1.2.1(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-bg/l7l5QzUjgsh8kjwDFommzAshnUsuVMV5NM56QVCm+7ZckYdd9P/ExR8xG/Oup0OajVxNLaHJ1tb8mXk+nzQ==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-collapsible': 1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-context': 1.1.1(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-direction': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-id': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-alert-dialog@1.0.5(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-OrVIOcZL0tl6xibeuGt5/+UxoT2N27KCFOPjFyfXMnchxSHZ/OW7cCX2nGlIYJrbHK/fczPcFzAwvNBB6XBNMA==} peerDependencies: @@ -5048,6 +5056,33 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-collapsible@1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-1///SnrfQHJEofLokyczERxQbWfCGQlQ2XsCZMucVs6it+lq9iw4vXy+uDn1edlb58cOZOWSldnfPAYcT4O/Yg==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/primitive': 1.1.0 + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-context': 1.1.1(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-id': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-presence': 1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-collection@1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA==} peerDependencies: @@ -5072,6 +5107,29 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-collection@1.1.0(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-context': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0) + '@radix-ui/react-slot': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-compose-refs@1.0.1(@types/react@18.2.67)(react@18.2.0): resolution: {integrity: sha512-fDSBgd44FKHa1FRMU59qBMPFcl2PZE+2nmqunj+BWFyYYjnhIDWL2ItDs3rrbJDQOtzt5nIebLCQc4QRfz6LJw==} peerDependencies: @@ -5086,6 +5144,19 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-compose-refs@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-context-menu@2.1.5(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-R5XaDj06Xul1KGb+WP8qiOh7tKJNz2durpLBXAGZjSVtctcRFCuEvy2gtMwRJGePwQQE5nV77gs4FwRi8T+r2g==} peerDependencies: @@ -5126,6 +5197,32 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-context@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + + /@radix-ui/react-context@1.1.1(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-dialog@1.0.5(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q==} peerDependencies: @@ -5174,6 +5271,19 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-direction@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-dismissable-layer@1.0.4(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-7UpBa/RKMoHJYjie1gkF1DlK8l1fdU/VKDpoS3rCCo8YBJR294GwcEHyxHw72yvphJ7ld0AXEcSLAzY2F/WyCg==} peerDependencies: @@ -5389,6 +5499,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-id@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-label@2.0.2(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==} peerDependencies: @@ -5676,6 +5800,27 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-presence@1.1.1(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-primitive@1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-yi58uVyoAcK/Nq1inRY56ZSjKypBNKTa/1mcL8qdl6oJeEaDbOldlzrGn7P6Q3Id5d+SYNGc5AJgc4vGhjs5+g==} peerDependencies: @@ -5697,6 +5842,26 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false + /@radix-ui/react-primitive@2.0.0(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==} + peerDependencies: + '@types/react': '*' + '@types/react-dom': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + dependencies: + '@radix-ui/react-slot': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + '@types/react-dom': 18.2.22 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + dev: false + /@radix-ui/react-progress@1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-5G6Om/tYSxjSeEdrb1VfKkfZfn/1IlPWd731h2RfPuSbIfNUgfqAwbKfJCg/PP6nuUCTrYzalwHSpSinoWoCag==} peerDependencies: @@ -5894,6 +6059,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-slot@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-switch@1.0.3(@types/react-dom@18.2.22)(@types/react@18.2.67)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==} peerDependencies: @@ -6077,6 +6256,19 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-callback-ref@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-use-controllable-state@1.0.1(@types/react@18.2.67)(react@18.2.0): resolution: {integrity: sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA==} peerDependencies: @@ -6092,6 +6284,20 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-controllable-state@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.2.67)(react@18.2.0) + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-use-escape-keydown@1.0.3(@types/react@18.2.67)(react@18.2.0): resolution: {integrity: sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg==} peerDependencies: @@ -6121,6 +6327,19 @@ packages: react: 18.2.0 dev: false + /@radix-ui/react-use-layout-effect@1.1.0(@types/react@18.2.67)(react@18.2.0): + resolution: {integrity: sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==} + peerDependencies: + '@types/react': '*' + react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + dependencies: + '@types/react': 18.2.67 + react: 18.2.0 + dev: false + /@radix-ui/react-use-previous@1.0.1(@types/react@18.2.67)(react@18.2.0): resolution: {integrity: sha512-cV5La9DPwiQ7S0gf/0qiD6YgNqM5Fk97Kdrlc5yBcrF3jyEZQwm7vYFqMo4IfeHgJXsRaMvLABFtd0OVEmZhDw==} peerDependencies: @@ -6897,7 +7116,6 @@ packages: cpu: [arm64] os: [darwin] requiresBuild: true - dev: false optional: true /@swc/core-darwin-arm64@1.3.85: @@ -6914,7 +7132,6 @@ packages: cpu: [x64] os: [darwin] requiresBuild: true - dev: false optional: true /@swc/core-darwin-x64@1.3.85: @@ -6931,7 +7148,6 @@ packages: cpu: [arm] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-arm-gnueabihf@1.3.85: @@ -6948,7 +7164,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-arm64-gnu@1.3.85: @@ -6965,7 +7180,6 @@ packages: cpu: [arm64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-arm64-musl@1.3.85: @@ -6982,7 +7196,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-x64-gnu@1.3.85: @@ -6999,7 +7212,6 @@ packages: cpu: [x64] os: [linux] requiresBuild: true - dev: false optional: true /@swc/core-linux-x64-musl@1.3.85: @@ -7016,7 +7228,6 @@ packages: cpu: [arm64] os: [win32] requiresBuild: true - dev: false optional: true /@swc/core-win32-arm64-msvc@1.3.85: @@ -7033,7 +7244,6 @@ packages: cpu: [ia32] os: [win32] requiresBuild: true - dev: false optional: true /@swc/core-win32-ia32-msvc@1.3.85: @@ -7050,7 +7260,6 @@ packages: cpu: [x64] os: [win32] requiresBuild: true - dev: false optional: true /@swc/core-win32-x64-msvc@1.3.85: @@ -7085,7 +7294,6 @@ packages: '@swc/core-win32-arm64-msvc': 1.3.101 '@swc/core-win32-ia32-msvc': 1.3.101 '@swc/core-win32-x64-msvc': 1.3.101 - dev: false /@swc/core@1.3.85(@swc/helpers@0.5.2): resolution: {integrity: sha512-qnoxp+2O0GtvRdYnXgR1v8J7iymGGYpx6f6yCK9KxipOZOjrlKILFANYlghQxZyPUfXwK++TFxfSlX4r9wK+kg==} @@ -8325,7 +8533,7 @@ packages: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.91.0) /@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.91.0): @@ -8335,7 +8543,7 @@ packages: webpack: 5.x.x webpack-cli: 5.x.x dependencies: - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.91.0) /@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack@5.91.0): @@ -8349,7 +8557,7 @@ packages: webpack-dev-server: optional: true dependencies: - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.91.0) /@xtuc/ieee754@1.2.0: @@ -8867,7 +9075,7 @@ packages: '@babel/core': 7.24.4 find-cache-dir: 4.0.0 schema-utils: 4.2.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /babel-plugin-const-enum@1.2.0(@babel/core@7.24.4): @@ -9897,7 +10105,7 @@ packages: normalize-path: 3.0.0 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /core-js-compat@3.36.1: @@ -10039,7 +10247,7 @@ packages: postcss-modules-values: 4.0.0(postcss@8.4.38) postcss-value-parser: 4.2.0 semver: 7.6.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /css-minimizer-webpack-plugin@5.0.1(webpack@5.91.0): @@ -10073,7 +10281,7 @@ packages: postcss: 8.4.38 schema-utils: 4.2.0 serialize-javascript: 6.0.2 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /css-select@5.1.0: @@ -11212,7 +11420,6 @@ packages: '@esbuild/win32-arm64': 0.19.11 '@esbuild/win32-ia32': 0.19.11 '@esbuild/win32-x64': 0.19.11 - dev: false /esbuild@0.19.12: resolution: {integrity: sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==} @@ -11951,7 +12158,7 @@ packages: dependencies: loader-utils: 2.0.4 schema-utils: 3.3.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /filelist@1.0.4: @@ -12128,7 +12335,7 @@ packages: semver: 7.6.0 tapable: 2.2.1 typescript: 5.4.5 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /form-data@4.0.0: @@ -14348,7 +14555,7 @@ packages: dependencies: klona: 2.0.6 less: 4.1.3 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /less@4.1.3: @@ -14388,8 +14595,10 @@ packages: peerDependenciesMeta: webpack: optional: true + webpack-sources: + optional: true dependencies: - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-sources: 3.2.3 dev: true @@ -15464,7 +15673,7 @@ packages: webpack: ^5.0.0 dependencies: schema-utils: 4.2.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /minimalistic-assert@1.0.1: @@ -16712,7 +16921,7 @@ packages: klona: 2.0.6 postcss: 8.4.21 semver: 7.6.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /postcss-merge-longhand@6.0.5(postcss@8.4.38): @@ -17928,7 +18137,7 @@ packages: klona: 2.0.6 neo-async: 2.6.2 sass: 1.72.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /sass@1.72.0: @@ -18344,7 +18553,7 @@ packages: abab: 2.0.6 iconv-lite: 0.6.3 source-map-js: 1.2.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /source-map-support@0.5.13: @@ -18666,7 +18875,7 @@ packages: peerDependencies: webpack: ^5.0.0 dependencies: - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /style-to-object@0.4.4: @@ -18717,7 +18926,7 @@ packages: fast-glob: 3.3.2 normalize-path: 3.0.0 stylus: 0.59.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /stylus@0.59.0: @@ -18935,31 +19144,6 @@ packages: serialize-javascript: 6.0.2 terser: 5.29.2 webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) - dev: false - - /terser-webpack-plugin@5.3.10(@swc/core@1.3.85)(webpack@5.91.0): - resolution: {integrity: sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==} - engines: {node: '>= 10.13.0'} - peerDependencies: - '@swc/core': '*' - esbuild: '*' - uglify-js: '*' - webpack: ^5.1.0 - peerDependenciesMeta: - '@swc/core': - optional: true - esbuild: - optional: true - uglify-js: - optional: true - dependencies: - '@jridgewell/trace-mapping': 0.3.25 - '@swc/core': 1.3.85(@swc/helpers@0.5.2) - jest-worker: 27.5.1 - schema-utils: 3.3.0 - serialize-javascript: 6.0.2 - terser: 5.29.2 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) /terser@5.29.2: resolution: {integrity: sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==} @@ -19203,7 +19387,7 @@ packages: semver: 7.6.0 source-map: 0.7.4 typescript: 5.4.5 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /ts-morph@18.0.0: @@ -20065,7 +20249,7 @@ packages: import-local: 3.1.0 interpret: 3.1.1 rechoir: 0.8.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-merge: 5.10.0 /webpack-dev-middleware@5.3.4(webpack@5.91.0): @@ -20079,7 +20263,7 @@ packages: mime-types: 2.1.35 range-parser: 1.2.1 schema-utils: 4.2.0 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /webpack-dev-server@4.15.2(webpack-cli@5.1.4)(webpack@5.91.0): @@ -20123,7 +20307,7 @@ packages: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack@5.91.0) webpack-dev-middleware: 5.3.4(webpack@5.91.0) ws: 8.16.0 @@ -20162,7 +20346,7 @@ packages: optional: true dependencies: typed-assert: 1.0.9 - webpack: 5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4) + webpack: 5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4) dev: true /webpack@5.91.0(@swc/core@1.3.101)(esbuild@0.19.11)(webpack-cli@5.1.4): @@ -20204,47 +20388,6 @@ packages: - '@swc/core' - esbuild - uglify-js - dev: false - - /webpack@5.91.0(@swc/core@1.3.85)(webpack-cli@5.1.4): - resolution: {integrity: sha512-rzVwlLeBWHJbmgTC/8TvAcu5vpJNII+MelQpylD4jNERPwpBJOE2lEcko1zJX3QJeLjTTAnQxn/OJ8bjDzVQaw==} - engines: {node: '>=10.13.0'} - hasBin: true - peerDependencies: - webpack-cli: '*' - peerDependenciesMeta: - webpack-cli: - optional: true - dependencies: - '@types/eslint-scope': 3.7.7 - '@types/estree': 1.0.5 - '@webassemblyjs/ast': 1.12.1 - '@webassemblyjs/wasm-edit': 1.12.1 - '@webassemblyjs/wasm-parser': 1.12.1 - acorn: 8.11.3 - acorn-import-assertions: 1.9.0(acorn@8.11.3) - browserslist: 4.23.0 - chrome-trace-event: 1.0.3 - enhanced-resolve: 5.16.0 - es-module-lexer: 1.4.2 - eslint-scope: 5.1.1 - events: 3.3.0 - glob-to-regexp: 0.4.1 - graceful-fs: 4.2.11 - json-parse-even-better-errors: 2.3.1 - loader-runner: 4.3.0 - mime-types: 2.1.35 - neo-async: 2.6.2 - schema-utils: 3.3.0 - tapable: 2.2.1 - terser-webpack-plugin: 5.3.10(@swc/core@1.3.85)(webpack@5.91.0) - watchpack: 2.4.1 - webpack-cli: 5.1.4(webpack@5.91.0) - webpack-sources: 3.2.3 - transitivePeerDependencies: - - '@swc/core' - - esbuild - - uglify-js /websocket-driver@0.7.4: resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} @@ -20571,3 +20714,7 @@ packages: /zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} dev: false + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false