[frontend]: add header, sidebar, dashboard page
This commit is contained in:
parent
8bd66ffe46
commit
7eca41f8fb
@ -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;
|
||||
|
||||
@ -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"
|
||||
}
|
||||
|
||||
19
frontend/src/app/(site)/dashboard/settings/page.tsx
Normal file
19
frontend/src/app/(site)/dashboard/settings/page.tsx
Normal 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;
|
||||
23
frontend/src/app/(site)/layout.tsx
Normal file
23
frontend/src/app/(site)/layout.tsx
Normal 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;
|
||||
19
frontend/src/app/(site)/page.tsx
Normal file
19
frontend/src/app/(site)/page.tsx
Normal 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;
|
||||
@ -1,7 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { redirect } from 'next/navigation';
|
||||
|
||||
export default function Home() {
|
||||
redirect('account/login');
|
||||
}
|
||||
31
frontend/src/components/layout/LayoutContainer.tsx
Normal file
31
frontend/src/components/layout/LayoutContainer.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
13
frontend/src/components/layout/header/Header.tsx
Normal file
13
frontend/src/components/layout/header/Header.tsx
Normal 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>
|
||||
);
|
||||
38
frontend/src/components/layout/header/HeaderMenu.tsx
Normal file
38
frontend/src/components/layout/header/HeaderMenu.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
29
frontend/src/components/layout/header/Logo.tsx
Normal file
29
frontend/src/components/layout/header/Logo.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
90
frontend/src/components/layout/header/ProfileMenu.tsx
Normal file
90
frontend/src/components/layout/header/ProfileMenu.tsx
Normal 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>
|
||||
</>
|
||||
);
|
||||
};
|
||||
44
frontend/src/components/layout/header/Search.tsx
Normal file
44
frontend/src/components/layout/header/Search.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
@ -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>
|
||||
);
|
||||
};
|
||||
@ -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>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
64
frontend/src/components/layout/sidebar/DashboardNav.tsx
Normal file
64
frontend/src/components/layout/sidebar/DashboardNav.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
31
frontend/src/components/layout/sidebar/Sidebar.tsx
Normal file
31
frontend/src/components/layout/sidebar/Sidebar.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
42
frontend/src/components/layout/sidebar/SidebarHeader.tsx
Normal file
42
frontend/src/components/layout/sidebar/SidebarHeader.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
53
frontend/src/components/layout/sidebar/SidebarItem.tsx
Normal file
53
frontend/src/components/layout/sidebar/SidebarItem.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
38
frontend/src/components/layout/sidebar/UserNav.tsx
Normal file
38
frontend/src/components/layout/sidebar/UserNav.tsx
Normal 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>
|
||||
);
|
||||
};
|
||||
@ -0,0 +1,7 @@
|
||||
import type { LucideIcon } from 'lucide-react';
|
||||
|
||||
export type Route = {
|
||||
label: string;
|
||||
href: string;
|
||||
icon: LucideIcon;
|
||||
};
|
||||
@ -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',
|
||||
|
||||
54
frontend/src/components/ui/common/Avatar.tsx
Normal file
54
frontend/src/components/ui/common/Avatar.tsx
Normal 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 };
|
||||
@ -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: {
|
||||
|
||||
@ -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) => (
|
||||
|
||||
210
frontend/src/components/ui/common/DropdownMenu.tsx
Normal file
210
frontend/src/components/ui/common/DropdownMenu.tsx
Normal 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,
|
||||
};
|
||||
@ -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';
|
||||
|
||||
|
||||
@ -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) => (
|
||||
|
||||
@ -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>,
|
||||
|
||||
@ -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',
|
||||
|
||||
37
frontend/src/components/ui/common/Popover.tsx
Normal file
37
frontend/src/components/ui/common/Popover.tsx
Normal 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 };
|
||||
39
frontend/src/components/ui/common/Separator.tsx
Normal file
39
frontend/src/components/ui/common/Separator.tsx
Normal 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 };
|
||||
36
frontend/src/components/ui/common/Tooltip.tsx
Normal file
36
frontend/src/components/ui/common/Tooltip.tsx
Normal 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,
|
||||
};
|
||||
52
frontend/src/components/ui/elements/ChannelAvatar.tsx
Normal file
52
frontend/src/components/ui/elements/ChannelAvatar.tsx
Normal 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>
|
||||
);
|
||||
41
frontend/src/components/ui/elements/Hint.tsx
Normal file
41
frontend/src/components/ui/elements/Hint.tsx
Normal 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>
|
||||
);
|
||||
@ -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>;
|
||||
@ -0,0 +1,3 @@
|
||||
mutation ClearSessionCookie {
|
||||
clearSessionCookie
|
||||
}
|
||||
3
frontend/src/graphql/mutations/auth/LogoutUser.graphql
Normal file
3
frontend/src/graphql/mutations/auth/LogoutUser.graphql
Normal file
@ -0,0 +1,3 @@
|
||||
mutation LogoutUser {
|
||||
logoutUser
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
query FindNotificationByUser {
|
||||
findNotificationByUser {
|
||||
createdAt
|
||||
id
|
||||
isRead
|
||||
text
|
||||
type
|
||||
updatedAt
|
||||
userId
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,3 @@
|
||||
query FindUnreadNotificationsCount {
|
||||
findUnreadNotificationsCount
|
||||
}
|
||||
20
frontend/src/graphql/queries/user/FindProfile.graphql
Normal file
20
frontend/src/graphql/queries/user/FindProfile.graphql
Normal file
@ -0,0 +1,20 @@
|
||||
query FindProfile {
|
||||
findProfile {
|
||||
avatar
|
||||
bio
|
||||
createdAt
|
||||
email
|
||||
id
|
||||
name
|
||||
updatedAt
|
||||
isEmailVerified
|
||||
isTotpEnabled
|
||||
isVerified
|
||||
displayName
|
||||
socialLink {
|
||||
title
|
||||
url
|
||||
position
|
||||
}
|
||||
}
|
||||
}
|
||||
37
frontend/src/hooks/useCurrent.ts
Normal file
37
frontend/src/hooks/useCurrent.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
22
frontend/src/hooks/useMediaQuery.ts
Normal file
22
frontend/src/hooks/useMediaQuery.ts
Normal 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;
|
||||
}
|
||||
22
frontend/src/hooks/useSidebar.ts
Normal file
22
frontend/src/hooks/useSidebar.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
@ -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',
|
||||
});
|
||||
|
||||
|
||||
2
frontend/src/libs/constants/url.constants.ts
Normal file
2
frontend/src/libs/constants/url.constants.ts
Normal 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;
|
||||
21
frontend/src/store/sidebar/sidebar.store.ts
Normal file
21
frontend/src/store/sidebar/sidebar.store.ts
Normal 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),
|
||||
},
|
||||
),
|
||||
);
|
||||
4
frontend/src/store/sidebar/sidebar.types.ts
Normal file
4
frontend/src/store/sidebar/sidebar.types.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export type SidebarStore = {
|
||||
isCollapsed: boolean;
|
||||
setIsCollapsed: (value: boolean) => void;
|
||||
};
|
||||
5
frontend/src/utils/get-media-source.ts
Normal file
5
frontend/src/utils/get-media-source.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { MEDIA_URL } from '@/libs/constants/url.constants';
|
||||
|
||||
export function getMediaSource(path: string | null | undefined) {
|
||||
return MEDIA_URL + path;
|
||||
}
|
||||
22
frontend/src/utils/get-notification-icon.ts
Normal file
22
frontend/src/utils/get-notification-icon.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user