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