@tirth_jasoliya/ui 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +240 -0
- package/dist/index.cjs +3133 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +398 -0
- package/dist/index.d.ts +398 -0
- package/dist/index.js +3091 -0
- package/dist/index.js.map +1 -0
- package/package.json +44 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
AppMetaProvider: () => AppMetaProvider,
|
|
34
|
+
DataTable: () => DataTable,
|
|
35
|
+
DataTableActionBar: () => DataTableActionBar,
|
|
36
|
+
DataTableActionBarAction: () => DataTableActionBarAction,
|
|
37
|
+
DataTableActionBarSelection: () => DataTableActionBarSelection,
|
|
38
|
+
DataTemplate: () => DataTemplate,
|
|
39
|
+
DataTemplateActionBar: () => DataTemplateActionBar,
|
|
40
|
+
DataTemplateActionBarAction: () => DataTemplateActionBarAction,
|
|
41
|
+
DataTemplateActionBarSelection: () => DataTemplateActionBarSelection,
|
|
42
|
+
GeneralHelper: () => GeneralHelper,
|
|
43
|
+
createLayoutComponents: () => createLayoutComponents,
|
|
44
|
+
createPageTemplateHook: () => createPageTemplateHook,
|
|
45
|
+
createTypedAppMetaContext: () => createTypedAppMetaContext
|
|
46
|
+
});
|
|
47
|
+
module.exports = __toCommonJS(index_exports);
|
|
48
|
+
|
|
49
|
+
// src/components/data/data-table/data-table.tsx
|
|
50
|
+
var import_react_table = require("@tanstack/react-table");
|
|
51
|
+
var import_lucide_react5 = require("lucide-react");
|
|
52
|
+
|
|
53
|
+
// src/components/ui/button.tsx
|
|
54
|
+
var import_radix_ui = require("radix-ui");
|
|
55
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
56
|
+
|
|
57
|
+
// src/lib/utils.ts
|
|
58
|
+
var import_clsx = require("clsx");
|
|
59
|
+
var import_tailwind_merge = require("tailwind-merge");
|
|
60
|
+
function cn(...inputs) {
|
|
61
|
+
return (0, import_tailwind_merge.twMerge)((0, import_clsx.clsx)(inputs));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// src/components/ui/button.tsx
|
|
65
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
66
|
+
var buttonVariants = (0, import_class_variance_authority.cva)(
|
|
67
|
+
"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",
|
|
68
|
+
{
|
|
69
|
+
variants: {
|
|
70
|
+
variant: {
|
|
71
|
+
default: "bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
|
|
72
|
+
destructive: "bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
73
|
+
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",
|
|
74
|
+
secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
|
|
75
|
+
ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
|
|
76
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
77
|
+
},
|
|
78
|
+
size: {
|
|
79
|
+
default: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
80
|
+
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
|
|
81
|
+
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
82
|
+
icon: "size-9"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
defaultVariants: {
|
|
86
|
+
variant: "default",
|
|
87
|
+
size: "default"
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
function Button({
|
|
92
|
+
className,
|
|
93
|
+
variant,
|
|
94
|
+
size,
|
|
95
|
+
asChild = false,
|
|
96
|
+
...props
|
|
97
|
+
}) {
|
|
98
|
+
const Comp = asChild ? import_radix_ui.Slot.Slot : "button";
|
|
99
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
100
|
+
Comp,
|
|
101
|
+
{
|
|
102
|
+
"data-slot": "button",
|
|
103
|
+
className: cn(buttonVariants({ variant, size, className }), "transition-none"),
|
|
104
|
+
...props
|
|
105
|
+
}
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// src/components/ui/table.tsx
|
|
110
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
111
|
+
function Table({ className, ...props }) {
|
|
112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
113
|
+
"div",
|
|
114
|
+
{
|
|
115
|
+
"data-slot": "table-container",
|
|
116
|
+
className: "relative w-full overflow-auto max-h-full",
|
|
117
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
118
|
+
"table",
|
|
119
|
+
{
|
|
120
|
+
"data-slot": "table",
|
|
121
|
+
className: cn("w-full caption-bottom text-sm", className),
|
|
122
|
+
...props
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
function TableHeader({ className, ...props }) {
|
|
129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
130
|
+
"thead",
|
|
131
|
+
{
|
|
132
|
+
"data-slot": "table-header",
|
|
133
|
+
className: cn("[&_tr]:border-b", className),
|
|
134
|
+
...props
|
|
135
|
+
}
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
function TableBody({ className, ...props }) {
|
|
139
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
140
|
+
"tbody",
|
|
141
|
+
{
|
|
142
|
+
"data-slot": "table-body",
|
|
143
|
+
className: cn("[&_tr:last-child]:border-0", className),
|
|
144
|
+
...props
|
|
145
|
+
}
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
function TableFooter({ className, ...props }) {
|
|
149
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
150
|
+
"tfoot",
|
|
151
|
+
{
|
|
152
|
+
"data-slot": "table-footer",
|
|
153
|
+
className: cn(
|
|
154
|
+
"bg-muted/50 border-t font-medium [&>tr]:last:border-b-0",
|
|
155
|
+
className
|
|
156
|
+
),
|
|
157
|
+
...props
|
|
158
|
+
}
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
function TableRow({ className, ...props }) {
|
|
162
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
163
|
+
"tr",
|
|
164
|
+
{
|
|
165
|
+
"data-slot": "table-row",
|
|
166
|
+
className: cn(
|
|
167
|
+
"hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
|
|
168
|
+
className
|
|
169
|
+
),
|
|
170
|
+
...props
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
function TableHead({ className, ...props }) {
|
|
175
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
176
|
+
"th",
|
|
177
|
+
{
|
|
178
|
+
"data-slot": "table-head",
|
|
179
|
+
className: cn(
|
|
180
|
+
"text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap",
|
|
181
|
+
className
|
|
182
|
+
),
|
|
183
|
+
...props
|
|
184
|
+
}
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
function TableCell({ className, ...props }) {
|
|
188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
189
|
+
"td",
|
|
190
|
+
{
|
|
191
|
+
"data-slot": "table-cell",
|
|
192
|
+
className: cn(
|
|
193
|
+
"p-2 align-middle whitespace-nowrap",
|
|
194
|
+
className
|
|
195
|
+
),
|
|
196
|
+
...props
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/components/ui/card.tsx
|
|
202
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
203
|
+
function Card({ className, ...props }) {
|
|
204
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
205
|
+
"div",
|
|
206
|
+
{
|
|
207
|
+
"data-slot": "card",
|
|
208
|
+
className: cn(
|
|
209
|
+
"bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm",
|
|
210
|
+
className
|
|
211
|
+
),
|
|
212
|
+
...props
|
|
213
|
+
}
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
function CardContent({ className, ...props }) {
|
|
217
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
218
|
+
"div",
|
|
219
|
+
{
|
|
220
|
+
"data-slot": "card-content",
|
|
221
|
+
className: cn("px-6", className),
|
|
222
|
+
...props
|
|
223
|
+
}
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// src/components/ui/tooltip.tsx
|
|
228
|
+
var import_radix_ui2 = require("radix-ui");
|
|
229
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
230
|
+
function TooltipProvider({
|
|
231
|
+
delayDuration = 0,
|
|
232
|
+
...props
|
|
233
|
+
}) {
|
|
234
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
235
|
+
import_radix_ui2.Tooltip.Provider,
|
|
236
|
+
{
|
|
237
|
+
"data-slot": "tooltip-provider",
|
|
238
|
+
delayDuration,
|
|
239
|
+
...props
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
function Tooltip({
|
|
244
|
+
...props
|
|
245
|
+
}) {
|
|
246
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_radix_ui2.Tooltip.Root, { "data-slot": "tooltip", ...props }) });
|
|
247
|
+
}
|
|
248
|
+
function TooltipTrigger({
|
|
249
|
+
...props
|
|
250
|
+
}) {
|
|
251
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_radix_ui2.Tooltip.Trigger, { "data-slot": "tooltip-trigger", ...props });
|
|
252
|
+
}
|
|
253
|
+
function TooltipContent({
|
|
254
|
+
className,
|
|
255
|
+
sideOffset = 0,
|
|
256
|
+
children,
|
|
257
|
+
...props
|
|
258
|
+
}) {
|
|
259
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_radix_ui2.Tooltip.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
260
|
+
import_radix_ui2.Tooltip.Content,
|
|
261
|
+
{
|
|
262
|
+
"data-slot": "tooltip-content",
|
|
263
|
+
sideOffset,
|
|
264
|
+
className: cn(
|
|
265
|
+
"bg-primary text-primary-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-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 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance",
|
|
266
|
+
className
|
|
267
|
+
),
|
|
268
|
+
...props,
|
|
269
|
+
children: [
|
|
270
|
+
children,
|
|
271
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_radix_ui2.Tooltip.Arrow, { className: "bg-primary fill-primary z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" })
|
|
272
|
+
]
|
|
273
|
+
}
|
|
274
|
+
) });
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// src/components/data/data-table/data-table-toolbar.tsx
|
|
278
|
+
var import_lucide_react3 = require("lucide-react");
|
|
279
|
+
|
|
280
|
+
// src/components/ui/input.tsx
|
|
281
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
282
|
+
function Input({ className, type, ...props }) {
|
|
283
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
284
|
+
"input",
|
|
285
|
+
{
|
|
286
|
+
type,
|
|
287
|
+
"data-slot": "input",
|
|
288
|
+
className: cn(
|
|
289
|
+
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex 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",
|
|
290
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
291
|
+
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
292
|
+
className
|
|
293
|
+
),
|
|
294
|
+
...props
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// src/components/ui/select.tsx
|
|
300
|
+
var import_radix_ui3 = require("radix-ui");
|
|
301
|
+
var import_lucide_react = require("lucide-react");
|
|
302
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
303
|
+
function Select({
|
|
304
|
+
...props
|
|
305
|
+
}) {
|
|
306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Select.Root, { "data-slot": "select", ...props });
|
|
307
|
+
}
|
|
308
|
+
function SelectValue({
|
|
309
|
+
...props
|
|
310
|
+
}) {
|
|
311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Select.Value, { "data-slot": "select-value", ...props });
|
|
312
|
+
}
|
|
313
|
+
function SelectTrigger({
|
|
314
|
+
className,
|
|
315
|
+
size = "default",
|
|
316
|
+
children,
|
|
317
|
+
...props
|
|
318
|
+
}) {
|
|
319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
320
|
+
import_radix_ui3.Select.Trigger,
|
|
321
|
+
{
|
|
322
|
+
"data-slot": "select-trigger",
|
|
323
|
+
"data-size": size,
|
|
324
|
+
className: cn(
|
|
325
|
+
"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",
|
|
326
|
+
className
|
|
327
|
+
),
|
|
328
|
+
...props,
|
|
329
|
+
children: [
|
|
330
|
+
children,
|
|
331
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Select.Icon, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.ChevronDownIcon, { className: "size-4 opacity-50" }) })
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
function SelectContent({
|
|
337
|
+
className,
|
|
338
|
+
children,
|
|
339
|
+
position = "popper",
|
|
340
|
+
...props
|
|
341
|
+
}) {
|
|
342
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Select.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
343
|
+
import_radix_ui3.Select.Content,
|
|
344
|
+
{
|
|
345
|
+
"data-slot": "select-content",
|
|
346
|
+
className: cn(
|
|
347
|
+
"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",
|
|
348
|
+
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",
|
|
349
|
+
className
|
|
350
|
+
),
|
|
351
|
+
position,
|
|
352
|
+
...props,
|
|
353
|
+
children: [
|
|
354
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectScrollUpButton, {}),
|
|
355
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
356
|
+
import_radix_ui3.Select.Viewport,
|
|
357
|
+
{
|
|
358
|
+
className: cn(
|
|
359
|
+
"p-1",
|
|
360
|
+
position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)] scroll-my-1"
|
|
361
|
+
),
|
|
362
|
+
children
|
|
363
|
+
}
|
|
364
|
+
),
|
|
365
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SelectScrollDownButton, {})
|
|
366
|
+
]
|
|
367
|
+
}
|
|
368
|
+
) });
|
|
369
|
+
}
|
|
370
|
+
function SelectItem({
|
|
371
|
+
className,
|
|
372
|
+
children,
|
|
373
|
+
...props
|
|
374
|
+
}) {
|
|
375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
376
|
+
import_radix_ui3.Select.Item,
|
|
377
|
+
{
|
|
378
|
+
"data-slot": "select-item",
|
|
379
|
+
className: cn(
|
|
380
|
+
"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",
|
|
381
|
+
className
|
|
382
|
+
),
|
|
383
|
+
...props,
|
|
384
|
+
children: [
|
|
385
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute right-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Select.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.CheckIcon, { className: "size-4" }) }) }),
|
|
386
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_radix_ui3.Select.ItemText, { children })
|
|
387
|
+
]
|
|
388
|
+
}
|
|
389
|
+
);
|
|
390
|
+
}
|
|
391
|
+
function SelectScrollUpButton({
|
|
392
|
+
className,
|
|
393
|
+
...props
|
|
394
|
+
}) {
|
|
395
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
396
|
+
import_radix_ui3.Select.ScrollUpButton,
|
|
397
|
+
{
|
|
398
|
+
"data-slot": "select-scroll-up-button",
|
|
399
|
+
className: cn(
|
|
400
|
+
"flex cursor-default items-center justify-center py-1",
|
|
401
|
+
className
|
|
402
|
+
),
|
|
403
|
+
...props,
|
|
404
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.ChevronUpIcon, { className: "size-4" })
|
|
405
|
+
}
|
|
406
|
+
);
|
|
407
|
+
}
|
|
408
|
+
function SelectScrollDownButton({
|
|
409
|
+
className,
|
|
410
|
+
...props
|
|
411
|
+
}) {
|
|
412
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
413
|
+
import_radix_ui3.Select.ScrollDownButton,
|
|
414
|
+
{
|
|
415
|
+
"data-slot": "select-scroll-down-button",
|
|
416
|
+
className: cn(
|
|
417
|
+
"flex cursor-default items-center justify-center py-1",
|
|
418
|
+
className
|
|
419
|
+
),
|
|
420
|
+
...props,
|
|
421
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react.ChevronDownIcon, { className: "size-4" })
|
|
422
|
+
}
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
// src/components/ui/dropdown-menu.tsx
|
|
427
|
+
var import_radix_ui4 = require("radix-ui");
|
|
428
|
+
var import_lucide_react2 = require("lucide-react");
|
|
429
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
430
|
+
function DropdownMenu({
|
|
431
|
+
...props
|
|
432
|
+
}) {
|
|
433
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui4.DropdownMenu.Root, { "data-slot": "dropdown-menu", ...props });
|
|
434
|
+
}
|
|
435
|
+
function DropdownMenuTrigger({
|
|
436
|
+
...props
|
|
437
|
+
}) {
|
|
438
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
439
|
+
import_radix_ui4.DropdownMenu.Trigger,
|
|
440
|
+
{
|
|
441
|
+
"data-slot": "dropdown-menu-trigger",
|
|
442
|
+
...props
|
|
443
|
+
}
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
function DropdownMenuContent({
|
|
447
|
+
className,
|
|
448
|
+
sideOffset = 4,
|
|
449
|
+
...props
|
|
450
|
+
}) {
|
|
451
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui4.DropdownMenu.Portal, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
452
|
+
import_radix_ui4.DropdownMenu.Content,
|
|
453
|
+
{
|
|
454
|
+
"data-slot": "dropdown-menu-content",
|
|
455
|
+
sideOffset,
|
|
456
|
+
className: cn(
|
|
457
|
+
"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) rounded-md border p-1 shadow-md",
|
|
458
|
+
className
|
|
459
|
+
),
|
|
460
|
+
...props
|
|
461
|
+
}
|
|
462
|
+
) });
|
|
463
|
+
}
|
|
464
|
+
function DropdownMenuGroup({
|
|
465
|
+
...props
|
|
466
|
+
}) {
|
|
467
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui4.DropdownMenu.Group, { "data-slot": "dropdown-menu-group", ...props });
|
|
468
|
+
}
|
|
469
|
+
function DropdownMenuItem({
|
|
470
|
+
className,
|
|
471
|
+
inset,
|
|
472
|
+
variant = "default",
|
|
473
|
+
...props
|
|
474
|
+
}) {
|
|
475
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
476
|
+
import_radix_ui4.DropdownMenu.Item,
|
|
477
|
+
{
|
|
478
|
+
"data-slot": "dropdown-menu-item",
|
|
479
|
+
"data-inset": inset,
|
|
480
|
+
"data-variant": variant,
|
|
481
|
+
className: cn(
|
|
482
|
+
"cursor-pointer 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 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",
|
|
483
|
+
className
|
|
484
|
+
),
|
|
485
|
+
...props
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
}
|
|
489
|
+
function DropdownMenuCheckboxItem({
|
|
490
|
+
className,
|
|
491
|
+
children,
|
|
492
|
+
checked,
|
|
493
|
+
...props
|
|
494
|
+
}) {
|
|
495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
496
|
+
import_radix_ui4.DropdownMenu.CheckboxItem,
|
|
497
|
+
{
|
|
498
|
+
"data-slot": "dropdown-menu-checkbox-item",
|
|
499
|
+
className: cn(
|
|
500
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 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",
|
|
501
|
+
className
|
|
502
|
+
),
|
|
503
|
+
checked,
|
|
504
|
+
...props,
|
|
505
|
+
children: [
|
|
506
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "pointer-events-none absolute left-2 flex size-3.5 items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_radix_ui4.DropdownMenu.ItemIndicator, { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react2.CheckIcon, { className: "size-4" }) }) }),
|
|
507
|
+
children
|
|
508
|
+
]
|
|
509
|
+
}
|
|
510
|
+
);
|
|
511
|
+
}
|
|
512
|
+
function DropdownMenuLabel({
|
|
513
|
+
className,
|
|
514
|
+
inset,
|
|
515
|
+
...props
|
|
516
|
+
}) {
|
|
517
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
518
|
+
import_radix_ui4.DropdownMenu.Label,
|
|
519
|
+
{
|
|
520
|
+
"data-slot": "dropdown-menu-label",
|
|
521
|
+
"data-inset": inset,
|
|
522
|
+
className: cn(
|
|
523
|
+
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
524
|
+
className
|
|
525
|
+
),
|
|
526
|
+
...props
|
|
527
|
+
}
|
|
528
|
+
);
|
|
529
|
+
}
|
|
530
|
+
function DropdownMenuSeparator({
|
|
531
|
+
className,
|
|
532
|
+
...props
|
|
533
|
+
}) {
|
|
534
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
535
|
+
import_radix_ui4.DropdownMenu.Separator,
|
|
536
|
+
{
|
|
537
|
+
"data-slot": "dropdown-menu-separator",
|
|
538
|
+
className: cn("bg-border -mx-1 my-1 h-px", className),
|
|
539
|
+
...props
|
|
540
|
+
}
|
|
541
|
+
);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// src/components/data/data-table/data-table-toolbar.tsx
|
|
545
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
546
|
+
function DataTableToolbar({
|
|
547
|
+
table,
|
|
548
|
+
filters = [],
|
|
549
|
+
globalFilter,
|
|
550
|
+
onGlobalFilterChange,
|
|
551
|
+
enableGlobalFilter = true,
|
|
552
|
+
onExport,
|
|
553
|
+
onRefresh,
|
|
554
|
+
loading = false,
|
|
555
|
+
enableColumnVisibility = true,
|
|
556
|
+
data,
|
|
557
|
+
onClearSorting,
|
|
558
|
+
onClearFilters,
|
|
559
|
+
enableColumnPinning = false
|
|
560
|
+
}) {
|
|
561
|
+
const getAllLeafColumns = () => {
|
|
562
|
+
return table.getAllLeafColumns().filter((column) => column.getCanHide?.() !== false);
|
|
563
|
+
};
|
|
564
|
+
const getGroupColumns = () => {
|
|
565
|
+
return table.getAllColumns().filter(
|
|
566
|
+
(column) => !table.getAllLeafColumns().includes(column) && column.columns?.length && column.columns.some((col) => col.getCanHide?.() !== false)
|
|
567
|
+
);
|
|
568
|
+
};
|
|
569
|
+
const getUngroupedLeafColumns = () => {
|
|
570
|
+
const groupedColumnIds = new Set(
|
|
571
|
+
getGroupColumns().flatMap(
|
|
572
|
+
(group) => group.columns?.filter((col) => col.getCanHide?.() !== false).map((c) => c.id) || []
|
|
573
|
+
)
|
|
574
|
+
);
|
|
575
|
+
return getAllLeafColumns().filter((column) => !groupedColumnIds.has(column.id));
|
|
576
|
+
};
|
|
577
|
+
const getColumnDisplayName = (columnId, groupName) => {
|
|
578
|
+
if (groupName && columnId.startsWith(`${groupName}.`)) {
|
|
579
|
+
const cleanId = columnId.replace(`${groupName}.`, "");
|
|
580
|
+
return cleanId.split("_").map((word) => word.slice(1)).join(" ");
|
|
581
|
+
}
|
|
582
|
+
return columnId.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
583
|
+
};
|
|
584
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "rounded-xl", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex flex-col gap-6", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
585
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex items-center gap-3", children: filters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-3 flex-wrap", children: [
|
|
586
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Filter, { className: "h-4 w-4" }) }),
|
|
587
|
+
filters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: cn("relative min-w-[150px]", filter.width), children: filter.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
588
|
+
Select,
|
|
589
|
+
{
|
|
590
|
+
value: table.getColumn(filter.key)?.getFilterValue() ?? "",
|
|
591
|
+
onValueChange: (value) => table.getColumn(filter.key)?.setFilterValue(value === "all" ? "" : value),
|
|
592
|
+
children: [
|
|
593
|
+
filter.icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }) }),
|
|
594
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectTrigger, { className: cn("h-9 rounded-lg w-full", filter.icon && "pl-9"), children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectValue, { placeholder: filter.placeholder }) }),
|
|
595
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(SelectContent, { className: "rounded-lg", children: [
|
|
596
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectItem, { value: "all", children: "All" }),
|
|
597
|
+
filter.options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(SelectItem, { value: option.value, children: option.label }, option.label))
|
|
598
|
+
] })
|
|
599
|
+
]
|
|
600
|
+
}
|
|
601
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "relative", children: [
|
|
602
|
+
filter.icon && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }) }),
|
|
603
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
604
|
+
Input,
|
|
605
|
+
{
|
|
606
|
+
placeholder: filter.placeholder,
|
|
607
|
+
value: table.getColumn(filter.key)?.getFilterValue() ?? "",
|
|
608
|
+
onChange: (event) => table.getColumn(filter.key)?.setFilterValue(event.target.value),
|
|
609
|
+
className: cn("h-9 rounded-lg", filter.icon && "pl-9"),
|
|
610
|
+
type: filter.type === "number" ? "number" : filter.type === "date" ? "date" : "text"
|
|
611
|
+
}
|
|
612
|
+
)
|
|
613
|
+
] }) }, filter.key))
|
|
614
|
+
] }) }),
|
|
615
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
616
|
+
enableGlobalFilter && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "relative", children: [
|
|
617
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
618
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
619
|
+
Input,
|
|
620
|
+
{
|
|
621
|
+
placeholder: "Global search...",
|
|
622
|
+
value: globalFilter ?? "",
|
|
623
|
+
onChange: (event) => onGlobalFilterChange(event.target.value),
|
|
624
|
+
className: "pl-9 max-w-max"
|
|
625
|
+
}
|
|
626
|
+
)
|
|
627
|
+
] }),
|
|
628
|
+
onExport && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Button, { variant: "outline", size: "sm", onClick: () => onExport(data), className: "rounded-lg", children: [
|
|
629
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Download, { className: "mr-2 h-4 w-4" }),
|
|
630
|
+
"Export"
|
|
631
|
+
] }),
|
|
632
|
+
enableColumnVisibility && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenu, { children: [
|
|
633
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(Button, { variant: "outline", size: "sm", className: "rounded-lg gap-1", children: [
|
|
634
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { children: "Columns" }),
|
|
635
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.ChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
636
|
+
] }) }),
|
|
637
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenuContent, { align: "end", className: "w-[220px] rounded-lg max-h-[400px] overflow-y-auto", children: [
|
|
638
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuLabel, { className: "px-4 py-2 text-sm font-medium", children: "Toggle Columns" }),
|
|
639
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuSeparator, {}),
|
|
640
|
+
getUngroupedLeafColumns().length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenuGroup, { children: [
|
|
641
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuLabel, { className: "px-4 py-1.5 text-sm font-medium text-muted-foreground", children: "General" }),
|
|
642
|
+
getUngroupedLeafColumns().map((column) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
643
|
+
DropdownMenuCheckboxItem,
|
|
644
|
+
{
|
|
645
|
+
className: "text-sm",
|
|
646
|
+
checked: column.getIsVisible(),
|
|
647
|
+
onCheckedChange: (value) => column.toggleVisibility(!!value),
|
|
648
|
+
children: getColumnDisplayName(column.id)
|
|
649
|
+
},
|
|
650
|
+
column.id
|
|
651
|
+
))
|
|
652
|
+
] }),
|
|
653
|
+
getGroupColumns().map((group) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenuGroup, { children: [
|
|
654
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuSeparator, {}),
|
|
655
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuLabel, { className: "px-4 py-1.5 text-sm font-medium text-muted-foreground", children: group.id }),
|
|
656
|
+
group.columns?.filter((column) => column.getCanHide?.() !== false).map((column) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
657
|
+
DropdownMenuCheckboxItem,
|
|
658
|
+
{
|
|
659
|
+
className: "text-sm",
|
|
660
|
+
checked: column.getIsVisible(),
|
|
661
|
+
onCheckedChange: (value) => column.toggleVisibility(!!value),
|
|
662
|
+
children: getColumnDisplayName(column.id, group.id)
|
|
663
|
+
},
|
|
664
|
+
column.id
|
|
665
|
+
))
|
|
666
|
+
] }, group.id))
|
|
667
|
+
] })
|
|
668
|
+
] }),
|
|
669
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenu, { children: [
|
|
670
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { variant: "outline", size: "sm", className: "rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Settings2, { className: "h-4 w-4" }) }) }),
|
|
671
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenuContent, { align: "end", className: "w-[200px] rounded-lg", children: [
|
|
672
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuLabel, { children: "Table Settings" }),
|
|
673
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuSeparator, {}),
|
|
674
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenuItem, { onClick: onClearSorting, children: [
|
|
675
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.ArrowUpDown, { className: "mr-2 h-4 w-4" }),
|
|
676
|
+
"Clear All Sorting"
|
|
677
|
+
] }),
|
|
678
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(DropdownMenuItem, { onClick: onClearFilters, children: [
|
|
679
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Filter, { className: "mr-2 h-4 w-4" }),
|
|
680
|
+
"Clear All Filters"
|
|
681
|
+
] }),
|
|
682
|
+
enableColumnPinning && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
683
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuSeparator, {}),
|
|
684
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(DropdownMenuLabel, { children: "Column Pinning" }),
|
|
685
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
686
|
+
DropdownMenuItem,
|
|
687
|
+
{
|
|
688
|
+
onClick: () => table.setColumnPinning({ left: [], right: [] }),
|
|
689
|
+
children: [
|
|
690
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.PinOff, { className: "mr-2 h-4 w-4" }),
|
|
691
|
+
"Reset All Pinning"
|
|
692
|
+
]
|
|
693
|
+
}
|
|
694
|
+
),
|
|
695
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
696
|
+
DropdownMenuItem,
|
|
697
|
+
{
|
|
698
|
+
onClick: () => {
|
|
699
|
+
const leftColumns = getAllLeafColumns().filter((column) => column.getCanPin?.() !== false).map((column) => column.id);
|
|
700
|
+
table.setColumnPinning({ left: leftColumns, right: [] });
|
|
701
|
+
},
|
|
702
|
+
children: [
|
|
703
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Pin, { className: "mr-2 h-4 w-4 rotate-90" }),
|
|
704
|
+
"Pin All Left"
|
|
705
|
+
]
|
|
706
|
+
}
|
|
707
|
+
),
|
|
708
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
709
|
+
DropdownMenuItem,
|
|
710
|
+
{
|
|
711
|
+
onClick: () => {
|
|
712
|
+
const rightColumns = getAllLeafColumns().filter((column) => column.getCanPin?.() !== false).map((column) => column.id);
|
|
713
|
+
table.setColumnPinning({ left: [], right: rightColumns });
|
|
714
|
+
},
|
|
715
|
+
children: [
|
|
716
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.Pin, { className: "mr-2 h-4 w-4 -rotate-90" }),
|
|
717
|
+
"Pin All Right"
|
|
718
|
+
]
|
|
719
|
+
}
|
|
720
|
+
)
|
|
721
|
+
] })
|
|
722
|
+
] })
|
|
723
|
+
] }),
|
|
724
|
+
onRefresh && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(Button, { variant: "outline", size: "sm", onClick: onRefresh, disabled: loading, className: "rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react3.RefreshCw, { className: cn("h-4 w-4", loading && "animate-spin") }) })
|
|
725
|
+
] })
|
|
726
|
+
] }) }) }) });
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
// src/components/data/data-table/data-table-pagination.tsx
|
|
730
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
731
|
+
function DataTablePagination({ table, config }) {
|
|
732
|
+
if (!config.enabled) return null;
|
|
733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "rounded-xl", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
734
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center gap-6 text-sm text-muted-foreground", children: config.showInfo !== false && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("span", { children: [
|
|
735
|
+
"Showing ",
|
|
736
|
+
table.getState().pagination.pageIndex * table.getState().pagination.pageSize + 1,
|
|
737
|
+
" to",
|
|
738
|
+
" ",
|
|
739
|
+
Math.min(
|
|
740
|
+
(table.getState().pagination.pageIndex + 1) * table.getState().pagination.pageSize,
|
|
741
|
+
table.getFilteredRowModel().rows.length
|
|
742
|
+
),
|
|
743
|
+
" ",
|
|
744
|
+
"of ",
|
|
745
|
+
table.getFilteredRowModel().rows.length,
|
|
746
|
+
" entries"
|
|
747
|
+
] }) }),
|
|
748
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-4", children: [
|
|
749
|
+
config.pageSizeOptions && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
750
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)("span", { className: "text-sm font-medium", children: "Rows per page:" }),
|
|
751
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
752
|
+
Select,
|
|
753
|
+
{
|
|
754
|
+
value: `${table.getState().pagination.pageSize}`,
|
|
755
|
+
onValueChange: (value) => table.setPageSize(Number(value)),
|
|
756
|
+
children: [
|
|
757
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectTrigger, { className: "h-9 w-[70px] rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectValue, {}) }),
|
|
758
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectContent, { side: "top", className: "rounded-lg", children: config.pageSizeOptions.map((pageSize) => /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(SelectItem, { value: `${pageSize}`, children: pageSize }, pageSize)) })
|
|
759
|
+
]
|
|
760
|
+
}
|
|
761
|
+
)
|
|
762
|
+
] }),
|
|
763
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
764
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
765
|
+
Button,
|
|
766
|
+
{
|
|
767
|
+
variant: "outline",
|
|
768
|
+
size: "sm",
|
|
769
|
+
onClick: () => table.setPageIndex(0),
|
|
770
|
+
disabled: !table.getCanPreviousPage(),
|
|
771
|
+
className: "rounded-lg",
|
|
772
|
+
children: "First"
|
|
773
|
+
}
|
|
774
|
+
),
|
|
775
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
776
|
+
Button,
|
|
777
|
+
{
|
|
778
|
+
variant: "outline",
|
|
779
|
+
size: "sm",
|
|
780
|
+
onClick: () => table.previousPage(),
|
|
781
|
+
disabled: !table.getCanPreviousPage(),
|
|
782
|
+
className: "rounded-lg",
|
|
783
|
+
children: "Previous"
|
|
784
|
+
}
|
|
785
|
+
),
|
|
786
|
+
config.showPageNumbers && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "flex items-center gap-1", children: Array.from({ length: Math.min(5, table.getPageCount()) }, (_, i) => {
|
|
787
|
+
const pageIndex = table.getState().pagination.pageIndex;
|
|
788
|
+
const pageNumber = pageIndex - 2 + i + 1;
|
|
789
|
+
if (pageNumber < 1 || pageNumber > table.getPageCount()) return null;
|
|
790
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
791
|
+
Button,
|
|
792
|
+
{
|
|
793
|
+
variant: pageNumber === pageIndex + 1 ? "default" : "outline",
|
|
794
|
+
size: "sm",
|
|
795
|
+
className: "size-8 p-0 rounded-lg",
|
|
796
|
+
onClick: () => table.setPageIndex(pageNumber - 1),
|
|
797
|
+
children: pageNumber
|
|
798
|
+
},
|
|
799
|
+
pageNumber
|
|
800
|
+
);
|
|
801
|
+
}) }),
|
|
802
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
803
|
+
Button,
|
|
804
|
+
{
|
|
805
|
+
variant: "outline",
|
|
806
|
+
size: "sm",
|
|
807
|
+
onClick: () => table.nextPage(),
|
|
808
|
+
disabled: !table.getCanNextPage(),
|
|
809
|
+
className: "rounded-lg",
|
|
810
|
+
children: "Next"
|
|
811
|
+
}
|
|
812
|
+
),
|
|
813
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
814
|
+
Button,
|
|
815
|
+
{
|
|
816
|
+
variant: "outline",
|
|
817
|
+
size: "sm",
|
|
818
|
+
onClick: () => table.setPageIndex(table.getPageCount() - 1),
|
|
819
|
+
disabled: !table.getCanNextPage(),
|
|
820
|
+
className: "rounded-lg",
|
|
821
|
+
children: "Last"
|
|
822
|
+
}
|
|
823
|
+
)
|
|
824
|
+
] })
|
|
825
|
+
] })
|
|
826
|
+
] }) }) });
|
|
827
|
+
}
|
|
828
|
+
|
|
829
|
+
// src/components/ui/toggle.tsx
|
|
830
|
+
var import_radix_ui5 = require("radix-ui");
|
|
831
|
+
var import_class_variance_authority2 = require("class-variance-authority");
|
|
832
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
833
|
+
var toggleVariants = (0, import_class_variance_authority2.cva)(
|
|
834
|
+
"inline-flex cursor-pointer 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 [&_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",
|
|
835
|
+
{
|
|
836
|
+
variants: {
|
|
837
|
+
variant: {
|
|
838
|
+
default: "bg-transparent",
|
|
839
|
+
outline: "border border-input bg-transparent shadow-xs hover:bg-accent hover:text-accent-foreground"
|
|
840
|
+
},
|
|
841
|
+
size: {
|
|
842
|
+
sm: "h-7 px-0 min-w-7",
|
|
843
|
+
default: "h-8 px-1 min-w-8",
|
|
844
|
+
lg: "h-9 px-2 min-w-10"
|
|
845
|
+
},
|
|
846
|
+
bg: {
|
|
847
|
+
enabled: "data-[state=on]:bg-accent data-[state=on]:text-accent-foreground",
|
|
848
|
+
disabled: ""
|
|
849
|
+
}
|
|
850
|
+
},
|
|
851
|
+
defaultVariants: {
|
|
852
|
+
variant: "default",
|
|
853
|
+
size: "default",
|
|
854
|
+
bg: "enabled"
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
);
|
|
858
|
+
function Toggle({
|
|
859
|
+
className,
|
|
860
|
+
variant,
|
|
861
|
+
size,
|
|
862
|
+
noBg,
|
|
863
|
+
...props
|
|
864
|
+
}) {
|
|
865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
866
|
+
import_radix_ui5.Toggle.Root,
|
|
867
|
+
{
|
|
868
|
+
"data-slot": "toggle",
|
|
869
|
+
className: cn(toggleVariants({ className, variant, size, bg: noBg ? "disabled" : "enabled" })),
|
|
870
|
+
...props
|
|
871
|
+
}
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
|
|
875
|
+
// src/components/ui/checkbox.tsx
|
|
876
|
+
var import_radix_ui6 = require("radix-ui");
|
|
877
|
+
var import_lucide_react4 = require("lucide-react");
|
|
878
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
879
|
+
function Checkbox({
|
|
880
|
+
className,
|
|
881
|
+
...props
|
|
882
|
+
}) {
|
|
883
|
+
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
884
|
+
import_radix_ui6.Checkbox.Root,
|
|
885
|
+
{
|
|
886
|
+
"data-slot": "checkbox",
|
|
887
|
+
className: cn(
|
|
888
|
+
"peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50",
|
|
889
|
+
className
|
|
890
|
+
),
|
|
891
|
+
...props,
|
|
892
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
893
|
+
import_radix_ui6.Checkbox.Indicator,
|
|
894
|
+
{
|
|
895
|
+
"data-slot": "checkbox-indicator",
|
|
896
|
+
className: "flex items-center justify-center text-current transition-none",
|
|
897
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(import_lucide_react4.CheckIcon, { className: "size-3.5" })
|
|
898
|
+
}
|
|
899
|
+
)
|
|
900
|
+
}
|
|
901
|
+
);
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// src/components/data/data-table/data-table.tsx
|
|
905
|
+
var import_react = require("react");
|
|
906
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
907
|
+
function DataTable({
|
|
908
|
+
data,
|
|
909
|
+
columns: initialColumns,
|
|
910
|
+
filters = [],
|
|
911
|
+
pagination = { enabled: false },
|
|
912
|
+
settings = {},
|
|
913
|
+
header,
|
|
914
|
+
footer,
|
|
915
|
+
className = "",
|
|
916
|
+
maxHeight = "600px",
|
|
917
|
+
loading = false,
|
|
918
|
+
error,
|
|
919
|
+
emptyMessage = "No data available",
|
|
920
|
+
onRowSelectionChange,
|
|
921
|
+
onExport,
|
|
922
|
+
onRefresh,
|
|
923
|
+
onTableReady,
|
|
924
|
+
children
|
|
925
|
+
}) {
|
|
926
|
+
const [sorting, setSorting] = (0, import_react.useState)([]);
|
|
927
|
+
const [columnFilters, setColumnFilters] = (0, import_react.useState)([]);
|
|
928
|
+
const [columnVisibility, setColumnVisibility] = (0, import_react.useState)({});
|
|
929
|
+
const [rowSelection, setRowSelection] = (0, import_react.useState)({});
|
|
930
|
+
const [globalFilter, setGlobalFilter] = (0, import_react.useState)("");
|
|
931
|
+
const [columnOrder, setColumnOrder] = (0, import_react.useState)([]);
|
|
932
|
+
const [columnPinning, setColumnPinning] = (0, import_react.useState)(
|
|
933
|
+
settings.enableColumnPinning ? { left: [], right: [] } : {}
|
|
934
|
+
);
|
|
935
|
+
const {
|
|
936
|
+
enableSorting = true,
|
|
937
|
+
enableFiltering = true,
|
|
938
|
+
enableGlobalFilter = true,
|
|
939
|
+
enableColumnVisibility = true,
|
|
940
|
+
enableRowSelection = true,
|
|
941
|
+
stickyHeader = true,
|
|
942
|
+
toolbar = false,
|
|
943
|
+
showSerialNumbers = true,
|
|
944
|
+
fixedCheckboxColumn = true,
|
|
945
|
+
striped = true,
|
|
946
|
+
hoverable = true,
|
|
947
|
+
compact = true,
|
|
948
|
+
bordered = true,
|
|
949
|
+
fullHeight = false,
|
|
950
|
+
enableColumnResizing = false,
|
|
951
|
+
enableColumnPinning = true,
|
|
952
|
+
hideHeader = false
|
|
953
|
+
} = settings;
|
|
954
|
+
const columns = (0, import_react.useMemo)(() => {
|
|
955
|
+
const cols = [...initialColumns];
|
|
956
|
+
const processColumns = (columns2) => {
|
|
957
|
+
return columns2.map((col) => {
|
|
958
|
+
if (col.id === "select" || col.id === "serialNumber") {
|
|
959
|
+
return col;
|
|
960
|
+
}
|
|
961
|
+
const newCol = {
|
|
962
|
+
...col,
|
|
963
|
+
enablePinning: true
|
|
964
|
+
};
|
|
965
|
+
if (col.columns) {
|
|
966
|
+
newCol.columns = processColumns(col.columns);
|
|
967
|
+
}
|
|
968
|
+
return newCol;
|
|
969
|
+
});
|
|
970
|
+
};
|
|
971
|
+
const processedCols = processColumns(cols);
|
|
972
|
+
if (enableRowSelection) {
|
|
973
|
+
const selectColumn = {
|
|
974
|
+
id: "select",
|
|
975
|
+
header: ({ table: table2 }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
976
|
+
Checkbox,
|
|
977
|
+
{
|
|
978
|
+
checked: table2.getIsAllPageRowsSelected() || table2.getIsSomePageRowsSelected() && "indeterminate",
|
|
979
|
+
onCheckedChange: (value) => table2.toggleAllPageRowsSelected(!!value),
|
|
980
|
+
"aria-label": "Select all"
|
|
981
|
+
}
|
|
982
|
+
),
|
|
983
|
+
cell: ({ row }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: cn("flex items-center justify-center"), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
984
|
+
Checkbox,
|
|
985
|
+
{
|
|
986
|
+
checked: row.getIsSelected(),
|
|
987
|
+
onCheckedChange: (value) => row.toggleSelected(!!value),
|
|
988
|
+
"aria-label": "Select row"
|
|
989
|
+
}
|
|
990
|
+
) }),
|
|
991
|
+
enableSorting: false,
|
|
992
|
+
enableHiding: false,
|
|
993
|
+
enablePinning: true,
|
|
994
|
+
headerAlign: "center",
|
|
995
|
+
size: 10
|
|
996
|
+
};
|
|
997
|
+
processedCols.unshift(selectColumn);
|
|
998
|
+
}
|
|
999
|
+
if (showSerialNumbers) {
|
|
1000
|
+
const serialColumn = {
|
|
1001
|
+
id: "serialNumber",
|
|
1002
|
+
header: "No.",
|
|
1003
|
+
cell: ({ row }) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-center font-medium text-muted-foreground", children: row.index + 1 }),
|
|
1004
|
+
enableSorting: true,
|
|
1005
|
+
enableHiding: false,
|
|
1006
|
+
enablePinning: true,
|
|
1007
|
+
size: 60,
|
|
1008
|
+
headerAlign: "center"
|
|
1009
|
+
};
|
|
1010
|
+
processedCols.unshift(serialColumn);
|
|
1011
|
+
}
|
|
1012
|
+
return processedCols;
|
|
1013
|
+
}, [initialColumns, showSerialNumbers, enableRowSelection, fixedCheckboxColumn]);
|
|
1014
|
+
const table = (0, import_react_table.useReactTable)({
|
|
1015
|
+
data,
|
|
1016
|
+
columns,
|
|
1017
|
+
onSortingChange: enableSorting ? setSorting : void 0,
|
|
1018
|
+
onColumnFiltersChange: enableFiltering ? setColumnFilters : void 0,
|
|
1019
|
+
onGlobalFilterChange: enableGlobalFilter ? setGlobalFilter : void 0,
|
|
1020
|
+
getCoreRowModel: (0, import_react_table.getCoreRowModel)(),
|
|
1021
|
+
getPaginationRowModel: pagination.enabled ? (0, import_react_table.getPaginationRowModel)() : void 0,
|
|
1022
|
+
getSortedRowModel: enableSorting ? (0, import_react_table.getSortedRowModel)() : void 0,
|
|
1023
|
+
getFilteredRowModel: enableFiltering ? (0, import_react_table.getFilteredRowModel)() : void 0,
|
|
1024
|
+
onColumnVisibilityChange: enableColumnVisibility ? setColumnVisibility : void 0,
|
|
1025
|
+
onRowSelectionChange: enableRowSelection ? setRowSelection : void 0,
|
|
1026
|
+
onColumnOrderChange: setColumnOrder,
|
|
1027
|
+
onColumnPinningChange: enableColumnPinning ? setColumnPinning : void 0,
|
|
1028
|
+
state: {
|
|
1029
|
+
sorting: enableSorting ? sorting : void 0,
|
|
1030
|
+
columnFilters: enableFiltering ? columnFilters : void 0,
|
|
1031
|
+
columnVisibility: enableColumnVisibility ? columnVisibility : void 0,
|
|
1032
|
+
rowSelection: enableRowSelection ? rowSelection : {},
|
|
1033
|
+
globalFilter,
|
|
1034
|
+
columnOrder,
|
|
1035
|
+
columnPinning: enableColumnPinning ? columnPinning : {}
|
|
1036
|
+
},
|
|
1037
|
+
initialState: {
|
|
1038
|
+
pagination: pagination.enabled ? { pageSize: pagination.pageSize || 10 } : void 0,
|
|
1039
|
+
columnPinning: enableColumnPinning ? {
|
|
1040
|
+
left: [
|
|
1041
|
+
...showSerialNumbers ? ["serialNumber"] : [],
|
|
1042
|
+
...enableRowSelection ? ["select"] : []
|
|
1043
|
+
],
|
|
1044
|
+
right: []
|
|
1045
|
+
} : void 0
|
|
1046
|
+
},
|
|
1047
|
+
enableRowSelection,
|
|
1048
|
+
enableColumnResizing,
|
|
1049
|
+
enableColumnPinning,
|
|
1050
|
+
columnResizeMode: "onChange"
|
|
1051
|
+
});
|
|
1052
|
+
(0, import_react.useEffect)(() => {
|
|
1053
|
+
if (onTableReady) {
|
|
1054
|
+
onTableReady(table);
|
|
1055
|
+
}
|
|
1056
|
+
}, [table, onTableReady]);
|
|
1057
|
+
(0, import_react.useEffect)(() => {
|
|
1058
|
+
if (enableRowSelection && onRowSelectionChange) {
|
|
1059
|
+
const selectedRows = table.getFilteredSelectedRowModel().rows.map((row) => row.original);
|
|
1060
|
+
onRowSelectionChange(selectedRows);
|
|
1061
|
+
}
|
|
1062
|
+
}, [rowSelection, enableRowSelection, onRowSelectionChange, table]);
|
|
1063
|
+
const handleClearSorting = (0, import_react.useCallback)(() => {
|
|
1064
|
+
setSorting([]);
|
|
1065
|
+
}, []);
|
|
1066
|
+
const handleClearFilters = (0, import_react.useCallback)(() => {
|
|
1067
|
+
setColumnFilters([]);
|
|
1068
|
+
setGlobalFilter("");
|
|
1069
|
+
}, []);
|
|
1070
|
+
const handlePinColumn = (columnId, side) => {
|
|
1071
|
+
if (!enableColumnPinning) return;
|
|
1072
|
+
const alwaysPinnedLeft = [
|
|
1073
|
+
...showSerialNumbers ? ["serialNumber"] : [],
|
|
1074
|
+
...enableRowSelection && fixedCheckboxColumn ? ["select"] : []
|
|
1075
|
+
];
|
|
1076
|
+
const newPinning = {
|
|
1077
|
+
left: [...(columnPinning.left ?? []).filter((id) => alwaysPinnedLeft.includes(id))],
|
|
1078
|
+
right: [...columnPinning.right ?? []]
|
|
1079
|
+
};
|
|
1080
|
+
if (side === false) {
|
|
1081
|
+
newPinning.left = newPinning.left.filter((id) => id !== columnId);
|
|
1082
|
+
newPinning.right = newPinning.right.filter((id) => id !== columnId);
|
|
1083
|
+
} else if (side === "right") {
|
|
1084
|
+
newPinning.left = newPinning.left.filter((id) => id !== columnId);
|
|
1085
|
+
if (!newPinning.right.includes(columnId)) {
|
|
1086
|
+
newPinning.right.push(columnId);
|
|
1087
|
+
}
|
|
1088
|
+
} else if (side === "left") {
|
|
1089
|
+
newPinning.right = newPinning.right.filter((id) => id !== columnId);
|
|
1090
|
+
if (!newPinning.left.includes(columnId) && !alwaysPinnedLeft.includes(columnId)) {
|
|
1091
|
+
newPinning.left.push(columnId);
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
table.setColumnPinning(newPinning);
|
|
1095
|
+
};
|
|
1096
|
+
const renderTableHeader = () => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableHeader, { className: cn(
|
|
1097
|
+
stickyHeader && "sticky top-0 bg-sidebar z-20"
|
|
1098
|
+
), children: table.getHeaderGroups().map((headerGroup, groupIndex) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableRow, { className: "hover:bg-transparent", children: headerGroup.headers.map((header2, index) => {
|
|
1099
|
+
const isGroupHeader = header2.depth === 0 && header2.colSpan > 1;
|
|
1100
|
+
const isPinnedLeft = enableColumnPinning && (header2.column.getIsPinned() === "left" || header2.column.id === "serialNumber" || header2.column.id === "select" && enableRowSelection);
|
|
1101
|
+
const isPinnedRight = enableColumnPinning && header2.column.getIsPinned() === "right";
|
|
1102
|
+
const canSort = header2.column.getCanSort();
|
|
1103
|
+
const canPin = enableColumnPinning && header2.column.columnDef.enablePinning !== false;
|
|
1104
|
+
const isSerialNumber = header2.column.id === "serialNumber";
|
|
1105
|
+
const isCheckbox = header2.column.id === "select";
|
|
1106
|
+
const alwaysPinned = isSerialNumber || isCheckbox && fixedCheckboxColumn;
|
|
1107
|
+
const headerAlign = header2.column.columnDef.headerAlign || "left";
|
|
1108
|
+
const flexJustify = {
|
|
1109
|
+
left: "justify-start",
|
|
1110
|
+
center: "justify-center",
|
|
1111
|
+
right: "justify-end"
|
|
1112
|
+
}[headerAlign];
|
|
1113
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1114
|
+
TableHead,
|
|
1115
|
+
{
|
|
1116
|
+
colSpan: header2.colSpan,
|
|
1117
|
+
className: cn(
|
|
1118
|
+
"font-semibold text-foreground bg-sidebar group px-0",
|
|
1119
|
+
!compact && "py-2",
|
|
1120
|
+
bordered && index < headerGroup.headers.length - 1 && "border-r",
|
|
1121
|
+
"relative",
|
|
1122
|
+
isPinnedLeft && "sticky left-0 z-15 bg-sidebar",
|
|
1123
|
+
isPinnedRight && "sticky right-0 z-15 bg-sidebar",
|
|
1124
|
+
(isSerialNumber || isCheckbox) && "sticky left-0 z-15 bg-sidebar",
|
|
1125
|
+
isGroupHeader ? "text-center" : "text-left"
|
|
1126
|
+
),
|
|
1127
|
+
style: {
|
|
1128
|
+
width: header2.getSize() !== 150 ? header2.getSize() : "auto",
|
|
1129
|
+
minWidth: header2.getSize() !== 150 ? header2.getSize() : "auto",
|
|
1130
|
+
...isPinnedLeft && {
|
|
1131
|
+
left: isSerialNumber ? 0 : isCheckbox ? showSerialNumbers ? table.getColumn("serialNumber")?.getSize() || 0 : 0 : getLeftOffset(header2.column)
|
|
1132
|
+
},
|
|
1133
|
+
...isPinnedRight && { right: getRightOffset(header2.column) },
|
|
1134
|
+
...isSerialNumber && { left: 0 }
|
|
1135
|
+
},
|
|
1136
|
+
children: [
|
|
1137
|
+
isGroupHeader ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "flex items-center justify-center", children: (0, import_react_table.flexRender)(header2.column.columnDef.header, header2.getContext()) }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("relative flex items-center w-full px-2", flexJustify), children: [
|
|
1138
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
1139
|
+
canSort && headerAlign === "right" && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ml-1 order-2", children: header2.column.getIsSorted() && {
|
|
1140
|
+
asc: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.ChevronUp, { className: "h-4 w-4" }),
|
|
1141
|
+
desc: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.ChevronDown, { className: "h-4 w-4" })
|
|
1142
|
+
}[header2.column.getIsSorted()] }),
|
|
1143
|
+
header2.isPlaceholder ? null : (0, import_react_table.flexRender)(header2.column.columnDef.header, header2.getContext()),
|
|
1144
|
+
canSort && headerAlign !== "right" && header2.column.getIsSorted() && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ml-1 order-2", children: header2.column.getIsSorted() && {
|
|
1145
|
+
asc: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.ChevronUp, { className: "h-4 w-4" }),
|
|
1146
|
+
desc: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.ChevronDown, { className: "h-4 w-4" })
|
|
1147
|
+
}[header2.column.getIsSorted()] })
|
|
1148
|
+
] }),
|
|
1149
|
+
(canSort || canPin && !alwaysPinned) && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(DropdownMenu, { children: [
|
|
1150
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DropdownMenuTrigger, { asChild: true, className: cn(
|
|
1151
|
+
"absolute",
|
|
1152
|
+
headerAlign === "left" && "right-1",
|
|
1153
|
+
headerAlign === "center" && "right-1",
|
|
1154
|
+
headerAlign === "right" && "left-1"
|
|
1155
|
+
), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1156
|
+
Toggle,
|
|
1157
|
+
{
|
|
1158
|
+
variant: "default",
|
|
1159
|
+
size: "sm",
|
|
1160
|
+
noBg: true,
|
|
1161
|
+
tabIndex: -1,
|
|
1162
|
+
className: "opacity-0 group-hover:opacity-70 hover:opacity-100 data-[state=open]:opacity-100",
|
|
1163
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.MoreHorizontal, { className: "h-4 w-4" })
|
|
1164
|
+
}
|
|
1165
|
+
) }),
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(DropdownMenuContent, { align: "end", className: "w-48", children: [
|
|
1167
|
+
canSort && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1168
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DropdownMenuLabel, { children: "Sorting" }),
|
|
1169
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1170
|
+
DropdownMenuItem,
|
|
1171
|
+
{
|
|
1172
|
+
onClick: () => header2.column.toggleSorting(false),
|
|
1173
|
+
children: [
|
|
1174
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.ChevronUp, { className: "mr-2 h-4 w-4" }),
|
|
1175
|
+
"Sort Ascending"
|
|
1176
|
+
]
|
|
1177
|
+
}
|
|
1178
|
+
),
|
|
1179
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1180
|
+
DropdownMenuItem,
|
|
1181
|
+
{
|
|
1182
|
+
onClick: () => header2.column.toggleSorting(true),
|
|
1183
|
+
children: [
|
|
1184
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.ChevronDown, { className: "mr-2 h-4 w-4" }),
|
|
1185
|
+
"Sort Descending"
|
|
1186
|
+
]
|
|
1187
|
+
}
|
|
1188
|
+
),
|
|
1189
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1190
|
+
DropdownMenuItem,
|
|
1191
|
+
{
|
|
1192
|
+
onClick: () => header2.column.clearSorting(),
|
|
1193
|
+
disabled: !header2.column.getIsSorted(),
|
|
1194
|
+
children: [
|
|
1195
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.ChevronsUpDown, { className: "mr-2 h-4 w-4" }),
|
|
1196
|
+
"Clear Sort"
|
|
1197
|
+
]
|
|
1198
|
+
}
|
|
1199
|
+
),
|
|
1200
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DropdownMenuSeparator, {})
|
|
1201
|
+
] }),
|
|
1202
|
+
canPin && !alwaysPinned && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
1203
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DropdownMenuLabel, { children: "Pin Column" }),
|
|
1204
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1205
|
+
DropdownMenuItem,
|
|
1206
|
+
{
|
|
1207
|
+
onClick: () => handlePinColumn(header2.column.id, "right"),
|
|
1208
|
+
disabled: header2.column.getIsPinned() === "right",
|
|
1209
|
+
children: [
|
|
1210
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.MoveRightIcon, {}),
|
|
1211
|
+
"Pin Right"
|
|
1212
|
+
]
|
|
1213
|
+
}
|
|
1214
|
+
),
|
|
1215
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
|
|
1216
|
+
DropdownMenuItem,
|
|
1217
|
+
{
|
|
1218
|
+
onClick: () => handlePinColumn(header2.column.id, false),
|
|
1219
|
+
disabled: !header2.column.getIsPinned(),
|
|
1220
|
+
children: [
|
|
1221
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.PinOffIcon, {}),
|
|
1222
|
+
"Unpin"
|
|
1223
|
+
]
|
|
1224
|
+
}
|
|
1225
|
+
)
|
|
1226
|
+
] })
|
|
1227
|
+
] })
|
|
1228
|
+
] })
|
|
1229
|
+
] }),
|
|
1230
|
+
enableColumnResizing && header2.column.getCanResize() && !isGroupHeader && header2.colSpan === 1 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1231
|
+
"div",
|
|
1232
|
+
{
|
|
1233
|
+
className: "absolute right-0 top-0 h-full w-1 bg-border hover:bg-primary cursor-col-resize opacity-0 hover:opacity-100 transition-opacity",
|
|
1234
|
+
onMouseDown: header2.getResizeHandler()
|
|
1235
|
+
}
|
|
1236
|
+
)
|
|
1237
|
+
]
|
|
1238
|
+
},
|
|
1239
|
+
header2.id
|
|
1240
|
+
);
|
|
1241
|
+
}) }, headerGroup.id)) });
|
|
1242
|
+
const getLeftOffset = (column) => {
|
|
1243
|
+
if (!enableColumnPinning) return void 0;
|
|
1244
|
+
let offset = 0;
|
|
1245
|
+
const pinnedLeftColumns = table.getLeftHeaderGroups()[0]?.headers || [];
|
|
1246
|
+
const alwaysPinnedColumns = [
|
|
1247
|
+
...showSerialNumbers ? ["serialNumber"] : [],
|
|
1248
|
+
...enableRowSelection ? ["select"] : []
|
|
1249
|
+
];
|
|
1250
|
+
for (const col of pinnedLeftColumns) {
|
|
1251
|
+
if (col.id === column.id) break;
|
|
1252
|
+
if (alwaysPinnedColumns.includes(col.id)) {
|
|
1253
|
+
const column2 = table.getColumn(col.id);
|
|
1254
|
+
if (column2) {
|
|
1255
|
+
offset += column2.getSize();
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
}
|
|
1259
|
+
return offset;
|
|
1260
|
+
};
|
|
1261
|
+
const getRightOffset = (column) => {
|
|
1262
|
+
if (!enableColumnPinning) return void 0;
|
|
1263
|
+
const pinnedRightIds = table.getState().columnPinning.right || [];
|
|
1264
|
+
const columnIndex = pinnedRightIds.indexOf(column.id);
|
|
1265
|
+
if (columnIndex === -1) return void 0;
|
|
1266
|
+
let offset = 0;
|
|
1267
|
+
for (let i = columnIndex + 1; i < pinnedRightIds.length; i++) {
|
|
1268
|
+
const col = table.getColumn(pinnedRightIds[i]);
|
|
1269
|
+
if (col) {
|
|
1270
|
+
offset += col.getSize();
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
return offset;
|
|
1274
|
+
};
|
|
1275
|
+
if (error) {
|
|
1276
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Card, { className: "w-full rounded-xl shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardContent, { className: "flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "text-center", children: [
|
|
1277
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-red-500 mb-3 text-2xl", children: "\u26A0\uFE0F" }),
|
|
1278
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: error }),
|
|
1279
|
+
onRefresh && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Button, { variant: "outline", size: "sm", onClick: onRefresh, className: "rounded-lg", children: [
|
|
1280
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Loader2, { className: "mr-2 h-4 w-4" }),
|
|
1281
|
+
"Try Again"
|
|
1282
|
+
] })
|
|
1283
|
+
] }) }) });
|
|
1284
|
+
}
|
|
1285
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: cn("w-full space-y-2 flex flex-col h-full", className), children: [
|
|
1286
|
+
header && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Card, { className: "rounded-2xl py-2 sticky top-0 z-20", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardContent, { className: "px-2", children: header }) }),
|
|
1287
|
+
toolbar && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1288
|
+
DataTableToolbar,
|
|
1289
|
+
{
|
|
1290
|
+
table,
|
|
1291
|
+
filters,
|
|
1292
|
+
globalFilter,
|
|
1293
|
+
onGlobalFilterChange: setGlobalFilter,
|
|
1294
|
+
enableGlobalFilter,
|
|
1295
|
+
onExport,
|
|
1296
|
+
onRefresh,
|
|
1297
|
+
loading,
|
|
1298
|
+
enableColumnVisibility,
|
|
1299
|
+
enableColumnPinning,
|
|
1300
|
+
data,
|
|
1301
|
+
onClearSorting: handleClearSorting,
|
|
1302
|
+
onClearFilters: handleClearFilters
|
|
1303
|
+
}
|
|
1304
|
+
),
|
|
1305
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Card, { className: cn("shadow-sm overflow-auto py-0", fullHeight && "flex-1"), children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(CardContent, { className: "p-0 h-full", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "relative flex flex-col h-full justify-between", children: [
|
|
1306
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "absolute inset-0 bg-background/80 backdrop-blur-sm z-50 flex items-center justify-center rounded-xl", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-3 bg-background/90 px-4 py-3 rounded-lg shadow-sm", children: [
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react5.Loader2, { className: "size-5 animate-spin text-primary" }),
|
|
1308
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "text-sm font-medium text-muted-foreground", children: "Loading..." })
|
|
1309
|
+
] }) }),
|
|
1310
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "relative rounded-t-xl overflow-auto border-b", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(Table, { className: "border-collapse w-full", children: [
|
|
1311
|
+
!hideHeader && renderTableHeader(),
|
|
1312
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableBody, { children: table.getRowModel().rows?.length ? table.getRowModel().rows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1313
|
+
TableRow,
|
|
1314
|
+
{
|
|
1315
|
+
"data-state": row.getIsSelected() && "selected",
|
|
1316
|
+
className: cn(
|
|
1317
|
+
hoverable && "hover:bg-muted/50",
|
|
1318
|
+
striped && rowIndex % 2 === 0 && "bg-muted/20",
|
|
1319
|
+
row.getIsSelected() && "bg-muted",
|
|
1320
|
+
"border-b last:border-b-0"
|
|
1321
|
+
),
|
|
1322
|
+
children: row.getVisibleCells().map((cell, cellIndex) => {
|
|
1323
|
+
const isPinnedLeft = enableColumnPinning && (cell.column.getIsPinned() === "left" || cell.column.id === "serialNumber" || cell.column.id === "select" && enableRowSelection);
|
|
1324
|
+
const isPinnedRight = enableColumnPinning && cell.column.getIsPinned() === "right";
|
|
1325
|
+
const isSerialNumber = cell.column.id === "serialNumber";
|
|
1326
|
+
const isCheckbox = cell.column.id === "select";
|
|
1327
|
+
const alwaysPinned = isSerialNumber || isCheckbox && fixedCheckboxColumn;
|
|
1328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
1329
|
+
TableCell,
|
|
1330
|
+
{
|
|
1331
|
+
className: cn(
|
|
1332
|
+
compact ? "py-2" : "py-4",
|
|
1333
|
+
bordered && cellIndex < row.getVisibleCells().length && "border-r",
|
|
1334
|
+
isPinnedLeft && "sticky left-0 z-10 bg-sidebar/97",
|
|
1335
|
+
isPinnedRight && "sticky right-0 z-10 bg-sidebar/97",
|
|
1336
|
+
isSerialNumber && "sticky left-0 z-10 bg-sidebar/97",
|
|
1337
|
+
"p-1"
|
|
1338
|
+
),
|
|
1339
|
+
style: {
|
|
1340
|
+
width: cell.column.getSize() !== 150 ? cell.column.getSize() : "auto",
|
|
1341
|
+
minWidth: cell.column.getSize() !== 150 ? cell.column.getSize() : "auto",
|
|
1342
|
+
...isPinnedLeft && {
|
|
1343
|
+
left: isSerialNumber ? 0 : isCheckbox ? showSerialNumbers ? table.getColumn("serialNumber")?.getSize() || 0 : 0 : getLeftOffset(cell.column)
|
|
1344
|
+
},
|
|
1345
|
+
...isPinnedRight && { right: getRightOffset(cell.column) },
|
|
1346
|
+
...isSerialNumber && { left: 0 }
|
|
1347
|
+
},
|
|
1348
|
+
children: (0, import_react_table.flexRender)(cell.column.columnDef.cell, cell.getContext())
|
|
1349
|
+
},
|
|
1350
|
+
cell.id
|
|
1351
|
+
);
|
|
1352
|
+
})
|
|
1353
|
+
},
|
|
1354
|
+
row.id
|
|
1355
|
+
)) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableCell, { colSpan: columns.length, className: "h-32 text-center border-0", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex flex-col items-center gap-3", children: [
|
|
1356
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "text-muted-foreground text-5xl", children: "\u{1F4CB}" }),
|
|
1357
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("p", { className: "text-muted-foreground font-medium", children: emptyMessage })
|
|
1358
|
+
] }) }) }) })
|
|
1359
|
+
] }) }),
|
|
1360
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "sticky bottom-0 bg-sidebar w-full z-20", style: {
|
|
1361
|
+
width: "100%",
|
|
1362
|
+
minWidth: "fit-content"
|
|
1363
|
+
}, children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(Table, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableFooter, { children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableRow, { className: "bg-sidebar", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(TableCell, { colSpan: columns.length, className: "p-2", children: footer }) }) }) }) })
|
|
1364
|
+
] }) }) }),
|
|
1365
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(DataTablePagination, { table, config: pagination }),
|
|
1366
|
+
children && children(table)
|
|
1367
|
+
] }) });
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
// src/components/ui/separator.tsx
|
|
1371
|
+
var import_radix_ui7 = require("radix-ui");
|
|
1372
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
1373
|
+
function Separator({
|
|
1374
|
+
className,
|
|
1375
|
+
orientation = "horizontal",
|
|
1376
|
+
decorative = true,
|
|
1377
|
+
...props
|
|
1378
|
+
}) {
|
|
1379
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
1380
|
+
import_radix_ui7.Separator.Root,
|
|
1381
|
+
{
|
|
1382
|
+
"data-slot": "separator-root",
|
|
1383
|
+
decorative,
|
|
1384
|
+
orientation,
|
|
1385
|
+
className: cn(
|
|
1386
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
1387
|
+
className
|
|
1388
|
+
),
|
|
1389
|
+
...props
|
|
1390
|
+
}
|
|
1391
|
+
);
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
// src/components/data/data-table/data-table-action-bar.tsx
|
|
1395
|
+
var import_lucide_react6 = require("lucide-react");
|
|
1396
|
+
var import_framer_motion = require("framer-motion");
|
|
1397
|
+
var React = __toESM(require("react"), 1);
|
|
1398
|
+
var ReactDOM = __toESM(require("react-dom"), 1);
|
|
1399
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
1400
|
+
function DataTableActionBar({
|
|
1401
|
+
table,
|
|
1402
|
+
visible: visibleProp,
|
|
1403
|
+
container: containerProp,
|
|
1404
|
+
children,
|
|
1405
|
+
className,
|
|
1406
|
+
...props
|
|
1407
|
+
}) {
|
|
1408
|
+
const [mounted, setMounted] = React.useState(false);
|
|
1409
|
+
React.useLayoutEffect(() => {
|
|
1410
|
+
setMounted(true);
|
|
1411
|
+
}, []);
|
|
1412
|
+
React.useEffect(() => {
|
|
1413
|
+
function onKeyDown(event) {
|
|
1414
|
+
if (event.key === "Escape" && table) {
|
|
1415
|
+
table.toggleAllRowsSelected(false);
|
|
1416
|
+
}
|
|
1417
|
+
}
|
|
1418
|
+
window.addEventListener("keydown", onKeyDown);
|
|
1419
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
1420
|
+
}, [table]);
|
|
1421
|
+
const container = containerProp ?? (mounted ? globalThis.document?.body : null);
|
|
1422
|
+
if (!container || !table) return null;
|
|
1423
|
+
const visible = visibleProp ?? table.getFilteredSelectedRowModel().rows.length > 0;
|
|
1424
|
+
return ReactDOM.createPortal(
|
|
1425
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_framer_motion.AnimatePresence, { children: visible && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1426
|
+
import_framer_motion.motion.div,
|
|
1427
|
+
{
|
|
1428
|
+
role: "toolbar",
|
|
1429
|
+
"aria-orientation": "horizontal",
|
|
1430
|
+
initial: { opacity: 0, y: 20 },
|
|
1431
|
+
animate: { opacity: 1, y: 0 },
|
|
1432
|
+
exit: { opacity: 0, y: 20 },
|
|
1433
|
+
transition: { duration: 0.3, ease: "easeInOut" },
|
|
1434
|
+
className: cn(
|
|
1435
|
+
"fixed inset-x-0 bottom-6 z-50 mx-auto flex w-fit flex-wrap items-center justify-center gap-2 rounded-xl border bg-primary/10 backdrop-blur-sm p-3 text-foreground ring-5 ring-primary/5",
|
|
1436
|
+
className
|
|
1437
|
+
),
|
|
1438
|
+
...props,
|
|
1439
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(TooltipProvider, { children: [
|
|
1440
|
+
"1",
|
|
1441
|
+
children
|
|
1442
|
+
] })
|
|
1443
|
+
}
|
|
1444
|
+
) }),
|
|
1445
|
+
container
|
|
1446
|
+
);
|
|
1447
|
+
}
|
|
1448
|
+
function DataTableActionBarAction({
|
|
1449
|
+
size = "sm",
|
|
1450
|
+
tooltip,
|
|
1451
|
+
isPending,
|
|
1452
|
+
disabled,
|
|
1453
|
+
className,
|
|
1454
|
+
children,
|
|
1455
|
+
...props
|
|
1456
|
+
}) {
|
|
1457
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1458
|
+
Button,
|
|
1459
|
+
{
|
|
1460
|
+
variant: "secondary",
|
|
1461
|
+
size,
|
|
1462
|
+
className: cn(
|
|
1463
|
+
"gap-1.5 rounded-lg border border-secondary bg-secondary/50 hover:bg-secondary/70 transition-all duration-200",
|
|
1464
|
+
size === "icon" ? "size-8" : "h-8 px-3",
|
|
1465
|
+
className
|
|
1466
|
+
),
|
|
1467
|
+
disabled: disabled || isPending,
|
|
1468
|
+
...props,
|
|
1469
|
+
children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.Loader, { className: "animate-spin" }) : children
|
|
1470
|
+
}
|
|
1471
|
+
);
|
|
1472
|
+
if (!tooltip) return trigger;
|
|
1473
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Tooltip, { children: [
|
|
1474
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TooltipTrigger, { asChild: true, children: trigger }),
|
|
1475
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
1476
|
+
TooltipContent,
|
|
1477
|
+
{
|
|
1478
|
+
sideOffset: 8,
|
|
1479
|
+
className: "rounded-lg border font-semibold text-foreground bg-secondary [&>span]:hidden",
|
|
1480
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: tooltip })
|
|
1481
|
+
}
|
|
1482
|
+
)
|
|
1483
|
+
] });
|
|
1484
|
+
}
|
|
1485
|
+
function DataTableActionBarSelection({ table }) {
|
|
1486
|
+
const onClearSelection = React.useCallback(() => {
|
|
1487
|
+
if (table) {
|
|
1488
|
+
table.toggleAllRowsSelected(false);
|
|
1489
|
+
}
|
|
1490
|
+
}, [table]);
|
|
1491
|
+
if (!table) return null;
|
|
1492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("div", { className: "flex h-8 items-center rounded-lg border bg-muted/50 pr-1 pl-3", children: [
|
|
1493
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)("span", { className: "whitespace-nowrap text-sm font-medium", children: [
|
|
1494
|
+
table.getFilteredSelectedRowModel().rows.length,
|
|
1495
|
+
" selected"
|
|
1496
|
+
] }),
|
|
1497
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Separator, { orientation: "vertical", className: "mr-2 ml-3 data-[orientation=vertical]:h-4" }),
|
|
1498
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Tooltip, { children: [
|
|
1499
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Button, { variant: "ghost", size: "icon", className: "size-6 rounded-md", onClick: onClearSelection, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react6.X, { className: "size-3.5" }) }) }),
|
|
1500
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
|
|
1501
|
+
TooltipContent,
|
|
1502
|
+
{
|
|
1503
|
+
sideOffset: 10,
|
|
1504
|
+
className: "flex items-center gap-2 rounded-lg border px-3 py-2 font-semibold text-foregroun bg-secondary [&>span]:hidden",
|
|
1505
|
+
children: [
|
|
1506
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("p", { children: "Clear selection" }),
|
|
1507
|
+
/* @__PURE__ */ (0, import_jsx_runtime14.jsx)("kbd", { className: "select-none rounded border bg-primary/50 px-2 py-1 font-mono font-normal text-[0.7rem] text-foreground shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("abbr", { title: "Escape", className: "no-underline", children: "Esc" }) })
|
|
1508
|
+
]
|
|
1509
|
+
}
|
|
1510
|
+
)
|
|
1511
|
+
] })
|
|
1512
|
+
] });
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
// src/components/data/data-table/data-table-column-header.tsx
|
|
1516
|
+
var import_lucide_react7 = require("lucide-react");
|
|
1517
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1518
|
+
|
|
1519
|
+
// src/components/data/data-table/data-table-view-options.tsx
|
|
1520
|
+
var import_lucide_react8 = require("lucide-react");
|
|
1521
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1522
|
+
|
|
1523
|
+
// src/components/ui/badge.tsx
|
|
1524
|
+
var import_radix_ui8 = require("radix-ui");
|
|
1525
|
+
var import_class_variance_authority3 = require("class-variance-authority");
|
|
1526
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1527
|
+
var badgeVariants = (0, import_class_variance_authority3.cva)(
|
|
1528
|
+
"inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-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 transition-[color,box-shadow] overflow-hidden",
|
|
1529
|
+
{
|
|
1530
|
+
variants: {
|
|
1531
|
+
variant: {
|
|
1532
|
+
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
1533
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
1534
|
+
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
1535
|
+
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
1536
|
+
}
|
|
1537
|
+
},
|
|
1538
|
+
defaultVariants: {
|
|
1539
|
+
variant: "default"
|
|
1540
|
+
}
|
|
1541
|
+
}
|
|
1542
|
+
);
|
|
1543
|
+
|
|
1544
|
+
// src/components/ui/command.tsx
|
|
1545
|
+
var import_cmdk = require("cmdk");
|
|
1546
|
+
var import_lucide_react10 = require("lucide-react");
|
|
1547
|
+
|
|
1548
|
+
// src/components/ui/dialog.tsx
|
|
1549
|
+
var import_radix_ui9 = require("radix-ui");
|
|
1550
|
+
var import_lucide_react9 = require("lucide-react");
|
|
1551
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1552
|
+
|
|
1553
|
+
// src/components/ui/command.tsx
|
|
1554
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1555
|
+
|
|
1556
|
+
// src/components/ui/popover.tsx
|
|
1557
|
+
var import_radix_ui10 = require("radix-ui");
|
|
1558
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1559
|
+
|
|
1560
|
+
// src/components/data/data-table/data-table-faceted-filter.tsx
|
|
1561
|
+
var import_lucide_react11 = require("lucide-react");
|
|
1562
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1563
|
+
|
|
1564
|
+
// src/components/data/data-template/data-template.tsx
|
|
1565
|
+
var import_react2 = require("react");
|
|
1566
|
+
var import_lucide_react14 = require("lucide-react");
|
|
1567
|
+
|
|
1568
|
+
// src/components/data/data-template/data-template-toolbar.tsx
|
|
1569
|
+
var import_lucide_react12 = require("lucide-react");
|
|
1570
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1571
|
+
function DataTemplateToolbar({
|
|
1572
|
+
fields,
|
|
1573
|
+
filters,
|
|
1574
|
+
globalFilter,
|
|
1575
|
+
onGlobalFilterChange,
|
|
1576
|
+
fieldFilters,
|
|
1577
|
+
onFieldFilterChange,
|
|
1578
|
+
sortField,
|
|
1579
|
+
sortDirection,
|
|
1580
|
+
onSortChange,
|
|
1581
|
+
selectedCount,
|
|
1582
|
+
totalCount,
|
|
1583
|
+
visibleCount,
|
|
1584
|
+
onExport,
|
|
1585
|
+
onRefresh,
|
|
1586
|
+
loading,
|
|
1587
|
+
onClearFilters,
|
|
1588
|
+
onClearSorting
|
|
1589
|
+
}) {
|
|
1590
|
+
const sortableFields = fields.filter((field) => field.sortable);
|
|
1591
|
+
const hasActiveFilters = Object.values(fieldFilters).some((value) => value !== void 0 && value !== null && value !== "") || globalFilter !== "";
|
|
1592
|
+
const hasActiveSorting = sortField !== "";
|
|
1593
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "rounded-xl p-0.5", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "px-2", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex flex-col gap-6", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex items-center gap-3", children: filters.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-3 flex-wrap", children: [
|
|
1595
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "flex items-center gap-2 text-sm font-medium text-muted-foreground", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react12.Filter, { className: "h-4 w-4" }) }),
|
|
1596
|
+
filters.map((filter) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("div", { className: "relative min-w-[150px]", children: filter.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
|
|
1597
|
+
Select,
|
|
1598
|
+
{
|
|
1599
|
+
value: fieldFilters[filter.key] || "all",
|
|
1600
|
+
onValueChange: (value) => onFieldFilterChange(filter.key, value),
|
|
1601
|
+
children: [
|
|
1602
|
+
filter.icon && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }),
|
|
1603
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectTrigger, { className: cn("h-9 rounded-lg w-full", filter.icon && "pl-9"), children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectValue, { placeholder: filter.placeholder || "Select..." }) }),
|
|
1604
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(SelectContent, { className: "rounded-lg", children: [
|
|
1605
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectItem, { value: "all", children: "All" }),
|
|
1606
|
+
filter.options?.map((option) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SelectItem, { value: option.value, children: option.label }, option.value))
|
|
1607
|
+
] })
|
|
1608
|
+
]
|
|
1609
|
+
}
|
|
1610
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative", children: [
|
|
1611
|
+
filter.icon && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(filter.icon, { className: "size-4 absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground" }),
|
|
1612
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1613
|
+
Input,
|
|
1614
|
+
{
|
|
1615
|
+
type: filter.type,
|
|
1616
|
+
placeholder: filter.placeholder,
|
|
1617
|
+
value: fieldFilters[filter.key] || "",
|
|
1618
|
+
onChange: (e) => onFieldFilterChange(filter.key, e.target.value),
|
|
1619
|
+
className: cn("h-9 rounded-lg", filter.icon && "pl-9")
|
|
1620
|
+
}
|
|
1621
|
+
)
|
|
1622
|
+
] }) }, String(filter.key)))
|
|
1623
|
+
] }) }),
|
|
1624
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1625
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { className: "relative", children: [
|
|
1626
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react12.Search, { className: "absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground" }),
|
|
1627
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1628
|
+
Input,
|
|
1629
|
+
{
|
|
1630
|
+
placeholder: "Global search...",
|
|
1631
|
+
value: globalFilter,
|
|
1632
|
+
onChange: (e) => onGlobalFilterChange(e.target.value),
|
|
1633
|
+
className: "pl-9 h-9 rounded-lg max-w-max"
|
|
1634
|
+
}
|
|
1635
|
+
)
|
|
1636
|
+
] }),
|
|
1637
|
+
sortableFields.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu, { children: [
|
|
1638
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Button, { variant: "outline", size: "sm", className: "rounded-lg gap-1", children: [
|
|
1639
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)("span", { children: "Sort" }),
|
|
1640
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react12.ChevronDown, { className: "h-4 w-4 opacity-50" })
|
|
1641
|
+
] }) }),
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenuContent, { align: "end", className: "w-[200px] rounded-lg", children: [
|
|
1643
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuLabel, { children: "Sort By" }),
|
|
1644
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuSeparator, {}),
|
|
1645
|
+
sortableFields.map((field) => /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)("div", { children: [
|
|
1646
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenuItem, { onClick: () => onSortChange(field.key, "asc"), children: [
|
|
1647
|
+
field.label,
|
|
1648
|
+
" (A-Z)"
|
|
1649
|
+
] }),
|
|
1650
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenuItem, { onClick: () => onSortChange(field.key, "desc"), children: [
|
|
1651
|
+
field.label,
|
|
1652
|
+
" (Z-A)"
|
|
1653
|
+
] })
|
|
1654
|
+
] }, String(field.key))),
|
|
1655
|
+
hasActiveSorting && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
1656
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuSeparator, {}),
|
|
1657
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuItem, { onClick: onClearSorting, children: "Clear All Sorting" })
|
|
1658
|
+
] })
|
|
1659
|
+
] })
|
|
1660
|
+
] }),
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenu, { children: [
|
|
1662
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Button, { variant: "outline", size: "sm", className: "rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react12.Settings2, { className: "h-4 w-4" }) }) }),
|
|
1663
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(DropdownMenuContent, { align: "end", className: "w-[200px] rounded-lg", children: [
|
|
1664
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuLabel, { children: "Table Settings" }),
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuSeparator, {}),
|
|
1666
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuItem, { onClick: onClearSorting, children: "Clear All Sorting" }),
|
|
1667
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(DropdownMenuItem, { onClick: onClearFilters, children: "Clear All Filters" })
|
|
1668
|
+
] })
|
|
1669
|
+
] }),
|
|
1670
|
+
onExport && /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Button, { variant: "outline", size: "sm", onClick: onExport, className: "rounded-lg", children: [
|
|
1671
|
+
/* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react12.Download, { className: "mr-2 h-4 w-4" }),
|
|
1672
|
+
"Export"
|
|
1673
|
+
] }),
|
|
1674
|
+
onRefresh && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1675
|
+
Button,
|
|
1676
|
+
{
|
|
1677
|
+
variant: "outline",
|
|
1678
|
+
size: "sm",
|
|
1679
|
+
onClick: onRefresh,
|
|
1680
|
+
disabled: loading,
|
|
1681
|
+
className: "rounded-lg",
|
|
1682
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(import_lucide_react12.RefreshCw, { className: cn("h-4 w-4", loading && "animate-spin") })
|
|
1683
|
+
}
|
|
1684
|
+
)
|
|
1685
|
+
] })
|
|
1686
|
+
] }) }) }) });
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
// src/components/data/data-template/data-template-pagination.tsx
|
|
1690
|
+
var import_lucide_react13 = require("lucide-react");
|
|
1691
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1692
|
+
function DataTemplatePagination({
|
|
1693
|
+
currentPage,
|
|
1694
|
+
totalPages,
|
|
1695
|
+
pageSize,
|
|
1696
|
+
totalItems,
|
|
1697
|
+
onPageChange,
|
|
1698
|
+
onPageSizeChange,
|
|
1699
|
+
config
|
|
1700
|
+
}) {
|
|
1701
|
+
if (!config.enabled) {
|
|
1702
|
+
return null;
|
|
1703
|
+
}
|
|
1704
|
+
const pageSizeOptions = config.pageSizeOptions || [10, 20, 50, 100];
|
|
1705
|
+
const startItem = (currentPage - 1) * pageSize + 1;
|
|
1706
|
+
const endItem = Math.min(currentPage * pageSize, totalItems);
|
|
1707
|
+
const canPreviousPage = currentPage > 1;
|
|
1708
|
+
const canNextPage = currentPage < totalPages;
|
|
1709
|
+
const getPageNumbers = () => {
|
|
1710
|
+
const delta = 2;
|
|
1711
|
+
const range = [];
|
|
1712
|
+
const rangeWithDots = [];
|
|
1713
|
+
for (let i = Math.max(2, currentPage - delta); i <= Math.min(totalPages - 1, currentPage + delta); i++) {
|
|
1714
|
+
range.push(i);
|
|
1715
|
+
}
|
|
1716
|
+
if (currentPage - delta > 2) {
|
|
1717
|
+
rangeWithDots.push(1, "...");
|
|
1718
|
+
} else {
|
|
1719
|
+
rangeWithDots.push(1);
|
|
1720
|
+
}
|
|
1721
|
+
rangeWithDots.push(...range);
|
|
1722
|
+
if (currentPage + delta < totalPages - 1) {
|
|
1723
|
+
rangeWithDots.push("...", totalPages);
|
|
1724
|
+
} else if (totalPages > 1) {
|
|
1725
|
+
rangeWithDots.push(totalPages);
|
|
1726
|
+
}
|
|
1727
|
+
return rangeWithDots;
|
|
1728
|
+
};
|
|
1729
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "rounded-xl", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col sm:flex-row items-center justify-between gap-4", children: [
|
|
1730
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "flex items-center gap-6 text-sm text-muted-foreground", children: config.showInfo !== false && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { children: [
|
|
1731
|
+
"Showing ",
|
|
1732
|
+
startItem,
|
|
1733
|
+
" to ",
|
|
1734
|
+
endItem,
|
|
1735
|
+
" of ",
|
|
1736
|
+
totalItems,
|
|
1737
|
+
" entries"
|
|
1738
|
+
] }) }),
|
|
1739
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex flex-col sm:flex-row items-center gap-4", children: [
|
|
1740
|
+
pageSizeOptions && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1741
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-sm font-medium whitespace-nowrap", children: "Page size:" }),
|
|
1742
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Select, { value: `${pageSize}`, onValueChange: (value) => onPageSizeChange(Number(value)), children: [
|
|
1743
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectTrigger, { className: "h-9 w-[70px] rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectValue, {}) }),
|
|
1744
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectContent, { side: "top", className: "rounded-lg", children: pageSizeOptions.map((size) => /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(SelectItem, { value: `${size}`, children: size }, size)) })
|
|
1745
|
+
] })
|
|
1746
|
+
] }),
|
|
1747
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
1748
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
1749
|
+
Button,
|
|
1750
|
+
{
|
|
1751
|
+
variant: "outline",
|
|
1752
|
+
size: "sm",
|
|
1753
|
+
onClick: () => onPageChange(1),
|
|
1754
|
+
disabled: !canPreviousPage,
|
|
1755
|
+
className: "hidden sm:flex rounded-lg",
|
|
1756
|
+
children: [
|
|
1757
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react13.ChevronsLeft, { className: "h-4 w-4" }),
|
|
1758
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "sr-only", children: "Go to first page" })
|
|
1759
|
+
]
|
|
1760
|
+
}
|
|
1761
|
+
),
|
|
1762
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
1763
|
+
Button,
|
|
1764
|
+
{
|
|
1765
|
+
variant: "outline",
|
|
1766
|
+
size: "sm",
|
|
1767
|
+
onClick: () => onPageChange(currentPage - 1),
|
|
1768
|
+
disabled: !canPreviousPage,
|
|
1769
|
+
className: "rounded-lg",
|
|
1770
|
+
children: [
|
|
1771
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react13.ChevronLeft, { className: "h-4 w-4 sm:mr-2" }),
|
|
1772
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "hidden sm:inline", children: "Previous" }),
|
|
1773
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "sr-only sm:hidden", children: "Go to previous page" })
|
|
1774
|
+
]
|
|
1775
|
+
}
|
|
1776
|
+
),
|
|
1777
|
+
config.showPageNumbers && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "hidden sm:flex items-center gap-1", children: getPageNumbers().map((pageNumber, index) => {
|
|
1778
|
+
if (pageNumber === "...") {
|
|
1779
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "px-2 py-1 text-sm text-muted-foreground", children: "..." }, `dots-${index}`);
|
|
1780
|
+
}
|
|
1781
|
+
const page = pageNumber;
|
|
1782
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1783
|
+
Button,
|
|
1784
|
+
{
|
|
1785
|
+
variant: page === currentPage ? "default" : "outline",
|
|
1786
|
+
size: "sm",
|
|
1787
|
+
className: "w-9 h-9 p-0 rounded-lg",
|
|
1788
|
+
onClick: () => onPageChange(page),
|
|
1789
|
+
children: page
|
|
1790
|
+
},
|
|
1791
|
+
page
|
|
1792
|
+
);
|
|
1793
|
+
}) }),
|
|
1794
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "sm:hidden flex items-center gap-2 px-3 py-1 text-sm font-medium bg-muted rounded-lg", children: [
|
|
1795
|
+
currentPage,
|
|
1796
|
+
" of ",
|
|
1797
|
+
totalPages
|
|
1798
|
+
] }),
|
|
1799
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
1800
|
+
Button,
|
|
1801
|
+
{
|
|
1802
|
+
variant: "outline",
|
|
1803
|
+
size: "sm",
|
|
1804
|
+
onClick: () => onPageChange(currentPage + 1),
|
|
1805
|
+
disabled: !canNextPage,
|
|
1806
|
+
className: "rounded-lg",
|
|
1807
|
+
children: [
|
|
1808
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "hidden sm:inline", children: "Next" }),
|
|
1809
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react13.ChevronRight, { className: "h-4 w-4 sm:ml-2" }),
|
|
1810
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "sr-only sm:hidden", children: "Go to next page" })
|
|
1811
|
+
]
|
|
1812
|
+
}
|
|
1813
|
+
),
|
|
1814
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
|
|
1815
|
+
Button,
|
|
1816
|
+
{
|
|
1817
|
+
variant: "outline",
|
|
1818
|
+
size: "sm",
|
|
1819
|
+
onClick: () => onPageChange(totalPages),
|
|
1820
|
+
disabled: !canNextPage,
|
|
1821
|
+
className: "hidden sm:flex rounded-lg",
|
|
1822
|
+
children: [
|
|
1823
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react13.ChevronsRight, { className: "h-4 w-4" }),
|
|
1824
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "sr-only", children: "Go to last page" })
|
|
1825
|
+
]
|
|
1826
|
+
}
|
|
1827
|
+
)
|
|
1828
|
+
] })
|
|
1829
|
+
] })
|
|
1830
|
+
] }) });
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
// src/components/data/data-template/data-template.tsx
|
|
1834
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1835
|
+
function DataTemplate({
|
|
1836
|
+
data,
|
|
1837
|
+
template,
|
|
1838
|
+
fields = [],
|
|
1839
|
+
filters = [],
|
|
1840
|
+
pagination = { enabled: false },
|
|
1841
|
+
settings = {},
|
|
1842
|
+
header,
|
|
1843
|
+
footer,
|
|
1844
|
+
className = "",
|
|
1845
|
+
loading = false,
|
|
1846
|
+
error,
|
|
1847
|
+
emptyMessage = "No items found",
|
|
1848
|
+
emptyIcon,
|
|
1849
|
+
onSelectionChange,
|
|
1850
|
+
onExport,
|
|
1851
|
+
onRefresh,
|
|
1852
|
+
onTemplateReady,
|
|
1853
|
+
children
|
|
1854
|
+
}) {
|
|
1855
|
+
const {
|
|
1856
|
+
enableSorting = true,
|
|
1857
|
+
enableFiltering = true,
|
|
1858
|
+
enableGlobalSearch = true,
|
|
1859
|
+
enableSelection = false,
|
|
1860
|
+
enableExport = false,
|
|
1861
|
+
toolbar = true,
|
|
1862
|
+
selectionMode = "multiple",
|
|
1863
|
+
gridCols = { default: 3, sm: 1, md: 2, lg: 3, xl: 4, "2xl": 6 },
|
|
1864
|
+
gap = 4,
|
|
1865
|
+
aspectRatio = "auto",
|
|
1866
|
+
minCardWidth = 350,
|
|
1867
|
+
maxCardWidth = 350
|
|
1868
|
+
} = settings;
|
|
1869
|
+
const [globalFilter, setGlobalFilter] = (0, import_react2.useState)("");
|
|
1870
|
+
const [fieldFilters, setFieldFilters] = (0, import_react2.useState)({});
|
|
1871
|
+
const [sortField, setSortField] = (0, import_react2.useState)("");
|
|
1872
|
+
const [sortDirection, setSortDirection] = (0, import_react2.useState)("asc");
|
|
1873
|
+
const [selectedItems, setSelectedItems] = (0, import_react2.useState)(/* @__PURE__ */ new Set());
|
|
1874
|
+
const [currentPage, setCurrentPage] = (0, import_react2.useState)(1);
|
|
1875
|
+
const [pageSize, setPageSize] = (0, import_react2.useState)(pagination.pageSize || 12);
|
|
1876
|
+
const [currentGridCols, setCurrentGridCols] = (0, import_react2.useState)(gridCols.default);
|
|
1877
|
+
const filteredAndSortedData = (0, import_react2.useMemo)(() => {
|
|
1878
|
+
let result = [...data];
|
|
1879
|
+
if (enableGlobalSearch && globalFilter) {
|
|
1880
|
+
const searchableFields = fields.filter((field) => field.searchable !== false);
|
|
1881
|
+
result = result.filter(
|
|
1882
|
+
(item) => searchableFields.some((field) => {
|
|
1883
|
+
const value = item[field.key];
|
|
1884
|
+
return value?.toString().toLowerCase().includes(globalFilter.toLowerCase());
|
|
1885
|
+
})
|
|
1886
|
+
);
|
|
1887
|
+
}
|
|
1888
|
+
if (enableFiltering) {
|
|
1889
|
+
Object.keys(fieldFilters).forEach((key) => {
|
|
1890
|
+
const value = fieldFilters[key];
|
|
1891
|
+
if (value !== void 0 && value !== null && value !== "") {
|
|
1892
|
+
const field = fields.find((f) => f.key === key);
|
|
1893
|
+
if (field) {
|
|
1894
|
+
result = result.filter((item) => {
|
|
1895
|
+
const itemValue = item[key];
|
|
1896
|
+
if (field.type === "boolean") {
|
|
1897
|
+
return itemValue === (value === "true");
|
|
1898
|
+
} else if (field.type === "number") {
|
|
1899
|
+
return itemValue === Number(value);
|
|
1900
|
+
} else {
|
|
1901
|
+
return itemValue?.toString().toLowerCase().includes(String(value).toLowerCase());
|
|
1902
|
+
}
|
|
1903
|
+
});
|
|
1904
|
+
}
|
|
1905
|
+
}
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
if (enableSorting && sortField) {
|
|
1909
|
+
const field = fields.find((f) => f.key === sortField);
|
|
1910
|
+
if (field) {
|
|
1911
|
+
result.sort((a, b) => {
|
|
1912
|
+
const aValue = a[sortField];
|
|
1913
|
+
const bValue = b[sortField];
|
|
1914
|
+
if (field.type === "number") {
|
|
1915
|
+
return sortDirection === "asc" ? Number(aValue) - Number(bValue) : Number(bValue) - Number(aValue);
|
|
1916
|
+
} else if (field.type === "date") {
|
|
1917
|
+
const aDate = new Date(aValue);
|
|
1918
|
+
const bDate = new Date(bValue);
|
|
1919
|
+
return sortDirection === "asc" ? aDate.getTime() - bDate.getTime() : bDate.getTime() - aDate.getTime();
|
|
1920
|
+
} else {
|
|
1921
|
+
const aStr = String(aValue).toLowerCase();
|
|
1922
|
+
const bStr = String(bValue).toLowerCase();
|
|
1923
|
+
return sortDirection === "asc" ? aStr.localeCompare(bStr) : bStr.localeCompare(aStr);
|
|
1924
|
+
}
|
|
1925
|
+
});
|
|
1926
|
+
}
|
|
1927
|
+
}
|
|
1928
|
+
return result;
|
|
1929
|
+
}, [
|
|
1930
|
+
data,
|
|
1931
|
+
globalFilter,
|
|
1932
|
+
fieldFilters,
|
|
1933
|
+
sortField,
|
|
1934
|
+
sortDirection,
|
|
1935
|
+
fields,
|
|
1936
|
+
enableGlobalSearch,
|
|
1937
|
+
enableFiltering,
|
|
1938
|
+
enableSorting
|
|
1939
|
+
]);
|
|
1940
|
+
const paginatedData = (0, import_react2.useMemo)(() => {
|
|
1941
|
+
if (!pagination.enabled) return filteredAndSortedData;
|
|
1942
|
+
const startIndex = (currentPage - 1) * pageSize;
|
|
1943
|
+
const endIndex = startIndex + pageSize;
|
|
1944
|
+
return filteredAndSortedData.slice(startIndex, endIndex);
|
|
1945
|
+
}, [filteredAndSortedData, currentPage, pageSize, pagination.enabled]);
|
|
1946
|
+
const totalPages = Math.ceil(filteredAndSortedData.length / pageSize);
|
|
1947
|
+
const handleToggleSelect = (0, import_react2.useCallback)(
|
|
1948
|
+
(index) => {
|
|
1949
|
+
if (!enableSelection) return;
|
|
1950
|
+
setSelectedItems((prev) => {
|
|
1951
|
+
const newSelection = new Set(prev);
|
|
1952
|
+
if (selectionMode === "single") {
|
|
1953
|
+
newSelection.clear();
|
|
1954
|
+
newSelection.add(index);
|
|
1955
|
+
} else {
|
|
1956
|
+
if (newSelection.has(index)) {
|
|
1957
|
+
newSelection.delete(index);
|
|
1958
|
+
} else {
|
|
1959
|
+
newSelection.add(index);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
return newSelection;
|
|
1963
|
+
});
|
|
1964
|
+
},
|
|
1965
|
+
[enableSelection, selectionMode]
|
|
1966
|
+
);
|
|
1967
|
+
const handleSelectAll = (0, import_react2.useCallback)(() => {
|
|
1968
|
+
if (!enableSelection || selectionMode === "single") return;
|
|
1969
|
+
if (selectedItems.size === filteredAndSortedData.length) {
|
|
1970
|
+
setSelectedItems(/* @__PURE__ */ new Set());
|
|
1971
|
+
} else {
|
|
1972
|
+
setSelectedItems(new Set(filteredAndSortedData.map((_, index) => index)));
|
|
1973
|
+
}
|
|
1974
|
+
}, [enableSelection, selectionMode, selectedItems.size, filteredAndSortedData.length]);
|
|
1975
|
+
const handleFieldFilterChange = (0, import_react2.useCallback)((key, value) => {
|
|
1976
|
+
setFieldFilters((prev) => ({ ...prev, [key]: value }));
|
|
1977
|
+
setCurrentPage(1);
|
|
1978
|
+
}, []);
|
|
1979
|
+
const handleSortChange = (0, import_react2.useCallback)((field, direction) => {
|
|
1980
|
+
setSortField(field);
|
|
1981
|
+
setSortDirection(direction);
|
|
1982
|
+
}, []);
|
|
1983
|
+
const handleClearFilters = (0, import_react2.useCallback)(() => {
|
|
1984
|
+
setGlobalFilter("");
|
|
1985
|
+
setFieldFilters({});
|
|
1986
|
+
setCurrentPage(1);
|
|
1987
|
+
}, []);
|
|
1988
|
+
const handleClearSorting = (0, import_react2.useCallback)(() => {
|
|
1989
|
+
setSortField("");
|
|
1990
|
+
setSortDirection("asc");
|
|
1991
|
+
}, []);
|
|
1992
|
+
const controller = (0, import_react2.useMemo)(
|
|
1993
|
+
() => ({
|
|
1994
|
+
getSelectedItems: () => Array.from(selectedItems).map((index) => filteredAndSortedData[index]),
|
|
1995
|
+
clearSelection: () => setSelectedItems(/* @__PURE__ */ new Set()),
|
|
1996
|
+
selectAll: handleSelectAll,
|
|
1997
|
+
getFilteredData: () => filteredAndSortedData,
|
|
1998
|
+
getTotalCount: () => data.length,
|
|
1999
|
+
getVisibleCount: () => filteredAndSortedData.length,
|
|
2000
|
+
refresh: () => onRefresh?.(),
|
|
2001
|
+
exportData: () => onExport?.(filteredAndSortedData)
|
|
2002
|
+
}),
|
|
2003
|
+
[selectedItems, filteredAndSortedData, data.length, handleSelectAll, onRefresh, onExport]
|
|
2004
|
+
);
|
|
2005
|
+
const controllerRef = (0, import_react2.useRef)(null);
|
|
2006
|
+
controllerRef.current = controller;
|
|
2007
|
+
(0, import_react2.useEffect)(() => {
|
|
2008
|
+
if (onTemplateReady && controllerRef.current) {
|
|
2009
|
+
onTemplateReady(controllerRef.current);
|
|
2010
|
+
}
|
|
2011
|
+
}, []);
|
|
2012
|
+
(0, import_react2.useEffect)(() => {
|
|
2013
|
+
if (enableSelection && onSelectionChange) {
|
|
2014
|
+
const selected = Array.from(selectedItems).map((index) => filteredAndSortedData[index]);
|
|
2015
|
+
onSelectionChange(selected);
|
|
2016
|
+
}
|
|
2017
|
+
}, [selectedItems]);
|
|
2018
|
+
const gridContainerClasses = cn(
|
|
2019
|
+
"w-full",
|
|
2020
|
+
"overflow-hidden",
|
|
2021
|
+
// Prevent any potential overflow issues
|
|
2022
|
+
className
|
|
2023
|
+
);
|
|
2024
|
+
const gridClasses = cn(
|
|
2025
|
+
"grid",
|
|
2026
|
+
`gap-${gap}`,
|
|
2027
|
+
"w-full",
|
|
2028
|
+
// Ensure grid takes full width
|
|
2029
|
+
"mx-auto",
|
|
2030
|
+
// Center the grid if it doesn't take full width
|
|
2031
|
+
"items-start"
|
|
2032
|
+
// Align items to the top
|
|
2033
|
+
);
|
|
2034
|
+
const gridStyle = {
|
|
2035
|
+
// Primary grid definition - choose one of these options:
|
|
2036
|
+
gridTemplateColumns: currentGridCols === 0 ? `repeat(auto-fill, minmax(clamp(${minCardWidth}px, 30%, ${maxCardWidth}px), 1fr))` : `repeat(auto-fill, minmax(clamp(${minCardWidth}px, calc(100%/${currentGridCols} - ${gap * 4}px), ${maxCardWidth}px), 1fr))`,
|
|
2037
|
+
// gridTemplateColumns: `repeat(auto-fill, minmax(clamp(${minCardWidth}px, calc(100%/${Math.min(
|
|
2038
|
+
// currentGridCols,
|
|
2039
|
+
// gridCols["2xl"] || 6
|
|
2040
|
+
// )} - ${gap * 4}px), ${maxCardWidth}px))`,
|
|
2041
|
+
// Option 1: Fully fluid grid (recommended)
|
|
2042
|
+
// gridTemplateColumns: `repeat(auto-fill, minmax(clamp(${minCardWidth}px, 30%, ${maxCardWidth}px), 1fr))`,
|
|
2043
|
+
// Option 2: More controlled fluid grid
|
|
2044
|
+
// gridTemplateColumns: `repeat(auto-fit, minmax(clamp(${minCardWidth}px, 25vw, ${maxCardWidth}px), 1fr))`,
|
|
2045
|
+
// Option 3: Fixed maximum columns with fluid width
|
|
2046
|
+
// gridTemplateColumns: `repeat(min(6, auto-fill), minmax(${minCardWidth}px, ${maxCardWidth}px))`,
|
|
2047
|
+
// Additional grid enhancements
|
|
2048
|
+
justifyItems: "center",
|
|
2049
|
+
// Center items horizontally in their grid cells
|
|
2050
|
+
alignItems: "stretch",
|
|
2051
|
+
// Stretch items vertically to fill the grid cell
|
|
2052
|
+
gridAutoRows: "1fr",
|
|
2053
|
+
// Make all rows the same height
|
|
2054
|
+
gridAutoFlow: "dense"
|
|
2055
|
+
// Try to fill holes in the grid
|
|
2056
|
+
};
|
|
2057
|
+
if (error) {
|
|
2058
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Card, { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CardContent, { className: "flex items-center justify-center py-12", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "text-center", children: [
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "text-red-500 mb-3 text-2xl", children: "\u26A0\uFE0F" }),
|
|
2060
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-sm text-muted-foreground mb-4", children: error }),
|
|
2061
|
+
onRefresh && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(Button, { variant: "outline", size: "sm", onClick: onRefresh, children: [
|
|
2062
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.Loader2, { className: "mr-2 h-4 w-4" }),
|
|
2063
|
+
"Try Again"
|
|
2064
|
+
] })
|
|
2065
|
+
] }) }) });
|
|
2066
|
+
}
|
|
2067
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: cn("w-full flex gap-2 flex-col h-full", gridContainerClasses), children: [
|
|
2068
|
+
header && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Card, { className: "shadow-sm border-0 bg-gradient-to-r from-background to-muted/20", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CardContent, { className: "p-6", children: header }) }),
|
|
2069
|
+
toolbar && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2070
|
+
DataTemplateToolbar,
|
|
2071
|
+
{
|
|
2072
|
+
fields,
|
|
2073
|
+
filters,
|
|
2074
|
+
globalFilter,
|
|
2075
|
+
onGlobalFilterChange: setGlobalFilter,
|
|
2076
|
+
fieldFilters,
|
|
2077
|
+
onFieldFilterChange: handleFieldFilterChange,
|
|
2078
|
+
sortField,
|
|
2079
|
+
sortDirection,
|
|
2080
|
+
onSortChange: handleSortChange,
|
|
2081
|
+
selectedCount: selectedItems.size,
|
|
2082
|
+
totalCount: data.length,
|
|
2083
|
+
visibleCount: filteredAndSortedData.length,
|
|
2084
|
+
onExport: enableExport ? () => onExport?.(filteredAndSortedData) : void 0,
|
|
2085
|
+
onRefresh,
|
|
2086
|
+
loading,
|
|
2087
|
+
onClearFilters: handleClearFilters,
|
|
2088
|
+
onClearSorting: handleClearSorting
|
|
2089
|
+
}
|
|
2090
|
+
),
|
|
2091
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Card, { className: "border-0 overflow-auto shadow-none py-0 p-2 flex-1", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(CardContent, { className: "px-0", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "relative", children: [
|
|
2092
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute inset-0 bg-background/80 backdrop-blur-sm z-50 flex items-center justify-center rounded-lg", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex items-center gap-3 bg-background/90 px-4 py-3 rounded-lg shadow-sm", children: [
|
|
2093
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react14.Loader2, { className: "size-5 animate-spin text-primary" }),
|
|
2094
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-sm font-medium text-muted-foreground", children: "Loading..." })
|
|
2095
|
+
] }) }),
|
|
2096
|
+
paginatedData.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2097
|
+
"div",
|
|
2098
|
+
{
|
|
2099
|
+
className: cn(gridClasses),
|
|
2100
|
+
style: gridStyle,
|
|
2101
|
+
children: paginatedData.map((item, index) => {
|
|
2102
|
+
const globalIndex = pagination.enabled ? (currentPage - 1) * pageSize + index : index;
|
|
2103
|
+
const isSelected = selectedItems.has(globalIndex);
|
|
2104
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(
|
|
2105
|
+
"div",
|
|
2106
|
+
{
|
|
2107
|
+
className: cn(
|
|
2108
|
+
"relative h-full w-full flex flex-col",
|
|
2109
|
+
"transition-all duration-200 overflow-hidden",
|
|
2110
|
+
"rounded-2xl",
|
|
2111
|
+
"border border-border/20 hover:border-border/50",
|
|
2112
|
+
aspectRatio === "square" ? "aspect-square" : "",
|
|
2113
|
+
aspectRatio === "video" ? "aspect-video" : "",
|
|
2114
|
+
enableSelection ? "cursor-pointer" : "",
|
|
2115
|
+
isSelected ? "ring-2 ring-primary" : ""
|
|
2116
|
+
),
|
|
2117
|
+
onClick: () => enableSelection && handleToggleSelect(globalIndex),
|
|
2118
|
+
children: [
|
|
2119
|
+
enableSelection && selectionMode === "multiple" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "absolute top-2 right-2 z-10", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2120
|
+
Checkbox,
|
|
2121
|
+
{
|
|
2122
|
+
checked: isSelected,
|
|
2123
|
+
onCheckedChange: () => handleToggleSelect(globalIndex),
|
|
2124
|
+
className: "bg-background/80 backdrop-blur-sm",
|
|
2125
|
+
onClick: (e) => e.stopPropagation()
|
|
2126
|
+
}
|
|
2127
|
+
) }),
|
|
2128
|
+
template(item, index, isSelected, () => handleToggleSelect(globalIndex))
|
|
2129
|
+
]
|
|
2130
|
+
},
|
|
2131
|
+
globalIndex
|
|
2132
|
+
);
|
|
2133
|
+
})
|
|
2134
|
+
}
|
|
2135
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex flex-col items-center justify-center py-12 text-center", children: [
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "text-6xl mb-4", children: emptyIcon || "\u{1F4CB}" }),
|
|
2137
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { className: "text-lg font-medium text-muted-foreground mb-2", children: emptyMessage }),
|
|
2138
|
+
(globalFilter || Object.values(fieldFilters).some((v) => v)) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Button, { variant: "outline", onClick: handleClearFilters, children: "Clear Filters" })
|
|
2139
|
+
] })
|
|
2140
|
+
] }) }) }),
|
|
2141
|
+
pagination.enabled && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
2142
|
+
DataTemplatePagination,
|
|
2143
|
+
{
|
|
2144
|
+
currentPage,
|
|
2145
|
+
totalPages,
|
|
2146
|
+
pageSize,
|
|
2147
|
+
totalItems: filteredAndSortedData.length,
|
|
2148
|
+
onPageChange: setCurrentPage,
|
|
2149
|
+
onPageSizeChange: (size) => {
|
|
2150
|
+
setPageSize(size);
|
|
2151
|
+
setCurrentPage(1);
|
|
2152
|
+
},
|
|
2153
|
+
config: pagination
|
|
2154
|
+
}
|
|
2155
|
+
) }),
|
|
2156
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "p-2 m-0.5", children: footer }),
|
|
2157
|
+
children && children(controller)
|
|
2158
|
+
] });
|
|
2159
|
+
}
|
|
2160
|
+
|
|
2161
|
+
// src/components/data/data-template/data-template-action-bar.tsx
|
|
2162
|
+
var import_lucide_react15 = require("lucide-react");
|
|
2163
|
+
var import_framer_motion2 = require("framer-motion");
|
|
2164
|
+
var React2 = __toESM(require("react"), 1);
|
|
2165
|
+
var ReactDOM2 = __toESM(require("react-dom"), 1);
|
|
2166
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
2167
|
+
function DataTemplateActionBar({
|
|
2168
|
+
controller,
|
|
2169
|
+
visible: visibleProp,
|
|
2170
|
+
container: containerProp,
|
|
2171
|
+
children,
|
|
2172
|
+
className,
|
|
2173
|
+
...props
|
|
2174
|
+
}) {
|
|
2175
|
+
const [mounted, setMounted] = React2.useState(false);
|
|
2176
|
+
React2.useLayoutEffect(() => {
|
|
2177
|
+
setMounted(true);
|
|
2178
|
+
}, []);
|
|
2179
|
+
React2.useEffect(() => {
|
|
2180
|
+
function onKeyDown(event) {
|
|
2181
|
+
if (event.key === "Escape" && controller) {
|
|
2182
|
+
controller.clearSelection();
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
window.addEventListener("keydown", onKeyDown);
|
|
2186
|
+
return () => window.removeEventListener("keydown", onKeyDown);
|
|
2187
|
+
}, [controller]);
|
|
2188
|
+
const container = containerProp ?? (mounted ? globalThis.document?.body : null);
|
|
2189
|
+
if (!container || !controller) return null;
|
|
2190
|
+
const selectedItems = controller.getSelectedItems();
|
|
2191
|
+
const visible = visibleProp ?? selectedItems.length > 0;
|
|
2192
|
+
return ReactDOM2.createPortal(
|
|
2193
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_framer_motion2.AnimatePresence, { children: visible && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2194
|
+
import_framer_motion2.motion.div,
|
|
2195
|
+
{
|
|
2196
|
+
role: "toolbar",
|
|
2197
|
+
"aria-orientation": "horizontal",
|
|
2198
|
+
initial: { opacity: 0, y: 20 },
|
|
2199
|
+
animate: { opacity: 1, y: 0 },
|
|
2200
|
+
exit: { opacity: 0, y: 20 },
|
|
2201
|
+
transition: { duration: 0.3, ease: "easeInOut" },
|
|
2202
|
+
className: cn(
|
|
2203
|
+
"fixed inset-x-0 bottom-6 z-50 mx-auto flex w-fit flex-wrap items-center justify-center gap-2 rounded-xl border bg-primary/10 backdrop-blur-sm p-3 text-foreground ring-8 ring-primary/5",
|
|
2204
|
+
className
|
|
2205
|
+
),
|
|
2206
|
+
...props,
|
|
2207
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipProvider, { children })
|
|
2208
|
+
}
|
|
2209
|
+
) }),
|
|
2210
|
+
container
|
|
2211
|
+
);
|
|
2212
|
+
}
|
|
2213
|
+
function DataTemplateActionBarAction({
|
|
2214
|
+
size = "sm",
|
|
2215
|
+
variant = "secondary",
|
|
2216
|
+
tooltip,
|
|
2217
|
+
isPending,
|
|
2218
|
+
disabled,
|
|
2219
|
+
className,
|
|
2220
|
+
children,
|
|
2221
|
+
onClick,
|
|
2222
|
+
...props
|
|
2223
|
+
}) {
|
|
2224
|
+
const trigger = /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2225
|
+
Button,
|
|
2226
|
+
{
|
|
2227
|
+
variant,
|
|
2228
|
+
size,
|
|
2229
|
+
className: cn(
|
|
2230
|
+
"gap-1.5 rounded-lg border border-secondary bg-secondary/50 hover:bg-secondary/70 transition-all duration-200",
|
|
2231
|
+
size === "icon" ? "size-8" : "h-8 px-3",
|
|
2232
|
+
className
|
|
2233
|
+
),
|
|
2234
|
+
disabled: disabled || isPending,
|
|
2235
|
+
onClick,
|
|
2236
|
+
...props,
|
|
2237
|
+
children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react15.Loader, { className: "animate-spin" }) : children
|
|
2238
|
+
}
|
|
2239
|
+
);
|
|
2240
|
+
if (!tooltip) return trigger;
|
|
2241
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
|
|
2242
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: trigger }),
|
|
2243
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
2244
|
+
TooltipContent,
|
|
2245
|
+
{
|
|
2246
|
+
sideOffset: 8,
|
|
2247
|
+
className: "rounded-lg border font-semibold text-foreground bg-secondary [&>span]:hidden",
|
|
2248
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { children: tooltip })
|
|
2249
|
+
}
|
|
2250
|
+
)
|
|
2251
|
+
] });
|
|
2252
|
+
}
|
|
2253
|
+
function DataTemplateActionBarSelection({ controller }) {
|
|
2254
|
+
const onClearSelection = React2.useCallback(() => {
|
|
2255
|
+
if (controller) {
|
|
2256
|
+
controller.clearSelection();
|
|
2257
|
+
}
|
|
2258
|
+
}, [controller]);
|
|
2259
|
+
if (!controller) return null;
|
|
2260
|
+
const selectedItems = controller.getSelectedItems();
|
|
2261
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex h-8 items-center rounded-lg border bg-muted/50 pr-1 pl-3", children: [
|
|
2262
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("span", { className: "whitespace-nowrap text-sm font-medium", children: [
|
|
2263
|
+
selectedItems.length,
|
|
2264
|
+
" selected"
|
|
2265
|
+
] }),
|
|
2266
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Separator, { orientation: "vertical", className: "mr-2 ml-3 data-[orientation=vertical]:h-4" }),
|
|
2267
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(Tooltip, { children: [
|
|
2268
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Button, { variant: "ghost", size: "icon", className: "size-6 rounded-md", onClick: onClearSelection, children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react15.X, { className: "size-3.5" }) }) }),
|
|
2269
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
|
|
2270
|
+
TooltipContent,
|
|
2271
|
+
{
|
|
2272
|
+
sideOffset: 10,
|
|
2273
|
+
className: "flex items-center gap-2 rounded-lg border px-3 py-2 font-semibold text-foreground bg-secondary [&>span]:hidden",
|
|
2274
|
+
children: [
|
|
2275
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { children: "Clear selection" }),
|
|
2276
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("kbd", { className: "select-none rounded border bg-primary/50 px-2 py-1 font-mono font-normal text-[0.7rem] text-foreground shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("abbr", { title: "Escape", className: "no-underline", children: "Esc" }) })
|
|
2277
|
+
]
|
|
2278
|
+
}
|
|
2279
|
+
)
|
|
2280
|
+
] })
|
|
2281
|
+
] });
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// src/components/layouts/app-container.tsx
|
|
2285
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
2286
|
+
var spacingClasses = {
|
|
2287
|
+
"none": "gap-0",
|
|
2288
|
+
"tight": "gap-2",
|
|
2289
|
+
"default": "gap-4",
|
|
2290
|
+
"loose": "gap-6",
|
|
2291
|
+
"extra-loose": "gap-8"
|
|
2292
|
+
};
|
|
2293
|
+
var paddingClasses = {
|
|
2294
|
+
"none": "p-0",
|
|
2295
|
+
"tight": "p-2",
|
|
2296
|
+
"default": "p-4",
|
|
2297
|
+
"loose": "p-6"
|
|
2298
|
+
};
|
|
2299
|
+
var AppContainer = ({
|
|
2300
|
+
children,
|
|
2301
|
+
className,
|
|
2302
|
+
spacing = "tight",
|
|
2303
|
+
padding = "none"
|
|
2304
|
+
}) => {
|
|
2305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: cn(
|
|
2306
|
+
"flex flex-col h-full",
|
|
2307
|
+
spacingClasses[spacing],
|
|
2308
|
+
paddingClasses[padding],
|
|
2309
|
+
className
|
|
2310
|
+
), children });
|
|
2311
|
+
};
|
|
2312
|
+
|
|
2313
|
+
// src/components/layouts/app-header.tsx
|
|
2314
|
+
var import_lucide_react16 = require("lucide-react");
|
|
2315
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
2316
|
+
var AppHeader = ({
|
|
2317
|
+
className,
|
|
2318
|
+
columns = [],
|
|
2319
|
+
showBackButton = true,
|
|
2320
|
+
meta = { title: "" }
|
|
2321
|
+
}) => {
|
|
2322
|
+
const renderBackAction = () => {
|
|
2323
|
+
if (!meta.backAction || !showBackButton) return null;
|
|
2324
|
+
const buttonProps = {
|
|
2325
|
+
variant: "secondary",
|
|
2326
|
+
size: "icon",
|
|
2327
|
+
className: "hover:bg-primary/20 inline-flex"
|
|
2328
|
+
};
|
|
2329
|
+
if (meta.backAction.href) {
|
|
2330
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Button, { ...buttonProps, children: [
|
|
2331
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react16.ArrowLeftIcon, { className: "size-6" }),
|
|
2332
|
+
meta.backAction.content
|
|
2333
|
+
] });
|
|
2334
|
+
}
|
|
2335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(Button, { ...buttonProps, onClick: meta.backAction.onClick, children: [
|
|
2336
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react16.ArrowLeftIcon, { className: "size-6" }),
|
|
2337
|
+
meta.backAction.content
|
|
2338
|
+
] });
|
|
2339
|
+
};
|
|
2340
|
+
const renderMetadata = () => {
|
|
2341
|
+
if (!meta.metadata || meta.metadata.length === 0) return null;
|
|
2342
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex gap-4", children: meta.metadata.map((item, index) => item.value && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "text-sm", children: [
|
|
2343
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: "text-muted-foreground", children: [
|
|
2344
|
+
item.label,
|
|
2345
|
+
" "
|
|
2346
|
+
] }),
|
|
2347
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: item.value })
|
|
2348
|
+
] }, index)) });
|
|
2349
|
+
};
|
|
2350
|
+
const renderStatus = () => {
|
|
2351
|
+
if (!meta.status) return null;
|
|
2352
|
+
const colorClasses = {
|
|
2353
|
+
success: "bg-green-100 text-green-800",
|
|
2354
|
+
warning: "bg-yellow-100 text-yellow-800",
|
|
2355
|
+
critical: "bg-red-100 text-red-800",
|
|
2356
|
+
info: "bg-blue-100 text-blue-800",
|
|
2357
|
+
default: "bg-gray-100 text-gray-800"
|
|
2358
|
+
};
|
|
2359
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: cn(
|
|
2360
|
+
"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium",
|
|
2361
|
+
colorClasses[meta.status.color]
|
|
2362
|
+
), children: meta.status.content });
|
|
2363
|
+
};
|
|
2364
|
+
const reservedColumn = {
|
|
2365
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex gap-2 items-center", children: [
|
|
2366
|
+
renderBackAction(),
|
|
2367
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-col gap-2 w-max", children: [
|
|
2368
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("h1", { className: "text-2xl font-bold tracking-tight", children: meta.title }),
|
|
2369
|
+
renderStatus(),
|
|
2370
|
+
meta.description && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-muted-foreground", children: meta.description }),
|
|
2371
|
+
renderMetadata(),
|
|
2372
|
+
meta.breadcrumbs && meta.breadcrumbs.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: "flex items-center text-sm text-muted-foreground", children: meta.breadcrumbs.map((crumb, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex items-center", children: [
|
|
2373
|
+
crumb.href ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: "hover:text-primary hover:underline", children: crumb.label }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { children: crumb.label }),
|
|
2374
|
+
index < meta.breadcrumbs.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react16.ChevronRight, { className: "mx-2 h-4 w-4" })
|
|
2375
|
+
] }, index)) })
|
|
2376
|
+
] })
|
|
2377
|
+
] }),
|
|
2378
|
+
align: "left",
|
|
2379
|
+
width: "fill"
|
|
2380
|
+
};
|
|
2381
|
+
const actionsColumn = {
|
|
2382
|
+
content: meta.primaryActions,
|
|
2383
|
+
align: "right",
|
|
2384
|
+
width: "auto"
|
|
2385
|
+
};
|
|
2386
|
+
const allColumns = [
|
|
2387
|
+
reservedColumn,
|
|
2388
|
+
...columns.filter((col) => col !== void 0),
|
|
2389
|
+
actionsColumn
|
|
2390
|
+
];
|
|
2391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { className: cn("flex items-center w-full gap-4 p-2", className), children: allColumns.map((column, index) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
2392
|
+
"div",
|
|
2393
|
+
{
|
|
2394
|
+
className: cn(
|
|
2395
|
+
"flex items-center h-full",
|
|
2396
|
+
column.className,
|
|
2397
|
+
{
|
|
2398
|
+
"justify-start": column.align === "left",
|
|
2399
|
+
"justify-center": column.align === "center",
|
|
2400
|
+
"justify-end": column.align === "right",
|
|
2401
|
+
"flex-1": column.width === "fill"
|
|
2402
|
+
}
|
|
2403
|
+
),
|
|
2404
|
+
children: column.content
|
|
2405
|
+
},
|
|
2406
|
+
index
|
|
2407
|
+
)) });
|
|
2408
|
+
};
|
|
2409
|
+
|
|
2410
|
+
// src/components/layouts/app-content.tsx
|
|
2411
|
+
var import_react3 = __toESM(require("react"), 1);
|
|
2412
|
+
|
|
2413
|
+
// src/components/ui/sheet.tsx
|
|
2414
|
+
var import_radix_ui11 = require("radix-ui");
|
|
2415
|
+
var import_lucide_react17 = require("lucide-react");
|
|
2416
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
2417
|
+
function Sheet({ ...props }) {
|
|
2418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_radix_ui11.Dialog.Root, { "data-slot": "sheet", ...props });
|
|
2419
|
+
}
|
|
2420
|
+
function SheetTrigger({
|
|
2421
|
+
...props
|
|
2422
|
+
}) {
|
|
2423
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_radix_ui11.Dialog.Trigger, { "data-slot": "sheet-trigger", ...props });
|
|
2424
|
+
}
|
|
2425
|
+
function SheetPortal({
|
|
2426
|
+
...props
|
|
2427
|
+
}) {
|
|
2428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_radix_ui11.Dialog.Portal, { "data-slot": "sheet-portal", ...props });
|
|
2429
|
+
}
|
|
2430
|
+
function SheetOverlay({
|
|
2431
|
+
className,
|
|
2432
|
+
...props
|
|
2433
|
+
}) {
|
|
2434
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
2435
|
+
import_radix_ui11.Dialog.Overlay,
|
|
2436
|
+
{
|
|
2437
|
+
"data-slot": "sheet-overlay",
|
|
2438
|
+
className: cn(
|
|
2439
|
+
"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",
|
|
2440
|
+
className
|
|
2441
|
+
),
|
|
2442
|
+
...props
|
|
2443
|
+
}
|
|
2444
|
+
);
|
|
2445
|
+
}
|
|
2446
|
+
function SheetContent({
|
|
2447
|
+
className,
|
|
2448
|
+
children,
|
|
2449
|
+
side = "right",
|
|
2450
|
+
...props
|
|
2451
|
+
}) {
|
|
2452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(SheetPortal, { children: [
|
|
2453
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(SheetOverlay, {}),
|
|
2454
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
2455
|
+
import_radix_ui11.Dialog.Content,
|
|
2456
|
+
{
|
|
2457
|
+
"data-slot": "sheet-content",
|
|
2458
|
+
className: cn(
|
|
2459
|
+
"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",
|
|
2460
|
+
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",
|
|
2461
|
+
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",
|
|
2462
|
+
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",
|
|
2463
|
+
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",
|
|
2464
|
+
className
|
|
2465
|
+
),
|
|
2466
|
+
...props,
|
|
2467
|
+
children: [
|
|
2468
|
+
children,
|
|
2469
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_radix_ui11.Dialog.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: [
|
|
2470
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_lucide_react17.XIcon, { className: "size-4" }),
|
|
2471
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)("span", { className: "sr-only", children: "Close" })
|
|
2472
|
+
] })
|
|
2473
|
+
]
|
|
2474
|
+
}
|
|
2475
|
+
)
|
|
2476
|
+
] });
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
// src/components/layouts/app-content.tsx
|
|
2480
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
2481
|
+
var AppContentContext = (0, import_react3.createContext)(false);
|
|
2482
|
+
var splitRatioClasses = {
|
|
2483
|
+
"one-half": ["w-1/2", "w-1/2"],
|
|
2484
|
+
"one-third": ["w-1/3", "w-2/3"],
|
|
2485
|
+
"two-third": ["w-2/3", "w-1/3"],
|
|
2486
|
+
"one-fourth": ["w-1/4", "w-3/4"],
|
|
2487
|
+
"three-fourth": ["w-3/4", "w-1/4"],
|
|
2488
|
+
"one-fifth": ["w-1/5", "w-4/5"],
|
|
2489
|
+
"four-fifth": ["w-4/5", "w-1/5"]
|
|
2490
|
+
};
|
|
2491
|
+
var paddingClasses2 = {
|
|
2492
|
+
none: "p-0",
|
|
2493
|
+
tight: "p-2",
|
|
2494
|
+
default: "p-4",
|
|
2495
|
+
loose: "p-6"
|
|
2496
|
+
};
|
|
2497
|
+
var getContainerSheetClasses = (side, width) => {
|
|
2498
|
+
const [contentWidth, sheetWidth] = splitRatioClasses[width];
|
|
2499
|
+
return {
|
|
2500
|
+
container: "inset-y-0 z-50 transition-all duration-500 ease-in-out",
|
|
2501
|
+
content: cn(
|
|
2502
|
+
"h-full bg-background transition-all duration-500 ease-in-out",
|
|
2503
|
+
side === "right" ? "border-l" : "border-r"
|
|
2504
|
+
),
|
|
2505
|
+
transform: side === "right" ? "translate-x-full" : "-translate-x-full",
|
|
2506
|
+
transformOpen: "translate-x-0",
|
|
2507
|
+
contentPushClass: side === "right" ? contentWidth : sheetWidth,
|
|
2508
|
+
sheetPushClass: side === "right" ? sheetWidth : contentWidth
|
|
2509
|
+
};
|
|
2510
|
+
};
|
|
2511
|
+
var baseClasses = "flex flex-col overflow-hidden rounded-2xl relative";
|
|
2512
|
+
var variantClasses = {
|
|
2513
|
+
default: "bg-background",
|
|
2514
|
+
card: "bg-background shadow-sm border",
|
|
2515
|
+
border: "bg-background border-2",
|
|
2516
|
+
transparent: "bg-transparent"
|
|
2517
|
+
};
|
|
2518
|
+
var AppContent = (props) => {
|
|
2519
|
+
const {
|
|
2520
|
+
children,
|
|
2521
|
+
className,
|
|
2522
|
+
variant = "default",
|
|
2523
|
+
layout = "full",
|
|
2524
|
+
header,
|
|
2525
|
+
footer,
|
|
2526
|
+
headerClassName,
|
|
2527
|
+
footerClassName,
|
|
2528
|
+
parentContainer = false,
|
|
2529
|
+
padding = parentContainer ? "none" : "tight"
|
|
2530
|
+
} = props;
|
|
2531
|
+
const isNested = (0, import_react3.useContext)(AppContentContext);
|
|
2532
|
+
const [internalSheetOpen, setInternalSheetOpen] = (0, import_react3.useState)(false);
|
|
2533
|
+
const contentWrapper = import_react3.default.useCallback(
|
|
2534
|
+
(content) => /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn(
|
|
2535
|
+
"flex-1 overflow-auto h-full no-scrollbar",
|
|
2536
|
+
parentContainer && "flex",
|
|
2537
|
+
!parentContainer && paddingClasses2[padding]
|
|
2538
|
+
), children: content }),
|
|
2539
|
+
[padding, parentContainer]
|
|
2540
|
+
);
|
|
2541
|
+
const renderContent = () => {
|
|
2542
|
+
switch (layout) {
|
|
2543
|
+
case "split": {
|
|
2544
|
+
const { splitRatio = "three-fourth", reverse = false } = props;
|
|
2545
|
+
if (!Array.isArray(children) || children.length !== 2) {
|
|
2546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex items-center justify-center h-full text-red-500", children: 'Error: AppContent with layout="split" requires exactly 2 children' });
|
|
2547
|
+
}
|
|
2548
|
+
const [leftClass, rightClass] = splitRatioClasses[splitRatio];
|
|
2549
|
+
const [firstChild, secondChild] = reverse ? [children[1], children[0]] : [children[0], children[1]];
|
|
2550
|
+
const [firstClass, secondClass] = reverse ? [rightClass, leftClass] : [leftClass, rightClass];
|
|
2551
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex h-full gap-2", children: [
|
|
2552
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn(firstClass, "overflow-auto"), children: contentWrapper(firstChild) }),
|
|
2553
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn(secondClass, "overflow-auto"), children: contentWrapper(secondChild) })
|
|
2554
|
+
] });
|
|
2555
|
+
}
|
|
2556
|
+
case "with-sheet": {
|
|
2557
|
+
const {
|
|
2558
|
+
sheetContent,
|
|
2559
|
+
sheetWidth = "four-fifth",
|
|
2560
|
+
sheetSide = "right",
|
|
2561
|
+
sheetMode = "container",
|
|
2562
|
+
sheetTrigger,
|
|
2563
|
+
sheetClassName,
|
|
2564
|
+
isSheetOpen,
|
|
2565
|
+
onSheetOpenChange,
|
|
2566
|
+
showSheetOverlay = true,
|
|
2567
|
+
disableOverlay = true
|
|
2568
|
+
} = props;
|
|
2569
|
+
const isControlled = isSheetOpen !== void 0;
|
|
2570
|
+
const sheetOpen = isControlled ? isSheetOpen : internalSheetOpen;
|
|
2571
|
+
const setSheetOpen = isControlled ? onSheetOpenChange : setInternalSheetOpen;
|
|
2572
|
+
if (sheetMode === "container") {
|
|
2573
|
+
const sheetClasses = getContainerSheetClasses(sheetSide, sheetWidth);
|
|
2574
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn(
|
|
2575
|
+
"flex relative flex-1 overflow-hidden",
|
|
2576
|
+
sheetOpen && disableOverlay && ["left", "right"].includes(sheetSide)
|
|
2577
|
+
), children: [
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn(
|
|
2579
|
+
"h-full overflow-auto transition-all duration-500",
|
|
2580
|
+
sheetOpen && disableOverlay && ["left", "right"].includes(sheetSide) ? sheetClasses.contentPushClass : "w-full",
|
|
2581
|
+
sheetOpen && disableOverlay && "overflow-y-auto overflow-x-hidden"
|
|
2582
|
+
), children: [
|
|
2583
|
+
sheetTrigger && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { onClick: () => setSheetOpen?.(!sheetOpen), children: sheetTrigger }),
|
|
2584
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn("h-full", !parentContainer && paddingClasses2[padding]), children })
|
|
2585
|
+
] }),
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2587
|
+
"div",
|
|
2588
|
+
{
|
|
2589
|
+
className: cn(
|
|
2590
|
+
sheetClasses.container,
|
|
2591
|
+
"transition-all duration-500 ease-in-out",
|
|
2592
|
+
sheetOpen && disableOverlay && ["left", "right"].includes(sheetSide) ? cn(sheetClasses.sheetPushClass, "overflow-y-auto") : sheetOpen ? sheetClasses.transformOpen : cn(sheetClasses.transform, "hidden"),
|
|
2593
|
+
"overflow-y-auto"
|
|
2594
|
+
),
|
|
2595
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: cn(sheetClasses.content, sheetClassName, "h-full"), children: sheetContent })
|
|
2596
|
+
}
|
|
2597
|
+
),
|
|
2598
|
+
sheetOpen && showSheetOverlay && !disableOverlay && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2599
|
+
"div",
|
|
2600
|
+
{
|
|
2601
|
+
className: cn(
|
|
2602
|
+
"absolute inset-0 bg-secondary/20 z-40",
|
|
2603
|
+
"transition-opacity duration-500 ease-in-out",
|
|
2604
|
+
"opacity-0",
|
|
2605
|
+
sheetOpen ? "opacity-100" : "opacity-0"
|
|
2606
|
+
),
|
|
2607
|
+
onClick: () => setSheetOpen?.(false)
|
|
2608
|
+
}
|
|
2609
|
+
)
|
|
2610
|
+
] });
|
|
2611
|
+
}
|
|
2612
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(Sheet, { open: sheetOpen, onOpenChange: setSheetOpen, children: [
|
|
2613
|
+
sheetTrigger && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(SheetTrigger, { asChild: true, children: sheetTrigger }),
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(SheetPortal, { children: [
|
|
2615
|
+
showSheetOverlay && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(SheetOverlay, { className: "fixed inset-0 bg-secondary/50 z-50" }),
|
|
2616
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2617
|
+
SheetContent,
|
|
2618
|
+
{
|
|
2619
|
+
side: sheetSide,
|
|
2620
|
+
className: cn(
|
|
2621
|
+
"fixed bg-background border",
|
|
2622
|
+
"transition-all duration-500 ease-in-out",
|
|
2623
|
+
splitRatioClasses[sheetWidth][1],
|
|
2624
|
+
sheetClassName
|
|
2625
|
+
),
|
|
2626
|
+
children: sheetContent
|
|
2627
|
+
}
|
|
2628
|
+
)
|
|
2629
|
+
] })
|
|
2630
|
+
] });
|
|
2631
|
+
}
|
|
2632
|
+
default:
|
|
2633
|
+
return contentWrapper(children);
|
|
2634
|
+
}
|
|
2635
|
+
};
|
|
2636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(AppContentContext.Provider, { value: true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: cn(
|
|
2637
|
+
baseClasses,
|
|
2638
|
+
variantClasses[variant],
|
|
2639
|
+
paddingClasses2[padding],
|
|
2640
|
+
isNested && "flex-1",
|
|
2641
|
+
parentContainer && "h-full",
|
|
2642
|
+
!parentContainer && "rounded-2xl",
|
|
2643
|
+
className
|
|
2644
|
+
), children: [
|
|
2645
|
+
header && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2646
|
+
"div",
|
|
2647
|
+
{
|
|
2648
|
+
className: cn(
|
|
2649
|
+
"border-b",
|
|
2650
|
+
headerClassName,
|
|
2651
|
+
variant === "card" && !parentContainer && "rounded-t-2xl",
|
|
2652
|
+
variant === "border" && "border-b-2",
|
|
2653
|
+
paddingClasses2[padding]
|
|
2654
|
+
),
|
|
2655
|
+
children: header
|
|
2656
|
+
}
|
|
2657
|
+
),
|
|
2658
|
+
renderContent(),
|
|
2659
|
+
footer && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
2660
|
+
"div",
|
|
2661
|
+
{
|
|
2662
|
+
className: cn(
|
|
2663
|
+
"border-t",
|
|
2664
|
+
footerClassName,
|
|
2665
|
+
variant === "card" && !parentContainer && "rounded-b-2xl",
|
|
2666
|
+
variant === "border" && "border-t-2",
|
|
2667
|
+
paddingClasses2[padding]
|
|
2668
|
+
),
|
|
2669
|
+
children: footer
|
|
2670
|
+
}
|
|
2671
|
+
)
|
|
2672
|
+
] }) });
|
|
2673
|
+
};
|
|
2674
|
+
|
|
2675
|
+
// src/components/layouts/app-footer.tsx
|
|
2676
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
2677
|
+
var AppFooter = ({
|
|
2678
|
+
className,
|
|
2679
|
+
columns = [],
|
|
2680
|
+
meta = { title: "" }
|
|
2681
|
+
}) => {
|
|
2682
|
+
const actionsColumn = {
|
|
2683
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "flex items-center gap-4 p-2", children: meta.secondaryActions }),
|
|
2684
|
+
align: "right",
|
|
2685
|
+
width: "fill"
|
|
2686
|
+
};
|
|
2687
|
+
const allColumns = [
|
|
2688
|
+
...columns.filter((col) => col !== void 0),
|
|
2689
|
+
actionsColumn
|
|
2690
|
+
];
|
|
2691
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: cn("flex items-center w-full gap-4", className), children: allColumns.map((column, index) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
2692
|
+
"div",
|
|
2693
|
+
{
|
|
2694
|
+
className: cn(
|
|
2695
|
+
"flex items-center h-full",
|
|
2696
|
+
column.className,
|
|
2697
|
+
{
|
|
2698
|
+
"justify-start": column.align === "left",
|
|
2699
|
+
"justify-center": column.align === "center",
|
|
2700
|
+
"justify-end": column.align === "right",
|
|
2701
|
+
"flex-1": column.width === "fill"
|
|
2702
|
+
}
|
|
2703
|
+
),
|
|
2704
|
+
children: column.content
|
|
2705
|
+
},
|
|
2706
|
+
index
|
|
2707
|
+
)) });
|
|
2708
|
+
};
|
|
2709
|
+
|
|
2710
|
+
// src/components/layouts/factories.tsx
|
|
2711
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
2712
|
+
function createLayoutComponents({
|
|
2713
|
+
useTypedAppMeta
|
|
2714
|
+
}) {
|
|
2715
|
+
const AppHeader2 = (props) => {
|
|
2716
|
+
const { meta } = useTypedAppMeta();
|
|
2717
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AppHeader, { ...props, meta });
|
|
2718
|
+
};
|
|
2719
|
+
const AppFooter2 = (props) => {
|
|
2720
|
+
const { meta } = useTypedAppMeta();
|
|
2721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AppFooter, { ...props, meta });
|
|
2722
|
+
};
|
|
2723
|
+
const AppContent2 = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AppContent, { ...props });
|
|
2724
|
+
const AppContainer2 = (props) => /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(AppContainer, { ...props });
|
|
2725
|
+
return {
|
|
2726
|
+
AppHeader: AppHeader2,
|
|
2727
|
+
AppFooter: AppFooter2,
|
|
2728
|
+
AppContent: AppContent2,
|
|
2729
|
+
AppContainer: AppContainer2
|
|
2730
|
+
};
|
|
2731
|
+
}
|
|
2732
|
+
|
|
2733
|
+
// src/context/app-meta/context.tsx
|
|
2734
|
+
var import_react4 = require("react");
|
|
2735
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
2736
|
+
var AppMetaContext = (0, import_react4.createContext)(void 0);
|
|
2737
|
+
var AppMetaProvider = ({ children }) => {
|
|
2738
|
+
const [meta, setMetaState] = (0, import_react4.useState)({
|
|
2739
|
+
title: "",
|
|
2740
|
+
description: "",
|
|
2741
|
+
breadcrumbs: []
|
|
2742
|
+
});
|
|
2743
|
+
const setMeta = (0, import_react4.useCallback)((partialMeta) => {
|
|
2744
|
+
setMetaState((prev) => ({ ...prev, ...partialMeta }));
|
|
2745
|
+
}, []);
|
|
2746
|
+
const resetMeta = (0, import_react4.useCallback)(() => {
|
|
2747
|
+
setMetaState({
|
|
2748
|
+
title: "",
|
|
2749
|
+
description: "",
|
|
2750
|
+
breadcrumbs: []
|
|
2751
|
+
});
|
|
2752
|
+
}, []);
|
|
2753
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AppMetaContext.Provider, { value: { meta, setMeta, resetMeta }, children });
|
|
2754
|
+
};
|
|
2755
|
+
function createTypedAppMetaContext() {
|
|
2756
|
+
const TypedAppMetaContext = (0, import_react4.createContext)(void 0);
|
|
2757
|
+
const TypedAppMetaProvider = ({ children }) => {
|
|
2758
|
+
const [meta, setMetaState] = (0, import_react4.useState)({
|
|
2759
|
+
title: "",
|
|
2760
|
+
description: "",
|
|
2761
|
+
breadcrumbs: []
|
|
2762
|
+
});
|
|
2763
|
+
const setMeta = (0, import_react4.useCallback)((partialMeta) => {
|
|
2764
|
+
setMetaState((prev) => ({ ...prev, ...partialMeta }));
|
|
2765
|
+
}, []);
|
|
2766
|
+
const resetMeta = (0, import_react4.useCallback)(() => {
|
|
2767
|
+
setMetaState({
|
|
2768
|
+
title: "",
|
|
2769
|
+
description: "",
|
|
2770
|
+
breadcrumbs: []
|
|
2771
|
+
});
|
|
2772
|
+
}, []);
|
|
2773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(TypedAppMetaContext.Provider, { value: { meta, setMeta, resetMeta }, children });
|
|
2774
|
+
};
|
|
2775
|
+
const useTypedAppMeta = () => {
|
|
2776
|
+
const context = (0, import_react4.useContext)(TypedAppMetaContext);
|
|
2777
|
+
if (!context) {
|
|
2778
|
+
throw new Error("useTypedAppMeta must be used within a TypedAppMetaProvider");
|
|
2779
|
+
}
|
|
2780
|
+
return context;
|
|
2781
|
+
};
|
|
2782
|
+
return { TypedAppMetaProvider, useTypedAppMeta, TypedAppMetaContext };
|
|
2783
|
+
}
|
|
2784
|
+
|
|
2785
|
+
// src/context/app-meta/hooks.ts
|
|
2786
|
+
var import_react5 = require("react");
|
|
2787
|
+
function createPageTemplateHook({
|
|
2788
|
+
useTypedAppMeta
|
|
2789
|
+
}) {
|
|
2790
|
+
function usePageTemplate(options) {
|
|
2791
|
+
const { setMeta, resetMeta } = useTypedAppMeta();
|
|
2792
|
+
const memoizedOptions = (0, import_react5.useMemo)(() => options, [
|
|
2793
|
+
options.title,
|
|
2794
|
+
options.description,
|
|
2795
|
+
options.breadcrumbs,
|
|
2796
|
+
options.primaryActions,
|
|
2797
|
+
options.secondaryActions,
|
|
2798
|
+
options.backAction,
|
|
2799
|
+
options.pagination,
|
|
2800
|
+
options.metadata,
|
|
2801
|
+
options.status
|
|
2802
|
+
]);
|
|
2803
|
+
(0, import_react5.useEffect)(() => {
|
|
2804
|
+
setMeta(memoizedOptions);
|
|
2805
|
+
return () => resetMeta();
|
|
2806
|
+
}, [memoizedOptions, setMeta, resetMeta]);
|
|
2807
|
+
}
|
|
2808
|
+
return { usePageTemplate };
|
|
2809
|
+
}
|
|
2810
|
+
|
|
2811
|
+
// src/components/general.tsx
|
|
2812
|
+
var import_react6 = require("react");
|
|
2813
|
+
var import_lucide_react18 = require("lucide-react");
|
|
2814
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
2815
|
+
var GeneralHelper = class {
|
|
2816
|
+
static currencyFormatter = new Intl.NumberFormat("en-IN", {
|
|
2817
|
+
style: "currency",
|
|
2818
|
+
currency: "INR",
|
|
2819
|
+
maximumFractionDigits: 2
|
|
2820
|
+
});
|
|
2821
|
+
static compactFormatter = new Intl.NumberFormat("en-IN", {
|
|
2822
|
+
style: "currency",
|
|
2823
|
+
currency: "INR",
|
|
2824
|
+
notation: "compact",
|
|
2825
|
+
maximumFractionDigits: 1
|
|
2826
|
+
});
|
|
2827
|
+
static MONTH_NAMES_SHORT = [
|
|
2828
|
+
"Jan",
|
|
2829
|
+
"Feb",
|
|
2830
|
+
"Mar",
|
|
2831
|
+
"Apr",
|
|
2832
|
+
"May",
|
|
2833
|
+
"Jun",
|
|
2834
|
+
"Jul",
|
|
2835
|
+
"Aug",
|
|
2836
|
+
"Sep",
|
|
2837
|
+
"Oct",
|
|
2838
|
+
"Nov",
|
|
2839
|
+
"Dec"
|
|
2840
|
+
];
|
|
2841
|
+
/**
|
|
2842
|
+
* Copies text to clipboard
|
|
2843
|
+
* @param text Text to copy
|
|
2844
|
+
* @returns Promise that resolves when copy is complete
|
|
2845
|
+
*/
|
|
2846
|
+
static async copyToClipboard(text) {
|
|
2847
|
+
if (!text) return;
|
|
2848
|
+
try {
|
|
2849
|
+
await navigator.clipboard.writeText(text);
|
|
2850
|
+
} catch (error) {
|
|
2851
|
+
console.error("Failed to copy text:", error);
|
|
2852
|
+
throw error;
|
|
2853
|
+
}
|
|
2854
|
+
}
|
|
2855
|
+
/**
|
|
2856
|
+
* React component for copy to clipboard functionality
|
|
2857
|
+
*/
|
|
2858
|
+
static CopyToClipboard = ({
|
|
2859
|
+
text,
|
|
2860
|
+
children,
|
|
2861
|
+
className,
|
|
2862
|
+
size = "icon",
|
|
2863
|
+
variant = "ghost"
|
|
2864
|
+
}) => {
|
|
2865
|
+
const [isCopied, setIsCopied] = (0, import_react6.useState)(false);
|
|
2866
|
+
const [isLoading, setIsLoading] = (0, import_react6.useState)(false);
|
|
2867
|
+
const handleCopy = async () => {
|
|
2868
|
+
if (!text || isLoading) return;
|
|
2869
|
+
setIsLoading(true);
|
|
2870
|
+
try {
|
|
2871
|
+
await this.copyToClipboard(text);
|
|
2872
|
+
setIsCopied(true);
|
|
2873
|
+
setTimeout(() => setIsCopied(false), 2e3);
|
|
2874
|
+
} catch (error) {
|
|
2875
|
+
console.error("Failed to copy text:", error);
|
|
2876
|
+
} finally {
|
|
2877
|
+
setIsLoading(false);
|
|
2878
|
+
}
|
|
2879
|
+
};
|
|
2880
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(Tooltip, { children: [
|
|
2881
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
2882
|
+
Button,
|
|
2883
|
+
{
|
|
2884
|
+
variant,
|
|
2885
|
+
size,
|
|
2886
|
+
className: cn(
|
|
2887
|
+
size === "icon" && "size-6",
|
|
2888
|
+
className
|
|
2889
|
+
),
|
|
2890
|
+
onClick: handleCopy,
|
|
2891
|
+
disabled: isLoading || !text,
|
|
2892
|
+
children: isLoading ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.Loader2Icon, { className: "animate-spin" }) : isCopied ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.Check, { className: "h-3 w-3" }) : children ? children : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_lucide_react18.Copy, { className: "h-3 w-3" })
|
|
2893
|
+
}
|
|
2894
|
+
) }),
|
|
2895
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(TooltipContent, { children: isCopied ? "Copied!" : isLoading ? "Copying..." : "Copy to clipboard" })
|
|
2896
|
+
] });
|
|
2897
|
+
};
|
|
2898
|
+
/**
|
|
2899
|
+
* Formats a number as Indian Rupees (INR)
|
|
2900
|
+
* @param amount Amount to format
|
|
2901
|
+
* @param options Formatting options
|
|
2902
|
+
* @returns Formatted currency string
|
|
2903
|
+
*/
|
|
2904
|
+
static formatINR(amount, options = {}) {
|
|
2905
|
+
const { prefix = "", suffix = "", withSymbol = true, compact = false } = options;
|
|
2906
|
+
if (typeof amount !== "number" || isNaN(amount)) {
|
|
2907
|
+
return `${prefix}${withSymbol ? "\u20B9 " : ""}0.00${suffix}`;
|
|
2908
|
+
}
|
|
2909
|
+
const isNegative = amount < 0;
|
|
2910
|
+
const absoluteAmount = Math.abs(amount);
|
|
2911
|
+
const formatter = compact && absoluteAmount >= 1e5 ? this.compactFormatter : this.currencyFormatter;
|
|
2912
|
+
const formatted = formatter.format(absoluteAmount).replace("\u20B9", "");
|
|
2913
|
+
return `${prefix}${isNegative ? "- " : ""}${withSymbol ? "\u20B9 " : ""}${formatted}${suffix}`;
|
|
2914
|
+
}
|
|
2915
|
+
/**
|
|
2916
|
+
* Formats a date according to specified options
|
|
2917
|
+
* @param input Date input (string, number, or Date object)
|
|
2918
|
+
* @param options Formatting options
|
|
2919
|
+
* @returns Formatted date string
|
|
2920
|
+
*/
|
|
2921
|
+
static formatDate(input, options = {}) {
|
|
2922
|
+
const { format = "dd-mm-yyyy", separator = "-" } = options;
|
|
2923
|
+
const dateObj = new Date(input);
|
|
2924
|
+
if (isNaN(dateObj.getTime())) return "";
|
|
2925
|
+
const dd = String(dateObj.getDate()).padStart(2, "0");
|
|
2926
|
+
const mm = String(dateObj.getMonth() + 1).padStart(2, "0");
|
|
2927
|
+
const mmm = this.MONTH_NAMES_SHORT[dateObj.getMonth()];
|
|
2928
|
+
const yyyy = dateObj.getFullYear();
|
|
2929
|
+
switch (format) {
|
|
2930
|
+
case "dd-mmm-yyyy":
|
|
2931
|
+
return `${dd}${separator}${mmm}${separator}${yyyy}`;
|
|
2932
|
+
case "iso":
|
|
2933
|
+
return dateObj.toISOString().split("T")[0];
|
|
2934
|
+
case "long":
|
|
2935
|
+
return dateObj.toLocaleDateString("en-IN", {
|
|
2936
|
+
year: "numeric",
|
|
2937
|
+
month: "long",
|
|
2938
|
+
day: "numeric"
|
|
2939
|
+
});
|
|
2940
|
+
case "short":
|
|
2941
|
+
return dateObj.toLocaleDateString("en-IN");
|
|
2942
|
+
default:
|
|
2943
|
+
return `${dd}${separator}${mm}${separator}${yyyy}`;
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
static toProperCase(text) {
|
|
2947
|
+
if (!text) return "";
|
|
2948
|
+
return text.toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
2949
|
+
}
|
|
2950
|
+
/**
|
|
2951
|
+
* Advanced proper case conversion that handles hyphenated words and apostrophes
|
|
2952
|
+
* @param text Text to convert
|
|
2953
|
+
* @returns Text in proper case with special handling
|
|
2954
|
+
*/
|
|
2955
|
+
static toProperCaseAdvanced(text) {
|
|
2956
|
+
if (!text) return "";
|
|
2957
|
+
return text.toLowerCase().split(/(\s+|['-])/).map((part, index, array) => {
|
|
2958
|
+
if (["-", "'", " "].includes(part) || index > 0 && ["-", "'"].includes(array[index - 1])) {
|
|
2959
|
+
return part;
|
|
2960
|
+
}
|
|
2961
|
+
return part.charAt(0).toUpperCase() + part.slice(1);
|
|
2962
|
+
}).join("");
|
|
2963
|
+
}
|
|
2964
|
+
static StatusBadge = ({
|
|
2965
|
+
status,
|
|
2966
|
+
className,
|
|
2967
|
+
showDot = true,
|
|
2968
|
+
capitalize = true,
|
|
2969
|
+
size = "md",
|
|
2970
|
+
variant = "outline",
|
|
2971
|
+
customColors,
|
|
2972
|
+
icon,
|
|
2973
|
+
trueMessage = "active",
|
|
2974
|
+
falseMessage = "inactive"
|
|
2975
|
+
}) => {
|
|
2976
|
+
const normalizedStatus = typeof status === "boolean" ? status ? trueMessage : falseMessage : typeof status === "number" ? status > 0 ? trueMessage : falseMessage : status.toLowerCase();
|
|
2977
|
+
const statusConfig = {
|
|
2978
|
+
active: {
|
|
2979
|
+
label: "active",
|
|
2980
|
+
solid: {
|
|
2981
|
+
bg: "bg-emerald-500",
|
|
2982
|
+
text: "text-white",
|
|
2983
|
+
border: "border-emerald-600",
|
|
2984
|
+
dot: "bg-white"
|
|
2985
|
+
},
|
|
2986
|
+
outline: {
|
|
2987
|
+
bg: "bg-emerald-50",
|
|
2988
|
+
text: "text-emerald-700",
|
|
2989
|
+
border: "border-emerald-100",
|
|
2990
|
+
dot: "bg-emerald-500"
|
|
2991
|
+
},
|
|
2992
|
+
subtle: {
|
|
2993
|
+
bg: "bg-emerald-50",
|
|
2994
|
+
text: "text-emerald-700",
|
|
2995
|
+
border: "border-transparent",
|
|
2996
|
+
dot: "bg-emerald-500"
|
|
2997
|
+
}
|
|
2998
|
+
},
|
|
2999
|
+
pending: {
|
|
3000
|
+
label: "pending",
|
|
3001
|
+
solid: {
|
|
3002
|
+
bg: "bg-amber-500",
|
|
3003
|
+
text: "text-white",
|
|
3004
|
+
border: "border-amber-600",
|
|
3005
|
+
dot: "bg-white"
|
|
3006
|
+
},
|
|
3007
|
+
outline: {
|
|
3008
|
+
bg: "bg-amber-50",
|
|
3009
|
+
text: "text-amber-700",
|
|
3010
|
+
border: "border-amber-100",
|
|
3011
|
+
dot: "bg-amber-500"
|
|
3012
|
+
},
|
|
3013
|
+
subtle: {
|
|
3014
|
+
bg: "bg-amber-50",
|
|
3015
|
+
text: "text-amber-700",
|
|
3016
|
+
border: "border-transparent",
|
|
3017
|
+
dot: "bg-amber-500"
|
|
3018
|
+
}
|
|
3019
|
+
},
|
|
3020
|
+
inactive: {
|
|
3021
|
+
label: "inactive",
|
|
3022
|
+
solid: {
|
|
3023
|
+
bg: "bg-rose-500",
|
|
3024
|
+
text: "text-white",
|
|
3025
|
+
border: "border-rose-600",
|
|
3026
|
+
dot: "bg-white"
|
|
3027
|
+
},
|
|
3028
|
+
outline: {
|
|
3029
|
+
bg: "bg-rose-50",
|
|
3030
|
+
text: "text-rose-700",
|
|
3031
|
+
border: "border-rose-100",
|
|
3032
|
+
dot: "bg-rose-500"
|
|
3033
|
+
},
|
|
3034
|
+
subtle: {
|
|
3035
|
+
bg: "bg-rose-50",
|
|
3036
|
+
text: "text-rose-700",
|
|
3037
|
+
border: "border-transparent",
|
|
3038
|
+
dot: "bg-rose-500"
|
|
3039
|
+
}
|
|
3040
|
+
},
|
|
3041
|
+
draft: {
|
|
3042
|
+
label: "draft",
|
|
3043
|
+
solid: {
|
|
3044
|
+
bg: "bg-gray-500",
|
|
3045
|
+
text: "text-white",
|
|
3046
|
+
border: "border-gray-600",
|
|
3047
|
+
dot: "bg-white"
|
|
3048
|
+
},
|
|
3049
|
+
outline: {
|
|
3050
|
+
bg: "bg-gray-50",
|
|
3051
|
+
text: "text-gray-700",
|
|
3052
|
+
border: "border-gray-100",
|
|
3053
|
+
dot: "bg-gray-500"
|
|
3054
|
+
},
|
|
3055
|
+
subtle: {
|
|
3056
|
+
bg: "bg-gray-50",
|
|
3057
|
+
text: "text-gray-700",
|
|
3058
|
+
border: "border-transparent",
|
|
3059
|
+
dot: "bg-gray-500"
|
|
3060
|
+
}
|
|
3061
|
+
},
|
|
3062
|
+
completed: {
|
|
3063
|
+
label: "completed",
|
|
3064
|
+
solid: {
|
|
3065
|
+
bg: "bg-indigo-500",
|
|
3066
|
+
text: "text-white",
|
|
3067
|
+
border: "border-indigo-600",
|
|
3068
|
+
dot: "bg-white"
|
|
3069
|
+
},
|
|
3070
|
+
outline: {
|
|
3071
|
+
bg: "bg-indigo-50",
|
|
3072
|
+
text: "text-indigo-700",
|
|
3073
|
+
border: "border-indigo-100",
|
|
3074
|
+
dot: "bg-indigo-500"
|
|
3075
|
+
},
|
|
3076
|
+
subtle: {
|
|
3077
|
+
bg: "bg-indigo-50",
|
|
3078
|
+
text: "text-indigo-700",
|
|
3079
|
+
border: "border-transparent",
|
|
3080
|
+
dot: "bg-indigo-500"
|
|
3081
|
+
}
|
|
3082
|
+
}
|
|
3083
|
+
};
|
|
3084
|
+
const config = statusConfig[normalizedStatus.toLowerCase()] || statusConfig.inactive;
|
|
3085
|
+
const colors = customColors || config[variant];
|
|
3086
|
+
const sizeClasses = {
|
|
3087
|
+
sm: "text-xs px-2 py-0.5",
|
|
3088
|
+
md: "text-xs px-2.5 py-0.5",
|
|
3089
|
+
lg: "text-sm px-3 py-1"
|
|
3090
|
+
};
|
|
3091
|
+
const displayText = capitalize ? normalizedStatus.charAt(0).toUpperCase() + normalizedStatus.slice(1) : normalizedStatus;
|
|
3092
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { className: "flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
3093
|
+
"span",
|
|
3094
|
+
{
|
|
3095
|
+
className: cn(
|
|
3096
|
+
"inline-flex items-center gap-1.5 rounded-full border font-medium",
|
|
3097
|
+
colors.bg,
|
|
3098
|
+
colors.text,
|
|
3099
|
+
colors.border,
|
|
3100
|
+
sizeClasses[size],
|
|
3101
|
+
className
|
|
3102
|
+
),
|
|
3103
|
+
children: [
|
|
3104
|
+
showDot && (icon ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: "flex items-center", children: icon }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
3105
|
+
"span",
|
|
3106
|
+
{
|
|
3107
|
+
className: cn("size-2 rounded-full", colors.dot),
|
|
3108
|
+
"aria-hidden": "true"
|
|
3109
|
+
}
|
|
3110
|
+
)),
|
|
3111
|
+
displayText
|
|
3112
|
+
]
|
|
3113
|
+
}
|
|
3114
|
+
) });
|
|
3115
|
+
};
|
|
3116
|
+
};
|
|
3117
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
3118
|
+
0 && (module.exports = {
|
|
3119
|
+
AppMetaProvider,
|
|
3120
|
+
DataTable,
|
|
3121
|
+
DataTableActionBar,
|
|
3122
|
+
DataTableActionBarAction,
|
|
3123
|
+
DataTableActionBarSelection,
|
|
3124
|
+
DataTemplate,
|
|
3125
|
+
DataTemplateActionBar,
|
|
3126
|
+
DataTemplateActionBarAction,
|
|
3127
|
+
DataTemplateActionBarSelection,
|
|
3128
|
+
GeneralHelper,
|
|
3129
|
+
createLayoutComponents,
|
|
3130
|
+
createPageTemplateHook,
|
|
3131
|
+
createTypedAppMetaContext
|
|
3132
|
+
});
|
|
3133
|
+
//# sourceMappingURL=index.cjs.map
|