@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.cjs
CHANGED
|
@@ -5906,11 +5906,77 @@ function FileUpload({
|
|
|
5906
5906
|
// src/components/ui/repeater.tsx
|
|
5907
5907
|
var import_lucide_react15 = require("lucide-react");
|
|
5908
5908
|
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
5909
|
+
function RepeaterFieldRenderer({
|
|
5910
|
+
field,
|
|
5911
|
+
value,
|
|
5912
|
+
onChange
|
|
5913
|
+
}) {
|
|
5914
|
+
if (field.type === "image") {
|
|
5915
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
5916
|
+
field.label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
|
|
5917
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-3", children: [
|
|
5918
|
+
value && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("img", { src: value, alt: field.key, className: "h-10 w-10 rounded-lg object-cover ring-1 ring-border shrink-0" }),
|
|
5919
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
5920
|
+
Input,
|
|
5921
|
+
{
|
|
5922
|
+
inputMode: "text",
|
|
5923
|
+
value: value ?? "",
|
|
5924
|
+
onChange: (e) => onChange(e.target.value),
|
|
5925
|
+
placeholder: field.placeholder ?? "Image URL"
|
|
5926
|
+
}
|
|
5927
|
+
)
|
|
5928
|
+
] })
|
|
5929
|
+
] });
|
|
5930
|
+
}
|
|
5931
|
+
if (field.type === "attachment") {
|
|
5932
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
5933
|
+
field.label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
|
|
5934
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
5935
|
+
value && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
5936
|
+
"a",
|
|
5937
|
+
{
|
|
5938
|
+
href: value,
|
|
5939
|
+
target: "_blank",
|
|
5940
|
+
rel: "noopener noreferrer",
|
|
5941
|
+
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",
|
|
5942
|
+
children: [
|
|
5943
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.Paperclip, { className: "h-3 w-3" }),
|
|
5944
|
+
String(value).split("/").pop()
|
|
5945
|
+
]
|
|
5946
|
+
}
|
|
5947
|
+
),
|
|
5948
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
5949
|
+
Input,
|
|
5950
|
+
{
|
|
5951
|
+
inputMode: "text",
|
|
5952
|
+
value: value ?? "",
|
|
5953
|
+
onChange: (e) => onChange(e.target.value),
|
|
5954
|
+
placeholder: field.placeholder ?? "Attachment URL"
|
|
5955
|
+
}
|
|
5956
|
+
)
|
|
5957
|
+
] })
|
|
5958
|
+
] });
|
|
5959
|
+
}
|
|
5960
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
|
|
5961
|
+
field.label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
|
|
5962
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
5963
|
+
Input,
|
|
5964
|
+
{
|
|
5965
|
+
inputMode: "text",
|
|
5966
|
+
value: value ?? "",
|
|
5967
|
+
onChange: (e) => onChange(e.target.value),
|
|
5968
|
+
placeholder: field.placeholder ?? field.key
|
|
5969
|
+
}
|
|
5970
|
+
)
|
|
5971
|
+
] });
|
|
5972
|
+
}
|
|
5909
5973
|
function Repeater({
|
|
5910
5974
|
items,
|
|
5911
5975
|
onAdd,
|
|
5912
5976
|
onRemove,
|
|
5913
5977
|
renderItem,
|
|
5978
|
+
fields,
|
|
5979
|
+
onFieldChange,
|
|
5914
5980
|
addButtonText = "Add Item",
|
|
5915
5981
|
className
|
|
5916
5982
|
}) {
|
|
@@ -5923,7 +5989,15 @@ function Repeater({
|
|
|
5923
5989
|
children: [
|
|
5924
5990
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "mt-1 cursor-grab text-muted-foreground/30 group-hover:text-muted-foreground/60 transition-colors shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react15.GripVertical, { className: "h-4 w-4" }) }),
|
|
5925
5991
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("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 }),
|
|
5926
|
-
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex-1 min-w-0", children:
|
|
5992
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex-1 min-w-0", children: fields ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("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__ */ (0, import_jsx_runtime29.jsx)(
|
|
5993
|
+
RepeaterFieldRenderer,
|
|
5994
|
+
{
|
|
5995
|
+
field: f,
|
|
5996
|
+
value: item[f.key],
|
|
5997
|
+
onChange: (v) => onFieldChange?.(index, f.key, v)
|
|
5998
|
+
},
|
|
5999
|
+
f.key
|
|
6000
|
+
)) }) : renderItem ? renderItem(item, index) : null }),
|
|
5927
6001
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
5928
6002
|
Button,
|
|
5929
6003
|
{
|
|
@@ -6496,8 +6570,14 @@ function useServerTable({ url, params, encrypt, key, decryptPayloadLog, columnOv
|
|
|
6496
6570
|
goToPage: (page) => setCurrentPage(page),
|
|
6497
6571
|
reload: () => setTick((t) => t + 1),
|
|
6498
6572
|
refresh: () => setTick((t) => t + 1),
|
|
6573
|
+
// Passthrough props
|
|
6499
6574
|
searchValue,
|
|
6500
|
-
onSearchChange: handleSearchChange
|
|
6575
|
+
onSearchChange: handleSearchChange,
|
|
6576
|
+
page: currentPage,
|
|
6577
|
+
onPageChange: (page) => setCurrentPage(page),
|
|
6578
|
+
sort: [],
|
|
6579
|
+
onSortChange: () => {
|
|
6580
|
+
}
|
|
6501
6581
|
};
|
|
6502
6582
|
}
|
|
6503
6583
|
var MODAL_WIDTH = {
|
|
@@ -6653,6 +6733,28 @@ function FieldRenderer({ field, value, onChange }) {
|
|
|
6653
6733
|
} });
|
|
6654
6734
|
case "repeater": {
|
|
6655
6735
|
const items = Array.isArray(value) ? value : [];
|
|
6736
|
+
if (field.repeaterFields) {
|
|
6737
|
+
const rows = Array.isArray(value) ? value : [];
|
|
6738
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6739
|
+
Repeater,
|
|
6740
|
+
{
|
|
6741
|
+
items: rows,
|
|
6742
|
+
fields: field.repeaterFields,
|
|
6743
|
+
onAdd: () => {
|
|
6744
|
+
const blank = {};
|
|
6745
|
+
field.repeaterFields.forEach((f) => {
|
|
6746
|
+
blank[f.key] = "";
|
|
6747
|
+
});
|
|
6748
|
+
onChange([...rows, blank]);
|
|
6749
|
+
},
|
|
6750
|
+
onRemove: (i) => onChange(rows.filter((_, idx) => idx !== i)),
|
|
6751
|
+
onFieldChange: (i, key, val) => {
|
|
6752
|
+
const next = rows.map((r, idx) => idx === i ? { ...r, [key]: val } : r);
|
|
6753
|
+
onChange(next);
|
|
6754
|
+
}
|
|
6755
|
+
}
|
|
6756
|
+
);
|
|
6757
|
+
}
|
|
6656
6758
|
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6657
6759
|
Repeater,
|
|
6658
6760
|
{
|
|
@@ -6693,8 +6795,172 @@ function ViewModal({
|
|
|
6693
6795
|
item,
|
|
6694
6796
|
fields,
|
|
6695
6797
|
onClose,
|
|
6696
|
-
width
|
|
6798
|
+
width,
|
|
6799
|
+
grid
|
|
6697
6800
|
}) {
|
|
6801
|
+
const renderViewValue = (f, value) => {
|
|
6802
|
+
const sizeStyle = {
|
|
6803
|
+
...f.width ? { width: typeof f.width === "number" ? `${f.width}px` : f.width } : {},
|
|
6804
|
+
...f.height ? { height: typeof f.height === "number" ? `${f.height}px` : f.height } : {}
|
|
6805
|
+
};
|
|
6806
|
+
const vt = f.viewType ?? f.type;
|
|
6807
|
+
const empty = value === null || value === void 0 || value === "";
|
|
6808
|
+
const dash = /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-muted-foreground italic text-sm", children: "\u2014" });
|
|
6809
|
+
if (f.component) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: f.component });
|
|
6810
|
+
if (f.render) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children: f.render(value, () => {
|
|
6811
|
+
}) });
|
|
6812
|
+
switch (vt) {
|
|
6813
|
+
case "image":
|
|
6814
|
+
return empty ? dash : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6815
|
+
"img",
|
|
6816
|
+
{
|
|
6817
|
+
src: value,
|
|
6818
|
+
alt: f.label,
|
|
6819
|
+
className: "rounded-xl object-cover ring-1 ring-border",
|
|
6820
|
+
style: { width: sizeStyle.width ?? 128, height: sizeStyle.height ?? 128 }
|
|
6821
|
+
}
|
|
6822
|
+
);
|
|
6823
|
+
case "image-url":
|
|
6824
|
+
return empty ? dash : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6825
|
+
"a",
|
|
6826
|
+
{
|
|
6827
|
+
href: value,
|
|
6828
|
+
onClick: (e) => e.preventDefault(),
|
|
6829
|
+
className: "inline-block rounded-xl overflow-hidden ring-1 ring-border hover:ring-primary transition-all",
|
|
6830
|
+
style: { width: sizeStyle.width ?? 128, height: sizeStyle.height ?? 128 },
|
|
6831
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("img", { src: value, alt: f.label, className: "w-full h-full object-cover" })
|
|
6832
|
+
}
|
|
6833
|
+
);
|
|
6834
|
+
case "image-url-open-other-tabs":
|
|
6835
|
+
return empty ? dash : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6836
|
+
"a",
|
|
6837
|
+
{
|
|
6838
|
+
href: value,
|
|
6839
|
+
target: "_blank",
|
|
6840
|
+
rel: "noopener noreferrer",
|
|
6841
|
+
className: "inline-block rounded-xl overflow-hidden ring-1 ring-border hover:ring-primary transition-all",
|
|
6842
|
+
style: { width: sizeStyle.width ?? 128, height: sizeStyle.height ?? 128 },
|
|
6843
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("img", { src: value, alt: f.label, className: "w-full h-full object-cover" })
|
|
6844
|
+
}
|
|
6845
|
+
);
|
|
6846
|
+
case "text-url":
|
|
6847
|
+
return empty ? dash : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6848
|
+
"a",
|
|
6849
|
+
{
|
|
6850
|
+
href: value,
|
|
6851
|
+
onClick: (e) => e.preventDefault(),
|
|
6852
|
+
className: "text-sm text-primary underline underline-offset-2 hover:text-primary/80 break-all",
|
|
6853
|
+
style: sizeStyle,
|
|
6854
|
+
children: value
|
|
6855
|
+
}
|
|
6856
|
+
);
|
|
6857
|
+
case "text-url-open-other-tabs":
|
|
6858
|
+
return empty ? dash : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6859
|
+
"a",
|
|
6860
|
+
{
|
|
6861
|
+
href: value,
|
|
6862
|
+
target: "_blank",
|
|
6863
|
+
rel: "noopener noreferrer",
|
|
6864
|
+
className: "text-sm text-primary underline underline-offset-2 hover:text-primary/80 break-all",
|
|
6865
|
+
style: sizeStyle,
|
|
6866
|
+
children: value
|
|
6867
|
+
}
|
|
6868
|
+
);
|
|
6869
|
+
case "attachment":
|
|
6870
|
+
return empty ? dash : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
6871
|
+
"a",
|
|
6872
|
+
{
|
|
6873
|
+
href: value,
|
|
6874
|
+
target: "_blank",
|
|
6875
|
+
rel: "noopener noreferrer",
|
|
6876
|
+
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",
|
|
6877
|
+
style: sizeStyle,
|
|
6878
|
+
children: [
|
|
6879
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { className: "h-3.5 w-3.5 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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" }) }),
|
|
6880
|
+
String(value).split("/").pop() ?? "Download"
|
|
6881
|
+
]
|
|
6882
|
+
}
|
|
6883
|
+
);
|
|
6884
|
+
case "repeater": {
|
|
6885
|
+
const rows = Array.isArray(value) ? value : [];
|
|
6886
|
+
if (!rows.length) return dash;
|
|
6887
|
+
const rFields = f.repeaterFields;
|
|
6888
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "space-y-2", children: rows.map((row, ri) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-wrap gap-3 rounded-xl border border-border bg-muted/30 px-3 py-2", children: [
|
|
6889
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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 }),
|
|
6890
|
+
rFields ? rFields.map((rf) => {
|
|
6891
|
+
const v = row[rf.key];
|
|
6892
|
+
if (rf.type === "image") return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6893
|
+
rf.label && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
|
|
6894
|
+
v ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("img", { src: v, alt: rf.key, className: "h-10 w-10 rounded-lg object-cover ring-1 ring-border" }) : dash
|
|
6895
|
+
] }, rf.key);
|
|
6896
|
+
if (rf.type === "attachment") return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6897
|
+
rf.label && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
|
|
6898
|
+
v ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
6899
|
+
"a",
|
|
6900
|
+
{
|
|
6901
|
+
href: v,
|
|
6902
|
+
target: "_blank",
|
|
6903
|
+
rel: "noopener noreferrer",
|
|
6904
|
+
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",
|
|
6905
|
+
children: [
|
|
6906
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("svg", { className: "h-3 w-3 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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" }) }),
|
|
6907
|
+
String(v).split("/").pop()
|
|
6908
|
+
]
|
|
6909
|
+
}
|
|
6910
|
+
) : dash
|
|
6911
|
+
] }, rf.key);
|
|
6912
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6913
|
+
rf.label && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
|
|
6914
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: v ?? "\u2014" })
|
|
6915
|
+
] }, rf.key);
|
|
6916
|
+
}) : (
|
|
6917
|
+
// payload mode: row has { type, key, value }
|
|
6918
|
+
Object.entries(row).map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
|
|
6919
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: k }),
|
|
6920
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: String(v) })
|
|
6921
|
+
] }, k))
|
|
6922
|
+
)
|
|
6923
|
+
] }, ri)) });
|
|
6924
|
+
}
|
|
6925
|
+
case "checkbox":
|
|
6926
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6927
|
+
"input",
|
|
6928
|
+
{
|
|
6929
|
+
type: "checkbox",
|
|
6930
|
+
checked: !!value,
|
|
6931
|
+
readOnly: true,
|
|
6932
|
+
className: "h-4 w-4 rounded border-border accent-primary cursor-default",
|
|
6933
|
+
style: sizeStyle
|
|
6934
|
+
}
|
|
6935
|
+
);
|
|
6936
|
+
case "toggle":
|
|
6937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6938
|
+
"div",
|
|
6939
|
+
{
|
|
6940
|
+
className: cn(
|
|
6941
|
+
"relative inline-flex shrink-0 rounded-full border-2 border-transparent transition-colors",
|
|
6942
|
+
value ? "bg-primary" : "bg-muted"
|
|
6943
|
+
),
|
|
6944
|
+
style: { width: sizeStyle.width ?? 36, height: sizeStyle.height ?? 20 },
|
|
6945
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6946
|
+
"span",
|
|
6947
|
+
{
|
|
6948
|
+
className: cn(
|
|
6949
|
+
"pointer-events-none inline-block rounded-full bg-white shadow-sm transition-transform"
|
|
6950
|
+
),
|
|
6951
|
+
style: {
|
|
6952
|
+
width: typeof (sizeStyle.height ?? 20) === "number" ? sizeStyle.height - 4 : 16,
|
|
6953
|
+
height: typeof (sizeStyle.height ?? 20) === "number" ? sizeStyle.height - 4 : 16,
|
|
6954
|
+
transform: value ? `translateX(${typeof (sizeStyle.width ?? 36) === "number" ? sizeStyle.width - (sizeStyle.height ?? 20) : 16}px)` : "translateX(0)"
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6957
|
+
)
|
|
6958
|
+
}
|
|
6959
|
+
);
|
|
6960
|
+
default:
|
|
6961
|
+
return empty ? dash : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "text-sm text-foreground break-words", style: sizeStyle, children: String(value) });
|
|
6962
|
+
}
|
|
6963
|
+
};
|
|
6698
6964
|
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6699
6965
|
ModalShell,
|
|
6700
6966
|
{
|
|
@@ -6702,11 +6968,27 @@ function ViewModal({
|
|
|
6702
6968
|
onClose,
|
|
6703
6969
|
width,
|
|
6704
6970
|
footer: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Button, { variant: "outline", size: "sm", onClick: onClose, children: "Close" }),
|
|
6705
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6971
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
6972
|
+
"div",
|
|
6973
|
+
{
|
|
6974
|
+
className: grid ? "grid gap-4" : "space-y-3",
|
|
6975
|
+
style: grid ? { gridTemplateColumns: `repeat(${grid}, minmax(0, 1fr))` } : void 0,
|
|
6976
|
+
children: fields.map((f) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
6977
|
+
"div",
|
|
6978
|
+
{
|
|
6979
|
+
style: {
|
|
6980
|
+
...f.colSpan ? { gridColumn: `span ${f.colSpan}` } : {},
|
|
6981
|
+
...f.rowSpan ? { gridRow: `span ${f.rowSpan}` } : {}
|
|
6982
|
+
},
|
|
6983
|
+
children: [
|
|
6984
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { className: "text-xs font-semibold text-muted-foreground mb-1", children: f.label }),
|
|
6985
|
+
renderViewValue(f, item[f.key])
|
|
6986
|
+
]
|
|
6987
|
+
},
|
|
6988
|
+
f.key
|
|
6989
|
+
))
|
|
6990
|
+
}
|
|
6991
|
+
)
|
|
6710
6992
|
}
|
|
6711
6993
|
);
|
|
6712
6994
|
}
|
|
@@ -6939,26 +7221,84 @@ var BADGE_COLORS = {
|
|
|
6939
7221
|
function badgeClass(value) {
|
|
6940
7222
|
return BADGE_COLORS[value.toLowerCase()] ?? "bg-primary/10 text-primary border-primary/20";
|
|
6941
7223
|
}
|
|
7224
|
+
function deriveField(key, sample) {
|
|
7225
|
+
const label = key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
7226
|
+
const base = { key, label };
|
|
7227
|
+
if (typeof sample === "boolean") return { ...base, type: "toggle", viewType: "toggle" };
|
|
7228
|
+
if (typeof sample === "number") return { ...base, inputType: "number" };
|
|
7229
|
+
if (Array.isArray(sample)) {
|
|
7230
|
+
if (sample.length === 0 || typeof sample[0] === "string")
|
|
7231
|
+
return { ...base, type: "tag-input" };
|
|
7232
|
+
return base;
|
|
7233
|
+
}
|
|
7234
|
+
if (typeof sample === "string") {
|
|
7235
|
+
if (/\.(png|jpe?g|gif|webp|svg|avif)(\?.*)?$/i.test(sample))
|
|
7236
|
+
return { ...base, type: "input", viewType: "image" };
|
|
7237
|
+
if (/\.(pdf|docx?|xlsx?|csv|zip|pptx?)(\?.*)?$/i.test(sample))
|
|
7238
|
+
return { ...base, type: "input", viewType: "attachment" };
|
|
7239
|
+
if (/^https?:\/\//.test(sample))
|
|
7240
|
+
return { ...base, type: "input", viewType: "text-url-open-other-tabs" };
|
|
7241
|
+
if (sample.length > 120 || /\n/.test(sample))
|
|
7242
|
+
return { ...base, type: "textarea" };
|
|
7243
|
+
if (/password|secret|token/i.test(key))
|
|
7244
|
+
return { ...base, type: "password" };
|
|
7245
|
+
if (/email/i.test(key))
|
|
7246
|
+
return { ...base, inputType: "email" };
|
|
7247
|
+
if (/color|colour/i.test(key) && /^#[0-9a-f]{3,8}$/i.test(sample))
|
|
7248
|
+
return { ...base, type: "color-picker", viewType: "text" };
|
|
7249
|
+
}
|
|
7250
|
+
return base;
|
|
7251
|
+
}
|
|
6942
7252
|
function Table({
|
|
6943
7253
|
data,
|
|
6944
7254
|
columns,
|
|
7255
|
+
loading,
|
|
7256
|
+
emptyState,
|
|
7257
|
+
error: errorProp,
|
|
6945
7258
|
searchable = false,
|
|
6946
7259
|
searchPlaceholder = "Search...",
|
|
6947
|
-
|
|
7260
|
+
searchValue: controlledSearch,
|
|
7261
|
+
onSearchChange,
|
|
7262
|
+
clientPagination = false,
|
|
6948
7263
|
itemsPerPage = 10,
|
|
6949
7264
|
selectable = false,
|
|
6950
7265
|
onBulkDelete,
|
|
6951
7266
|
idKey = "id",
|
|
7267
|
+
bulkDeleteBaseUrl,
|
|
6952
7268
|
defaultActions,
|
|
6953
7269
|
serverPagination,
|
|
6954
|
-
|
|
7270
|
+
variant = "default",
|
|
7271
|
+
className,
|
|
7272
|
+
onRowClick,
|
|
7273
|
+
onRowDoubleClick,
|
|
7274
|
+
rowClassName,
|
|
7275
|
+
expandable = false,
|
|
7276
|
+
renderExpanded,
|
|
7277
|
+
columnVisibility,
|
|
7278
|
+
onColumnVisibilityChange,
|
|
7279
|
+
exportable = false,
|
|
7280
|
+
onExport,
|
|
7281
|
+
virtualized = false,
|
|
7282
|
+
draggable = false,
|
|
7283
|
+
onRowReorder,
|
|
7284
|
+
keyboardNavigation = false
|
|
6955
7285
|
}) {
|
|
6956
7286
|
const { toast } = useToast();
|
|
6957
|
-
const
|
|
7287
|
+
const isControlledSearch = controlledSearch !== void 0;
|
|
7288
|
+
const [internalSearch, setInternalSearch] = React28.useState("");
|
|
7289
|
+
const search = isControlledSearch ? controlledSearch : internalSearch;
|
|
7290
|
+
const setSearch = (v) => {
|
|
7291
|
+
if (!isControlledSearch) setInternalSearch(v);
|
|
7292
|
+
onSearchChange?.(v);
|
|
7293
|
+
};
|
|
6958
7294
|
const [currentPage, setCurrentPage] = React28.useState(1);
|
|
6959
7295
|
const [selectedIds, setSelectedIds] = React28.useState([]);
|
|
6960
7296
|
const [sortKey, setSortKey] = React28.useState(null);
|
|
6961
7297
|
const [sortDir, setSortDir] = React28.useState(null);
|
|
7298
|
+
const [bulkLoading, setBulkLoading] = React28.useState(false);
|
|
7299
|
+
const [expandedIds, setExpandedIds] = React28.useState(/* @__PURE__ */ new Set());
|
|
7300
|
+
const [dragOverId, setDragOverId] = React28.useState(null);
|
|
7301
|
+
const [focusedRowIdx, setFocusedRowIdx] = React28.useState(-1);
|
|
6962
7302
|
const [viewItem, setViewItem] = React28.useState(null);
|
|
6963
7303
|
const [editItem, setEditItem] = React28.useState(null);
|
|
6964
7304
|
const [deleteItem, setDeleteItem] = React28.useState(null);
|
|
@@ -6970,15 +7310,17 @@ function Table({
|
|
|
6970
7310
|
const safeBaseUrl = defaultActions?.baseUrl.replace(/\/+$/, "") ?? "";
|
|
6971
7311
|
const autoFields = React28.useMemo(() => {
|
|
6972
7312
|
if (!tableData.length) return [];
|
|
6973
|
-
|
|
6974
|
-
|
|
6975
|
-
label: k.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
|
|
6976
|
-
}));
|
|
7313
|
+
const row = tableData[0];
|
|
7314
|
+
return Object.keys(row).map((k) => deriveField(k, row[k]));
|
|
6977
7315
|
}, [tableData]);
|
|
6978
7316
|
const editFields = defaultActions?.editForm ?? autoFields;
|
|
6979
7317
|
const viewFields = defaultActions?.viewForm ?? autoFields;
|
|
7318
|
+
const visibleColumns = React28.useMemo(() => {
|
|
7319
|
+
if (!columnVisibility) return columns;
|
|
7320
|
+
return columns.filter((col) => columnVisibility[String(col.key)] !== false);
|
|
7321
|
+
}, [columns, columnVisibility]);
|
|
6980
7322
|
const allColumns = React28.useMemo(() => {
|
|
6981
|
-
if (!defaultActions) return
|
|
7323
|
+
if (!defaultActions) return visibleColumns;
|
|
6982
7324
|
const actionsCol = {
|
|
6983
7325
|
key: "__actions__",
|
|
6984
7326
|
title: "Actions",
|
|
@@ -7027,8 +7369,8 @@ function Table({
|
|
|
7027
7369
|
))
|
|
7028
7370
|
] })
|
|
7029
7371
|
};
|
|
7030
|
-
return defaultActions.position === "first" ? [actionsCol, ...
|
|
7031
|
-
}, [
|
|
7372
|
+
return defaultActions.position === "first" ? [actionsCol, ...visibleColumns] : [...visibleColumns, actionsCol];
|
|
7373
|
+
}, [visibleColumns, defaultActions]);
|
|
7032
7374
|
const handleSort = (key) => {
|
|
7033
7375
|
if (sortKey !== key) {
|
|
7034
7376
|
setSortKey(key);
|
|
@@ -7061,16 +7403,74 @@ function Table({
|
|
|
7061
7403
|
const totalPages = Math.max(1, Math.ceil(filteredData.length / itemsPerPage));
|
|
7062
7404
|
const safePage = Math.min(currentPage, totalPages);
|
|
7063
7405
|
const paginatedData = React28.useMemo(() => {
|
|
7064
|
-
if (!
|
|
7406
|
+
if (!clientPagination) return filteredData;
|
|
7065
7407
|
const start = (safePage - 1) * itemsPerPage;
|
|
7066
7408
|
return filteredData.slice(start, start + itemsPerPage);
|
|
7067
|
-
}, [filteredData,
|
|
7409
|
+
}, [filteredData, clientPagination, safePage, itemsPerPage]);
|
|
7068
7410
|
React28.useEffect(() => {
|
|
7069
7411
|
setCurrentPage(1);
|
|
7070
7412
|
}, [search]);
|
|
7413
|
+
React28.useEffect(() => {
|
|
7414
|
+
if (!keyboardNavigation) return;
|
|
7415
|
+
const handler = (e) => {
|
|
7416
|
+
if (e.key === "ArrowDown") {
|
|
7417
|
+
e.preventDefault();
|
|
7418
|
+
setFocusedRowIdx((i) => Math.min(i + 1, paginatedData.length - 1));
|
|
7419
|
+
}
|
|
7420
|
+
if (e.key === "ArrowUp") {
|
|
7421
|
+
e.preventDefault();
|
|
7422
|
+
setFocusedRowIdx((i) => Math.max(i - 1, 0));
|
|
7423
|
+
}
|
|
7424
|
+
};
|
|
7425
|
+
window.addEventListener("keydown", handler);
|
|
7426
|
+
return () => window.removeEventListener("keydown", handler);
|
|
7427
|
+
}, [keyboardNavigation, paginatedData.length]);
|
|
7071
7428
|
const handleSelectAll = (checked) => setSelectedIds(checked ? paginatedData.map((item) => String(item[idKey])) : []);
|
|
7072
7429
|
const handleSelect = (id, checked) => setSelectedIds((prev) => checked ? [...prev, id] : prev.filter((i) => i !== id));
|
|
7073
7430
|
const allSelected = paginatedData.length > 0 && selectedIds.length === paginatedData.length;
|
|
7431
|
+
const totalRows = serverPagination ? serverPagination.pagination.total : filteredData.length;
|
|
7432
|
+
const unselectedCount = totalRows - selectedIds.length;
|
|
7433
|
+
const handleSelectAllRecords = () => setSelectedIds(filteredData.map((item) => String(item[idKey])));
|
|
7434
|
+
const handleUnselectAll = () => setSelectedIds([]);
|
|
7435
|
+
const handleBulkDeleteSelected = async () => {
|
|
7436
|
+
if (!bulkDeleteBaseUrl || selectedIds.length === 0) {
|
|
7437
|
+
onBulkDelete?.(selectedIds);
|
|
7438
|
+
setSelectedIds([]);
|
|
7439
|
+
return;
|
|
7440
|
+
}
|
|
7441
|
+
setBulkLoading(true);
|
|
7442
|
+
try {
|
|
7443
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
|
7444
|
+
if (!csrfToken) throw new Error("[Table] CSRF token not found.");
|
|
7445
|
+
const safeUrl = bulkDeleteBaseUrl.replace(/\/+$/, "");
|
|
7446
|
+
await import_axios3.default.delete(`${safeUrl}/delete/${selectedIds.join(",")}/selected`, { headers: { "X-CSRF-Token": csrfToken } });
|
|
7447
|
+
setTableData((prev) => prev.filter((r) => !selectedIds.includes(String(r[idKey]))));
|
|
7448
|
+
onBulkDelete?.(selectedIds);
|
|
7449
|
+
setSelectedIds([]);
|
|
7450
|
+
defaultActions?.onReload?.();
|
|
7451
|
+
} catch (err) {
|
|
7452
|
+
console.error("[Table] Bulk delete selected failed:", err?.response?.data?.message ?? err.message);
|
|
7453
|
+
} finally {
|
|
7454
|
+
setBulkLoading(false);
|
|
7455
|
+
}
|
|
7456
|
+
};
|
|
7457
|
+
const handleDeleteAll = async () => {
|
|
7458
|
+
if (!bulkDeleteBaseUrl) return;
|
|
7459
|
+
setBulkLoading(true);
|
|
7460
|
+
try {
|
|
7461
|
+
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute("content");
|
|
7462
|
+
if (!csrfToken) throw new Error("[Table] CSRF token not found.");
|
|
7463
|
+
const safeUrl = bulkDeleteBaseUrl.replace(/\/+$/, "");
|
|
7464
|
+
await import_axios3.default.delete(`${safeUrl}/delete/all`, { headers: { "X-CSRF-Token": csrfToken } });
|
|
7465
|
+
setTableData([]);
|
|
7466
|
+
setSelectedIds([]);
|
|
7467
|
+
defaultActions?.onReload?.();
|
|
7468
|
+
} catch (err) {
|
|
7469
|
+
console.error("[Table] Delete all failed:", err?.response?.data?.message ?? err.message);
|
|
7470
|
+
} finally {
|
|
7471
|
+
setBulkLoading(false);
|
|
7472
|
+
}
|
|
7473
|
+
};
|
|
7074
7474
|
const pagePills = React28.useMemo(() => {
|
|
7075
7475
|
if (totalPages <= 5) return Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
7076
7476
|
if (safePage <= 3) return [1, 2, 3, 4, 5];
|
|
@@ -7084,6 +7484,7 @@ function Table({
|
|
|
7084
7484
|
};
|
|
7085
7485
|
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
|
|
7086
7486
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: cn("w-full space-y-3", className), children: [
|
|
7487
|
+
errorProp && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "rounded-xl border border-danger/30 bg-danger/5 px-4 py-3 text-sm text-danger", children: errorProp }),
|
|
7087
7488
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-3 flex-wrap", children: [
|
|
7088
7489
|
searchable && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "relative w-72", children: [
|
|
7089
7490
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Search, { className: "absolute text-primary left-3 top-1/2 -translate-y-1/2 h-4 w-4 z-10" }),
|
|
@@ -7105,33 +7506,115 @@ function Table({
|
|
|
7105
7506
|
}
|
|
7106
7507
|
)
|
|
7107
7508
|
] }),
|
|
7108
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2 ml-auto", children: [
|
|
7109
|
-
selectable &&
|
|
7509
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2 ml-auto flex-wrap", children: [
|
|
7510
|
+
selectable && selectedIds.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
|
|
7511
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
7512
|
+
"button",
|
|
7513
|
+
{
|
|
7514
|
+
onClick: handleUnselectAll,
|
|
7515
|
+
disabled: bulkLoading,
|
|
7516
|
+
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",
|
|
7517
|
+
children: [
|
|
7518
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.X, { className: "h-3.5 w-3.5" }),
|
|
7519
|
+
"Unselect all ",
|
|
7520
|
+
selectedIds.length
|
|
7521
|
+
]
|
|
7522
|
+
}
|
|
7523
|
+
),
|
|
7524
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
7525
|
+
"button",
|
|
7526
|
+
{
|
|
7527
|
+
onClick: handleBulkDeleteSelected,
|
|
7528
|
+
disabled: bulkLoading,
|
|
7529
|
+
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",
|
|
7530
|
+
children: [
|
|
7531
|
+
bulkLoading ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Trash2, { className: "h-3.5 w-3.5" }),
|
|
7532
|
+
"Delete ",
|
|
7533
|
+
selectedIds.length,
|
|
7534
|
+
" selected"
|
|
7535
|
+
]
|
|
7536
|
+
}
|
|
7537
|
+
)
|
|
7538
|
+
] }),
|
|
7539
|
+
selectable && unselectedCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
7110
7540
|
"button",
|
|
7111
7541
|
{
|
|
7112
|
-
onClick:
|
|
7113
|
-
|
|
7114
|
-
|
|
7115
|
-
|
|
7116
|
-
|
|
7542
|
+
onClick: handleSelectAllRecords,
|
|
7543
|
+
disabled: bulkLoading,
|
|
7544
|
+
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",
|
|
7545
|
+
children: [
|
|
7546
|
+
"Select all ",
|
|
7547
|
+
unselectedCount
|
|
7548
|
+
]
|
|
7549
|
+
}
|
|
7550
|
+
),
|
|
7551
|
+
selectable && bulkDeleteBaseUrl && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
7552
|
+
"button",
|
|
7553
|
+
{
|
|
7554
|
+
onClick: handleDeleteAll,
|
|
7555
|
+
disabled: bulkLoading,
|
|
7556
|
+
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",
|
|
7117
7557
|
children: [
|
|
7118
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Trash2, { className: "h-3.5 w-3.5" }),
|
|
7119
|
-
"Delete "
|
|
7120
|
-
selectedIds.length,
|
|
7121
|
-
" selected"
|
|
7558
|
+
bulkLoading ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Loader2, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Trash2, { className: "h-3.5 w-3.5" }),
|
|
7559
|
+
"Delete all"
|
|
7122
7560
|
]
|
|
7123
7561
|
}
|
|
7124
7562
|
),
|
|
7563
|
+
exportable && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "relative group", children: [
|
|
7564
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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" }),
|
|
7565
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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__ */ (0, import_jsx_runtime32.jsx)(
|
|
7566
|
+
"button",
|
|
7567
|
+
{
|
|
7568
|
+
onClick: () => onExport?.(type),
|
|
7569
|
+
className: "px-4 py-2 text-xs text-left hover:bg-muted transition-colors capitalize",
|
|
7570
|
+
children: type.toUpperCase()
|
|
7571
|
+
},
|
|
7572
|
+
type
|
|
7573
|
+
)) })
|
|
7574
|
+
] }),
|
|
7575
|
+
columnVisibility && onColumnVisibilityChange && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "relative group", children: [
|
|
7576
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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" }),
|
|
7577
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("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__ */ (0, import_jsx_runtime32.jsxs)("label", { className: "flex items-center gap-2 px-2 py-1 rounded-lg hover:bg-muted cursor-pointer text-xs", children: [
|
|
7578
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7579
|
+
"input",
|
|
7580
|
+
{
|
|
7581
|
+
type: "checkbox",
|
|
7582
|
+
checked: columnVisibility[String(col.key)] !== false,
|
|
7583
|
+
onChange: (e) => onColumnVisibilityChange({ ...columnVisibility, [String(col.key)]: e.target.checked }),
|
|
7584
|
+
className: "accent-primary"
|
|
7585
|
+
}
|
|
7586
|
+
),
|
|
7587
|
+
col.title
|
|
7588
|
+
] }, String(col.key))) })
|
|
7589
|
+
] }),
|
|
7125
7590
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
|
|
7126
|
-
|
|
7591
|
+
totalRows,
|
|
7127
7592
|
" ",
|
|
7128
|
-
|
|
7593
|
+
totalRows === 1 ? "row" : "rows",
|
|
7129
7594
|
search && ` \xB7 filtered from ${tableData.length}`
|
|
7130
7595
|
] })
|
|
7131
7596
|
] })
|
|
7132
7597
|
] }),
|
|
7133
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.
|
|
7134
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7598
|
+
loading && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-center py-12 text-muted-foreground gap-2", children: [
|
|
7599
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Loader2, { className: "h-5 w-5 animate-spin" }),
|
|
7600
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: "Loading\u2026" })
|
|
7601
|
+
] }),
|
|
7602
|
+
!loading && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(
|
|
7603
|
+
variant === "default" && "rounded-xl border border-border overflow-hidden bg-card/50 backdrop-blur-sm shadow-sm",
|
|
7604
|
+
variant === "zebra" && "rounded-xl border border-border overflow-hidden bg-card/50 backdrop-blur-sm shadow-sm",
|
|
7605
|
+
variant === "card" && "space-y-2",
|
|
7606
|
+
variant === "glass" && "rounded-2xl overflow-hidden border border-white/10 bg-background/30 backdrop-blur-xl shadow-xl",
|
|
7607
|
+
variant === "soft" && "rounded-2xl overflow-hidden bg-card",
|
|
7608
|
+
variant === "soft" && "[box-shadow:6px_6px_12px_hsl(var(--foreground)/0.07),-6px_-6px_12px_hsl(var(--background)/0.8)]",
|
|
7609
|
+
virtualized && "max-h-[520px] overflow-y-auto"
|
|
7610
|
+
), children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn("w-full overflow-auto", variant === "card" && "space-y-2"), children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("table", { className: cn("w-full caption-bottom text-sm", variant === "card" && "border-separate border-spacing-y-2"), children: [
|
|
7611
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("tr", { className: cn(
|
|
7612
|
+
variant === "default" && "border-b border-border bg-muted/40",
|
|
7613
|
+
variant === "zebra" && "border-b border-border bg-muted/40",
|
|
7614
|
+
variant === "card" && "[&>th]:bg-transparent",
|
|
7615
|
+
variant === "glass" && "border-b border-white/10 bg-white/5",
|
|
7616
|
+
variant === "soft" && "border-b-0 bg-muted/30"
|
|
7617
|
+
), children: [
|
|
7135
7618
|
selectable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("th", { className: "h-11 w-[46px] px-4 text-left align-middle", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7136
7619
|
Checkbox,
|
|
7137
7620
|
{
|
|
@@ -7139,13 +7622,16 @@ function Table({
|
|
|
7139
7622
|
onChange: (e) => handleSelectAll(e.target.checked)
|
|
7140
7623
|
}
|
|
7141
7624
|
) }),
|
|
7625
|
+
expandable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("th", { className: "h-11 w-8" }),
|
|
7142
7626
|
allColumns.map((col, ci) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7143
7627
|
"th",
|
|
7144
7628
|
{
|
|
7145
7629
|
onClick: () => col.sortable && handleSort(String(col.key)),
|
|
7146
7630
|
className: cn(
|
|
7147
7631
|
"h-11 px-4 text-left align-middle text-xs font-semibold uppercase tracking-wider text-muted-foreground select-none whitespace-nowrap",
|
|
7148
|
-
col.sortable && "cursor-pointer hover:text-foreground transition-colors"
|
|
7632
|
+
col.sortable && "cursor-pointer hover:text-foreground transition-colors",
|
|
7633
|
+
variant === "glass" && "text-foreground/70",
|
|
7634
|
+
variant === "soft" && "text-muted-foreground/80"
|
|
7149
7635
|
),
|
|
7150
7636
|
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "inline-flex items-center", children: [
|
|
7151
7637
|
col.title,
|
|
@@ -7158,9 +7644,9 @@ function Table({
|
|
|
7158
7644
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("tbody", { children: paginatedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("tr", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7159
7645
|
"td",
|
|
7160
7646
|
{
|
|
7161
|
-
colSpan: allColumns.length + (selectable ? 1 : 0),
|
|
7647
|
+
colSpan: allColumns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0),
|
|
7162
7648
|
className: "h-32 text-center align-middle",
|
|
7163
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col items-center gap-1 text-muted-foreground", children: [
|
|
7649
|
+
children: emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col items-center gap-1 text-muted-foreground", children: [
|
|
7164
7650
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Search, { className: "h-8 w-8 opacity-20" }),
|
|
7165
7651
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: "No results found" }),
|
|
7166
7652
|
search && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { onClick: () => setSearch(""), className: "text-xs text-primary hover:underline", children: "Clear search" })
|
|
@@ -7169,85 +7655,168 @@ function Table({
|
|
|
7169
7655
|
) }) : paginatedData.map((item, i) => {
|
|
7170
7656
|
const id = String(item[idKey] || i);
|
|
7171
7657
|
const isSelected = selectedIds.includes(id);
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7181
|
-
|
|
7182
|
-
|
|
7183
|
-
|
|
7184
|
-
|
|
7185
|
-
|
|
7186
|
-
|
|
7187
|
-
|
|
7188
|
-
|
|
7189
|
-
|
|
7190
|
-
|
|
7191
|
-
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7195
|
-
|
|
7196
|
-
|
|
7197
|
-
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7658
|
+
const isExpanded = expandedIds.has(id);
|
|
7659
|
+
const isFocused = keyboardNavigation && focusedRowIdx === i;
|
|
7660
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(React28.Fragment, { children: [
|
|
7661
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
7662
|
+
"tr",
|
|
7663
|
+
{
|
|
7664
|
+
draggable,
|
|
7665
|
+
tabIndex: keyboardNavigation ? 0 : void 0,
|
|
7666
|
+
onDragStart: draggable ? (e) => {
|
|
7667
|
+
e.dataTransfer.setData("text/plain", id);
|
|
7668
|
+
} : void 0,
|
|
7669
|
+
onDragOver: draggable ? (e) => {
|
|
7670
|
+
e.preventDefault();
|
|
7671
|
+
setDragOverId(id);
|
|
7672
|
+
} : void 0,
|
|
7673
|
+
onDragLeave: draggable ? () => setDragOverId(null) : void 0,
|
|
7674
|
+
onDrop: draggable ? (e) => {
|
|
7675
|
+
e.preventDefault();
|
|
7676
|
+
setDragOverId(null);
|
|
7677
|
+
const fromId = e.dataTransfer.getData("text/plain");
|
|
7678
|
+
if (fromId === id) return;
|
|
7679
|
+
setTableData((prev) => {
|
|
7680
|
+
const fromIdx = prev.findIndex((r) => String(r[idKey] || "") === fromId);
|
|
7681
|
+
const toIdx = prev.findIndex((r) => String(r[idKey] || "") === id);
|
|
7682
|
+
if (fromIdx < 0 || toIdx < 0) return prev;
|
|
7683
|
+
const next = [...prev];
|
|
7684
|
+
const [moved] = next.splice(fromIdx, 1);
|
|
7685
|
+
next.splice(toIdx, 0, moved);
|
|
7686
|
+
onRowReorder?.(next);
|
|
7687
|
+
return next;
|
|
7688
|
+
});
|
|
7689
|
+
} : void 0,
|
|
7690
|
+
onClick: () => {
|
|
7691
|
+
if (expandable) setExpandedIds((prev) => {
|
|
7692
|
+
const s = new Set(prev);
|
|
7693
|
+
s.has(id) ? s.delete(id) : s.add(id);
|
|
7694
|
+
return s;
|
|
7695
|
+
});
|
|
7696
|
+
onRowClick?.(item);
|
|
7697
|
+
if (keyboardNavigation) setFocusedRowIdx(i);
|
|
7698
|
+
},
|
|
7699
|
+
onDoubleClick: () => onRowDoubleClick?.(item),
|
|
7700
|
+
className: cn(
|
|
7701
|
+
// default
|
|
7702
|
+
variant === "default" && "border-b border-border/60 transition-colors last:border-0",
|
|
7703
|
+
variant === "default" && (isSelected ? "bg-primary/5 hover:bg-primary/8" : "hover:bg-muted/30"),
|
|
7704
|
+
// zebra
|
|
7705
|
+
variant === "zebra" && "border-b border-border/40 transition-colors last:border-0",
|
|
7706
|
+
variant === "zebra" && (isSelected ? "bg-primary/8" : i % 2 === 0 ? "bg-card" : "bg-muted/40"),
|
|
7707
|
+
variant === "zebra" && !isSelected && "hover:bg-primary/5",
|
|
7708
|
+
// card
|
|
7709
|
+
variant === "card" && "rounded-xl border border-border bg-card shadow-sm transition-all hover:shadow-md hover:-translate-y-px",
|
|
7710
|
+
variant === "card" && (isSelected ? "border-primary/50 bg-primary/5" : ""),
|
|
7711
|
+
variant === "card" && "[&>td:first-child]:rounded-l-xl [&>td:last-child]:rounded-r-xl",
|
|
7712
|
+
// glass
|
|
7713
|
+
variant === "glass" && "border-b border-white/8 transition-colors last:border-0",
|
|
7714
|
+
variant === "glass" && (isSelected ? "bg-primary/15 hover:bg-primary/20" : "hover:bg-white/5"),
|
|
7715
|
+
// soft
|
|
7716
|
+
variant === "soft" && "transition-all",
|
|
7717
|
+
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"),
|
|
7718
|
+
variant === "soft" && "border-b border-border/30 last:border-0",
|
|
7719
|
+
(onRowClick || onRowDoubleClick || expandable) && "cursor-pointer",
|
|
7720
|
+
draggable && dragOverId === id && "ring-2 ring-inset ring-primary/40",
|
|
7721
|
+
isFocused && "ring-2 ring-inset ring-ring",
|
|
7722
|
+
rowClassName?.(item)
|
|
7723
|
+
),
|
|
7724
|
+
children: [
|
|
7725
|
+
selectable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: "px-4 py-3 align-middle", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7726
|
+
Checkbox,
|
|
7727
|
+
{
|
|
7728
|
+
checked: isSelected,
|
|
7729
|
+
onChange: (e) => handleSelect(id, e.target.checked)
|
|
7730
|
+
}
|
|
7201
7731
|
) }),
|
|
7202
|
-
|
|
7203
|
-
|
|
7204
|
-
|
|
7205
|
-
{
|
|
7206
|
-
value: item[col.key],
|
|
7207
|
-
onChange: (e) => col.onChange?.(item, e.target.value),
|
|
7208
|
-
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",
|
|
7209
|
-
children: (col.selectOptions ?? []).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: opt, children: opt }, opt))
|
|
7210
|
-
}
|
|
7211
|
-
) : col.type === "toggle" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7212
|
-
"button",
|
|
7213
|
-
{
|
|
7214
|
-
role: "switch",
|
|
7215
|
-
"aria-checked": !!item[col.key],
|
|
7216
|
-
onClick: () => col.onChange?.(item, !item[col.key]),
|
|
7217
|
-
className: cn(
|
|
7218
|
-
"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",
|
|
7219
|
-
item[col.key] ? "bg-primary" : "bg-muted"
|
|
7220
|
-
),
|
|
7221
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
|
|
7222
|
-
"pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
|
|
7223
|
-
item[col.key] ? "translate-x-4" : "translate-x-0"
|
|
7224
|
-
) })
|
|
7225
|
-
}
|
|
7226
|
-
) : col.type === "color" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
7227
|
-
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7228
|
-
"input",
|
|
7732
|
+
expandable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: "w-8 px-2 py-3 align-middle", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.ChevronRight, { className: cn("h-3.5 w-3.5 text-muted-foreground transition-transform", isExpanded && "rotate-90") }) }),
|
|
7733
|
+
allColumns.map((col, ci) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: "px-4 py-3 align-middle", children: col.render ? col.render(item) : col.type === "image" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7734
|
+
"img",
|
|
7229
7735
|
{
|
|
7230
|
-
|
|
7231
|
-
|
|
7736
|
+
src: item[col.key],
|
|
7737
|
+
alt: item[col.key],
|
|
7738
|
+
className: "h-9 w-9 rounded-lg object-cover ring-1 ring-border"
|
|
7739
|
+
}
|
|
7740
|
+
) : col.type === "badge" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: cn(
|
|
7741
|
+
"inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium",
|
|
7742
|
+
badgeClass(String(item[col.key]))
|
|
7743
|
+
), children: [
|
|
7744
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
|
|
7745
|
+
"mr-1.5 h-1.5 w-1.5 rounded-full",
|
|
7746
|
+
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"
|
|
7747
|
+
) }),
|
|
7748
|
+
item[col.key]
|
|
7749
|
+
] }) : col.type === "stack" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(AvatarStack, { images: Array.isArray(item[col.key]) ? item[col.key] : [], ...col.stackProps ?? {} }) : col.type === "icon" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "flex items-center", children: item[col.key] }) : col.type === "select" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7750
|
+
"select",
|
|
7751
|
+
{
|
|
7752
|
+
value: item[col.key],
|
|
7232
7753
|
onChange: (e) => col.onChange?.(item, e.target.value),
|
|
7233
|
-
className: "h-
|
|
7754
|
+
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",
|
|
7755
|
+
children: (col.selectOptions ?? []).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: opt, children: opt }, opt))
|
|
7234
7756
|
}
|
|
7235
|
-
),
|
|
7236
|
-
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
|
|
7240
|
-
|
|
7241
|
-
|
|
7242
|
-
|
|
7243
|
-
|
|
7244
|
-
|
|
7245
|
-
|
|
7246
|
-
|
|
7247
|
-
|
|
7757
|
+
) : col.type === "toggle" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7758
|
+
"button",
|
|
7759
|
+
{
|
|
7760
|
+
role: "switch",
|
|
7761
|
+
"aria-checked": !!item[col.key],
|
|
7762
|
+
onClick: () => col.onChange?.(item, !item[col.key]),
|
|
7763
|
+
className: cn(
|
|
7764
|
+
"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",
|
|
7765
|
+
item[col.key] ? "bg-primary" : "bg-muted"
|
|
7766
|
+
),
|
|
7767
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
|
|
7768
|
+
"pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
|
|
7769
|
+
item[col.key] ? "translate-x-4" : "translate-x-0"
|
|
7770
|
+
) })
|
|
7771
|
+
}
|
|
7772
|
+
) : col.type === "color" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
7773
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7774
|
+
"input",
|
|
7775
|
+
{
|
|
7776
|
+
type: "color",
|
|
7777
|
+
value: item[col.key] || "#000000",
|
|
7778
|
+
onChange: (e) => col.onChange?.(item, e.target.value),
|
|
7779
|
+
className: "h-7 w-7 cursor-pointer rounded border border-border bg-transparent p-0.5"
|
|
7780
|
+
}
|
|
7781
|
+
),
|
|
7782
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-xs text-muted-foreground font-mono", children: item[col.key] })
|
|
7783
|
+
] }) : col.type === "checkbox" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7784
|
+
Checkbox,
|
|
7785
|
+
{
|
|
7786
|
+
checked: !!item[col.key],
|
|
7787
|
+
onChange: (e) => col.onChange?.(item, e.target.checked)
|
|
7788
|
+
}
|
|
7789
|
+
) : col.type === "text-url" ? (() => {
|
|
7790
|
+
const href = col.redirect ? typeof col.redirect === "function" ? col.redirect(item) : col.redirect : String(item[col.key] ?? "");
|
|
7791
|
+
const colorMap = {
|
|
7792
|
+
primary: "var(--primary)",
|
|
7793
|
+
info: "var(--info)",
|
|
7794
|
+
success: "var(--success)",
|
|
7795
|
+
warning: "var(--warning)",
|
|
7796
|
+
danger: "var(--danger)"
|
|
7797
|
+
};
|
|
7798
|
+
const underline = col.underlineColor ? colorMap[col.underlineColor] ?? col.underlineColor : "var(--primary)";
|
|
7799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
7800
|
+
"a",
|
|
7801
|
+
{
|
|
7802
|
+
href,
|
|
7803
|
+
target: col.openNewTab ? "_blank" : void 0,
|
|
7804
|
+
rel: col.openNewTab ? "noopener noreferrer" : void 0,
|
|
7805
|
+
style: { textDecorationColor: underline },
|
|
7806
|
+
className: "text-sm underline underline-offset-2 hover:opacity-75 transition-opacity break-all",
|
|
7807
|
+
onClick: col.openNewTab ? void 0 : (e) => e.preventDefault(),
|
|
7808
|
+
children: item[col.key]
|
|
7809
|
+
}
|
|
7810
|
+
);
|
|
7811
|
+
})() : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-foreground/90", children: item[col.key] }) }, `${String(col.key)}-${ci}`))
|
|
7812
|
+
]
|
|
7813
|
+
}
|
|
7814
|
+
),
|
|
7815
|
+
expandable && isExpanded && renderExpanded && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("tr", { className: "bg-muted/20 border-b border-border/60", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { colSpan: allColumns.length + (selectable ? 1 : 0) + 1, className: "px-6 py-3", children: renderExpanded(item) }) })
|
|
7816
|
+
] }, id);
|
|
7248
7817
|
}) })
|
|
7249
7818
|
] }) }) }),
|
|
7250
|
-
|
|
7819
|
+
clientPagination && !serverPagination && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
7251
7820
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
|
|
7252
7821
|
"Showing ",
|
|
7253
7822
|
(safePage - 1) * itemsPerPage + 1,
|
|
@@ -7298,8 +7867,8 @@ function Table({
|
|
|
7298
7867
|
] })
|
|
7299
7868
|
] }),
|
|
7300
7869
|
serverPagination && (() => {
|
|
7301
|
-
const { pagination
|
|
7302
|
-
const totalServerPages =
|
|
7870
|
+
const { pagination, currentPage: cp, goToPage } = serverPagination;
|
|
7871
|
+
const totalServerPages = pagination.last_page ?? Math.ceil(pagination.total / pagination.per_page);
|
|
7303
7872
|
const pills = [];
|
|
7304
7873
|
if (totalServerPages <= 7) {
|
|
7305
7874
|
for (let i = 1; i <= totalServerPages; i++) pills.push(i);
|
|
@@ -7312,7 +7881,7 @@ function Table({
|
|
|
7312
7881
|
}
|
|
7313
7882
|
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
|
|
7314
7883
|
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
|
|
7315
|
-
|
|
7884
|
+
pagination.total,
|
|
7316
7885
|
" total rows \xB7 page ",
|
|
7317
7886
|
cp,
|
|
7318
7887
|
" of ",
|
|
@@ -7323,7 +7892,7 @@ function Table({
|
|
|
7323
7892
|
"button",
|
|
7324
7893
|
{
|
|
7325
7894
|
onClick: () => goToPage(cp - 1),
|
|
7326
|
-
disabled: !
|
|
7895
|
+
disabled: !pagination.prev_page_url,
|
|
7327
7896
|
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",
|
|
7328
7897
|
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.ChevronLeft, { className: "h-4 w-4" })
|
|
7329
7898
|
}
|
|
@@ -7346,7 +7915,7 @@ function Table({
|
|
|
7346
7915
|
"button",
|
|
7347
7916
|
{
|
|
7348
7917
|
onClick: () => goToPage(cp + 1),
|
|
7349
|
-
disabled: !
|
|
7918
|
+
disabled: !pagination.next_page_url,
|
|
7350
7919
|
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",
|
|
7351
7920
|
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.ChevronRight, { className: "h-4 w-4" })
|
|
7352
7921
|
}
|
|
@@ -7361,6 +7930,7 @@ function Table({
|
|
|
7361
7930
|
item: viewItem,
|
|
7362
7931
|
fields: viewFields,
|
|
7363
7932
|
width: defaultActions.modalWidth,
|
|
7933
|
+
grid: defaultActions.viewFormGrid,
|
|
7364
7934
|
onClose: () => setViewItem(null)
|
|
7365
7935
|
}
|
|
7366
7936
|
),
|