@mesob/ui 0.2.3 → 0.2.5

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