@hobenakicoffee/libraries 1.27.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/package.json +5 -39
  2. package/src/nuqs/common.ts +12 -0
  3. package/src/nuqs/index.ts +2 -0
  4. package/src/nuqs/transactions.ts +31 -0
  5. package/src/types/supabase.ts +30 -0
  6. package/src/components/ui/alert-dialog.tsx +0 -196
  7. package/src/components/ui/alert.tsx +0 -76
  8. package/src/components/ui/avatar.tsx +0 -110
  9. package/src/components/ui/badge.tsx +0 -49
  10. package/src/components/ui/breadcrumb.tsx +0 -122
  11. package/src/components/ui/button-group.tsx +0 -82
  12. package/src/components/ui/card.tsx +0 -100
  13. package/src/components/ui/chart.tsx +0 -364
  14. package/src/components/ui/checkbox.tsx +0 -30
  15. package/src/components/ui/dialog.tsx +0 -162
  16. package/src/components/ui/drawer.tsx +0 -126
  17. package/src/components/ui/dropdown-menu.tsx +0 -267
  18. package/src/components/ui/empty-minimal.tsx +0 -20
  19. package/src/components/ui/empty.tsx +0 -101
  20. package/src/components/ui/field.tsx +0 -235
  21. package/src/components/ui/input-group.tsx +0 -170
  22. package/src/components/ui/input-otp.tsx +0 -84
  23. package/src/components/ui/input.tsx +0 -37
  24. package/src/components/ui/item.tsx +0 -196
  25. package/src/components/ui/label.tsx +0 -19
  26. package/src/components/ui/popover.tsx +0 -87
  27. package/src/components/ui/radio-group.tsx +0 -47
  28. package/src/components/ui/select.tsx +0 -205
  29. package/src/components/ui/separator.tsx +0 -26
  30. package/src/components/ui/sheet.tsx +0 -141
  31. package/src/components/ui/sidebar.tsx +0 -699
  32. package/src/components/ui/skeleton.tsx +0 -13
  33. package/src/components/ui/sonner.tsx +0 -74
  34. package/src/components/ui/table.tsx +0 -114
  35. package/src/components/ui/tabs.tsx +0 -88
  36. package/src/components/ui/textarea.tsx +0 -35
  37. package/src/components/ui/toggle-group.tsx +0 -91
  38. package/src/components/ui/toggle.tsx +0 -44
  39. package/src/components/ui/tooltip.tsx +0 -59
package/package.json CHANGED
@@ -1,54 +1,18 @@
1
1
  {
2
2
  "name": "@hobenakicoffee/libraries",
3
- "version": "1.27.0",
3
+ "version": "1.29.0",
4
4
  "type": "module",
5
5
  "types": "src/index.ts",
6
6
  "exports": {
7
7
  ".": "./src/index.ts",
8
8
  "./components/turnstile-captcha": "./src/components/turnstile-captcha.tsx",
9
- "./components/ui/alert": "./src/components/ui/alert.tsx",
10
- "./components/ui/alert-dialog": "./src/components/ui/alert-dialog.tsx",
11
- "./components/ui/avatar": "./src/components/ui/avatar.tsx",
12
- "./components/ui/badge": "./src/components/ui/badge.tsx",
13
- "./components/ui/breadcrumb": "./src/components/ui/breadcrumb.tsx",
14
- "./components/ui/button": "./src/components/ui/button.tsx",
15
- "./components/ui/button-group": "./src/components/ui/button-group.tsx",
16
- "./components/ui/calendar": "./src/components/ui/calendar.tsx",
17
- "./components/ui/card": "./src/components/ui/card.tsx",
18
- "./components/ui/chart": "./src/components/ui/chart.tsx",
19
- "./components/ui/checkbox": "./src/components/ui/checkbox.tsx",
20
- "./components/ui/dialog": "./src/components/ui/dialog.tsx",
21
- "./components/ui/drawer": "./src/components/ui/drawer.tsx",
22
- "./components/ui/dropdown-menu": "./src/components/ui/dropdown-menu.tsx",
23
- "./components/ui/empty": "./src/components/ui/empty.tsx",
24
- "./components/ui/empty-minimal": "./src/components/ui/empty-minimal.tsx",
25
- "./components/ui/field": "./src/components/ui/field.tsx",
26
- "./components/ui/input": "./src/components/ui/input.tsx",
27
- "./components/ui/input-group": "./src/components/ui/input-group.tsx",
28
- "./components/ui/input-otp": "./src/components/ui/input-otp.tsx",
29
- "./components/ui/item": "./src/components/ui/item.tsx",
30
- "./components/ui/label": "./src/components/ui/label.tsx",
31
- "./components/ui/popover": "./src/components/ui/popover.tsx",
32
- "./components/ui/radio-group": "./src/components/ui/radio-group.tsx",
33
- "./components/ui/select": "./src/components/ui/select.tsx",
34
- "./components/ui/separator": "./src/components/ui/separator.tsx",
35
- "./components/ui/sheet": "./src/components/ui/sheet.tsx",
36
- "./components/ui/sidebar": "./src/components/ui/sidebar.tsx",
37
- "./components/ui/skeleton": "./src/components/ui/skeleton.tsx",
38
- "./components/ui/sonner": "./src/components/ui/sonner.tsx",
39
- "./components/ui/spinner": "./src/components/ui/spinner.tsx",
40
- "./components/ui/table": "./src/components/ui/table.tsx",
41
- "./components/ui/tabs": "./src/components/ui/tabs.tsx",
42
- "./components/ui/textarea": "./src/components/ui/textarea.tsx",
43
- "./components/ui/toggle": "./src/components/ui/toggle.tsx",
44
- "./components/ui/toggle-group": "./src/components/ui/toggle-group.tsx",
45
- "./components/ui/tooltip": "./src/components/ui/tooltip.tsx",
46
9
  "./constants": "./src/constants/index.ts",
47
10
  "./lib/utils": "./src/lib/utils.ts",
48
11
  "./moderation": "./src/moderation/index.ts",
49
12
  "./providers/theme-provider": "./src/providers/theme-provider.tsx",
50
13
  "./types": "./src/types/index.ts",
51
14
  "./utils": "./src/utils/index.ts",
15
+ "./nuqs": "./src/nuqs/index.ts",
52
16
  "./scripts": "./src/scripts/index.ts"
53
17
  },
54
18
  "files": [
@@ -103,6 +67,7 @@
103
67
  "input-otp": "^1.4.2",
104
68
  "install": "^0.13.0",
105
69
  "next-themes": "^0.4.6",
70
+ "nuqs": "^2.8.9",
106
71
  "openai": "^6.22.0",
107
72
  "radix-ui": "^1.4.3",
108
73
  "react": "^19.2.4",
@@ -114,6 +79,7 @@
114
79
  "tailwind-merge": "^3.5.0",
115
80
  "tailwindcss": "^4.2.1",
116
81
  "tw-animate-css": "^1.4.0",
117
- "vaul": "^1.1.2"
82
+ "vaul": "^1.1.2",
83
+ "zod": "^4.3.6"
118
84
  }
119
85
  }
@@ -0,0 +1,12 @@
1
+ import { type inferParserType, parseAsJson, parseAsStringLiteral } from "nuqs";
2
+ import { z } from "zod";
3
+
4
+ export const parseAsSortOrder = parseAsStringLiteral(["asc", "desc"]);
5
+ export type SortOrder = inferParserType<typeof parseAsSortOrder>;
6
+
7
+ export const parseAsDateRange = parseAsJson(
8
+ z.object({
9
+ from: z.date(),
10
+ to: z.date().optional(),
11
+ })
12
+ );
@@ -0,0 +1,2 @@
1
+ export * from "./common";
2
+ export * from "./transactions";
@@ -0,0 +1,31 @@
1
+ import {
2
+ type inferParserType,
3
+ parseAsArrayOf,
4
+ parseAsStringLiteral,
5
+ } from "nuqs";
6
+ import {
7
+ PaymentProviders,
8
+ PaymentStatuses,
9
+ PaymentTypes,
10
+ ServiceTypes,
11
+ } from "@/constants";
12
+ import { parseAsDateRange, parseAsSortOrder } from "./common";
13
+
14
+ export const transactionsFilterParsers = {
15
+ statuses: parseAsArrayOf(
16
+ parseAsStringLiteral(Object.values(PaymentStatuses))
17
+ ),
18
+ types: parseAsArrayOf(parseAsStringLiteral(Object.values(PaymentTypes))),
19
+ serviceTypes: parseAsArrayOf(
20
+ parseAsStringLiteral(Object.values(ServiceTypes))
21
+ ),
22
+ providers: parseAsArrayOf(
23
+ parseAsStringLiteral(Object.values(PaymentProviders))
24
+ ),
25
+ dateRange: parseAsDateRange,
26
+ amountSort: parseAsSortOrder,
27
+ };
28
+
29
+ export type TransactionFilters = inferParserType<
30
+ typeof transactionsFilterParsers
31
+ >;
@@ -1678,6 +1678,36 @@ export type Database = {
1678
1678
  Args: { p_creator_id: string; p_from_date: string; p_to_date: string };
1679
1679
  Returns: number;
1680
1680
  };
1681
+ get_transaction_service_breakdown: {
1682
+ Args: {
1683
+ p_direction?: Database["public"]["Enums"]["transaction_direction_enum"];
1684
+ p_from?: string;
1685
+ p_to?: string;
1686
+ };
1687
+ Returns: {
1688
+ percentage: number;
1689
+ service_type: string;
1690
+ total_amount: number;
1691
+ transaction_count: number;
1692
+ }[];
1693
+ };
1694
+ get_transaction_stats: {
1695
+ Args: { p_from?: string; p_to?: string };
1696
+ Returns: {
1697
+ earned_change: number;
1698
+ earned_one_time: number;
1699
+ earned_subscription: number;
1700
+ earned_total: number;
1701
+ pending_in: number;
1702
+ pending_in_change: number;
1703
+ pending_out: number;
1704
+ pending_out_change: number;
1705
+ spent_change: number;
1706
+ spent_one_time: number;
1707
+ spent_subscription: number;
1708
+ spent_total: number;
1709
+ }[];
1710
+ };
1681
1711
  gift_newsletter_post: {
1682
1712
  Args: {
1683
1713
  p_expires_at?: string;
@@ -1,196 +0,0 @@
1
- import { AlertDialog as AlertDialogPrimitive } from "radix-ui";
2
- import type * as React from "react";
3
- import { Button } from "@/components/ui/button";
4
- import { cn } from "@/lib/utils";
5
-
6
- function AlertDialog({
7
- ...props
8
- }: React.ComponentProps<typeof AlertDialogPrimitive.Root>) {
9
- return <AlertDialogPrimitive.Root data-slot="alert-dialog" {...props} />;
10
- }
11
-
12
- function AlertDialogTrigger({
13
- ...props
14
- }: React.ComponentProps<typeof AlertDialogPrimitive.Trigger>) {
15
- return (
16
- <AlertDialogPrimitive.Trigger data-slot="alert-dialog-trigger" {...props} />
17
- );
18
- }
19
-
20
- function AlertDialogPortal({
21
- ...props
22
- }: React.ComponentProps<typeof AlertDialogPrimitive.Portal>) {
23
- return (
24
- <AlertDialogPrimitive.Portal data-slot="alert-dialog-portal" {...props} />
25
- );
26
- }
27
-
28
- function AlertDialogOverlay({
29
- className,
30
- ...props
31
- }: React.ComponentProps<typeof AlertDialogPrimitive.Overlay>) {
32
- return (
33
- <AlertDialogPrimitive.Overlay
34
- className={cn(
35
- "data-closed:fade-out-0 data-open:fade-in-0 fixed inset-0 z-50 bg-black/10 duration-100 data-closed:animate-out data-open:animate-in supports-backdrop-filter:backdrop-blur-xs",
36
- className
37
- )}
38
- data-slot="alert-dialog-overlay"
39
- {...props}
40
- />
41
- );
42
- }
43
-
44
- function AlertDialogContent({
45
- className,
46
- size = "default",
47
- ...props
48
- }: React.ComponentProps<typeof AlertDialogPrimitive.Content> & {
49
- size?: "default" | "sm";
50
- }) {
51
- return (
52
- <AlertDialogPortal>
53
- <AlertDialogOverlay />
54
- <AlertDialogPrimitive.Content
55
- className={cn(
56
- "data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-6 rounded-xl bg-background p-6 outline-none ring-1 ring-foreground/10 duration-100 data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-closed:animate-out data-open:animate-in data-[size=default]:sm:max-w-lg",
57
- className
58
- )}
59
- data-size={size}
60
- data-slot="alert-dialog-content"
61
- {...props}
62
- />
63
- </AlertDialogPortal>
64
- );
65
- }
66
-
67
- function AlertDialogHeader({
68
- className,
69
- ...props
70
- }: React.ComponentProps<"div">) {
71
- return (
72
- <div
73
- className={cn(
74
- "grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-6 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]",
75
- className
76
- )}
77
- data-slot="alert-dialog-header"
78
- {...props}
79
- />
80
- );
81
- }
82
-
83
- function AlertDialogFooter({
84
- className,
85
- ...props
86
- }: React.ComponentProps<"div">) {
87
- return (
88
- <div
89
- className={cn(
90
- "flex flex-col-reverse gap-2 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end",
91
- className
92
- )}
93
- data-slot="alert-dialog-footer"
94
- {...props}
95
- />
96
- );
97
- }
98
-
99
- function AlertDialogMedia({
100
- className,
101
- ...props
102
- }: React.ComponentProps<"div">) {
103
- return (
104
- <div
105
- className={cn(
106
- "mb-2 inline-flex size-16 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-8",
107
- className
108
- )}
109
- data-slot="alert-dialog-media"
110
- {...props}
111
- />
112
- );
113
- }
114
-
115
- function AlertDialogTitle({
116
- className,
117
- ...props
118
- }: React.ComponentProps<typeof AlertDialogPrimitive.Title>) {
119
- return (
120
- <AlertDialogPrimitive.Title
121
- className={cn(
122
- "font-medium text-lg sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2",
123
- className
124
- )}
125
- data-slot="alert-dialog-title"
126
- {...props}
127
- />
128
- );
129
- }
130
-
131
- function AlertDialogDescription({
132
- className,
133
- ...props
134
- }: React.ComponentProps<typeof AlertDialogPrimitive.Description>) {
135
- return (
136
- <AlertDialogPrimitive.Description
137
- className={cn(
138
- "text-balance text-muted-foreground text-sm md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground",
139
- className
140
- )}
141
- data-slot="alert-dialog-description"
142
- {...props}
143
- />
144
- );
145
- }
146
-
147
- function AlertDialogAction({
148
- className,
149
- variant = "default",
150
- size = "default",
151
- ...props
152
- }: React.ComponentProps<typeof AlertDialogPrimitive.Action> &
153
- Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
154
- return (
155
- <Button asChild size={size} variant={variant}>
156
- <AlertDialogPrimitive.Action
157
- className={cn(className)}
158
- data-slot="alert-dialog-action"
159
- {...props}
160
- />
161
- </Button>
162
- );
163
- }
164
-
165
- function AlertDialogCancel({
166
- className,
167
- variant = "outline",
168
- size = "default",
169
- ...props
170
- }: React.ComponentProps<typeof AlertDialogPrimitive.Cancel> &
171
- Pick<React.ComponentProps<typeof Button>, "variant" | "size">) {
172
- return (
173
- <Button asChild size={size} variant={variant}>
174
- <AlertDialogPrimitive.Cancel
175
- className={cn(className)}
176
- data-slot="alert-dialog-cancel"
177
- {...props}
178
- />
179
- </Button>
180
- );
181
- }
182
-
183
- export {
184
- AlertDialog,
185
- AlertDialogAction,
186
- AlertDialogCancel,
187
- AlertDialogContent,
188
- AlertDialogDescription,
189
- AlertDialogFooter,
190
- AlertDialogHeader,
191
- AlertDialogMedia,
192
- AlertDialogOverlay,
193
- AlertDialogPortal,
194
- AlertDialogTitle,
195
- AlertDialogTrigger,
196
- };
@@ -1,76 +0,0 @@
1
- import { cva, type VariantProps } from "class-variance-authority";
2
- import type * as React from "react";
3
-
4
- import { cn } from "@/lib/utils";
5
-
6
- const alertVariants = cva(
7
- "group/alert relative grid w-full gap-0.5 rounded-lg border px-3 py-3 text-left text-xs has-data-[slot=alert-action]:relative has-[>svg]:grid-cols-[auto_1fr] has-[>svg]:gap-x-2.5 has-data-[slot=alert-action]:pr-18 *:[svg:not([class*='size-'])]:size-4 *:[svg]:row-span-2 *:[svg]:translate-y-0.5 *:[svg]:text-current",
8
- {
9
- variants: {
10
- variant: {
11
- default: "bg-card text-card-foreground",
12
- destructive:
13
- "border-destructive/15 bg-destructive/5 text-destructive *:data-[slot=alert-description]:text-destructive/90 *:[svg]:text-current",
14
- },
15
- },
16
- defaultVariants: {
17
- variant: "default",
18
- },
19
- }
20
- );
21
-
22
- function Alert({
23
- className,
24
- variant,
25
- ...props
26
- }: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
27
- return (
28
- <div
29
- className={cn(alertVariants({ variant }), className)}
30
- data-slot="alert"
31
- role="alert"
32
- {...props}
33
- />
34
- );
35
- }
36
-
37
- function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
38
- return (
39
- <div
40
- className={cn(
41
- "font-medium group-has-[>svg]/alert:col-start-2 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground",
42
- className
43
- )}
44
- data-slot="alert-title"
45
- {...props}
46
- />
47
- );
48
- }
49
-
50
- function AlertDescription({
51
- className,
52
- ...props
53
- }: React.ComponentProps<"div">) {
54
- return (
55
- <div
56
- className={cn(
57
- "text-balance text-muted-foreground text-sm md:text-pretty [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
58
- className
59
- )}
60
- data-slot="alert-description"
61
- {...props}
62
- />
63
- );
64
- }
65
-
66
- function AlertAction({ className, ...props }: React.ComponentProps<"div">) {
67
- return (
68
- <div
69
- className={cn("absolute top-2.5 right-3", className)}
70
- data-slot="alert-action"
71
- {...props}
72
- />
73
- );
74
- }
75
-
76
- export { Alert, AlertTitle, AlertDescription, AlertAction };
@@ -1,110 +0,0 @@
1
- import { Avatar as AvatarPrimitive } from "radix-ui";
2
- import type * as React from "react";
3
-
4
- import { cn } from "@/lib/utils";
5
-
6
- function Avatar({
7
- className,
8
- size = "default",
9
- ...props
10
- }: React.ComponentProps<typeof AvatarPrimitive.Root> & {
11
- size?: "default" | "sm" | "lg";
12
- }) {
13
- return (
14
- <AvatarPrimitive.Root
15
- className={cn(
16
- "group/avatar relative flex size-8 shrink-0 select-none rounded-full after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
17
- className
18
- )}
19
- data-size={size}
20
- data-slot="avatar"
21
- {...props}
22
- />
23
- );
24
- }
25
-
26
- function AvatarImage({
27
- className,
28
- ...props
29
- }: React.ComponentProps<typeof AvatarPrimitive.Image>) {
30
- return (
31
- <AvatarPrimitive.Image
32
- className={cn(
33
- "aspect-square size-full rounded-full object-cover",
34
- className
35
- )}
36
- data-slot="avatar-image"
37
- {...props}
38
- />
39
- );
40
- }
41
-
42
- function AvatarFallback({
43
- className,
44
- ...props
45
- }: React.ComponentProps<typeof AvatarPrimitive.Fallback>) {
46
- return (
47
- <AvatarPrimitive.Fallback
48
- className={cn(
49
- "flex size-full items-center justify-center rounded-full bg-muted text-muted-foreground text-sm group-data-[size=sm]/avatar:text-xs",
50
- className
51
- )}
52
- data-slot="avatar-fallback"
53
- {...props}
54
- />
55
- );
56
- }
57
-
58
- function AvatarBadge({ className, ...props }: React.ComponentProps<"span">) {
59
- return (
60
- <span
61
- className={cn(
62
- "absolute right-0 bottom-0 z-10 inline-flex select-none items-center justify-center rounded-full bg-primary text-primary-foreground bg-blend-color ring-2 ring-background",
63
- "group-data-[size=sm]/avatar:size-2 group-data-[size=sm]/avatar:[&>svg]:hidden",
64
- "group-data-[size=default]/avatar:size-2.5 group-data-[size=default]/avatar:[&>svg]:size-2",
65
- "group-data-[size=lg]/avatar:size-3 group-data-[size=lg]/avatar:[&>svg]:size-2",
66
- className
67
- )}
68
- data-slot="avatar-badge"
69
- {...props}
70
- />
71
- );
72
- }
73
-
74
- function AvatarGroup({ className, ...props }: React.ComponentProps<"div">) {
75
- return (
76
- <div
77
- className={cn(
78
- "group/avatar-group flex -gap-x-2 *:data-[slot=avatar]:ring-2 *:data-[slot=avatar]:ring-background",
79
- className
80
- )}
81
- data-slot="avatar-group"
82
- {...props}
83
- />
84
- );
85
- }
86
-
87
- function AvatarGroupCount({
88
- className,
89
- ...props
90
- }: React.ComponentProps<"div">) {
91
- return (
92
- <div
93
- className={cn(
94
- "relative flex size-8 shrink-0 items-center justify-center rounded-full bg-muted text-muted-foreground text-sm ring-2 ring-background group-has-data-[size=lg]/avatar-group:size-10 group-has-data-[size=sm]/avatar-group:size-6 [&>svg]:size-4 group-has-data-[size=lg]/avatar-group:[&>svg]:size-5 group-has-data-[size=sm]/avatar-group:[&>svg]:size-3",
95
- className
96
- )}
97
- data-slot="avatar-group-count"
98
- {...props}
99
- />
100
- );
101
- }
102
-
103
- export {
104
- Avatar,
105
- AvatarImage,
106
- AvatarFallback,
107
- AvatarGroup,
108
- AvatarGroupCount,
109
- AvatarBadge,
110
- };
@@ -1,49 +0,0 @@
1
- import { cva, type VariantProps } from "class-variance-authority";
2
- import { Slot } from "radix-ui";
3
- import type * as React from "react";
4
-
5
- import { cn } from "@/lib/utils";
6
-
7
- const badgeVariants = cva(
8
- "group/badge inline-flex h-6 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden whitespace-nowrap rounded-4xl px-2 py-1 font-normal text-xs uppercase ring-1 transition-all transition-colors focus-visible:border-ring focus-visible:ring-ring focus-visible:ring-ring has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
9
- {
10
- variants: {
11
- variant: {
12
- default: "bg-primary text-primary-foreground [a]:hover:bg-primary/80",
13
- secondary:
14
- "bg-secondary text-secondary-foreground [a]:hover:bg-secondary/80",
15
- destructive:
16
- "bg-destructive/10 text-destructive focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:focus-visible:ring-destructive/40 [a]:hover:bg-destructive/20",
17
- outline:
18
- "border-border text-foreground [a]:hover:bg-muted [a]:hover:text-muted-foreground",
19
- ghost:
20
- "hover:bg-muted hover:text-muted-foreground dark:hover:bg-muted/50",
21
- link: "text-primary underline-offset-4 hover:underline",
22
- },
23
- },
24
- defaultVariants: {
25
- variant: "default",
26
- },
27
- }
28
- );
29
-
30
- function Badge({
31
- className,
32
- variant = "default",
33
- asChild = false,
34
- ...props
35
- }: React.ComponentProps<"span"> &
36
- VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
37
- const Comp = asChild ? Slot.Root : "span";
38
-
39
- return (
40
- <Comp
41
- className={cn(badgeVariants({ variant }), className)}
42
- data-slot="badge"
43
- data-variant={variant}
44
- {...props}
45
- />
46
- );
47
- }
48
-
49
- export { Badge, badgeVariants };