@juv/codego-react-ui 3.4.6 → 3.4.8
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/dist/index.cjs +686 -116
- package/dist/index.d.cts +109 -21
- package/dist/index.d.ts +109 -21
- package/dist/index.global.js +743 -160
- package/dist/index.js +717 -147
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -5783,13 +5783,79 @@ function FileUpload({
|
|
|
5783
5783
|
}
|
|
5784
5784
|
|
|
5785
5785
|
// src/components/ui/repeater.tsx
|
|
5786
|
-
import { Plus as Plus3, Trash2, GripVertical as GripVertical3 } from "lucide-react";
|
|
5786
|
+
import { Plus as Plus3, Trash2, GripVertical as GripVertical3, Paperclip } from "lucide-react";
|
|
5787
5787
|
import { jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
5788
|
+
function RepeaterFieldRenderer({
|
|
5789
|
+
field,
|
|
5790
|
+
value,
|
|
5791
|
+
onChange
|
|
5792
|
+
}) {
|
|
5793
|
+
if (field.type === "image") {
|
|
5794
|
+
return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-1.5", children: [
|
|
5795
|
+
field.label && /* @__PURE__ */ jsx29("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
|
|
5796
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-3", children: [
|
|
5797
|
+
value && /* @__PURE__ */ jsx29("img", { src: value, alt: field.key, className: "h-10 w-10 rounded-lg object-cover ring-1 ring-border shrink-0" }),
|
|
5798
|
+
/* @__PURE__ */ jsx29(
|
|
5799
|
+
Input,
|
|
5800
|
+
{
|
|
5801
|
+
inputMode: "text",
|
|
5802
|
+
value: value ?? "",
|
|
5803
|
+
onChange: (e) => onChange(e.target.value),
|
|
5804
|
+
placeholder: field.placeholder ?? "Image URL"
|
|
5805
|
+
}
|
|
5806
|
+
)
|
|
5807
|
+
] })
|
|
5808
|
+
] });
|
|
5809
|
+
}
|
|
5810
|
+
if (field.type === "attachment") {
|
|
5811
|
+
return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-1.5", children: [
|
|
5812
|
+
field.label && /* @__PURE__ */ jsx29("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
|
|
5813
|
+
/* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
|
|
5814
|
+
value && /* @__PURE__ */ jsxs27(
|
|
5815
|
+
"a",
|
|
5816
|
+
{
|
|
5817
|
+
href: value,
|
|
5818
|
+
target: "_blank",
|
|
5819
|
+
rel: "noopener noreferrer",
|
|
5820
|
+
className: "inline-flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-2.5 py-1 text-xs font-medium text-foreground hover:bg-muted transition-colors shrink-0",
|
|
5821
|
+
children: [
|
|
5822
|
+
/* @__PURE__ */ jsx29(Paperclip, { className: "h-3 w-3" }),
|
|
5823
|
+
String(value).split("/").pop()
|
|
5824
|
+
]
|
|
5825
|
+
}
|
|
5826
|
+
),
|
|
5827
|
+
/* @__PURE__ */ jsx29(
|
|
5828
|
+
Input,
|
|
5829
|
+
{
|
|
5830
|
+
inputMode: "text",
|
|
5831
|
+
value: value ?? "",
|
|
5832
|
+
onChange: (e) => onChange(e.target.value),
|
|
5833
|
+
placeholder: field.placeholder ?? "Attachment URL"
|
|
5834
|
+
}
|
|
5835
|
+
)
|
|
5836
|
+
] })
|
|
5837
|
+
] });
|
|
5838
|
+
}
|
|
5839
|
+
return /* @__PURE__ */ jsxs27("div", { className: "flex flex-col gap-1.5", children: [
|
|
5840
|
+
field.label && /* @__PURE__ */ jsx29("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
|
|
5841
|
+
/* @__PURE__ */ jsx29(
|
|
5842
|
+
Input,
|
|
5843
|
+
{
|
|
5844
|
+
inputMode: "text",
|
|
5845
|
+
value: value ?? "",
|
|
5846
|
+
onChange: (e) => onChange(e.target.value),
|
|
5847
|
+
placeholder: field.placeholder ?? field.key
|
|
5848
|
+
}
|
|
5849
|
+
)
|
|
5850
|
+
] });
|
|
5851
|
+
}
|
|
5788
5852
|
function Repeater({
|
|
5789
5853
|
items,
|
|
5790
5854
|
onAdd,
|
|
5791
5855
|
onRemove,
|
|
5792
5856
|
renderItem,
|
|
5857
|
+
fields,
|
|
5858
|
+
onFieldChange,
|
|
5793
5859
|
addButtonText = "Add Item",
|
|
5794
5860
|
className
|
|
5795
5861
|
}) {
|
|
@@ -5802,7 +5868,15 @@ function Repeater({
|
|
|
5802
5868
|
children: [
|
|
5803
5869
|
/* @__PURE__ */ jsx29("div", { className: "mt-1 cursor-grab text-muted-foreground/30 group-hover:text-muted-foreground/60 transition-colors shrink-0", children: /* @__PURE__ */ jsx29(GripVertical3, { className: "h-4 w-4" }) }),
|
|
5804
5870
|
/* @__PURE__ */ jsx29("div", { className: "mt-1 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-semibold text-primary", children: index + 1 }),
|
|
5805
|
-
/* @__PURE__ */ jsx29("div", { className: "flex-1 min-w-0", children:
|
|
5871
|
+
/* @__PURE__ */ jsx29("div", { className: "flex-1 min-w-0", children: fields ? /* @__PURE__ */ jsx29("div", { className: "grid gap-3", style: { gridTemplateColumns: fields.length > 1 ? `repeat(${Math.min(fields.length, 3)}, minmax(0, 1fr))` : "1fr" }, children: fields.map((f) => /* @__PURE__ */ jsx29(
|
|
5872
|
+
RepeaterFieldRenderer,
|
|
5873
|
+
{
|
|
5874
|
+
field: f,
|
|
5875
|
+
value: item[f.key],
|
|
5876
|
+
onChange: (v) => onFieldChange?.(index, f.key, v)
|
|
5877
|
+
},
|
|
5878
|
+
f.key
|
|
5879
|
+
)) }) : renderItem ? renderItem(item, index) : null }),
|
|
5806
5880
|
/* @__PURE__ */ jsxs27(
|
|
5807
5881
|
Button,
|
|
5808
5882
|
{
|
|
@@ -6284,7 +6358,7 @@ import * as React28 from "react";
|
|
|
6284
6358
|
import { createPortal as createPortal3 } from "react-dom";
|
|
6285
6359
|
import axios3 from "axios";
|
|
6286
6360
|
import { ChevronLeft as ChevronLeft6, ChevronRight as ChevronRight8, Search as Search5, Trash2 as Trash22, ChevronsUpDown, ChevronUp, ChevronDown as ChevronDown4, X as X9, Eye as Eye2, Pencil as Pencil2, Trash as Trash3, Loader2 as Loader22 } from "lucide-react";
|
|
6287
|
-
import { Fragment as
|
|
6361
|
+
import { Fragment as Fragment12, jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
6288
6362
|
function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOverrides, debounce = 300, transform, manual = false, refresh: refreshEnabled = false, refreshInterval = 0, hardReload, onSuccess, onError }) {
|
|
6289
6363
|
const [data, setData] = React28.useState([]);
|
|
6290
6364
|
const [columns, setColumns] = React28.useState([]);
|
|
@@ -6375,8 +6449,14 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
|
|
|
6375
6449
|
goToPage: (page) => setCurrentPage(page),
|
|
6376
6450
|
reload: () => setTick((t) => t + 1),
|
|
6377
6451
|
refresh: () => setTick((t) => t + 1),
|
|
6452
|
+
// Passthrough props
|
|
6378
6453
|
searchValue,
|
|
6379
|
-
onSearchChange: handleSearchChange
|
|
6454
|
+
onSearchChange: handleSearchChange,
|
|
6455
|
+
page: currentPage,
|
|
6456
|
+
onPageChange: (page) => setCurrentPage(page),
|
|
6457
|
+
sort: [],
|
|
6458
|
+
onSortChange: () => {
|
|
6459
|
+
}
|
|
6380
6460
|
};
|
|
6381
6461
|
}
|
|
6382
6462
|
var MODAL_WIDTH = {
|
|
@@ -6434,8 +6514,8 @@ function validateField(field, value) {
|
|
|
6434
6514
|
return null;
|
|
6435
6515
|
}
|
|
6436
6516
|
function FieldRenderer({ field, value, onChange }) {
|
|
6437
|
-
if (field.component) return /* @__PURE__ */ jsx32(
|
|
6438
|
-
if (field.render) return /* @__PURE__ */ jsx32(
|
|
6517
|
+
if (field.component) return /* @__PURE__ */ jsx32(Fragment12, { children: field.component });
|
|
6518
|
+
if (field.render) return /* @__PURE__ */ jsx32(Fragment12, { children: field.render(value, onChange) });
|
|
6439
6519
|
const toLabelValue = (o) => {
|
|
6440
6520
|
if (typeof o === "string") return { label: o, value: o };
|
|
6441
6521
|
if (Array.isArray(o)) return { label: o[0], value: o[1] };
|
|
@@ -6532,6 +6612,28 @@ function FieldRenderer({ field, value, onChange }) {
|
|
|
6532
6612
|
} });
|
|
6533
6613
|
case "repeater": {
|
|
6534
6614
|
const items = Array.isArray(value) ? value : [];
|
|
6615
|
+
if (field.repeaterFields) {
|
|
6616
|
+
const rows = Array.isArray(value) ? value : [];
|
|
6617
|
+
return /* @__PURE__ */ jsx32(
|
|
6618
|
+
Repeater,
|
|
6619
|
+
{
|
|
6620
|
+
items: rows,
|
|
6621
|
+
fields: field.repeaterFields,
|
|
6622
|
+
onAdd: () => {
|
|
6623
|
+
const blank = {};
|
|
6624
|
+
field.repeaterFields.forEach((f) => {
|
|
6625
|
+
blank[f.key] = "";
|
|
6626
|
+
});
|
|
6627
|
+
onChange([...rows, blank]);
|
|
6628
|
+
},
|
|
6629
|
+
onRemove: (i) => onChange(rows.filter((_, idx) => idx !== i)),
|
|
6630
|
+
onFieldChange: (i, key, val) => {
|
|
6631
|
+
const next = rows.map((r, idx) => idx === i ? { ...r, [key]: val } : r);
|
|
6632
|
+
onChange(next);
|
|
6633
|
+
}
|
|
6634
|
+
}
|
|
6635
|
+
);
|
|
6636
|
+
}
|
|
6535
6637
|
return /* @__PURE__ */ jsx32(
|
|
6536
6638
|
Repeater,
|
|
6537
6639
|
{
|
|
@@ -6572,8 +6674,172 @@ function ViewModal({
|
|
|
6572
6674
|
item,
|
|
6573
6675
|
fields,
|
|
6574
6676
|
onClose,
|
|
6575
|
-
width
|
|
6677
|
+
width,
|
|
6678
|
+
grid
|
|
6576
6679
|
}) {
|
|
6680
|
+
const renderViewValue = (f, value) => {
|
|
6681
|
+
const sizeStyle = {
|
|
6682
|
+
...f.width ? { width: typeof f.width === "number" ? `${f.width}px` : f.width } : {},
|
|
6683
|
+
...f.height ? { height: typeof f.height === "number" ? `${f.height}px` : f.height } : {}
|
|
6684
|
+
};
|
|
6685
|
+
const vt = f.viewType ?? f.type;
|
|
6686
|
+
const empty = value === null || value === void 0 || value === "";
|
|
6687
|
+
const dash = /* @__PURE__ */ jsx32("span", { className: "text-muted-foreground italic text-sm", children: "\u2014" });
|
|
6688
|
+
if (f.component) return /* @__PURE__ */ jsx32(Fragment12, { children: f.component });
|
|
6689
|
+
if (f.render) return /* @__PURE__ */ jsx32(Fragment12, { children: f.render(value, () => {
|
|
6690
|
+
}) });
|
|
6691
|
+
switch (vt) {
|
|
6692
|
+
case "image":
|
|
6693
|
+
return empty ? dash : /* @__PURE__ */ jsx32(
|
|
6694
|
+
"img",
|
|
6695
|
+
{
|
|
6696
|
+
src: value,
|
|
6697
|
+
alt: f.label,
|
|
6698
|
+
className: "rounded-xl object-cover ring-1 ring-border",
|
|
6699
|
+
style: { width: sizeStyle.width ?? 128, height: sizeStyle.height ?? 128 }
|
|
6700
|
+
}
|
|
6701
|
+
);
|
|
6702
|
+
case "image-url":
|
|
6703
|
+
return empty ? dash : /* @__PURE__ */ jsx32(
|
|
6704
|
+
"a",
|
|
6705
|
+
{
|
|
6706
|
+
href: value,
|
|
6707
|
+
onClick: (e) => e.preventDefault(),
|
|
6708
|
+
className: "inline-block rounded-xl overflow-hidden ring-1 ring-border hover:ring-primary transition-all",
|
|
6709
|
+
style: { width: sizeStyle.width ?? 128, height: sizeStyle.height ?? 128 },
|
|
6710
|
+
children: /* @__PURE__ */ jsx32("img", { src: value, alt: f.label, className: "w-full h-full object-cover" })
|
|
6711
|
+
}
|
|
6712
|
+
);
|
|
6713
|
+
case "image-url-open-other-tabs":
|
|
6714
|
+
return empty ? dash : /* @__PURE__ */ jsx32(
|
|
6715
|
+
"a",
|
|
6716
|
+
{
|
|
6717
|
+
href: value,
|
|
6718
|
+
target: "_blank",
|
|
6719
|
+
rel: "noopener noreferrer",
|
|
6720
|
+
className: "inline-block rounded-xl overflow-hidden ring-1 ring-border hover:ring-primary transition-all",
|
|
6721
|
+
style: { width: sizeStyle.width ?? 128, height: sizeStyle.height ?? 128 },
|
|
6722
|
+
children: /* @__PURE__ */ jsx32("img", { src: value, alt: f.label, className: "w-full h-full object-cover" })
|
|
6723
|
+
}
|
|
6724
|
+
);
|
|
6725
|
+
case "text-url":
|
|
6726
|
+
return empty ? dash : /* @__PURE__ */ jsx32(
|
|
6727
|
+
"a",
|
|
6728
|
+
{
|
|
6729
|
+
href: value,
|
|
6730
|
+
onClick: (e) => e.preventDefault(),
|
|
6731
|
+
className: "text-sm text-primary underline underline-offset-2 hover:text-primary/80 break-all",
|
|
6732
|
+
style: sizeStyle,
|
|
6733
|
+
children: value
|
|
6734
|
+
}
|
|
6735
|
+
);
|
|
6736
|
+
case "text-url-open-other-tabs":
|
|
6737
|
+
return empty ? dash : /* @__PURE__ */ jsx32(
|
|
6738
|
+
"a",
|
|
6739
|
+
{
|
|
6740
|
+
href: value,
|
|
6741
|
+
target: "_blank",
|
|
6742
|
+
rel: "noopener noreferrer",
|
|
6743
|
+
className: "text-sm text-primary underline underline-offset-2 hover:text-primary/80 break-all",
|
|
6744
|
+
style: sizeStyle,
|
|
6745
|
+
children: value
|
|
6746
|
+
}
|
|
6747
|
+
);
|
|
6748
|
+
case "attachment":
|
|
6749
|
+
return empty ? dash : /* @__PURE__ */ jsxs30(
|
|
6750
|
+
"a",
|
|
6751
|
+
{
|
|
6752
|
+
href: value,
|
|
6753
|
+
target: "_blank",
|
|
6754
|
+
rel: "noopener noreferrer",
|
|
6755
|
+
className: "inline-flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-3 py-1.5 text-xs font-medium text-foreground hover:bg-muted transition-colors",
|
|
6756
|
+
style: sizeStyle,
|
|
6757
|
+
children: [
|
|
6758
|
+
/* @__PURE__ */ jsx32("svg", { className: "h-3.5 w-3.5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx32("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" }) }),
|
|
6759
|
+
String(value).split("/").pop() ?? "Download"
|
|
6760
|
+
]
|
|
6761
|
+
}
|
|
6762
|
+
);
|
|
6763
|
+
case "repeater": {
|
|
6764
|
+
const rows = Array.isArray(value) ? value : [];
|
|
6765
|
+
if (!rows.length) return dash;
|
|
6766
|
+
const rFields = f.repeaterFields;
|
|
6767
|
+
return /* @__PURE__ */ jsx32("div", { className: "space-y-2", children: rows.map((row, ri) => /* @__PURE__ */ jsxs30("div", { className: "flex flex-wrap gap-3 rounded-xl border border-border bg-muted/30 px-3 py-2", children: [
|
|
6768
|
+
/* @__PURE__ */ jsx32("span", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-semibold text-primary", children: ri + 1 }),
|
|
6769
|
+
rFields ? rFields.map((rf) => {
|
|
6770
|
+
const v = row[rf.key];
|
|
6771
|
+
if (rf.type === "image") return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1", children: [
|
|
6772
|
+
rf.label && /* @__PURE__ */ jsx32("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
|
|
6773
|
+
v ? /* @__PURE__ */ jsx32("img", { src: v, alt: rf.key, className: "h-10 w-10 rounded-lg object-cover ring-1 ring-border" }) : dash
|
|
6774
|
+
] }, rf.key);
|
|
6775
|
+
if (rf.type === "attachment") return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1", children: [
|
|
6776
|
+
rf.label && /* @__PURE__ */ jsx32("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
|
|
6777
|
+
v ? /* @__PURE__ */ jsxs30(
|
|
6778
|
+
"a",
|
|
6779
|
+
{
|
|
6780
|
+
href: v,
|
|
6781
|
+
target: "_blank",
|
|
6782
|
+
rel: "noopener noreferrer",
|
|
6783
|
+
className: "inline-flex items-center gap-1 rounded-lg border border-border bg-muted/50 px-2 py-1 text-xs font-medium hover:bg-muted transition-colors",
|
|
6784
|
+
children: [
|
|
6785
|
+
/* @__PURE__ */ jsx32("svg", { className: "h-3 w-3 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ jsx32("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15.172 7l-6.586 6.586a2 2 0 102.828 2.828l6.414-6.586a4 4 0 00-5.656-5.656l-6.415 6.585a6 6 0 108.486 8.486L20.5 13" }) }),
|
|
6786
|
+
String(v).split("/").pop()
|
|
6787
|
+
]
|
|
6788
|
+
}
|
|
6789
|
+
) : dash
|
|
6790
|
+
] }, rf.key);
|
|
6791
|
+
return /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1", children: [
|
|
6792
|
+
rf.label && /* @__PURE__ */ jsx32("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
|
|
6793
|
+
/* @__PURE__ */ jsx32("span", { className: "text-sm", children: v ?? "\u2014" })
|
|
6794
|
+
] }, rf.key);
|
|
6795
|
+
}) : (
|
|
6796
|
+
// payload mode: row has { type, key, value }
|
|
6797
|
+
Object.entries(row).map(([k, v]) => /* @__PURE__ */ jsxs30("div", { className: "flex flex-col gap-1", children: [
|
|
6798
|
+
/* @__PURE__ */ jsx32("span", { className: "text-[10px] text-muted-foreground", children: k }),
|
|
6799
|
+
/* @__PURE__ */ jsx32("span", { className: "text-sm", children: String(v) })
|
|
6800
|
+
] }, k))
|
|
6801
|
+
)
|
|
6802
|
+
] }, ri)) });
|
|
6803
|
+
}
|
|
6804
|
+
case "checkbox":
|
|
6805
|
+
return /* @__PURE__ */ jsx32(
|
|
6806
|
+
"input",
|
|
6807
|
+
{
|
|
6808
|
+
type: "checkbox",
|
|
6809
|
+
checked: !!value,
|
|
6810
|
+
readOnly: true,
|
|
6811
|
+
className: "h-4 w-4 rounded border-border accent-primary cursor-default",
|
|
6812
|
+
style: sizeStyle
|
|
6813
|
+
}
|
|
6814
|
+
);
|
|
6815
|
+
case "toggle":
|
|
6816
|
+
return /* @__PURE__ */ jsx32(
|
|
6817
|
+
"div",
|
|
6818
|
+
{
|
|
6819
|
+
className: cn(
|
|
6820
|
+
"relative inline-flex shrink-0 rounded-full border-2 border-transparent transition-colors",
|
|
6821
|
+
value ? "bg-primary" : "bg-muted"
|
|
6822
|
+
),
|
|
6823
|
+
style: { width: sizeStyle.width ?? 36, height: sizeStyle.height ?? 20 },
|
|
6824
|
+
children: /* @__PURE__ */ jsx32(
|
|
6825
|
+
"span",
|
|
6826
|
+
{
|
|
6827
|
+
className: cn(
|
|
6828
|
+
"pointer-events-none inline-block rounded-full bg-white shadow-sm transition-transform"
|
|
6829
|
+
),
|
|
6830
|
+
style: {
|
|
6831
|
+
width: typeof (sizeStyle.height ?? 20) === "number" ? sizeStyle.height - 4 : 16,
|
|
6832
|
+
height: typeof (sizeStyle.height ?? 20) === "number" ? sizeStyle.height - 4 : 16,
|
|
6833
|
+
transform: value ? `translateX(${typeof (sizeStyle.width ?? 36) === "number" ? sizeStyle.width - (sizeStyle.height ?? 20) : 16}px)` : "translateX(0)"
|
|
6834
|
+
}
|
|
6835
|
+
}
|
|
6836
|
+
)
|
|
6837
|
+
}
|
|
6838
|
+
);
|
|
6839
|
+
default:
|
|
6840
|
+
return empty ? dash : /* @__PURE__ */ jsx32("p", { className: "text-sm text-foreground break-words", style: sizeStyle, children: String(value) });
|
|
6841
|
+
}
|
|
6842
|
+
};
|
|
6577
6843
|
return /* @__PURE__ */ jsx32(
|
|
6578
6844
|
ModalShell,
|
|
6579
6845
|
{
|
|
@@ -6581,11 +6847,27 @@ function ViewModal({
|
|
|
6581
6847
|
onClose,
|
|
6582
6848
|
width,
|
|
6583
6849
|
footer: /* @__PURE__ */ jsx32(Button, { variant: "outline", size: "sm", onClick: onClose, children: "Close" }),
|
|
6584
|
-
children: /* @__PURE__ */ jsx32(
|
|
6585
|
-
|
|
6586
|
-
|
|
6587
|
-
|
|
6588
|
-
|
|
6850
|
+
children: /* @__PURE__ */ jsx32(
|
|
6851
|
+
"div",
|
|
6852
|
+
{
|
|
6853
|
+
className: grid ? "grid gap-4" : "space-y-3",
|
|
6854
|
+
style: grid ? { gridTemplateColumns: `repeat(${grid}, minmax(0, 1fr))` } : void 0,
|
|
6855
|
+
children: fields.map((f) => /* @__PURE__ */ jsxs30(
|
|
6856
|
+
"div",
|
|
6857
|
+
{
|
|
6858
|
+
style: {
|
|
6859
|
+
...f.colSpan ? { gridColumn: `span ${f.colSpan}` } : {},
|
|
6860
|
+
...f.rowSpan ? { gridRow: `span ${f.rowSpan}` } : {}
|
|
6861
|
+
},
|
|
6862
|
+
children: [
|
|
6863
|
+
/* @__PURE__ */ jsx32("p", { className: "text-xs font-semibold text-muted-foreground mb-1", children: f.label }),
|
|
6864
|
+
renderViewValue(f, item[f.key])
|
|
6865
|
+
]
|
|
6866
|
+
},
|
|
6867
|
+
f.key
|
|
6868
|
+
))
|
|
6869
|
+
}
|
|
6870
|
+
)
|
|
6589
6871
|
}
|
|
6590
6872
|
);
|
|
6591
6873
|
}
|
|
@@ -6671,7 +6953,7 @@ function EditModal({
|
|
|
6671
6953
|
title: "Edit Record",
|
|
6672
6954
|
onClose,
|
|
6673
6955
|
width,
|
|
6674
|
-
footer: /* @__PURE__ */ jsxs30(
|
|
6956
|
+
footer: /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
6675
6957
|
/* @__PURE__ */ jsx32(Button, { variant: "outline", size: "sm", onClick: onClose, disabled: loading, children: "Cancel" }),
|
|
6676
6958
|
/* @__PURE__ */ jsxs30(Button, { size: "sm", onClick: handleSubmit, disabled: loading, children: [
|
|
6677
6959
|
loading && /* @__PURE__ */ jsx32(Loader22, { className: "h-3.5 w-3.5 mr-1.5 animate-spin" }),
|
|
@@ -6698,7 +6980,7 @@ function EditModal({
|
|
|
6698
6980
|
...f.colSpan ? { gridColumn: `span ${f.colSpan}` } : {},
|
|
6699
6981
|
...f.rowSpan ? { gridRow: `span ${f.rowSpan}` } : {}
|
|
6700
6982
|
},
|
|
6701
|
-
children: f.component ? /* @__PURE__ */ jsx32(
|
|
6983
|
+
children: f.component ? /* @__PURE__ */ jsx32(Fragment12, { children: f.component }) : /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
6702
6984
|
f.type !== "checkbox" && /* @__PURE__ */ jsxs30("label", { className: "block text-xs font-semibold text-muted-foreground mb-1", children: [
|
|
6703
6985
|
f.label,
|
|
6704
6986
|
f.required && /* @__PURE__ */ jsx32("span", { className: "text-danger ml-0.5", children: "*" })
|
|
@@ -6758,7 +7040,7 @@ function DeleteModal({
|
|
|
6758
7040
|
title: "Confirm Delete",
|
|
6759
7041
|
onClose,
|
|
6760
7042
|
width: "lg",
|
|
6761
|
-
footer: /* @__PURE__ */ jsxs30(
|
|
7043
|
+
footer: /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
6762
7044
|
/* @__PURE__ */ jsx32(Button, { variant: "outline", size: "sm", onClick: onClose, disabled: loading, children: "Cancel" }),
|
|
6763
7045
|
/* @__PURE__ */ jsxs30(Button, { variant: "danger", size: "sm", onClick: handleDelete, disabled: loading, children: [
|
|
6764
7046
|
loading && /* @__PURE__ */ jsx32(Loader22, { className: "h-3.5 w-3.5 mr-1.5 animate-spin" }),
|
|
@@ -6818,26 +7100,84 @@ var BADGE_COLORS = {
|
|
|
6818
7100
|
function badgeClass(value) {
|
|
6819
7101
|
return BADGE_COLORS[value.toLowerCase()] ?? "bg-primary/10 text-primary border-primary/20";
|
|
6820
7102
|
}
|
|
7103
|
+
function deriveField(key, sample) {
|
|
7104
|
+
const label = key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
7105
|
+
const base = { key, label };
|
|
7106
|
+
if (typeof sample === "boolean") return { ...base, type: "toggle", viewType: "toggle" };
|
|
7107
|
+
if (typeof sample === "number") return { ...base, inputType: "number" };
|
|
7108
|
+
if (Array.isArray(sample)) {
|
|
7109
|
+
if (sample.length === 0 || typeof sample[0] === "string")
|
|
7110
|
+
return { ...base, type: "tag-input" };
|
|
7111
|
+
return base;
|
|
7112
|
+
}
|
|
7113
|
+
if (typeof sample === "string") {
|
|
7114
|
+
if (/\.(png|jpe?g|gif|webp|svg|avif)(\?.*)?$/i.test(sample))
|
|
7115
|
+
return { ...base, type: "input", viewType: "image" };
|
|
7116
|
+
if (/\.(pdf|docx?|xlsx?|csv|zip|pptx?)(\?.*)?$/i.test(sample))
|
|
7117
|
+
return { ...base, type: "input", viewType: "attachment" };
|
|
7118
|
+
if (/^https?:\/\//.test(sample))
|
|
7119
|
+
return { ...base, type: "input", viewType: "text-url-open-other-tabs" };
|
|
7120
|
+
if (sample.length > 120 || /\n/.test(sample))
|
|
7121
|
+
return { ...base, type: "textarea" };
|
|
7122
|
+
if (/password|secret|token/i.test(key))
|
|
7123
|
+
return { ...base, type: "password" };
|
|
7124
|
+
if (/email/i.test(key))
|
|
7125
|
+
return { ...base, inputType: "email" };
|
|
7126
|
+
if (/color|colour/i.test(key) && /^#[0-9a-f]{3,8}$/i.test(sample))
|
|
7127
|
+
return { ...base, type: "color-picker", viewType: "text" };
|
|
7128
|
+
}
|
|
7129
|
+
return base;
|
|
7130
|
+
}
|
|
6821
7131
|
function Table({
|
|
6822
7132
|
data,
|
|
6823
7133
|
columns,
|
|
7134
|
+
loading,
|
|
7135
|
+
emptyState,
|
|
7136
|
+
error: errorProp,
|
|
6824
7137
|
searchable = false,
|
|
6825
7138
|
searchPlaceholder = "Search...",
|
|
6826
|
-
|
|
7139
|
+
searchValue: controlledSearch,
|
|
7140
|
+
onSearchChange,
|
|
7141
|
+
clientPagination = false,
|
|
6827
7142
|
itemsPerPage = 10,
|
|
6828
7143
|
selectable = false,
|
|
6829
7144
|
onBulkDelete,
|
|
6830
7145
|
idKey = "id",
|
|
7146
|
+
bulkDeleteBaseUrl,
|
|
6831
7147
|
defaultActions,
|
|
6832
7148
|
serverPagination,
|
|
6833
|
-
|
|
7149
|
+
variant = "default",
|
|
7150
|
+
className,
|
|
7151
|
+
onRowClick,
|
|
7152
|
+
onRowDoubleClick,
|
|
7153
|
+
rowClassName,
|
|
7154
|
+
expandable = false,
|
|
7155
|
+
renderExpanded,
|
|
7156
|
+
columnVisibility,
|
|
7157
|
+
onColumnVisibilityChange,
|
|
7158
|
+
exportable = false,
|
|
7159
|
+
onExport,
|
|
7160
|
+
virtualized = false,
|
|
7161
|
+
draggable = false,
|
|
7162
|
+
onRowReorder,
|
|
7163
|
+
keyboardNavigation = false
|
|
6834
7164
|
}) {
|
|
6835
7165
|
const { toast } = useToast();
|
|
6836
|
-
const
|
|
7166
|
+
const isControlledSearch = controlledSearch !== void 0;
|
|
7167
|
+
const [internalSearch, setInternalSearch] = React28.useState("");
|
|
7168
|
+
const search = isControlledSearch ? controlledSearch : internalSearch;
|
|
7169
|
+
const setSearch = (v) => {
|
|
7170
|
+
if (!isControlledSearch) setInternalSearch(v);
|
|
7171
|
+
onSearchChange?.(v);
|
|
7172
|
+
};
|
|
6837
7173
|
const [currentPage, setCurrentPage] = React28.useState(1);
|
|
6838
7174
|
const [selectedIds, setSelectedIds] = React28.useState([]);
|
|
6839
7175
|
const [sortKey, setSortKey] = React28.useState(null);
|
|
6840
7176
|
const [sortDir, setSortDir] = React28.useState(null);
|
|
7177
|
+
const [bulkLoading, setBulkLoading] = React28.useState(false);
|
|
7178
|
+
const [expandedIds, setExpandedIds] = React28.useState(/* @__PURE__ */ new Set());
|
|
7179
|
+
const [dragOverId, setDragOverId] = React28.useState(null);
|
|
7180
|
+
const [focusedRowIdx, setFocusedRowIdx] = React28.useState(-1);
|
|
6841
7181
|
const [viewItem, setViewItem] = React28.useState(null);
|
|
6842
7182
|
const [editItem, setEditItem] = React28.useState(null);
|
|
6843
7183
|
const [deleteItem, setDeleteItem] = React28.useState(null);
|
|
@@ -6849,15 +7189,17 @@ function Table({
|
|
|
6849
7189
|
const safeBaseUrl = defaultActions?.baseUrl.replace(/\/+$/, "") ?? "";
|
|
6850
7190
|
const autoFields = React28.useMemo(() => {
|
|
6851
7191
|
if (!tableData.length) return [];
|
|
6852
|
-
|
|
6853
|
-
|
|
6854
|
-
label: k.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
6855
|
-
}));
|
|
7192
|
+
const row = tableData[0];
|
|
7193
|
+
return Object.keys(row).map((k) => deriveField(k, row[k]));
|
|
6856
7194
|
}, [tableData]);
|
|
6857
7195
|
const editFields = defaultActions?.editForm ?? autoFields;
|
|
6858
7196
|
const viewFields = defaultActions?.viewForm ?? autoFields;
|
|
7197
|
+
const visibleColumns = React28.useMemo(() => {
|
|
7198
|
+
if (!columnVisibility) return columns;
|
|
7199
|
+
return columns.filter((col) => columnVisibility[String(col.key)] !== false);
|
|
7200
|
+
}, [columns, columnVisibility]);
|
|
6859
7201
|
const allColumns = React28.useMemo(() => {
|
|
6860
|
-
if (!defaultActions) return
|
|
7202
|
+
if (!defaultActions) return visibleColumns;
|
|
6861
7203
|
const actionsCol = {
|
|
6862
7204
|
key: "__actions__",
|
|
6863
7205
|
title: "Actions",
|
|
@@ -6906,8 +7248,8 @@ function Table({
|
|
|
6906
7248
|
))
|
|
6907
7249
|
] })
|
|
6908
7250
|
};
|
|
6909
|
-
return defaultActions.position === "first" ? [actionsCol, ...
|
|
6910
|
-
}, [
|
|
7251
|
+
return defaultActions.position === "first" ? [actionsCol, ...visibleColumns] : [...visibleColumns, actionsCol];
|
|
7252
|
+
}, [visibleColumns, defaultActions]);
|
|
6911
7253
|
const handleSort = (key) => {
|
|
6912
7254
|
if (sortKey !== key) {
|
|
6913
7255
|
setSortKey(key);
|
|
@@ -6940,16 +7282,74 @@ function Table({
|
|
|
6940
7282
|
const totalPages = Math.max(1, Math.ceil(filteredData.length / itemsPerPage));
|
|
6941
7283
|
const safePage = Math.min(currentPage, totalPages);
|
|
6942
7284
|
const paginatedData = React28.useMemo(() => {
|
|
6943
|
-
if (!
|
|
7285
|
+
if (!clientPagination) return filteredData;
|
|
6944
7286
|
const start = (safePage - 1) * itemsPerPage;
|
|
6945
7287
|
return filteredData.slice(start, start + itemsPerPage);
|
|
6946
|
-
}, [filteredData,
|
|
7288
|
+
}, [filteredData, clientPagination, safePage, itemsPerPage]);
|
|
6947
7289
|
React28.useEffect(() => {
|
|
6948
7290
|
setCurrentPage(1);
|
|
6949
7291
|
}, [search]);
|
|
7292
|
+
React28.useEffect(() => {
|
|
7293
|
+
if (!keyboardNavigation) return;
|
|
7294
|
+
const handler = (e) => {
|
|
7295
|
+
if (e.key === "ArrowDown") {
|
|
7296
|
+
e.preventDefault();
|
|
7297
|
+
setFocusedRowIdx((i) => Math.min(i + 1, paginatedData.length - 1));
|
|
7298
|
+
}
|
|
7299
|
+
if (e.key === "ArrowUp") {
|
|
7300
|
+
e.preventDefault();
|
|
7301
|
+
setFocusedRowIdx((i) => Math.max(i - 1, 0));
|
|
7302
|
+
}
|
|
7303
|
+
};
|
|
7304
|
+
window.addEventListener("keydown", handler);
|
|
7305
|
+
return () => window.removeEventListener("keydown", handler);
|
|
7306
|
+
}, [keyboardNavigation, paginatedData.length]);
|
|
6950
7307
|
const handleSelectAll = (checked) => setSelectedIds(checked ? paginatedData.map((item) => String(item[idKey])) : []);
|
|
6951
7308
|
const handleSelect = (id, checked) => setSelectedIds((prev) => checked ? [...prev, id] : prev.filter((i) => i !== id));
|
|
6952
7309
|
const allSelected = paginatedData.length > 0 && selectedIds.length === paginatedData.length;
|
|
7310
|
+
const totalRows = serverPagination ? serverPagination.pagination.total : filteredData.length;
|
|
7311
|
+
const unselectedCount = totalRows - selectedIds.length;
|
|
7312
|
+
const handleSelectAllRecords = () => setSelectedIds(filteredData.map((item) => String(item[idKey])));
|
|
7313
|
+
const handleUnselectAll = () => setSelectedIds([]);
|
|
7314
|
+
const handleBulkDeleteSelected = async () => {
|
|
7315
|
+
if (!bulkDeleteBaseUrl || selectedIds.length === 0) {
|
|
7316
|
+
onBulkDelete?.(selectedIds);
|
|
7317
|
+
setSelectedIds([]);
|
|
7318
|
+
return;
|
|
7319
|
+
}
|
|
7320
|
+
setBulkLoading(true);
|
|
7321
|
+
try {
|
|
7322
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
|
7323
|
+
if (!csrfToken) throw new Error("[Table] CSRF token not found.");
|
|
7324
|
+
const safeUrl = bulkDeleteBaseUrl.replace(/\/+$/, "");
|
|
7325
|
+
await axios3.delete(`${safeUrl}/delete/${selectedIds.join(",")}/selected`, { headers: { "X-CSRF-Token": csrfToken } });
|
|
7326
|
+
setTableData((prev) => prev.filter((r) => !selectedIds.includes(String(r[idKey]))));
|
|
7327
|
+
onBulkDelete?.(selectedIds);
|
|
7328
|
+
setSelectedIds([]);
|
|
7329
|
+
defaultActions?.onReload?.();
|
|
7330
|
+
} catch (err) {
|
|
7331
|
+
console.error("[Table] Bulk delete selected failed:", err?.response?.data?.message ?? err.message);
|
|
7332
|
+
} finally {
|
|
7333
|
+
setBulkLoading(false);
|
|
7334
|
+
}
|
|
7335
|
+
};
|
|
7336
|
+
const handleDeleteAll = async () => {
|
|
7337
|
+
if (!bulkDeleteBaseUrl) return;
|
|
7338
|
+
setBulkLoading(true);
|
|
7339
|
+
try {
|
|
7340
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
|
7341
|
+
if (!csrfToken) throw new Error("[Table] CSRF token not found.");
|
|
7342
|
+
const safeUrl = bulkDeleteBaseUrl.replace(/\/+$/, "");
|
|
7343
|
+
await axios3.delete(`${safeUrl}/delete/all`, { headers: { "X-CSRF-Token": csrfToken } });
|
|
7344
|
+
setTableData([]);
|
|
7345
|
+
setSelectedIds([]);
|
|
7346
|
+
defaultActions?.onReload?.();
|
|
7347
|
+
} catch (err) {
|
|
7348
|
+
console.error("[Table] Delete all failed:", err?.response?.data?.message ?? err.message);
|
|
7349
|
+
} finally {
|
|
7350
|
+
setBulkLoading(false);
|
|
7351
|
+
}
|
|
7352
|
+
};
|
|
6953
7353
|
const pagePills = React28.useMemo(() => {
|
|
6954
7354
|
if (totalPages <= 5) return Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
6955
7355
|
if (safePage <= 3) return [1, 2, 3, 4, 5];
|
|
@@ -6961,8 +7361,9 @@ function Table({
|
|
|
6961
7361
|
if (sortKey !== String(col.key)) return /* @__PURE__ */ jsx32(ChevronsUpDown, { className: "ml-1.5 h-3.5 w-3.5 opacity-40" });
|
|
6962
7362
|
return sortDir === "asc" ? /* @__PURE__ */ jsx32(ChevronUp, { className: "ml-1.5 h-3.5 w-3.5 text-primary" }) : /* @__PURE__ */ jsx32(ChevronDown4, { className: "ml-1.5 h-3.5 w-3.5 text-primary" });
|
|
6963
7363
|
};
|
|
6964
|
-
return /* @__PURE__ */ jsxs30(
|
|
7364
|
+
return /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
6965
7365
|
/* @__PURE__ */ jsxs30("div", { className: cn("w-full space-y-3", className), children: [
|
|
7366
|
+
errorProp && /* @__PURE__ */ jsx32("div", { className: "rounded-xl border border-danger/30 bg-danger/5 px-4 py-3 text-sm text-danger", children: errorProp }),
|
|
6966
7367
|
/* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between gap-3 flex-wrap", children: [
|
|
6967
7368
|
searchable && /* @__PURE__ */ jsxs30("div", { className: "relative w-72", children: [
|
|
6968
7369
|
/* @__PURE__ */ jsx32(Search5, { className: "absolute text-primary left-3 top-1/2 -translate-y-1/2 h-4 w-4 z-10" }),
|
|
@@ -6984,33 +7385,115 @@ function Table({
|
|
|
6984
7385
|
}
|
|
6985
7386
|
)
|
|
6986
7387
|
] }),
|
|
6987
|
-
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2 ml-auto", children: [
|
|
6988
|
-
selectable &&
|
|
7388
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2 ml-auto flex-wrap", children: [
|
|
7389
|
+
selectable && selectedIds.length > 0 && /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
7390
|
+
/* @__PURE__ */ jsxs30(
|
|
7391
|
+
"button",
|
|
7392
|
+
{
|
|
7393
|
+
onClick: handleUnselectAll,
|
|
7394
|
+
disabled: bulkLoading,
|
|
7395
|
+
className: "inline-flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors disabled:opacity-40",
|
|
7396
|
+
children: [
|
|
7397
|
+
/* @__PURE__ */ jsx32(X9, { className: "h-3.5 w-3.5" }),
|
|
7398
|
+
"Unselect all ",
|
|
7399
|
+
selectedIds.length
|
|
7400
|
+
]
|
|
7401
|
+
}
|
|
7402
|
+
),
|
|
7403
|
+
/* @__PURE__ */ jsxs30(
|
|
7404
|
+
"button",
|
|
7405
|
+
{
|
|
7406
|
+
onClick: handleBulkDeleteSelected,
|
|
7407
|
+
disabled: bulkLoading,
|
|
7408
|
+
className: "inline-flex items-center gap-1.5 rounded-lg bg-danger/10 border border-danger/20 px-3 py-1.5 text-xs font-medium text-danger hover:bg-danger/20 transition-colors disabled:opacity-40",
|
|
7409
|
+
children: [
|
|
7410
|
+
bulkLoading ? /* @__PURE__ */ jsx32(Loader22, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx32(Trash22, { className: "h-3.5 w-3.5" }),
|
|
7411
|
+
"Delete ",
|
|
7412
|
+
selectedIds.length,
|
|
7413
|
+
" selected"
|
|
7414
|
+
]
|
|
7415
|
+
}
|
|
7416
|
+
)
|
|
7417
|
+
] }),
|
|
7418
|
+
selectable && unselectedCount > 0 && /* @__PURE__ */ jsxs30(
|
|
6989
7419
|
"button",
|
|
6990
7420
|
{
|
|
6991
|
-
onClick:
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
7421
|
+
onClick: handleSelectAllRecords,
|
|
7422
|
+
disabled: bulkLoading,
|
|
7423
|
+
className: "inline-flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors disabled:opacity-40",
|
|
7424
|
+
children: [
|
|
7425
|
+
"Select all ",
|
|
7426
|
+
unselectedCount
|
|
7427
|
+
]
|
|
7428
|
+
}
|
|
7429
|
+
),
|
|
7430
|
+
selectable && bulkDeleteBaseUrl && /* @__PURE__ */ jsxs30(
|
|
7431
|
+
"button",
|
|
7432
|
+
{
|
|
7433
|
+
onClick: handleDeleteAll,
|
|
7434
|
+
disabled: bulkLoading,
|
|
7435
|
+
className: "inline-flex items-center gap-1.5 rounded-lg bg-danger/10 border border-danger/20 px-3 py-1.5 text-xs font-medium text-danger hover:bg-danger/20 transition-colors disabled:opacity-40",
|
|
6996
7436
|
children: [
|
|
6997
|
-
/* @__PURE__ */ jsx32(Trash22, { className: "h-3.5 w-3.5" }),
|
|
6998
|
-
"Delete "
|
|
6999
|
-
selectedIds.length,
|
|
7000
|
-
" selected"
|
|
7437
|
+
bulkLoading ? /* @__PURE__ */ jsx32(Loader22, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsx32(Trash22, { className: "h-3.5 w-3.5" }),
|
|
7438
|
+
"Delete all"
|
|
7001
7439
|
]
|
|
7002
7440
|
}
|
|
7003
7441
|
),
|
|
7442
|
+
exportable && /* @__PURE__ */ jsxs30("div", { className: "relative group", children: [
|
|
7443
|
+
/* @__PURE__ */ jsx32("button", { className: "inline-flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: "Export" }),
|
|
7444
|
+
/* @__PURE__ */ jsx32("div", { className: "absolute right-0 top-full mt-1 z-20 hidden group-hover:flex flex-col min-w-[110px] rounded-xl border border-border bg-card shadow-lg overflow-hidden", children: ["csv", "excel", "pdf"].map((type) => /* @__PURE__ */ jsx32(
|
|
7445
|
+
"button",
|
|
7446
|
+
{
|
|
7447
|
+
onClick: () => onExport?.(type),
|
|
7448
|
+
className: "px-4 py-2 text-xs text-left hover:bg-muted transition-colors capitalize",
|
|
7449
|
+
children: type.toUpperCase()
|
|
7450
|
+
},
|
|
7451
|
+
type
|
|
7452
|
+
)) })
|
|
7453
|
+
] }),
|
|
7454
|
+
columnVisibility && onColumnVisibilityChange && /* @__PURE__ */ jsxs30("div", { className: "relative group", children: [
|
|
7455
|
+
/* @__PURE__ */ jsx32("button", { className: "inline-flex items-center gap-1.5 rounded-lg border border-border bg-muted/50 px-3 py-1.5 text-xs font-medium text-muted-foreground hover:bg-muted transition-colors", children: "Columns" }),
|
|
7456
|
+
/* @__PURE__ */ jsx32("div", { className: "absolute right-0 top-full mt-1 z-20 hidden group-hover:flex flex-col min-w-[150px] rounded-xl border border-border bg-card shadow-lg overflow-hidden p-2 gap-1", children: columns.map((col) => /* @__PURE__ */ jsxs30("label", { className: "flex items-center gap-2 px-2 py-1 rounded-lg hover:bg-muted cursor-pointer text-xs", children: [
|
|
7457
|
+
/* @__PURE__ */ jsx32(
|
|
7458
|
+
"input",
|
|
7459
|
+
{
|
|
7460
|
+
type: "checkbox",
|
|
7461
|
+
checked: columnVisibility[String(col.key)] !== false,
|
|
7462
|
+
onChange: (e) => onColumnVisibilityChange({ ...columnVisibility, [String(col.key)]: e.target.checked }),
|
|
7463
|
+
className: "accent-primary"
|
|
7464
|
+
}
|
|
7465
|
+
),
|
|
7466
|
+
col.title
|
|
7467
|
+
] }, String(col.key))) })
|
|
7468
|
+
] }),
|
|
7004
7469
|
/* @__PURE__ */ jsxs30("span", { className: "text-xs text-muted-foreground", children: [
|
|
7005
|
-
|
|
7470
|
+
totalRows,
|
|
7006
7471
|
" ",
|
|
7007
|
-
|
|
7472
|
+
totalRows === 1 ? "row" : "rows",
|
|
7008
7473
|
search && ` \xB7 filtered from ${tableData.length}`
|
|
7009
7474
|
] })
|
|
7010
7475
|
] })
|
|
7011
7476
|
] }),
|
|
7012
|
-
/* @__PURE__ */
|
|
7013
|
-
/* @__PURE__ */ jsx32(
|
|
7477
|
+
loading && /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-center py-12 text-muted-foreground gap-2", children: [
|
|
7478
|
+
/* @__PURE__ */ jsx32(Loader22, { className: "h-5 w-5 animate-spin" }),
|
|
7479
|
+
/* @__PURE__ */ jsx32("span", { className: "text-sm", children: "Loading\u2026" })
|
|
7480
|
+
] }),
|
|
7481
|
+
!loading && /* @__PURE__ */ jsx32("div", { className: cn(
|
|
7482
|
+
variant === "default" && "rounded-xl border border-border overflow-hidden bg-card/50 backdrop-blur-sm shadow-sm",
|
|
7483
|
+
variant === "zebra" && "rounded-xl border border-border overflow-hidden bg-card/50 backdrop-blur-sm shadow-sm",
|
|
7484
|
+
variant === "card" && "space-y-2",
|
|
7485
|
+
variant === "glass" && "rounded-2xl overflow-hidden border border-white/10 bg-background/30 backdrop-blur-xl shadow-xl",
|
|
7486
|
+
variant === "soft" && "rounded-2xl overflow-hidden bg-card",
|
|
7487
|
+
variant === "soft" && "[box-shadow:6px_6px_12px_hsl(var(--foreground)/0.07),-6px_-6px_12px_hsl(var(--background)/0.8)]",
|
|
7488
|
+
virtualized && "max-h-[520px] overflow-y-auto"
|
|
7489
|
+
), children: /* @__PURE__ */ jsx32("div", { className: cn("w-full overflow-auto", variant === "card" && "space-y-2"), children: /* @__PURE__ */ jsxs30("table", { className: cn("w-full caption-bottom text-sm", variant === "card" && "border-separate border-spacing-y-2"), children: [
|
|
7490
|
+
/* @__PURE__ */ jsx32("thead", { children: /* @__PURE__ */ jsxs30("tr", { className: cn(
|
|
7491
|
+
variant === "default" && "border-b border-border bg-muted/40",
|
|
7492
|
+
variant === "zebra" && "border-b border-border bg-muted/40",
|
|
7493
|
+
variant === "card" && "[&>th]:bg-transparent",
|
|
7494
|
+
variant === "glass" && "border-b border-white/10 bg-white/5",
|
|
7495
|
+
variant === "soft" && "border-b-0 bg-muted/30"
|
|
7496
|
+
), children: [
|
|
7014
7497
|
selectable && /* @__PURE__ */ jsx32("th", { className: "h-11 w-[46px] px-4 text-left align-middle", children: /* @__PURE__ */ jsx32(
|
|
7015
7498
|
Checkbox,
|
|
7016
7499
|
{
|
|
@@ -7018,13 +7501,16 @@ function Table({
|
|
|
7018
7501
|
onChange: (e) => handleSelectAll(e.target.checked)
|
|
7019
7502
|
}
|
|
7020
7503
|
) }),
|
|
7504
|
+
expandable && /* @__PURE__ */ jsx32("th", { className: "h-11 w-8" }),
|
|
7021
7505
|
allColumns.map((col, ci) => /* @__PURE__ */ jsx32(
|
|
7022
7506
|
"th",
|
|
7023
7507
|
{
|
|
7024
7508
|
onClick: () => col.sortable && handleSort(String(col.key)),
|
|
7025
7509
|
className: cn(
|
|
7026
7510
|
"h-11 px-4 text-left align-middle text-xs font-semibold uppercase tracking-wider text-muted-foreground select-none whitespace-nowrap",
|
|
7027
|
-
col.sortable && "cursor-pointer hover:text-foreground transition-colors"
|
|
7511
|
+
col.sortable && "cursor-pointer hover:text-foreground transition-colors",
|
|
7512
|
+
variant === "glass" && "text-foreground/70",
|
|
7513
|
+
variant === "soft" && "text-muted-foreground/80"
|
|
7028
7514
|
),
|
|
7029
7515
|
children: /* @__PURE__ */ jsxs30("span", { className: "inline-flex items-center", children: [
|
|
7030
7516
|
col.title,
|
|
@@ -7037,9 +7523,9 @@ function Table({
|
|
|
7037
7523
|
/* @__PURE__ */ jsx32("tbody", { children: paginatedData.length === 0 ? /* @__PURE__ */ jsx32("tr", { children: /* @__PURE__ */ jsx32(
|
|
7038
7524
|
"td",
|
|
7039
7525
|
{
|
|
7040
|
-
colSpan: allColumns.length + (selectable ? 1 : 0),
|
|
7526
|
+
colSpan: allColumns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0),
|
|
7041
7527
|
className: "h-32 text-center align-middle",
|
|
7042
|
-
children: /* @__PURE__ */ jsxs30("div", { className: "flex flex-col items-center gap-1 text-muted-foreground", children: [
|
|
7528
|
+
children: emptyState ?? /* @__PURE__ */ jsxs30("div", { className: "flex flex-col items-center gap-1 text-muted-foreground", children: [
|
|
7043
7529
|
/* @__PURE__ */ jsx32(Search5, { className: "h-8 w-8 opacity-20" }),
|
|
7044
7530
|
/* @__PURE__ */ jsx32("span", { className: "text-sm", children: "No results found" }),
|
|
7045
7531
|
search && /* @__PURE__ */ jsx32("button", { onClick: () => setSearch(""), className: "text-xs text-primary hover:underline", children: "Clear search" })
|
|
@@ -7048,85 +7534,168 @@ function Table({
|
|
|
7048
7534
|
) }) : paginatedData.map((item, i) => {
|
|
7049
7535
|
const id = String(item[idKey] || i);
|
|
7050
7536
|
const isSelected = selectedIds.includes(id);
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7537
|
+
const isExpanded = expandedIds.has(id);
|
|
7538
|
+
const isFocused = keyboardNavigation && focusedRowIdx === i;
|
|
7539
|
+
return /* @__PURE__ */ jsxs30(React28.Fragment, { children: [
|
|
7540
|
+
/* @__PURE__ */ jsxs30(
|
|
7541
|
+
"tr",
|
|
7542
|
+
{
|
|
7543
|
+
draggable,
|
|
7544
|
+
tabIndex: keyboardNavigation ? 0 : void 0,
|
|
7545
|
+
onDragStart: draggable ? (e) => {
|
|
7546
|
+
e.dataTransfer.setData("text/plain", id);
|
|
7547
|
+
} : void 0,
|
|
7548
|
+
onDragOver: draggable ? (e) => {
|
|
7549
|
+
e.preventDefault();
|
|
7550
|
+
setDragOverId(id);
|
|
7551
|
+
} : void 0,
|
|
7552
|
+
onDragLeave: draggable ? () => setDragOverId(null) : void 0,
|
|
7553
|
+
onDrop: draggable ? (e) => {
|
|
7554
|
+
e.preventDefault();
|
|
7555
|
+
setDragOverId(null);
|
|
7556
|
+
const fromId = e.dataTransfer.getData("text/plain");
|
|
7557
|
+
if (fromId === id) return;
|
|
7558
|
+
setTableData((prev) => {
|
|
7559
|
+
const fromIdx = prev.findIndex((r) => String(r[idKey] || "") === fromId);
|
|
7560
|
+
const toIdx = prev.findIndex((r) => String(r[idKey] || "") === id);
|
|
7561
|
+
if (fromIdx < 0 || toIdx < 0) return prev;
|
|
7562
|
+
const next = [...prev];
|
|
7563
|
+
const [moved] = next.splice(fromIdx, 1);
|
|
7564
|
+
next.splice(toIdx, 0, moved);
|
|
7565
|
+
onRowReorder?.(next);
|
|
7566
|
+
return next;
|
|
7567
|
+
});
|
|
7568
|
+
} : void 0,
|
|
7569
|
+
onClick: () => {
|
|
7570
|
+
if (expandable) setExpandedIds((prev) => {
|
|
7571
|
+
const s = new Set(prev);
|
|
7572
|
+
s.has(id) ? s.delete(id) : s.add(id);
|
|
7573
|
+
return s;
|
|
7574
|
+
});
|
|
7575
|
+
onRowClick?.(item);
|
|
7576
|
+
if (keyboardNavigation) setFocusedRowIdx(i);
|
|
7577
|
+
},
|
|
7578
|
+
onDoubleClick: () => onRowDoubleClick?.(item),
|
|
7579
|
+
className: cn(
|
|
7580
|
+
// default
|
|
7581
|
+
variant === "default" && "border-b border-border/60 transition-colors last:border-0",
|
|
7582
|
+
variant === "default" && (isSelected ? "bg-primary/5 hover:bg-primary/8" : "hover:bg-muted/30"),
|
|
7583
|
+
// zebra
|
|
7584
|
+
variant === "zebra" && "border-b border-border/40 transition-colors last:border-0",
|
|
7585
|
+
variant === "zebra" && (isSelected ? "bg-primary/8" : i % 2 === 0 ? "bg-card" : "bg-muted/40"),
|
|
7586
|
+
variant === "zebra" && !isSelected && "hover:bg-primary/5",
|
|
7587
|
+
// card
|
|
7588
|
+
variant === "card" && "rounded-xl border border-border bg-card shadow-sm transition-all hover:shadow-md hover:-translate-y-px",
|
|
7589
|
+
variant === "card" && (isSelected ? "border-primary/50 bg-primary/5" : ""),
|
|
7590
|
+
variant === "card" && "[&>td:first-child]:rounded-l-xl [&>td:last-child]:rounded-r-xl",
|
|
7591
|
+
// glass
|
|
7592
|
+
variant === "glass" && "border-b border-white/8 transition-colors last:border-0",
|
|
7593
|
+
variant === "glass" && (isSelected ? "bg-primary/15 hover:bg-primary/20" : "hover:bg-white/5"),
|
|
7594
|
+
// soft
|
|
7595
|
+
variant === "soft" && "transition-all",
|
|
7596
|
+
variant === "soft" && (isSelected ? "bg-primary/8 [box-shadow:inset_2px_2px_5px_hsl(var(--foreground)/0.06),inset_-2px_-2px_5px_hsl(var(--background)/0.7)]" : "hover:bg-muted/20"),
|
|
7597
|
+
variant === "soft" && "border-b border-border/30 last:border-0",
|
|
7598
|
+
(onRowClick || onRowDoubleClick || expandable) && "cursor-pointer",
|
|
7599
|
+
draggable && dragOverId === id && "ring-2 ring-inset ring-primary/40",
|
|
7600
|
+
isFocused && "ring-2 ring-inset ring-ring",
|
|
7601
|
+
rowClassName?.(item)
|
|
7602
|
+
),
|
|
7603
|
+
children: [
|
|
7604
|
+
selectable && /* @__PURE__ */ jsx32("td", { className: "px-4 py-3 align-middle", children: /* @__PURE__ */ jsx32(
|
|
7605
|
+
Checkbox,
|
|
7606
|
+
{
|
|
7607
|
+
checked: isSelected,
|
|
7608
|
+
onChange: (e) => handleSelect(id, e.target.checked)
|
|
7609
|
+
}
|
|
7080
7610
|
) }),
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7084
|
-
{
|
|
7085
|
-
value: item[col.key],
|
|
7086
|
-
onChange: (e) => col.onChange?.(item, e.target.value),
|
|
7087
|
-
className: "h-8 rounded-lg border border-border bg-background/50 px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-ring transition-colors",
|
|
7088
|
-
children: (col.selectOptions ?? []).map((opt) => /* @__PURE__ */ jsx32("option", { value: opt, children: opt }, opt))
|
|
7089
|
-
}
|
|
7090
|
-
) : col.type === "toggle" ? /* @__PURE__ */ jsx32(
|
|
7091
|
-
"button",
|
|
7092
|
-
{
|
|
7093
|
-
role: "switch",
|
|
7094
|
-
"aria-checked": !!item[col.key],
|
|
7095
|
-
onClick: () => col.onChange?.(item, !item[col.key]),
|
|
7096
|
-
className: cn(
|
|
7097
|
-
"relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
7098
|
-
item[col.key] ? "bg-primary" : "bg-muted"
|
|
7099
|
-
),
|
|
7100
|
-
children: /* @__PURE__ */ jsx32("span", { className: cn(
|
|
7101
|
-
"pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
|
|
7102
|
-
item[col.key] ? "translate-x-4" : "translate-x-0"
|
|
7103
|
-
) })
|
|
7104
|
-
}
|
|
7105
|
-
) : col.type === "color" ? /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
|
|
7106
|
-
/* @__PURE__ */ jsx32(
|
|
7107
|
-
"input",
|
|
7611
|
+
expandable && /* @__PURE__ */ jsx32("td", { className: "w-8 px-2 py-3 align-middle", children: /* @__PURE__ */ jsx32(ChevronRight8, { className: cn("h-3.5 w-3.5 text-muted-foreground transition-transform", isExpanded && "rotate-90") }) }),
|
|
7612
|
+
allColumns.map((col, ci) => /* @__PURE__ */ jsx32("td", { className: "px-4 py-3 align-middle", children: col.render ? col.render(item) : col.type === "image" ? /* @__PURE__ */ jsx32(
|
|
7613
|
+
"img",
|
|
7108
7614
|
{
|
|
7109
|
-
|
|
7110
|
-
|
|
7615
|
+
src: item[col.key],
|
|
7616
|
+
alt: item[col.key],
|
|
7617
|
+
className: "h-9 w-9 rounded-lg object-cover ring-1 ring-border"
|
|
7618
|
+
}
|
|
7619
|
+
) : col.type === "badge" ? /* @__PURE__ */ jsxs30("span", { className: cn(
|
|
7620
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium",
|
|
7621
|
+
badgeClass(String(item[col.key]))
|
|
7622
|
+
), children: [
|
|
7623
|
+
/* @__PURE__ */ jsx32("span", { className: cn(
|
|
7624
|
+
"mr-1.5 h-1.5 w-1.5 rounded-full",
|
|
7625
|
+
badgeClass(String(item[col.key])).includes("success") ? "bg-success" : badgeClass(String(item[col.key])).includes("warning") ? "bg-warning" : badgeClass(String(item[col.key])).includes("danger") ? "bg-danger" : badgeClass(String(item[col.key])).includes("info") ? "bg-info" : "bg-primary"
|
|
7626
|
+
) }),
|
|
7627
|
+
item[col.key]
|
|
7628
|
+
] }) : col.type === "stack" ? /* @__PURE__ */ jsx32(AvatarStack, { images: Array.isArray(item[col.key]) ? item[col.key] : [], ...col.stackProps ?? {} }) : col.type === "icon" ? /* @__PURE__ */ jsx32("span", { className: "flex items-center", children: item[col.key] }) : col.type === "select" ? /* @__PURE__ */ jsx32(
|
|
7629
|
+
"select",
|
|
7630
|
+
{
|
|
7631
|
+
value: item[col.key],
|
|
7111
7632
|
onChange: (e) => col.onChange?.(item, e.target.value),
|
|
7112
|
-
className: "h-
|
|
7633
|
+
className: "h-8 rounded-lg border border-border bg-background/50 px-2 text-xs text-foreground focus:outline-none focus:ring-2 focus:ring-ring transition-colors",
|
|
7634
|
+
children: (col.selectOptions ?? []).map((opt) => /* @__PURE__ */ jsx32("option", { value: opt, children: opt }, opt))
|
|
7113
7635
|
}
|
|
7114
|
-
)
|
|
7115
|
-
|
|
7116
|
-
|
|
7117
|
-
|
|
7118
|
-
|
|
7119
|
-
|
|
7120
|
-
|
|
7121
|
-
|
|
7122
|
-
|
|
7123
|
-
|
|
7124
|
-
|
|
7125
|
-
|
|
7126
|
-
|
|
7636
|
+
) : col.type === "toggle" ? /* @__PURE__ */ jsx32(
|
|
7637
|
+
"button",
|
|
7638
|
+
{
|
|
7639
|
+
role: "switch",
|
|
7640
|
+
"aria-checked": !!item[col.key],
|
|
7641
|
+
onClick: () => col.onChange?.(item, !item[col.key]),
|
|
7642
|
+
className: cn(
|
|
7643
|
+
"relative inline-flex h-5 w-9 shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
7644
|
+
item[col.key] ? "bg-primary" : "bg-muted"
|
|
7645
|
+
),
|
|
7646
|
+
children: /* @__PURE__ */ jsx32("span", { className: cn(
|
|
7647
|
+
"pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
|
|
7648
|
+
item[col.key] ? "translate-x-4" : "translate-x-0"
|
|
7649
|
+
) })
|
|
7650
|
+
}
|
|
7651
|
+
) : col.type === "color" ? /* @__PURE__ */ jsxs30("div", { className: "flex items-center gap-2", children: [
|
|
7652
|
+
/* @__PURE__ */ jsx32(
|
|
7653
|
+
"input",
|
|
7654
|
+
{
|
|
7655
|
+
type: "color",
|
|
7656
|
+
value: item[col.key] || "#000000",
|
|
7657
|
+
onChange: (e) => col.onChange?.(item, e.target.value),
|
|
7658
|
+
className: "h-7 w-7 cursor-pointer rounded border border-border bg-transparent p-0.5"
|
|
7659
|
+
}
|
|
7660
|
+
),
|
|
7661
|
+
/* @__PURE__ */ jsx32("span", { className: "text-xs text-muted-foreground font-mono", children: item[col.key] })
|
|
7662
|
+
] }) : col.type === "checkbox" ? /* @__PURE__ */ jsx32(
|
|
7663
|
+
Checkbox,
|
|
7664
|
+
{
|
|
7665
|
+
checked: !!item[col.key],
|
|
7666
|
+
onChange: (e) => col.onChange?.(item, e.target.checked)
|
|
7667
|
+
}
|
|
7668
|
+
) : col.type === "text-url" ? (() => {
|
|
7669
|
+
const href = col.redirect ? typeof col.redirect === "function" ? col.redirect(item) : col.redirect : String(item[col.key] ?? "");
|
|
7670
|
+
const colorMap = {
|
|
7671
|
+
primary: "var(--primary)",
|
|
7672
|
+
info: "var(--info)",
|
|
7673
|
+
success: "var(--success)",
|
|
7674
|
+
warning: "var(--warning)",
|
|
7675
|
+
danger: "var(--danger)"
|
|
7676
|
+
};
|
|
7677
|
+
const underline = col.underlineColor ? colorMap[col.underlineColor] ?? col.underlineColor : "var(--primary)";
|
|
7678
|
+
return /* @__PURE__ */ jsx32(
|
|
7679
|
+
"a",
|
|
7680
|
+
{
|
|
7681
|
+
href,
|
|
7682
|
+
target: col.openNewTab ? "_blank" : void 0,
|
|
7683
|
+
rel: col.openNewTab ? "noopener noreferrer" : void 0,
|
|
7684
|
+
style: { textDecorationColor: underline },
|
|
7685
|
+
className: "text-sm underline underline-offset-2 hover:opacity-75 transition-opacity break-all",
|
|
7686
|
+
onClick: col.openNewTab ? void 0 : (e) => e.preventDefault(),
|
|
7687
|
+
children: item[col.key]
|
|
7688
|
+
}
|
|
7689
|
+
);
|
|
7690
|
+
})() : /* @__PURE__ */ jsx32("span", { className: "text-foreground/90", children: item[col.key] }) }, `${String(col.key)}-${ci}`))
|
|
7691
|
+
]
|
|
7692
|
+
}
|
|
7693
|
+
),
|
|
7694
|
+
expandable && isExpanded && renderExpanded && /* @__PURE__ */ jsx32("tr", { className: "bg-muted/20 border-b border-border/60", children: /* @__PURE__ */ jsx32("td", { colSpan: allColumns.length + (selectable ? 1 : 0) + 1, className: "px-6 py-3", children: renderExpanded(item) }) })
|
|
7695
|
+
] }, id);
|
|
7127
7696
|
}) })
|
|
7128
7697
|
] }) }) }),
|
|
7129
|
-
|
|
7698
|
+
clientPagination && !serverPagination && totalPages > 1 && /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
7130
7699
|
/* @__PURE__ */ jsxs30("span", { className: "text-xs text-muted-foreground", children: [
|
|
7131
7700
|
"Showing ",
|
|
7132
7701
|
(safePage - 1) * itemsPerPage + 1,
|
|
@@ -7145,7 +7714,7 @@ function Table({
|
|
|
7145
7714
|
children: /* @__PURE__ */ jsx32(ChevronLeft6, { className: "h-4 w-4" })
|
|
7146
7715
|
}
|
|
7147
7716
|
),
|
|
7148
|
-
pagePills[0] > 1 && /* @__PURE__ */ jsxs30(
|
|
7717
|
+
pagePills[0] > 1 && /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
7149
7718
|
/* @__PURE__ */ jsx32("button", { onClick: () => setCurrentPage(1), className: "flex h-8 w-8 items-center justify-center rounded-lg border border-border text-xs text-muted-foreground hover:bg-muted transition-colors", children: "1" }),
|
|
7150
7719
|
pagePills[0] > 2 && /* @__PURE__ */ jsx32("span", { className: "px-1 text-muted-foreground text-xs", children: "\u2026" })
|
|
7151
7720
|
] }),
|
|
@@ -7161,7 +7730,7 @@ function Table({
|
|
|
7161
7730
|
},
|
|
7162
7731
|
p
|
|
7163
7732
|
)),
|
|
7164
|
-
pagePills[pagePills.length - 1] < totalPages && /* @__PURE__ */ jsxs30(
|
|
7733
|
+
pagePills[pagePills.length - 1] < totalPages && /* @__PURE__ */ jsxs30(Fragment12, { children: [
|
|
7165
7734
|
pagePills[pagePills.length - 1] < totalPages - 1 && /* @__PURE__ */ jsx32("span", { className: "px-1 text-muted-foreground text-xs", children: "\u2026" }),
|
|
7166
7735
|
/* @__PURE__ */ jsx32("button", { onClick: () => setCurrentPage(totalPages), className: "flex h-8 w-8 items-center justify-center rounded-lg border border-border text-xs text-muted-foreground hover:bg-muted transition-colors", children: totalPages })
|
|
7167
7736
|
] }),
|
|
@@ -7177,8 +7746,8 @@ function Table({
|
|
|
7177
7746
|
] })
|
|
7178
7747
|
] }),
|
|
7179
7748
|
serverPagination && (() => {
|
|
7180
|
-
const { pagination
|
|
7181
|
-
const totalServerPages =
|
|
7749
|
+
const { pagination, currentPage: cp, goToPage } = serverPagination;
|
|
7750
|
+
const totalServerPages = pagination.last_page ?? Math.ceil(pagination.total / pagination.per_page);
|
|
7182
7751
|
const pills = [];
|
|
7183
7752
|
if (totalServerPages <= 7) {
|
|
7184
7753
|
for (let i = 1; i <= totalServerPages; i++) pills.push(i);
|
|
@@ -7191,7 +7760,7 @@ function Table({
|
|
|
7191
7760
|
}
|
|
7192
7761
|
return /* @__PURE__ */ jsxs30("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
7193
7762
|
/* @__PURE__ */ jsxs30("span", { className: "text-xs text-muted-foreground", children: [
|
|
7194
|
-
|
|
7763
|
+
pagination.total,
|
|
7195
7764
|
" total rows \xB7 page ",
|
|
7196
7765
|
cp,
|
|
7197
7766
|
" of ",
|
|
@@ -7202,7 +7771,7 @@ function Table({
|
|
|
7202
7771
|
"button",
|
|
7203
7772
|
{
|
|
7204
7773
|
onClick: () => goToPage(cp - 1),
|
|
7205
|
-
disabled: !
|
|
7774
|
+
disabled: !pagination.prev_page_url,
|
|
7206
7775
|
className: "flex h-8 w-8 items-center justify-center rounded-lg border border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-40 disabled:pointer-events-none",
|
|
7207
7776
|
children: /* @__PURE__ */ jsx32(ChevronLeft6, { className: "h-4 w-4" })
|
|
7208
7777
|
}
|
|
@@ -7225,7 +7794,7 @@ function Table({
|
|
|
7225
7794
|
"button",
|
|
7226
7795
|
{
|
|
7227
7796
|
onClick: () => goToPage(cp + 1),
|
|
7228
|
-
disabled: !
|
|
7797
|
+
disabled: !pagination.next_page_url,
|
|
7229
7798
|
className: "flex h-8 w-8 items-center justify-center rounded-lg border border-border text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-40 disabled:pointer-events-none",
|
|
7230
7799
|
children: /* @__PURE__ */ jsx32(ChevronRight8, { className: "h-4 w-4" })
|
|
7231
7800
|
}
|
|
@@ -7240,6 +7809,7 @@ function Table({
|
|
|
7240
7809
|
item: viewItem,
|
|
7241
7810
|
fields: viewFields,
|
|
7242
7811
|
width: defaultActions.modalWidth,
|
|
7812
|
+
grid: defaultActions.viewFormGrid,
|
|
7243
7813
|
onClose: () => setViewItem(null)
|
|
7244
7814
|
}
|
|
7245
7815
|
),
|
|
@@ -7302,7 +7872,7 @@ function Table({
|
|
|
7302
7872
|
}
|
|
7303
7873
|
|
|
7304
7874
|
// src/components/ui/data-grid.tsx
|
|
7305
|
-
import { Fragment as
|
|
7875
|
+
import { Fragment as Fragment13, jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
7306
7876
|
function useServerDataGrid({ url, params, encrypt, key, decryptPayloadLog, columnOverrides }) {
|
|
7307
7877
|
const [data, setData] = React29.useState([]);
|
|
7308
7878
|
const [columns, setColumns] = React29.useState([]);
|
|
@@ -7430,7 +8000,7 @@ function DGModalShell({ title, onClose, children, footer, width = "lg" }) {
|
|
|
7430
8000
|
);
|
|
7431
8001
|
}
|
|
7432
8002
|
function DGFieldRenderer({ field, value, onChange }) {
|
|
7433
|
-
if (field.render) return /* @__PURE__ */ jsx33(
|
|
8003
|
+
if (field.render) return /* @__PURE__ */ jsx33(Fragment13, { children: field.render(value, onChange) });
|
|
7434
8004
|
const toLabelValue = (o) => {
|
|
7435
8005
|
if (typeof o === "string") return { label: o, value: o };
|
|
7436
8006
|
if (Array.isArray(o)) return { label: o[0], value: o[1] };
|
|
@@ -7510,7 +8080,7 @@ function DGViewModal({ item, fields, onClose, width }) {
|
|
|
7510
8080
|
footer: /* @__PURE__ */ jsx33("button", { onClick: onClose, className: "px-4 py-1.5 text-sm rounded-xl border border-border hover:bg-accent transition-colors", children: "Close" }),
|
|
7511
8081
|
children: /* @__PURE__ */ jsx33("div", { className: "space-y-3", children: fields.map((f) => /* @__PURE__ */ jsxs31("div", { children: [
|
|
7512
8082
|
/* @__PURE__ */ jsx33("p", { className: "text-xs font-semibold text-muted-foreground mb-1", children: f.label }),
|
|
7513
|
-
f.render ? /* @__PURE__ */ jsx33(
|
|
8083
|
+
f.render ? /* @__PURE__ */ jsx33(Fragment13, { children: f.render(item[f.key], () => {
|
|
7514
8084
|
}) }) : /* @__PURE__ */ jsx33("p", { className: "text-sm text-foreground break-words", children: item[f.key] == null || item[f.key] === "" ? /* @__PURE__ */ jsx33("span", { className: "text-muted-foreground italic", children: "\u2014" }) : String(item[f.key]) })
|
|
7515
8085
|
] }, f.key)) })
|
|
7516
8086
|
}
|
|
@@ -7574,7 +8144,7 @@ function DGEditModal({
|
|
|
7574
8144
|
title: "Edit Record",
|
|
7575
8145
|
onClose,
|
|
7576
8146
|
width,
|
|
7577
|
-
footer: /* @__PURE__ */ jsxs31(
|
|
8147
|
+
footer: /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
7578
8148
|
/* @__PURE__ */ jsx33("button", { onClick: onClose, disabled: loading, className: "px-4 py-1.5 text-sm rounded-xl border border-border hover:bg-accent transition-colors", children: "Cancel" }),
|
|
7579
8149
|
/* @__PURE__ */ jsxs31("button", { onClick: handleSubmit, disabled: loading, className: "px-4 py-1.5 text-sm rounded-xl bg-primary text-primary-foreground hover:bg-primary-hover transition-colors flex items-center gap-1.5", children: [
|
|
7580
8150
|
loading && /* @__PURE__ */ jsx33(Loader23, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
@@ -7634,7 +8204,7 @@ function DGDeleteModal({
|
|
|
7634
8204
|
title: "Confirm Delete",
|
|
7635
8205
|
onClose,
|
|
7636
8206
|
width: "lg",
|
|
7637
|
-
footer: /* @__PURE__ */ jsxs31(
|
|
8207
|
+
footer: /* @__PURE__ */ jsxs31(Fragment13, { children: [
|
|
7638
8208
|
/* @__PURE__ */ jsx33("button", { onClick: onClose, disabled: loading, className: "px-4 py-1.5 text-sm rounded-xl border border-border hover:bg-accent transition-colors", children: "Cancel" }),
|
|
7639
8209
|
/* @__PURE__ */ jsxs31("button", { onClick: handleDelete, disabled: loading, className: "px-4 py-1.5 text-sm rounded-xl bg-danger text-danger-foreground hover:bg-danger-hover transition-colors flex items-center gap-1.5", children: [
|
|
7640
8210
|
loading && /* @__PURE__ */ jsx33(Loader23, { className: "h-3.5 w-3.5 animate-spin" }),
|
|
@@ -8566,7 +9136,7 @@ function KanbanBoard({ columns: controlled, onChange, onAddCard, className }) {
|
|
|
8566
9136
|
import * as React33 from "react";
|
|
8567
9137
|
import { MapContainer, TileLayer, Marker, Popup, Polyline, useMap, CircleMarker } from "react-leaflet";
|
|
8568
9138
|
import L from "leaflet";
|
|
8569
|
-
import { Fragment as
|
|
9139
|
+
import { Fragment as Fragment15, jsx as jsx39, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
8570
9140
|
L.Icon.Default.mergeOptions({
|
|
8571
9141
|
iconUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon.png",
|
|
8572
9142
|
iconRetinaUrl: "https://unpkg.com/leaflet@1.9.4/dist/images/marker-icon-2x.png",
|
|
@@ -8672,7 +9242,7 @@ function RouteLayer({ routes }) {
|
|
|
8672
9242
|
});
|
|
8673
9243
|
}, [routes]);
|
|
8674
9244
|
if (loading) return null;
|
|
8675
|
-
return /* @__PURE__ */ jsx39(
|
|
9245
|
+
return /* @__PURE__ */ jsx39(Fragment15, { children: resolved.map((r, i) => {
|
|
8676
9246
|
const color = r.route.color ?? (r.route.routeType === "walk" ? "#22c55e" : "#6366f1");
|
|
8677
9247
|
const isDrive = (r.route.routeType ?? "drive") === "drive";
|
|
8678
9248
|
const midIdx = Math.floor(r.coords.length / 2);
|
|
@@ -8712,7 +9282,7 @@ function RouteLayer({ routes }) {
|
|
|
8712
9282
|
zIndexOffset: 100,
|
|
8713
9283
|
children: /* @__PURE__ */ jsx39(Popup, { children: /* @__PURE__ */ jsxs35("div", { className: "text-xs space-y-0.5 min-w-[120px]", children: [
|
|
8714
9284
|
/* @__PURE__ */ jsx39("p", { className: "font-semibold", children: r.route.label ? `${r.route.label} \u2014 Start` : "Start" }),
|
|
8715
|
-
r.distance > 0 && /* @__PURE__ */ jsxs35(
|
|
9285
|
+
r.distance > 0 && /* @__PURE__ */ jsxs35(Fragment15, { children: [
|
|
8716
9286
|
/* @__PURE__ */ jsx39("p", { className: "text-muted-foreground", children: fmtDistance(r.distance) }),
|
|
8717
9287
|
/* @__PURE__ */ jsxs35("p", { className: "text-muted-foreground", children: [
|
|
8718
9288
|
fmtDuration(r.duration),
|
|
@@ -8731,7 +9301,7 @@ function RouteLayer({ routes }) {
|
|
|
8731
9301
|
zIndexOffset: 100,
|
|
8732
9302
|
children: /* @__PURE__ */ jsx39(Popup, { children: /* @__PURE__ */ jsxs35("div", { className: "text-xs space-y-0.5 min-w-[120px]", children: [
|
|
8733
9303
|
/* @__PURE__ */ jsx39("p", { className: "font-semibold", children: r.route.label ? `${r.route.label} \u2014 End` : "End" }),
|
|
8734
|
-
r.distance > 0 && /* @__PURE__ */ jsxs35(
|
|
9304
|
+
r.distance > 0 && /* @__PURE__ */ jsxs35(Fragment15, { children: [
|
|
8735
9305
|
/* @__PURE__ */ jsx39("p", { className: "text-muted-foreground", children: fmtDistance(r.distance) }),
|
|
8736
9306
|
/* @__PURE__ */ jsxs35("p", { className: "text-muted-foreground", children: [
|
|
8737
9307
|
fmtDuration(r.duration),
|
|
@@ -8846,7 +9416,7 @@ function ClusterLayer({ markers, variant, onMarkerClick }) {
|
|
|
8846
9416
|
});
|
|
8847
9417
|
return groups;
|
|
8848
9418
|
}, [markers, zoom, map]);
|
|
8849
|
-
return /* @__PURE__ */ jsx39(
|
|
9419
|
+
return /* @__PURE__ */ jsx39(Fragment15, { children: clusters.map((g, gi) => {
|
|
8850
9420
|
if (g.items.length === 1) {
|
|
8851
9421
|
const m = g.items[0];
|
|
8852
9422
|
const color2 = resolveColor(m.color);
|
|
@@ -9715,7 +10285,7 @@ function Modal({
|
|
|
9715
10285
|
// src/components/ui/modal-variants.tsx
|
|
9716
10286
|
import * as React36 from "react";
|
|
9717
10287
|
import { AlertTriangle as AlertTriangle3, CheckCircle as CheckCircle2, Trash2 as Trash23, X as X13 } from "lucide-react";
|
|
9718
|
-
import { Fragment as
|
|
10288
|
+
import { Fragment as Fragment16, jsx as jsx42, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
9719
10289
|
function ModalBase({
|
|
9720
10290
|
isOpen,
|
|
9721
10291
|
onClose,
|
|
@@ -9866,7 +10436,7 @@ function ModalWithForms({
|
|
|
9866
10436
|
onSubmit(values);
|
|
9867
10437
|
}
|
|
9868
10438
|
function renderField(field) {
|
|
9869
|
-
if (field.render) return /* @__PURE__ */ jsx42(
|
|
10439
|
+
if (field.render) return /* @__PURE__ */ jsx42(Fragment16, { children: field.render(values[field.name], (v) => handleChange(field.name, v)) });
|
|
9870
10440
|
const strOptions = (field.options ?? []).map(
|
|
9871
10441
|
(o) => typeof o === "string" ? { label: o, value: o } : o
|
|
9872
10442
|
);
|
|
@@ -10214,7 +10784,7 @@ import { PanelLeftClose, PanelLeftOpen, Sun as Sun3, Moon as Moon2, Loader2 as L
|
|
|
10214
10784
|
// src/components/ui/tooltip.tsx
|
|
10215
10785
|
import * as React38 from "react";
|
|
10216
10786
|
import * as ReactDOM2 from "react-dom";
|
|
10217
|
-
import { Fragment as
|
|
10787
|
+
import { Fragment as Fragment17, jsx as jsx44, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
10218
10788
|
function Tooltip({
|
|
10219
10789
|
content,
|
|
10220
10790
|
children,
|
|
@@ -10225,7 +10795,7 @@ function Tooltip({
|
|
|
10225
10795
|
const [visible, setVisible] = React38.useState(false);
|
|
10226
10796
|
const [coords, setCoords] = React38.useState({ top: 0, left: 0 });
|
|
10227
10797
|
const ref = React38.useRef(null);
|
|
10228
|
-
if (!enabled) return /* @__PURE__ */ jsx44(
|
|
10798
|
+
if (!enabled) return /* @__PURE__ */ jsx44(Fragment17, { children });
|
|
10229
10799
|
function calcCoords() {
|
|
10230
10800
|
const r = ref.current?.getBoundingClientRect();
|
|
10231
10801
|
if (!r) return;
|
|
@@ -10822,7 +11392,7 @@ var useTheme = () => {
|
|
|
10822
11392
|
};
|
|
10823
11393
|
|
|
10824
11394
|
// src/components/ui/panel.tsx
|
|
10825
|
-
import { Fragment as
|
|
11395
|
+
import { Fragment as Fragment18, jsx as jsx46, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
10826
11396
|
var PanelCollapsedContext = React40.createContext(false);
|
|
10827
11397
|
var PanelGroupsContext = React40.createContext({ expandedGroups: /* @__PURE__ */ new Set(), onGroupToggle: () => {
|
|
10828
11398
|
} });
|
|
@@ -10984,7 +11554,7 @@ function Panel({
|
|
|
10984
11554
|
"shrink-0 border-b border-border",
|
|
10985
11555
|
effectiveCollapsed ? "flex items-center justify-center py-3" : "flex items-center gap-2 px-4 py-3"
|
|
10986
11556
|
),
|
|
10987
|
-
children: sidebarBrand ? effectiveCollapsed ? sidebarBrand.image ? /* @__PURE__ */ jsx46("img", { src: sidebarBrand.image, alt: "logo", className: "h-7 w-7 rounded-md object-cover shrink-0" }) : /* @__PURE__ */ jsx46("span", { className: "shrink-0", children: sidebarBrand.icon }) : /* @__PURE__ */ jsxs41(
|
|
11557
|
+
children: sidebarBrand ? effectiveCollapsed ? sidebarBrand.image ? /* @__PURE__ */ jsx46("img", { src: sidebarBrand.image, alt: "logo", className: "h-7 w-7 rounded-md object-cover shrink-0" }) : /* @__PURE__ */ jsx46("span", { className: "shrink-0", children: sidebarBrand.icon }) : /* @__PURE__ */ jsxs41(Fragment18, { children: [
|
|
10988
11558
|
sidebarBrand.image ? /* @__PURE__ */ jsx46("img", { src: sidebarBrand.image, alt: "logo", className: "h-7 w-7 rounded-md object-cover shrink-0" }) : sidebarBrand.icon && /* @__PURE__ */ jsx46("span", { className: "shrink-0", children: sidebarBrand.icon }),
|
|
10989
11559
|
sidebarBrand.title && /* @__PURE__ */ jsx46("span", { className: "flex-1 truncate text-sm font-semibold", children: sidebarBrand.title }),
|
|
10990
11560
|
sidebarBrand.trailing && /* @__PURE__ */ jsx46("span", { className: "shrink-0", children: sidebarBrand.trailing })
|
|
@@ -12293,7 +12863,7 @@ function Widget({
|
|
|
12293
12863
|
// src/components/ui/wizard.tsx
|
|
12294
12864
|
import * as React50 from "react";
|
|
12295
12865
|
import { Check as Check7, X as X15, ChevronLeft as ChevronLeft8, ChevronRight as ChevronRight12, AlertCircle as AlertCircle2 } from "lucide-react";
|
|
12296
|
-
import { Fragment as
|
|
12866
|
+
import { Fragment as Fragment21, jsx as jsx62, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
12297
12867
|
var SIZE_MAP = {
|
|
12298
12868
|
sm: "max-w-sm",
|
|
12299
12869
|
md: "max-w-lg",
|
|
@@ -12503,10 +13073,10 @@ function DefaultActions({
|
|
|
12503
13073
|
/* @__PURE__ */ jsx62("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8v8z" })
|
|
12504
13074
|
] }),
|
|
12505
13075
|
"Processing..."
|
|
12506
|
-
] }) : isLast ? /* @__PURE__ */ jsxs55(
|
|
13076
|
+
] }) : isLast ? /* @__PURE__ */ jsxs55(Fragment21, { children: [
|
|
12507
13077
|
/* @__PURE__ */ jsx62(Check7, { className: "h-4 w-4" }),
|
|
12508
13078
|
finishLabel ?? "Finish"
|
|
12509
|
-
] }) : /* @__PURE__ */ jsxs55(
|
|
13079
|
+
] }) : /* @__PURE__ */ jsxs55(Fragment21, { children: [
|
|
12510
13080
|
nextLabel ?? "Next",
|
|
12511
13081
|
/* @__PURE__ */ jsx62(ChevronRight12, { className: "h-4 w-4" })
|
|
12512
13082
|
] })
|
|
@@ -12815,13 +13385,13 @@ var setupInterceptors = () => {
|
|
|
12815
13385
|
|
|
12816
13386
|
// src/lib/codego/provider.tsx
|
|
12817
13387
|
import * as React51 from "react";
|
|
12818
|
-
import { Fragment as
|
|
13388
|
+
import { Fragment as Fragment22, jsx as jsx63 } from "react/jsx-runtime";
|
|
12819
13389
|
function CodegoApiProvider({ children }) {
|
|
12820
13390
|
const { toast } = useToast();
|
|
12821
13391
|
React51.useEffect(() => {
|
|
12822
13392
|
setToastFunction(toast);
|
|
12823
13393
|
}, [toast]);
|
|
12824
|
-
return /* @__PURE__ */ jsx63(
|
|
13394
|
+
return /* @__PURE__ */ jsx63(Fragment22, { children });
|
|
12825
13395
|
}
|
|
12826
13396
|
|
|
12827
13397
|
// src/lib/codego/index.ts
|