committed by
GitHub
parent
df944bb1e5
commit
14c2220904
@@ -13,7 +13,7 @@
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.48.1",
|
||||
"@types/node": "^22.7.8",
|
||||
"@types/node": "^22.7.9",
|
||||
"node-html-parser": "^6.1.13"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,6 @@ const ModeToggle = dynamic(
|
||||
import('@kit/ui/mode-toggle').then((mod) => ({
|
||||
default: mod.ModeToggle,
|
||||
})),
|
||||
{
|
||||
ssr: false,
|
||||
},
|
||||
);
|
||||
|
||||
const paths = {
|
||||
|
||||
@@ -11,7 +11,7 @@ async function DocsLayout({ children }: React.PropsWithChildren) {
|
||||
const pages = await getDocs(resolvedLanguage);
|
||||
|
||||
return (
|
||||
<div className={'container flex'}>
|
||||
<div className={'md:container flex'}>
|
||||
<DocsNavigation pages={buildDocumentationTree(pages)} />
|
||||
|
||||
{children}
|
||||
|
||||
@@ -1,40 +1,70 @@
|
||||
import { Home, Users } from 'lucide-react';
|
||||
'use client';
|
||||
|
||||
import Link from 'next/link';
|
||||
import { usePathname } from 'next/navigation';
|
||||
|
||||
import { LayoutDashboard, Users } from 'lucide-react';
|
||||
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarGroup,
|
||||
SidebarItem,
|
||||
} from '@kit/ui/sidebar';
|
||||
SidebarGroupContent,
|
||||
SidebarGroupLabel,
|
||||
SidebarHeader,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarProvider,
|
||||
} from '@kit/ui/shadcn-sidebar';
|
||||
|
||||
import { AppLogo } from '~/components/app-logo';
|
||||
import { ProfileAccountDropdownContainer } from '~/components/personal-account-dropdown-container';
|
||||
|
||||
export function AdminSidebar() {
|
||||
const path = usePathname();
|
||||
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<Sidebar>
|
||||
<SidebarContent className={'py-4'}>
|
||||
<SidebarHeader className={'m-2'}>
|
||||
<AppLogo href={'/admin'} />
|
||||
</SidebarContent>
|
||||
</SidebarHeader>
|
||||
|
||||
<SidebarContent className={'mt-5'}>
|
||||
<SidebarGroup label={'Admin'}>
|
||||
<SidebarItem end path={'/admin'} Icon={<Home className={'h-4'} />}>
|
||||
Home
|
||||
</SidebarItem>
|
||||
<SidebarContent>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Admin</SidebarGroupLabel>
|
||||
|
||||
<SidebarItem
|
||||
path={'/admin/accounts'}
|
||||
Icon={<Users className={'h-4'} />}
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuButton isActive={path === '/admin'} asChild>
|
||||
<Link className={'flex gap-2.5'} href={'/admin'}>
|
||||
<LayoutDashboard className={'h-4'} />
|
||||
<span>Dashboard</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
|
||||
<SidebarMenuButton
|
||||
isActive={path.includes('/admin/accounts')}
|
||||
asChild
|
||||
>
|
||||
Accounts
|
||||
</SidebarItem>
|
||||
<Link
|
||||
className={'flex size-full gap-2.5'}
|
||||
href={'/admin/accounts'}
|
||||
>
|
||||
<Users className={'h-4'} />
|
||||
<span>Accounts</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarContent>
|
||||
|
||||
<SidebarContent className={'absolute bottom-4'}>
|
||||
<SidebarFooter>
|
||||
<ProfileAccountDropdownContainer />
|
||||
</SidebarContent>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useContext } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
|
||||
import { AccountSelector } from '@kit/accounts/account-selector';
|
||||
import { SidebarContext } from '@kit/ui/sidebar';
|
||||
import { SidebarContext } from '@kit/ui/shadcn-sidebar';
|
||||
|
||||
import featureFlagsConfig from '~/config/feature-flags.config';
|
||||
import pathsConfig from '~/config/paths.config';
|
||||
@@ -25,11 +25,11 @@ export function HomeAccountSelector(props: {
|
||||
collisionPadding?: number;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const { collapsed } = useContext(SidebarContext);
|
||||
const context = useContext(SidebarContext);
|
||||
|
||||
return (
|
||||
<AccountSelector
|
||||
collapsed={collapsed}
|
||||
collapsed={context?.minimized}
|
||||
collisionPadding={props.collisionPadding ?? 20}
|
||||
accounts={props.accounts}
|
||||
features={features}
|
||||
|
||||
@@ -44,15 +44,6 @@ export function HomeMobileNavigation(props: { workspace: UserWorkspace }) {
|
||||
if ('divider' in item) {
|
||||
return <DropdownMenuSeparator key={index} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownLink
|
||||
key={item.path}
|
||||
Icon={item.Icon}
|
||||
path={item.path}
|
||||
label={item.label}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { If } from '@kit/ui/if';
|
||||
import { Sidebar, SidebarContent, SidebarNavigation } from '@kit/ui/sidebar';
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
SidebarNavigation,
|
||||
SidebarProvider,
|
||||
} from '@kit/ui/shadcn-sidebar';
|
||||
import { cn } from '@kit/ui/utils';
|
||||
|
||||
import { AppLogo } from '~/components/app-logo';
|
||||
@@ -16,21 +23,23 @@ interface HomeSidebarProps {
|
||||
workspace: UserWorkspace;
|
||||
}
|
||||
|
||||
const minimized = personalAccountNavigationConfig.sidebarCollapsed;
|
||||
|
||||
export function HomeSidebar(props: HomeSidebarProps) {
|
||||
const { workspace, user, accounts } = props.workspace;
|
||||
const collapsed = personalAccountNavigationConfig.sidebarCollapsed;
|
||||
|
||||
return (
|
||||
<Sidebar collapsed={collapsed}>
|
||||
<SidebarContent className={'h-16 justify-center'}>
|
||||
<SidebarProvider minimized={minimized}>
|
||||
<Sidebar>
|
||||
<SidebarHeader className={'h-16 justify-center'}>
|
||||
<div className={'flex items-center justify-between space-x-2'}>
|
||||
<If
|
||||
condition={featuresFlagConfig.enableTeamAccounts}
|
||||
fallback={
|
||||
<AppLogo
|
||||
className={cn({
|
||||
'max-w-full': collapsed,
|
||||
'py-2': !collapsed,
|
||||
'max-w-full': minimized,
|
||||
'py-2': !minimized,
|
||||
})}
|
||||
/>
|
||||
}
|
||||
@@ -38,21 +47,20 @@ export function HomeSidebar(props: HomeSidebarProps) {
|
||||
<HomeAccountSelector userId={user.id} accounts={accounts} />
|
||||
</If>
|
||||
|
||||
<div className={'hidden group-aria-[expanded=true]/sidebar:block'}>
|
||||
<div className={'group-data-[minimized=true]:hidden'}>
|
||||
<UserNotifications userId={user.id} />
|
||||
</div>
|
||||
</div>
|
||||
</SidebarContent>
|
||||
</SidebarHeader>
|
||||
|
||||
<SidebarContent className={`mt-5 h-[calc(100%-160px)] overflow-y-auto`}>
|
||||
<SidebarContent>
|
||||
<SidebarNavigation config={personalAccountNavigationConfig} />
|
||||
</SidebarContent>
|
||||
|
||||
<div className={'absolute bottom-4 left-0 w-full'}>
|
||||
<SidebarContent>
|
||||
<SidebarFooter>
|
||||
<ProfileAccountDropdownContainer user={user} account={workspace} />
|
||||
</SidebarContent>
|
||||
</div>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -65,15 +65,6 @@ export const TeamAccountLayoutMobileNavigation = (
|
||||
if ('divider' in item) {
|
||||
return <DropdownMenuSeparator key={index} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<DropdownLink
|
||||
key={item.path}
|
||||
Icon={item.Icon}
|
||||
path={item.path}
|
||||
label={item.label}
|
||||
/>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { SidebarDivider, SidebarGroup, SidebarItem } from '@kit/ui/sidebar';
|
||||
import { Trans } from '@kit/ui/trans';
|
||||
import { SidebarNavigation } from '@kit/ui/shadcn-sidebar';
|
||||
|
||||
import { getTeamAccountSidebarConfig } from '~/config/team-account-navigation.config';
|
||||
|
||||
@@ -8,50 +7,7 @@ export function TeamAccountLayoutSidebarNavigation({
|
||||
}: React.PropsWithChildren<{
|
||||
account: string;
|
||||
}>) {
|
||||
const routes = getTeamAccountSidebarConfig(account).routes;
|
||||
const routes = getTeamAccountSidebarConfig(account);
|
||||
|
||||
return (
|
||||
<>
|
||||
{routes.map((item, index) => {
|
||||
if ('divider' in item) {
|
||||
return <SidebarDivider key={index} />;
|
||||
}
|
||||
|
||||
if ('children' in item) {
|
||||
return (
|
||||
<SidebarGroup
|
||||
key={item.label}
|
||||
label={<Trans i18nKey={item.label} defaults={item.label} />}
|
||||
collapsible={item.collapsible}
|
||||
collapsed={item.collapsed}
|
||||
>
|
||||
{item.children.map((child) => {
|
||||
return (
|
||||
<SidebarItem
|
||||
key={child.path}
|
||||
end={child.end}
|
||||
path={child.path}
|
||||
Icon={child.Icon}
|
||||
>
|
||||
<Trans i18nKey={child.label} defaults={child.label} />
|
||||
</SidebarItem>
|
||||
);
|
||||
})}
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarItem
|
||||
key={item.path}
|
||||
end={item.end}
|
||||
path={item.path}
|
||||
Icon={item.Icon}
|
||||
>
|
||||
<Trans i18nKey={item.label} defaults={item.label} />
|
||||
</SidebarItem>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
return <SidebarNavigation config={routes} />;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
'use client';
|
||||
|
||||
import { useContext } from 'react';
|
||||
|
||||
import type { User } from '@supabase/supabase-js';
|
||||
|
||||
import { Sidebar, SidebarContent, SidebarContext } from '@kit/ui/sidebar';
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
SidebarFooter,
|
||||
SidebarHeader,
|
||||
SidebarProvider,
|
||||
useSidebar,
|
||||
} from '@kit/ui/shadcn-sidebar';
|
||||
import { cn } from '@kit/ui/utils';
|
||||
|
||||
import { ProfileAccountDropdownContainer } from '~/components//personal-account-dropdown-container';
|
||||
@@ -26,17 +31,17 @@ export function TeamAccountLayoutSidebar(props: {
|
||||
accounts: AccountModel[];
|
||||
user: User;
|
||||
}) {
|
||||
const collapsed = getTeamAccountSidebarConfig(props.account).sidebarCollapsed;
|
||||
const minimized = getTeamAccountSidebarConfig(props.account).sidebarCollapsed;
|
||||
|
||||
return (
|
||||
<Sidebar collapsed={collapsed}>
|
||||
<SidebarProvider minimized={minimized}>
|
||||
<SidebarContainer
|
||||
account={props.account}
|
||||
accountId={props.accountId}
|
||||
accounts={props.accounts}
|
||||
user={props.user}
|
||||
/>
|
||||
</Sidebar>
|
||||
</SidebarProvider>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -48,48 +53,44 @@ function SidebarContainer(props: {
|
||||
}) {
|
||||
const { account, accounts, user } = props;
|
||||
const userId = user.id;
|
||||
const { collapsed } = useContext(SidebarContext);
|
||||
const { minimized } = useSidebar();
|
||||
|
||||
const className = cn(
|
||||
'flex max-w-full items-center justify-between space-x-4',
|
||||
{
|
||||
'w-full justify-start space-x-0': collapsed,
|
||||
'w-full justify-start space-x-0': minimized,
|
||||
},
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<SidebarContent className={'h-16 justify-center'}>
|
||||
<Sidebar>
|
||||
<SidebarHeader className={'h-16 justify-center'}>
|
||||
<div className={className}>
|
||||
<TeamAccountAccountsSelector
|
||||
userId={userId}
|
||||
selectedAccount={account}
|
||||
accounts={accounts}
|
||||
collapsed={collapsed}
|
||||
collapsed={minimized}
|
||||
/>
|
||||
|
||||
<div
|
||||
className={cn({
|
||||
hidden: collapsed,
|
||||
})}
|
||||
>
|
||||
<div className="group-data-[minimized=true]:hidden">
|
||||
<TeamAccountNotifications
|
||||
userId={userId}
|
||||
accountId={props.accountId}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarContent>
|
||||
</SidebarHeader>
|
||||
|
||||
<SidebarContent className={`mt-5 h-[calc(100%-160px)] overflow-y-auto`}>
|
||||
<TeamAccountLayoutSidebarNavigation account={account} />
|
||||
</SidebarContent>
|
||||
|
||||
<div className={'absolute bottom-4 left-0 w-full'}>
|
||||
<SidebarFooter>
|
||||
<SidebarContent>
|
||||
<ProfileAccountDropdownContainer user={props.user} />
|
||||
</SidebarContent>
|
||||
</div>
|
||||
</>
|
||||
</SidebarFooter>
|
||||
</Sidebar>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { CreditCard, Home, User } from 'lucide-react';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { NavigationConfigSchema } from '@kit/ui/navigation-schema';
|
||||
|
||||
@@ -8,26 +9,35 @@ import pathsConfig from '~/config/paths.config';
|
||||
const iconClasses = 'w-4';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
label: 'common:routes.application',
|
||||
children: [
|
||||
{
|
||||
label: 'common:routes.home',
|
||||
path: pathsConfig.app.home,
|
||||
Icon: <Home className={iconClasses} />,
|
||||
end: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'common:routes.account',
|
||||
label: 'common:routes.settings',
|
||||
children: [
|
||||
{
|
||||
label: 'common:routes.profile',
|
||||
path: pathsConfig.app.personalAccountSettings,
|
||||
Icon: <User className={iconClasses} />,
|
||||
},
|
||||
];
|
||||
|
||||
if (featureFlagsConfig.enablePersonalAccountBilling) {
|
||||
routes.push({
|
||||
featureFlagsConfig.enablePersonalAccountBilling
|
||||
? {
|
||||
label: 'common:routes.billing',
|
||||
path: pathsConfig.app.personalAccountBilling,
|
||||
Icon: <CreditCard className={iconClasses} />,
|
||||
});
|
||||
}
|
||||
}
|
||||
: undefined,
|
||||
].filter(route => !!route),
|
||||
},
|
||||
] satisfies z.infer<typeof NavigationConfigSchema>['routes'];
|
||||
|
||||
export const personalAccountNavigationConfig = NavigationConfigSchema.parse({
|
||||
routes,
|
||||
|
||||
@@ -8,12 +8,17 @@ import pathsConfig from '~/config/paths.config';
|
||||
const iconClasses = 'w-4';
|
||||
|
||||
const getRoutes = (account: string) => [
|
||||
{
|
||||
label: 'common:routes.application',
|
||||
children: [
|
||||
{
|
||||
label: 'common:routes.dashboard',
|
||||
path: pathsConfig.app.accountHome.replace('[account]', account),
|
||||
Icon: <LayoutDashboard className={iconClasses} />,
|
||||
end: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'common:routes.settings',
|
||||
collapsible: false,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"supabase:db:dump:local": "supabase db dump --local --data-only"
|
||||
},
|
||||
"dependencies": {
|
||||
"@edge-csrf/nextjs": "2.5.0",
|
||||
"@edge-csrf/nextjs": "2.5.1",
|
||||
"@hookform/resolvers": "^3.9.0",
|
||||
"@kit/accounts": "workspace:^",
|
||||
"@kit/admin": "workspace:^",
|
||||
@@ -56,11 +56,11 @@
|
||||
"@marsidev/react-turnstile": "^1.0.2",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-react": "^0.453.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"next-sitemap": "^4.2.3",
|
||||
"next-themes": "0.3.0",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
@@ -77,9 +77,9 @@
|
||||
"@kit/prettier-config": "workspace:^",
|
||||
"@kit/tailwind-config": "workspace:^",
|
||||
"@kit/tsconfig": "workspace:^",
|
||||
"@next/bundle-analyzer": "15.0.0",
|
||||
"@next/bundle-analyzer": "15.0.1",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^22.7.8",
|
||||
"@types/node": "^22.7.9",
|
||||
"@types/react": "npm:types-react@19.0.0-rc.1",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
|
||||
"autoprefixer": "^10.4.20",
|
||||
@@ -89,7 +89,7 @@
|
||||
"import-in-the-middle": "1.11.2",
|
||||
"prettier": "^3.3.3",
|
||||
"require-in-the-middle": "7.4.0",
|
||||
"supabase": "^1.207.8",
|
||||
"supabase": "^1.207.9",
|
||||
"tailwindcss": "3.4.14",
|
||||
"typescript": "^5.6.3"
|
||||
},
|
||||
|
||||
@@ -62,7 +62,8 @@
|
||||
"billing": "Billing",
|
||||
"dashboard": "Dashboard",
|
||||
"settings": "Settings",
|
||||
"profile": "Profile"
|
||||
"profile": "Profile",
|
||||
"application": "Application"
|
||||
},
|
||||
"roles": {
|
||||
"owner": {
|
||||
|
||||
@@ -24,11 +24,21 @@
|
||||
--input: 214.3 31.8% 91.4%;
|
||||
--ring: 224 71.4% 4.1%;
|
||||
--radius: 0.5rem;
|
||||
|
||||
--chart-1: 12 76% 61%;
|
||||
--chart-2: 173 58% 39%;
|
||||
--chart-3: 197 37% 24%;
|
||||
--chart-4: 43 74% 66%;
|
||||
--chart-5: 27 87% 67%;
|
||||
|
||||
--sidebar-background: 0 0% 98%;
|
||||
--sidebar-foreground: 240 5.3% 26.1%;
|
||||
--sidebar-primary: 240 5.9% 10%;
|
||||
--sidebar-primary-foreground: 0 0% 98%;
|
||||
--sidebar-accent: 240 4.8% 95.9%;
|
||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
||||
--sidebar-border: 220 13% 91%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
}
|
||||
|
||||
.dark {
|
||||
@@ -51,11 +61,21 @@
|
||||
--border: 215 27.9% 13%;
|
||||
--input: 215 27.9% 13%;
|
||||
--ring: 216 12.2% 83.9%;
|
||||
|
||||
--chart-1: 220 70% 50%;
|
||||
--chart-2: 160 60% 45%;
|
||||
--chart-3: 30 80% 55%;
|
||||
--chart-4: 280 65% 60%;
|
||||
--chart-5: 340 75% 55%;
|
||||
|
||||
--sidebar-background: 224 71.4% 4.1%;
|
||||
--sidebar-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-primary: 224.3 76.3% 48%;
|
||||
--sidebar-primary-foreground: 0 0% 100%;
|
||||
--sidebar-accent: 215 27.9% 13%;
|
||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
||||
--sidebar-border: 240 3.7% 15.9%;
|
||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tailwind-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@types/node": "^22.7.8"
|
||||
"@types/node": "^22.7.9"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
"@types/react": "^18.3.11",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-react": "^0.453.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-hook-form": "^7.53.1",
|
||||
"react-i18next": "^15.1.0",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:^",
|
||||
"@types/react": "^18.3.11",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
"@kit/ui": "workspace:^",
|
||||
"@types/react": "^18.3.11",
|
||||
"date-fns": "^4.1.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/wordpress": "workspace:^",
|
||||
"@types/node": "^22.7.8"
|
||||
"@types/node": "^22.7.9"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"root": true,
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
"./route-handler": "./src/keystatic-route-handler.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keystatic/core": "0.5.38",
|
||||
"@keystatic/core": "0.5.39",
|
||||
"@keystatic/next": "^5.0.1",
|
||||
"@markdoc/markdoc": "^0.4.0"
|
||||
},
|
||||
@@ -26,7 +26,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:^",
|
||||
"@types/node": "^22.7.8",
|
||||
"@types/node": "^22.7.9",
|
||||
"@types/react": "^18.3.11",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"zod": "^3.23.8"
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:^",
|
||||
"@types/node": "^22.7.8",
|
||||
"@types/node": "^22.7.9",
|
||||
"@types/react": "^18.3.11",
|
||||
"wp-types": "^4.66.1"
|
||||
},
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
"@kit/ui": "workspace:^",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@types/react": "^18.3.11",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"lucide-react": "^0.453.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"next-themes": "0.3.0",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-dom": "19.0.0-rc-69d4b800-20241021",
|
||||
|
||||
@@ -86,7 +86,7 @@ export function AccountSelector({
|
||||
pictureUrl ? (
|
||||
<UserAvatar pictureUrl={pictureUrl} />
|
||||
) : (
|
||||
<PersonIcon className="h-4 min-h-4 w-4 min-w-4" />
|
||||
<PersonIcon className="h-5 min-h-5 w-5 min-w-5" />
|
||||
);
|
||||
|
||||
return (
|
||||
@@ -103,7 +103,7 @@ export function AccountSelector({
|
||||
'dark:shadow-primary/10 group w-full min-w-0 px-2 lg:w-auto lg:max-w-fit',
|
||||
{
|
||||
'justify-start': !collapsed,
|
||||
'm-auto justify-center px-4 lg:w-full': collapsed,
|
||||
'm-auto justify-center px-2 lg:w-full': collapsed,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
@@ -111,7 +111,7 @@ export function AccountSelector({
|
||||
<If
|
||||
condition={selected}
|
||||
fallback={
|
||||
<span className={'flex max-w-full items-center space-x-2'}>
|
||||
<span className={'flex max-w-full items-center space-x-4'}>
|
||||
<PersonalAccountAvatar />
|
||||
|
||||
<span
|
||||
@@ -125,11 +125,11 @@ export function AccountSelector({
|
||||
}
|
||||
>
|
||||
{(account) => (
|
||||
<span className={'flex max-w-full items-center space-x-2'}>
|
||||
<Avatar className={'h-5 w-5'}>
|
||||
<span className={'flex max-w-full items-center space-x-4'}>
|
||||
<Avatar className={'h-6 w-6 rounded-sm'}>
|
||||
<AvatarImage src={account.image ?? undefined} />
|
||||
|
||||
<AvatarFallback className={'group-hover:bg-background'}>
|
||||
<AvatarFallback className={'group-hover:bg-background rounded-sm'}>
|
||||
{account.label ? account.label[0] : ''}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
@@ -210,11 +210,11 @@ export function AccountSelector({
|
||||
}}
|
||||
>
|
||||
<div className={'flex items-center'}>
|
||||
<Avatar className={'mr-2 h-5 w-5'}>
|
||||
<Avatar className={'mr-2 h-6 w-6 rounded-sm'}>
|
||||
<AvatarImage src={account.image ?? undefined} />
|
||||
|
||||
<AvatarFallback
|
||||
className={cn({
|
||||
className={cn('rounded-sm', {
|
||||
['bg-background']: value === account.value,
|
||||
['group-hover:bg-background']:
|
||||
value !== account.value,
|
||||
@@ -274,7 +274,7 @@ export function AccountSelector({
|
||||
|
||||
function UserAvatar(props: { pictureUrl?: string }) {
|
||||
return (
|
||||
<Avatar className={'h-6 w-6'}>
|
||||
<Avatar className={'h-6 w-6 rounded-sm'}>
|
||||
<AvatarImage src={props.pictureUrl} />
|
||||
</Avatar>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,7 @@ import Link from 'next/link';
|
||||
import type { User } from '@supabase/supabase-js';
|
||||
|
||||
import {
|
||||
EllipsisVertical,
|
||||
ChevronsUpDown,
|
||||
Home,
|
||||
LogOut,
|
||||
MessageCircleQuestion,
|
||||
@@ -85,16 +85,17 @@ export function PersonalAccountDropdown({
|
||||
aria-label="Open your profile menu"
|
||||
data-test={'account-dropdown-trigger'}
|
||||
className={cn(
|
||||
'animate-in fade-in group flex cursor-pointer items-center focus:outline-none',
|
||||
'animate-in fade-in focus:outline-primary flex cursor-pointer items-center duration-500 group-data-[minimized=true]:px-0',
|
||||
className ?? '',
|
||||
{
|
||||
['active:bg-secondary/50 items-center space-x-2.5 rounded-md' +
|
||||
['active:bg-secondary/50 items-center space-x-4 rounded-md' +
|
||||
' hover:bg-secondary p-2 transition-colors']: showProfileName,
|
||||
},
|
||||
)}
|
||||
>
|
||||
<ProfileAvatar
|
||||
className={'group-hover:border-primary/10 border border-transparent'}
|
||||
className={'rounded-md'}
|
||||
fallbackClassName={'rounded-md border'}
|
||||
displayName={displayName ?? user?.email ?? ''}
|
||||
pictureUrl={personalAccountData?.picture_url}
|
||||
/>
|
||||
@@ -102,7 +103,7 @@ export function PersonalAccountDropdown({
|
||||
<If condition={showProfileName}>
|
||||
<div
|
||||
className={
|
||||
'fade-in animate-in flex w-full flex-col truncate text-left'
|
||||
'fade-in animate-in flex w-full flex-col truncate text-left group-data-[minimized=true]:hidden'
|
||||
}
|
||||
>
|
||||
<span
|
||||
@@ -120,17 +121,15 @@ export function PersonalAccountDropdown({
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<EllipsisVertical
|
||||
className={'text-muted-foreground mr-1 hidden h-8 group-hover:flex'}
|
||||
<ChevronsUpDown
|
||||
className={
|
||||
'text-muted-foreground mr-1 h-8 group-data-[minimized=true]:hidden'
|
||||
}
|
||||
/>
|
||||
</If>
|
||||
</DropdownMenuTrigger>
|
||||
|
||||
<DropdownMenuContent
|
||||
className={'xl:!min-w-[15rem]'}
|
||||
collisionPadding={{ right: 20, left: 20 }}
|
||||
sideOffset={10}
|
||||
>
|
||||
<DropdownMenuContent className={'xl:!min-w-[15rem]'}>
|
||||
<DropdownMenuItem className={'!h-10 rounded-none'}>
|
||||
<div
|
||||
className={'flex flex-col justify-start truncate text-left text-xs'}
|
||||
|
||||
@@ -22,11 +22,11 @@
|
||||
"@makerkit/data-loader-supabase-core": "^0.0.8",
|
||||
"@makerkit/data-loader-supabase-nextjs": "^1.2.3",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@types/react": "^18.3.11",
|
||||
"lucide-react": "^0.453.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-dom": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-hook-form": "^7.53.1",
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
"@marsidev/react-turnstile": "^1.0.2",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@types/react": "^18.3.11",
|
||||
"lucide-react": "^0.453.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react-hook-form": "^7.53.1",
|
||||
"react-i18next": "^15.1.0",
|
||||
"sonner": "^1.5.0",
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:*",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@types/react": "^18.3.11",
|
||||
"lucide-react": "^0.453.0",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
|
||||
@@ -33,14 +33,14 @@
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@kit/ui": "workspace:^",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@types/react": "^18.3.11",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"lucide-react": "^0.453.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-dom": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-hook-form": "^7.53.1",
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
"@kit/shared": "workspace:^",
|
||||
"@kit/tailwind-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"react-i18next": "^15.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"i18next": "^23.16.2",
|
||||
"i18next-browser-languagedetector": "8.0.0",
|
||||
"i18next-resources-to-backend": "^1.2.1",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"react-dom": "19.0.0-rc-69d4b800-20241021"
|
||||
},
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
"@kit/resend": "workspace:^",
|
||||
"@kit/tailwind-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@types/node": "^22.7.8",
|
||||
"@types/node": "^22.7.9",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"@kit/prettier-config": "workspace:*",
|
||||
"@kit/tailwind-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@types/node": "^22.7.8",
|
||||
"@types/node": "^22.7.9",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"@kit/tailwind-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"zod": "^3.23.8"
|
||||
},
|
||||
"eslintConfig": {
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@supabase/ssr": "^0.5.1",
|
||||
"@supabase/supabase-js": "^2.45.6",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@types/react": "^18.3.11",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"react": "19.0.0-rc-69d4b800-20241021",
|
||||
"server-only": "^0.0.1",
|
||||
"zod": "^3.23.8"
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"@radix-ui/react-alert-dialog": "^1.1.2",
|
||||
"@radix-ui/react-avatar": "^1.1.1",
|
||||
"@radix-ui/react-checkbox": "^1.1.2",
|
||||
"@radix-ui/react-collapsible": "1.1.1",
|
||||
"@radix-ui/react-dialog": "^1.1.2",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.2",
|
||||
"@radix-ui/react-label": "^2.1.0",
|
||||
@@ -42,14 +43,14 @@
|
||||
"@kit/tailwind-config": "workspace:*",
|
||||
"@kit/tsconfig": "workspace:*",
|
||||
"@radix-ui/react-icons": "^1.3.0",
|
||||
"@tanstack/react-query": "5.59.15",
|
||||
"@tanstack/react-query": "5.59.16",
|
||||
"@tanstack/react-table": "^8.20.5",
|
||||
"@types/react": "^18.3.11",
|
||||
"@types/react-dom": "^18.3.1",
|
||||
"class-variance-authority": "^0.7.0",
|
||||
"date-fns": "^4.1.0",
|
||||
"eslint": "^8.57.0",
|
||||
"next": "15.0.0",
|
||||
"next": "15.0.1",
|
||||
"next-themes": "0.3.0",
|
||||
"prettier": "^3.3.3",
|
||||
"react-day-picker": "^8.10.1",
|
||||
@@ -103,6 +104,8 @@
|
||||
"./switch": "./src/shadcn/switch.tsx",
|
||||
"./breadcrumb": "./src/shadcn/breadcrumb.tsx",
|
||||
"./chart": "./src/shadcn/chart.tsx",
|
||||
"./skeleton": "./src/shadcn/skeleton.tsx",
|
||||
"./shadcn-sidebar": "./src/shadcn/sidebar.tsx",
|
||||
"./utils": "./src/lib/utils/index.ts",
|
||||
"./if": "./src/makerkit/if.tsx",
|
||||
"./trans": "./src/makerkit/trans.tsx",
|
||||
|
||||
21
packages/ui/src/hooks/use-mobile.tsx
Normal file
21
packages/ui/src/hooks/use-mobile.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import * as React from 'react';
|
||||
|
||||
const MOBILE_BREAKPOINT = 768;
|
||||
|
||||
export function useIsMobile() {
|
||||
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(
|
||||
undefined,
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
|
||||
const onChange = () => {
|
||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
||||
};
|
||||
mql.addEventListener('change', onChange);
|
||||
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
||||
return () => mql.removeEventListener('change', onChange);
|
||||
}, []);
|
||||
|
||||
return !!isMobile;
|
||||
}
|
||||
@@ -5,6 +5,30 @@ const RouteMatchingEnd = z
|
||||
.default(false)
|
||||
.optional();
|
||||
|
||||
const Divider = z.object({
|
||||
divider: z.literal(true),
|
||||
});
|
||||
|
||||
const RouteChildren = z.array(
|
||||
z.object({
|
||||
label: z.string(),
|
||||
path: z.string(),
|
||||
Icon: z.custom<React.ReactNode>(),
|
||||
end: RouteMatchingEnd,
|
||||
children: z
|
||||
.array(
|
||||
z.object({
|
||||
label: z.string(),
|
||||
path: z.string(),
|
||||
Icon: z.custom<React.ReactNode>(),
|
||||
end: RouteMatchingEnd,
|
||||
}),
|
||||
)
|
||||
.default([])
|
||||
.optional(),
|
||||
}),
|
||||
);
|
||||
|
||||
export const NavigationConfigSchema = z.object({
|
||||
style: z.enum(['custom', 'sidebar', 'header']).default('sidebar'),
|
||||
sidebarCollapsed: z
|
||||
@@ -14,28 +38,14 @@ export const NavigationConfigSchema = z.object({
|
||||
.transform((value) => value === `true`),
|
||||
routes: z.array(
|
||||
z.union([
|
||||
z.object({
|
||||
label: z.string(),
|
||||
path: z.string(),
|
||||
Icon: z.custom<React.ReactNode>(),
|
||||
end: RouteMatchingEnd,
|
||||
}),
|
||||
z.object({
|
||||
label: z.string(),
|
||||
collapsible: z.boolean().optional(),
|
||||
collapsed: z.boolean().optional(),
|
||||
children: z.array(
|
||||
z.object({
|
||||
label: z.string(),
|
||||
path: z.string(),
|
||||
Icon: z.custom<React.ReactNode>(),
|
||||
end: RouteMatchingEnd,
|
||||
}),
|
||||
),
|
||||
}),
|
||||
z.object({
|
||||
divider: z.literal(true),
|
||||
children: RouteChildren,
|
||||
renderAction: z.custom<React.ReactNode>().optional(),
|
||||
}),
|
||||
Divider,
|
||||
]),
|
||||
),
|
||||
});
|
||||
|
||||
@@ -29,12 +29,7 @@ function PageWithSidebar(props: PageProps) {
|
||||
const { Navigation, Children, MobileNavigation } = getSlotsFromPage(props);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
'flex bg-gray-50/95 dark:bg-background/85',
|
||||
props.className,
|
||||
)}
|
||||
>
|
||||
<div className={cn('flex', props.className)}>
|
||||
{Navigation}
|
||||
|
||||
<div
|
||||
@@ -47,7 +42,7 @@ function PageWithSidebar(props: PageProps) {
|
||||
|
||||
<div
|
||||
className={
|
||||
'flex flex-1 flex-col overflow-y-auto bg-background px-4 lg:m-1.5 lg:ml-0 lg:rounded-lg lg:border lg:px-0'
|
||||
'flex flex-1 flex-col overflow-y-auto bg-background px-4 lg:px-0'
|
||||
}
|
||||
>
|
||||
{Children}
|
||||
|
||||
@@ -12,6 +12,7 @@ type TextProps = {
|
||||
|
||||
type ProfileAvatarProps = (SessionProps | TextProps) & {
|
||||
className?: string;
|
||||
fallbackClassName?: string;
|
||||
};
|
||||
|
||||
export function ProfileAvatar(props: ProfileAvatarProps) {
|
||||
@@ -23,8 +24,13 @@ export function ProfileAvatar(props: ProfileAvatarProps) {
|
||||
if ('text' in props) {
|
||||
return (
|
||||
<Avatar className={avatarClassName}>
|
||||
<AvatarFallback>
|
||||
<span className={'uppercase'}>{props.text.slice(0, 1)}</span>
|
||||
<AvatarFallback
|
||||
className={cn(
|
||||
props.fallbackClassName,
|
||||
'uppercase animate-in fade-in',
|
||||
)}
|
||||
>
|
||||
{props.text.slice(0, 1)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
);
|
||||
@@ -36,7 +42,9 @@ export function ProfileAvatar(props: ProfileAvatarProps) {
|
||||
<Avatar className={avatarClassName}>
|
||||
<AvatarImage src={props.pictureUrl ?? undefined} />
|
||||
|
||||
<AvatarFallback className={'animate-in fade-in'}>
|
||||
<AvatarFallback
|
||||
className={cn(props.fallbackClassName, 'animate-in fade-in')}
|
||||
>
|
||||
<span suppressHydrationWarning className={'uppercase'}>
|
||||
{initials}
|
||||
</span>
|
||||
|
||||
@@ -26,6 +26,11 @@ export type SidebarConfig = z.infer<typeof NavigationConfigSchema>;
|
||||
|
||||
export { SidebarContext };
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* This component is deprecated and will be removed in a future version.
|
||||
* Please use the Shadcn Sidebar component instead.
|
||||
*/
|
||||
export function Sidebar(props: {
|
||||
collapsed?: boolean;
|
||||
expandOnHover?: boolean;
|
||||
@@ -338,17 +343,6 @@ export function SidebarNavigation({
|
||||
</SidebarGroup>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<SidebarItem
|
||||
key={item.path}
|
||||
end={item.end}
|
||||
path={item.path}
|
||||
Icon={item.Icon}
|
||||
>
|
||||
<Trans i18nKey={item.label} defaults={item.label} />
|
||||
</SidebarItem>
|
||||
);
|
||||
})}
|
||||
</>
|
||||
);
|
||||
|
||||
11
packages/ui/src/shadcn/collapsible.tsx
Normal file
11
packages/ui/src/shadcn/collapsible.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
|
||||
|
||||
const Collapsible = CollapsiblePrimitive.Root
|
||||
|
||||
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
|
||||
|
||||
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
|
||||
|
||||
export { Collapsible, CollapsibleTrigger, CollapsibleContent }
|
||||
@@ -3,9 +3,8 @@
|
||||
import * as React from 'react';
|
||||
|
||||
import * as SheetPrimitive from '@radix-ui/react-dialog';
|
||||
import { cva } from 'class-variance-authority';
|
||||
import type { VariantProps } from 'class-variance-authority';
|
||||
import { X } from 'lucide-react';
|
||||
import { Cross2Icon } from '@radix-ui/react-icons';
|
||||
import { type VariantProps, cva } from 'class-variance-authority';
|
||||
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
@@ -33,7 +32,7 @@ const SheetOverlay = React.forwardRef<
|
||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
||||
|
||||
const sheetVariants = cva(
|
||||
'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
|
||||
'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out',
|
||||
{
|
||||
variants: {
|
||||
side: {
|
||||
@@ -66,11 +65,11 @@ const SheetContent = React.forwardRef<
|
||||
className={cn(sheetVariants({ side }), className)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
|
||||
<X className="h-4 w-4" />
|
||||
<Cross2Icon className="h-4 w-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
{children}
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
));
|
||||
|
||||
1033
packages/ui/src/shadcn/sidebar.tsx
Normal file
1033
packages/ui/src/shadcn/sidebar.tsx
Normal file
File diff suppressed because it is too large
Load Diff
15
packages/ui/src/shadcn/skeleton.tsx
Normal file
15
packages/ui/src/shadcn/skeleton.tsx
Normal file
@@ -0,0 +1,15 @@
|
||||
import { cn } from '../lib/utils';
|
||||
|
||||
function Skeleton({
|
||||
className,
|
||||
...props
|
||||
}: React.HTMLAttributes<HTMLDivElement>) {
|
||||
return (
|
||||
<div
|
||||
className={cn('animate-pulse rounded-md bg-primary/10', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export { Skeleton };
|
||||
762
pnpm-lock.yaml
generated
762
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -20,7 +20,7 @@
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-config-turbo": "^2.2.3",
|
||||
"eslint-plugin-import": "^2.31.0",
|
||||
"eslint-plugin-react": "7.37.1",
|
||||
"eslint-plugin-react": "7.37.2",
|
||||
"eslint-plugin-react-hooks": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -23,7 +23,7 @@ const config = {
|
||||
'^~/(.*)$', // app-specific imports
|
||||
'^[./]', // relative imports
|
||||
],
|
||||
tailwindFunctions: ['tw', 'clsx', 'cn'],
|
||||
tailwindFunctions: ['tw', 'clsx', 'cn', 'cva'],
|
||||
importOrderSeparation: true,
|
||||
importOrderSortSpecifiers: true,
|
||||
plugins: [
|
||||
|
||||
@@ -60,6 +60,16 @@ export default {
|
||||
DEFAULT: 'hsl(var(--card) / <alpha-value>)',
|
||||
foreground: 'hsl(var(--card-foreground) / <alpha-value>)',
|
||||
},
|
||||
sidebar: {
|
||||
DEFAULT: 'hsl(var(--sidebar-background))',
|
||||
foreground: 'hsl(var(--sidebar-foreground))',
|
||||
primary: 'hsl(var(--sidebar-primary))',
|
||||
'primary-foreground': 'hsl(var(--sidebar-primary-foreground))',
|
||||
accent: 'hsl(var(--sidebar-accent))',
|
||||
'accent-foreground': 'hsl(var(--sidebar-accent-foreground))',
|
||||
border: 'hsl(var(--sidebar-border))',
|
||||
ring: 'hsl(var(--sidebar-ring))',
|
||||
},
|
||||
},
|
||||
borderRadius: {
|
||||
lg: `var(--radius)`,
|
||||
|
||||
Reference in New Issue
Block a user