@juv/codego-react-ui 3.4.7 → 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 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: renderItem(item, index) }),
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
  {
@@ -6779,6 +6881,47 @@ function ViewModal({
6779
6881
  ]
6780
6882
  }
6781
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
+ }
6782
6925
  case "checkbox":
6783
6926
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
6784
6927
  "input",
@@ -7078,12 +7221,45 @@ var BADGE_COLORS = {
7078
7221
  function badgeClass(value) {
7079
7222
  return BADGE_COLORS[value.toLowerCase()] ?? "bg-primary/10 text-primary border-primary/20";
7080
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
+ }
7081
7252
  function Table({
7082
7253
  data,
7083
7254
  columns,
7255
+ loading,
7256
+ emptyState,
7257
+ error: errorProp,
7084
7258
  searchable = false,
7085
7259
  searchPlaceholder = "Search...",
7086
- pagination = false,
7260
+ searchValue: controlledSearch,
7261
+ onSearchChange,
7262
+ clientPagination = false,
7087
7263
  itemsPerPage = 10,
7088
7264
  selectable = false,
7089
7265
  onBulkDelete,
@@ -7091,15 +7267,38 @@ function Table({
7091
7267
  bulkDeleteBaseUrl,
7092
7268
  defaultActions,
7093
7269
  serverPagination,
7094
- className
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
7095
7285
  }) {
7096
7286
  const { toast } = useToast();
7097
- const [search, setSearch] = React28.useState("");
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
+ };
7098
7294
  const [currentPage, setCurrentPage] = React28.useState(1);
7099
7295
  const [selectedIds, setSelectedIds] = React28.useState([]);
7100
7296
  const [sortKey, setSortKey] = React28.useState(null);
7101
7297
  const [sortDir, setSortDir] = React28.useState(null);
7102
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);
7103
7302
  const [viewItem, setViewItem] = React28.useState(null);
7104
7303
  const [editItem, setEditItem] = React28.useState(null);
7105
7304
  const [deleteItem, setDeleteItem] = React28.useState(null);
@@ -7111,15 +7310,17 @@ function Table({
7111
7310
  const safeBaseUrl = defaultActions?.baseUrl.replace(/\/+$/, "") ?? "";
7112
7311
  const autoFields = React28.useMemo(() => {
7113
7312
  if (!tableData.length) return [];
7114
- return Object.keys(tableData[0]).map((k) => ({
7115
- key: k,
7116
- label: k.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
7117
- }));
7313
+ const row = tableData[0];
7314
+ return Object.keys(row).map((k) => deriveField(k, row[k]));
7118
7315
  }, [tableData]);
7119
7316
  const editFields = defaultActions?.editForm ?? autoFields;
7120
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]);
7121
7322
  const allColumns = React28.useMemo(() => {
7122
- if (!defaultActions) return columns;
7323
+ if (!defaultActions) return visibleColumns;
7123
7324
  const actionsCol = {
7124
7325
  key: "__actions__",
7125
7326
  title: "Actions",
@@ -7168,8 +7369,8 @@ function Table({
7168
7369
  ))
7169
7370
  ] })
7170
7371
  };
7171
- return defaultActions.position === "first" ? [actionsCol, ...columns] : [...columns, actionsCol];
7172
- }, [columns, defaultActions]);
7372
+ return defaultActions.position === "first" ? [actionsCol, ...visibleColumns] : [...visibleColumns, actionsCol];
7373
+ }, [visibleColumns, defaultActions]);
7173
7374
  const handleSort = (key) => {
7174
7375
  if (sortKey !== key) {
7175
7376
  setSortKey(key);
@@ -7202,13 +7403,28 @@ function Table({
7202
7403
  const totalPages = Math.max(1, Math.ceil(filteredData.length / itemsPerPage));
7203
7404
  const safePage = Math.min(currentPage, totalPages);
7204
7405
  const paginatedData = React28.useMemo(() => {
7205
- if (!pagination) return filteredData;
7406
+ if (!clientPagination) return filteredData;
7206
7407
  const start = (safePage - 1) * itemsPerPage;
7207
7408
  return filteredData.slice(start, start + itemsPerPage);
7208
- }, [filteredData, pagination, safePage, itemsPerPage]);
7409
+ }, [filteredData, clientPagination, safePage, itemsPerPage]);
7209
7410
  React28.useEffect(() => {
7210
7411
  setCurrentPage(1);
7211
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]);
7212
7428
  const handleSelectAll = (checked) => setSelectedIds(checked ? paginatedData.map((item) => String(item[idKey])) : []);
7213
7429
  const handleSelect = (id, checked) => setSelectedIds((prev) => checked ? [...prev, id] : prev.filter((i) => i !== id));
7214
7430
  const allSelected = paginatedData.length > 0 && selectedIds.length === paginatedData.length;
@@ -7268,6 +7484,7 @@ function Table({
7268
7484
  };
7269
7485
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
7270
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 }),
7271
7488
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-3 flex-wrap", children: [
7272
7489
  searchable && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "relative w-72", children: [
7273
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" }),
@@ -7343,6 +7560,33 @@ function Table({
7343
7560
  ]
7344
7561
  }
7345
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
+ ] }),
7346
7590
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
7347
7591
  totalRows,
7348
7592
  " ",
@@ -7351,8 +7595,26 @@ function Table({
7351
7595
  ] })
7352
7596
  ] })
7353
7597
  ] }),
7354
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "rounded-xl border border-border overflow-hidden bg-card/50 backdrop-blur-sm shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: "w-full overflow-auto", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("table", { className: "w-full caption-bottom text-sm", children: [
7355
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("tr", { className: "border-b border-border bg-muted/40", children: [
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: [
7356
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)(
7357
7619
  Checkbox,
7358
7620
  {
@@ -7360,13 +7622,16 @@ function Table({
7360
7622
  onChange: (e) => handleSelectAll(e.target.checked)
7361
7623
  }
7362
7624
  ) }),
7625
+ expandable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("th", { className: "h-11 w-8" }),
7363
7626
  allColumns.map((col, ci) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7364
7627
  "th",
7365
7628
  {
7366
7629
  onClick: () => col.sortable && handleSort(String(col.key)),
7367
7630
  className: cn(
7368
7631
  "h-11 px-4 text-left align-middle text-xs font-semibold uppercase tracking-wider text-muted-foreground select-none whitespace-nowrap",
7369
- 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"
7370
7635
  ),
7371
7636
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "inline-flex items-center", children: [
7372
7637
  col.title,
@@ -7379,9 +7644,9 @@ function Table({
7379
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)(
7380
7645
  "td",
7381
7646
  {
7382
- colSpan: allColumns.length + (selectable ? 1 : 0),
7647
+ colSpan: allColumns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0),
7383
7648
  className: "h-32 text-center align-middle",
7384
- 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: [
7385
7650
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.Search, { className: "h-8 w-8 opacity-20" }),
7386
7651
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: "No results found" }),
7387
7652
  search && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { onClick: () => setSearch(""), className: "text-xs text-primary hover:underline", children: "Clear search" })
@@ -7390,107 +7655,168 @@ function Table({
7390
7655
  ) }) : paginatedData.map((item, i) => {
7391
7656
  const id = String(item[idKey] || i);
7392
7657
  const isSelected = selectedIds.includes(id);
7393
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
7394
- "tr",
7395
- {
7396
- className: cn(
7397
- "border-b border-border/60 transition-colors last:border-0",
7398
- isSelected ? "bg-primary/5 hover:bg-primary/8" : "hover:bg-muted/30"
7399
- ),
7400
- children: [
7401
- selectable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: "px-4 py-3 align-middle", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7402
- Checkbox,
7403
- {
7404
- checked: isSelected,
7405
- onChange: (e) => handleSelect(id, e.target.checked)
7406
- }
7407
- ) }),
7408
- 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)(
7409
- "img",
7410
- {
7411
- src: item[col.key],
7412
- alt: item[col.key],
7413
- className: "h-9 w-9 rounded-lg object-cover ring-1 ring-border"
7414
- }
7415
- ) : col.type === "badge" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: cn(
7416
- "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium",
7417
- badgeClass(String(item[col.key]))
7418
- ), children: [
7419
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
7420
- "mr-1.5 h-1.5 w-1.5 rounded-full",
7421
- 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"
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
+ }
7422
7731
  ) }),
7423
- item[col.key]
7424
- ] }) : 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)(
7425
- "select",
7426
- {
7427
- value: item[col.key],
7428
- onChange: (e) => col.onChange?.(item, e.target.value),
7429
- 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",
7430
- children: (col.selectOptions ?? []).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: opt, children: opt }, opt))
7431
- }
7432
- ) : col.type === "toggle" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7433
- "button",
7434
- {
7435
- role: "switch",
7436
- "aria-checked": !!item[col.key],
7437
- onClick: () => col.onChange?.(item, !item[col.key]),
7438
- className: cn(
7439
- "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",
7440
- item[col.key] ? "bg-primary" : "bg-muted"
7441
- ),
7442
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
7443
- "pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
7444
- item[col.key] ? "translate-x-4" : "translate-x-0"
7445
- ) })
7446
- }
7447
- ) : col.type === "color" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
7448
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7449
- "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",
7450
7735
  {
7451
- type: "color",
7452
- value: item[col.key] || "#000000",
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],
7453
7753
  onChange: (e) => col.onChange?.(item, e.target.value),
7454
- className: "h-7 w-7 cursor-pointer rounded border border-border bg-transparent p-0.5"
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))
7455
7756
  }
7456
- ),
7457
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-xs text-muted-foreground font-mono", children: item[col.key] })
7458
- ] }) : col.type === "checkbox" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7459
- Checkbox,
7460
- {
7461
- checked: !!item[col.key],
7462
- onChange: (e) => col.onChange?.(item, e.target.checked)
7463
- }
7464
- ) : col.type === "text-url" ? (() => {
7465
- const href = col.redirect ? typeof col.redirect === "function" ? col.redirect(item) : col.redirect : String(item[col.key] ?? "");
7466
- const colorMap = {
7467
- primary: "var(--primary)",
7468
- info: "var(--info)",
7469
- success: "var(--success)",
7470
- warning: "var(--warning)",
7471
- danger: "var(--danger)"
7472
- };
7473
- const underline = col.underlineColor ? colorMap[col.underlineColor] ?? col.underlineColor : "var(--primary)";
7474
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7475
- "a",
7757
+ ) : col.type === "toggle" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
7758
+ "button",
7476
7759
  {
7477
- href,
7478
- target: col.openNewTab ? "_blank" : void 0,
7479
- rel: col.openNewTab ? "noopener noreferrer" : void 0,
7480
- style: { textDecorationColor: underline },
7481
- className: "text-sm underline underline-offset-2 hover:opacity-75 transition-opacity break-all",
7482
- onClick: col.openNewTab ? void 0 : (e) => e.preventDefault(),
7483
- children: item[col.key]
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
+ ) })
7484
7771
  }
7485
- );
7486
- })() : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-foreground/90", children: item[col.key] }) }, `${String(col.key)}-${ci}`))
7487
- ]
7488
- },
7489
- id
7490
- );
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);
7491
7817
  }) })
7492
7818
  ] }) }) }),
7493
- pagination && !serverPagination && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
7819
+ clientPagination && !serverPagination && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
7494
7820
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
7495
7821
  "Showing ",
7496
7822
  (safePage - 1) * itemsPerPage + 1,
@@ -7541,8 +7867,8 @@ function Table({
7541
7867
  ] })
7542
7868
  ] }),
7543
7869
  serverPagination && (() => {
7544
- const { pagination: pagination2, currentPage: cp, goToPage } = serverPagination;
7545
- const totalServerPages = pagination2.last_page ?? Math.ceil(pagination2.total / pagination2.per_page);
7870
+ const { pagination, currentPage: cp, goToPage } = serverPagination;
7871
+ const totalServerPages = pagination.last_page ?? Math.ceil(pagination.total / pagination.per_page);
7546
7872
  const pills = [];
7547
7873
  if (totalServerPages <= 7) {
7548
7874
  for (let i = 1; i <= totalServerPages; i++) pills.push(i);
@@ -7555,7 +7881,7 @@ function Table({
7555
7881
  }
7556
7882
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
7557
7883
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
7558
- pagination2.total,
7884
+ pagination.total,
7559
7885
  " total rows \xB7 page ",
7560
7886
  cp,
7561
7887
  " of ",
@@ -7566,7 +7892,7 @@ function Table({
7566
7892
  "button",
7567
7893
  {
7568
7894
  onClick: () => goToPage(cp - 1),
7569
- disabled: !pagination2.prev_page_url,
7895
+ disabled: !pagination.prev_page_url,
7570
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",
7571
7897
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.ChevronLeft, { className: "h-4 w-4" })
7572
7898
  }
@@ -7589,7 +7915,7 @@ function Table({
7589
7915
  "button",
7590
7916
  {
7591
7917
  onClick: () => goToPage(cp + 1),
7592
- disabled: !pagination2.next_page_url,
7918
+ disabled: !pagination.next_page_url,
7593
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",
7594
7920
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react17.ChevronRight, { className: "h-4 w-4" })
7595
7921
  }