1<script lang="ts" module>
 2	import { cn, type WithElementRef } from '$lib/components/ui/utils';
 3	import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
 4	import { type VariantProps, tv } from 'tailwind-variants';
 5
 6	export const buttonVariants = tv({
 7		base: "focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive inline-flex shrink-0 items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium outline-none transition-all focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
 8		variants: {
 9			variant: {
10				default: 'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
11				destructive:
12					'bg-destructive shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 text-white',
13				outline:
14					'bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50 border',
15				secondary: 'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
16				ghost: 'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
17				link: 'text-primary underline-offset-4 hover:underline'
18			},
19			size: {
20				default: 'h-9 px-4 py-2 has-[>svg]:px-3',
21				sm: 'h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5',
22				lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
23				icon: 'size-9'
24			}
25		},
26		defaultVariants: {
27			variant: 'default',
28			size: 'default'
29		}
30	});
31
32	export type ButtonVariant = VariantProps<typeof buttonVariants>['variant'];
33	export type ButtonSize = VariantProps<typeof buttonVariants>['size'];
34
35	export type ButtonProps = WithElementRef<HTMLButtonAttributes> &
36		WithElementRef<HTMLAnchorAttributes> & {
37			variant?: ButtonVariant;
38			size?: ButtonSize;
39		};
40</script>
41
42<script lang="ts">
43	let {
44		class: className,
45		variant = 'default',
46		size = 'default',
47		ref = $bindable(null),
48		href = undefined,
49		type = 'button',
50		disabled,
51		children,
52		...restProps
53	}: ButtonProps = $props();
54</script>
55
56{#if href}
57	<a
58		bind:this={ref}
59		data-slot="button"
60		class={cn(buttonVariants({ variant, size }), className)}
61		href={disabled ? undefined : href}
62		aria-disabled={disabled}
63		role={disabled ? 'link' : undefined}
64		tabindex={disabled ? -1 : undefined}
65		{...restProps}
66	>
67		{@render children?.()}
68	</a>
69{:else}
70	<button
71		bind:this={ref}
72		data-slot="button"
73		class={cn(buttonVariants({ variant, size }), className)}
74		{type}
75		{disabled}
76		{...restProps}
77	>
78		{@render children?.()}
79	</button>
80{/if}
81
82<style>
83	a,
84	button {
85		cursor: pointer;
86	}
87</style>