update shadcn components

This commit is contained in:
maxDorninger
2025-08-02 03:24:13 +02:00
parent fb095e61cb
commit 56a215de97
259 changed files with 3871 additions and 1186 deletions

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Accordion as AccordionPrimitive, type WithoutChild } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Accordion as AccordionPrimitive, type WithoutChild } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -13,7 +13,7 @@
<AccordionPrimitive.Content
bind:ref
class={cn(
'overflow-hidden text-sm data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down',
"data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm",
className
)}
{...restProps}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Accordion as AccordionPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Accordion as AccordionPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -9,4 +9,4 @@
}: AccordionPrimitive.ItemProps = $props();
</script>
<AccordionPrimitive.Item {...restProps} bind:ref class={cn('border-b', className)} />
<AccordionPrimitive.Item bind:ref class={cn("border-b", className)} {...restProps} />

View File

@@ -1,7 +1,7 @@
<script lang="ts">
import { Accordion as AccordionPrimitive, type WithoutChild } from 'bits-ui';
import ChevronDown from '@lucide/svelte/icons/chevron-down';
import { cn } from '$lib/utils.js';
import { Accordion as AccordionPrimitive, type WithoutChild } from "bits-ui";
import ChevronDown from "@lucide/svelte/icons/chevron-down";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -10,20 +10,22 @@
children,
...restProps
}: WithoutChild<AccordionPrimitive.TriggerProps> & {
level?: AccordionPrimitive.HeaderProps['level'];
level?: AccordionPrimitive.HeaderProps["level"];
} = $props();
</script>
<AccordionPrimitive.Header class="flex" {level}>
<AccordionPrimitive.Header {level} class="flex">
<AccordionPrimitive.Trigger
bind:ref
class={cn(
'flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180',
"flex flex-1 items-center justify-between py-4 text-sm font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
className
)}
{...restProps}
>
{@render children?.()}
<ChevronDown class="size-4 shrink-0 text-muted-foreground transition-transform duration-200" />
<ChevronDown
class="text-muted-foreground size-4 shrink-0 transition-transform duration-200"
/>
</AccordionPrimitive.Trigger>
</AccordionPrimitive.Header>

View File

@@ -1,7 +1,7 @@
import { Accordion as AccordionPrimitive } from 'bits-ui';
import Content from './accordion-content.svelte';
import Item from './accordion-item.svelte';
import Trigger from './accordion-trigger.svelte';
import { Accordion as AccordionPrimitive } from "bits-ui";
import Content from "./accordion-content.svelte";
import Item from "./accordion-item.svelte";
import Trigger from "./accordion-trigger.svelte";
const Root = AccordionPrimitive.Root;
export {
@@ -13,5 +13,5 @@ export {
Root as Accordion,
Content as AccordionContent,
Item as AccordionItem,
Trigger as AccordionTrigger
Trigger as AccordionTrigger,
};

View File

@@ -0,0 +1,13 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import { buttonVariants } from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";
let {
class: className,
ref = $bindable(null),
...restProps
}: AlertDialogPrimitive.ActionProps = $props();
</script>
<AlertDialogPrimitive.Action bind:ref class={cn(buttonVariants(), className)} {...restProps} />

View File

@@ -0,0 +1,17 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import { buttonVariants } from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";
let {
class: className,
ref = $bindable(null),
...restProps
}: AlertDialogPrimitive.CancelProps = $props();
</script>
<AlertDialogPrimitive.Cancel
bind:ref
class={cn(buttonVariants({ variant: "outline" }), "mt-2 sm:mt-0", className)}
{...restProps}
/>

View File

@@ -0,0 +1,26 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive, type WithoutChild } from "bits-ui";
import AlertDialogOverlay from "./alert-dialog-overlay.svelte";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
portalProps,
...restProps
}: WithoutChild<AlertDialogPrimitive.ContentProps> & {
portalProps?: AlertDialogPrimitive.PortalProps;
} = $props();
</script>
<AlertDialogPrimitive.Portal {...portalProps}>
<AlertDialogOverlay />
<AlertDialogPrimitive.Content
bind:ref
class={cn(
"bg-background 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%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 sm:rounded-lg",
className
)}
{...restProps}
/>
</AlertDialogPrimitive.Portal>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
class: className,
ref = $bindable(null),
...restProps
}: AlertDialogPrimitive.DescriptionProps = $props();
</script>
<AlertDialogPrimitive.Description
bind:ref
class={cn("text-muted-foreground text-sm", 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 { 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 space-y-2 text-center sm:text-left", className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
class: className,
ref = $bindable(null),
...restProps
}: AlertDialogPrimitive.OverlayProps = $props();
</script>
<AlertDialogPrimitive.Overlay
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",
className
)}
{...restProps}
/>

View File

@@ -0,0 +1,18 @@
<script lang="ts">
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
class: className,
level = 3,
ref = $bindable(null),
...restProps
}: AlertDialogPrimitive.TitleProps = $props();
</script>
<AlertDialogPrimitive.Title
bind:ref
class={cn("text-lg font-semibold", className)}
{level}
{...restProps}
/>

View File

@@ -0,0 +1,40 @@
import { AlertDialog as AlertDialogPrimitive } from "bits-ui";
import Title from "./alert-dialog-title.svelte";
import Action from "./alert-dialog-action.svelte";
import Cancel from "./alert-dialog-cancel.svelte";
import Footer from "./alert-dialog-footer.svelte";
import Header from "./alert-dialog-header.svelte";
import Overlay from "./alert-dialog-overlay.svelte";
import Content from "./alert-dialog-content.svelte";
import Description from "./alert-dialog-description.svelte";
const Root = AlertDialogPrimitive.Root;
const Trigger = AlertDialogPrimitive.Trigger;
const Portal = AlertDialogPrimitive.Portal;
export {
Root,
Title,
Action,
Cancel,
Portal,
Footer,
Header,
Trigger,
Overlay,
Content,
Description,
//
Root as AlertDialog,
Title as AlertDialogTitle,
Action as AlertDialogAction,
Cancel as AlertDialogCancel,
Portal as AlertDialogPortal,
Footer as AlertDialogFooter,
Header as AlertDialogHeader,
Trigger as AlertDialogTrigger,
Overlay as AlertDialogOverlay,
Content as AlertDialogContent,
Description as AlertDialogDescription,
};

View File

@@ -0,0 +1,16 @@
<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("text-sm [&_p]:leading-relaxed", className)} {...restProps}>
{@render children?.()}
</div>

View File

@@ -0,0 +1,24 @@
<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,
level = 5,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
level?: 1 | 2 | 3 | 4 | 5 | 6;
} = $props();
</script>
<div
bind:this={ref}
aria-level={level}
class={cn("mb-1 font-medium leading-none tracking-tight", className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -0,0 +1,39 @@
<script lang="ts" module>
import { type VariantProps, tv } from "tailwind-variants";
export const alertVariants = tv({
base: "[&>svg]:text-foreground relative w-full rounded-lg border px-4 py-3 text-sm [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg~*]:pl-7",
variants: {
variant: {
default: "bg-background text-foreground",
destructive:
"border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive",
},
},
defaultVariants: {
variant: "default",
},
});
export type AlertVariant = VariantProps<typeof alertVariants>["variant"];
</script>
<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,
variant = "default",
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
variant?: AlertVariant;
} = $props();
</script>
<div bind:this={ref} class={cn(alertVariants({ variant }), className)} {...restProps} role="alert">
{@render children?.()}
</div>

View File

@@ -0,0 +1,14 @@
import Root from "./alert.svelte";
import Description from "./alert-description.svelte";
import Title from "./alert-title.svelte";
export { alertVariants, type AlertVariant } from "./alert.svelte";
export {
Root,
Description,
Title,
//
Root as Alert,
Description as AlertDescription,
Title as AlertTitle,
};

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,
@@ -11,6 +11,6 @@
<AvatarPrimitive.Fallback
bind:ref
class={cn('flex size-full items-center justify-center bg-muted', className)}
class={cn("bg-muted flex size-full items-center justify-center", 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,
@@ -15,6 +15,6 @@
bind:ref
{src}
{alt}
class={cn('aspect-square size-full', className)}
class={cn("aspect-square size-full", className)}
{...restProps}
/>

View File

@@ -1,11 +1,11 @@
<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>
@@ -13,6 +13,6 @@
<AvatarPrimitive.Root
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,36 +1,36 @@
<script lang="ts" module>
import { type VariantProps, tv } from 'tailwind-variants';
import { type VariantProps, tv } from "tailwind-variants";
export const badgeVariants = tv({
base: 'focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2',
base: "focus:ring-ring inline-flex select-none items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-offset-2",
variants: {
variant: {
default: 'bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow',
default:
"bg-primary text-primary-foreground hover:bg-primary/80 border-transparent shadow",
secondary:
'bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent',
"bg-secondary text-secondary-foreground hover:bg-secondary/80 border-transparent",
destructive:
'bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow',
outline: 'text-foreground'
}
"bg-destructive text-destructive-foreground hover:bg-destructive/80 border-transparent shadow",
outline: "text-foreground",
},
},
defaultVariants: {
variant: 'default'
}
variant: "default",
},
});
export type BadgeVariant = VariantProps<typeof badgeVariants>['variant'];
export type BadgeVariant = VariantProps<typeof badgeVariants>["variant"];
</script>
<script lang="ts">
import type { WithElementRef } from 'bits-ui';
import type { HTMLAnchorAttributes } from 'svelte/elements';
import { cn } from '$lib/utils.js';
import type { WithElementRef } from "bits-ui";
import type { HTMLAnchorAttributes } from "svelte/elements";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
href,
class: className,
variant = 'default',
variant = "default",
children,
...restProps
}: WithElementRef<HTMLAnchorAttributes> & {
@@ -39,11 +39,11 @@
</script>
<svelte:element
this={href ? 'a' : 'span'}
{...restProps}
this={href ? "a" : "span"}
bind:this={ref}
class={cn(badgeVariants({ variant }), className)}
{href}
class={cn(badgeVariants({ variant }), className)}
{...restProps}
>
{@render children?.()}
</svelte:element>

View File

@@ -1,2 +1,2 @@
export { default as Badge } from './badge.svelte';
export { badgeVariants, type BadgeVariant } from './badge.svelte';
export { default as Badge } from "./badge.svelte";
export { badgeVariants, type BadgeVariant } from "./badge.svelte";

View File

@@ -1,8 +1,8 @@
<script lang="ts">
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';
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),
@@ -12,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 bind:this={ref} class={cn('inline-flex items-center gap-1.5', className)} {...restProps}>
<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),
@@ -14,7 +14,7 @@
<ol
bind:this={ref}
class={cn(
'flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5',
"text-muted-foreground flex flex-wrap items-center gap-1.5 break-words text-sm sm:gap-2.5",
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,12 +12,12 @@
</script>
<span
{...restProps}
aria-current="page"
aria-disabled="true"
bind:this={ref}
class={cn('font-normal text-foreground', className)}
role="link"
aria-disabled="true"
aria-current="page"
class={cn("text-foreground font-normal", className)}
{...restProps}
>
{@render children?.()}
</span>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
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';
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),
@@ -15,7 +15,7 @@
<li
role="presentation"
aria-hidden="true"
class={cn('[&>svg]:size-3.5', className)}
class={cn("[&>svg]:size-3.5", className)}
bind:this={ref}
{...restProps}
>

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(),

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,35 +1,36 @@
<script lang="ts" module>
import type { WithElementRef } from 'bits-ui';
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
import { type VariantProps, tv } 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> & {
@@ -39,22 +40,27 @@
</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

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

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.CellProps = $props();
</script>
<CalendarPrimitive.Cell
class={cn(
"[&:has([data-selected])]:bg-accent [&:has([data-selected][data-outside-month])]:bg-accent/50 relative p-0 text-center text-sm focus-within:relative focus-within:z-20 [&:has([data-selected])]:rounded-md",
className
)}
bind:ref
{...restProps}
/>

View File

@@ -0,0 +1,31 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { buttonVariants } from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.DayProps = $props();
</script>
<CalendarPrimitive.Day
class={cn(
buttonVariants({ variant: "ghost" }),
"size-8 p-0 font-normal",
// Today
"[&[data-today]:not([data-selected])]:bg-accent [&[data-today]:not([data-selected])]:text-accent-foreground",
// Selected
"data-[selected]:bg-primary data-[selected]:text-primary-foreground data-[selected]:hover:bg-primary data-[selected]:hover:text-primary-foreground data-[selected]:focus:bg-primary data-[selected]:focus:text-primary-foreground data-[selected]:opacity-100",
// Disabled
"data-[disabled]:text-muted-foreground data-[disabled]:opacity-50",
// Unavailable
"data-[unavailable]:text-destructive-foreground data-[unavailable]:line-through",
// Outside months
"data-[outside-month]:text-muted-foreground [&[data-outside-month][data-selected]]:bg-accent/50 [&[data-outside-month][data-selected]]:text-muted-foreground data-[outside-month]:pointer-events-none data-[outside-month]:opacity-50 [&[data-outside-month][data-selected]]:opacity-30",
className
)}
bind:ref
{...restProps}
/>

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.GridBodyProps = $props();
</script>
<CalendarPrimitive.GridBody bind:ref class={cn(className)} {...restProps} />

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.GridHeadProps = $props();
</script>
<CalendarPrimitive.GridHead bind:ref class={cn(className)} {...restProps} />

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.GridRowProps = $props();
</script>
<CalendarPrimitive.GridRow bind:ref class={cn("flex", className)} {...restProps} />

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.GridProps = $props();
</script>
<CalendarPrimitive.Grid
bind:ref
class={cn("w-full border-collapse space-y-1", className)}
{...restProps}
/>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.HeadCellProps = $props();
</script>
<CalendarPrimitive.HeadCell
bind:ref
class={cn("text-muted-foreground w-8 rounded-md text-[0.8rem] font-normal", className)}
{...restProps}
/>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.HeaderProps = $props();
</script>
<CalendarPrimitive.Header
bind:ref
class={cn("relative flex w-full items-center justify-between pt-1", className)}
{...restProps}
/>

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: CalendarPrimitive.HeadingProps = $props();
</script>
<CalendarPrimitive.Heading bind:ref class={cn("text-sm font-medium", 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("mt-4 flex flex-col space-y-4 sm:flex-row sm:space-x-4 sm:space-y-0", className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import ChevronRight from "@lucide/svelte/icons/chevron-right";
import { buttonVariants } from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: CalendarPrimitive.NextButtonProps = $props();
</script>
{#snippet Fallback()}
<ChevronRight />
{/snippet}
<CalendarPrimitive.NextButton
bind:ref
class={cn(
buttonVariants({ variant: "outline" }),
"size-7 bg-transparent p-0 opacity-50 hover:opacity-100",
className
)}
{...restProps}
children={children || Fallback}
/>

View File

@@ -0,0 +1,28 @@
<script lang="ts">
import { Calendar as CalendarPrimitive } from "bits-ui";
import ChevronLeft from "@lucide/svelte/icons/chevron-left";
import { buttonVariants } from "$lib/components/ui/button/index.js";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: CalendarPrimitive.PrevButtonProps = $props();
</script>
{#snippet Fallback()}
<ChevronLeft />
{/snippet}
<CalendarPrimitive.PrevButton
bind:ref
class={cn(
buttonVariants({ variant: "outline" }),
"size-7 bg-transparent p-0 opacity-50 hover:opacity-100",
className
)}
{...restProps}
children={children || Fallback}
/>

View File

@@ -0,0 +1,61 @@
<script lang="ts">
import { Calendar as CalendarPrimitive, type WithoutChildrenOrChild } from "bits-ui";
import * as Calendar from "./index.js";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
value = $bindable(),
placeholder = $bindable(),
class: className,
weekdayFormat = "short",
...restProps
}: WithoutChildrenOrChild<CalendarPrimitive.RootProps> = $props();
</script>
<!--
Discriminated Unions + Destructing (required for bindable) do not
get along, so we shut typescript up by casting `value` to `never`.
-->
<CalendarPrimitive.Root
bind:value={value as never}
bind:ref
bind:placeholder
{weekdayFormat}
class={cn("p-3", className)}
{...restProps}
>
{#snippet children({ months, weekdays })}
<Calendar.Header>
<Calendar.PrevButton />
<Calendar.Heading />
<Calendar.NextButton />
</Calendar.Header>
<Calendar.Months>
{#each months as month (month)}
<Calendar.Grid>
<Calendar.GridHead>
<Calendar.GridRow class="flex">
{#each weekdays as weekday (weekday)}
<Calendar.HeadCell>
{weekday.slice(0, 2)}
</Calendar.HeadCell>
{/each}
</Calendar.GridRow>
</Calendar.GridHead>
<Calendar.GridBody>
{#each month.weeks as weekDates (weekDates)}
<Calendar.GridRow class="mt-2 w-full">
{#each weekDates as date (date)}
<Calendar.Cell {date} month={month.value}>
<Calendar.Day />
</Calendar.Cell>
{/each}
</Calendar.GridRow>
{/each}
</Calendar.GridBody>
</Calendar.Grid>
{/each}
</Calendar.Months>
{/snippet}
</CalendarPrimitive.Root>

View File

@@ -0,0 +1,30 @@
import Root from "./calendar.svelte";
import Cell from "./calendar-cell.svelte";
import Day from "./calendar-day.svelte";
import Grid from "./calendar-grid.svelte";
import Header from "./calendar-header.svelte";
import Months from "./calendar-months.svelte";
import GridRow from "./calendar-grid-row.svelte";
import Heading from "./calendar-heading.svelte";
import GridBody from "./calendar-grid-body.svelte";
import GridHead from "./calendar-grid-head.svelte";
import HeadCell from "./calendar-head-cell.svelte";
import NextButton from "./calendar-next-button.svelte";
import PrevButton from "./calendar-prev-button.svelte";
export {
Day,
Cell,
Grid,
Header,
Months,
GridRow,
Heading,
GridBody,
GridHead,
HeadCell,
NextButton,
PrevButton,
//
Root as Calendar,
};

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 bind:this={ref} class={cn("p-6", className)} {...restProps}>
{@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-sm text-muted-foreground', className)}>
<p bind:this={ref} class={cn("text-muted-foreground text-sm", className)} {...restProps}>
{@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 bind:this={ref} class={cn("flex items-center p-6 pt-0", className)} {...restProps}>
{@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 bind:this={ref} class={cn("flex flex-col space-y-1.5 p-6 pb-0", className)} {...restProps}>
{@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),
@@ -15,11 +15,11 @@
</script>
<div
{...restProps}
role="heading"
aria-level={level}
bind:this={ref}
class={cn('font-semibold leading-none tracking-tight', className)}
role="heading"
class={cn("font-semibold leading-none tracking-tight", className)}
{...restProps}
>
{@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),
@@ -12,9 +12,9 @@
</script>
<div
{...restProps}
bind:this={ref}
class={cn('rounded-xl border bg-card text-card-foreground shadow', className)}
class={cn("bg-card text-card-foreground rounded-xl border shadow", className)}
{...restProps}
>
{@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,9 +1,9 @@
<script lang="ts">
import emblaCarouselSvelte from 'embla-carousel-svelte';
import type { WithElementRef } from 'bits-ui';
import type { HTMLAttributes } from 'svelte/elements';
import { getEmblaContext } from './context.js';
import { cn } from '$lib/utils.js';
import emblaCarouselSvelte from "embla-carousel-svelte";
import type { WithElementRef } from "bits-ui";
import type { HTMLAttributes } from "svelte/elements";
import { getEmblaContext } from "./context.js";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -12,32 +12,32 @@
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
const emblaCtx = getEmblaContext('<Carousel.Content/>');
const emblaCtx = getEmblaContext("<Carousel.Content/>");
</script>
<!-- svelte-ignore event_directive_deprecated -->
<div
class="overflow-hidden"
on:emblaInit={emblaCtx.onInit}
use:emblaCarouselSvelte={{
options: {
container: '[data-embla-container]',
slides: '[data-embla-slide]',
container: "[data-embla-container]",
slides: "[data-embla-slide]",
...emblaCtx.options,
axis: emblaCtx.orientation === 'horizontal' ? 'x' : 'y'
axis: emblaCtx.orientation === "horizontal" ? "x" : "y",
},
plugins: emblaCtx.plugins
plugins: emblaCtx.plugins,
}}
on:emblaInit={emblaCtx.onInit}
>
<div
{...restProps}
bind:this={ref}
class={cn(
'flex',
emblaCtx.orientation === 'horizontal' ? '-ml-4' : '-mt-4 flex-col',
"flex",
emblaCtx.orientation === "horizontal" ? "-ml-4" : "-mt-4 flex-col",
className
)}
data-embla-container=""
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import type { WithElementRef } from 'bits-ui';
import type { HTMLAttributes } from 'svelte/elements';
import { getEmblaContext } from './context.js';
import { cn } from '$lib/utils.js';
import type { WithElementRef } from "bits-ui";
import type { HTMLAttributes } from "svelte/elements";
import { getEmblaContext } from "./context.js";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -11,20 +11,20 @@
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
const emblaCtx = getEmblaContext('<Carousel.Item/>');
const emblaCtx = getEmblaContext("<Carousel.Item/>");
</script>
<div
{...restProps}
aria-roledescription="slide"
bind:this={ref}
role="group"
aria-roledescription="slide"
class={cn(
'min-w-0 shrink-0 grow-0 basis-full',
emblaCtx.orientation === 'horizontal' ? 'pl-4' : 'pt-4',
"min-w-0 shrink-0 grow-0 basis-full",
emblaCtx.orientation === "horizontal" ? "pl-4" : "pt-4",
className
)}
data-embla-slide=""
role="group"
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -1,36 +1,36 @@
<script lang="ts">
import ArrowRight from '@lucide/svelte/icons/arrow-right';
import type { WithoutChildren } from 'bits-ui';
import { getEmblaContext } from './context.js';
import { cn } from '$lib/utils.js';
import { Button, type Props } from '$lib/components/ui/button/index.js';
import ArrowRight from "@lucide/svelte/icons/arrow-right";
import type { WithoutChildren } from "bits-ui";
import { getEmblaContext } from "./context.js";
import { cn } from "$lib/utils.js";
import { Button, type Props } from "$lib/components/ui/button/index.js";
let {
ref = $bindable(null),
class: className,
variant = 'outline',
size = 'icon',
variant = "outline",
size = "icon",
...restProps
}: WithoutChildren<Props> = $props();
const emblaCtx = getEmblaContext('<Carousel.Next/>');
const emblaCtx = getEmblaContext("<Carousel.Next/>");
</script>
<Button
{...restProps}
bind:ref
{variant}
{size}
class={cn(
'absolute size-8 touch-manipulation rounded-full',
emblaCtx.orientation === 'horizontal'
? '-right-12 top-1/2 -translate-y-1/2'
: '-bottom-12 left-1/2 -translate-x-1/2 rotate-90',
"absolute size-8 touch-manipulation rounded-full",
emblaCtx.orientation === "horizontal"
? "-right-12 top-1/2 -translate-y-1/2"
: "-bottom-12 left-1/2 -translate-x-1/2 rotate-90",
className
)}
disabled={!emblaCtx.canScrollNext}
onclick={emblaCtx.scrollNext}
onkeydown={emblaCtx.handleKeyDown}
{size}
{variant}
bind:ref
{...restProps}
>
<ArrowRight />
<span class="sr-only">Next slide</span>

View File

@@ -1,36 +1,36 @@
<script lang="ts">
import ArrowLeft from '@lucide/svelte/icons/arrow-left';
import type { WithoutChildren } from 'bits-ui';
import { getEmblaContext } from './context.js';
import { cn } from '$lib/utils.js';
import { Button, type Props } from '$lib/components/ui/button/index.js';
import ArrowLeft from "@lucide/svelte/icons/arrow-left";
import type { WithoutChildren } from "bits-ui";
import { getEmblaContext } from "./context.js";
import { cn } from "$lib/utils.js";
import { Button, type Props } from "$lib/components/ui/button/index.js";
let {
ref = $bindable(null),
class: className,
variant = 'outline',
size = 'icon',
variant = "outline",
size = "icon",
...restProps
}: WithoutChildren<Props> = $props();
const emblaCtx = getEmblaContext('<Carousel.Previous/>');
const emblaCtx = getEmblaContext("<Carousel.Previous/>");
</script>
<Button
{...restProps}
bind:ref
{variant}
{size}
class={cn(
'absolute size-8 touch-manipulation rounded-full',
emblaCtx.orientation === 'horizontal'
? '-left-12 top-1/2 -translate-y-1/2'
: '-top-12 left-1/2 -translate-x-1/2 rotate-90',
"absolute size-8 touch-manipulation rounded-full",
emblaCtx.orientation === "horizontal"
? "-left-12 top-1/2 -translate-y-1/2"
: "-top-12 left-1/2 -translate-x-1/2 rotate-90",
className
)}
disabled={!emblaCtx.canScrollPrev}
onclick={emblaCtx.scrollPrev}
onkeydown={emblaCtx.handleKeyDown}
{size}
{variant}
{...restProps}
bind:ref
>
<ArrowLeft />
<span class="sr-only">Previous slide</span>

View File

@@ -3,15 +3,15 @@
type CarouselAPI,
type CarouselProps,
type EmblaContext,
setEmblaContext
} from './context.js';
import { cn } from '$lib/utils.js';
setEmblaContext,
} from "./context.js";
import { cn } from "$lib/utils.js";
let {
opts = {},
plugins = [],
setApi = () => {},
orientation = 'horizontal',
orientation = "horizontal",
class: className,
children,
...restProps
@@ -30,7 +30,7 @@
onInit,
scrollSnaps: [],
selectedIndex: 0,
scrollTo
scrollTo,
});
setEmblaContext(carouselState);
@@ -38,11 +38,9 @@
function scrollPrev() {
carouselState.api?.scrollPrev();
}
function scrollNext() {
carouselState.api?.scrollNext();
}
function scrollTo(index: number, jump?: boolean) {
carouselState.api?.scrollTo(index, jump);
}
@@ -57,16 +55,16 @@
$effect(() => {
if (carouselState.api) {
onSelect(carouselState.api);
carouselState.api.on('select', onSelect);
carouselState.api.on('reInit', onSelect);
carouselState.api.on("select", onSelect);
carouselState.api.on("reInit", onSelect);
}
});
function handleKeyDown(e: KeyboardEvent) {
if (e.key === 'ArrowLeft') {
if (e.key === "ArrowLeft") {
e.preventDefault();
scrollPrev();
} else if (e.key === 'ArrowRight') {
} else if (e.key === "ArrowRight") {
e.preventDefault();
scrollNext();
}
@@ -84,11 +82,11 @@
$effect(() => {
return () => {
carouselState.api?.off('select', onSelect);
carouselState.api?.off("select", onSelect);
};
});
</script>
<div {...restProps} aria-roledescription="carousel" class={cn('relative', className)} role="region">
<div class={cn("relative", className)} role="region" aria-roledescription="carousel" {...restProps}>
{@render children?.()}
</div>

View File

@@ -1,11 +1,11 @@
import type { EmblaCarouselSvelteType } from 'embla-carousel-svelte';
import type emblaCarouselSvelte from 'embla-carousel-svelte';
import { getContext, hasContext, setContext } from 'svelte';
import type { WithElementRef } from 'bits-ui';
import type { HTMLAttributes } from 'svelte/elements';
import type { EmblaCarouselSvelteType } from "embla-carousel-svelte";
import type emblaCarouselSvelte from "embla-carousel-svelte";
import { getContext, hasContext, setContext } from "svelte";
import type { WithElementRef } from "bits-ui";
import type { HTMLAttributes } from "svelte/elements";
export type CarouselAPI =
NonNullable<NonNullable<EmblaCarouselSvelteType['$$_attributes']>['on:emblaInit']> extends (
NonNullable<NonNullable<EmblaCarouselSvelteType["$$_attributes"]>["on:emblaInit"]> extends (
evt: CustomEvent<infer CarouselAPI>
) => void
? CarouselAPI
@@ -13,8 +13,8 @@ export type CarouselAPI =
type EmblaCarouselConfig = NonNullable<Parameters<typeof emblaCarouselSvelte>[1]>;
export type CarouselOptions = EmblaCarouselConfig['options'];
export type CarouselPlugins = EmblaCarouselConfig['plugins'];
export type CarouselOptions = EmblaCarouselConfig["options"];
export type CarouselPlugins = EmblaCarouselConfig["plugins"];
////
@@ -22,14 +22,14 @@ export type CarouselProps = {
opts?: CarouselOptions;
plugins?: CarouselPlugins;
setApi?: (api: CarouselAPI | undefined) => void;
orientation?: 'horizontal' | 'vertical';
orientation?: "horizontal" | "vertical";
} & WithElementRef<HTMLAttributes<HTMLDivElement>>;
const EMBLA_CAROUSEL_CONTEXT = Symbol('EMBLA_CAROUSEL_CONTEXT');
const EMBLA_CAROUSEL_CONTEXT = Symbol("EMBLA_CAROUSEL_CONTEXT");
export type EmblaContext = {
api: CarouselAPI | undefined;
orientation: 'horizontal' | 'vertical';
orientation: "horizontal" | "vertical";
scrollNext: () => void;
scrollPrev: () => void;
canScrollNext: boolean;
@@ -48,7 +48,7 @@ export function setEmblaContext(config: EmblaContext): EmblaContext {
return config;
}
export function getEmblaContext(name = 'This component') {
export function getEmblaContext(name = "This component") {
if (!hasContext(EMBLA_CAROUSEL_CONTEXT)) {
throw new Error(`${name} must be used within a <Carousel.Root> component`);
}

View File

@@ -1,8 +1,8 @@
import Root from './carousel.svelte';
import Content from './carousel-content.svelte';
import Item from './carousel-item.svelte';
import Previous from './carousel-previous.svelte';
import Next from './carousel-next.svelte';
import Root from "./carousel.svelte";
import Content from "./carousel-content.svelte";
import Item from "./carousel-item.svelte";
import Previous from "./carousel-previous.svelte";
import Next from "./carousel-next.svelte";
export {
Root,
@@ -15,5 +15,5 @@ export {
Content as CarouselContent,
Item as CarouselItem,
Previous as CarouselPrevious,
Next as CarouselNext
Next as CarouselNext,
};

View File

@@ -1,8 +1,8 @@
<script lang="ts">
import { Checkbox as CheckboxPrimitive, 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 { Checkbox as CheckboxPrimitive, 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";
let {
ref = $bindable(null),
@@ -14,21 +14,21 @@
</script>
<CheckboxPrimitive.Root
{...restProps}
bind:checked
bind:indeterminate
bind:ref
class={cn(
'peer box-content size-4 shrink-0 rounded-sm border border-primary shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground data-[disabled=true]:opacity-50',
"border-primary focus-visible:ring-ring data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground peer box-content size-4 shrink-0 rounded-sm border shadow focus-visible:outline-none focus-visible:ring-1 disabled:cursor-not-allowed disabled:opacity-50 data-[disabled=true]:cursor-not-allowed data-[disabled=true]:opacity-50",
className
)}
bind:checked
bind:ref
bind:indeterminate
{...restProps}
>
{#snippet children({ checked, indeterminate })}
<span class="flex items-center justify-center text-current">
{#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>
{/snippet}

View File

@@ -1,7 +1,6 @@
import Root from './checkbox.svelte';
import Root from "./checkbox.svelte";
export {
Root,
//
Root as Checkbox
Root as Checkbox,
};

View File

@@ -2,16 +2,16 @@
import {
Command as CommandPrimitive,
Dialog as DialogPrimitive,
type WithoutChildrenOrChild
} from 'bits-ui';
import type { Snippet } from 'svelte';
import Command from './command.svelte';
import * as Dialog from '$lib/components/ui/dialog/index.js';
type WithoutChildrenOrChild,
} from "bits-ui";
import type { Snippet } from "svelte";
import Command from "./command.svelte";
import * as Dialog from "$lib/components/ui/dialog/index.js";
let {
open = $bindable(false),
ref = $bindable(null),
value = $bindable(''),
value = $bindable(""),
portalProps,
children,
...restProps
@@ -25,7 +25,7 @@
<Dialog.Root bind:open {...restProps}>
<Dialog.Content class="overflow-hidden p-0" {portalProps}>
<Command
class="**:data-cmdk-group-heading:px-2 **:data-cmdk-group-heading:font-medium [&_[data-cmdk-group]:not([hidden])_~[data-cmdk-group]]:pt-0 **:data-cmdk-group:px-2 [&_[data-cmdk-input-wrapper]_svg]:h-5 [&_[data-cmdk-input-wrapper]_svg]:w-5 **:data-cmdk-input:h-12 **:data-cmdk-item:px-2 **:data-cmdk-item:py-3 [&_[data-cmdk-item]_svg]:h-5 [&_[data-cmdk-item]_svg]:w-5"
class="[&_[data-cmdk-group-heading]]:px-2 [&_[data-cmdk-group-heading]]:font-medium [&_[data-cmdk-group]:not([hidden])_~[data-cmdk-group]]:pt-0 [&_[data-cmdk-group]]:px-2 [&_[data-cmdk-input-wrapper]_svg]:h-5 [&_[data-cmdk-input-wrapper]_svg]:w-5 [&_[data-cmdk-input]]:h-12 [&_[data-cmdk-item]]:px-2 [&_[data-cmdk-item]]:py-3 [&_[data-cmdk-item]_svg]:h-5 [&_[data-cmdk-item]_svg]:w-5"
{...restProps}
bind:value
bind:ref

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Command as CommandPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -9,4 +9,4 @@
}: CommandPrimitive.EmptyProps = $props();
</script>
<CommandPrimitive.Empty bind:ref class={cn('py-6 text-center text-sm', className)} {...restProps} />
<CommandPrimitive.Empty bind:ref class={cn("py-6 text-center text-sm", className)} {...restProps} />

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Command as CommandPrimitive, useId } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Command as CommandPrimitive, useId } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -15,13 +15,15 @@
</script>
<CommandPrimitive.Group
class={cn('overflow-hidden p-1 text-foreground', className)}
class={cn("text-foreground overflow-hidden p-1", className)}
bind:ref
value={value ?? heading ?? `----${useId()}`}
{...restProps}
>
{#if heading}
<CommandPrimitive.GroupHeading class="px-2 py-1.5 text-xs font-medium text-muted-foreground">
<CommandPrimitive.GroupHeading
class="text-muted-foreground px-2 py-1.5 text-xs font-medium"
>
{heading}
</CommandPrimitive.GroupHeading>
{/if}

View File

@@ -1,12 +1,12 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import Search from '@lucide/svelte/icons/search';
import { cn } from '$lib/utils.js';
import { Command as CommandPrimitive } from "bits-ui";
import Search from "@lucide/svelte/icons/search";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
value = $bindable(''),
value = $bindable(""),
...restProps
}: CommandPrimitive.InputProps = $props();
</script>
@@ -15,7 +15,7 @@
<Search class="mr-2 size-4 shrink-0 opacity-50" />
<CommandPrimitive.Input
class={cn(
'flex h-10 w-full rounded-md bg-transparent py-3 text-base outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
"placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-base outline-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
className
)}
bind:ref

View File

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

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Command as CommandPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -11,7 +11,7 @@
<CommandPrimitive.LinkItem
class={cn(
'relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none aria-selected:bg-accent aria-selected:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0',
"aria-selected:bg-accent aria-selected:text-accent-foreground relative flex cursor-default select-none items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
className
)}
bind:ref

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Command as CommandPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -10,7 +10,7 @@
</script>
<CommandPrimitive.List
class={cn('max-h-[300px] overflow-y-auto overflow-x-hidden', className)}
class={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
bind:ref
{...restProps}
/>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Command as CommandPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -9,4 +9,4 @@
}: CommandPrimitive.SeparatorProps = $props();
</script>
<CommandPrimitive.Separator bind:ref class={cn('-mx-1 h-px bg-border', className)} {...restProps} />
<CommandPrimitive.Separator bind:ref class={cn("bg-border -mx-1 h-px", 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,7 +12,7 @@
</script>
<span
class={cn('ml-auto text-xs tracking-widest text-muted-foreground', className)}
class={cn("text-muted-foreground ml-auto text-xs tracking-widest", className)}
{...restProps}
bind:this={ref}
>

View File

@@ -1,9 +1,9 @@
<script lang="ts">
import { Command as CommandPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Command as CommandPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
value = $bindable(''),
value = $bindable(""),
ref = $bindable(null),
class: className,
...restProps
@@ -12,7 +12,7 @@
<CommandPrimitive.Root
class={cn(
'flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground',
"bg-popover text-popover-foreground flex h-full w-full flex-col overflow-hidden rounded-md",
className
)}
bind:ref

View File

@@ -1,15 +1,15 @@
import { Command as CommandPrimitive } from 'bits-ui';
import { Command as CommandPrimitive } from "bits-ui";
import Root from './command.svelte';
import Dialog from './command-dialog.svelte';
import Empty from './command-empty.svelte';
import Group from './command-group.svelte';
import Item from './command-item.svelte';
import Input from './command-input.svelte';
import List from './command-list.svelte';
import Separator from './command-separator.svelte';
import Shortcut from './command-shortcut.svelte';
import LinkItem from './command-link-item.svelte';
import Root from "./command.svelte";
import Dialog from "./command-dialog.svelte";
import Empty from "./command-empty.svelte";
import Group from "./command-group.svelte";
import Item from "./command-item.svelte";
import Input from "./command-input.svelte";
import List from "./command-list.svelte";
import Separator from "./command-separator.svelte";
import Shortcut from "./command-shortcut.svelte";
import LinkItem from "./command-link-item.svelte";
const Loading: typeof CommandPrimitive.Loading = CommandPrimitive.Loading;
@@ -36,5 +36,5 @@ export {
List as CommandList,
Separator as CommandSeparator,
Shortcut as CommandShortcut,
Loading as CommandLoading
Loading as CommandLoading,
};

View File

@@ -0,0 +1,40 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive, type WithoutChildrenOrChild } from "bits-ui";
import Check from "@lucide/svelte/icons/check";
import Minus from "@lucide/svelte/icons/minus";
import type { Snippet } from "svelte";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
checked = $bindable(false),
indeterminate = $bindable(false),
children: childrenProp,
...restProps
}: WithoutChildrenOrChild<ContextMenuPrimitive.CheckboxItemProps> & {
children?: Snippet;
} = $props();
</script>
<ContextMenuPrimitive.CheckboxItem
bind:ref
bind:checked
bind:indeterminate
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",
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")} />
{/if}
</span>
{@render childrenProp?.()}
{/snippet}
</ContextMenuPrimitive.CheckboxItem>

View File

@@ -0,0 +1,24 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
portalProps,
...restProps
}: ContextMenuPrimitive.ContentProps & {
portalProps?: ContextMenuPrimitive.PortalProps;
} = $props();
</script>
<ContextMenuPrimitive.Portal {...portalProps}>
<ContextMenuPrimitive.Content
class={cn(
"bg-popover text-popover-foreground z-50 min-w-[8rem] rounded-md border p-1 shadow-md focus:outline-none",
className
)}
{...restProps}
bind:ref
/>
</ContextMenuPrimitive.Portal>

View File

@@ -0,0 +1,19 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
inset,
...restProps
}: ContextMenuPrimitive.GroupHeadingProps & {
inset?: boolean;
} = $props();
</script>
<ContextMenuPrimitive.GroupHeading
bind:ref
class={cn("text-foreground px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
{...restProps}
/>

View File

@@ -0,0 +1,23 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
inset,
...restProps
}: ContextMenuPrimitive.ItemProps & {
inset?: boolean;
} = $props();
</script>
<ContextMenuPrimitive.Item
class={cn(
"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
inset && "pl-8",
className
)}
bind:ref
{...restProps}
/>

View File

@@ -0,0 +1,30 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive, type WithoutChild } from "bits-ui";
import Circle from "@lucide/svelte/icons/circle";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
children: childrenProp,
...restProps
}: WithoutChild<ContextMenuPrimitive.RadioItemProps> = $props();
</script>
<ContextMenuPrimitive.RadioItem
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",
className
)}
{...restProps}
>
{#snippet children({ checked })}
<span class="absolute left-2 flex size-3.5 items-center justify-center">
{#if checked}
<Circle class="size-2 fill-current" />
{/if}
</span>
{@render childrenProp?.({ checked })}
{/snippet}
</ContextMenuPrimitive.RadioItem>

View File

@@ -0,0 +1,16 @@
<script lang="ts">
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
...restProps
}: ContextMenuPrimitive.SeparatorProps = $props();
</script>
<ContextMenuPrimitive.Separator
bind:ref
class={cn("bg-border -mx-1 my-1 h-px", 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<HTMLSpanElement>> = $props();
</script>
<span
bind:this={ref}
class={cn("text-muted-foreground ml-auto text-xs tracking-widest", className)}
{...restProps}
>
{@render children?.()}
</span>

View File

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

View File

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

View File

@@ -0,0 +1,49 @@
import { ContextMenu as ContextMenuPrimitive } from "bits-ui";
import Item from "./context-menu-item.svelte";
import GroupHeading from "./context-menu-group-heading.svelte";
import Content from "./context-menu-content.svelte";
import Shortcut from "./context-menu-shortcut.svelte";
import RadioItem from "./context-menu-radio-item.svelte";
import Separator from "./context-menu-separator.svelte";
import SubContent from "./context-menu-sub-content.svelte";
import SubTrigger from "./context-menu-sub-trigger.svelte";
import CheckboxItem from "./context-menu-checkbox-item.svelte";
const Sub: typeof ContextMenuPrimitive.Sub = ContextMenuPrimitive.Sub;
const Root: typeof ContextMenuPrimitive.Root = ContextMenuPrimitive.Root;
const Trigger: typeof ContextMenuPrimitive.Trigger = ContextMenuPrimitive.Trigger;
const Group: typeof ContextMenuPrimitive.Group = ContextMenuPrimitive.Group;
const RadioGroup: typeof ContextMenuPrimitive.RadioGroup = ContextMenuPrimitive.RadioGroup;
export {
Sub,
Root,
Item,
Group,
Trigger,
Content,
Shortcut,
Separator,
RadioItem,
GroupHeading,
SubContent,
SubTrigger,
RadioGroup,
CheckboxItem,
//
Root as ContextMenu,
Sub as ContextMenuSub,
Item as ContextMenuItem,
Group as ContextMenuGroup,
Content as ContextMenuContent,
Trigger as ContextMenuTrigger,
Shortcut as ContextMenuShortcut,
RadioItem as ContextMenuRadioItem,
Separator as ContextMenuSeparator,
GroupHeading as ContextMenuGroupHeading,
RadioGroup as ContextMenuRadioGroup,
SubContent as ContextMenuSubContent,
SubTrigger as ContextMenuSubTrigger,
CheckboxItem as ContextMenuCheckboxItem,
};

View File

@@ -0,0 +1,117 @@
import {
type RowData,
type TableOptions,
type TableOptionsResolved,
type TableState,
createTable,
} from "@tanstack/table-core";
/**
* Creates a reactive TanStack table object for Svelte.
* @param options Table options to create the table with.
* @returns A reactive table object.
* @example
* ```svelte
* <script>
* const table = createSvelteTable({ ... })
* </script>
*
* <table>
* <thead>
* {#each table.getHeaderGroups() as headerGroup}
* <tr>
* {#each headerGroup.headers as header}
* <th colspan={header.colSpan}>
* <FlexRender content={header.column.columnDef.header} context={header.getContext()} />
* </th>
* {/each}
* </tr>
* {/each}
* </thead>
* <!-- ... -->
* </table>
* ```
*/
export function createSvelteTable<TData extends RowData>(options: TableOptions<TData>) {
const resolvedOptions: TableOptionsResolved<TData> = mergeObjects(
{
state: {},
onStateChange() {},
renderFallbackValue: null,
mergeOptions: (
defaultOptions: TableOptions<TData>,
options: Partial<TableOptions<TData>>
) => {
return mergeObjects(defaultOptions, options);
},
},
options
);
const table = createTable(resolvedOptions);
let state = $state<Partial<TableState>>(table.initialState);
function updateOptions() {
table.setOptions((prev) => {
return mergeObjects(prev, options, {
state: mergeObjects(state, options.state || {}),
// eslint-disable-next-line @typescript-eslint/no-explicit-any
onStateChange: (updater: any) => {
if (updater instanceof Function) state = updater(state);
else state = mergeObjects(state, updater);
options.onStateChange?.(updater);
},
});
});
}
updateOptions();
$effect.pre(() => {
updateOptions();
});
return table;
}
/**
* Merges objects together while keeping their getters alive.
* Taken from SolidJS: {@link https://github.com/solidjs/solid/blob/24abc825c0996fd2bc8c1de1491efe9a7e743aff/packages/solid/src/server/rendering.ts#L82-L115}
*/
export function mergeObjects<T>(source: T): T;
export function mergeObjects<T, U>(source: T, source1: U): T & U;
export function mergeObjects<T, U, V>(source: T, source1: U, source2: V): T & U & V;
export function mergeObjects<T, U, V, W>(
source: T,
source1: U,
source2: V,
source3: W
): T & U & V & W;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function mergeObjects(...sources: any): any {
const target = {};
for (let i = 0; i < sources.length; i++) {
let source = sources[i];
if (typeof source === "function") source = source();
if (source) {
const descriptors = Object.getOwnPropertyDescriptors(source);
for (const key in descriptors) {
if (key in target) continue;
Object.defineProperty(target, key, {
enumerable: true,
get() {
for (let i = sources.length - 1; i >= 0; i--) {
let s = sources[i];
if (typeof s === "function") s = s();
const v = (s || {})[key];
if (v !== undefined) return v;
}
},
});
}
}
}
return target;
}

View File

@@ -0,0 +1,43 @@
<script lang="ts" module>
import type { CellContext, ColumnDefTemplate, HeaderContext } from "@tanstack/table-core";
type TData = unknown;
type TValue = unknown;
type TContext = unknown;
</script>
<script
lang="ts"
generics="TData, TValue, TContext extends HeaderContext<TData, TValue> | CellContext<TData, TValue>"
>
import { RenderComponentConfig, RenderSnippetConfig } from "./render-helpers.js";
type Props = {
/** The cell or header field of the current cell's column definition. */
content?: TContext extends HeaderContext<TData, TValue>
? ColumnDefTemplate<HeaderContext<TData, TValue>>
: TContext extends CellContext<TData, TValue>
? ColumnDefTemplate<CellContext<TData, TValue>>
: never;
/** The result of the `getContext()` function of the header or cell */
context: TContext;
};
let { content, context }: Props = $props();
</script>
{#if typeof content === "string"}
{content}
{:else if content instanceof Function}
<!-- It's unlikely that a CellContext will be passed to a Header -->
<!-- eslint-disable-next-line @typescript-eslint/no-explicit-any -->
{@const result = content(context as any)}
{#if result instanceof RenderComponentConfig}
{@const { component: Component, props } = result}
<Component {...props} />
{:else if result instanceof RenderSnippetConfig}
{@const { snippet, params } = result}
{@render snippet(params)}
{:else}
{result}
{/if}
{/if}

View File

@@ -0,0 +1,3 @@
export { default as FlexRender } from "./flex-render.svelte";
export { renderComponent, renderSnippet } from "./render-helpers.js";
export { createSvelteTable } from "./data-table.svelte.js";

View File

@@ -0,0 +1,111 @@
import type { Component, ComponentProps, Snippet } from "svelte";
/**
* A helper class to make it easy to identify Svelte components in
* `columnDef.cell` and `columnDef.header` properties.
*
* > NOTE: This class should only be used internally by the adapter. If you're
* reading this and you don't know what this is for, you probably don't need it.
*
* @example
* ```svelte
* {@const result = content(context as any)}
* {#if result instanceof RenderComponentConfig}
* {@const { component: Component, props } = result}
* <Component {...props} />
* {/if}
* ```
*/
export class RenderComponentConfig<TComponent extends Component> {
component: TComponent;
props: ComponentProps<TComponent> | Record<string, never>;
constructor(
component: TComponent,
props: ComponentProps<TComponent> | Record<string, never> = {}
) {
this.component = component;
this.props = props;
}
}
/**
* A helper class to make it easy to identify Svelte Snippets in `columnDef.cell` and `columnDef.header` properties.
*
* > NOTE: This class should only be used internally by the adapter. If you're
* reading this and you don't know what this is for, you probably don't need it.
*
* @example
* ```svelte
* {@const result = content(context as any)}
* {#if result instanceof RenderSnippetConfig}
* {@const { snippet, params } = result}
* {@render snippet(params)}
* {/if}
* ```
*/
export class RenderSnippetConfig<TProps> {
snippet: Snippet<[TProps]>;
params: TProps;
constructor(snippet: Snippet<[TProps]>, params: TProps) {
this.snippet = snippet;
this.params = params;
}
}
/**
* A helper function to help create cells from Svelte components through ColumnDef's `cell` and `header` properties.
*
* This is only to be used with Svelte Components - use `renderSnippet` for Svelte Snippets.
*
* @param component A Svelte component
* @param props The props to pass to `component`
* @returns A `RenderComponentConfig` object that helps svelte-table know how to render the header/cell component.
* @example
* ```ts
* // +page.svelte
* const defaultColumns = [
* columnHelper.accessor('name', {
* header: header => renderComponent(SortHeader, { label: 'Name', header }),
* }),
* columnHelper.accessor('state', {
* header: header => renderComponent(SortHeader, { label: 'State', header }),
* }),
* ]
* ```
* @see {@link https://tanstack.com/table/latest/docs/guide/column-defs}
*/
export function renderComponent<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
T extends Component<any>,
Props extends ComponentProps<T>,
>(component: T, props: Props) {
return new RenderComponentConfig(component, props);
}
/**
* A helper function to help create cells from Svelte Snippets through ColumnDef's `cell` and `header` properties.
*
* The snippet must only take one parameter.
*
* This is only to be used with Snippets - use `renderComponent` for Svelte Components.
*
* @param snippet
* @param params
* @returns - A `RenderSnippetConfig` object that helps svelte-table know how to render the header/cell snippet.
* @example
* ```ts
* // +page.svelte
* const defaultColumns = [
* columnHelper.accessor('name', {
* cell: cell => renderSnippet(nameSnippet, { name: cell.row.name }),
* }),
* columnHelper.accessor('state', {
* cell: cell => renderSnippet(stateSnippet, { state: cell.row.state }),
* }),
* ]
* ```
* @see {@link https://tanstack.com/table/latest/docs/guide/column-defs}
*/
export function renderSnippet<TProps>(snippet: Snippet<[TProps]>, params: TProps) {
return new RenderSnippetConfig(snippet, params);
}

View File

@@ -1,9 +1,9 @@
<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';
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),
@@ -22,14 +22,14 @@
<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',
"bg-background 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%] fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border p-6 shadow-lg duration-200 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"
class="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground 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"
>
<X class="size-4" />
<span class="sr-only">Close</span>

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Dialog as DialogPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -11,6 +11,6 @@
<DialogPrimitive.Description
bind:ref
class={cn('text-sm text-muted-foreground', className)}
class={cn("text-muted-foreground text-sm", 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),
@@ -13,7 +13,7 @@
<div
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?.()}

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),
@@ -13,7 +13,7 @@
<div
bind:this={ref}
class={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}
class={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)}
{...restProps}
>
{@render children?.()}

View File

@@ -1,6 +1,6 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { Dialog as DialogPrimitive } from "bits-ui";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
@@ -12,7 +12,7 @@
<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',
"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",
className
)}
{...restProps}

View File

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

View File

@@ -1,11 +1,11 @@
import { Dialog as DialogPrimitive } from 'bits-ui';
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';
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;
@@ -33,5 +33,5 @@ export {
Overlay as DialogOverlay,
Content as DialogContent,
Description as DialogDescription,
Close as DialogClose
Close as DialogClose,
};

View File

@@ -0,0 +1,30 @@
<script lang="ts">
import { Drawer as DrawerPrimitive } from "vaul-svelte";
import DrawerOverlay from "./drawer-overlay.svelte";
import { cn } from "$lib/utils.js";
let {
ref = $bindable(null),
class: className,
portalProps,
children,
...restProps
}: DrawerPrimitive.ContentProps & {
portalProps?: DrawerPrimitive.PortalProps;
} = $props();
</script>
<DrawerPrimitive.Portal {...portalProps}>
<DrawerOverlay />
<DrawerPrimitive.Content
bind:ref
class={cn(
"bg-background fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border",
className
)}
{...restProps}
>
<div class="bg-muted mx-auto mt-4 h-2 w-[100px] rounded-full"></div>
{@render children?.()}
</DrawerPrimitive.Content>
</DrawerPrimitive.Portal>

View File

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

View File

@@ -0,0 +1,18 @@
<script lang="ts">
import { cn } from "$lib/utils.js";
import type { WithElementRef } from "bits-ui";
import type { HTMLAttributes } from "svelte/elements";
let {
ref = $bindable(null),
class: className,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
export { className as class };
</script>
<div bind:this={ref} class={cn("mt-auto flex flex-col gap-2 p-4", className)} {...restProps}>
{@render children?.()}
</div>

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("grid gap-1.5 p-4 text-center sm:text-left", className)}
{...restProps}
>
{@render children?.()}
</div>

View File

@@ -0,0 +1,12 @@
<script lang="ts">
import { Drawer as DrawerPrimitive } from "vaul-svelte";
let {
shouldScaleBackground = true,
open = $bindable(false),
activeSnapPoint = $bindable(null),
...restProps
}: DrawerPrimitive.RootProps = $props();
</script>
<DrawerPrimitive.NestedRoot {shouldScaleBackground} bind:open bind:activeSnapPoint {...restProps} />

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