@mesob/ui 0.0.2

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 (194) hide show
  1. package/dist/components/accordion.d.ts +10 -0
  2. package/dist/components/accordion.js +74 -0
  3. package/dist/components/accordion.js.map +1 -0
  4. package/dist/components/alert-dialog.d.ts +17 -0
  5. package/dist/components/alert-dialog.js +187 -0
  6. package/dist/components/alert-dialog.js.map +1 -0
  7. package/dist/components/alert.d.ts +13 -0
  8. package/dist/components/alert.js +74 -0
  9. package/dist/components/alert.js.map +1 -0
  10. package/dist/components/animated-tabs.d.ts +26 -0
  11. package/dist/components/animated-tabs.js +290 -0
  12. package/dist/components/animated-tabs.js.map +1 -0
  13. package/dist/components/aspect-ratio.d.ts +6 -0
  14. package/dist/components/aspect-ratio.js +14 -0
  15. package/dist/components/aspect-ratio.js.map +1 -0
  16. package/dist/components/avatar.d.ts +9 -0
  17. package/dist/components/avatar.js +63 -0
  18. package/dist/components/avatar.js.map +1 -0
  19. package/dist/components/badge.d.ts +13 -0
  20. package/dist/components/badge.js +48 -0
  21. package/dist/components/badge.js.map +1 -0
  22. package/dist/components/breadcrumb.d.ts +14 -0
  23. package/dist/components/breadcrumb.js +110 -0
  24. package/dist/components/breadcrumb.js.map +1 -0
  25. package/dist/components/button-group.d.ts +17 -0
  26. package/dist/components/button-group.js +106 -0
  27. package/dist/components/button-group.js.map +1 -0
  28. package/dist/components/button.d.ts +14 -0
  29. package/dist/components/button.js +60 -0
  30. package/dist/components/button.js.map +1 -0
  31. package/dist/components/calendar.d.ts +13 -0
  32. package/dist/components/calendar.js +254 -0
  33. package/dist/components/calendar.js.map +1 -0
  34. package/dist/components/card.d.ts +12 -0
  35. package/dist/components/card.js +98 -0
  36. package/dist/components/card.js.map +1 -0
  37. package/dist/components/carousel.d.ts +24 -0
  38. package/dist/components/carousel.js +260 -0
  39. package/dist/components/carousel.js.map +1 -0
  40. package/dist/components/chart.d.ts +43 -0
  41. package/dist/components/chart.js +261 -0
  42. package/dist/components/chart.js.map +1 -0
  43. package/dist/components/checkbox.d.ts +7 -0
  44. package/dist/components/checkbox.js +41 -0
  45. package/dist/components/checkbox.js.map +1 -0
  46. package/dist/components/collapsible.d.ts +8 -0
  47. package/dist/components/collapsible.js +38 -0
  48. package/dist/components/collapsible.js.map +1 -0
  49. package/dist/components/command.d.ts +22 -0
  50. package/dist/components/command.js +281 -0
  51. package/dist/components/command.js.map +1 -0
  52. package/dist/components/context-menu.d.ts +28 -0
  53. package/dist/components/context-menu.js +233 -0
  54. package/dist/components/context-menu.js.map +1 -0
  55. package/dist/components/data-table/index.d.ts +46 -0
  56. package/dist/components/data-table/index.js +639 -0
  57. package/dist/components/data-table/index.js.map +1 -0
  58. package/dist/components/dialog.d.ts +18 -0
  59. package/dist/components/dialog.js +146 -0
  60. package/dist/components/dialog.js.map +1 -0
  61. package/dist/components/drawer.d.ts +16 -0
  62. package/dist/components/drawer.js +138 -0
  63. package/dist/components/drawer.js.map +1 -0
  64. package/dist/components/dropdown-menu.d.ts +28 -0
  65. package/dist/components/dropdown-menu.js +241 -0
  66. package/dist/components/dropdown-menu.js.map +1 -0
  67. package/dist/components/empty.d.ts +15 -0
  68. package/dist/components/empty.js +110 -0
  69. package/dist/components/empty.js.map +1 -0
  70. package/dist/components/entity/index.d.ts +160 -0
  71. package/dist/components/entity/index.js +1671 -0
  72. package/dist/components/entity/index.js.map +1 -0
  73. package/dist/components/field.d.ts +30 -0
  74. package/dist/components/field.js +279 -0
  75. package/dist/components/field.js.map +1 -0
  76. package/dist/components/form.d.ts +28 -0
  77. package/dist/components/form.js +150 -0
  78. package/dist/components/form.js.map +1 -0
  79. package/dist/components/hover-card.d.ts +9 -0
  80. package/dist/components/hover-card.js +48 -0
  81. package/dist/components/hover-card.js.map +1 -0
  82. package/dist/components/input-group.d.ts +20 -0
  83. package/dist/components/input-group.js +257 -0
  84. package/dist/components/input-group.js.map +1 -0
  85. package/dist/components/input-otp.d.ts +14 -0
  86. package/dist/components/input-otp.js +76 -0
  87. package/dist/components/input-otp.js.map +1 -0
  88. package/dist/components/input.d.ts +6 -0
  89. package/dist/components/input.js +29 -0
  90. package/dist/components/input.js.map +1 -0
  91. package/dist/components/item.d.ts +28 -0
  92. package/dist/components/item.js +220 -0
  93. package/dist/components/item.js.map +1 -0
  94. package/dist/components/jiret-logo.d.ts +13 -0
  95. package/dist/components/jiret-logo.js +80 -0
  96. package/dist/components/jiret-logo.js.map +1 -0
  97. package/dist/components/kbd.d.ts +6 -0
  98. package/dist/components/kbd.js +39 -0
  99. package/dist/components/kbd.js.map +1 -0
  100. package/dist/components/label.d.ts +7 -0
  101. package/dist/components/label.js +32 -0
  102. package/dist/components/label.js.map +1 -0
  103. package/dist/components/menubar.d.ts +29 -0
  104. package/dist/components/menubar.js +261 -0
  105. package/dist/components/menubar.js.map +1 -0
  106. package/dist/components/navigation-menu.d.ts +18 -0
  107. package/dist/components/navigation-menu.js +178 -0
  108. package/dist/components/navigation-menu.js.map +1 -0
  109. package/dist/components/pagination.d.ts +18 -0
  110. package/dist/components/pagination.js +160 -0
  111. package/dist/components/pagination.js.map +1 -0
  112. package/dist/components/popover.d.ts +10 -0
  113. package/dist/components/popover.js +54 -0
  114. package/dist/components/popover.js.map +1 -0
  115. package/dist/components/powered-by.d.ts +5 -0
  116. package/dist/components/powered-by.js +98 -0
  117. package/dist/components/powered-by.js.map +1 -0
  118. package/dist/components/progress.d.ts +7 -0
  119. package/dist/components/progress.js +41 -0
  120. package/dist/components/progress.js.map +1 -0
  121. package/dist/components/radio-group.d.ts +8 -0
  122. package/dist/components/radio-group.js +55 -0
  123. package/dist/components/radio-group.js.map +1 -0
  124. package/dist/components/resizable.d.ts +11 -0
  125. package/dist/components/resizable.js +58 -0
  126. package/dist/components/resizable.js.map +1 -0
  127. package/dist/components/scroll-area.d.ts +8 -0
  128. package/dist/components/scroll-area.js +70 -0
  129. package/dist/components/scroll-area.js.map +1 -0
  130. package/dist/components/section/index.d.ts +14 -0
  131. package/dist/components/section/index.js +139 -0
  132. package/dist/components/section/index.js.map +1 -0
  133. package/dist/components/select.d.ts +18 -0
  134. package/dist/components/select.js +181 -0
  135. package/dist/components/select.js.map +1 -0
  136. package/dist/components/separator.d.ts +7 -0
  137. package/dist/components/separator.js +36 -0
  138. package/dist/components/separator.js.map +1 -0
  139. package/dist/components/sheet.d.ts +16 -0
  140. package/dist/components/sheet.js +136 -0
  141. package/dist/components/sheet.js.map +1 -0
  142. package/dist/components/sidebar.d.ts +75 -0
  143. package/dist/components/sidebar.js +909 -0
  144. package/dist/components/sidebar.js.map +1 -0
  145. package/dist/components/skeleton.d.ts +5 -0
  146. package/dist/components/skeleton.js +23 -0
  147. package/dist/components/skeleton.js.map +1 -0
  148. package/dist/components/slider.d.ts +7 -0
  149. package/dist/components/slider.js +76 -0
  150. package/dist/components/slider.js.map +1 -0
  151. package/dist/components/sonner.d.ts +6 -0
  152. package/dist/components/sonner.js +41 -0
  153. package/dist/components/sonner.js.map +1 -0
  154. package/dist/components/spinner.d.ts +6 -0
  155. package/dist/components/spinner.js +28 -0
  156. package/dist/components/spinner.js.map +1 -0
  157. package/dist/components/spotlight-search.d.ts +25 -0
  158. package/dist/components/spotlight-search.js +387 -0
  159. package/dist/components/spotlight-search.js.map +1 -0
  160. package/dist/components/switch.d.ts +7 -0
  161. package/dist/components/switch.js +41 -0
  162. package/dist/components/switch.js.map +1 -0
  163. package/dist/components/table.d.ts +13 -0
  164. package/dist/components/table.js +124 -0
  165. package/dist/components/table.js.map +1 -0
  166. package/dist/components/tabs.d.ts +10 -0
  167. package/dist/components/tabs.js +77 -0
  168. package/dist/components/tabs.js.map +1 -0
  169. package/dist/components/textarea.d.ts +6 -0
  170. package/dist/components/textarea.js +26 -0
  171. package/dist/components/textarea.js.map +1 -0
  172. package/dist/components/theme-toggle.d.ts +8 -0
  173. package/dist/components/theme-toggle.js +86 -0
  174. package/dist/components/theme-toggle.js.map +1 -0
  175. package/dist/components/toggle-group.d.ts +14 -0
  176. package/dist/components/toggle-group.js +102 -0
  177. package/dist/components/toggle-group.js.map +1 -0
  178. package/dist/components/toggle.d.ts +13 -0
  179. package/dist/components/toggle.js +53 -0
  180. package/dist/components/toggle.js.map +1 -0
  181. package/dist/components/tooltip.d.ts +10 -0
  182. package/dist/components/tooltip.js +65 -0
  183. package/dist/components/tooltip.js.map +1 -0
  184. package/dist/hooks/use-mobile.d.ts +3 -0
  185. package/dist/hooks/use-mobile.js +22 -0
  186. package/dist/hooks/use-mobile.js.map +1 -0
  187. package/dist/index.d.ts +2 -0
  188. package/dist/index.js +10 -0
  189. package/dist/index.js.map +1 -0
  190. package/dist/lib/utils.d.ts +5 -0
  191. package/dist/lib/utils.js +10 -0
  192. package/dist/lib/utils.js.map +1 -0
  193. package/package.json +123 -0
  194. package/src/styles/globals.css +125 -0
@@ -0,0 +1,1671 @@
1
+ // src/components/entity/entity-bulk-actions.tsx
2
+ import { IconChevronDown, IconDownload, IconTrash } from "@tabler/icons-react";
3
+ import { useState } from "react";
4
+
5
+ // src/lib/utils.ts
6
+ import { clsx } from "clsx";
7
+ import { twMerge } from "tailwind-merge";
8
+ function cn(...inputs) {
9
+ return twMerge(clsx(inputs));
10
+ }
11
+
12
+ // src/components/button.tsx
13
+ import { Slot } from "@radix-ui/react-slot";
14
+ import { cva } from "class-variance-authority";
15
+ import { jsx } from "react/jsx-runtime";
16
+ var buttonVariants = cva(
17
+ "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
18
+ {
19
+ variants: {
20
+ variant: {
21
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
22
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
23
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
24
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
25
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
26
+ link: "text-primary underline-offset-4 hover:underline"
27
+ },
28
+ size: {
29
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
30
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
31
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
32
+ icon: "size-9",
33
+ "icon-sm": "size-8",
34
+ "icon-lg": "size-10"
35
+ }
36
+ },
37
+ defaultVariants: {
38
+ variant: "default",
39
+ size: "default"
40
+ }
41
+ }
42
+ );
43
+ function Button({
44
+ className,
45
+ variant,
46
+ size,
47
+ asChild = false,
48
+ ...props
49
+ }) {
50
+ const Comp = asChild ? Slot : "button";
51
+ return /* @__PURE__ */ jsx(
52
+ Comp,
53
+ {
54
+ "data-slot": "button",
55
+ className: cn(buttonVariants({ variant, size, className })),
56
+ ...props
57
+ }
58
+ );
59
+ }
60
+
61
+ // src/components/alert-dialog.tsx
62
+ import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
63
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
64
+ function AlertDialog({
65
+ ...props
66
+ }) {
67
+ return /* @__PURE__ */ jsx2(AlertDialogPrimitive.Root, { "data-slot": "alert-dialog", ...props });
68
+ }
69
+ function AlertDialogTrigger({
70
+ ...props
71
+ }) {
72
+ return /* @__PURE__ */ jsx2(AlertDialogPrimitive.Trigger, { "data-slot": "alert-dialog-trigger", ...props });
73
+ }
74
+ function AlertDialogPortal({
75
+ ...props
76
+ }) {
77
+ return /* @__PURE__ */ jsx2(AlertDialogPrimitive.Portal, { "data-slot": "alert-dialog-portal", ...props });
78
+ }
79
+ function AlertDialogOverlay({
80
+ className,
81
+ ...props
82
+ }) {
83
+ return /* @__PURE__ */ jsx2(
84
+ AlertDialogPrimitive.Overlay,
85
+ {
86
+ "data-slot": "alert-dialog-overlay",
87
+ className: cn(
88
+ "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/50",
89
+ className
90
+ ),
91
+ ...props
92
+ }
93
+ );
94
+ }
95
+ function AlertDialogContent({
96
+ className,
97
+ ...props
98
+ }) {
99
+ return /* @__PURE__ */ jsxs(AlertDialogPortal, { children: [
100
+ /* @__PURE__ */ jsx2(AlertDialogOverlay, {}),
101
+ /* @__PURE__ */ jsx2(
102
+ AlertDialogPrimitive.Content,
103
+ {
104
+ "data-slot": "alert-dialog-content",
105
+ className: cn(
106
+ "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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg",
107
+ className
108
+ ),
109
+ ...props
110
+ }
111
+ )
112
+ ] });
113
+ }
114
+ function AlertDialogHeader({
115
+ className,
116
+ ...props
117
+ }) {
118
+ return /* @__PURE__ */ jsx2(
119
+ "div",
120
+ {
121
+ "data-slot": "alert-dialog-header",
122
+ className: cn("flex flex-col gap-2 text-center sm:text-left", className),
123
+ ...props
124
+ }
125
+ );
126
+ }
127
+ function AlertDialogFooter({
128
+ className,
129
+ ...props
130
+ }) {
131
+ return /* @__PURE__ */ jsx2(
132
+ "div",
133
+ {
134
+ "data-slot": "alert-dialog-footer",
135
+ className: cn(
136
+ "flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
137
+ className
138
+ ),
139
+ ...props
140
+ }
141
+ );
142
+ }
143
+ function AlertDialogTitle({
144
+ className,
145
+ ...props
146
+ }) {
147
+ return /* @__PURE__ */ jsx2(
148
+ AlertDialogPrimitive.Title,
149
+ {
150
+ "data-slot": "alert-dialog-title",
151
+ className: cn("text-lg font-semibold", className),
152
+ ...props
153
+ }
154
+ );
155
+ }
156
+ function AlertDialogDescription({
157
+ className,
158
+ ...props
159
+ }) {
160
+ return /* @__PURE__ */ jsx2(
161
+ AlertDialogPrimitive.Description,
162
+ {
163
+ "data-slot": "alert-dialog-description",
164
+ className: cn("text-muted-foreground text-sm", className),
165
+ ...props
166
+ }
167
+ );
168
+ }
169
+ function AlertDialogAction({
170
+ className,
171
+ ...props
172
+ }) {
173
+ return /* @__PURE__ */ jsx2(
174
+ AlertDialogPrimitive.Action,
175
+ {
176
+ className: cn(buttonVariants(), className),
177
+ ...props
178
+ }
179
+ );
180
+ }
181
+ function AlertDialogCancel({
182
+ className,
183
+ ...props
184
+ }) {
185
+ return /* @__PURE__ */ jsx2(
186
+ AlertDialogPrimitive.Cancel,
187
+ {
188
+ className: cn(buttonVariants({ variant: "outline" }), className),
189
+ ...props
190
+ }
191
+ );
192
+ }
193
+
194
+ // src/components/dropdown-menu.tsx
195
+ import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
196
+ import { IconCheck, IconChevronRight, IconCircle } from "@tabler/icons-react";
197
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
198
+ function DropdownMenu({
199
+ ...props
200
+ }) {
201
+ return /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Root, { "data-slot": "dropdown-menu", ...props });
202
+ }
203
+ function DropdownMenuTrigger({
204
+ ...props
205
+ }) {
206
+ return /* @__PURE__ */ jsx3(
207
+ DropdownMenuPrimitive.Trigger,
208
+ {
209
+ "data-slot": "dropdown-menu-trigger",
210
+ ...props
211
+ }
212
+ );
213
+ }
214
+ function DropdownMenuContent({
215
+ className,
216
+ sideOffset = 4,
217
+ ...props
218
+ }) {
219
+ return /* @__PURE__ */ jsx3(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx3(
220
+ DropdownMenuPrimitive.Content,
221
+ {
222
+ "data-slot": "dropdown-menu-content",
223
+ sideOffset,
224
+ className: cn(
225
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
226
+ className
227
+ ),
228
+ ...props
229
+ }
230
+ ) });
231
+ }
232
+ function DropdownMenuItem({
233
+ className,
234
+ inset,
235
+ variant = "default",
236
+ ...props
237
+ }) {
238
+ return /* @__PURE__ */ jsx3(
239
+ DropdownMenuPrimitive.Item,
240
+ {
241
+ "data-slot": "dropdown-menu-item",
242
+ "data-inset": inset,
243
+ "data-variant": variant,
244
+ className: cn(
245
+ "focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
246
+ className
247
+ ),
248
+ ...props
249
+ }
250
+ );
251
+ }
252
+ function DropdownMenuSeparator({
253
+ className,
254
+ ...props
255
+ }) {
256
+ return /* @__PURE__ */ jsx3(
257
+ DropdownMenuPrimitive.Separator,
258
+ {
259
+ "data-slot": "dropdown-menu-separator",
260
+ className: cn("bg-border -mx-1 my-1 h-px", className),
261
+ ...props
262
+ }
263
+ );
264
+ }
265
+
266
+ // src/components/entity/entity-bulk-actions.tsx
267
+ import { Fragment, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
268
+ function EntityBulkActions({
269
+ selectedCount,
270
+ actions,
271
+ onDelete,
272
+ onExport,
273
+ itemName = "item"
274
+ }) {
275
+ const [showDeleteConfirm, setShowDeleteConfirm] = useState(false);
276
+ const hasSelection = selectedCount > 0;
277
+ const defaultActions = [];
278
+ if (onExport) {
279
+ defaultActions.push({
280
+ label: "Export",
281
+ icon: /* @__PURE__ */ jsx4(IconDownload, { className: "mr-2 h-4 w-4" }),
282
+ onClick: onExport
283
+ });
284
+ }
285
+ if (onDelete) {
286
+ defaultActions.push({
287
+ label: "Delete",
288
+ icon: /* @__PURE__ */ jsx4(IconTrash, { className: "mr-2 h-4 w-4" }),
289
+ onClick: () => setShowDeleteConfirm(true),
290
+ variant: "destructive"
291
+ });
292
+ }
293
+ const allActions = actions ? [...actions, ...defaultActions] : defaultActions;
294
+ return /* @__PURE__ */ jsxs3(Fragment, { children: [
295
+ /* @__PURE__ */ jsxs3(DropdownMenu, { children: [
296
+ /* @__PURE__ */ jsx4(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
297
+ Button,
298
+ {
299
+ variant: "outline",
300
+ size: "sm",
301
+ disabled: !hasSelection,
302
+ className: "min-w-[140px]",
303
+ children: [
304
+ hasSelection ? `${selectedCount} selected` : "Bulk Actions",
305
+ /* @__PURE__ */ jsx4(IconChevronDown, { className: "ml-2 h-4 w-4" })
306
+ ]
307
+ }
308
+ ) }),
309
+ /* @__PURE__ */ jsx4(DropdownMenuContent, { align: "end", children: allActions.map((action, index) => /* @__PURE__ */ jsxs3("div", { children: [
310
+ action.variant === "destructive" && index > 0 && /* @__PURE__ */ jsx4(DropdownMenuSeparator, {}),
311
+ /* @__PURE__ */ jsxs3(
312
+ DropdownMenuItem,
313
+ {
314
+ onClick: action.onClick,
315
+ className: action.variant === "destructive" ? "text-destructive" : "",
316
+ children: [
317
+ action.icon,
318
+ action.label
319
+ ]
320
+ }
321
+ )
322
+ ] }, action.label)) })
323
+ ] }),
324
+ /* @__PURE__ */ jsx4(AlertDialog, { open: showDeleteConfirm, onOpenChange: setShowDeleteConfirm, children: /* @__PURE__ */ jsxs3(AlertDialogContent, { children: [
325
+ /* @__PURE__ */ jsxs3(AlertDialogHeader, { children: [
326
+ /* @__PURE__ */ jsxs3(AlertDialogTitle, { children: [
327
+ "Delete ",
328
+ selectedCount,
329
+ " ",
330
+ itemName,
331
+ "(s)?"
332
+ ] }),
333
+ /* @__PURE__ */ jsxs3(AlertDialogDescription, { children: [
334
+ "This will permanently delete the selected ",
335
+ itemName,
336
+ "(s). This action cannot be undone."
337
+ ] })
338
+ ] }),
339
+ /* @__PURE__ */ jsxs3(AlertDialogFooter, { children: [
340
+ /* @__PURE__ */ jsx4(AlertDialogCancel, { children: "Cancel" }),
341
+ /* @__PURE__ */ jsx4(
342
+ AlertDialogAction,
343
+ {
344
+ onClick: () => {
345
+ onDelete?.();
346
+ setShowDeleteConfirm(false);
347
+ },
348
+ className: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
349
+ children: "Delete"
350
+ }
351
+ )
352
+ ] })
353
+ ] }) })
354
+ ] });
355
+ }
356
+
357
+ // src/components/entity/entity-detail-header.tsx
358
+ import { IconChevronDown as IconChevronDown2 } from "@tabler/icons-react";
359
+ import { motion } from "motion/react";
360
+ import { useLayoutEffect, useMemo, useRef, useState as useState2 } from "react";
361
+
362
+ // src/components/card.tsx
363
+ import { jsx as jsx5 } from "react/jsx-runtime";
364
+ function Card({ className, ...props }) {
365
+ return /* @__PURE__ */ jsx5(
366
+ "div",
367
+ {
368
+ "data-slot": "card",
369
+ className: cn(
370
+ "bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 ",
371
+ className
372
+ ),
373
+ ...props
374
+ }
375
+ );
376
+ }
377
+
378
+ // src/components/entity/entity-detail-header.tsx
379
+ import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
380
+ function EntityDetailHeader({
381
+ title,
382
+ icon,
383
+ backButton,
384
+ actions,
385
+ tabs,
386
+ activeTab: controlledActiveTab,
387
+ defaultTab,
388
+ onTabChange,
389
+ className,
390
+ linkComponent: LinkComponent
391
+ }) {
392
+ const [internalActiveTab, setInternalActiveTab] = useState2(
393
+ defaultTab ?? tabs[0]?.value ?? ""
394
+ );
395
+ const activeTab = controlledActiveTab ?? internalActiveTab;
396
+ const [visibleTabs, setVisibleTabs] = useState2(tabs);
397
+ const [overflowTabs, setOverflowTabs] = useState2([]);
398
+ const containerRef = useRef(null);
399
+ const tabsListRef = useRef(null);
400
+ const dropdownTriggerRef = useRef(null);
401
+ const tabRefs = useRef([]);
402
+ const [underlineStyle, setUnderlineStyle] = useState2({ left: 0, width: 0 });
403
+ const handleTabChange = (newValue) => {
404
+ if (!controlledActiveTab) {
405
+ setInternalActiveTab(newValue);
406
+ }
407
+ onTabChange?.(newValue);
408
+ };
409
+ useLayoutEffect(() => {
410
+ const updateTabs = () => {
411
+ if (!containerRef.current) {
412
+ return;
413
+ }
414
+ if (!tabsListRef.current) {
415
+ return;
416
+ }
417
+ const containerWidth = containerRef.current.offsetWidth;
418
+ const dropdownWidth = 80;
419
+ const padding = 16;
420
+ const availableWidth = containerWidth - padding;
421
+ let totalWidth = 0;
422
+ const visible = [];
423
+ const overflow = [];
424
+ let hasOverflow = false;
425
+ for (const [i, tab] of tabs.entries()) {
426
+ const tabEl = tabRefs.current[i];
427
+ if (!tabEl || tabEl.offsetWidth === 0) {
428
+ if (hasOverflow) {
429
+ overflow.push(tab);
430
+ } else {
431
+ visible.push(tab);
432
+ }
433
+ continue;
434
+ }
435
+ const tabWidth = tabEl.scrollWidth || tabEl.offsetWidth;
436
+ const wouldFitWithoutDropdown = totalWidth + tabWidth <= availableWidth;
437
+ const wouldFitWithDropdown = totalWidth + tabWidth + dropdownWidth <= availableWidth;
438
+ if (!hasOverflow && wouldFitWithoutDropdown) {
439
+ visible.push(tab);
440
+ totalWidth += tabWidth;
441
+ } else if (!hasOverflow && wouldFitWithDropdown) {
442
+ visible.push(tab);
443
+ totalWidth += tabWidth;
444
+ hasOverflow = true;
445
+ } else {
446
+ hasOverflow = true;
447
+ overflow.push(tab);
448
+ }
449
+ }
450
+ setVisibleTabs(visible);
451
+ setOverflowTabs(overflow);
452
+ };
453
+ const timeoutId = setTimeout(updateTabs, 100);
454
+ const resizeObserver = new ResizeObserver(() => {
455
+ setTimeout(updateTabs, 0);
456
+ });
457
+ if (containerRef.current) {
458
+ resizeObserver.observe(containerRef.current);
459
+ }
460
+ if (tabsListRef.current) {
461
+ resizeObserver.observe(tabsListRef.current);
462
+ }
463
+ window.addEventListener("resize", updateTabs);
464
+ return () => {
465
+ clearTimeout(timeoutId);
466
+ resizeObserver.disconnect();
467
+ window.removeEventListener("resize", updateTabs);
468
+ };
469
+ }, [tabs]);
470
+ useLayoutEffect(() => {
471
+ const updateUnderline = () => {
472
+ const isInOverflow = overflowTabs.some((tab) => tab.value === activeTab);
473
+ if (isInOverflow && dropdownTriggerRef.current) {
474
+ const { offsetLeft, offsetWidth } = dropdownTriggerRef.current;
475
+ setUnderlineStyle({
476
+ left: offsetLeft,
477
+ width: offsetWidth
478
+ });
479
+ return;
480
+ }
481
+ const activeTabIndex = tabs.findIndex((tab) => tab.value === activeTab);
482
+ const activeTabElement = tabRefs.current[activeTabIndex];
483
+ if (activeTabElement && visibleTabs.some((tab) => tab.value === activeTab)) {
484
+ const { offsetLeft, offsetWidth } = activeTabElement;
485
+ setUnderlineStyle({
486
+ left: offsetLeft,
487
+ width: offsetWidth
488
+ });
489
+ }
490
+ };
491
+ updateUnderline();
492
+ }, [activeTab, visibleTabs, overflowTabs, tabs]);
493
+ const activeTabData = useMemo(
494
+ () => tabs.find((tab) => tab.value === activeTab),
495
+ [tabs, activeTab]
496
+ );
497
+ const renderTab = (tab, originalIndex) => {
498
+ const isActive = activeTab === tab.value;
499
+ const tabClassName = cn(
500
+ "relative z-10 px-4 py-3 text-sm font-medium transition-all duration-200",
501
+ "hover:bg-muted/60 rounded-t-md cursor-pointer",
502
+ isActive ? "text-primary" : "text-muted-foreground hover:text-foreground"
503
+ );
504
+ const setRef = (el) => {
505
+ if (originalIndex >= 0) {
506
+ tabRefs.current[originalIndex] = el;
507
+ }
508
+ };
509
+ if (tab.href && LinkComponent) {
510
+ return /* @__PURE__ */ jsx6(
511
+ LinkComponent,
512
+ {
513
+ href: tab.href,
514
+ className: tabClassName,
515
+ ref: setRef,
516
+ children: tab.name
517
+ },
518
+ tab.value
519
+ );
520
+ }
521
+ return /* @__PURE__ */ jsx6(
522
+ "button",
523
+ {
524
+ type: "button",
525
+ ref: setRef,
526
+ onClick: () => handleTabChange(tab.value),
527
+ className: tabClassName,
528
+ children: tab.name
529
+ },
530
+ tab.value
531
+ );
532
+ };
533
+ const renderDropdownItem = (tab) => {
534
+ const isActive = activeTab === tab.value;
535
+ const itemClassName = cn(
536
+ "cursor-pointer",
537
+ isActive && "bg-accent font-medium"
538
+ );
539
+ if (tab.href && LinkComponent) {
540
+ return /* @__PURE__ */ jsx6(DropdownMenuItem, { asChild: true, className: itemClassName, children: /* @__PURE__ */ jsx6(LinkComponent, { href: tab.href, children: tab.name }) }, tab.value);
541
+ }
542
+ return /* @__PURE__ */ jsx6(
543
+ DropdownMenuItem,
544
+ {
545
+ onClick: () => handleTabChange(tab.value),
546
+ className: itemClassName,
547
+ children: tab.name
548
+ },
549
+ tab.value
550
+ );
551
+ };
552
+ return /* @__PURE__ */ jsxs4("div", { className: cn("flex flex-col", className), children: [
553
+ /* @__PURE__ */ jsxs4(Card, { className: "overflow-hidden p-0 gap-0", children: [
554
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center justify-between gap-2 p-4 pb-2 ", children: [
555
+ /* @__PURE__ */ jsxs4("div", { className: "flex items-center gap-2", children: [
556
+ backButton,
557
+ icon,
558
+ /* @__PURE__ */ jsx6("span", { className: "text-lg font-semibold", children: title })
559
+ ] }),
560
+ actions && /* @__PURE__ */ jsx6("div", { className: "flex items-center gap-2", children: actions })
561
+ ] }),
562
+ /* @__PURE__ */ jsx6("div", { ref: containerRef, className: "w-full px-4 ", children: /* @__PURE__ */ jsxs4("div", { ref: tabsListRef, className: "relative flex items-center", children: [
563
+ visibleTabs.map((tab) => {
564
+ const originalIndex = tabs.findIndex(
565
+ (t) => t.value === tab.value
566
+ );
567
+ return renderTab(tab, originalIndex);
568
+ }),
569
+ overflowTabs.length > 0 && /* @__PURE__ */ jsxs4(DropdownMenu, { children: [
570
+ /* @__PURE__ */ jsxs4(
571
+ DropdownMenuTrigger,
572
+ {
573
+ ref: dropdownTriggerRef,
574
+ className: cn(
575
+ "relative z-10 flex items-center gap-1 px-4 py-3 text-sm font-medium transition-all duration-200",
576
+ "hover:bg-muted/60 rounded-t-md",
577
+ overflowTabs.some((tab) => tab.value === activeTab) ? "text-primary" : "text-muted-foreground hover:text-foreground"
578
+ ),
579
+ children: [
580
+ "More",
581
+ /* @__PURE__ */ jsx6(IconChevronDown2, { className: "h-4 w-4" })
582
+ ]
583
+ }
584
+ ),
585
+ /* @__PURE__ */ jsx6(DropdownMenuContent, { align: "start", className: "min-w-40", children: overflowTabs.map(renderDropdownItem) })
586
+ ] }),
587
+ /* @__PURE__ */ jsx6(
588
+ motion.div,
589
+ {
590
+ className: "absolute bottom-0 left-0 z-20 h-0.5 bg-primary",
591
+ animate: {
592
+ left: underlineStyle.left,
593
+ width: underlineStyle.width
594
+ },
595
+ transition: {
596
+ type: "spring",
597
+ stiffness: 400,
598
+ damping: 40
599
+ }
600
+ }
601
+ )
602
+ ] }) })
603
+ ] }),
604
+ activeTabData?.content && /* @__PURE__ */ jsx6("div", { className: "flex-1", children: activeTabData.content })
605
+ ] });
606
+ }
607
+
608
+ // src/components/entity/entity-drawer.tsx
609
+ import { useState as useState3 } from "react";
610
+
611
+ // src/components/sheet.tsx
612
+ import * as SheetPrimitive from "@radix-ui/react-dialog";
613
+ import { IconX } from "@tabler/icons-react";
614
+ import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
615
+ function Sheet({ ...props }) {
616
+ return /* @__PURE__ */ jsx7(SheetPrimitive.Root, { "data-slot": "sheet", ...props });
617
+ }
618
+ function SheetPortal({
619
+ ...props
620
+ }) {
621
+ return /* @__PURE__ */ jsx7(SheetPrimitive.Portal, { "data-slot": "sheet-portal", ...props });
622
+ }
623
+ function SheetOverlay({
624
+ className,
625
+ ...props
626
+ }) {
627
+ return /* @__PURE__ */ jsx7(
628
+ SheetPrimitive.Overlay,
629
+ {
630
+ "data-slot": "sheet-overlay",
631
+ className: cn(
632
+ "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/50",
633
+ className
634
+ ),
635
+ ...props
636
+ }
637
+ );
638
+ }
639
+ function SheetContent({
640
+ className,
641
+ children,
642
+ side = "right",
643
+ ...props
644
+ }) {
645
+ return /* @__PURE__ */ jsxs5(SheetPortal, { children: [
646
+ /* @__PURE__ */ jsx7(SheetOverlay, {}),
647
+ /* @__PURE__ */ jsxs5(
648
+ SheetPrimitive.Content,
649
+ {
650
+ "data-slot": "sheet-content",
651
+ className: cn(
652
+ "bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
653
+ side === "right" && "data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
654
+ side === "left" && "data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
655
+ side === "top" && "data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
656
+ side === "bottom" && "data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
657
+ className
658
+ ),
659
+ ...props,
660
+ children: [
661
+ children,
662
+ /* @__PURE__ */ jsxs5(SheetPrimitive.Close, { className: "ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none", children: [
663
+ /* @__PURE__ */ jsx7(IconX, { className: "size-4" }),
664
+ /* @__PURE__ */ jsx7("span", { className: "sr-only", children: "Close" })
665
+ ] })
666
+ ]
667
+ }
668
+ )
669
+ ] });
670
+ }
671
+ function SheetHeader({ className, ...props }) {
672
+ return /* @__PURE__ */ jsx7(
673
+ "div",
674
+ {
675
+ "data-slot": "sheet-header",
676
+ className: cn("flex flex-col gap-1.5 p-4", className),
677
+ ...props
678
+ }
679
+ );
680
+ }
681
+ function SheetTitle({
682
+ className,
683
+ ...props
684
+ }) {
685
+ return /* @__PURE__ */ jsx7(
686
+ SheetPrimitive.Title,
687
+ {
688
+ "data-slot": "sheet-title",
689
+ className: cn("text-foreground font-semibold", className),
690
+ ...props
691
+ }
692
+ );
693
+ }
694
+
695
+ // src/components/entity/entity-drawer.tsx
696
+ import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
697
+ var sizeClasses = {
698
+ sm: "sm:max-w-sm",
699
+ md: "sm:max-w-md",
700
+ lg: "sm:max-w-lg",
701
+ xl: "sm:max-w-xl"
702
+ };
703
+ function EntityDrawer({
704
+ title,
705
+ form,
706
+ actions,
707
+ open,
708
+ onClose,
709
+ isDirty = false,
710
+ size = "lg"
711
+ }) {
712
+ const [showConfirm, setShowConfirm] = useState3(false);
713
+ const handleClose = () => {
714
+ if (isDirty) {
715
+ setShowConfirm(true);
716
+ } else {
717
+ onClose();
718
+ }
719
+ };
720
+ const handleConfirmDiscard = () => {
721
+ setShowConfirm(false);
722
+ onClose();
723
+ };
724
+ return /* @__PURE__ */ jsxs6(Fragment2, { children: [
725
+ /* @__PURE__ */ jsx8(Sheet, { open, onOpenChange: (isOpen) => !isOpen && handleClose(), children: /* @__PURE__ */ jsxs6(
726
+ SheetContent,
727
+ {
728
+ className: `${sizeClasses[size]} flex flex-col p-0`,
729
+ onInteractOutside: (e) => {
730
+ if (isDirty) {
731
+ e.preventDefault();
732
+ setShowConfirm(true);
733
+ }
734
+ },
735
+ onEscapeKeyDown: (e) => {
736
+ if (isDirty) {
737
+ e.preventDefault();
738
+ setShowConfirm(true);
739
+ }
740
+ },
741
+ children: [
742
+ /* @__PURE__ */ jsx8(SheetHeader, { className: "border-b px-6 py-4", children: /* @__PURE__ */ jsx8(SheetTitle, { children: title }) }),
743
+ /* @__PURE__ */ jsx8("div", { className: "flex-1 overflow-y-auto px-6 py-4", children: form }),
744
+ /* @__PURE__ */ jsx8("div", { className: "border-t px-6 py-4", children: actions })
745
+ ]
746
+ }
747
+ ) }),
748
+ /* @__PURE__ */ jsx8(AlertDialog, { open: showConfirm, onOpenChange: setShowConfirm, children: /* @__PURE__ */ jsxs6(AlertDialogContent, { children: [
749
+ /* @__PURE__ */ jsxs6(AlertDialogHeader, { children: [
750
+ /* @__PURE__ */ jsx8(AlertDialogTitle, { children: "Discard changes?" }),
751
+ /* @__PURE__ */ jsx8(AlertDialogDescription, { children: "You have unsaved changes. Are you sure you want to discard them?" })
752
+ ] }),
753
+ /* @__PURE__ */ jsxs6(AlertDialogFooter, { children: [
754
+ /* @__PURE__ */ jsx8(AlertDialogCancel, { children: "Cancel" }),
755
+ /* @__PURE__ */ jsx8(
756
+ AlertDialogAction,
757
+ {
758
+ onClick: handleConfirmDiscard,
759
+ className: "bg-destructive text-white hover:bg-destructive/90",
760
+ children: "Discard"
761
+ }
762
+ )
763
+ ] })
764
+ ] }) })
765
+ ] });
766
+ }
767
+
768
+ // src/components/entity/entity-drawer-trigger.tsx
769
+ import { IconChevronRight as IconChevronRight2, IconPencil, IconPlus } from "@tabler/icons-react";
770
+ import { useState as useState4 } from "react";
771
+ import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
772
+ function EntityDrawerTrigger({
773
+ mode,
774
+ entity,
775
+ label,
776
+ children,
777
+ variant = "default",
778
+ disabled = false,
779
+ className,
780
+ open: controlledOpen,
781
+ onOpenChange
782
+ }) {
783
+ const [uncontrolledOpen, setUncontrolledOpen] = useState4(false);
784
+ const isControlled = controlledOpen !== void 0;
785
+ const open = isControlled ? controlledOpen : uncontrolledOpen;
786
+ const handleOpen = () => {
787
+ if (isControlled) {
788
+ onOpenChange?.(true);
789
+ } else {
790
+ setUncontrolledOpen(true);
791
+ }
792
+ };
793
+ const handleClose = () => {
794
+ if (isControlled) {
795
+ onOpenChange?.(false);
796
+ } else {
797
+ setUncontrolledOpen(false);
798
+ }
799
+ };
800
+ const buttonLabel = label || (mode === "new" ? `New ${entity}` : `Edit ${entity}`);
801
+ return /* @__PURE__ */ jsxs7(Fragment3, { children: [
802
+ mode === "edit" && variant === "icon" && /* @__PURE__ */ jsx9(
803
+ Button,
804
+ {
805
+ variant: "ghost",
806
+ size: "icon",
807
+ className: `h-8 w-8 opacity-0 group-hover:opacity-100 transition-opacity ${className}`,
808
+ onClick: handleOpen,
809
+ disabled,
810
+ children: /* @__PURE__ */ jsx9(IconChevronRight2, { className: "h-4 w-4" })
811
+ }
812
+ ),
813
+ mode === "edit" && variant !== "icon" && /* @__PURE__ */ jsxs7(
814
+ Button,
815
+ {
816
+ variant: variant === "outline" ? "outline" : "default",
817
+ size: "sm",
818
+ onClick: handleOpen,
819
+ disabled,
820
+ className,
821
+ children: [
822
+ /* @__PURE__ */ jsx9(IconPencil, { className: "mr-2 h-4 w-4" }),
823
+ buttonLabel
824
+ ]
825
+ }
826
+ ),
827
+ mode === "new" && /* @__PURE__ */ jsxs7(
828
+ Button,
829
+ {
830
+ variant: variant === "outline" ? "outline" : "default",
831
+ size: "sm",
832
+ onClick: handleOpen,
833
+ disabled,
834
+ className,
835
+ children: [
836
+ /* @__PURE__ */ jsx9(IconPlus, { className: "mr-2 h-4 w-4" }),
837
+ buttonLabel
838
+ ]
839
+ }
840
+ ),
841
+ open && children(open, handleClose)
842
+ ] });
843
+ }
844
+
845
+ // src/components/entity/entity-empty-state.tsx
846
+ import { IconPackage } from "@tabler/icons-react";
847
+
848
+ // src/components/empty.tsx
849
+ import { cva as cva2 } from "class-variance-authority";
850
+ import { jsx as jsx10 } from "react/jsx-runtime";
851
+ function Empty({ className, ...props }) {
852
+ return /* @__PURE__ */ jsx10(
853
+ "div",
854
+ {
855
+ "data-slot": "empty",
856
+ className: cn(
857
+ "flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12",
858
+ className
859
+ ),
860
+ ...props
861
+ }
862
+ );
863
+ }
864
+ function EmptyHeader({ className, ...props }) {
865
+ return /* @__PURE__ */ jsx10(
866
+ "div",
867
+ {
868
+ "data-slot": "empty-header",
869
+ className: cn(
870
+ "flex max-w-sm flex-col items-center gap-2 text-center",
871
+ className
872
+ ),
873
+ ...props
874
+ }
875
+ );
876
+ }
877
+ var emptyMediaVariants = cva2(
878
+ "flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0",
879
+ {
880
+ variants: {
881
+ variant: {
882
+ default: "bg-transparent",
883
+ icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6"
884
+ }
885
+ },
886
+ defaultVariants: {
887
+ variant: "default"
888
+ }
889
+ }
890
+ );
891
+ function EmptyMedia({
892
+ className,
893
+ variant = "default",
894
+ ...props
895
+ }) {
896
+ return /* @__PURE__ */ jsx10(
897
+ "div",
898
+ {
899
+ "data-slot": "empty-icon",
900
+ "data-variant": variant,
901
+ className: cn(emptyMediaVariants({ variant, className })),
902
+ ...props
903
+ }
904
+ );
905
+ }
906
+ function EmptyTitle({ className, ...props }) {
907
+ return /* @__PURE__ */ jsx10(
908
+ "div",
909
+ {
910
+ "data-slot": "empty-title",
911
+ className: cn("text-lg font-medium tracking-tight", className),
912
+ ...props
913
+ }
914
+ );
915
+ }
916
+ function EmptyDescription({ className, ...props }) {
917
+ return /* @__PURE__ */ jsx10(
918
+ "div",
919
+ {
920
+ "data-slot": "empty-description",
921
+ className: cn(
922
+ "text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
923
+ className
924
+ ),
925
+ ...props
926
+ }
927
+ );
928
+ }
929
+ function EmptyContent({ className, ...props }) {
930
+ return /* @__PURE__ */ jsx10(
931
+ "div",
932
+ {
933
+ "data-slot": "empty-content",
934
+ className: cn(
935
+ "flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance",
936
+ className
937
+ ),
938
+ ...props
939
+ }
940
+ );
941
+ }
942
+
943
+ // src/components/entity/entity-empty-state.tsx
944
+ import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
945
+ function EntityEmptyState({
946
+ icon: Icon2 = IconPackage,
947
+ title,
948
+ description,
949
+ entityName = "item",
950
+ actionLabel,
951
+ onAction,
952
+ children,
953
+ className
954
+ }) {
955
+ const defaultTitle = `No ${entityName}s yet`;
956
+ const defaultDescription = `Get started by creating your first ${entityName}.`;
957
+ const defaultActionLabel = `Create ${entityName}`;
958
+ return /* @__PURE__ */ jsxs8(Empty, { className: cn("border py-12", className), children: [
959
+ /* @__PURE__ */ jsxs8(EmptyHeader, { children: [
960
+ /* @__PURE__ */ jsx11(EmptyMedia, { variant: "icon", children: /* @__PURE__ */ jsx11(Icon2, { className: "size-5" }) }),
961
+ /* @__PURE__ */ jsx11(EmptyTitle, { children: title ?? defaultTitle }),
962
+ /* @__PURE__ */ jsx11(EmptyDescription, { children: description ?? defaultDescription })
963
+ ] }),
964
+ /* @__PURE__ */ jsx11(EmptyContent, { children: children ?? (onAction && /* @__PURE__ */ jsx11(Button, { onClick: onAction, children: actionLabel ?? defaultActionLabel })) })
965
+ ] });
966
+ }
967
+
968
+ // src/components/entity/entity-filter.tsx
969
+ import { IconFilter } from "@tabler/icons-react";
970
+ import { parseAsString, useQueryState } from "nuqs";
971
+
972
+ // src/components/select.tsx
973
+ import * as SelectPrimitive from "@radix-ui/react-select";
974
+ import { IconCheck as IconCheck2, IconChevronDown as IconChevronDown3, IconChevronUp } from "@tabler/icons-react";
975
+ import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
976
+ function Select({
977
+ ...props
978
+ }) {
979
+ return /* @__PURE__ */ jsx12(SelectPrimitive.Root, { "data-slot": "select", ...props });
980
+ }
981
+ function SelectValue({
982
+ ...props
983
+ }) {
984
+ return /* @__PURE__ */ jsx12(SelectPrimitive.Value, { "data-slot": "select-value", ...props });
985
+ }
986
+ function SelectTrigger({
987
+ className,
988
+ size = "default",
989
+ children,
990
+ ...props
991
+ }) {
992
+ return /* @__PURE__ */ jsxs9(
993
+ SelectPrimitive.Trigger,
994
+ {
995
+ "data-slot": "select-trigger",
996
+ "data-size": size,
997
+ className: cn(
998
+ "border-input data-[placeholder]:text-muted-foreground [&_svg:not([class*='text-'])]:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 dark:hover:bg-input/50 flex w-fit items-center justify-between gap-2 rounded-md border bg-transparent px-3 py-2 text-sm whitespace-nowrap shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 data-[size=default]:h-9 data-[size=sm]:h-8 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-2 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
999
+ className
1000
+ ),
1001
+ ...props,
1002
+ children: [
1003
+ children,
1004
+ /* @__PURE__ */ jsx12(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx12(IconChevronDown3, { className: "size-4 opacity-50" }) })
1005
+ ]
1006
+ }
1007
+ );
1008
+ }
1009
+ function SelectContent({
1010
+ className,
1011
+ children,
1012
+ position = "popper",
1013
+ align = "center",
1014
+ ...props
1015
+ }) {
1016
+ return /* @__PURE__ */ jsx12(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs9(
1017
+ SelectPrimitive.Content,
1018
+ {
1019
+ "data-slot": "select-content",
1020
+ className: cn(
1021
+ "bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 relative z-50 max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border shadow-md",
1022
+ position === "popper" && "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
1023
+ className
1024
+ ),
1025
+ position,
1026
+ align,
1027
+ ...props,
1028
+ children: [
1029
+ /* @__PURE__ */ jsx12(SelectScrollUpButton, {}),
1030
+ /* @__PURE__ */ jsx12(
1031
+ SelectPrimitive.Viewport,
1032
+ {
1033
+ className: cn(
1034
+ "p-1",
1035
+ position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
1036
+ ),
1037
+ children
1038
+ }
1039
+ ),
1040
+ /* @__PURE__ */ jsx12(SelectScrollDownButton, {})
1041
+ ]
1042
+ }
1043
+ ) });
1044
+ }
1045
+ function SelectItem({
1046
+ className,
1047
+ children,
1048
+ ...props
1049
+ }) {
1050
+ return /* @__PURE__ */ jsxs9(
1051
+ SelectPrimitive.Item,
1052
+ {
1053
+ "data-slot": "select-item",
1054
+ className: cn(
1055
+ "focus:bg-accent focus:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex w-full cursor-default items-center gap-2 rounded-sm py-1.5 pr-8 pl-2 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
1056
+ className
1057
+ ),
1058
+ ...props,
1059
+ children: [
1060
+ /* @__PURE__ */ jsx12("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ jsx12(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx12(IconCheck2, { className: "size-4" }) }) }),
1061
+ /* @__PURE__ */ jsx12(SelectPrimitive.ItemText, { children })
1062
+ ]
1063
+ }
1064
+ );
1065
+ }
1066
+ function SelectScrollUpButton({
1067
+ className,
1068
+ ...props
1069
+ }) {
1070
+ return /* @__PURE__ */ jsx12(
1071
+ SelectPrimitive.ScrollUpButton,
1072
+ {
1073
+ "data-slot": "select-scroll-up-button",
1074
+ className: cn(
1075
+ "flex cursor-default items-center justify-center py-1",
1076
+ className
1077
+ ),
1078
+ ...props,
1079
+ children: /* @__PURE__ */ jsx12(IconChevronUp, { className: "size-4" })
1080
+ }
1081
+ );
1082
+ }
1083
+ function SelectScrollDownButton({
1084
+ className,
1085
+ ...props
1086
+ }) {
1087
+ return /* @__PURE__ */ jsx12(
1088
+ SelectPrimitive.ScrollDownButton,
1089
+ {
1090
+ "data-slot": "select-scroll-down-button",
1091
+ className: cn(
1092
+ "flex cursor-default items-center justify-center py-1",
1093
+ className
1094
+ ),
1095
+ ...props,
1096
+ children: /* @__PURE__ */ jsx12(IconChevronDown3, { className: "size-4" })
1097
+ }
1098
+ );
1099
+ }
1100
+
1101
+ // src/components/entity/entity-filter.tsx
1102
+ import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
1103
+ function EntityFilter({
1104
+ paramKey = "filter",
1105
+ options,
1106
+ placeholder = "Filter",
1107
+ className,
1108
+ label
1109
+ }) {
1110
+ const [filter, setFilter] = useQueryState(
1111
+ paramKey,
1112
+ parseAsString.withDefault("").withOptions({ shallow: false })
1113
+ );
1114
+ return /* @__PURE__ */ jsxs10("div", { className: cn("flex items-center gap-2", className), children: [
1115
+ label && /* @__PURE__ */ jsx13("span", { className: "text-sm text-muted-foreground", children: label }),
1116
+ /* @__PURE__ */ jsxs10(
1117
+ Select,
1118
+ {
1119
+ value: filter || void 0,
1120
+ onValueChange: (value) => setFilter(value || null),
1121
+ children: [
1122
+ /* @__PURE__ */ jsxs10(SelectTrigger, { className: "w-[150px] h-9", children: [
1123
+ /* @__PURE__ */ jsx13(IconFilter, { className: "mr-2 h-4 w-4" }),
1124
+ /* @__PURE__ */ jsx13(SelectValue, { placeholder })
1125
+ ] }),
1126
+ /* @__PURE__ */ jsx13(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx13(SelectItem, { value: option.value, children: option.label }, option.value)) })
1127
+ ]
1128
+ }
1129
+ )
1130
+ ] });
1131
+ }
1132
+
1133
+ // src/components/entity/entity-form-actions.tsx
1134
+ import {
1135
+ IconCheck as IconCheck3,
1136
+ IconPlus as IconPlus2,
1137
+ IconRotateClockwise,
1138
+ IconTrash as IconTrash2
1139
+ } from "@tabler/icons-react";
1140
+
1141
+ // src/components/spinner.tsx
1142
+ import { IconLoader2 } from "@tabler/icons-react";
1143
+ import { jsx as jsx14 } from "react/jsx-runtime";
1144
+ function Spinner({
1145
+ className,
1146
+ ...props
1147
+ }) {
1148
+ return /* @__PURE__ */ jsx14(
1149
+ IconLoader2,
1150
+ {
1151
+ role: "status",
1152
+ "aria-label": "Loading",
1153
+ className: cn("size-4 animate-spin", className),
1154
+ ...props
1155
+ }
1156
+ );
1157
+ }
1158
+
1159
+ // src/components/entity/entity-form-actions.tsx
1160
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
1161
+ function EntityFormActions({
1162
+ mode,
1163
+ onSubmit,
1164
+ onReset,
1165
+ onDelete,
1166
+ onCancel,
1167
+ isSubmitting = false,
1168
+ isDeleting = false,
1169
+ disabled = false,
1170
+ submitLabel,
1171
+ deleteLabel = "Delete",
1172
+ itemName = "item"
1173
+ }) {
1174
+ const defaultSubmitLabel = mode === "new" ? "Create" : "Update";
1175
+ const label = submitLabel || defaultSubmitLabel;
1176
+ return /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-3", children: [
1177
+ onSubmit && /* @__PURE__ */ jsxs11(
1178
+ Button,
1179
+ {
1180
+ onClick: onSubmit,
1181
+ disabled: disabled || isSubmitting,
1182
+ className: "cursor-pointer",
1183
+ children: [
1184
+ isSubmitting && /* @__PURE__ */ jsx15(Spinner, { className: "mr-2 h-4 w-4" }),
1185
+ !isSubmitting && mode === "new" && /* @__PURE__ */ jsx15(IconPlus2, { className: "mr-2 h-4 w-4" }),
1186
+ !isSubmitting && mode === "edit" && /* @__PURE__ */ jsx15(IconCheck3, { className: "mr-2 h-4 w-4" }),
1187
+ label
1188
+ ]
1189
+ }
1190
+ ),
1191
+ mode === "new" && onReset && /* @__PURE__ */ jsxs11(
1192
+ Button,
1193
+ {
1194
+ variant: "outline",
1195
+ onClick: onReset,
1196
+ disabled,
1197
+ className: "cursor-pointer",
1198
+ children: [
1199
+ /* @__PURE__ */ jsx15(IconRotateClockwise, { className: "mr-2 h-4 w-4" }),
1200
+ "Reset"
1201
+ ]
1202
+ }
1203
+ ),
1204
+ mode === "edit" && onDelete && /* @__PURE__ */ jsxs11(AlertDialog, { children: [
1205
+ /* @__PURE__ */ jsx15(AlertDialogTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(
1206
+ Button,
1207
+ {
1208
+ variant: "destructive",
1209
+ disabled: disabled || isDeleting,
1210
+ className: "cursor-pointer",
1211
+ children: [
1212
+ isDeleting && /* @__PURE__ */ jsx15(Spinner, { className: "mr-2 h-4 w-4" }),
1213
+ /* @__PURE__ */ jsx15(IconTrash2, { className: "mr-2 h-4 w-4" }),
1214
+ deleteLabel
1215
+ ]
1216
+ }
1217
+ ) }),
1218
+ /* @__PURE__ */ jsxs11(AlertDialogContent, { children: [
1219
+ /* @__PURE__ */ jsxs11(AlertDialogHeader, { children: [
1220
+ /* @__PURE__ */ jsx15(AlertDialogTitle, { children: "Are you sure?" }),
1221
+ /* @__PURE__ */ jsxs11(AlertDialogDescription, { children: [
1222
+ "This will permanently delete this ",
1223
+ itemName,
1224
+ ". This action cannot be undone."
1225
+ ] })
1226
+ ] }),
1227
+ /* @__PURE__ */ jsxs11(AlertDialogFooter, { children: [
1228
+ /* @__PURE__ */ jsx15(AlertDialogCancel, { children: "Cancel" }),
1229
+ /* @__PURE__ */ jsx15(
1230
+ AlertDialogAction,
1231
+ {
1232
+ onClick: onDelete,
1233
+ className: "bg-destructive text-white hover:bg-destructive/90",
1234
+ children: "Delete"
1235
+ }
1236
+ )
1237
+ ] })
1238
+ ] })
1239
+ ] }),
1240
+ onCancel && /* @__PURE__ */ jsx15(
1241
+ Button,
1242
+ {
1243
+ variant: "ghost",
1244
+ onClick: onCancel,
1245
+ disabled,
1246
+ className: "cursor-pointer",
1247
+ children: "Cancel"
1248
+ }
1249
+ )
1250
+ ] });
1251
+ }
1252
+
1253
+ // src/components/entity/entity-header.tsx
1254
+ import { jsx as jsx16, jsxs as jsxs12 } from "react/jsx-runtime";
1255
+ function EntityHeader({
1256
+ title,
1257
+ icon,
1258
+ actions,
1259
+ search,
1260
+ filter,
1261
+ sort,
1262
+ view
1263
+ }) {
1264
+ return /* @__PURE__ */ jsx16(Card, { className: "p-4", children: /* @__PURE__ */ jsxs12("div", { className: "flex flex-col gap-4", children: [
1265
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center justify-between gap-2", children: [
1266
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1267
+ icon,
1268
+ /* @__PURE__ */ jsx16("span", { className: "text-lg font-semibold", children: title })
1269
+ ] }),
1270
+ actions
1271
+ ] }),
1272
+ /* @__PURE__ */ jsxs12("div", { className: "flex flex-col md:flex-row md:items-center justify-between gap-2", children: [
1273
+ /* @__PURE__ */ jsx16("div", { className: "grow", children: search }),
1274
+ /* @__PURE__ */ jsxs12("div", { className: "flex items-center gap-2", children: [
1275
+ filter,
1276
+ sort,
1277
+ view
1278
+ ] })
1279
+ ] })
1280
+ ] }) });
1281
+ }
1282
+
1283
+ // src/components/skeleton.tsx
1284
+ import { jsx as jsx17 } from "react/jsx-runtime";
1285
+ function Skeleton({ className, ...props }) {
1286
+ return /* @__PURE__ */ jsx17(
1287
+ "div",
1288
+ {
1289
+ "data-slot": "skeleton",
1290
+ className: cn("bg-accent animate-pulse rounded-md", className),
1291
+ ...props
1292
+ }
1293
+ );
1294
+ }
1295
+
1296
+ // src/components/table.tsx
1297
+ import { jsx as jsx18 } from "react/jsx-runtime";
1298
+ function Table({ className, ...props }) {
1299
+ return /* @__PURE__ */ jsx18(
1300
+ "div",
1301
+ {
1302
+ "data-slot": "table-container",
1303
+ className: "relative w-full overflow-x-auto",
1304
+ children: /* @__PURE__ */ jsx18(
1305
+ "table",
1306
+ {
1307
+ "data-slot": "table",
1308
+ className: cn("w-full caption-bottom text-sm", className),
1309
+ ...props
1310
+ }
1311
+ )
1312
+ }
1313
+ );
1314
+ }
1315
+ function TableHeader({ className, ...props }) {
1316
+ return /* @__PURE__ */ jsx18(
1317
+ "thead",
1318
+ {
1319
+ "data-slot": "table-header",
1320
+ className: cn("[&_tr]:border-b", className),
1321
+ ...props
1322
+ }
1323
+ );
1324
+ }
1325
+ function TableBody({ className, ...props }) {
1326
+ return /* @__PURE__ */ jsx18(
1327
+ "tbody",
1328
+ {
1329
+ "data-slot": "table-body",
1330
+ className: cn("[&_tr:last-child]:border-0", className),
1331
+ ...props
1332
+ }
1333
+ );
1334
+ }
1335
+ function TableRow({ className, ...props }) {
1336
+ return /* @__PURE__ */ jsx18(
1337
+ "tr",
1338
+ {
1339
+ "data-slot": "table-row",
1340
+ className: cn(
1341
+ "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
1342
+ className
1343
+ ),
1344
+ ...props
1345
+ }
1346
+ );
1347
+ }
1348
+ function TableHead({ className, ...props }) {
1349
+ return /* @__PURE__ */ jsx18(
1350
+ "th",
1351
+ {
1352
+ "data-slot": "table-head",
1353
+ className: cn(
1354
+ "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
1355
+ className
1356
+ ),
1357
+ ...props
1358
+ }
1359
+ );
1360
+ }
1361
+ function TableCell({ className, ...props }) {
1362
+ return /* @__PURE__ */ jsx18(
1363
+ "td",
1364
+ {
1365
+ "data-slot": "table-cell",
1366
+ className: cn(
1367
+ "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
1368
+ className
1369
+ ),
1370
+ ...props
1371
+ }
1372
+ );
1373
+ }
1374
+
1375
+ // src/components/entity/entity-loading-state.tsx
1376
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
1377
+ function EntityLoadingState({
1378
+ view,
1379
+ rowCount = 5,
1380
+ columnCount = 5,
1381
+ cardCount = 8,
1382
+ className
1383
+ }) {
1384
+ if (view === "table") {
1385
+ return /* @__PURE__ */ jsx19("div", { className: cn("rounded-md border", className), children: /* @__PURE__ */ jsxs13(Table, { children: [
1386
+ /* @__PURE__ */ jsx19(TableHeader, { children: /* @__PURE__ */ jsx19(TableRow, { children: Array.from({ length: columnCount }).map((_, i) => /* @__PURE__ */ jsx19(TableHead, { children: /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-24" }) }, `header-${i}`)) }) }),
1387
+ /* @__PURE__ */ jsx19(TableBody, { children: Array.from({ length: rowCount }).map((_, rowIndex) => /* @__PURE__ */ jsx19(TableRow, { children: Array.from({ length: columnCount }).map((_2, colIndex) => /* @__PURE__ */ jsx19(TableCell, { children: /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full" }) }, `cell-${rowIndex}-${colIndex}`)) }, `row-${rowIndex}`)) })
1388
+ ] }) });
1389
+ }
1390
+ return /* @__PURE__ */ jsx19(
1391
+ "div",
1392
+ {
1393
+ className: cn(
1394
+ "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4",
1395
+ className
1396
+ ),
1397
+ children: Array.from({ length: cardCount }).map((_, i) => /* @__PURE__ */ jsxs13("div", { className: "space-y-3 rounded-lg border p-4", children: [
1398
+ /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-2", children: [
1399
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-4 rounded-full" }),
1400
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-5 w-32" })
1401
+ ] }),
1402
+ /* @__PURE__ */ jsxs13("div", { className: "flex gap-2", children: [
1403
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-5 w-16" }),
1404
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-5 w-16" })
1405
+ ] }),
1406
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-full" }),
1407
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-4 w-3/4" }),
1408
+ /* @__PURE__ */ jsx19(Skeleton, { className: "h-3 w-24" })
1409
+ ] }, `card-${i}`))
1410
+ }
1411
+ );
1412
+ }
1413
+
1414
+ // src/components/entity/entity-search.tsx
1415
+ import { IconSearch, IconX as IconX2 } from "@tabler/icons-react";
1416
+ import { parseAsString as parseAsString2, useQueryState as useQueryState2 } from "nuqs";
1417
+ import { useRef as useRef2 } from "react";
1418
+ import { useDebouncedCallback } from "use-debounce";
1419
+
1420
+ // src/components/input.tsx
1421
+ import { jsx as jsx20 } from "react/jsx-runtime";
1422
+ function Input({ className, type, ...props }) {
1423
+ return /* @__PURE__ */ jsx20(
1424
+ "input",
1425
+ {
1426
+ type,
1427
+ "data-slot": "input",
1428
+ className: cn(
1429
+ "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
1430
+ "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
1431
+ "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
1432
+ className
1433
+ ),
1434
+ ...props
1435
+ }
1436
+ );
1437
+ }
1438
+
1439
+ // src/components/entity/entity-search.tsx
1440
+ import { jsx as jsx21, jsxs as jsxs14 } from "react/jsx-runtime";
1441
+ function EntitySearch({
1442
+ paramKey = "search",
1443
+ placeholder = "Search...",
1444
+ className
1445
+ }) {
1446
+ const ref = useRef2(null);
1447
+ const [search, setSearch] = useQueryState2(
1448
+ paramKey,
1449
+ parseAsString2.withDefault("").withOptions({ shallow: false })
1450
+ );
1451
+ const handleSearch = useDebouncedCallback((term) => {
1452
+ setSearch(term || null);
1453
+ }, 300);
1454
+ const handleClear = () => {
1455
+ setSearch(null);
1456
+ if (ref.current) {
1457
+ ref.current.value = "";
1458
+ }
1459
+ };
1460
+ return /* @__PURE__ */ jsxs14("div", { className: cn("relative", className), children: [
1461
+ /* @__PURE__ */ jsx21(IconSearch, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
1462
+ /* @__PURE__ */ jsx21(
1463
+ Input,
1464
+ {
1465
+ ref,
1466
+ placeholder,
1467
+ defaultValue: search,
1468
+ onChange: (e) => handleSearch(e.target.value),
1469
+ className: "pl-9 pr-9"
1470
+ }
1471
+ ),
1472
+ search && /* @__PURE__ */ jsx21(
1473
+ "button",
1474
+ {
1475
+ type: "button",
1476
+ onClick: handleClear,
1477
+ className: "absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground hover:text-foreground",
1478
+ children: /* @__PURE__ */ jsx21(IconX2, { className: "h-4 w-4" })
1479
+ }
1480
+ )
1481
+ ] });
1482
+ }
1483
+
1484
+ // src/components/entity/entity-sort.tsx
1485
+ import {
1486
+ IconSortAscendingLetters,
1487
+ IconSortDescendingLetters
1488
+ } from "@tabler/icons-react";
1489
+ import { parseAsString as parseAsString3, useQueryState as useQueryState3 } from "nuqs";
1490
+ import { jsx as jsx22, jsxs as jsxs15 } from "react/jsx-runtime";
1491
+ function EntitySort({
1492
+ sortKey = "sort",
1493
+ orderKey = "order",
1494
+ options,
1495
+ defaultSort,
1496
+ className
1497
+ }) {
1498
+ const [sort, setSort] = useQueryState3(
1499
+ sortKey,
1500
+ parseAsString3.withDefault(defaultSort || options[0]?.value || "").withOptions({ shallow: false })
1501
+ );
1502
+ const [order, setOrder] = useQueryState3(
1503
+ orderKey,
1504
+ parseAsString3.withDefault("desc").withOptions({ shallow: false })
1505
+ );
1506
+ const toggleOrder = () => {
1507
+ setOrder(order === "asc" ? "desc" : "asc");
1508
+ };
1509
+ return /* @__PURE__ */ jsxs15("div", { className: cn("flex items-center gap-0", className), children: [
1510
+ /* @__PURE__ */ jsxs15(Select, { value: sort, onValueChange: setSort, children: [
1511
+ /* @__PURE__ */ jsx22(SelectTrigger, { className: "w-[150px] h-9 rounded-r-none border-r-0", children: /* @__PURE__ */ jsx22(SelectValue, { placeholder: "Sort by" }) }),
1512
+ /* @__PURE__ */ jsx22(SelectContent, { children: options.map((option) => /* @__PURE__ */ jsx22(SelectItem, { value: option.value, children: option.label }, option.value)) })
1513
+ ] }),
1514
+ /* @__PURE__ */ jsx22(
1515
+ Button,
1516
+ {
1517
+ variant: "outline",
1518
+ size: "icon",
1519
+ className: "h-9 rounded-l-none",
1520
+ onClick: toggleOrder,
1521
+ children: order === "asc" ? /* @__PURE__ */ jsx22(IconSortAscendingLetters, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx22(IconSortDescendingLetters, { className: "h-4 w-4" })
1522
+ }
1523
+ )
1524
+ ] });
1525
+ }
1526
+
1527
+ // src/components/entity/entity-view-toggle.tsx
1528
+ import { IconGridDots, IconList, IconTable } from "@tabler/icons-react";
1529
+ import { parseAsString as parseAsString4, useQueryState as useQueryState4 } from "nuqs";
1530
+
1531
+ // src/components/toggle.tsx
1532
+ import * as TogglePrimitive from "@radix-ui/react-toggle";
1533
+ import { cva as cva3 } from "class-variance-authority";
1534
+ import { jsx as jsx23 } from "react/jsx-runtime";
1535
+ var toggleVariants = cva3(
1536
+ "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium hover:bg-muted hover:text-muted-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0 focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] outline-none transition-[color,box-shadow] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive whitespace-nowrap",
1537
+ {
1538
+ variants: {
1539
+ variant: {
1540
+ default: "bg-transparent",
1541
+ outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
1542
+ },
1543
+ size: {
1544
+ default: "h-9 px-2 min-w-9",
1545
+ sm: "h-8 px-1.5 min-w-8",
1546
+ lg: "h-10 px-2.5 min-w-10"
1547
+ }
1548
+ },
1549
+ defaultVariants: {
1550
+ variant: "default",
1551
+ size: "default"
1552
+ }
1553
+ }
1554
+ );
1555
+
1556
+ // src/components/toggle-group.tsx
1557
+ import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group";
1558
+ import * as React from "react";
1559
+ import { jsx as jsx24 } from "react/jsx-runtime";
1560
+ var ToggleGroupContext = React.createContext({
1561
+ size: "default",
1562
+ variant: "default",
1563
+ spacing: 0
1564
+ });
1565
+ function ToggleGroup({
1566
+ className,
1567
+ variant,
1568
+ size,
1569
+ spacing = 0,
1570
+ children,
1571
+ ...props
1572
+ }) {
1573
+ return /* @__PURE__ */ jsx24(
1574
+ ToggleGroupPrimitive.Root,
1575
+ {
1576
+ "data-slot": "toggle-group",
1577
+ "data-variant": variant,
1578
+ "data-size": size,
1579
+ "data-spacing": spacing,
1580
+ style: { "--gap": spacing },
1581
+ className: cn(
1582
+ "group/toggle-group flex w-fit items-center gap-[--spacing(var(--gap))] rounded-md data-[spacing=default]:data-[variant=outline]:shadow-xs",
1583
+ className
1584
+ ),
1585
+ ...props,
1586
+ children: /* @__PURE__ */ jsx24(ToggleGroupContext.Provider, { value: { variant, size, spacing }, children })
1587
+ }
1588
+ );
1589
+ }
1590
+ function ToggleGroupItem({
1591
+ className,
1592
+ children,
1593
+ variant,
1594
+ size,
1595
+ ...props
1596
+ }) {
1597
+ const context = React.useContext(ToggleGroupContext);
1598
+ return /* @__PURE__ */ jsx24(
1599
+ ToggleGroupPrimitive.Item,
1600
+ {
1601
+ "data-slot": "toggle-group-item",
1602
+ "data-variant": context.variant || variant,
1603
+ "data-size": context.size || size,
1604
+ "data-spacing": context.spacing,
1605
+ className: cn(
1606
+ toggleVariants({
1607
+ variant: context.variant || variant,
1608
+ size: context.size || size
1609
+ }),
1610
+ "w-auto min-w-0 shrink-0 px-3 focus:z-10 focus-visible:z-10",
1611
+ "data-[spacing=0]:rounded-none data-[spacing=0]:shadow-none data-[spacing=0]:first:rounded-l-md data-[spacing=0]:last:rounded-r-md data-[spacing=0]:data-[variant=outline]:border-l-0 data-[spacing=0]:data-[variant=outline]:first:border-l",
1612
+ className
1613
+ ),
1614
+ ...props,
1615
+ children
1616
+ }
1617
+ );
1618
+ }
1619
+
1620
+ // src/components/entity/entity-view-toggle.tsx
1621
+ import { jsx as jsx25 } from "react/jsx-runtime";
1622
+ var viewIcons = {
1623
+ table: /* @__PURE__ */ jsx25(IconTable, { className: "h-4 w-4" }),
1624
+ card: /* @__PURE__ */ jsx25(IconGridDots, { className: "h-4 w-4" }),
1625
+ list: /* @__PURE__ */ jsx25(IconList, { className: "h-4 w-4" })
1626
+ };
1627
+ function EntityViewToggle({
1628
+ paramKey = "view",
1629
+ defaultView = "table",
1630
+ views = ["table", "card"],
1631
+ className
1632
+ }) {
1633
+ const [view, setView] = useQueryState4(
1634
+ paramKey,
1635
+ parseAsString4.withDefault(defaultView).withOptions({ shallow: false })
1636
+ );
1637
+ return /* @__PURE__ */ jsx25(
1638
+ ToggleGroup,
1639
+ {
1640
+ type: "single",
1641
+ value: view,
1642
+ onValueChange: (value) => value && setView(value),
1643
+ className: cn("border rounded-md", className),
1644
+ children: views.map((v) => /* @__PURE__ */ jsx25(
1645
+ ToggleGroupItem,
1646
+ {
1647
+ value: v,
1648
+ "aria-label": `${v} view`,
1649
+ className: "h-9 px-3",
1650
+ children: viewIcons[v]
1651
+ },
1652
+ v
1653
+ ))
1654
+ }
1655
+ );
1656
+ }
1657
+ export {
1658
+ EntityBulkActions,
1659
+ EntityDetailHeader,
1660
+ EntityDrawer,
1661
+ EntityDrawerTrigger,
1662
+ EntityEmptyState,
1663
+ EntityFilter,
1664
+ EntityFormActions,
1665
+ EntityHeader,
1666
+ EntityLoadingState,
1667
+ EntitySearch,
1668
+ EntitySort,
1669
+ EntityViewToggle
1670
+ };
1671
+ //# sourceMappingURL=index.js.map