working on the frontend, adding torrent page, working on show directory, working on the api

This commit is contained in:
maxDorninger
2025-05-11 10:59:38 +02:00
parent 180771882d
commit ef7b020043
164 changed files with 5389 additions and 1594 deletions

View File

@@ -1,122 +1,107 @@
<script lang="ts" module>
import BookOpen from "@lucide/svelte/icons/book-open";
import Bot from "@lucide/svelte/icons/bot";
import Settings2 from "@lucide/svelte/icons/settings-2";
import SquareTerminal from "@lucide/svelte/icons/square-terminal";
import LifeBuoy from '@lucide/svelte/icons/life-buoy';
import Send from '@lucide/svelte/icons/send';
import TvIcon from '@lucide/svelte/icons/tv';
import LayoutPanelLeft from '@lucide/svelte/icons/layout-panel-left';
import DownloadIcon from '@lucide/svelte/icons/download';
const data = {
navMain: [
{
title: "Playground",
url: "#",
icon: SquareTerminal,
isActive: true,
items: [
{
title: "History",
url: "#",
},
{
title: "Starred",
url: "#",
},
{
title: "Settings",
url: "#",
},
],
},
{
title: "Models",
url: "#",
icon: Bot,
items: [
{
title: "Genesis",
url: "#",
},
{
title: "Explorer",
url: "#",
},
{
title: "Quantum",
url: "#",
},
],
},
{
title: "Documentation",
url: "#",
icon: BookOpen,
items: [
{
title: "Introduction",
url: "#",
},
{
title: "Get Started",
url: "#",
},
{
title: "Tutorials",
url: "#",
},
{
title: "Changelog",
url: "#",
},
],
},
{
title: "Settings",
url: "#",
icon: Settings2,
items: [
{
title: "General",
url: "#",
},
{
title: "Team",
url: "#",
},
{
title: "Billing",
url: "#",
},
{
title: "Limits",
url: "#",
},
],
},
],
};
const data = {
navMain: [
{
title: 'TV',
url: '#',
icon: TvIcon,
isActive: true,
items: [
{
title: 'Shows',
url: '/dashboard/tv'
},
{
title: 'Add Show',
url: '/dashboard/tv/add-show'
},
{
title: 'Settings',
url: '#'
}
]
},
{
title: 'Torrents',
url: '#',
icon: DownloadIcon,
isActive: true,
items: [
{
title: 'Show Torrents',
url: '/dashboard/torrents'
}
]
}
],
navSecondary: [
{
title: 'Support',
url: '#',
icon: LifeBuoy
},
{
title: 'Feedback',
url: '#',
icon: Send
}
],
projects: [
{
name: 'Dashboard',
url: '/dashboard',
icon: LayoutPanelLeft
}
]
};
</script>
<script lang="ts">
import NavMain from "$lib/components/nav-main.svelte";
import NavUser from "$lib/components/nav-user.svelte";
import * as Sidebar from "$lib/components/ui/sidebar/index.js";
import type {ComponentProps} from "svelte";
import NavMain from '$lib/components/nav-main.svelte';
import NavProjects from '$lib/components/nav-projects.svelte';
import NavSecondary from '$lib/components/nav-secondary.svelte';
import NavUser from '$lib/components/nav-user.svelte';
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
import Command from '@lucide/svelte/icons/command';
import type {ComponentProps} from 'svelte';
let {
ref = $bindable(null),
collapsible = "icon",
...restProps
}: ComponentProps<typeof Sidebar.Root> = $props();
let {ref = $bindable(null), ...restProps}: ComponentProps<typeof Sidebar.Root> = $props();
</script>
<Sidebar.Root {...restProps} bind:ref {collapsible}>
<Sidebar.Header>
<h1 class="font-bold">MediaManager</h1>
</Sidebar.Header>
<Sidebar.Content>
<NavMain items={data.navMain}/>
</Sidebar.Content>
<Sidebar.Footer>
<NavUser user={data.user}/>
</Sidebar.Footer>
<Sidebar.Rail/>
<Sidebar.Root bind:ref variant="inset" {...restProps}>
<Sidebar.Header>
<Sidebar.Menu>
<Sidebar.MenuItem>
<Sidebar.MenuButton size="lg">
{#snippet child({props})}
<a href="##" {...props}>
<div
class="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground"
>
<Command class="size-4"/>
</div>
<div class="grid flex-1 text-left text-sm leading-tight">
<span class="truncate font-semibold">Acme Inc</span>
<span class="truncate text-xs">Enterprise</span>
</div>
</a>
{/snippet}
</Sidebar.MenuButton>
</Sidebar.MenuItem>
</Sidebar.Menu>
</Sidebar.Header>
<Sidebar.Content>
<NavMain items={data.navMain}/>
<NavProjects projects={data.projects}/>
<NavSecondary items={data.navSecondary} class="mt-auto"/>
</Sidebar.Content>
<Sidebar.Footer>
<NavUser/>
</Sidebar.Footer>
</Sidebar.Root>

View File

@@ -0,0 +1,67 @@
<script lang="ts">
import {cn} from '$lib/utils'; // Assuming you have the cn utility from shadcn-svelte
let {
label,
variant = 'default',
size = 'default',
onClose = undefined,
class: className = ''
} = $props<{
label: string;
variant?: 'default' | 'secondary' | 'outline' | 'destructive';
size?: 'default' | 'sm' | 'lg';
onClose?: () => void;
class?: string;
}>();
// Base styles for the chip
const baseStyles =
'inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50';
// Variant styles
const variantStyles = {
default:
'border bg-background text-foreground shadow-sm hover:bg-accent hover:text-accent-foreground',
secondary: 'bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80',
outline:
'border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground',
destructive: 'bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90'
};
// Size styles
const sizeStyles = {
default: 'h-9 px-3 py-0.5', // Adjusted height for New York style
sm: 'h-7 px-2 py-0.5 text-xs', // Adjusted height for New York style
lg: 'h-10 px-4 py-0.5' // Adjusted height for New York style
};
// Styles for the close button
const closeButtonStyles =
'ml-1 inline-flex h-4 w-4 shrink-0 items-center justify-center rounded-full';
</script>
<div class={cn(baseStyles, variantStyles[variant], sizeStyles[size], className)}>
{label}
{#if onClose}
<button
class={cn(closeButtonStyles, 'hover:bg-accent-foreground/20')}
onclick={onClose}
aria-label="remove tag"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
class="h-3 w-3"
>
<path d="M18 6L6 18"/>
<path d="M6 6L18 18"/>
</svg>
</button>
{/if}
</div>

View File

@@ -1,102 +1,99 @@
<script lang="ts">
import {Button} from "$lib/components/ui/button/index.js";
import {Input} from "$lib/components/ui/input/index.js";
import {Label} from "$lib/components/ui/label/index.js";
import {goto} from "$app/navigation";
import {env} from "$env/dynamic/public"
import {Button} from '$lib/components/ui/button/index.js';
import * as Card from '$lib/components/ui/card/index.js';
import {Input} from '$lib/components/ui/input/index.js';
import {Label} from '$lib/components/ui/label/index.js';
import {goto} from '$app/navigation';
import {env} from '$env/dynamic/public';
let apiUrl = env.PUBLIC_API_URL
let apiUrl = env.PUBLIC_API_URL;
let email = '';
let password = '';
let errorMessage = '';
let isLoading = false;
let email = '';
let password = '';
let errorMessage = '';
let isLoading = false;
async function handleLogin(event: Event) {
event.preventDefault();
async function handleLogin(event: Event) {
event.preventDefault();
isLoading = true;
errorMessage = '';
isLoading = true;
errorMessage = '';
const formData = new URLSearchParams();
formData.append('username', email);
formData.append('password', password);
console.log(apiUrl + '/auth/cookie/login')
try {
const response = await fetch(apiUrl + '/auth/cookie/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: formData.toString(),
credentials: 'include',
});
const formData = new URLSearchParams();
formData.append('username', email);
formData.append('password', password);
console.log(apiUrl + '/auth/cookie/login');
try {
const response = await fetch(apiUrl + '/auth/cookie/login', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: formData.toString(),
credentials: 'include'
});
if (response.ok) {
console.log('Login successful!');
console.log("Received User Data: ", response);
await goto('/dashboard');
errorMessage = 'Login successful! Redirecting...';
} else {
let errorText = await response.text();
try {
const errorData = JSON.parse(errorText);
errorMessage = errorData.message || 'Login failed. Please check your credentials.';
} catch {
errorMessage = errorText || 'Login failed. Please check your credentials.';
}
console.error('Login failed:', response.status, errorText);
}
} catch (error) {
console.error('Login request failed:', error);
errorMessage = 'An error occurred during the login request.';
} finally {
isLoading = false;
}
}
if (response.ok) {
console.log('Login successful!');
console.log('Received User Data: ', response);
await goto('/dashboard');
errorMessage = 'Login successful! Redirecting...';
} else {
let errorText = await response.text();
try {
const errorData = JSON.parse(errorText);
errorMessage = errorData.message || 'Login failed. Please check your credentials.';
} catch {
errorMessage = errorText || 'Login failed. Please check your credentials.';
}
console.error('Login failed:', response.status, errorText);
}
} catch (error) {
console.error('Login request failed:', error);
errorMessage = 'An error occurred during the login request.';
} finally {
isLoading = false;
}
}
</script>
<Card.Root class="mx-auto max-w-sm">
<Card.Header>
<Card.Title class="text-2xl">Login</Card.Title>
<Card.Description>Enter your email below to login to your account</Card.Description>
</Card.Header>
<Card.Content>
<form class="grid gap-4" on:submit={handleLogin}>
<div class="grid gap-2">
<Label for="email">Email</Label>
<Input bind:value={email} id="email" placeholder="m@example.com" required type="email"/>
</div>
<div class="grid gap-2">
<div class="flex items-center">
<Label for="password">Password</Label>
<a class="ml-auto inline-block text-sm underline" href="##">
Forgot your password?
</a>
</div>
<Input bind:value={password} id="password" required type="password"/>
</div>
<Card.Header>
<Card.Title class="text-2xl">Login</Card.Title>
<Card.Description>Enter your email below to login to your account</Card.Description>
</Card.Header>
<Card.Content>
<form class="grid gap-4" on:submit={handleLogin}>
<div class="grid gap-2">
<Label for="email">Email</Label>
<Input bind:value={email} id="email" placeholder="m@example.com" required type="email"/>
</div>
<div class="grid gap-2">
<div class="flex items-center">
<Label for="password">Password</Label>
<a class="ml-auto inline-block text-sm underline" href="##"> Forgot your password? </a>
</div>
<Input bind:value={password} id="password" required type="password"/>
</div>
{#if errorMessage}
<p class="text-sm text-red-500">{errorMessage}</p>
{/if}
{#if errorMessage}
<p class="text-sm text-red-500">{errorMessage}</p>
{/if}
<Button class="w-full" disabled={isLoading} type="submit">
{#if isLoading}
Logging in...
{:else}
Login
{/if}
</Button>
</form>
<Button class="w-full" disabled={isLoading} type="submit">
{#if isLoading}
Logging in...
{:else}
Login
{/if}
</Button>
</form>
<Button class="w-full mt-2" variant="outline">Login with Google</Button>
<Button class="mt-2 w-full" variant="outline">Login with Google</Button>
<div class="mt-4 text-center text-sm">
Don't have an account?
<a class="underline" href="##"> Sign up </a>
</div>
</Card.Content>
</Card.Root>
<div class="mt-4 text-center text-sm">
Don't have an account?
<a class="underline" href="##"> Sign up </a>
</div>
</Card.Content>
</Card.Root>

View File

@@ -1,66 +1,68 @@
<script lang="ts">
import * as Collapsible from '$lib/components/ui/collapsible/index.js';
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
import ChevronRight from '@lucide/svelte/icons/chevron-right';
let {
items,
}: {
items: {
title: string;
url: string;
// this should be `Component` after @lucide/svelte updates types
// eslint-disable-next-line @typescript-eslint/no-explicit-any
icon?: any;
isActive?: boolean;
items?: {
title: string;
url: string;
}[];
}[];
} = $props();
let {
items
}: {
items: {
title: string;
url: string;
// This should be `Component` after @lucide/svelte updates types
// eslint-disable-next-line @typescript-eslint/no-explicit-any
icon: any;
isActive?: boolean;
items?: {
title: string;
url: string;
}[];
}[];
} = $props();
</script>
<Sidebar.Group>
<Sidebar.GroupLabel>Platform</Sidebar.GroupLabel>
<Sidebar.Menu>
{#each items as mainItem (mainItem.title)}
<Collapsible.Root open={mainItem.isActive} class="group/collapsible">
{#snippet child({props})}
<Sidebar.MenuItem {...props}>
<Collapsible.Trigger>
{#snippet child({props})}
<Sidebar.MenuButton {...props}>
{#snippet tooltipContent()}
{mainItem.title}
{/snippet}
{#if mainItem.icon}
<mainItem.icon/>
{/if}
<span>{mainItem.title}</span>
<ChevronRight
class="ml-auto transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
/>
</Sidebar.MenuButton>
{/snippet}
</Collapsible.Trigger>
<Collapsible.Content>
{#if mainItem.items}
<Sidebar.MenuSub>
{#each mainItem.items as subItem (subItem.title)}
<Sidebar.MenuSubItem>
<Sidebar.MenuSubButton>
{#snippet child({props})}
<a href={subItem.url} {...props}>
<span>{subItem.title}</span>
</a>
{/snippet}
</Sidebar.MenuSubButton>
</Sidebar.MenuSubItem>
{/each}
</Sidebar.MenuSub>
{/if}
</Collapsible.Content>
</Sidebar.MenuItem>
{/snippet}
</Collapsible.Root>
{/each}
</Sidebar.Menu>
<Sidebar.GroupLabel>Platform</Sidebar.GroupLabel>
<Sidebar.Menu>
{#each items as mainItem (mainItem.title)}
<Collapsible.Root open={mainItem.isActive}>
{#snippet child({props})}
<Sidebar.MenuItem {...props}>
<Sidebar.MenuButton>
{#snippet tooltipContent()}
{mainItem.title}
{/snippet}
{#snippet child({props})}
<a href={mainItem.url} {...props}>
<mainItem.icon/>
<span>{mainItem.title}</span>
</a>
{/snippet}
</Sidebar.MenuButton>
{#if mainItem.items?.length}
<Collapsible.Trigger>
{#snippet child({props})}
<Sidebar.MenuAction {...props} class="data-[state=open]:rotate-90">
<ChevronRight/>
<span class="sr-only">Toggle</span>
</Sidebar.MenuAction>
{/snippet}
</Collapsible.Trigger>
<Collapsible.Content>
<Sidebar.MenuSub>
{#each mainItem.items as subItem (subItem.title)}
<Sidebar.MenuSubItem>
<Sidebar.MenuSubButton href={subItem.url}>
<span>{subItem.title}</span>
</Sidebar.MenuSubButton>
</Sidebar.MenuSubItem>
{/each}
</Sidebar.MenuSub>
</Collapsible.Content>
{/if}
</Sidebar.MenuItem>
{/snippet}
</Collapsible.Root>
{/each}
</Sidebar.Menu>
</Sidebar.Group>

View File

@@ -1,70 +1,76 @@
<script lang="ts">
import {useSidebar} from "$lib/components/ui/sidebar/context.svelte.js";
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
import {useSidebar} from '$lib/components/ui/sidebar/index.js';
import Ellipsis from '@lucide/svelte/icons/ellipsis';
import Folder from '@lucide/svelte/icons/folder';
import Share from '@lucide/svelte/icons/share';
import Trash2 from '@lucide/svelte/icons/trash-2';
let {
projects,
}: {
projects: {
name: string;
url: string;
// This should be `Component` after @lucide/svelte updates types
// eslint-disable-next-line @typescript-eslint/no-explicit-any
icon: any;
}[];
} = $props();
let {
projects
}: {
projects: {
name: string;
url: string;
// This should be `Component` after @lucide/svelte updates types
// eslint-disable-next-line @typescript-eslint/no-explicit-any
icon: any;
}[];
} = $props();
const sidebar = useSidebar();
const sidebar = useSidebar();
</script>
<Sidebar.Group class="group-data-[collapsible=icon]:hidden">
<Sidebar.GroupLabel>Projects</Sidebar.GroupLabel>
<Sidebar.Menu>
{#each projects as item (item.name)}
<Sidebar.MenuItem>
<Sidebar.MenuButton>
{#snippet child({props})}
<a href={item.url} {...props}>
<item.icon/>
<span>{item.name}</span>
</a>
{/snippet}
</Sidebar.MenuButton>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
{#snippet child({props})}
<Sidebar.MenuAction showOnHover {...props}>
<Ellipsis/>
<span class="sr-only">More</span>
</Sidebar.MenuAction>
{/snippet}
</DropdownMenu.Trigger>
<DropdownMenu.Content
class="w-48 rounded-lg"
side={sidebar.isMobile ? "bottom" : "right"}
align={sidebar.isMobile ? "end" : "start"}
>
<DropdownMenu.Item>
<Folder class="text-muted-foreground"/>
<span>View Project</span>
</DropdownMenu.Item>
<DropdownMenu.Item>
<Forward class="text-muted-foreground"/>
<span>Share Project</span>
</DropdownMenu.Item>
<DropdownMenu.Separator/>
<DropdownMenu.Item>
<Trash2 class="text-muted-foreground"/>
<span>Delete Project</span>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Sidebar.MenuItem>
{/each}
<Sidebar.MenuItem>
<Sidebar.MenuButton class="text-sidebar-foreground/70">
<Ellipsis class="text-sidebar-foreground/70"/>
<span>More</span>
</Sidebar.MenuButton>
</Sidebar.MenuItem>
</Sidebar.Menu>
<Sidebar.GroupLabel>Projects</Sidebar.GroupLabel>
<Sidebar.Menu>
{#each projects as item (item.name)}
<Sidebar.MenuItem>
<Sidebar.MenuButton>
{#snippet child({props})}
<a href={item.url} {...props}>
<item.icon/>
<span>{item.name}</span>
</a>
{/snippet}
</Sidebar.MenuButton>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
{#snippet child({props})}
<Sidebar.MenuAction showOnHover {...props}>
<Ellipsis/>
<span class="sr-only">More</span>
</Sidebar.MenuAction>
{/snippet}
</DropdownMenu.Trigger>
<DropdownMenu.Content
class="w-48"
side={sidebar.isMobile ? 'bottom' : 'right'}
align={sidebar.isMobile ? 'end' : 'start'}
>
<DropdownMenu.Item>
<Folder class="text-muted-foreground"/>
<span>View Project</span>
</DropdownMenu.Item>
<DropdownMenu.Item>
<Share class="text-muted-foreground"/>
<span>Share Project</span>
</DropdownMenu.Item>
<DropdownMenu.Separator/>
<DropdownMenu.Item>
<Trash2 class="text-muted-foreground"/>
<span>Delete Project</span>
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Sidebar.MenuItem>
{/each}
<Sidebar.MenuItem>
<Sidebar.MenuButton>
<Ellipsis/>
<span>More</span>
</Sidebar.MenuButton>
</Sidebar.MenuItem>
</Sidebar.Menu>
</Sidebar.Group>

View File

@@ -0,0 +1,37 @@
<script lang="ts">
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
import type {ComponentProps} from 'svelte';
let {
ref = $bindable(null),
items,
...restProps
}: {
items: {
title: string;
url: string;
// This should be `Component` after @lucide/svelte updates types
// eslint-disable-next-line @typescript-eslint/no-explicit-any
icon: any;
}[];
} & ComponentProps<typeof Sidebar.Group> = $props();
</script>
<Sidebar.Group bind:ref {...restProps}>
<Sidebar.GroupContent>
<Sidebar.Menu>
{#each items as item (item.title)}
<Sidebar.MenuItem>
<Sidebar.MenuButton size="sm">
{#snippet child({props})}
<a href={item.url} {...props}>
<item.icon/>
<span>{item.title}</span>
</a>
{/snippet}
</Sidebar.MenuButton>
</Sidebar.MenuItem>
{/each}
</Sidebar.Menu>
</Sidebar.GroupContent>
</Sidebar.Group>

View File

@@ -1,69 +1,89 @@
<script lang="ts">
import {useSidebar} from "$lib/components/ui/sidebar/index.js";
import UserDetails from "$lib/components/user-details.svelte"
import BadgeCheck from '@lucide/svelte/icons/badge-check';
import Bell from '@lucide/svelte/icons/bell';
import ChevronsUpDown from '@lucide/svelte/icons/chevrons-up-down';
import CreditCard from '@lucide/svelte/icons/credit-card';
import LogOut from '@lucide/svelte/icons/log-out';
import Sparkles from '@lucide/svelte/icons/sparkles';
//let { user }: { user: { name: string; email: string; avatar: string } } = $props();
const sidebar = useSidebar();
import * as Avatar from '$lib/components/ui/avatar/index.js';
import * as DropdownMenu from '$lib/components/ui/dropdown-menu/index.js';
import * as Sidebar from '$lib/components/ui/sidebar/index.js';
import {useSidebar} from '$lib/components/ui/sidebar/index.js';
import {getContext} from 'svelte';
import UserDetails from './user-details.svelte';
import type {User} from '$lib/types';
const user: () => User = getContext('user');
const sidebar = useSidebar();
</script>
<Sidebar.Menu>
<Sidebar.MenuItem>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
{#snippet child({props})}
<Sidebar.MenuButton
size="lg"
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
{...props}
>
<div class="grid flex-1 text-left text-sm leading-tight">
<UserDetails/>
</div>
<ChevronsUpDown class="ml-auto size-4"/>
</Sidebar.MenuButton>
{/snippet}
</DropdownMenu.Trigger>
<DropdownMenu.Content
align="end"
class="w-[var(--bits-dropdown-menu-anchor-width)] min-w-56 rounded-lg"
side={sidebar.isMobile ? "bottom" : "right"}
sideOffset={4}
>
<DropdownMenu.Label class="p-0 font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<div class="grid flex-1 text-left text-sm leading-tight">
<UserDetails/>
</div>
</div>
</DropdownMenu.Label>
<DropdownMenu.Separator/>
<DropdownMenu.Group>
<DropdownMenu.Item>
<Sparkles/>
Upgrade to Pro
</DropdownMenu.Item>
</DropdownMenu.Group>
<DropdownMenu.Separator/>
<DropdownMenu.Group>
<DropdownMenu.Item>
<BadgeCheck/>
Account
</DropdownMenu.Item>
<DropdownMenu.Item>
<CreditCard/>
Billing
</DropdownMenu.Item>
<DropdownMenu.Item>
<Bell/>
Notifications
</DropdownMenu.Item>
</DropdownMenu.Group>
<DropdownMenu.Separator/>
<DropdownMenu.Item>
<LogOut/>
Log out
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Sidebar.MenuItem>
<Sidebar.MenuItem>
<DropdownMenu.Root>
<DropdownMenu.Trigger>
{#snippet child({props})}
<Sidebar.MenuButton
{...props}
size="lg"
class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
>
<Avatar.Root class="h-8 w-8 rounded-lg">
<!--<Avatar.Image src={user.avatar} alt={user.name} />-->
<Avatar.Fallback class="rounded-lg">CN</Avatar.Fallback>
</Avatar.Root>
<div class="grid flex-1 text-left text-sm leading-tight">
<UserDetails/>
</div>
<ChevronsUpDown class="ml-auto size-4"/>
</Sidebar.MenuButton>
{/snippet}
</DropdownMenu.Trigger>
<DropdownMenu.Content
class="w-[var(--bits-dropdown-menu-anchor-width)] min-w-56 rounded-lg"
side={sidebar.isMobile ? 'bottom' : 'right'}
align="end"
sideOffset={4}
>
<DropdownMenu.Label class="p-0 font-normal">
<div class="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
<Avatar.Root class="h-8 w-8 rounded-lg">
<!--<Avatar.Image src={user.avatar} alt={user.name} />-->
<Avatar.Fallback class="rounded-lg">CN</Avatar.Fallback>
</Avatar.Root>
<div class="grid flex-1 text-left text-sm leading-tight">
<UserDetails/>
</div>
</div>
</DropdownMenu.Label>
<DropdownMenu.Separator/>
<DropdownMenu.Group>
<DropdownMenu.Item>
<Sparkles/>
Upgrade to Pro
</DropdownMenu.Item>
</DropdownMenu.Group>
<DropdownMenu.Separator/>
<DropdownMenu.Group>
<DropdownMenu.Item>
<BadgeCheck/>
Account
</DropdownMenu.Item>
<DropdownMenu.Item>
<CreditCard/>
Billing
</DropdownMenu.Item>
<DropdownMenu.Item>
<Bell/>
Notifications
</DropdownMenu.Item>
</DropdownMenu.Group>
<DropdownMenu.Separator/>
<DropdownMenu.Item>
<LogOut/>
Log out
</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
</Sidebar.MenuItem>
</Sidebar.Menu>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {Avatar as AvatarPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Avatar as AvatarPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
class: className,
@@ -10,7 +10,7 @@
</script>
<AvatarPrimitive.Fallback
{...restProps}
bind:ref
class={cn("bg-muted flex size-full items-center justify-center", className)}
class={cn('flex size-full items-center justify-center bg-muted', className)}
{...restProps}
/>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {Avatar as AvatarPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Avatar as AvatarPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
class: className,
@@ -12,9 +12,9 @@
</script>
<AvatarPrimitive.Image
{...restProps}
{alt}
bind:ref
class={cn("aspect-square size-full", className)}
{src}
{alt}
class={cn('aspect-square size-full', className)}
{...restProps}
/>

View File

@@ -1,18 +1,18 @@
<script lang="ts">
import {Avatar as AvatarPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Avatar as AvatarPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
class: className,
ref = $bindable(null),
loadingStatus = $bindable("loading"),
loadingStatus = $bindable('loading'),
...restProps
}: AvatarPrimitive.RootProps = $props();
</script>
<AvatarPrimitive.Root
{...restProps}
bind:loadingStatus
bind:ref
class={cn("relative flex size-10 shrink-0 overflow-hidden rounded-full", className)}
class={cn('relative flex size-10 shrink-0 overflow-hidden rounded-full', className)}
{...restProps}
/>

View File

@@ -1,6 +1,6 @@
import Root from "./avatar.svelte";
import Image from "./avatar-image.svelte";
import Fallback from "./avatar-fallback.svelte";
import Root from './avatar.svelte';
import Image from './avatar-image.svelte';
import Fallback from './avatar-fallback.svelte';
export {
Root,
@@ -9,5 +9,5 @@ export {
//
Root as Avatar,
Image as AvatarImage,
Fallback as AvatarFallback,
Fallback as AvatarFallback
};

View File

@@ -1,7 +1,8 @@
<script lang="ts">
import type {WithElementRef, WithoutChildren} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import Ellipsis from '@lucide/svelte/icons/ellipsis';
import type {WithElementRef, WithoutChildren} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,11 +12,11 @@
</script>
<span
{...restProps}
aria-hidden="true"
bind:this={ref}
class={cn("flex size-9 items-center justify-center", className)}
role="presentation"
aria-hidden="true"
class={cn('flex size-9 items-center justify-center', className)}
{...restProps}
>
<Ellipsis class="size-4"/>
<span class="sr-only">More</span>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLLiAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLLiAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,6 +11,6 @@
}: WithElementRef<HTMLLiAttributes> = $props();
</script>
<li {...restProps} bind:this={ref} class={cn("inline-flex items-center gap-1.5", className)}>
<li bind:this={ref} class={cn('inline-flex items-center gap-1.5', className)} {...restProps}>
{@render children?.()}
</li>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import type {HTMLAnchorAttributes} from "svelte/elements";
import type {Snippet} from "svelte";
import type {WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLAnchorAttributes} from 'svelte/elements';
import type {Snippet} from 'svelte';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -16,9 +16,9 @@
} = $props();
const attrs = $derived({
class: cn("hover:text-foreground transition-colors", className),
class: cn('hover:text-foreground transition-colors', className),
href,
...restProps,
...restProps
});
</script>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLOlAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLOlAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,12 +12,12 @@
</script>
<ol
{...restProps}
bind:this={ref}
class={cn(
"text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5",
'flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5',
className
)}
{...restProps}
>
{@render children?.()}
</ol>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,12 +12,12 @@
</script>
<span
{...restProps}
aria-current="page"
aria-disabled="true"
bind:this={ref}
class={cn("text-foreground font-normal", className)}
role="link"
aria-disabled="true"
aria-current="page"
class={cn('font-normal text-foreground', className)}
{...restProps}
>
{@render children?.()}
</span>

View File

@@ -1,7 +1,8 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLLiAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import ChevronRight from '@lucide/svelte/icons/chevron-right';
import type {WithElementRef} from 'bits-ui';
import type {HTMLLiAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,11 +13,11 @@
</script>
<li
{...restProps}
aria-hidden="true"
bind:this={ref}
class={cn("[&>svg]:size-3.5", className)}
role="presentation"
aria-hidden="true"
class={cn('[&>svg]:size-3.5', className)}
bind:this={ref}
{...restProps}
>
{#if children}
{@render children?.()}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(),
@@ -10,6 +10,6 @@
}: WithElementRef<HTMLAttributes<HTMLElement>> = $props();
</script>
<nav {...restProps} aria-label="breadcrumb" bind:this={ref} class={className}>
<nav class={className} bind:this={ref} aria-label="breadcrumb" {...restProps}>
{@render children?.()}
</nav>

View File

@@ -1,10 +1,10 @@
import Root from "./breadcrumb.svelte";
import Ellipsis from "./breadcrumb-ellipsis.svelte";
import Item from "./breadcrumb-item.svelte";
import Separator from "./breadcrumb-separator.svelte";
import Link from "./breadcrumb-link.svelte";
import List from "./breadcrumb-list.svelte";
import Page from "./breadcrumb-page.svelte";
import Root from './breadcrumb.svelte';
import Ellipsis from './breadcrumb-ellipsis.svelte';
import Item from './breadcrumb-item.svelte';
import Separator from './breadcrumb-separator.svelte';
import Link from './breadcrumb-link.svelte';
import List from './breadcrumb-list.svelte';
import Page from './breadcrumb-page.svelte';
export {
Root,
@@ -21,5 +21,5 @@ export {
Separator as BreadcrumbSeparator,
Link as BreadcrumbLink,
List as BreadcrumbList,
Page as BreadcrumbPage,
Page as BreadcrumbPage
};

View File

@@ -1,36 +1,35 @@
<script lang="ts" module>
import type {WithElementRef} from "bits-ui";
import type {HTMLAnchorAttributes, HTMLButtonAttributes} from "svelte/elements";
import {tv, type VariantProps} from "tailwind-variants";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAnchorAttributes, HTMLButtonAttributes} from 'svelte/elements';
import {type VariantProps, tv} from 'tailwind-variants';
export const buttonVariants = tv({
base: "focus-visible:ring-ring inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
base: 'focus-visible:ring-ring inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
variants: {
variant: {
default: "bg-primary text-primary-foreground hover:bg-primary/90 shadow",
destructive:
"bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm",
default: 'bg-primary text-primary-foreground hover:bg-primary/90 shadow',
destructive: 'bg-destructive text-destructive-foreground hover:bg-destructive/90 shadow-sm',
outline:
"border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm",
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
'border-input bg-background hover:bg-accent hover:text-accent-foreground border shadow-sm',
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80 shadow-sm',
ghost: 'hover:bg-accent hover:text-accent-foreground',
link: 'text-primary underline-offset-4 hover:underline'
},
size: {
default: "h-9 px-4 py-2",
sm: "h-8 rounded-md px-3 text-xs",
lg: "h-10 rounded-md px-8",
icon: "h-9 w-9",
},
default: 'h-9 px-4 py-2',
sm: 'h-8 rounded-md px-3 text-xs',
lg: 'h-10 rounded-md px-8',
icon: 'h-9 w-9'
}
},
defaultVariants: {
variant: "default",
size: "default",
},
variant: 'default',
size: 'default'
}
});
export type ButtonVariant = VariantProps<typeof buttonVariants>["variant"];
export type ButtonSize = VariantProps<typeof buttonVariants>["size"];
export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
WithElementRef<HTMLAnchorAttributes> & {
@@ -40,27 +39,22 @@
</script>
<script lang="ts">
import {cn} from "$lib/utils.js";
import {cn} from '$lib/utils.js';
let {
class: className,
variant = "default",
size = "default",
variant = 'default',
size = 'default',
ref = $bindable(null),
href = undefined,
type = "button",
type = 'button',
children,
...restProps
}: ButtonProps = $props();
</script>
{#if href}
<a
bind:this={ref}
class={cn(buttonVariants({ variant, size }), className)}
{href}
{...restProps}
>
<a bind:this={ref} class={cn(buttonVariants({ variant, size }), className)} {href} {...restProps}>
{@render children?.()}
</a>
{:else}

View File

@@ -1,4 +1,9 @@
import Root, {type ButtonProps, type ButtonSize, type ButtonVariant, buttonVariants,} from "./button.svelte";
import Root, {
type ButtonProps,
type ButtonSize,
type ButtonVariant,
buttonVariants
} from './button.svelte';
export {
Root,
@@ -8,5 +13,5 @@ export {
buttonVariants,
type ButtonProps,
type ButtonSize,
type ButtonVariant,
type ButtonVariant
};

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,6 +11,6 @@
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div {...restProps} bind:this={ref} class={cn("p-6", className)}>
<div {...restProps} bind:this={ref} class={cn('p-6', className)}>
{@render children?.()}
</div>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,6 +11,6 @@
}: WithElementRef<HTMLAttributes<HTMLParagraphElement>> = $props();
</script>
<p {...restProps} bind:this={ref} class={cn("text-muted-foreground text-sm", className)}>
<p {...restProps} bind:this={ref} class={cn('text-sm text-muted-foreground', className)}>
{@render children?.()}
</p>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,6 +11,6 @@
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div {...restProps} bind:this={ref} class={cn("flex items-center p-6 pt-0", className)}>
<div {...restProps} bind:this={ref} class={cn('flex items-center p-6 pt-0', className)}>
{@render children?.()}
</div>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,6 +11,6 @@
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div {...restProps} bind:this={ref} class={cn("flex flex-col space-y-1.5 p-6 pb-0", className)}>
<div {...restProps} bind:this={ref} class={cn('flex flex-col space-y-1.5 p-6 pb-0', className)}>
{@render children?.()}
</div>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -18,7 +18,7 @@
{...restProps}
aria-level={level}
bind:this={ref}
class={cn("font-semibold leading-none tracking-tight", className)}
class={cn('font-semibold leading-none tracking-tight', className)}
role="heading"
>
{@render children?.()}

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -14,7 +14,7 @@
<div
{...restProps}
bind:this={ref}
class={cn("bg-card text-card-foreground rounded-xl border shadow", className)}
class={cn('rounded-xl border bg-card text-card-foreground shadow', className)}
>
{@render children?.()}
</div>

View File

@@ -1,9 +1,9 @@
import Root from "./card.svelte";
import Content from "./card-content.svelte";
import Description from "./card-description.svelte";
import Footer from "./card-footer.svelte";
import Header from "./card-header.svelte";
import Title from "./card-title.svelte";
import Root from './card.svelte';
import Content from './card-content.svelte';
import Description from './card-description.svelte';
import Footer from './card-footer.svelte';
import Header from './card-header.svelte';
import Title from './card-title.svelte';
export {
Root,
@@ -18,5 +18,5 @@ export {
Description as CardDescription,
Footer as CardFooter,
Header as CardHeader,
Title as CardTitle,
Title as CardTitle
};

View File

@@ -1,4 +1,4 @@
import {Collapsible as CollapsiblePrimitive} from "bits-ui";
import {Collapsible as CollapsiblePrimitive} from 'bits-ui';
const Root: typeof CollapsiblePrimitive.Root = CollapsiblePrimitive.Root;
const Trigger: typeof CollapsiblePrimitive.Trigger = CollapsiblePrimitive.Trigger;
@@ -11,5 +11,5 @@ export {
//
Root as Collapsible,
Content as CollapsibleContent,
Trigger as CollapsibleTrigger,
Trigger as CollapsibleTrigger
};

View File

@@ -0,0 +1,38 @@
<script lang="ts">
import {Dialog as DialogPrimitive, type WithoutChildrenOrChild} from 'bits-ui';
import X from '@lucide/svelte/icons/x';
import type {Snippet} from 'svelte';
import * as Dialog from './index.js';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
portalProps,
children,
...restProps
}: WithoutChildrenOrChild<DialogPrimitive.ContentProps> & {
portalProps?: DialogPrimitive.PortalProps;
children: Snippet;
} = $props();
</script>
<Dialog.Portal {...portalProps}>
<Dialog.Overlay/>
<DialogPrimitive.Content
bind:ref
class={cn(
'fixed left-[50%] top-[50%] z-50 grid translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
className
)}
{...restProps}
>
{@render children?.()}
<DialogPrimitive.Close
class="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-accent data-[state=open]:text-muted-foreground"
>
<X class="size-4"/>
<span class="sr-only">Close</span>
</DialogPrimitive.Close>
</DialogPrimitive.Content>
</Dialog.Portal>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import {Dialog as DialogPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: DialogPrimitive.DescriptionProps = $props();
</script>
<DialogPrimitive.Description
bind:ref
class={cn('text-sm text-muted-foreground', className)}
{...restProps}
/>

View File

@@ -0,0 +1,20 @@
<script lang="ts">
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -0,0 +1,20 @@
<script lang="ts">
import type {HTMLAttributes} from 'svelte/elements';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
</script>
<div
bind:this={ref}
class={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import {Dialog as DialogPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: DialogPrimitive.OverlayProps = $props();
</script>
<DialogPrimitive.Overlay
bind:ref
class={cn(
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className
)}
{...restProps}
/>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import {Dialog as DialogPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: DialogPrimitive.TitleProps = $props();
</script>
<DialogPrimitive.Title
bind:ref
class={cn('text-lg font-semibold leading-none tracking-tight', className)}
{...restProps}
/>

View File

@@ -0,0 +1,37 @@
import {Dialog as DialogPrimitive} from 'bits-ui';
import Title from './dialog-title.svelte';
import Footer from './dialog-footer.svelte';
import Header from './dialog-header.svelte';
import Overlay from './dialog-overlay.svelte';
import Content from './dialog-content.svelte';
import Description from './dialog-description.svelte';
const Root: typeof DialogPrimitive.Root = DialogPrimitive.Root;
const Trigger: typeof DialogPrimitive.Trigger = DialogPrimitive.Trigger;
const Close: typeof DialogPrimitive.Close = DialogPrimitive.Close;
const Portal: typeof DialogPrimitive.Portal = DialogPrimitive.Portal;
export {
Root,
Title,
Portal,
Footer,
Header,
Trigger,
Overlay,
Content,
Description,
Close,
//
Root as Dialog,
Title as DialogTitle,
Portal as DialogPortal,
Footer as DialogFooter,
Header as DialogHeader,
Trigger as DialogTrigger,
Overlay as DialogOverlay,
Content as DialogContent,
Description as DialogDescription,
Close as DialogClose
};

View File

@@ -1,7 +1,9 @@
<script lang="ts">
import {DropdownMenu as DropdownMenuPrimitive, type WithoutChildrenOrChild} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {Snippet} from "svelte";
import {DropdownMenu as DropdownMenuPrimitive, type WithoutChildrenOrChild} from 'bits-ui';
import Check from '@lucide/svelte/icons/check';
import Minus from '@lucide/svelte/icons/minus';
import {cn} from '$lib/utils.js';
import type {Snippet} from 'svelte';
let {
ref = $bindable(null),
@@ -16,21 +18,21 @@
</script>
<DropdownMenuPrimitive.CheckboxItem
{...restProps}
bind:ref
bind:checked
bind:indeterminate
bind:ref
class={cn(
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
className
)}
{...restProps}
>
{#snippet children({checked, indeterminate})}
<span class="absolute left-2 flex size-3.5 items-center justify-center">
{#if indeterminate}
<Minus class="size-4"/>
{:else}
<Check class={cn("size-4", !checked && "text-transparent")}/>
<Check class={cn('size-4', !checked && 'text-transparent')}/>
{/if}
</span>
{@render childrenProp?.()}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import {DropdownMenu as DropdownMenuPrimitive} from "bits-ui";
import {cn} from '$lib/utils.js';
import {DropdownMenu as DropdownMenuPrimitive} from 'bits-ui';
let {
ref = $bindable(null),
@@ -15,13 +15,13 @@
<DropdownMenuPrimitive.Portal {...portalProps}>
<DropdownMenuPrimitive.Content
{...restProps}
bind:ref
{sideOffset}
class={cn(
"bg-popover text-popover-foreground z-50 min-w-[8rem] overflow-hidden rounded-md border p-1 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 outline-none",
'z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 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}
{...restProps}
/>
</DropdownMenuPrimitive.Portal>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {DropdownMenu as DropdownMenuPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {DropdownMenu as DropdownMenuPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -13,7 +13,7 @@
</script>
<DropdownMenuPrimitive.GroupHeading
{...restProps}
bind:ref
class={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
class={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}
{...restProps}
/>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import {DropdownMenu as DropdownMenuPrimitive} from "bits-ui";
import {cn} from '$lib/utils.js';
import {DropdownMenu as DropdownMenuPrimitive} from 'bits-ui';
let {
ref = $bindable(null),
@@ -13,11 +13,11 @@
</script>
<DropdownMenuPrimitive.Item
{...restProps}
bind:ref
class={cn(
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0",
inset && "pl-8",
'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50 [&>svg]:size-4 [&>svg]:shrink-0',
inset && 'pl-8',
className
)}
{...restProps}
/>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import {type WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import {type WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -15,9 +15,9 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
class={cn('px-2 py-1.5 text-sm font-semibold', inset && 'pl-8', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import {DropdownMenu as DropdownMenuPrimitive, type WithoutChild} from "bits-ui";
import {cn} from "$lib/utils.js";
import {DropdownMenu as DropdownMenuPrimitive, type WithoutChild} from 'bits-ui';
import Circle from '@lucide/svelte/icons/circle';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,12 +12,12 @@
</script>
<DropdownMenuPrimitive.RadioItem
{...restProps}
bind:ref
class={cn(
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
'relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
className
)}
{...restProps}
>
{#snippet children({checked})}
<span class="absolute left-2 flex size-3.5 items-center justify-center">

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {DropdownMenu as DropdownMenuPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {DropdownMenu as DropdownMenuPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -10,7 +10,7 @@
</script>
<DropdownMenuPrimitive.Separator
{...restProps}
bind:ref
class={cn("bg-muted -mx-1 my-1 h-px", className)}
class={cn('-mx-1 my-1 h-px bg-muted', className)}
{...restProps}
/>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {HTMLAttributes} from "svelte/elements";
import {type WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLAttributes} from 'svelte/elements';
import {type WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,9 +12,9 @@
</script>
<span
{...restProps}
bind:this={ref}
class={cn("ml-auto text-xs tracking-widest opacity-60", className)}
class={cn('ml-auto text-xs tracking-widest opacity-60', className)}
{...restProps}
>
{@render children?.()}
</span>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {DropdownMenu as DropdownMenuPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {DropdownMenu as DropdownMenuPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -10,10 +10,10 @@
</script>
<DropdownMenuPrimitive.SubContent
{...restProps}
bind:ref
class={cn(
"bg-popover text-popover-foreground z-50 min-w-[8rem] rounded-md border p-1 shadow-lg focus:outline-none",
'z-50 min-w-[8rem] rounded-md border bg-popover p-1 text-popover-foreground shadow-lg focus:outline-none',
className
)}
{...restProps}
/>

View File

@@ -1,6 +1,7 @@
<script lang="ts">
import {DropdownMenu as DropdownMenuPrimitive, type WithoutChild} from "bits-ui";
import {cn} from "$lib/utils.js";
import {DropdownMenu as DropdownMenuPrimitive, type WithoutChild} from 'bits-ui';
import ChevronRight from '@lucide/svelte/icons/chevron-right';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -14,13 +15,13 @@
</script>
<DropdownMenuPrimitive.SubTrigger
{...restProps}
bind:ref
class={cn(
"data-[highlighted]:bg-accent data-[state=open]:bg-accent flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
inset && "pl-8",
'flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[highlighted]:bg-accent data-[state=open]:bg-accent [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
inset && 'pl-8',
className
)}
{...restProps}
>
{@render children?.()}
<ChevronRight class="ml-auto"/>

View File

@@ -1,14 +1,14 @@
import {DropdownMenu as DropdownMenuPrimitive} from "bits-ui";
import CheckboxItem from "./dropdown-menu-checkbox-item.svelte";
import Content from "./dropdown-menu-content.svelte";
import GroupHeading from "./dropdown-menu-group-heading.svelte";
import Item from "./dropdown-menu-item.svelte";
import Label from "./dropdown-menu-label.svelte";
import RadioItem from "./dropdown-menu-radio-item.svelte";
import Separator from "./dropdown-menu-separator.svelte";
import Shortcut from "./dropdown-menu-shortcut.svelte";
import SubContent from "./dropdown-menu-sub-content.svelte";
import SubTrigger from "./dropdown-menu-sub-trigger.svelte";
import {DropdownMenu as DropdownMenuPrimitive} from 'bits-ui';
import CheckboxItem from './dropdown-menu-checkbox-item.svelte';
import Content from './dropdown-menu-content.svelte';
import GroupHeading from './dropdown-menu-group-heading.svelte';
import Item from './dropdown-menu-item.svelte';
import Label from './dropdown-menu-label.svelte';
import RadioItem from './dropdown-menu-radio-item.svelte';
import Separator from './dropdown-menu-separator.svelte';
import Shortcut from './dropdown-menu-shortcut.svelte';
import SubContent from './dropdown-menu-sub-content.svelte';
import SubTrigger from './dropdown-menu-sub-trigger.svelte';
const Sub = DropdownMenuPrimitive.Sub;
const Root = DropdownMenuPrimitive.Root;
@@ -46,5 +46,5 @@ export {
Sub,
SubContent,
SubTrigger,
Trigger,
Trigger
};

View File

@@ -1,7 +1,7 @@
import Root from "./input.svelte";
import Root from './input.svelte';
export {
Root,
//
Root as Input,
Root as Input
};

View File

@@ -1,13 +1,13 @@
<script lang="ts">
import type {HTMLInputAttributes, HTMLInputTypeAttribute} from "svelte/elements";
import type {WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLInputAttributes, HTMLInputTypeAttribute} from 'svelte/elements';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
type InputType = Exclude<HTMLInputTypeAttribute, "file">;
type InputType = Exclude<HTMLInputTypeAttribute, 'file'>;
type Props = WithElementRef<
Omit<HTMLInputAttributes, "type"> &
({ type: "file"; files?: FileList } | { type?: InputType; files?: undefined })
Omit<HTMLInputAttributes, 'type'> &
({ type: 'file'; files?: FileList } | { type?: InputType; files?: undefined })
>;
let {
@@ -20,11 +20,11 @@
}: Props = $props();
</script>
{#if type === "file"}
{#if type === 'file'}
<input
bind:this={ref}
class={cn(
"border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
className
)}
type="file"
@@ -36,7 +36,7 @@
<input
bind:this={ref}
class={cn(
"border-input placeholder:text-muted-foreground focus-visible:ring-ring flex h-9 w-full rounded-md border bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
'flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-sm transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
className
)}
{type}

View File

@@ -1,7 +1,7 @@
import Root from "./label.svelte";
import Root from './label.svelte';
export {
Root,
//
Root as Label,
Root as Label
};

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {Label as LabelPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Label as LabelPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -13,7 +13,7 @@
{...restProps}
bind:ref
class={cn(
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
'text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70',
className
)}
/>

View File

@@ -0,0 +1,10 @@
import Root from './radio-group.svelte';
import Item from './radio-group-item.svelte';
export {
Root,
Item,
//
Root as RadioGroup,
Item as RadioGroupItem
};

View File

@@ -0,0 +1,30 @@
<script lang="ts">
import {RadioGroup as RadioGroupPrimitive, type WithoutChildrenOrChild} from 'bits-ui';
import Circle from '@lucide/svelte/icons/circle';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: WithoutChildrenOrChild<RadioGroupPrimitive.ItemProps> & {
value: string;
} = $props();
</script>
<RadioGroupPrimitive.Item
bind:ref
class={cn(
'aspect-square size-4 rounded-full border border-primary text-primary shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50',
className
)}
{...restProps}
>
{#snippet children({checked})}
<div class="flex items-center justify-center">
{#if checked}
<Circle class="size-3.5 fill-primary"/>
{/if}
</div>
{/snippet}
</RadioGroupPrimitive.Item>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import {RadioGroup as RadioGroupPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
value = $bindable(),
...restProps
}: RadioGroupPrimitive.RootProps = $props();
</script>
<RadioGroupPrimitive.Root bind:value class={cn('grid gap-2', className)} {...restProps} bind:ref/>

View File

@@ -0,0 +1,34 @@
import {Select as SelectPrimitive} from 'bits-ui';
import GroupHeading from './select-group-heading.svelte';
import Item from './select-item.svelte';
import Content from './select-content.svelte';
import Trigger from './select-trigger.svelte';
import Separator from './select-separator.svelte';
import ScrollDownButton from './select-scroll-down-button.svelte';
import ScrollUpButton from './select-scroll-up-button.svelte';
const Root = SelectPrimitive.Root;
const Group = SelectPrimitive.Group;
export {
Root,
Item,
Group,
GroupHeading,
Content,
Trigger,
Separator,
ScrollDownButton,
ScrollUpButton,
//
Root as Select,
Item as SelectItem,
Group as SelectGroup,
GroupHeading as SelectGroupHeading,
Content as SelectContent,
Trigger as SelectTrigger,
Separator as SelectSeparator,
ScrollDownButton as SelectScrollDownButton,
ScrollUpButton as SelectScrollUpButton
};

View File

@@ -0,0 +1,38 @@
<script lang="ts">
import {Select as SelectPrimitive, type WithoutChild} from 'bits-ui';
import * as Select from './index.js';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
sideOffset = 4,
portalProps,
children,
...restProps
}: WithoutChild<SelectPrimitive.ContentProps> & {
portalProps?: SelectPrimitive.PortalProps;
} = $props();
</script>
<SelectPrimitive.Portal {...portalProps}>
<SelectPrimitive.Content
bind:ref
{sideOffset}
class={cn(
'relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1 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
)}
{...restProps}
>
<Select.ScrollUpButton/>
<SelectPrimitive.Viewport
class={cn(
'h-[var(--bits-select-anchor-height)] w-full min-w-[var(--bits-select-anchor-width)] p-1'
)}
>
{@render children?.()}
</SelectPrimitive.Viewport>
<Select.ScrollDownButton/>
</SelectPrimitive.Content>
</SelectPrimitive.Portal>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import {Select as SelectPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: SelectPrimitive.GroupHeadingProps = $props();
</script>
<SelectPrimitive.GroupHeading
bind:ref
class={cn('px-2 py-1.5 text-sm font-semibold', className)}
{...restProps}
/>

View File

@@ -0,0 +1,37 @@
<script lang="ts">
import {Select as SelectPrimitive, type WithoutChild} from 'bits-ui';
import Check from '@lucide/svelte/icons/check';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
value,
label,
children: childrenProp,
...restProps
}: WithoutChild<SelectPrimitive.ItemProps> = $props();
</script>
<SelectPrimitive.Item
bind:ref
{value}
class={cn(
'relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none data-[disabled]:pointer-events-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground data-[disabled]:opacity-50',
className
)}
{...restProps}
>
{#snippet children({selected, highlighted})}
<span class="absolute right-2 flex size-3.5 items-center justify-center">
{#if selected}
<Check class="size-4"/>
{/if}
</span>
{#if childrenProp}
{@render childrenProp({selected, highlighted})}
{:else}
{label || value}
{/if}
{/snippet}
</SelectPrimitive.Item>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import ChevronDown from '@lucide/svelte/icons/chevron-down';
import {Select as SelectPrimitive, type WithoutChildrenOrChild} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: WithoutChildrenOrChild<SelectPrimitive.ScrollDownButtonProps> = $props();
</script>
<SelectPrimitive.ScrollDownButton
bind:ref
class={cn('flex cursor-default items-center justify-center py-1', className)}
{...restProps}
>
<ChevronDown class="size-4"/>
</SelectPrimitive.ScrollDownButton>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import ChevronUp from '@lucide/svelte/icons/chevron-up';
import {Select as SelectPrimitive, type WithoutChildrenOrChild} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: WithoutChildrenOrChild<SelectPrimitive.ScrollDownButtonProps> = $props();
</script>
<SelectPrimitive.ScrollUpButton
bind:ref
class={cn('flex cursor-default items-center justify-center py-1', className)}
{...restProps}
>
<ChevronUp class="size-4"/>
</SelectPrimitive.ScrollUpButton>

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import type {Separator as SeparatorPrimitive} from 'bits-ui';
import {Separator} from '$lib/components/ui/separator/index.js';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
...restProps
}: SeparatorPrimitive.RootProps = $props();
</script>
<Separator bind:ref class={cn('-mx-1 my-1 h-px bg-muted', className)} {...restProps}/>

View File

@@ -0,0 +1,24 @@
<script lang="ts">
import {Select as SelectPrimitive, type WithoutChild} from 'bits-ui';
import ChevronDown from '@lucide/svelte/icons/chevron-down';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithoutChild<SelectPrimitive.TriggerProps> = $props();
</script>
<SelectPrimitive.Trigger
bind:ref
class={cn(
'flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[placeholder]:text-muted-foreground [&>span]:line-clamp-1',
className
)}
{...restProps}
>
{@render children?.()}
<ChevronDown class="size-4 opacity-50"/>
</SelectPrimitive.Trigger>

View File

@@ -1,7 +1,7 @@
import Root from "./separator.svelte";
import Root from './separator.svelte';
export {
Root,
//
Root as Separator,
Root as Separator
};

View File

@@ -1,22 +1,22 @@
<script lang="ts">
import {Separator as SeparatorPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Separator as SeparatorPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
orientation = "horizontal",
orientation = 'horizontal',
...restProps
}: SeparatorPrimitive.RootProps = $props();
</script>
<SeparatorPrimitive.Root
{...restProps}
bind:ref
class={cn(
"bg-border shrink-0",
orientation === "horizontal" ? "h-[1px] w-full" : "min-h-full w-[1px]",
'shrink-0 bg-border',
orientation === 'horizontal' ? 'h-[1px] w-full' : 'min-h-full w-[1px]',
className
)}
{orientation}
{...restProps}
/>

View File

@@ -1,11 +1,11 @@
import {Dialog as SheetPrimitive} from "bits-ui";
import {Dialog as SheetPrimitive} from 'bits-ui';
import Overlay from "./sheet-overlay.svelte";
import Content from "./sheet-content.svelte";
import Header from "./sheet-header.svelte";
import Footer from "./sheet-footer.svelte";
import Title from "./sheet-title.svelte";
import Description from "./sheet-description.svelte";
import Overlay from './sheet-overlay.svelte';
import Content from './sheet-content.svelte';
import Header from './sheet-header.svelte';
import Footer from './sheet-footer.svelte';
import Title from './sheet-title.svelte';
import Description from './sheet-description.svelte';
const Root = SheetPrimitive.Root;
const Close = SheetPrimitive.Close;
@@ -33,5 +33,5 @@ export {
Header as SheetHeader,
Footer as SheetFooter,
Title as SheetTitle,
Description as SheetDescription,
Description as SheetDescription
};

View File

@@ -1,36 +1,38 @@
<script lang="ts" module>
import {tv, type VariantProps} from "tailwind-variants";
import {type VariantProps, tv} from 'tailwind-variants';
export const sheetVariants = tv({
base: "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 gap-4 p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
base: 'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 gap-4 p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
variants: {
side: {
top: "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 border-b",
bottom: "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 border-t",
left: "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
right: "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
},
top: 'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 border-b',
bottom:
'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 border-t',
left: 'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
right:
'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm'
}
},
defaultVariants: {
side: "right",
},
side: 'right'
}
});
export type Side = VariantProps<typeof sheetVariants>["side"];
export type Side = VariantProps<typeof sheetVariants>['side'];
</script>
<script lang="ts">
import {Dialog as SheetPrimitive, type WithoutChildrenOrChild} from "bits-ui";
import X from "@lucide/svelte/icons/x";
import type {Snippet} from "svelte";
import SheetOverlay from "./sheet-overlay.svelte";
import {cn} from "$lib/utils.js";
import {Dialog as SheetPrimitive, type WithoutChildrenOrChild} from 'bits-ui';
import X from '@lucide/svelte/icons/x';
import type {Snippet} from 'svelte';
import SheetOverlay from './sheet-overlay.svelte';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
class: className,
portalProps,
side = "right",
side = 'right',
children,
...restProps
}: WithoutChildrenOrChild<SheetPrimitive.ContentProps> & {
@@ -42,10 +44,10 @@
<SheetPrimitive.Portal {...portalProps}>
<SheetOverlay/>
<SheetPrimitive.Content {...restProps} bind:ref class={cn(sheetVariants({ side }), className)}>
<SheetPrimitive.Content bind:ref class={cn(sheetVariants({ side }), className)} {...restProps}>
{@render children?.()}
<SheetPrimitive.Close
class="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-offset-2 disabled:pointer-events-none"
class="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 class="size-4"/>
<span class="sr-only">Close</span>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {Dialog as SheetPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Dialog as SheetPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -10,7 +10,7 @@
</script>
<SheetPrimitive.Description
{...restProps}
bind:ref
class={cn("text-muted-foreground text-sm", className)}
class={cn('text-sm text-muted-foreground', className)}
{...restProps}
/>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,9 +12,9 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)}
class={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {HTMLAttributes} from "svelte/elements";
import type {WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLAttributes} from 'svelte/elements';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,9 +12,9 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("flex flex-col space-y-2 text-center sm:text-left", className)}
class={cn('flex flex-col space-y-2 text-center sm:text-left', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {Dialog as SheetPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Dialog as SheetPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -10,10 +10,10 @@
</script>
<SheetPrimitive.Overlay
{...restProps}
bind:ref
class={cn(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/80",
'fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
className
)}
{...restProps}
/>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import {Dialog as SheetPrimitive} from "bits-ui";
import {cn} from "$lib/utils.js";
import {Dialog as SheetPrimitive} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -10,7 +10,7 @@
</script>
<SheetPrimitive.Title
{...restProps}
bind:ref
class={cn("text-foreground text-lg font-semibold", className)}
class={cn('text-lg font-semibold text-foreground', className)}
{...restProps}
/>

View File

@@ -1,6 +1,6 @@
export const SIDEBAR_COOKIE_NAME = "sidebar:state";
export const SIDEBAR_COOKIE_NAME = 'sidebar:state';
export const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
export const SIDEBAR_WIDTH = "16rem";
export const SIDEBAR_WIDTH_MOBILE = "18rem";
export const SIDEBAR_WIDTH_ICON = "3rem";
export const SIDEBAR_KEYBOARD_SHORTCUT = "b";
export const SIDEBAR_WIDTH = '16rem';
export const SIDEBAR_WIDTH_MOBILE = '18rem';
export const SIDEBAR_WIDTH_ICON = '3rem';
export const SIDEBAR_KEYBOARD_SHORTCUT = 'b';

View File

@@ -1,6 +1,6 @@
import {IsMobile} from "$lib/hooks/is-mobile.svelte.js";
import {getContext, setContext} from "svelte";
import {SIDEBAR_KEYBOARD_SHORTCUT} from "./constants.js";
import {IsMobile} from '$lib/hooks/is-mobile.svelte.js';
import {getContext, setContext} from 'svelte';
import {SIDEBAR_KEYBOARD_SHORTCUT} from './constants.js';
type Getter<T> = () => T;
@@ -24,9 +24,9 @@ class SidebarState {
readonly props: SidebarStateProps;
open = $derived.by(() => this.props.open());
openMobile = $state(false);
setOpen: SidebarStateProps["setOpen"];
state = $derived.by(() => (this.open ? "expanded" : "collapsed"));
setOpen: SidebarStateProps['setOpen'];
#isMobile: IsMobile;
state = $derived.by(() => (this.open ? 'expanded' : 'collapsed'));
constructor(props: SidebarStateProps) {
this.setOpen = props.setOpen;
@@ -53,13 +53,11 @@ class SidebarState {
};
toggle = () => {
return this.#isMobile.current
? (this.openMobile = !this.openMobile)
: this.setOpen(!this.open);
return this.#isMobile.current ? (this.openMobile = !this.openMobile) : this.setOpen(!this.open);
};
}
const SYMBOL_KEY = "scn-sidebar";
const SYMBOL_KEY = 'scn-sidebar';
/**
* Instantiates a new `SidebarState` instance and sets it in the context.

View File

@@ -1,27 +1,27 @@
import {useSidebar} from "./context.svelte.js";
import Content from "./sidebar-content.svelte";
import Footer from "./sidebar-footer.svelte";
import GroupAction from "./sidebar-group-action.svelte";
import GroupContent from "./sidebar-group-content.svelte";
import GroupLabel from "./sidebar-group-label.svelte";
import Group from "./sidebar-group.svelte";
import Header from "./sidebar-header.svelte";
import Input from "./sidebar-input.svelte";
import Inset from "./sidebar-inset.svelte";
import MenuAction from "./sidebar-menu-action.svelte";
import MenuBadge from "./sidebar-menu-badge.svelte";
import MenuButton from "./sidebar-menu-button.svelte";
import MenuItem from "./sidebar-menu-item.svelte";
import MenuSkeleton from "./sidebar-menu-skeleton.svelte";
import MenuSubButton from "./sidebar-menu-sub-button.svelte";
import MenuSubItem from "./sidebar-menu-sub-item.svelte";
import MenuSub from "./sidebar-menu-sub.svelte";
import Menu from "./sidebar-menu.svelte";
import Provider from "./sidebar-provider.svelte";
import Rail from "./sidebar-rail.svelte";
import Separator from "./sidebar-separator.svelte";
import Trigger from "./sidebar-trigger.svelte";
import Root from "./sidebar.svelte";
import {useSidebar} from './context.svelte.js';
import Content from './sidebar-content.svelte';
import Footer from './sidebar-footer.svelte';
import GroupAction from './sidebar-group-action.svelte';
import GroupContent from './sidebar-group-content.svelte';
import GroupLabel from './sidebar-group-label.svelte';
import Group from './sidebar-group.svelte';
import Header from './sidebar-header.svelte';
import Input from './sidebar-input.svelte';
import Inset from './sidebar-inset.svelte';
import MenuAction from './sidebar-menu-action.svelte';
import MenuBadge from './sidebar-menu-badge.svelte';
import MenuButton from './sidebar-menu-button.svelte';
import MenuItem from './sidebar-menu-item.svelte';
import MenuSkeleton from './sidebar-menu-skeleton.svelte';
import MenuSubButton from './sidebar-menu-sub-button.svelte';
import MenuSubItem from './sidebar-menu-sub-item.svelte';
import MenuSub from './sidebar-menu-sub.svelte';
import Menu from './sidebar-menu.svelte';
import Provider from './sidebar-provider.svelte';
import Rail from './sidebar-rail.svelte';
import Separator from './sidebar-separator.svelte';
import Trigger from './sidebar-trigger.svelte';
import Root from './sidebar.svelte';
export {
Content,
@@ -71,5 +71,5 @@ export {
Separator as SidebarSeparator,
Trigger as SidebarTrigger,
Trigger,
useSidebar,
useSidebar
};

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {HTMLAttributes} from "svelte/elements";
import type {WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLAttributes} from 'svelte/elements';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,13 +12,13 @@
</script>
<div
{...restProps}
bind:this={ref}
data-sidebar="content"
class={cn(
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
'flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden',
className
)}
data-sidebar="content"
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {HTMLAttributes} from "svelte/elements";
import type {WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLAttributes} from 'svelte/elements';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,10 +12,10 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("flex flex-col gap-2 p-2", className)}
data-sidebar="footer"
class={cn('flex flex-col gap-2 p-2', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {Snippet} from "svelte";
import type {HTMLButtonAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {Snippet} from 'svelte';
import type {HTMLButtonAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -16,14 +16,14 @@
const propObj = $derived({
class: cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden",
"group-data-[collapsible=icon]:hidden",
'after:absolute after:-inset-2 after:md:hidden',
'group-data-[collapsible=icon]:hidden',
className
),
"data-sidebar": "group-action",
...restProps,
'data-sidebar': 'group-action',
...restProps
});
</script>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -12,10 +12,10 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("w-full text-sm", className)}
data-sidebar="group-content"
class={cn('w-full text-sm', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {Snippet} from "svelte";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {Snippet} from 'svelte';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -16,12 +16,12 @@
const mergedProps = $derived({
class: cn(
"text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-none transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
'text-sidebar-foreground/70 ring-sidebar-ring flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium outline-none transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
'group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0',
className
),
"data-sidebar": "group-label",
...restProps,
'data-sidebar': 'group-label',
...restProps
});
</script>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {HTMLAttributes} from "svelte/elements";
import type {WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLAttributes} from 'svelte/elements';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,10 +12,10 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("relative flex w-full min-w-0 flex-col p-2", className)}
data-sidebar="group"
class={cn('relative flex w-full min-w-0 flex-col p-2', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {HTMLAttributes} from "svelte/elements";
import type {WithElementRef} from "bits-ui";
import {cn} from "$lib/utils.js";
import type {HTMLAttributes} from 'svelte/elements';
import type {WithElementRef} from 'bits-ui';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -12,10 +12,10 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("flex flex-col gap-2 p-2", className)}
data-sidebar="header"
class={cn('flex flex-col gap-2 p-2', className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,23 +1,23 @@
<script lang="ts">
import {Input} from "$lib/components/ui/input/index.js";
import {cn} from "$lib/utils.js";
import type {ComponentProps} from "svelte";
import {Input} from '$lib/components/ui/input/index.js';
import {cn} from '$lib/utils.js';
import type {ComponentProps} from 'svelte';
let {
ref = $bindable(null),
value = $bindable(""),
value = $bindable(''),
class: className,
...restProps
}: ComponentProps<typeof Input> = $props();
</script>
<Input
{...restProps}
bind:ref
bind:value
data-sidebar="input"
class={cn(
"bg-background focus-visible:ring-sidebar-ring h-8 w-full shadow-none focus-visible:ring-2",
'h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring',
className
)}
data-sidebar="input"
{...restProps}
/>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -12,13 +12,13 @@
</script>
<main
{...restProps}
bind:this={ref}
class={cn(
"bg-background relative flex min-h-svh flex-1 flex-col",
"peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
'relative flex min-h-svh flex-1 flex-col bg-background',
'peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow',
className
)}
{...restProps}
>
{@render children?.()}
</main>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {Snippet} from "svelte";
import type {HTMLButtonAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {Snippet} from 'svelte';
import type {HTMLButtonAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -18,19 +18,19 @@
const mergedProps = $derived({
class: cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground peer-hover/menu-button:text-sidebar-accent-foreground absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 outline-none transition-transform focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0',
// Increases the hit area of the button on mobile.
"after:absolute after:-inset-2 after:md:hidden",
"peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
"group-data-[collapsible=icon]:hidden",
'after:absolute after:-inset-2 after:md:hidden',
'peer-data-[size=sm]/menu-button:top-1',
'peer-data-[size=default]/menu-button:top-1.5',
'peer-data-[size=lg]/menu-button:top-2.5',
'group-data-[collapsible=icon]:hidden',
showOnHover &&
"peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0",
'peer-data-[active=true]/menu-button:text-sidebar-accent-foreground group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 md:opacity-0',
className
),
"data-sidebar": "menu-action",
...restProps,
'data-sidebar': 'menu-action',
...restProps
});
</script>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -12,18 +12,18 @@
</script>
<div
{...restProps}
bind:this={ref}
data-sidebar="menu-badge"
class={cn(
"text-sidebar-foreground pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums",
"peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
"peer-data-[size=sm]/menu-button:top-1",
"peer-data-[size=default]/menu-button:top-1.5",
"peer-data-[size=lg]/menu-button:top-2.5",
"group-data-[collapsible=icon]:hidden",
'pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground',
'peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground',
'peer-data-[size=sm]/menu-button:top-1',
'peer-data-[size=default]/menu-button:top-1.5',
'peer-data-[size=lg]/menu-button:top-2.5',
'group-data-[collapsible=icon]:hidden',
className
)}
data-sidebar="menu-badge"
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,47 +1,45 @@
<script lang="ts" module>
import {tv, type VariantProps} from "tailwind-variants";
import {type VariantProps, tv} from 'tailwind-variants';
export const sidebarMenuButtonVariants = tv({
base: "peer/menu-button ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
base: 'peer/menu-button ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none transition-[width,height,padding] focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:font-medium group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
variants: {
variant: {
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
default: 'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground',
outline:
"bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
'bg-background hover:bg-sidebar-accent hover:text-sidebar-accent-foreground shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]'
},
size: {
default: "h-8 text-sm",
sm: "h-7 text-xs",
lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0",
},
default: 'h-8 text-sm',
sm: 'h-7 text-xs',
lg: 'h-12 text-sm group-data-[collapsible=icon]:!p-0'
}
},
defaultVariants: {
variant: "default",
size: "default",
},
variant: 'default',
size: 'default'
}
});
export type SidebarMenuButtonVariant = VariantProps<
typeof sidebarMenuButtonVariants
>["variant"];
export type SidebarMenuButtonSize = VariantProps<typeof sidebarMenuButtonVariants>["size"];
export type SidebarMenuButtonVariant = VariantProps<typeof sidebarMenuButtonVariants>['variant'];
export type SidebarMenuButtonSize = VariantProps<typeof sidebarMenuButtonVariants>['size'];
</script>
<script lang="ts">
import * as Tooltip from "$lib/components/ui/tooltip/index.js";
import {cn} from "$lib/utils.js";
import {mergeProps, type WithElementRef, type WithoutChildrenOrChild} from "bits-ui";
import type {ComponentProps, Snippet} from "svelte";
import type {HTMLAttributes} from "svelte/elements";
import {useSidebar} from "./context.svelte.js";
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
import {cn} from '$lib/utils.js';
import {type WithElementRef, type WithoutChildrenOrChild, mergeProps} from 'bits-ui';
import type {ComponentProps, Snippet} from 'svelte';
import type {HTMLAttributes} from 'svelte/elements';
import {useSidebar} from './context.svelte.js';
let {
ref = $bindable(null),
class: className,
children,
child,
variant = "default",
size = "default",
variant = 'default',
size = 'default',
isActive = false,
tooltipContent,
tooltipContentProps,
@@ -59,10 +57,10 @@
const buttonProps = $derived({
class: cn(sidebarMenuButtonVariants({variant, size}), className),
"data-sidebar": "menu-button",
"data-size": size,
"data-active": isActive,
...restProps,
'data-sidebar': 'menu-button',
'data-size': size,
'data-active': isActive,
...restProps
});
</script>
@@ -89,7 +87,7 @@
<Tooltip.Content
side="right"
align="center"
hidden={sidebar.state !== "collapsed" || sidebar.isMobile}
hidden={sidebar.state !== 'collapsed' || sidebar.isMobile}
children={tooltipContent}
{...tooltipContentProps}
/>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -12,10 +12,10 @@
</script>
<li
{...restProps}
bind:this={ref}
class={cn("group/menu-item relative", className)}
data-sidebar="menu-item"
class={cn('group/menu-item relative', className)}
{...restProps}
>
{@render children?.()}
</li>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import {Skeleton} from "$lib/components/ui/skeleton/index.js";
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {Skeleton} from '$lib/components/ui/skeleton/index.js';
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -19,10 +19,10 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
data-sidebar="menu-skeleton"
class={cn('flex h-8 items-center gap-2 rounded-md px-2', className)}
{...restProps}
>
{#if showIcon}
<Skeleton class="size-4 rounded-md" data-sidebar="menu-skeleton-icon"/>

View File

@@ -1,36 +1,36 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {Snippet} from "svelte";
import type {HTMLAnchorAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {Snippet} from 'svelte';
import type {HTMLAnchorAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
children,
child,
class: className,
size = "md",
size = 'md',
isActive,
...restProps
}: WithElementRef<HTMLAnchorAttributes> & {
child?: Snippet<[{ props: Record<string, unknown> }]>;
size?: "sm" | "md";
size?: 'sm' | 'md';
isActive?: boolean;
} = $props();
const mergedProps = $derived({
class: cn(
"text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
size === "sm" && "text-xs",
size === "md" && "text-sm",
"group-data-[collapsible=icon]:hidden",
'text-sidebar-foreground ring-sidebar-ring hover:bg-sidebar-accent hover:text-sidebar-accent-foreground active:bg-sidebar-accent active:text-sidebar-accent-foreground [&>svg]:text-sidebar-accent-foreground flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 outline-none focus-visible:ring-2 disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0',
'data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground',
size === 'sm' && 'text-xs',
size === 'md' && 'text-sm',
'group-data-[collapsible=icon]:hidden',
className
),
"data-sidebar": "menu-sub-button",
"data-size": size,
"data-active": isActive,
...restProps,
'data-sidebar': 'menu-sub-button',
'data-size': size,
'data-active': isActive,
...restProps
});
</script>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -9,6 +9,6 @@
}: WithElementRef<HTMLAttributes<HTMLLIElement>> = $props();
</script>
<li {...restProps} bind:this={ref} data-sidebar="menu-sub-item">
<li bind:this={ref} data-sidebar="menu-sub-item" {...restProps}>
{@render children?.()}
</li>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -12,14 +12,14 @@
</script>
<ul
{...restProps}
bind:this={ref}
data-sidebar="menu-sub"
class={cn(
"border-sidebar-border mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l px-2.5 py-0.5",
"group-data-[collapsible=icon]:hidden",
'mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5',
'group-data-[collapsible=icon]:hidden',
className
)}
data-sidebar="menu-sub"
{...restProps}
>
{@render children?.()}
</ul>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
let {
ref = $bindable(null),
@@ -12,10 +12,10 @@
</script>
<ul
{...restProps}
bind:this={ref}
class={cn("flex w-full min-w-0 flex-col gap-1", className)}
data-sidebar="menu"
class={cn('flex w-full min-w-0 flex-col gap-1', className)}
{...restProps}
>
{@render children?.()}
</ul>

View File

@@ -1,9 +1,15 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {SIDEBAR_COOKIE_MAX_AGE, SIDEBAR_COOKIE_NAME, SIDEBAR_WIDTH, SIDEBAR_WIDTH_ICON,} from "./constants.js";
import {setSidebar} from "./context.svelte.js";
import * as Tooltip from '$lib/components/ui/tooltip/index.js';
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {
SIDEBAR_COOKIE_MAX_AGE,
SIDEBAR_COOKIE_NAME,
SIDEBAR_WIDTH,
SIDEBAR_WIDTH_ICON
} from './constants.js';
import {setSidebar} from './context.svelte.js';
let {
ref = $bindable(null),
@@ -27,7 +33,7 @@
// This sets the cookie to keep the sidebar state.
document.cookie = `${SIDEBAR_COOKIE_NAME}=${open}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
},
}
});
</script>
@@ -35,13 +41,13 @@
<Tooltip.Provider delayDuration={0}>
<div
{...restProps}
bind:this={ref}
style="--sidebar-width: {SIDEBAR_WIDTH}; --sidebar-width-icon: {SIDEBAR_WIDTH_ICON}; {style}"
class={cn(
"group/sidebar-wrapper has-[[data-variant=inset]]:bg-sidebar flex min-h-svh w-full",
'group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar',
className
)}
style="--sidebar-width: {SIDEBAR_WIDTH}; --sidebar-width-icon: {SIDEBAR_WIDTH_ICON}; {style}"
bind:this={ref}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {useSidebar} from "./context.svelte.js";
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {useSidebar} from './context.svelte.js';
let {
ref = $bindable(null),
@@ -15,22 +15,22 @@
</script>
<button
{...restProps}
aria-label="Toggle Sidebar"
bind:this={ref}
data-sidebar="rail"
aria-label="Toggle Sidebar"
tabIndex={-1}
onclick={() => sidebar.toggle()}
title="Toggle Sidebar"
class={cn(
"hover:after:bg-sidebar-border absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex",
"[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
"group-data-[collapsible=offcanvas]:hover:bg-sidebar group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full",
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
'absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] hover:after:bg-sidebar-border group-data-[side=left]:-right-4 group-data-[side=right]:left-0 sm:flex',
'[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize',
'[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize',
'group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar',
'[[data-side=left][data-collapsible=offcanvas]_&]:-right-2',
'[[data-side=right][data-collapsible=offcanvas]_&]:-left-2',
className
)}
data-sidebar="rail"
onclick={() => sidebar.toggle()}
tabIndex={-1}
title="Toggle Sidebar"
{...restProps}
>
{@render children?.()}
</button>

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import {Separator} from "$lib/components/ui/separator/index.js";
import {cn} from "$lib/utils.js";
import type {ComponentProps} from "svelte";
import {Separator} from '$lib/components/ui/separator/index.js';
import {cn} from '$lib/utils.js';
import type {ComponentProps} from 'svelte';
let {
ref = $bindable(null),
@@ -11,8 +11,8 @@
</script>
<Separator
{...restProps}
bind:ref
class={cn("bg-sidebar-border mx-2 w-auto", className)}
data-sidebar="separator"
class={cn('mx-2 w-auto bg-sidebar-border', className)}
{...restProps}
/>

View File

@@ -1,8 +1,9 @@
<script lang="ts">
import {Button} from "$lib/components/ui/button/index.js";
import {cn} from "$lib/utils.js";
import type {ComponentProps} from "svelte";
import {useSidebar} from "./context.svelte.js";
import {Button} from '$lib/components/ui/button/index.js';
import {cn} from '$lib/utils.js';
import PanelLeft from '@lucide/svelte/icons/panel-left';
import type {ComponentProps} from 'svelte';
import {useSidebar} from './context.svelte.js';
let {
ref = $bindable(null),
@@ -17,16 +18,16 @@
</script>
<Button
{...restProps}
class={cn("h-7 w-7", className)}
data-sidebar="trigger"
type="button"
onclick={(e) => {
onclick?.(e);
sidebar.toggle();
}}
size="icon"
type="button"
data-sidebar="trigger"
variant="ghost"
size="icon"
class={cn('h-7 w-7', className)}
{...restProps}
>
<PanelLeft/>
<span class="sr-only">Toggle Sidebar</span>

View File

@@ -1,31 +1,32 @@
<script lang="ts">
import {cn} from "$lib/utils.js";
import type {WithElementRef} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {SIDEBAR_WIDTH_MOBILE} from "./constants.js";
import {useSidebar} from "./context.svelte.js";
import * as Sheet from '$lib/components/ui/sheet/index.js';
import {cn} from '$lib/utils.js';
import type {WithElementRef} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {SIDEBAR_WIDTH_MOBILE} from './constants.js';
import {useSidebar} from './context.svelte.js';
let {
ref = $bindable(null),
side = "left",
variant = "sidebar",
collapsible = "offcanvas",
side = 'left',
variant = 'sidebar',
collapsible = 'offcanvas',
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
side?: "left" | "right";
variant?: "sidebar" | "floating" | "inset";
collapsible?: "offcanvas" | "icon" | "none";
side?: 'left' | 'right';
variant?: 'sidebar' | 'floating' | 'inset';
collapsible?: 'offcanvas' | 'icon' | 'none';
} = $props();
const sidebar = useSidebar();
</script>
{#if collapsible === "none"}
{#if collapsible === 'none'}
<div
class={cn(
"bg-sidebar text-sidebar-foreground flex h-full w-[var(--sidebar-width)] flex-col",
'flex h-full w-[var(--sidebar-width)] flex-col bg-sidebar text-sidebar-foreground',
className
)}
bind:this={ref}
@@ -34,14 +35,11 @@
{@render children?.()}
</div>
{:else if sidebar.isMobile}
<Sheet.Root
bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)}
{...restProps}
>
<Sheet.Root bind:open={() => sidebar.openMobile, (v) => sidebar.setOpenMobile(v)} {...restProps}>
<Sheet.Content
data-sidebar="sidebar"
data-mobile="true"
class="bg-sidebar text-sidebar-foreground w-[var(--sidebar-width)] p-0 [&>button]:hidden"
class="w-[var(--sidebar-width)] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
style="--sidebar-width: {SIDEBAR_WIDTH_MOBILE};"
{side}
>
@@ -53,40 +51,40 @@
{:else}
<div
bind:this={ref}
class="text-sidebar-foreground group peer hidden md:block"
class="group peer hidden text-sidebar-foreground md:block"
data-state={sidebar.state}
data-collapsible={sidebar.state === "collapsed" ? collapsible : ""}
data-collapsible={sidebar.state === 'collapsed' ? collapsible : ''}
data-variant={variant}
data-side={side}
>
<!-- This is what handles the sidebar gap on desktop -->
<div
class={cn(
"relative h-svh w-[var(--sidebar-width)] bg-transparent transition-[width] duration-200 ease-linear",
"group-data-[collapsible=offcanvas]:w-0",
"group-data-[side=right]:rotate-180",
variant === "floating" || variant === "inset"
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
: "group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)]"
'relative h-svh w-[var(--sidebar-width)] bg-transparent transition-[width] duration-200 ease-linear',
'group-data-[collapsible=offcanvas]:w-0',
'group-data-[side=right]:rotate-180',
variant === 'floating' || variant === 'inset'
? 'group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]'
: 'group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)]'
)}
></div>
<div
class={cn(
"fixed inset-y-0 z-10 hidden h-svh w-[var(--sidebar-width)] transition-[left,right,width] duration-200 ease-linear md:flex",
side === "left"
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
'fixed inset-y-0 z-10 hidden h-svh w-[var(--sidebar-width)] transition-[left,right,width] duration-200 ease-linear md:flex',
side === 'left'
? 'left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]'
: 'right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]',
// Adjust the padding for floating and inset variants.
variant === "floating" || variant === "inset"
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
: "group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)] group-data-[side=left]:border-r group-data-[side=right]:border-l",
variant === 'floating' || variant === 'inset'
? 'p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]'
: 'group-data-[collapsible=icon]:w-[var(--sidebar-width-icon)] group-data-[side=left]:border-r group-data-[side=right]:border-l',
className
)}
{...restProps}
>
<div
data-sidebar="sidebar"
class="bg-sidebar group-data-[variant=floating]:border-sidebar-border flex h-full w-full flex-col group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:shadow"
class="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
>
{@render children?.()}
</div>

View File

@@ -1,7 +1,7 @@
import Root from "./skeleton.svelte";
import Root from './skeleton.svelte';
export {
Root,
//
Root as Skeleton,
Root as Skeleton
};

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import type {WithElementRef, WithoutChildren} from "bits-ui";
import type {HTMLAttributes} from "svelte/elements";
import {cn} from "$lib/utils.js";
import type {WithElementRef, WithoutChildren} from 'bits-ui';
import type {HTMLAttributes} from 'svelte/elements';
import {cn} from '$lib/utils.js';
let {
ref = $bindable(null),
@@ -11,7 +11,7 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn("bg-primary/10 animate-pulse rounded-md", className)}
class={cn('animate-pulse rounded-md bg-primary/10', className)}
{...restProps}
></div>

View File

@@ -0,0 +1,28 @@
import Root from './table.svelte';
import Body from './table-body.svelte';
import Caption from './table-caption.svelte';
import Cell from './table-cell.svelte';
import Footer from './table-footer.svelte';
import Head from './table-head.svelte';
import Header from './table-header.svelte';
import Row from './table-row.svelte';
export {
Root,
Body,
Caption,
Cell,
Footer,
Head,
Header,
Row,
//
Root as Table,
Body as TableBody,
Caption as TableCaption,
Cell as TableCell,
Footer as TableFooter,
Head as TableHead,
Header as TableHeader,
Row as TableRow
};

Some files were not shown because too many files have changed in this diff Show More