[frontend]: add header, sidebar, dashboard page

This commit is contained in:
Sergey Krylov 2025-08-06 06:33:20 +03:00
parent 8bd66ffe46
commit 7eca41f8fb
57 changed files with 2194 additions and 30 deletions

View File

@ -1,5 +1,5 @@
import { CodegenConfig } from '@graphql-codegen/cli';
import 'dotenv/config'
import type { CodegenConfig } from '@graphql-codegen/cli';
import 'dotenv/config';
const config: CodegenConfig = {
schema: process.env.NEXT_PUBLIC_SERVER_URL,
@ -9,11 +9,11 @@ const config: CodegenConfig = {
plugins: [
'typescript',
'typescript-operations',
'typescript-react-apollo'
]
}
'typescript-react-apollo',
],
},
},
ignoreNoDocuments: true
}
ignoreNoDocuments: true,
};
export default config
export default config;

View File

@ -7,7 +7,7 @@
"build": "yarn run codegen && next build",
"start": "next start",
"lint": "next lint",
"codegen": "graphql-codegen --config graphql.config.ts"
"codegen": "graphql-codegen --config graphql.config.ts --watch"
},
"dependencies": {
"@apollo/client": "3.13.9",
@ -16,11 +16,17 @@
"@graphql-codegen/typescript-operations": "4.6.1",
"@graphql-codegen/typescript-react-apollo": "4.3.3",
"@hookform/resolvers": "5.2.1",
"@radix-ui/react-avatar": "1.1.10",
"@radix-ui/react-dropdown-menu": "2.1.15",
"@radix-ui/react-label": "2.1.7",
"@radix-ui/react-popover": "^1.1.14",
"@radix-ui/react-separator": "^1.1.7",
"@radix-ui/react-slot": "1.2.3",
"@radix-ui/react-tooltip": "1.2.7",
"class-variance-authority": "0.7.1",
"clsx": "2.1.1",
"graphql": "16.11.0",
"html-react-parser": "^5.2.6",
"input-otp": "1.4.2",
"lucide-react": "0.534.0",
"next": "15.4.5",
@ -37,6 +43,7 @@
"devDependencies": {
"@eslint/eslintrc": "3.3.1",
"@next/eslint-plugin-next": "15.4.5",
"@parcel/watcher": "^2.5.1",
"@tailwindcss/postcss": "4.1.11",
"@types/node": "22.17.0",
"@types/react": "19.1.9",
@ -45,6 +52,7 @@
"eslint-config-ksv741": "0.2.0",
"eslint-config-next": "15.4.4",
"tailwindcss": "4.1.11",
"ts-node": "10.9.2",
"tw-animate-css": "1.3.6",
"typescript": "5.8.3"
}

View File

@ -0,0 +1,19 @@
import { getTranslations } from 'next-intl/server';
import type { Metadata } from 'next';
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations('layout.header.headerMenu.profileMenu');
return {
title: t('dashboard'),
};
}
const DashboardSettings = () => (
<div>
DashboardSettings page
</div>
);
export default DashboardSettings;

View File

@ -0,0 +1,23 @@
import { Header } from '@/components/layout/header/Header';
import { LayoutContainer } from '@/components/layout/LayoutContainer';
import { Sidebar } from '@/components/layout/sidebar/Sidebar';
import type { PropsWithChildren } from 'react';
const SiteLayout = ({ children }: PropsWithChildren) => (
<div className="flex h-full flex-col">
<div className="flex-1">
<div className="fixed inset-y-0 z-50 h-[75px] w-full">
<Header />
</div>
<Sidebar />
<LayoutContainer>
{children}
</LayoutContainer>
</div>
</div>
);
export default SiteLayout;

View File

@ -0,0 +1,19 @@
import { getTranslations } from 'next-intl/server';
import type { Metadata } from 'next';
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations('layout.header.logo');
return {
title: t('platform'),
};
}
const Home = () => (
<div>
home
</div>
);
export default Home;

View File

@ -1,7 +0,0 @@
'use client';
import { redirect } from 'next/navigation';
export default function Home() {
redirect('account/login');
}

View File

@ -0,0 +1,31 @@
'use client';
import { type PropsWithChildren, useEffect } from 'react';
import { useMediaQuery } from '@/hooks/useMediaQuery';
import { useSidebar } from '@/hooks/useSidebar';
import { cn } from '@/utils/tw-merge';
export const LayoutContainer = ({ children }: PropsWithChildren) => {
const isMobile: boolean = useMediaQuery('(max-width: 1024px)');
const { isCollapsed, open, close } = useSidebar();
useEffect(() => {
if (isMobile) {
if (!isCollapsed) close();
} else if (isCollapsed) open();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [isMobile]);
return (
<main
className={cn(
'mt-[75px] flex-1 p-8',
isCollapsed ? 'ml-16' : 'ml-16 lg:ml-64',
)}
>
{children}
</main>
);
};

View File

@ -0,0 +1,13 @@
import { HeaderMenu } from './HeaderMenu';
import { Logo } from './Logo';
import { Search } from './Search';
export const Header = () => (
<header className="flex h-full items-center gap-x-4 border-b border-border bg-card p-4">
<Logo />
<Search />
<HeaderMenu />
</header>
);

View File

@ -0,0 +1,38 @@
'use client';
import Link from 'next/link';
import { useTranslations } from 'next-intl';
import { Button } from '@/components/ui/common/Button';
import { useAuth } from '@/hooks/useAuth';
import { ProfileMenu } from './ProfileMenu';
export const HeaderMenu = () => {
const t = useTranslations('layout.header.headerMenu');
const { isAuthenticated } = useAuth();
return (
<div className="ml-auto flex items-center gap-x-4">
{isAuthenticated
? (
<ProfileMenu />
)
: (
<>
<Link href="/account/login">
<Button variant="secondary">
{t('login')}
</Button>
</Link>
<Link href="/account/create">
<Button>
{t('register')}
</Button>
</Link>
</>
)}
</div>
);
};

View File

@ -0,0 +1,29 @@
'use client';
import Link from 'next/link';
import { useTranslations } from 'next-intl';
import { LogoImage } from '@/components/images/LogoImage';
export const Logo = () => {
const t = useTranslations('layout.header.logo');
return (
<Link
className="flex items-center gap-x-4 transition-opacity hover:opacity-75"
href="/"
>
<LogoImage />
<div className="hidden leading-tight lg:block">
<h2 className="text-lg font-semibold tracking-wider text-accent-foreground">
TeaStream
</h2>
<p className="text-sm text-muted-foreground">
{t('platform')}
</p>
</div>
</Link>
);
};

View File

@ -0,0 +1,90 @@
'use client';
import {
LayoutDashboard, Loader, LogOut, User,
} from 'lucide-react';
import Link from 'next/link';
import { useRouter } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { toast } from 'sonner';
import { Notifications } from '@/components/layout/header/notifications/Notification';
import {
DropdownMenu, DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from '@/components/ui/common/DropdownMenu';
import { ChannelAvatar } from '@/components/ui/elements/ChannelAvatar';
import { useLogoutUserMutation } from '@/graphql/generated/output';
import { useAuth } from '@/hooks/useAuth';
import { useCurrent } from '@/hooks/useCurrent';
export const ProfileMenu = () => {
const t = useTranslations('layout.header.headerMenu.profileMenu');
const router = useRouter();
const { exit } = useAuth();
const { user, isLoadingProfile } = useCurrent();
const [logout] = useLogoutUserMutation({
onCompleted() {
exit();
toast.success(t('successMessage'));
router.push('/account/login');
},
onError() {
toast.error(t('errorMessage'));
},
});
return isLoadingProfile || !user
? (
<Loader className="size-6 animate-spin text-muted-foreground" />
)
: (
<>
<Notifications />
<DropdownMenu>
<DropdownMenuTrigger>
<ChannelAvatar channel={user} />
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="w-[230px]">
<div className="flex items-center gap-x-3 p-2">
<ChannelAvatar channel={user} />
<h2 className="font-medium text-foreground">
{user.name}
</h2>
</div>
<DropdownMenuSeparator />
<Link href={`/${user.name}`}>
<DropdownMenuItem>
<User className="mr-2 size-2" />
{t('channel')}
</DropdownMenuItem>
</Link>
<Link href="/dashboard/settings">
<DropdownMenuItem>
<LayoutDashboard className="mr-2 size-2" />
{t('dashboard')}
</DropdownMenuItem>
</Link>
<DropdownMenuItem onClick={async () => logout()}>
<LogOut className="mr-2 size-2" />
{t('logout')}
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</>
);
};

View File

@ -0,0 +1,44 @@
'use client';
import { SearchIcon } from 'lucide-react';
import { useRouter } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { type FormEvent, useState } from 'react';
import { Button } from '@/components/ui/common/Button';
import { Input } from '@/components/ui/common/Input';
export const Search = () => {
const t = useTranslations('layout.header.search');
const [searchTerm, setSearchTerm] = useState('');
const router = useRouter();
function onSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
if (searchTerm.trim()) {
router.push(`/streams?searchTerm=${searchTerm}`);
} else {
router.push('/streams');
}
}
return (
<div className="ml-auto hidden lg:block">
<form className="relative flex items-center" onSubmit={onSubmit}>
<Input
className="w-full rounded-full pl-4 pr-10 lg:w-[400px]"
placeholder={t('placeholder')}
type="text"
value={searchTerm}
onChange={(e) => { setSearchTerm(e.target.value); }}
/>
<Button className="absolute right-0.5 h-9" type="submit">
<SearchIcon className="absolute size-[18px]" />
</Button>
</form>
</div>
);
};

View File

@ -0,0 +1,40 @@
import { Bell } from 'lucide-react';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/common/Popover';
import { useFindUnreadNotificationsCountQuery } from '@/graphql/generated/output';
import { NotificationsList } from './NotificationsList';
export const Notifications = () => {
const { data, loading: isLoadingCount } = useFindUnreadNotificationsCountQuery();
const count = data?.findUnreadNotificationsCount ?? 0;
const displayCount = count > 10 ? '+9' : count;
if (isLoadingCount) return null;
return (
<Popover>
<PopoverTrigger>
{count !== 0 && (
<div className="absolute right-[72px] top-5 rounded-full bg-primary px-[5px] text-xs font-semibold text-white">
{displayCount}
</div>
)}
<Bell className="size-5 text-foreground" />
</PopoverTrigger>
<PopoverContent
align="end"
className="max-h-[500px] w-[320px] overflow-y-auto"
>
<NotificationsList />
</PopoverContent>
</Popover>
);
};

View File

@ -0,0 +1,73 @@
import parse from 'html-react-parser';
import { Loader2 } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { Fragment } from 'react';
import { Separator } from '@/components/ui/common/Separator';
import {
useFindNotificationByUserQuery,
useFindUnreadNotificationsCountQuery,
} from '@/graphql/generated/output';
import { getNotificationIcon } from '@/utils/get-notification-icon';
export const NotificationsList = () => {
const t = useTranslations(
'layout.header.headerMenu.profileMenu.notifications',
);
const { refetch } = useFindUnreadNotificationsCountQuery();
const { data, loading: isLoadingNotifications } = useFindNotificationByUserQuery({
onCompleted() {
void refetch();
},
});
const notifications = data?.findNotificationByUser ?? [];
return (
<>
<h2 className="text-center text-lg font-medium">
{t('heading')}
</h2>
<Separator className="my-3" />
{/* eslint-disable-next-line no-nested-ternary */}
{isLoadingNotifications
? (
<div className="flex items-center justify-center gap-x-2 text-sm text-foreground">
<Loader2 className="size-5 animate-spin" />
{t('loading')}
</div>
)
: notifications.length
? notifications.map((notification, index) => {
const Icon = getNotificationIcon(notification.type);
return (
<Fragment key={notification.id}>
<div className="flex items-center gap-x-3 text-sm">
<div className="rounded-full bg-foreground p-2">
<Icon className="size-6 text-secondary" />
</div>
<div>
{parse(notification.text)}
</div>
</div>
{index < notifications.length - 1 && (
<Separator className="my-3" />
)}
</Fragment>
);
})
: (
<div className="text-center text-muted-foreground">
{t('empty')}
</div>
)}
</>
);
};

View File

@ -0,0 +1,64 @@
import {
Banknote,
DollarSign,
KeyRound,
Medal,
MessageSquare,
Settings,
Users,
} from 'lucide-react';
import { useTranslations } from 'next-intl';
import { SidebarItem } from './SidebarItem';
import type { Route } from './route.interface';
export const DashboardNav = () => {
const t = useTranslations('layout.sidebar.dashboardNav');
const routes: Route[] = [
{
label: t('settings'),
href: '/dashboard/settings',
icon: Settings,
},
{
label: t('keys'),
href: '/dashboard/keys',
icon: KeyRound,
},
{
label: t('chatSettings'),
href: '/dashboard/chat',
icon: MessageSquare,
},
{
label: t('followers'),
href: '/dashboard/followers',
icon: Users,
},
{
label: t('sponsors'),
href: '/dashboard/sponsors',
icon: Medal,
},
{
label: t('premium'),
href: '/dashboard/plans',
icon: DollarSign,
},
{
label: t('transactions'),
href: '/dashboard/transactions',
icon: Banknote,
},
];
return (
<div className="space-y-2 px-2 pt-4 lg:pt-0">
{routes.map((route) => (
<SidebarItem key={route.href} route={route} />
))}
</div>
);
};

View File

@ -0,0 +1,31 @@
'use client';
import { usePathname } from 'next/navigation';
import { UserNav } from '@/components/layout/sidebar/UserNav';
import { useSidebar } from '@/hooks/useSidebar';
import { cn } from '@/utils/tw-merge';
import { DashboardNav } from './DashboardNav';
import { SidebarHeader } from './SidebarHeader';
export const Sidebar = () => {
const { isCollapsed } = useSidebar();
const pathname = usePathname();
const isDashboardPage = pathname.includes('/dashboard');
return (
<aside
className={cn(
'fixed left-0 z-50 mt-[75px] flex h-full flex-col border-r border-border bg-card transition-all duration-100 ease-in-out',
isCollapsed ? 'w-16' : 'w-64',
)}
>
<SidebarHeader />
{isDashboardPage ? <DashboardNav /> : <UserNav />}
</aside>
);
};

View File

@ -0,0 +1,42 @@
'use client';
import { ArrowLeftFromLine, ArrowRightFromLine } from 'lucide-react';
import { usePathname } from 'next/navigation';
import { useTranslations } from 'next-intl';
import { Button } from '@/components/ui/common/Button';
import { Hint } from '@/components/ui/elements/Hint';
import { useSidebar } from '@/hooks/useSidebar';
export const SidebarHeader = () => {
const t = useTranslations('layout.sidebar.header');
const pathname = usePathname();
const { isCollapsed, open, close } = useSidebar();
const label = isCollapsed ? t('expand') : t('collapse');
return isCollapsed
? (
<div className="mb-4 hidden w-full items-center justify-center pt-4 lg:flex">
<Hint asChild label={label} side="right">
<Button size="icon" variant="ghost" onClick={() => { open(); }}>
<ArrowRightFromLine className="size-4" />
</Button>
</Hint>
</div>
)
: (
<div className="mb-2 flex w-full items-center justify-between p-3 pl-4">
<h2 className="text-lg font-semibold text-foreground">
{t('navigation')}
</h2>
<Hint asChild label={label} side="right">
<Button size="icon" variant="ghost" onClick={() => { close(); }}>
<ArrowLeftFromLine className="size-4" />
</Button>
</Hint>
</div>
);
};

View File

@ -0,0 +1,53 @@
'use client';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { Button } from '@/components/ui/common/Button';
import { Hint } from '@/components/ui/elements/Hint';
import { useSidebar } from '@/hooks/useSidebar';
import { cn } from '@/utils/tw-merge';
import type { Route } from './route.interface';
type SidebarItemProps = {
route: Route;
};
export const SidebarItem = ({ route }: SidebarItemProps) => {
const pathname = usePathname();
const { isCollapsed } = useSidebar();
const isActive = pathname === route.href;
return isCollapsed
? (
<Hint asChild label={route.label} side="right">
<Button
asChild
className={cn(
'h-11 w-full justify-center',
isActive && 'bg-accent',
)}
variant="ghost"
>
<Link href={route.href}>
<route.icon className="mr-0 size-5" />
</Link>
</Button>
</Hint>
)
: (
<Button
asChild
className={cn('h-11 w-full justify-start', isActive && 'bg-accent')}
variant="ghost"
>
<Link className="flex items-start gap-x-4" href={route.href}>
<route.icon className="mr-0 size-5" />
{route.label}
</Link>
</Button>
);
};

View File

@ -0,0 +1,38 @@
import { Folder, Home, Radio } from 'lucide-react';
import { useTranslations } from 'next-intl';
import { SidebarItem } from './SidebarItem';
import type { Route } from './route.interface';
export const UserNav = () => {
const t = useTranslations('layout.sidebar.userNav');
const routes: Route[] = [
{
label: t('home'),
href: '/',
icon: Home,
},
{
label: t('categories'),
href: '/categories',
icon: Folder,
},
{
label: t('streams'),
href: '/streams',
icon: Radio,
},
];
return (
<div className="space-y-2 px-2 pt-4 lg:pt-0">
{routes.map((route) => (
<SidebarItem key={route.href} route={route} />
))}
{/* <RecommededChannels /> */}
</div>
);
};

View File

@ -0,0 +1,7 @@
import type { LucideIcon } from 'lucide-react';
export type Route = {
label: string;
href: string;
icon: LucideIcon;
};

View File

@ -1,7 +1,7 @@
import { type VariantProps, cva } from 'class-variance-authority';
import { type HTMLAttributes, forwardRef } from 'react';
import { cn } from '@/utils/twMerge';
import { cn } from '@/utils/tw-merge';
const alertVariants = cva(
'relative w-full rounded-lg border p-4 [&>svg~*]:pl-7 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground',

View File

@ -0,0 +1,54 @@
'use client';
import * as AvatarPrimitive from '@radix-ui/react-avatar';
import {
type ComponentPropsWithoutRef,
type ComponentRef,
forwardRef,
} from 'react';
import { cn } from '@/utils/tw-merge';
const Avatar = forwardRef<
ComponentRef<typeof AvatarPrimitive.Root>,
ComponentPropsWithoutRef<typeof AvatarPrimitive.Root>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Root
ref={ref}
className={cn(
'relative flex h-10 w-10 shrink-0 overflow-hidden rounded-full',
className,
)}
{...props}
/>
));
Avatar.displayName = AvatarPrimitive.Root.displayName;
const AvatarImage = forwardRef<
ComponentRef<typeof AvatarPrimitive.Image>,
ComponentPropsWithoutRef<typeof AvatarPrimitive.Image>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Image
ref={ref}
className={cn('aspect-square h-full w-full', className)}
{...props}
/>
));
AvatarImage.displayName = AvatarPrimitive.Image.displayName;
const AvatarFallback = forwardRef<
ComponentRef<typeof AvatarPrimitive.Fallback>,
ComponentPropsWithoutRef<typeof AvatarPrimitive.Fallback>
>(({ className, ...props }, ref) => (
<AvatarPrimitive.Fallback
ref={ref}
className={cn(
'flex h-full w-full items-center justify-center rounded-full bg-muted',
className,
)}
{...props}
/>
));
AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName;
export { Avatar, AvatarFallback, AvatarImage };

View File

@ -2,10 +2,10 @@ import { Slot } from '@radix-ui/react-slot';
import { type VariantProps, cva } from 'class-variance-authority';
import { type ButtonHTMLAttributes, forwardRef } from 'react';
import { cn } from '@/utils/twMerge';
import { cn } from '@/utils/tw-merge';
const buttonVariants = cva(
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
'inline-flex items-center justify-center gap-2 cursor-pointer whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
{
variants: {
variant: {

View File

@ -1,6 +1,6 @@
import { type HTMLAttributes, forwardRef } from 'react';
import { cn } from '@/utils/twMerge';
import { cn } from '@/utils/tw-merge';
const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (

View File

@ -0,0 +1,210 @@
'use client';
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
import { Check, ChevronRight, Circle } from 'lucide-react';
import {
type ComponentPropsWithoutRef,
type ComponentRef,
type HTMLAttributes,
forwardRef,
} from 'react';
import { cn } from '@/utils/tw-merge';
const DropdownMenu = DropdownMenuPrimitive.Root;
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
const DropdownMenuSubTrigger = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.SubTrigger>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean;
}
>(({
className, inset, children, ...props
}, ref) => (
<DropdownMenuPrimitive.SubTrigger
ref={ref}
className={cn(
'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
inset && 'pl-8',
className,
)}
{...props}
>
{children}
<ChevronRight className="ml-auto" />
</DropdownMenuPrimitive.SubTrigger>
));
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
const DropdownMenuSubContent = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.SubContent>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.SubContent
ref={ref}
className={cn(
'z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
{...props}
/>
));
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
const DropdownMenuContent = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.Content>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
ref={ref}
className={cn(
'z-50 min-w-32 overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
sideOffset={sideOffset}
{...props}
/>
</DropdownMenuPrimitive.Portal>
));
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
const DropdownMenuItem = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.Item>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Item
ref={ref}
className={cn(
'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
inset && 'pl-8',
className,
)}
{...props}
/>
));
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
const DropdownMenuCheckboxItem = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.CheckboxItem>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
>(({
className, children, checked, ...props
}, ref) => (
<DropdownMenuPrimitive.CheckboxItem
ref={ref}
checked={checked}
className={cn(
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
className,
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Check className="h-4 w-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
));
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
const DropdownMenuRadioItem = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.RadioItem>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
>(({ className, children, ...props }, ref) => (
<DropdownMenuPrimitive.RadioItem
ref={ref}
className={cn(
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50',
className,
)}
{...props}
>
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<Circle className="h-2 w-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
));
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
const DropdownMenuLabel = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.Label>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean;
}
>(({ className, inset, ...props }, ref) => (
<DropdownMenuPrimitive.Label
ref={ref}
className={cn(
'px-2 py-1.5 text-sm font-semibold',
inset && 'pl-8',
className,
)}
{...props}
/>
));
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
const DropdownMenuSeparator = forwardRef<
ComponentRef<typeof DropdownMenuPrimitive.Separator>,
ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
>(({ className, ...props }, ref) => (
<DropdownMenuPrimitive.Separator
ref={ref}
className={cn('-mx-1 my-1 h-px bg-muted', className)}
{...props}
/>
));
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
const DropdownMenuShortcut = ({
className,
...props
}: HTMLAttributes<HTMLSpanElement>) => (
<span
className={cn(
'ml-auto text-xs tracking-widest opacity-60',
className,
)}
{...props}
/>
);
DropdownMenuShortcut.displayName = 'DropdownMenuShortcut';
export {
DropdownMenu,
DropdownMenuCheckboxItem,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuPortal,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
};

View File

@ -19,7 +19,7 @@ import {
useFormContext,
} from 'react-hook-form';
import { cn } from '@/utils/twMerge';
import { cn } from '@/utils/tw-merge';
import { Label } from './Label';

View File

@ -1,6 +1,6 @@
import { type ComponentProps, forwardRef } from 'react';
import { cn } from '@/utils/twMerge';
import { cn } from '@/utils/tw-merge';
const Input = forwardRef<HTMLInputElement, ComponentProps<'input'>>(
({ className, type, ...props }, ref) => (

View File

@ -9,7 +9,7 @@ import {
useContext,
} from 'react';
import { cn } from '@/utils/twMerge';
import { cn } from '@/utils/tw-merge';
const InputOTP = forwardRef<
ComponentRef<typeof OTPInput>,

View File

@ -8,7 +8,7 @@ import {
forwardRef,
} from 'react';
import { cn } from '@/utils/twMerge';
import { cn } from '@/utils/tw-merge';
const labelVariants = cva(
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',

View File

@ -0,0 +1,37 @@
'use client';
import * as PopoverPrimitive from '@radix-ui/react-popover';
import {
type ComponentPropsWithoutRef,
type ComponentRef,
forwardRef,
} from 'react';
import { cn } from '@/utils/tw-merge';
const Popover = PopoverPrimitive.Root;
const PopoverTrigger = PopoverPrimitive.Trigger;
const PopoverContent = forwardRef<
ComponentRef<typeof PopoverPrimitive.Content>,
ComponentPropsWithoutRef<typeof PopoverPrimitive.Content>
>(({
className, align = 'center', sideOffset = 4, ...props
}, ref) => (
<PopoverPrimitive.Portal>
<PopoverPrimitive.Content
ref={ref}
align={align}
className={cn(
'z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
sideOffset={sideOffset}
{...props}
/>
</PopoverPrimitive.Portal>
));
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
export { Popover, PopoverContent, PopoverTrigger };

View File

@ -0,0 +1,39 @@
'use client';
import * as SeparatorPrimitive from '@radix-ui/react-separator';
import {
type ComponentPropsWithoutRef,
type ComponentRef,
forwardRef,
} from 'react';
import { cn } from '@/utils/tw-merge';
const Separator = forwardRef<
ComponentRef<typeof SeparatorPrimitive.Root>,
ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
>(
(
{
className, orientation = 'horizontal', decorative = true, ...props
},
ref,
) => (
<SeparatorPrimitive.Root
ref={ref}
className={cn(
'shrink-0 bg-border',
orientation === 'horizontal'
? 'h-px w-full'
: 'h-full w-px',
className,
)}
decorative={decorative}
orientation={orientation}
{...props}
/>
),
);
Separator.displayName = SeparatorPrimitive.Root.displayName;
export { Separator };

View File

@ -0,0 +1,36 @@
'use client';
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
import {
type ComponentPropsWithoutRef,
type ComponentRef,
forwardRef,
} from 'react';
import { cn } from '@/utils/tw-merge';
const TooltipProvider = TooltipPrimitive.Provider;
const Tooltip = TooltipPrimitive.Root;
const TooltipTrigger = TooltipPrimitive.Trigger;
const TooltipContent = forwardRef<
ComponentRef<typeof TooltipPrimitive.Content>,
ComponentPropsWithoutRef<typeof TooltipPrimitive.Content>
>(({ className, sideOffset = 4, ...props }, ref) => (
<TooltipPrimitive.Content
ref={ref}
className={cn(
'z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
className,
)}
sideOffset={sideOffset}
{...props}
/>
));
TooltipContent.displayName = TooltipPrimitive.Content.displayName;
export {
Tooltip, TooltipContent, TooltipProvider, TooltipTrigger,
};

View File

@ -0,0 +1,52 @@
import { type VariantProps, cva } from 'class-variance-authority';
import { getMediaSource } from '@/utils/get-media-source';
import { cn } from '@/utils/tw-merge';
import { Avatar, AvatarFallback, AvatarImage } from '../common/Avatar';
import type { FindProfileQuery } from '@/graphql/generated/output';
const avatarSizes = cva('', {
variants: {
size: {
sm: 'size-7',
default: 'size-9',
lg: 'size-14',
xl: 'size-32',
},
},
defaultVariants: {
size: 'default',
},
});
type ChannelAvatarProps = VariantProps<typeof avatarSizes> & {
channel: Pick<FindProfileQuery['findProfile'], 'avatar' | 'name'>;
isLive?: boolean;
};
export const ChannelAvatar = ({ size, channel, isLive }: ChannelAvatarProps) => (
<div className="relative">
<Avatar
className={cn(
avatarSizes({ size }),
isLive && 'ring-2 ring-rose-500',
)}
>
<AvatarImage
className="object-cover"
src={getMediaSource(channel.avatar)}
/>
<AvatarFallback
className={cn(
size === 'xl' && 'text-4xl',
size === 'lg' && 'text-2xl',
)}
>
{channel.name[0]}
</AvatarFallback>
</Avatar>
</div>
);

View File

@ -0,0 +1,41 @@
import {
Tooltip,
TooltipContent,
TooltipProvider,
TooltipTrigger,
} from '../common/Tooltip';
import type { PropsWithChildren } from 'react';
type HintProps = {
label: string;
asChild?: boolean;
side?: 'bottom' | 'left' | 'right' | 'top';
aling?: 'center' | 'end' | 'start';
};
export const Hint = ({
children,
label,
asChild,
aling,
side,
}: PropsWithChildren<HintProps>) => (
<TooltipProvider>
<Tooltip delayDuration={0}>
<TooltipTrigger asChild={asChild}>
{children}
</TooltipTrigger>
<TooltipContent
align={aling}
className="bg-[#1f2128] text-white dark:bg-white dark:text-[#1f2128]"
side={side}
>
<p className="font-semibold">
{label}
</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
);

View File

@ -591,6 +591,11 @@ export type VerificationInput = {
token: Scalars['String']['input'];
};
export type ClearSessionCookieMutationVariables = Exact<{ [key: string]: never; }>;
export type ClearSessionCookieMutation = { __typename?: 'Mutation', clearSessionCookie: boolean };
export type CreateUserMutationVariables = Exact<{
data: CreateUserInput;
}>;
@ -605,6 +610,11 @@ export type LoginUserMutationVariables = Exact<{
export type LoginUserMutation = { __typename?: 'Mutation', loginUser: { __typename?: 'AuthModel', message?: string | null, user?: { __typename?: 'UserModel', id: string, name: string, email: string } | null } };
export type LogoutUserMutationVariables = Exact<{ [key: string]: never; }>;
export type LogoutUserMutation = { __typename?: 'Mutation', logoutUser: boolean };
export type NewPasswordMutationVariables = Exact<{
data: NewPasswordInput;
}>;
@ -633,7 +643,52 @@ export type FindChannelByUsernameQueryVariables = Exact<{
export type FindChannelByUsernameQuery = { __typename?: 'Query', findChannelByUsername: { __typename?: 'UserModel', name: string, avatar?: string | null, displayName: string, stream: { __typename?: 'StreamModel', title: string } } };
export type FindNotificationByUserQueryVariables = Exact<{ [key: string]: never; }>;
export type FindNotificationByUserQuery = { __typename?: 'Query', findNotificationByUser: Array<{ __typename?: 'NotificationModel', createdAt: any, id: string, isRead: boolean, text: string, type: NotificationType, updatedAt: any, userId: string }> };
export type FindUnreadNotificationsCountQueryVariables = Exact<{ [key: string]: never; }>;
export type FindUnreadNotificationsCountQuery = { __typename?: 'Query', findUnreadNotificationsCount: number };
export type FindProfileQueryVariables = Exact<{ [key: string]: never; }>;
export type FindProfileQuery = { __typename?: 'Query', findProfile: { __typename?: 'UserModel', avatar?: string | null, bio?: string | null, createdAt: any, email: string, id: string, name: string, updatedAt: any, isEmailVerified: boolean, isTotpEnabled: boolean, isVerified: boolean, displayName: string, socialLink: Array<{ __typename?: 'SocialLinkModel', title: string, url: string, position: number }> } };
export const ClearSessionCookieDocument = gql`
mutation ClearSessionCookie {
clearSessionCookie
}
`;
export type ClearSessionCookieMutationFn = Apollo.MutationFunction<ClearSessionCookieMutation, ClearSessionCookieMutationVariables>;
/**
* __useClearSessionCookieMutation__
*
* To run a mutation, you first call `useClearSessionCookieMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useClearSessionCookieMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [clearSessionCookieMutation, { data, loading, error }] = useClearSessionCookieMutation({
* variables: {
* },
* });
*/
export function useClearSessionCookieMutation(baseOptions?: Apollo.MutationHookOptions<ClearSessionCookieMutation, ClearSessionCookieMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<ClearSessionCookieMutation, ClearSessionCookieMutationVariables>(ClearSessionCookieDocument, options);
}
export type ClearSessionCookieMutationHookResult = ReturnType<typeof useClearSessionCookieMutation>;
export type ClearSessionCookieMutationResult = Apollo.MutationResult<ClearSessionCookieMutation>;
export type ClearSessionCookieMutationOptions = Apollo.BaseMutationOptions<ClearSessionCookieMutation, ClearSessionCookieMutationVariables>;
export const CreateUserDocument = gql`
mutation CreateUser($data: CreateUserInput!) {
createUser(data: $data) {
@ -707,6 +762,36 @@ export function useLoginUserMutation(baseOptions?: Apollo.MutationHookOptions<Lo
export type LoginUserMutationHookResult = ReturnType<typeof useLoginUserMutation>;
export type LoginUserMutationResult = Apollo.MutationResult<LoginUserMutation>;
export type LoginUserMutationOptions = Apollo.BaseMutationOptions<LoginUserMutation, LoginUserMutationVariables>;
export const LogoutUserDocument = gql`
mutation LogoutUser {
logoutUser
}
`;
export type LogoutUserMutationFn = Apollo.MutationFunction<LogoutUserMutation, LogoutUserMutationVariables>;
/**
* __useLogoutUserMutation__
*
* To run a mutation, you first call `useLogoutUserMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useLogoutUserMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [logoutUserMutation, { data, loading, error }] = useLogoutUserMutation({
* variables: {
* },
* });
*/
export function useLogoutUserMutation(baseOptions?: Apollo.MutationHookOptions<LogoutUserMutation, LogoutUserMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<LogoutUserMutation, LogoutUserMutationVariables>(LogoutUserDocument, options);
}
export type LogoutUserMutationHookResult = ReturnType<typeof useLogoutUserMutation>;
export type LogoutUserMutationResult = Apollo.MutationResult<LogoutUserMutation>;
export type LogoutUserMutationOptions = Apollo.BaseMutationOptions<LogoutUserMutation, LogoutUserMutationVariables>;
export const NewPasswordDocument = gql`
mutation NewPassword($data: NewPasswordInput!) {
setNewPassword(data: $data)
@ -849,4 +934,140 @@ export function useFindChannelByUsernameSuspenseQuery(baseOptions?: Apollo.SkipT
export type FindChannelByUsernameQueryHookResult = ReturnType<typeof useFindChannelByUsernameQuery>;
export type FindChannelByUsernameLazyQueryHookResult = ReturnType<typeof useFindChannelByUsernameLazyQuery>;
export type FindChannelByUsernameSuspenseQueryHookResult = ReturnType<typeof useFindChannelByUsernameSuspenseQuery>;
export type FindChannelByUsernameQueryResult = Apollo.QueryResult<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>;
export type FindChannelByUsernameQueryResult = Apollo.QueryResult<FindChannelByUsernameQuery, FindChannelByUsernameQueryVariables>;
export const FindNotificationByUserDocument = gql`
query FindNotificationByUser {
findNotificationByUser {
createdAt
id
isRead
text
type
updatedAt
userId
}
}
`;
/**
* __useFindNotificationByUserQuery__
*
* To run a query within a React component, call `useFindNotificationByUserQuery` and pass it any options that fit your needs.
* When your component renders, `useFindNotificationByUserQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useFindNotificationByUserQuery({
* variables: {
* },
* });
*/
export function useFindNotificationByUserQuery(baseOptions?: Apollo.QueryHookOptions<FindNotificationByUserQuery, FindNotificationByUserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<FindNotificationByUserQuery, FindNotificationByUserQueryVariables>(FindNotificationByUserDocument, options);
}
export function useFindNotificationByUserLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FindNotificationByUserQuery, FindNotificationByUserQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<FindNotificationByUserQuery, FindNotificationByUserQueryVariables>(FindNotificationByUserDocument, options);
}
export function useFindNotificationByUserSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions<FindNotificationByUserQuery, FindNotificationByUserQueryVariables>) {
const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
return Apollo.useSuspenseQuery<FindNotificationByUserQuery, FindNotificationByUserQueryVariables>(FindNotificationByUserDocument, options);
}
export type FindNotificationByUserQueryHookResult = ReturnType<typeof useFindNotificationByUserQuery>;
export type FindNotificationByUserLazyQueryHookResult = ReturnType<typeof useFindNotificationByUserLazyQuery>;
export type FindNotificationByUserSuspenseQueryHookResult = ReturnType<typeof useFindNotificationByUserSuspenseQuery>;
export type FindNotificationByUserQueryResult = Apollo.QueryResult<FindNotificationByUserQuery, FindNotificationByUserQueryVariables>;
export const FindUnreadNotificationsCountDocument = gql`
query FindUnreadNotificationsCount {
findUnreadNotificationsCount
}
`;
/**
* __useFindUnreadNotificationsCountQuery__
*
* To run a query within a React component, call `useFindUnreadNotificationsCountQuery` and pass it any options that fit your needs.
* When your component renders, `useFindUnreadNotificationsCountQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useFindUnreadNotificationsCountQuery({
* variables: {
* },
* });
*/
export function useFindUnreadNotificationsCountQuery(baseOptions?: Apollo.QueryHookOptions<FindUnreadNotificationsCountQuery, FindUnreadNotificationsCountQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<FindUnreadNotificationsCountQuery, FindUnreadNotificationsCountQueryVariables>(FindUnreadNotificationsCountDocument, options);
}
export function useFindUnreadNotificationsCountLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FindUnreadNotificationsCountQuery, FindUnreadNotificationsCountQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<FindUnreadNotificationsCountQuery, FindUnreadNotificationsCountQueryVariables>(FindUnreadNotificationsCountDocument, options);
}
export function useFindUnreadNotificationsCountSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions<FindUnreadNotificationsCountQuery, FindUnreadNotificationsCountQueryVariables>) {
const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
return Apollo.useSuspenseQuery<FindUnreadNotificationsCountQuery, FindUnreadNotificationsCountQueryVariables>(FindUnreadNotificationsCountDocument, options);
}
export type FindUnreadNotificationsCountQueryHookResult = ReturnType<typeof useFindUnreadNotificationsCountQuery>;
export type FindUnreadNotificationsCountLazyQueryHookResult = ReturnType<typeof useFindUnreadNotificationsCountLazyQuery>;
export type FindUnreadNotificationsCountSuspenseQueryHookResult = ReturnType<typeof useFindUnreadNotificationsCountSuspenseQuery>;
export type FindUnreadNotificationsCountQueryResult = Apollo.QueryResult<FindUnreadNotificationsCountQuery, FindUnreadNotificationsCountQueryVariables>;
export const FindProfileDocument = gql`
query FindProfile {
findProfile {
avatar
bio
createdAt
email
id
name
updatedAt
isEmailVerified
isTotpEnabled
isVerified
displayName
socialLink {
title
url
position
}
}
}
`;
/**
* __useFindProfileQuery__
*
* To run a query within a React component, call `useFindProfileQuery` and pass it any options that fit your needs.
* When your component renders, `useFindProfileQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useFindProfileQuery({
* variables: {
* },
* });
*/
export function useFindProfileQuery(baseOptions?: Apollo.QueryHookOptions<FindProfileQuery, FindProfileQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<FindProfileQuery, FindProfileQueryVariables>(FindProfileDocument, options);
}
export function useFindProfileLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<FindProfileQuery, FindProfileQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<FindProfileQuery, FindProfileQueryVariables>(FindProfileDocument, options);
}
export function useFindProfileSuspenseQuery(baseOptions?: Apollo.SkipToken | Apollo.SuspenseQueryHookOptions<FindProfileQuery, FindProfileQueryVariables>) {
const options = baseOptions === Apollo.skipToken ? baseOptions : {...defaultOptions, ...baseOptions}
return Apollo.useSuspenseQuery<FindProfileQuery, FindProfileQueryVariables>(FindProfileDocument, options);
}
export type FindProfileQueryHookResult = ReturnType<typeof useFindProfileQuery>;
export type FindProfileLazyQueryHookResult = ReturnType<typeof useFindProfileLazyQuery>;
export type FindProfileSuspenseQueryHookResult = ReturnType<typeof useFindProfileSuspenseQuery>;
export type FindProfileQueryResult = Apollo.QueryResult<FindProfileQuery, FindProfileQueryVariables>;

View File

@ -0,0 +1,3 @@
mutation ClearSessionCookie {
clearSessionCookie
}

View File

@ -0,0 +1,3 @@
mutation LogoutUser {
logoutUser
}

View File

@ -0,0 +1,11 @@
query FindNotificationByUser {
findNotificationByUser {
createdAt
id
isRead
text
type
updatedAt
userId
}
}

View File

@ -0,0 +1,3 @@
query FindUnreadNotificationsCount {
findUnreadNotificationsCount
}

View File

@ -0,0 +1,20 @@
query FindProfile {
findProfile {
avatar
bio
createdAt
email
id
name
updatedAt
isEmailVerified
isTotpEnabled
isVerified
displayName
socialLink {
title
url
position
}
}
}

View File

@ -0,0 +1,37 @@
import { useEffect } from 'react';
import {
useClearSessionCookieMutation,
useFindProfileQuery,
} from '@/graphql/generated/output';
import { useAuth } from './useAuth';
export function useCurrent() {
const { isAuthenticated, exit } = useAuth();
const {
data, loading, refetch, error,
} = useFindProfileQuery({
skip: !isAuthenticated,
});
const [clear] = useClearSessionCookieMutation();
useEffect(() => {
if (error) {
console.log('error', error);
if (isAuthenticated) {
console.log('CLEAR');
void clear();
}
console.log('exit');
exit();
}
}, [isAuthenticated, exit, clear]);
return {
user: data?.findProfile,
isLoadingProfile: loading,
refetch,
};
}

View File

@ -0,0 +1,22 @@
import { useEffect, useState } from 'react';
export function useMediaQuery(query: string) {
const [value, setValue] = useState(false);
useEffect(() => {
function onChange(event: MediaQueryListEvent) {
setValue(event.matches);
}
const result = matchMedia(query);
result.addEventListener('change', onChange);
setValue(result.matches);
return () => {
result.removeEventListener('change', onChange);
};
}, [query]);
return value;
}

View File

@ -0,0 +1,22 @@
import { useCallback } from 'react';
import { sidebarStore } from '@/store/sidebar/sidebar.store';
export function useSidebar() {
const isCollapsed = sidebarStore((state) => state.isCollapsed);
const setIsCollapsed = sidebarStore((state) => state.setIsCollapsed);
const open = useCallback(() => {
setIsCollapsed(false);
}, []);
const close = useCallback(() => {
setIsCollapsed(true);
}, []);
return {
isCollapsed,
open,
close,
};
}

View File

@ -1,7 +1,8 @@
import { ApolloClient, createHttpLink, InMemoryCache } from '@apollo/client';
import { SERVER_URL } from './constants/url.constants';
const httpLink = createHttpLink({
uri: process.env.NEXT_PUBLIC_SERVER_URL,
uri: SERVER_URL,
credentials: 'include',
});

View File

@ -0,0 +1,2 @@
export const SERVER_URL = process.env.NEXT_PUBLIC_SERVER_URL as string;
export const MEDIA_URL = process.env.NEXT_PUBLIC_MEDIA_URL as string;

View File

@ -0,0 +1,21 @@
import { create } from 'zustand';
import { createJSONStorage, persist } from 'zustand/middleware';
import type { SidebarStore } from './sidebar.types';
const STORAGE_NAME = 'sidebar';
export const sidebarStore = create(
persist<SidebarStore>(
(set) => ({
isCollapsed: false,
setIsCollapsed: (value: boolean) => {
set({ isCollapsed: value });
},
}),
{
name: STORAGE_NAME,
storage: createJSONStorage(() => localStorage),
},
),
);

View File

@ -0,0 +1,4 @@
export type SidebarStore = {
isCollapsed: boolean;
setIsCollapsed: (value: boolean) => void;
};

View File

@ -0,0 +1,5 @@
import { MEDIA_URL } from '@/libs/constants/url.constants';
export function getMediaSource(path: string | null | undefined) {
return MEDIA_URL + path;
}

View File

@ -0,0 +1,22 @@
import {
Bell, Check, Fingerprint, Medal, Radio, User,
} from 'lucide-react';
import { NotificationType } from '@/graphql/generated/output';
export function getNotificationIcon(type: NotificationType) {
switch (type) {
case NotificationType.StreamStart:
return Radio;
case NotificationType.NewFollower:
return User;
case NotificationType.NewSponsorship:
return Medal;
case NotificationType.EnableTwoFactor:
return Fingerprint;
case NotificationType.VerifiedChannel:
return Check;
default:
return Bell;
}
}

View File

@ -486,6 +486,13 @@
"@babel/helper-string-parser" "^7.27.1"
"@babel/helper-validator-identifier" "^7.27.1"
"@cspotcode/source-map-support@^0.8.0":
version "0.8.1"
resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
"@emnapi/core@^1.4.3":
version "1.4.5"
resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.5.tgz#bfbb0cbbbb9f96ec4e2c4fd917b7bbe5495ceccb"
@ -605,6 +612,33 @@
resolved "https://registry.yarnpkg.com/@fastify/busboy/-/busboy-3.1.1.tgz#af3aea7f1e52ec916d8b5c9dcc0f09d4c060a3fc"
integrity sha512-5DGmA8FTdB2XbDeEwc/5ZXBl6UbBAyBOOLlPuBnZ/N1SwdH9Ii+cOX3tBROlDgcTXxjOYnLMVoKk9+FXAw0CJw==
"@floating-ui/core@^1.7.3":
version "1.7.3"
resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.7.3.tgz#462d722f001e23e46d86fd2bd0d21b7693ccb8b7"
integrity sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==
dependencies:
"@floating-ui/utils" "^0.2.10"
"@floating-ui/dom@^1.7.3":
version "1.7.3"
resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.7.3.tgz#6174ac3409e6a064bbdf1f4bb07188ee9461f8cf"
integrity sha512-uZA413QEpNuhtb3/iIKoYMSK07keHPYeXF02Zhd6e213j+d1NamLix/mCLxBUDW/Gx52sPH2m+chlUsyaBs/Ag==
dependencies:
"@floating-ui/core" "^1.7.3"
"@floating-ui/utils" "^0.2.10"
"@floating-ui/react-dom@^2.0.0":
version "2.1.5"
resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.5.tgz#d11e3726d2eb385d8cf3216348742907c1d49fcf"
integrity sha512-HDO/1/1oH9fjj4eLgegrlH3dklZpHtUYYFiVwMUwfGvk9jWDRWqkklA2/NFScknrcNSspbV868WjXORvreDX+Q==
dependencies:
"@floating-ui/dom" "^1.7.3"
"@floating-ui/utils@^0.2.10":
version "0.2.10"
resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.10.tgz#a2a1e3812d14525f725d011a73eceb41fef5bc1c"
integrity sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==
"@formatjs/ecma402-abstract@2.3.4":
version "2.3.4"
resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.4.tgz#e90c5a846ba2b33d92bc400fdd709da588280fbc"
@ -1360,16 +1394,24 @@
"@jridgewell/sourcemap-codec" "^1.5.0"
"@jridgewell/trace-mapping" "^0.3.24"
"@jridgewell/resolve-uri@^3.1.0":
"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.4"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz#7358043433b2e5da569aa02cbc4c121da3af27d7"
integrity sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==
"@jridgewell/trace-mapping@0.3.9":
version "0.3.9"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
dependencies:
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.28":
version "0.3.29"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz#a58d31eaadaf92c6695680b2e1d464a9b8fbf7fc"
@ -1472,11 +1514,188 @@
resolved "https://registry.yarnpkg.com/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz#3dc35ba0f1e66b403c00b39344f870298ebb1c8e"
integrity sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==
"@parcel/watcher-android-arm64@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.1.tgz#507f836d7e2042f798c7d07ad19c3546f9848ac1"
integrity sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==
"@parcel/watcher-darwin-arm64@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.1.tgz#3d26dce38de6590ef79c47ec2c55793c06ad4f67"
integrity sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==
"@parcel/watcher-darwin-x64@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.1.tgz#99f3af3869069ccf774e4ddfccf7e64fd2311ef8"
integrity sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==
"@parcel/watcher-freebsd-x64@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.1.tgz#14d6857741a9f51dfe51d5b08b7c8afdbc73ad9b"
integrity sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==
"@parcel/watcher-linux-arm-glibc@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.1.tgz#43c3246d6892381db473bb4f663229ad20b609a1"
integrity sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==
"@parcel/watcher-linux-arm-musl@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.1.tgz#663750f7090bb6278d2210de643eb8a3f780d08e"
integrity sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==
"@parcel/watcher-linux-arm64-glibc@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.1.tgz#ba60e1f56977f7e47cd7e31ad65d15fdcbd07e30"
integrity sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==
"@parcel/watcher-linux-arm64-musl@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.1.tgz#f7fbcdff2f04c526f96eac01f97419a6a99855d2"
integrity sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==
"@parcel/watcher-linux-x64-glibc@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.1.tgz#4d2ea0f633eb1917d83d483392ce6181b6a92e4e"
integrity sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==
"@parcel/watcher-linux-x64-musl@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.1.tgz#277b346b05db54f55657301dd77bdf99d63606ee"
integrity sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==
"@parcel/watcher-win32-arm64@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.1.tgz#7e9e02a26784d47503de1d10e8eab6cceb524243"
integrity sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==
"@parcel/watcher-win32-ia32@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.1.tgz#2d0f94fa59a873cdc584bf7f6b1dc628ddf976e6"
integrity sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==
"@parcel/watcher-win32-x64@2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.1.tgz#ae52693259664ba6f2228fa61d7ee44b64ea0947"
integrity sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==
"@parcel/watcher@^2.5.1":
version "2.5.1"
resolved "https://registry.yarnpkg.com/@parcel/watcher/-/watcher-2.5.1.tgz#342507a9cfaaf172479a882309def1e991fb1200"
integrity sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==
dependencies:
detect-libc "^1.0.3"
is-glob "^4.0.3"
micromatch "^4.0.5"
node-addon-api "^7.0.0"
optionalDependencies:
"@parcel/watcher-android-arm64" "2.5.1"
"@parcel/watcher-darwin-arm64" "2.5.1"
"@parcel/watcher-darwin-x64" "2.5.1"
"@parcel/watcher-freebsd-x64" "2.5.1"
"@parcel/watcher-linux-arm-glibc" "2.5.1"
"@parcel/watcher-linux-arm-musl" "2.5.1"
"@parcel/watcher-linux-arm64-glibc" "2.5.1"
"@parcel/watcher-linux-arm64-musl" "2.5.1"
"@parcel/watcher-linux-x64-glibc" "2.5.1"
"@parcel/watcher-linux-x64-musl" "2.5.1"
"@parcel/watcher-win32-arm64" "2.5.1"
"@parcel/watcher-win32-ia32" "2.5.1"
"@parcel/watcher-win32-x64" "2.5.1"
"@radix-ui/primitive@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.2.tgz#83f415c4425f21e3d27914c12b3272a32e3dae65"
integrity sha512-XnbHrrprsNqZKQhStrSwgRUQzoCI1glLzdw79xiZPoofhGICeZRSQ3dIxAKH1gb3OHfNf4d6f+vAv3kil2eggA==
"@radix-ui/react-arrow@1.1.7":
version "1.1.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz#e14a2657c81d961598c5e72b73dd6098acc04f09"
integrity sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==
dependencies:
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-avatar@1.1.10":
version "1.1.10"
resolved "https://registry.yarnpkg.com/@radix-ui/react-avatar/-/react-avatar-1.1.10.tgz#c58a8800ef3d3ee783b3168fee7c76f6534bfd93"
integrity sha512-V8piFfWapM5OmNCXTzVQY+E1rDa53zY+MQ4Y7356v4fFz6vqCyUtIz2rUD44ZEdwg78/jKmMJHj07+C/Z/rcog==
dependencies:
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-is-hydrated" "0.1.0"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-collection@1.1.7":
version "1.1.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.7.tgz#d05c25ca9ac4695cc19ba91f42f686e3ea2d9aec"
integrity sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-slot" "1.2.3"
"@radix-ui/react-compose-refs@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz#a2c4c47af6337048ee78ff6dc0d090b390d2bb30"
integrity sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==
"@radix-ui/react-context@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.2.tgz#61628ef269a433382c364f6f1e3788a6dc213a36"
integrity sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==
"@radix-ui/react-direction@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.1.tgz#39e5a5769e676c753204b792fbe6cf508e550a14"
integrity sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==
"@radix-ui/react-dismissable-layer@1.1.10":
version "1.1.10"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.10.tgz#429b9bada3672c6895a5d6a642aca6ecaf4f18c3"
integrity sha512-IM1zzRV4W3HtVgftdQiiOmA0AdJlCtMLe00FXaHwgt3rAnNsIyDqshvkIW3hj/iu5hu8ERP7KIYki6NkqDxAwQ==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-escape-keydown" "1.1.1"
"@radix-ui/react-dropdown-menu@2.1.15":
version "2.1.15"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.15.tgz#f507320de8e11bc1e671a6ec0c27a7a89e725131"
integrity sha512-mIBnOjgwo9AH3FyKaSWoSu/dYj6VdhJ7frEPiGTeXCdUFHjl9h3mFh2wwhEtINOmYXWhdpf1rY2minFsmaNgVQ==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-menu" "2.1.15"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-use-controllable-state" "1.2.2"
"@radix-ui/react-focus-guards@1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.2.tgz#4ec9a7e50925f7fb661394460045b46212a33bed"
integrity sha512-fyjAACV62oPV925xFCrH8DR5xWhg9KYtJT4s3u54jxp+L/hbpTY2kIeEFFbFe+a/HCE94zGQMZLIpVTPVZDhaA==
"@radix-ui/react-focus-scope@1.1.7":
version "1.1.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz#dfe76fc103537d80bf42723a183773fd07bfb58d"
integrity sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-id@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.1.tgz#1404002e79a03fe062b7e3864aa01e24bd1471f7"
integrity sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-label@2.1.7":
version "2.1.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.7.tgz#ad959ff9c6e4968d533329eb95696e1ba8ad72ab"
@ -1484,6 +1703,83 @@
dependencies:
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-menu@2.1.15":
version "2.1.15"
resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.15.tgz#a1a8f06cab3c309f9998cdbd2b3ad279e42ed483"
integrity sha512-tVlmA3Vb9n8SZSd+YSbuFR66l87Wiy4du+YE+0hzKQEANA+7cWKH1WgqcEX4pXqxUFQKrWQGHdvEfw00TjFiew==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-collection" "1.1.7"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-direction" "1.1.1"
"@radix-ui/react-dismissable-layer" "1.1.10"
"@radix-ui/react-focus-guards" "1.1.2"
"@radix-ui/react-focus-scope" "1.1.7"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-popper" "1.2.7"
"@radix-ui/react-portal" "1.1.9"
"@radix-ui/react-presence" "1.1.4"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-roving-focus" "1.1.10"
"@radix-ui/react-slot" "1.2.3"
"@radix-ui/react-use-callback-ref" "1.1.1"
aria-hidden "^1.2.4"
react-remove-scroll "^2.6.3"
"@radix-ui/react-popover@^1.1.14":
version "1.1.14"
resolved "https://registry.yarnpkg.com/@radix-ui/react-popover/-/react-popover-1.1.14.tgz#5496d1986f0287cdfc77e73f70a887e4cb77ad08"
integrity sha512-ODz16+1iIbGUfFEfKx2HTPKizg2MN39uIOV8MXeHnmdd3i/N9Wt7vU46wbHsqA0xoaQyXVcs0KIlBdOA2Y95bw==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-dismissable-layer" "1.1.10"
"@radix-ui/react-focus-guards" "1.1.2"
"@radix-ui/react-focus-scope" "1.1.7"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-popper" "1.2.7"
"@radix-ui/react-portal" "1.1.9"
"@radix-ui/react-presence" "1.1.4"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-slot" "1.2.3"
"@radix-ui/react-use-controllable-state" "1.2.2"
aria-hidden "^1.2.4"
react-remove-scroll "^2.6.3"
"@radix-ui/react-popper@1.2.7":
version "1.2.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.7.tgz#531cf2eebb3d3270d58f7d8136e4517646429978"
integrity sha512-IUFAccz1JyKcf/RjB552PlWwxjeCJB8/4KxT7EhBHOJM+mN7LdW+B3kacJXILm32xawcMMjb2i0cIZpo+f9kiQ==
dependencies:
"@floating-ui/react-dom" "^2.0.0"
"@radix-ui/react-arrow" "1.1.7"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-use-rect" "1.1.1"
"@radix-ui/react-use-size" "1.1.1"
"@radix-ui/rect" "1.1.1"
"@radix-ui/react-portal@1.1.9":
version "1.1.9"
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.9.tgz#14c3649fe48ec474ac51ed9f2b9f5da4d91c4472"
integrity sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==
dependencies:
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-presence@1.1.4":
version "1.1.4"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.4.tgz#253ac0ad4946c5b4a9c66878335f5cf07c967ced"
integrity sha512-ueDqRbdc4/bkaQT3GIpLQssRlFgWaL/U2z/S31qRwwLWoxHLgry3SIfCwhxeQNbirEUXFa+lq3RL3oBYXtcmIA==
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-primitive@2.1.3":
version "2.1.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz#db9b8bcff49e01be510ad79893fb0e4cda50f1bc"
@ -1491,6 +1787,28 @@
dependencies:
"@radix-ui/react-slot" "1.2.3"
"@radix-ui/react-roving-focus@1.1.10":
version "1.1.10"
resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.10.tgz#46030496d2a490c4979d29a7e1252465e51e4b0b"
integrity sha512-dT9aOXUen9JSsxnMPv/0VqySQf5eDQ6LCk5Sw28kamz8wSOW2bJdlX2Bg5VUIIcV+6XlHpWTIuTPCf/UNIyq8Q==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-collection" "1.1.7"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-direction" "1.1.1"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-controllable-state" "1.2.2"
"@radix-ui/react-separator@^1.1.7":
version "1.1.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.7.tgz#a18bd7fd07c10fda1bba14f2a3032e7b1a2b3470"
integrity sha512-0HEb8R9E8A+jZjvmFCy/J4xhbXy3TV+9XSnGJ3KvTtjlIUy/YQ/p6UYZvi7YbeoeXdyU9+Y3scizK6hkY37baA==
dependencies:
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-slot@1.2.3":
version "1.2.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.2.3.tgz#502d6e354fc847d4169c3bc5f189de777f68cfe1"
@ -1498,6 +1816,89 @@
dependencies:
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-tooltip@1.2.7":
version "1.2.7"
resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz#23612ac7a5e8e1f6829e46d0e0ad94afe3976c72"
integrity sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==
dependencies:
"@radix-ui/primitive" "1.1.2"
"@radix-ui/react-compose-refs" "1.1.2"
"@radix-ui/react-context" "1.1.2"
"@radix-ui/react-dismissable-layer" "1.1.10"
"@radix-ui/react-id" "1.1.1"
"@radix-ui/react-popper" "1.2.7"
"@radix-ui/react-portal" "1.1.9"
"@radix-ui/react-presence" "1.1.4"
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/react-slot" "1.2.3"
"@radix-ui/react-use-controllable-state" "1.2.2"
"@radix-ui/react-visually-hidden" "1.2.3"
"@radix-ui/react-use-callback-ref@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz#62a4dba8b3255fdc5cc7787faeac1c6e4cc58d40"
integrity sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==
"@radix-ui/react-use-controllable-state@1.2.2":
version "1.2.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz#905793405de57d61a439f4afebbb17d0645f3190"
integrity sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==
dependencies:
"@radix-ui/react-use-effect-event" "0.0.2"
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-use-effect-event@0.0.2":
version "0.0.2"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz#090cf30d00a4c7632a15548512e9152217593907"
integrity sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-use-escape-keydown@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz#b3fed9bbea366a118f40427ac40500aa1423cc29"
integrity sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==
dependencies:
"@radix-ui/react-use-callback-ref" "1.1.1"
"@radix-ui/react-use-is-hydrated@0.1.0":
version "0.1.0"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-is-hydrated/-/react-use-is-hydrated-0.1.0.tgz#544da73369517036c77659d7cdd019dc0f5ff9a0"
integrity sha512-U+UORVEq+cTnRIaostJv9AGdV3G6Y+zbVd+12e18jQ5A3c0xL03IhnHuiU4UV69wolOQp5GfR58NW/EgdQhwOA==
dependencies:
use-sync-external-store "^1.5.0"
"@radix-ui/react-use-layout-effect@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz#0c4230a9eed49d4589c967e2d9c0d9d60a23971e"
integrity sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==
"@radix-ui/react-use-rect@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz#01443ca8ed071d33023c1113e5173b5ed8769152"
integrity sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==
dependencies:
"@radix-ui/rect" "1.1.1"
"@radix-ui/react-use-size@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz#6de276ffbc389a537ffe4316f5b0f24129405b37"
integrity sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==
dependencies:
"@radix-ui/react-use-layout-effect" "1.1.1"
"@radix-ui/react-visually-hidden@1.2.3":
version "1.2.3"
resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz#a8c38c8607735dc9f05c32f87ab0f9c2b109efbf"
integrity sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==
dependencies:
"@radix-ui/react-primitive" "2.1.3"
"@radix-ui/rect@1.1.1":
version "1.1.1"
resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.1.tgz#78244efe12930c56fd255d7923865857c41ac8cb"
integrity sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==
"@repeaterjs/repeater@^3.0.4", "@repeaterjs/repeater@^3.0.6":
version "3.0.6"
resolved "https://registry.yarnpkg.com/@repeaterjs/repeater/-/repeater-3.0.6.tgz#be23df0143ceec3c69f8b6c2517971a5578fdaa2"
@ -1664,6 +2065,26 @@
json5 "^2.2.3"
lodash.sortby "^4.7.0"
"@tsconfig/node10@^1.0.7":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2"
integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==
"@tsconfig/node12@^1.0.7":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
"@tsconfig/node14@^1.0.0":
version "1.0.3"
resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
"@tsconfig/node16@^1.0.2":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
"@tybys/wasm-util@^0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.0.tgz#2fd3cd754b94b378734ce17058d0507c45c88369"
@ -2090,7 +2511,14 @@ acorn-jsx@^5.3.2:
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937"
integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==
acorn@^8.15.0:
acorn-walk@^8.1.1:
version "8.3.4"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7"
integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==
dependencies:
acorn "^8.11.0"
acorn@^8.11.0, acorn@^8.15.0, acorn@^8.4.1:
version "8.15.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816"
integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==
@ -2137,11 +2565,23 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
dependencies:
color-convert "^2.0.1"
arg@^4.1.0:
version "4.1.3"
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
argparse@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
aria-hidden@^1.2.4:
version "1.2.6"
resolved "https://registry.yarnpkg.com/aria-hidden/-/aria-hidden-1.2.6.tgz#73051c9b088114c795b1ea414e9c0fff874ffc1a"
integrity sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==
dependencies:
tslib "^2.0.0"
aria-query@^5.3.2:
version "5.3.2"
resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59"
@ -2636,6 +3076,11 @@ cosmiconfig@^8.1.0, cosmiconfig@^8.1.3:
parse-json "^5.2.0"
path-type "^4.0.0"
create-require@^1.1.0:
version "1.1.1"
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
cross-fetch@^3.1.5:
version "3.2.0"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.2.0.tgz#34e9192f53bc757d6614304d9e5e6fb4edb782e3"
@ -2775,11 +3220,26 @@ detect-indent@^6.0.0:
resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-6.1.0.tgz#592485ebbbf6b3b1ab2be175c8393d04ca0d57e6"
integrity sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==
detect-libc@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
integrity sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==
detect-libc@^2.0.3, detect-libc@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8"
integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==
detect-node-es@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/detect-node-es/-/detect-node-es-1.1.0.tgz#163acdf643330caa0b4cd7c21e7ee7755d6fa493"
integrity sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==
diff@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
dir-glob@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f"
@ -2794,6 +3254,36 @@ doctrine@^2.1.0:
dependencies:
esutils "^2.0.2"
dom-serializer@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-2.0.0.tgz#e41b802e1eedf9f6cae183ce5e622d789d7d8e53"
integrity sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.2"
entities "^4.2.0"
domelementtype@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d"
integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==
domhandler@5.0.3, domhandler@^5.0.2, domhandler@^5.0.3:
version "5.0.3"
resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-5.0.3.tgz#cc385f7f751f1d1fc650c21374804254538c7d31"
integrity sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==
dependencies:
domelementtype "^2.3.0"
domutils@^3.2.1:
version "3.2.2"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78"
integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==
dependencies:
dom-serializer "^2.0.0"
domelementtype "^2.3.0"
domhandler "^5.0.3"
dot-case@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/dot-case/-/dot-case-3.0.4.tgz#9b2b670d00a431667a8a75ba29cd1b98809ce751"
@ -2844,6 +3334,16 @@ enhanced-resolve@^5.18.1:
graceful-fs "^4.2.4"
tapable "^2.2.0"
entities@^4.2.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
entities@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.1.tgz#c28c34a43379ca7f61d074130b2f5f7020a30694"
integrity sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@ -3479,6 +3979,11 @@ get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@
hasown "^2.0.2"
math-intrinsics "^1.1.0"
get-nonce@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3"
integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==
get-proto@^1.0.0, get-proto@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1"
@ -3674,6 +4179,34 @@ hoist-non-react-statics@^3.3.2:
dependencies:
react-is "^16.7.0"
html-dom-parser@5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/html-dom-parser/-/html-dom-parser-5.1.1.tgz#9efb2cfa055f6a71de1bb2f07c5b019db5004f9e"
integrity sha512-+o4Y4Z0CLuyemeccvGN4bAO20aauB2N9tFEAep5x4OW34kV4PTarBHm6RL02afYt2BMKcr0D2Agep8S3nJPIBg==
dependencies:
domhandler "5.0.3"
htmlparser2 "10.0.0"
html-react-parser@^5.2.6:
version "5.2.6"
resolved "https://registry.yarnpkg.com/html-react-parser/-/html-react-parser-5.2.6.tgz#547a8820be5c76bc2a10f0bb32dd9119d440438b"
integrity sha512-qcpPWLaSvqXi+TndiHbCa+z8qt0tVzjMwFGFBAa41ggC+ZA5BHaMIeMJla9g3VSp4SmiZb9qyQbmbpHYpIfPOg==
dependencies:
domhandler "5.0.3"
html-dom-parser "5.1.1"
react-property "2.0.2"
style-to-js "1.1.17"
htmlparser2@10.0.0:
version "10.0.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-10.0.0.tgz#77ad249037b66bf8cc99c6e286ef73b83aeb621d"
integrity sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.3"
domutils "^3.2.1"
entities "^6.0.0"
http-proxy-agent@^7.0.0:
version "7.0.2"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
@ -3753,6 +4286,11 @@ inherits@2, inherits@^2.0.3, inherits@^2.0.4:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
inline-style-parser@0.2.4:
version "0.2.4"
resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.2.4.tgz#f4af5fe72e612839fcd453d989a586566d695f22"
integrity sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==
input-otp@1.4.2:
version "1.4.2"
resolved "https://registry.yarnpkg.com/input-otp/-/input-otp-1.4.2.tgz#f4d3d587d0f641729e55029b3b8c4870847f4f07"
@ -4370,6 +4908,11 @@ magic-string@^0.30.17:
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.0"
make-error@^1.1.1:
version "1.3.6"
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
map-cache@^0.2.0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf"
@ -4512,6 +5055,11 @@ no-case@^3.0.4:
lower-case "^2.0.2"
tslib "^2.0.3"
node-addon-api@^7.0.0:
version "7.1.1"
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
node-domexception@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
@ -4899,6 +5447,38 @@ react-is@^16.13.1, react-is@^16.7.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==
react-property@2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/react-property/-/react-property-2.0.2.tgz#d5ac9e244cef564880a610bc8d868bd6f60fdda6"
integrity sha512-+PbtI3VuDV0l6CleQMsx2gtK0JZbZKbpdu5ynr+lbsuvtmgbNcS3VM0tuY2QjFNOcWxvXeHjDpy42RO+4U2rug==
react-remove-scroll-bar@^2.3.7:
version "2.3.8"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==
dependencies:
react-style-singleton "^2.2.2"
tslib "^2.0.0"
react-remove-scroll@^2.6.3:
version "2.7.1"
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz#d2101d414f6d81d7d3bf033f3c1cb4785789f753"
integrity sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==
dependencies:
react-remove-scroll-bar "^2.3.7"
react-style-singleton "^2.2.3"
tslib "^2.1.0"
use-callback-ref "^1.3.3"
use-sidecar "^1.1.3"
react-style-singleton@^2.2.2, react-style-singleton@^2.2.3:
version "2.2.3"
resolved "https://registry.yarnpkg.com/react-style-singleton/-/react-style-singleton-2.2.3.tgz#4265608be69a4d70cfe3047f2c6c88b2c3ace388"
integrity sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==
dependencies:
get-nonce "^1.0.0"
tslib "^2.0.0"
react@19.1.1:
version "19.1.1"
resolved "https://registry.yarnpkg.com/react/-/react-19.1.1.tgz#06d9149ec5e083a67f9a1e39ce97b06a03b644af"
@ -5439,6 +6019,20 @@ strip-json-comments@^3.1.1:
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
style-to-js@1.1.17:
version "1.1.17"
resolved "https://registry.yarnpkg.com/style-to-js/-/style-to-js-1.1.17.tgz#488b1558a8c1fd05352943f088cc3ce376813d83"
integrity sha512-xQcBGDxJb6jjFCTzvQtfiPn6YvvP2O8U1MDIPNfJQlWMYfktPy+iGsHE7cssjs7y84d9fQaK4UF3RIJaAHSoYA==
dependencies:
style-to-object "1.0.9"
style-to-object@1.0.9:
version "1.0.9"
resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-1.0.9.tgz#35c65b713f4a6dba22d3d0c61435f965423653f0"
integrity sha512-G4qppLgKu/k6FwRpHiGiKPaPTFcG3g4wNVX/Qsfu+RqQM30E7Tyu/TEgxcL9PNLF5pdRLwQdE3YKKf+KF2Dzlw==
dependencies:
inline-style-parser "0.2.4"
styled-jsx@5.1.6:
version "5.1.6"
resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.6.tgz#83b90c077e6c6a80f7f5e8781d0f311b2fe41499"
@ -5567,6 +6161,25 @@ ts-log@^2.2.3:
resolved "https://registry.yarnpkg.com/ts-log/-/ts-log-2.2.7.tgz#4f4512144898b77c9984e91587076fcb8518688e"
integrity sha512-320x5Ggei84AxzlXp91QkIGSw5wgaLT6GeAH0KsqDmRZdVWW2OiSeVvElVoatk3f7nicwXlElXsoFkARiGE2yg==
ts-node@10.9.2:
version "10.9.2"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==
dependencies:
"@cspotcode/source-map-support" "^0.8.0"
"@tsconfig/node10" "^1.0.7"
"@tsconfig/node12" "^1.0.7"
"@tsconfig/node14" "^1.0.0"
"@tsconfig/node16" "^1.0.2"
acorn "^8.4.1"
acorn-walk "^8.1.1"
arg "^4.1.0"
create-require "^1.1.0"
diff "^4.0.1"
make-error "^1.1.1"
v8-compile-cache-lib "^3.0.1"
yn "3.1.1"
tsconfig-paths@^3.15.0:
version "3.15.0"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4"
@ -5577,7 +6190,7 @@ tsconfig-paths@^3.15.0:
minimist "^1.2.6"
strip-bom "^3.0.0"
tslib@2, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.3, tslib@^2.8.0, tslib@^2.8.1:
tslib@2, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.5.0, tslib@^2.6.3, tslib@^2.8.0, tslib@^2.8.1:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@ -5767,6 +6380,13 @@ urlpattern-polyfill@^10.0.0:
resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.1.0.tgz#1b2517e614136c73ba32948d5e7a3a063cba8e74"
integrity sha512-IGjKp/o0NL3Bso1PymYURCJxMPNAf/ILOpendP9f5B6e1rTJgdgiOvgfoT8VxCAdY+Wisb9uhGaJJf3yZ2V9nw==
use-callback-ref@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf"
integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==
dependencies:
tslib "^2.0.0"
use-intl@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/use-intl/-/use-intl-4.3.4.tgz#42bb2141480032623ffe412799c62cbdf306ed0f"
@ -5776,11 +6396,29 @@ use-intl@^4.3.4:
"@schummar/icu-type-parser" "1.21.5"
intl-messageformat "^10.5.14"
use-sidecar@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/use-sidecar/-/use-sidecar-1.1.3.tgz#10e7fd897d130b896e2c546c63a5e8233d00efdb"
integrity sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==
dependencies:
detect-node-es "^1.1.0"
tslib "^2.0.0"
use-sync-external-store@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz#55122e2a3edd2a6c106174c27485e0fd59bcfca0"
integrity sha512-Rb46I4cGGVBmjamjphe8L/UnvJD+uPPtTkNvX5mZgqdbavhI4EbgIWJiIHXJ8bc/i9EQGPRh4DwEURJ552Do0A==
util-deprecate@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==
v8-compile-cache-lib@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
wcwidth@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8"
@ -5982,6 +6620,11 @@ yargs@^17.0.0:
y18n "^5.0.5"
yargs-parser "^21.1.1"
yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"