@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.
@@ -63373,8 +63373,20 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63373
63373
  ];
63374
63374
  var PanelLeftOpen = createLucideIcon("panel-left-open", __iconNode49);
63375
63375
 
63376
- // node_modules/lucide-react/dist/esm/icons/pencil.js
63376
+ // node_modules/lucide-react/dist/esm/icons/paperclip.js
63377
63377
  var __iconNode50 = [
63378
+ [
63379
+ "path",
63380
+ {
63381
+ d: "m16 6-8.414 8.586a2 2 0 0 0 2.829 2.829l8.414-8.586a4 4 0 1 0-5.657-5.657l-8.379 8.551a6 6 0 1 0 8.485 8.485l8.379-8.551",
63382
+ key: "1miecu"
63383
+ }
63384
+ ]
63385
+ ];
63386
+ var Paperclip = createLucideIcon("paperclip", __iconNode50);
63387
+
63388
+ // node_modules/lucide-react/dist/esm/icons/pencil.js
63389
+ var __iconNode51 = [
63378
63390
  [
63379
63391
  "path",
63380
63392
  {
@@ -63384,10 +63396,10 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63384
63396
  ],
63385
63397
  ["path", { d: "m15 5 4 4", key: "1mk7zo" }]
63386
63398
  ];
63387
- var Pencil = createLucideIcon("pencil", __iconNode50);
63399
+ var Pencil = createLucideIcon("pencil", __iconNode51);
63388
63400
 
63389
63401
  // node_modules/lucide-react/dist/esm/icons/pin.js
63390
- var __iconNode51 = [
63402
+ var __iconNode52 = [
63391
63403
  ["path", { d: "M12 17v5", key: "bb1du9" }],
63392
63404
  [
63393
63405
  "path",
@@ -63397,17 +63409,17 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63397
63409
  }
63398
63410
  ]
63399
63411
  ];
63400
- var Pin = createLucideIcon("pin", __iconNode51);
63412
+ var Pin = createLucideIcon("pin", __iconNode52);
63401
63413
 
63402
63414
  // node_modules/lucide-react/dist/esm/icons/plus.js
63403
- var __iconNode52 = [
63415
+ var __iconNode53 = [
63404
63416
  ["path", { d: "M5 12h14", key: "1ays0h" }],
63405
63417
  ["path", { d: "M12 5v14", key: "s699le" }]
63406
63418
  ];
63407
- var Plus = createLucideIcon("plus", __iconNode52);
63419
+ var Plus = createLucideIcon("plus", __iconNode53);
63408
63420
 
63409
63421
  // node_modules/lucide-react/dist/esm/icons/quote.js
63410
- var __iconNode53 = [
63422
+ var __iconNode54 = [
63411
63423
  [
63412
63424
  "path",
63413
63425
  {
@@ -63423,31 +63435,31 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63423
63435
  }
63424
63436
  ]
63425
63437
  ];
63426
- var Quote = createLucideIcon("quote", __iconNode53);
63438
+ var Quote = createLucideIcon("quote", __iconNode54);
63427
63439
 
63428
63440
  // node_modules/lucide-react/dist/esm/icons/redo.js
63429
- var __iconNode54 = [
63441
+ var __iconNode55 = [
63430
63442
  ["path", { d: "M21 7v6h-6", key: "3ptur4" }],
63431
63443
  ["path", { d: "M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3l3 2.7", key: "1kgawr" }]
63432
63444
  ];
63433
- var Redo = createLucideIcon("redo", __iconNode54);
63445
+ var Redo = createLucideIcon("redo", __iconNode55);
63434
63446
 
63435
63447
  // node_modules/lucide-react/dist/esm/icons/rotate-ccw.js
63436
- var __iconNode55 = [
63448
+ var __iconNode56 = [
63437
63449
  ["path", { d: "M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8", key: "1357e3" }],
63438
63450
  ["path", { d: "M3 3v5h5", key: "1xhq8a" }]
63439
63451
  ];
63440
- var RotateCcw = createLucideIcon("rotate-ccw", __iconNode55);
63452
+ var RotateCcw = createLucideIcon("rotate-ccw", __iconNode56);
63441
63453
 
63442
63454
  // node_modules/lucide-react/dist/esm/icons/rotate-cw.js
63443
- var __iconNode56 = [
63455
+ var __iconNode57 = [
63444
63456
  ["path", { d: "M21 12a9 9 0 1 1-9-9c2.52 0 4.93 1 6.74 2.74L21 8", key: "1p45f6" }],
63445
63457
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }]
63446
63458
  ];
63447
- var RotateCw = createLucideIcon("rotate-cw", __iconNode56);
63459
+ var RotateCw = createLucideIcon("rotate-cw", __iconNode57);
63448
63460
 
63449
63461
  // node_modules/lucide-react/dist/esm/icons/satellite.js
63450
- var __iconNode57 = [
63462
+ var __iconNode58 = [
63451
63463
  [
63452
63464
  "path",
63453
63465
  {
@@ -63472,10 +63484,10 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63472
63484
  }
63473
63485
  ]
63474
63486
  ];
63475
- var Satellite = createLucideIcon("satellite", __iconNode57);
63487
+ var Satellite = createLucideIcon("satellite", __iconNode58);
63476
63488
 
63477
63489
  // node_modules/lucide-react/dist/esm/icons/save.js
63478
- var __iconNode58 = [
63490
+ var __iconNode59 = [
63479
63491
  [
63480
63492
  "path",
63481
63493
  {
@@ -63486,26 +63498,26 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63486
63498
  ["path", { d: "M17 21v-7a1 1 0 0 0-1-1H8a1 1 0 0 0-1 1v7", key: "1ydtos" }],
63487
63499
  ["path", { d: "M7 3v4a1 1 0 0 0 1 1h7", key: "t51u73" }]
63488
63500
  ];
63489
- var Save = createLucideIcon("save", __iconNode58);
63501
+ var Save = createLucideIcon("save", __iconNode59);
63490
63502
 
63491
63503
  // node_modules/lucide-react/dist/esm/icons/search.js
63492
- var __iconNode59 = [
63504
+ var __iconNode60 = [
63493
63505
  ["path", { d: "m21 21-4.34-4.34", key: "14j7rj" }],
63494
63506
  ["circle", { cx: "11", cy: "11", r: "8", key: "4ej97u" }]
63495
63507
  ];
63496
- var Search = createLucideIcon("search", __iconNode59);
63508
+ var Search = createLucideIcon("search", __iconNode60);
63497
63509
 
63498
63510
  // node_modules/lucide-react/dist/esm/icons/settings-2.js
63499
- var __iconNode60 = [
63511
+ var __iconNode61 = [
63500
63512
  ["path", { d: "M14 17H5", key: "gfn3mx" }],
63501
63513
  ["path", { d: "M19 7h-9", key: "6i9tg" }],
63502
63514
  ["circle", { cx: "17", cy: "17", r: "3", key: "18b49y" }],
63503
63515
  ["circle", { cx: "7", cy: "7", r: "3", key: "dfmy0x" }]
63504
63516
  ];
63505
- var Settings2 = createLucideIcon("settings-2", __iconNode60);
63517
+ var Settings2 = createLucideIcon("settings-2", __iconNode61);
63506
63518
 
63507
63519
  // node_modules/lucide-react/dist/esm/icons/sliders-vertical.js
63508
- var __iconNode61 = [
63520
+ var __iconNode62 = [
63509
63521
  ["path", { d: "M10 8h4", key: "1sr2af" }],
63510
63522
  ["path", { d: "M12 21v-9", key: "17s77i" }],
63511
63523
  ["path", { d: "M12 8V3", key: "13r4qs" }],
@@ -63516,10 +63528,10 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63516
63528
  ["path", { d: "M5 10V3", key: "cb8scm" }],
63517
63529
  ["path", { d: "M5 21v-7", key: "1w1uti" }]
63518
63530
  ];
63519
- var SlidersVertical = createLucideIcon("sliders-vertical", __iconNode61);
63531
+ var SlidersVertical = createLucideIcon("sliders-vertical", __iconNode62);
63520
63532
 
63521
63533
  // node_modules/lucide-react/dist/esm/icons/sun.js
63522
- var __iconNode62 = [
63534
+ var __iconNode63 = [
63523
63535
  ["circle", { cx: "12", cy: "12", r: "4", key: "4exip2" }],
63524
63536
  ["path", { d: "M12 2v2", key: "tus03m" }],
63525
63537
  ["path", { d: "M12 20v2", key: "1lh1kg" }],
@@ -63530,10 +63542,10 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63530
63542
  ["path", { d: "m6.34 17.66-1.41 1.41", key: "1m8zz5" }],
63531
63543
  ["path", { d: "m19.07 4.93-1.41 1.41", key: "1shlcs" }]
63532
63544
  ];
63533
- var Sun = createLucideIcon("sun", __iconNode62);
63545
+ var Sun = createLucideIcon("sun", __iconNode63);
63534
63546
 
63535
63547
  // node_modules/lucide-react/dist/esm/icons/tag.js
63536
- var __iconNode63 = [
63548
+ var __iconNode64 = [
63537
63549
  [
63538
63550
  "path",
63539
63551
  {
@@ -63543,42 +63555,42 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63543
63555
  ],
63544
63556
  ["circle", { cx: "7.5", cy: "7.5", r: ".5", fill: "currentColor", key: "kqv944" }]
63545
63557
  ];
63546
- var Tag = createLucideIcon("tag", __iconNode63);
63558
+ var Tag = createLucideIcon("tag", __iconNode64);
63547
63559
 
63548
63560
  // node_modules/lucide-react/dist/esm/icons/trash-2.js
63549
- var __iconNode64 = [
63561
+ var __iconNode65 = [
63550
63562
  ["path", { d: "M10 11v6", key: "nco0om" }],
63551
63563
  ["path", { d: "M14 11v6", key: "outv1u" }],
63552
63564
  ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
63553
63565
  ["path", { d: "M3 6h18", key: "d0wm0j" }],
63554
63566
  ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
63555
63567
  ];
63556
- var Trash2 = createLucideIcon("trash-2", __iconNode64);
63568
+ var Trash2 = createLucideIcon("trash-2", __iconNode65);
63557
63569
 
63558
63570
  // node_modules/lucide-react/dist/esm/icons/trash.js
63559
- var __iconNode65 = [
63571
+ var __iconNode66 = [
63560
63572
  ["path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6", key: "miytrc" }],
63561
63573
  ["path", { d: "M3 6h18", key: "d0wm0j" }],
63562
63574
  ["path", { d: "M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2", key: "e791ji" }]
63563
63575
  ];
63564
- var Trash = createLucideIcon("trash", __iconNode65);
63576
+ var Trash = createLucideIcon("trash", __iconNode66);
63565
63577
 
63566
63578
  // node_modules/lucide-react/dist/esm/icons/trending-down.js
63567
- var __iconNode66 = [
63579
+ var __iconNode67 = [
63568
63580
  ["path", { d: "M16 17h6v-6", key: "t6n2it" }],
63569
63581
  ["path", { d: "m22 17-8.5-8.5-5 5L2 7", key: "x473p" }]
63570
63582
  ];
63571
- var TrendingDown = createLucideIcon("trending-down", __iconNode66);
63583
+ var TrendingDown = createLucideIcon("trending-down", __iconNode67);
63572
63584
 
63573
63585
  // node_modules/lucide-react/dist/esm/icons/trending-up.js
63574
- var __iconNode67 = [
63586
+ var __iconNode68 = [
63575
63587
  ["path", { d: "M16 7h6v6", key: "box55l" }],
63576
63588
  ["path", { d: "m22 7-8.5 8.5-5-5L2 17", key: "1t1m79" }]
63577
63589
  ];
63578
- var TrendingUp = createLucideIcon("trending-up", __iconNode67);
63590
+ var TrendingUp = createLucideIcon("trending-up", __iconNode68);
63579
63591
 
63580
63592
  // node_modules/lucide-react/dist/esm/icons/triangle-alert.js
63581
- var __iconNode68 = [
63593
+ var __iconNode69 = [
63582
63594
  [
63583
63595
  "path",
63584
63596
  {
@@ -63589,28 +63601,28 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
63589
63601
  ["path", { d: "M12 9v4", key: "juzpu7" }],
63590
63602
  ["path", { d: "M12 17h.01", key: "p32p05" }]
63591
63603
  ];
63592
- var TriangleAlert = createLucideIcon("triangle-alert", __iconNode68);
63604
+ var TriangleAlert = createLucideIcon("triangle-alert", __iconNode69);
63593
63605
 
63594
63606
  // node_modules/lucide-react/dist/esm/icons/underline.js
63595
- var __iconNode69 = [
63607
+ var __iconNode70 = [
63596
63608
  ["path", { d: "M6 4v6a6 6 0 0 0 12 0V4", key: "9kb039" }],
63597
63609
  ["line", { x1: "4", x2: "20", y1: "20", y2: "20", key: "nun2al" }]
63598
63610
  ];
63599
- var Underline = createLucideIcon("underline", __iconNode69);
63611
+ var Underline = createLucideIcon("underline", __iconNode70);
63600
63612
 
63601
63613
  // node_modules/lucide-react/dist/esm/icons/undo.js
63602
- var __iconNode70 = [
63614
+ var __iconNode71 = [
63603
63615
  ["path", { d: "M3 7v6h6", key: "1v2h90" }],
63604
63616
  ["path", { d: "M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13", key: "1r6uu6" }]
63605
63617
  ];
63606
- var Undo = createLucideIcon("undo", __iconNode70);
63618
+ var Undo = createLucideIcon("undo", __iconNode71);
63607
63619
 
63608
63620
  // node_modules/lucide-react/dist/esm/icons/x.js
63609
- var __iconNode71 = [
63621
+ var __iconNode72 = [
63610
63622
  ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
63611
63623
  ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
63612
63624
  ];
63613
- var X = createLucideIcon("x", __iconNode71);
63625
+ var X = createLucideIcon("x", __iconNode72);
63614
63626
 
63615
63627
  // src/components/ui/date-picker.tsx
63616
63628
  var import_jsx_runtime2 = __toESM(require_jsx_runtime(), 1);
@@ -69055,11 +69067,77 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69055
69067
 
69056
69068
  // src/components/ui/repeater.tsx
69057
69069
  var import_jsx_runtime29 = __toESM(require_jsx_runtime(), 1);
69070
+ function RepeaterFieldRenderer({
69071
+ field,
69072
+ value,
69073
+ onChange
69074
+ }) {
69075
+ if (field.type === "image") {
69076
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
69077
+ field.label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
69078
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-3", children: [
69079
+ 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" }),
69080
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
69081
+ Input,
69082
+ {
69083
+ inputMode: "text",
69084
+ value: value ?? "",
69085
+ onChange: (e) => onChange(e.target.value),
69086
+ placeholder: field.placeholder ?? "Image URL"
69087
+ }
69088
+ )
69089
+ ] })
69090
+ ] });
69091
+ }
69092
+ if (field.type === "attachment") {
69093
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
69094
+ field.label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
69095
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex items-center gap-2", children: [
69096
+ value && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
69097
+ "a",
69098
+ {
69099
+ href: value,
69100
+ target: "_blank",
69101
+ rel: "noopener noreferrer",
69102
+ 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",
69103
+ children: [
69104
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(Paperclip, { className: "h-3 w-3" }),
69105
+ String(value).split("/").pop()
69106
+ ]
69107
+ }
69108
+ ),
69109
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
69110
+ Input,
69111
+ {
69112
+ inputMode: "text",
69113
+ value: value ?? "",
69114
+ onChange: (e) => onChange(e.target.value),
69115
+ placeholder: field.placeholder ?? "Attachment URL"
69116
+ }
69117
+ )
69118
+ ] })
69119
+ ] });
69120
+ }
69121
+ return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-1.5", children: [
69122
+ field.label && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("span", { className: "text-xs font-medium text-muted-foreground", children: field.label }),
69123
+ /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
69124
+ Input,
69125
+ {
69126
+ inputMode: "text",
69127
+ value: value ?? "",
69128
+ onChange: (e) => onChange(e.target.value),
69129
+ placeholder: field.placeholder ?? field.key
69130
+ }
69131
+ )
69132
+ ] });
69133
+ }
69058
69134
  function Repeater({
69059
69135
  items,
69060
69136
  onAdd,
69061
69137
  onRemove,
69062
69138
  renderItem,
69139
+ fields,
69140
+ onFieldChange,
69063
69141
  addButtonText = "Add Item",
69064
69142
  className
69065
69143
  }) {
@@ -69072,7 +69150,15 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69072
69150
  children: [
69073
69151
  /* @__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)(GripVertical, { className: "h-4 w-4" }) }),
69074
69152
  /* @__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 }),
69075
- /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("div", { className: "flex-1 min-w-0", children: renderItem(item, index) }),
69153
+ /* @__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)(
69154
+ RepeaterFieldRenderer,
69155
+ {
69156
+ field: f,
69157
+ value: item[f.key],
69158
+ onChange: (v) => onFieldChange?.(index, f.key, v)
69159
+ },
69160
+ f.key
69161
+ )) }) : renderItem ? renderItem(item, index) : null }),
69076
69162
  /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
69077
69163
  Button,
69078
69164
  {
@@ -69642,8 +69728,14 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69642
69728
  goToPage: (page) => setCurrentPage(page),
69643
69729
  reload: () => setTick((t) => t + 1),
69644
69730
  refresh: () => setTick((t) => t + 1),
69731
+ // Passthrough props
69645
69732
  searchValue,
69646
- onSearchChange: handleSearchChange
69733
+ onSearchChange: handleSearchChange,
69734
+ page: currentPage,
69735
+ onPageChange: (page) => setCurrentPage(page),
69736
+ sort: [],
69737
+ onSortChange: () => {
69738
+ }
69647
69739
  };
69648
69740
  }
69649
69741
  var MODAL_WIDTH = {
@@ -69799,6 +69891,28 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69799
69891
  } });
69800
69892
  case "repeater": {
69801
69893
  const items = Array.isArray(value) ? value : [];
69894
+ if (field.repeaterFields) {
69895
+ const rows = Array.isArray(value) ? value : [];
69896
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
69897
+ Repeater,
69898
+ {
69899
+ items: rows,
69900
+ fields: field.repeaterFields,
69901
+ onAdd: () => {
69902
+ const blank = {};
69903
+ field.repeaterFields.forEach((f) => {
69904
+ blank[f.key] = "";
69905
+ });
69906
+ onChange([...rows, blank]);
69907
+ },
69908
+ onRemove: (i) => onChange(rows.filter((_, idx) => idx !== i)),
69909
+ onFieldChange: (i, key, val) => {
69910
+ const next = rows.map((r2, idx) => idx === i ? { ...r2, [key]: val } : r2);
69911
+ onChange(next);
69912
+ }
69913
+ }
69914
+ );
69915
+ }
69802
69916
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
69803
69917
  Repeater,
69804
69918
  {
@@ -69925,6 +70039,47 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
69925
70039
  ]
69926
70040
  }
69927
70041
  );
70042
+ case "repeater": {
70043
+ const rows = Array.isArray(value) ? value : [];
70044
+ if (!rows.length) return dash;
70045
+ const rFields = f.repeaterFields;
70046
+ 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: [
70047
+ /* @__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 }),
70048
+ rFields ? rFields.map((rf) => {
70049
+ const v = row[rf.key];
70050
+ if (rf.type === "image") return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
70051
+ rf.label && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
70052
+ 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
70053
+ ] }, rf.key);
70054
+ if (rf.type === "attachment") return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
70055
+ rf.label && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
70056
+ v ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
70057
+ "a",
70058
+ {
70059
+ href: v,
70060
+ target: "_blank",
70061
+ rel: "noopener noreferrer",
70062
+ 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",
70063
+ children: [
70064
+ /* @__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" }) }),
70065
+ String(v).split("/").pop()
70066
+ ]
70067
+ }
70068
+ ) : dash
70069
+ ] }, rf.key);
70070
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
70071
+ rf.label && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: rf.label }),
70072
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: v ?? "\u2014" })
70073
+ ] }, rf.key);
70074
+ }) : (
70075
+ // payload mode: row has { type, key, value }
70076
+ Object.entries(row).map(([k, v]) => /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col gap-1", children: [
70077
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-[10px] text-muted-foreground", children: k }),
70078
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: String(v) })
70079
+ ] }, k))
70080
+ )
70081
+ ] }, ri)) });
70082
+ }
69928
70083
  case "checkbox":
69929
70084
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
69930
70085
  "input",
@@ -70224,12 +70379,45 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70224
70379
  function badgeClass(value) {
70225
70380
  return BADGE_COLORS[value.toLowerCase()] ?? "bg-primary/10 text-primary border-primary/20";
70226
70381
  }
70382
+ function deriveField(key, sample) {
70383
+ const label = key.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
70384
+ const base = { key, label };
70385
+ if (typeof sample === "boolean") return { ...base, type: "toggle", viewType: "toggle" };
70386
+ if (typeof sample === "number") return { ...base, inputType: "number" };
70387
+ if (Array.isArray(sample)) {
70388
+ if (sample.length === 0 || typeof sample[0] === "string")
70389
+ return { ...base, type: "tag-input" };
70390
+ return base;
70391
+ }
70392
+ if (typeof sample === "string") {
70393
+ if (/\.(png|jpe?g|gif|webp|svg|avif)(\?.*)?$/i.test(sample))
70394
+ return { ...base, type: "input", viewType: "image" };
70395
+ if (/\.(pdf|docx?|xlsx?|csv|zip|pptx?)(\?.*)?$/i.test(sample))
70396
+ return { ...base, type: "input", viewType: "attachment" };
70397
+ if (/^https?:\/\//.test(sample))
70398
+ return { ...base, type: "input", viewType: "text-url-open-other-tabs" };
70399
+ if (sample.length > 120 || /\n/.test(sample))
70400
+ return { ...base, type: "textarea" };
70401
+ if (/password|secret|token/i.test(key))
70402
+ return { ...base, type: "password" };
70403
+ if (/email/i.test(key))
70404
+ return { ...base, inputType: "email" };
70405
+ if (/color|colour/i.test(key) && /^#[0-9a-f]{3,8}$/i.test(sample))
70406
+ return { ...base, type: "color-picker", viewType: "text" };
70407
+ }
70408
+ return base;
70409
+ }
70227
70410
  function Table({
70228
70411
  data,
70229
70412
  columns,
70413
+ loading,
70414
+ emptyState,
70415
+ error: errorProp,
70230
70416
  searchable = false,
70231
70417
  searchPlaceholder = "Search...",
70232
- pagination = false,
70418
+ searchValue: controlledSearch,
70419
+ onSearchChange,
70420
+ clientPagination = false,
70233
70421
  itemsPerPage = 10,
70234
70422
  selectable = false,
70235
70423
  onBulkDelete,
@@ -70237,15 +70425,38 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70237
70425
  bulkDeleteBaseUrl,
70238
70426
  defaultActions,
70239
70427
  serverPagination,
70240
- className
70428
+ variant = "default",
70429
+ className,
70430
+ onRowClick,
70431
+ onRowDoubleClick,
70432
+ rowClassName,
70433
+ expandable = false,
70434
+ renderExpanded,
70435
+ columnVisibility,
70436
+ onColumnVisibilityChange,
70437
+ exportable = false,
70438
+ onExport,
70439
+ virtualized = false,
70440
+ draggable = false,
70441
+ onRowReorder,
70442
+ keyboardNavigation = false
70241
70443
  }) {
70242
70444
  const { toast } = useToast();
70243
- const [search, setSearch] = React28.useState("");
70445
+ const isControlledSearch = controlledSearch !== void 0;
70446
+ const [internalSearch, setInternalSearch] = React28.useState("");
70447
+ const search = isControlledSearch ? controlledSearch : internalSearch;
70448
+ const setSearch = (v) => {
70449
+ if (!isControlledSearch) setInternalSearch(v);
70450
+ onSearchChange?.(v);
70451
+ };
70244
70452
  const [currentPage, setCurrentPage] = React28.useState(1);
70245
70453
  const [selectedIds, setSelectedIds] = React28.useState([]);
70246
70454
  const [sortKey, setSortKey] = React28.useState(null);
70247
70455
  const [sortDir, setSortDir] = React28.useState(null);
70248
70456
  const [bulkLoading, setBulkLoading] = React28.useState(false);
70457
+ const [expandedIds, setExpandedIds] = React28.useState(/* @__PURE__ */ new Set());
70458
+ const [dragOverId, setDragOverId] = React28.useState(null);
70459
+ const [focusedRowIdx, setFocusedRowIdx] = React28.useState(-1);
70249
70460
  const [viewItem, setViewItem] = React28.useState(null);
70250
70461
  const [editItem, setEditItem] = React28.useState(null);
70251
70462
  const [deleteItem, setDeleteItem] = React28.useState(null);
@@ -70257,15 +70468,17 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70257
70468
  const safeBaseUrl = defaultActions?.baseUrl.replace(/\/+$/, "") ?? "";
70258
70469
  const autoFields = React28.useMemo(() => {
70259
70470
  if (!tableData.length) return [];
70260
- return Object.keys(tableData[0]).map((k) => ({
70261
- key: k,
70262
- label: k.replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase())
70263
- }));
70471
+ const row = tableData[0];
70472
+ return Object.keys(row).map((k) => deriveField(k, row[k]));
70264
70473
  }, [tableData]);
70265
70474
  const editFields = defaultActions?.editForm ?? autoFields;
70266
70475
  const viewFields = defaultActions?.viewForm ?? autoFields;
70476
+ const visibleColumns = React28.useMemo(() => {
70477
+ if (!columnVisibility) return columns;
70478
+ return columns.filter((col) => columnVisibility[String(col.key)] !== false);
70479
+ }, [columns, columnVisibility]);
70267
70480
  const allColumns = React28.useMemo(() => {
70268
- if (!defaultActions) return columns;
70481
+ if (!defaultActions) return visibleColumns;
70269
70482
  const actionsCol = {
70270
70483
  key: "__actions__",
70271
70484
  title: "Actions",
@@ -70314,8 +70527,8 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70314
70527
  ))
70315
70528
  ] })
70316
70529
  };
70317
- return defaultActions.position === "first" ? [actionsCol, ...columns] : [...columns, actionsCol];
70318
- }, [columns, defaultActions]);
70530
+ return defaultActions.position === "first" ? [actionsCol, ...visibleColumns] : [...visibleColumns, actionsCol];
70531
+ }, [visibleColumns, defaultActions]);
70319
70532
  const handleSort = (key) => {
70320
70533
  if (sortKey !== key) {
70321
70534
  setSortKey(key);
@@ -70348,13 +70561,28 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70348
70561
  const totalPages = Math.max(1, Math.ceil(filteredData.length / itemsPerPage));
70349
70562
  const safePage = Math.min(currentPage, totalPages);
70350
70563
  const paginatedData = React28.useMemo(() => {
70351
- if (!pagination) return filteredData;
70564
+ if (!clientPagination) return filteredData;
70352
70565
  const start = (safePage - 1) * itemsPerPage;
70353
70566
  return filteredData.slice(start, start + itemsPerPage);
70354
- }, [filteredData, pagination, safePage, itemsPerPage]);
70567
+ }, [filteredData, clientPagination, safePage, itemsPerPage]);
70355
70568
  React28.useEffect(() => {
70356
70569
  setCurrentPage(1);
70357
70570
  }, [search]);
70571
+ React28.useEffect(() => {
70572
+ if (!keyboardNavigation) return;
70573
+ const handler = (e) => {
70574
+ if (e.key === "ArrowDown") {
70575
+ e.preventDefault();
70576
+ setFocusedRowIdx((i) => Math.min(i + 1, paginatedData.length - 1));
70577
+ }
70578
+ if (e.key === "ArrowUp") {
70579
+ e.preventDefault();
70580
+ setFocusedRowIdx((i) => Math.max(i - 1, 0));
70581
+ }
70582
+ };
70583
+ window.addEventListener("keydown", handler);
70584
+ return () => window.removeEventListener("keydown", handler);
70585
+ }, [keyboardNavigation, paginatedData.length]);
70358
70586
  const handleSelectAll = (checked) => setSelectedIds(checked ? paginatedData.map((item) => String(item[idKey])) : []);
70359
70587
  const handleSelect = (id, checked) => setSelectedIds((prev) => checked ? [...prev, id] : prev.filter((i) => i !== id));
70360
70588
  const allSelected = paginatedData.length > 0 && selectedIds.length === paginatedData.length;
@@ -70414,6 +70642,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70414
70642
  };
70415
70643
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_jsx_runtime32.Fragment, { children: [
70416
70644
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: cn("w-full space-y-3", className), children: [
70645
+ 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 }),
70417
70646
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-3 flex-wrap", children: [
70418
70647
  searchable && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "relative w-72", children: [
70419
70648
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Search, { className: "absolute text-primary left-3 top-1/2 -translate-y-1/2 h-4 w-4 z-10" }),
@@ -70489,6 +70718,33 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70489
70718
  ]
70490
70719
  }
70491
70720
  ),
70721
+ exportable && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "relative group", children: [
70722
+ /* @__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" }),
70723
+ /* @__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)(
70724
+ "button",
70725
+ {
70726
+ onClick: () => onExport?.(type),
70727
+ className: "px-4 py-2 text-xs text-left hover:bg-muted transition-colors capitalize",
70728
+ children: type.toUpperCase()
70729
+ },
70730
+ type
70731
+ )) })
70732
+ ] }),
70733
+ columnVisibility && onColumnVisibilityChange && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "relative group", children: [
70734
+ /* @__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" }),
70735
+ /* @__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: [
70736
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70737
+ "input",
70738
+ {
70739
+ type: "checkbox",
70740
+ checked: columnVisibility[String(col.key)] !== false,
70741
+ onChange: (e) => onColumnVisibilityChange({ ...columnVisibility, [String(col.key)]: e.target.checked }),
70742
+ className: "accent-primary"
70743
+ }
70744
+ ),
70745
+ col.title
70746
+ ] }, String(col.key))) })
70747
+ ] }),
70492
70748
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
70493
70749
  totalRows,
70494
70750
  " ",
@@ -70497,8 +70753,26 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70497
70753
  ] })
70498
70754
  ] })
70499
70755
  ] }),
70500
- /* @__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: [
70501
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("tr", { className: "border-b border-border bg-muted/40", children: [
70756
+ loading && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-center py-12 text-muted-foreground gap-2", children: [
70757
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(LoaderCircle, { className: "h-5 w-5 animate-spin" }),
70758
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: "Loading\u2026" })
70759
+ ] }),
70760
+ !loading && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("div", { className: cn(
70761
+ variant === "default" && "rounded-xl border border-border overflow-hidden bg-card/50 backdrop-blur-sm shadow-sm",
70762
+ variant === "zebra" && "rounded-xl border border-border overflow-hidden bg-card/50 backdrop-blur-sm shadow-sm",
70763
+ variant === "card" && "space-y-2",
70764
+ variant === "glass" && "rounded-2xl overflow-hidden border border-white/10 bg-background/30 backdrop-blur-xl shadow-xl",
70765
+ variant === "soft" && "rounded-2xl overflow-hidden bg-card",
70766
+ variant === "soft" && "[box-shadow:6px_6px_12px_hsl(var(--foreground)/0.07),-6px_-6px_12px_hsl(var(--background)/0.8)]",
70767
+ virtualized && "max-h-[520px] overflow-y-auto"
70768
+ ), 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: [
70769
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("thead", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("tr", { className: cn(
70770
+ variant === "default" && "border-b border-border bg-muted/40",
70771
+ variant === "zebra" && "border-b border-border bg-muted/40",
70772
+ variant === "card" && "[&>th]:bg-transparent",
70773
+ variant === "glass" && "border-b border-white/10 bg-white/5",
70774
+ variant === "soft" && "border-b-0 bg-muted/30"
70775
+ ), children: [
70502
70776
  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)(
70503
70777
  Checkbox,
70504
70778
  {
@@ -70506,13 +70780,16 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70506
70780
  onChange: (e) => handleSelectAll(e.target.checked)
70507
70781
  }
70508
70782
  ) }),
70783
+ expandable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("th", { className: "h-11 w-8" }),
70509
70784
  allColumns.map((col, ci) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70510
70785
  "th",
70511
70786
  {
70512
70787
  onClick: () => col.sortable && handleSort(String(col.key)),
70513
70788
  className: cn(
70514
70789
  "h-11 px-4 text-left align-middle text-xs font-semibold uppercase tracking-wider text-muted-foreground select-none whitespace-nowrap",
70515
- col.sortable && "cursor-pointer hover:text-foreground transition-colors"
70790
+ col.sortable && "cursor-pointer hover:text-foreground transition-colors",
70791
+ variant === "glass" && "text-foreground/70",
70792
+ variant === "soft" && "text-muted-foreground/80"
70516
70793
  ),
70517
70794
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "inline-flex items-center", children: [
70518
70795
  col.title,
@@ -70525,9 +70802,9 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70525
70802
  /* @__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)(
70526
70803
  "td",
70527
70804
  {
70528
- colSpan: allColumns.length + (selectable ? 1 : 0),
70805
+ colSpan: allColumns.length + (selectable ? 1 : 0) + (expandable ? 1 : 0),
70529
70806
  className: "h-32 text-center align-middle",
70530
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col items-center gap-1 text-muted-foreground", children: [
70807
+ children: emptyState ?? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex flex-col items-center gap-1 text-muted-foreground", children: [
70531
70808
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Search, { className: "h-8 w-8 opacity-20" }),
70532
70809
  /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-sm", children: "No results found" }),
70533
70810
  search && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { onClick: () => setSearch(""), className: "text-xs text-primary hover:underline", children: "Clear search" })
@@ -70536,107 +70813,168 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70536
70813
  ) }) : paginatedData.map((item, i) => {
70537
70814
  const id = String(item[idKey] || i);
70538
70815
  const isSelected = selectedIds.includes(id);
70539
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
70540
- "tr",
70541
- {
70542
- className: cn(
70543
- "border-b border-border/60 transition-colors last:border-0",
70544
- isSelected ? "bg-primary/5 hover:bg-primary/8" : "hover:bg-muted/30"
70545
- ),
70546
- children: [
70547
- selectable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: "px-4 py-3 align-middle", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70548
- Checkbox,
70549
- {
70550
- checked: isSelected,
70551
- onChange: (e) => handleSelect(id, e.target.checked)
70552
- }
70553
- ) }),
70554
- 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)(
70555
- "img",
70556
- {
70557
- src: item[col.key],
70558
- alt: item[col.key],
70559
- className: "h-9 w-9 rounded-lg object-cover ring-1 ring-border"
70560
- }
70561
- ) : col.type === "badge" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: cn(
70562
- "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium",
70563
- badgeClass(String(item[col.key]))
70564
- ), children: [
70565
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
70566
- "mr-1.5 h-1.5 w-1.5 rounded-full",
70567
- 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"
70816
+ const isExpanded = expandedIds.has(id);
70817
+ const isFocused = keyboardNavigation && focusedRowIdx === i;
70818
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(React28.Fragment, { children: [
70819
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
70820
+ "tr",
70821
+ {
70822
+ draggable,
70823
+ tabIndex: keyboardNavigation ? 0 : void 0,
70824
+ onDragStart: draggable ? (e) => {
70825
+ e.dataTransfer.setData("text/plain", id);
70826
+ } : void 0,
70827
+ onDragOver: draggable ? (e) => {
70828
+ e.preventDefault();
70829
+ setDragOverId(id);
70830
+ } : void 0,
70831
+ onDragLeave: draggable ? () => setDragOverId(null) : void 0,
70832
+ onDrop: draggable ? (e) => {
70833
+ e.preventDefault();
70834
+ setDragOverId(null);
70835
+ const fromId = e.dataTransfer.getData("text/plain");
70836
+ if (fromId === id) return;
70837
+ setTableData((prev) => {
70838
+ const fromIdx = prev.findIndex((r2) => String(r2[idKey] || "") === fromId);
70839
+ const toIdx = prev.findIndex((r2) => String(r2[idKey] || "") === id);
70840
+ if (fromIdx < 0 || toIdx < 0) return prev;
70841
+ const next = [...prev];
70842
+ const [moved] = next.splice(fromIdx, 1);
70843
+ next.splice(toIdx, 0, moved);
70844
+ onRowReorder?.(next);
70845
+ return next;
70846
+ });
70847
+ } : void 0,
70848
+ onClick: () => {
70849
+ if (expandable) setExpandedIds((prev) => {
70850
+ const s = new Set(prev);
70851
+ s.has(id) ? s.delete(id) : s.add(id);
70852
+ return s;
70853
+ });
70854
+ onRowClick?.(item);
70855
+ if (keyboardNavigation) setFocusedRowIdx(i);
70856
+ },
70857
+ onDoubleClick: () => onRowDoubleClick?.(item),
70858
+ className: cn(
70859
+ // default
70860
+ variant === "default" && "border-b border-border/60 transition-colors last:border-0",
70861
+ variant === "default" && (isSelected ? "bg-primary/5 hover:bg-primary/8" : "hover:bg-muted/30"),
70862
+ // zebra
70863
+ variant === "zebra" && "border-b border-border/40 transition-colors last:border-0",
70864
+ variant === "zebra" && (isSelected ? "bg-primary/8" : i % 2 === 0 ? "bg-card" : "bg-muted/40"),
70865
+ variant === "zebra" && !isSelected && "hover:bg-primary/5",
70866
+ // card
70867
+ variant === "card" && "rounded-xl border border-border bg-card shadow-sm transition-all hover:shadow-md hover:-translate-y-px",
70868
+ variant === "card" && (isSelected ? "border-primary/50 bg-primary/5" : ""),
70869
+ variant === "card" && "[&>td:first-child]:rounded-l-xl [&>td:last-child]:rounded-r-xl",
70870
+ // glass
70871
+ variant === "glass" && "border-b border-white/8 transition-colors last:border-0",
70872
+ variant === "glass" && (isSelected ? "bg-primary/15 hover:bg-primary/20" : "hover:bg-white/5"),
70873
+ // soft
70874
+ variant === "soft" && "transition-all",
70875
+ 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"),
70876
+ variant === "soft" && "border-b border-border/30 last:border-0",
70877
+ (onRowClick || onRowDoubleClick || expandable) && "cursor-pointer",
70878
+ draggable && dragOverId === id && "ring-2 ring-inset ring-primary/40",
70879
+ isFocused && "ring-2 ring-inset ring-ring",
70880
+ rowClassName?.(item)
70881
+ ),
70882
+ children: [
70883
+ selectable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: "px-4 py-3 align-middle", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70884
+ Checkbox,
70885
+ {
70886
+ checked: isSelected,
70887
+ onChange: (e) => handleSelect(id, e.target.checked)
70888
+ }
70568
70889
  ) }),
70569
- item[col.key]
70570
- ] }) : 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)(
70571
- "select",
70572
- {
70573
- value: item[col.key],
70574
- onChange: (e) => col.onChange?.(item, e.target.value),
70575
- 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",
70576
- children: (col.selectOptions ?? []).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: opt, children: opt }, opt))
70577
- }
70578
- ) : col.type === "toggle" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70579
- "button",
70580
- {
70581
- role: "switch",
70582
- "aria-checked": !!item[col.key],
70583
- onClick: () => col.onChange?.(item, !item[col.key]),
70584
- className: cn(
70585
- "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",
70586
- item[col.key] ? "bg-primary" : "bg-muted"
70587
- ),
70588
- children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
70589
- "pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
70590
- item[col.key] ? "translate-x-4" : "translate-x-0"
70591
- ) })
70592
- }
70593
- ) : col.type === "color" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
70594
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70595
- "input",
70890
+ expandable && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("td", { className: "w-8 px-2 py-3 align-middle", children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ChevronRight, { className: cn("h-3.5 w-3.5 text-muted-foreground transition-transform", isExpanded && "rotate-90") }) }),
70891
+ 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)(
70892
+ "img",
70893
+ {
70894
+ src: item[col.key],
70895
+ alt: item[col.key],
70896
+ className: "h-9 w-9 rounded-lg object-cover ring-1 ring-border"
70897
+ }
70898
+ ) : col.type === "badge" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: cn(
70899
+ "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium",
70900
+ badgeClass(String(item[col.key]))
70901
+ ), children: [
70902
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
70903
+ "mr-1.5 h-1.5 w-1.5 rounded-full",
70904
+ 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"
70905
+ ) }),
70906
+ item[col.key]
70907
+ ] }) : 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)(
70908
+ "select",
70596
70909
  {
70597
- type: "color",
70598
- value: item[col.key] || "#000000",
70910
+ value: item[col.key],
70599
70911
  onChange: (e) => col.onChange?.(item, e.target.value),
70600
- className: "h-7 w-7 cursor-pointer rounded border border-border bg-transparent p-0.5"
70912
+ 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",
70913
+ children: (col.selectOptions ?? []).map((opt) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("option", { value: opt, children: opt }, opt))
70601
70914
  }
70602
- ),
70603
- /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-xs text-muted-foreground font-mono", children: item[col.key] })
70604
- ] }) : col.type === "checkbox" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70605
- Checkbox,
70606
- {
70607
- checked: !!item[col.key],
70608
- onChange: (e) => col.onChange?.(item, e.target.checked)
70609
- }
70610
- ) : col.type === "text-url" ? (() => {
70611
- const href = col.redirect ? typeof col.redirect === "function" ? col.redirect(item) : col.redirect : String(item[col.key] ?? "");
70612
- const colorMap = {
70613
- primary: "var(--primary)",
70614
- info: "var(--info)",
70615
- success: "var(--success)",
70616
- warning: "var(--warning)",
70617
- danger: "var(--danger)"
70618
- };
70619
- const underline = col.underlineColor ? colorMap[col.underlineColor] ?? col.underlineColor : "var(--primary)";
70620
- return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70621
- "a",
70915
+ ) : col.type === "toggle" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70916
+ "button",
70622
70917
  {
70623
- href,
70624
- target: col.openNewTab ? "_blank" : void 0,
70625
- rel: col.openNewTab ? "noopener noreferrer" : void 0,
70626
- style: { textDecorationColor: underline },
70627
- className: "text-sm underline underline-offset-2 hover:opacity-75 transition-opacity break-all",
70628
- onClick: col.openNewTab ? void 0 : (e) => e.preventDefault(),
70629
- children: item[col.key]
70918
+ role: "switch",
70919
+ "aria-checked": !!item[col.key],
70920
+ onClick: () => col.onChange?.(item, !item[col.key]),
70921
+ className: cn(
70922
+ "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",
70923
+ item[col.key] ? "bg-primary" : "bg-muted"
70924
+ ),
70925
+ children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: cn(
70926
+ "pointer-events-none inline-block h-4 w-4 rounded-full bg-white shadow-sm transition-transform",
70927
+ item[col.key] ? "translate-x-4" : "translate-x-0"
70928
+ ) })
70630
70929
  }
70631
- );
70632
- })() : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-foreground/90", children: item[col.key] }) }, `${String(col.key)}-${ci}`))
70633
- ]
70634
- },
70635
- id
70636
- );
70930
+ ) : col.type === "color" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center gap-2", children: [
70931
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70932
+ "input",
70933
+ {
70934
+ type: "color",
70935
+ value: item[col.key] || "#000000",
70936
+ onChange: (e) => col.onChange?.(item, e.target.value),
70937
+ className: "h-7 w-7 cursor-pointer rounded border border-border bg-transparent p-0.5"
70938
+ }
70939
+ ),
70940
+ /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-xs text-muted-foreground font-mono", children: item[col.key] })
70941
+ ] }) : col.type === "checkbox" ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70942
+ Checkbox,
70943
+ {
70944
+ checked: !!item[col.key],
70945
+ onChange: (e) => col.onChange?.(item, e.target.checked)
70946
+ }
70947
+ ) : col.type === "text-url" ? (() => {
70948
+ const href = col.redirect ? typeof col.redirect === "function" ? col.redirect(item) : col.redirect : String(item[col.key] ?? "");
70949
+ const colorMap = {
70950
+ primary: "var(--primary)",
70951
+ info: "var(--info)",
70952
+ success: "var(--success)",
70953
+ warning: "var(--warning)",
70954
+ danger: "var(--danger)"
70955
+ };
70956
+ const underline = col.underlineColor ? colorMap[col.underlineColor] ?? col.underlineColor : "var(--primary)";
70957
+ return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
70958
+ "a",
70959
+ {
70960
+ href,
70961
+ target: col.openNewTab ? "_blank" : void 0,
70962
+ rel: col.openNewTab ? "noopener noreferrer" : void 0,
70963
+ style: { textDecorationColor: underline },
70964
+ className: "text-sm underline underline-offset-2 hover:opacity-75 transition-opacity break-all",
70965
+ onClick: col.openNewTab ? void 0 : (e) => e.preventDefault(),
70966
+ children: item[col.key]
70967
+ }
70968
+ );
70969
+ })() : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: "text-foreground/90", children: item[col.key] }) }, `${String(col.key)}-${ci}`))
70970
+ ]
70971
+ }
70972
+ ),
70973
+ 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) }) })
70974
+ ] }, id);
70637
70975
  }) })
70638
70976
  ] }) }) }),
70639
- pagination && !serverPagination && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
70977
+ clientPagination && !serverPagination && totalPages > 1 && /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
70640
70978
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
70641
70979
  "Showing ",
70642
70980
  (safePage - 1) * itemsPerPage + 1,
@@ -70687,8 +71025,8 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70687
71025
  ] })
70688
71026
  ] }),
70689
71027
  serverPagination && (() => {
70690
- const { pagination: pagination2, currentPage: cp, goToPage } = serverPagination;
70691
- const totalServerPages = pagination2.last_page ?? Math.ceil(pagination2.total / pagination2.per_page);
71028
+ const { pagination, currentPage: cp, goToPage } = serverPagination;
71029
+ const totalServerPages = pagination.last_page ?? Math.ceil(pagination.total / pagination.per_page);
70692
71030
  const pills = [];
70693
71031
  if (totalServerPages <= 7) {
70694
71032
  for (let i = 1; i <= totalServerPages; i++) pills.push(i);
@@ -70701,7 +71039,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70701
71039
  }
70702
71040
  return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { className: "flex items-center justify-between gap-2 flex-wrap", children: [
70703
71041
  /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: "text-xs text-muted-foreground", children: [
70704
- pagination2.total,
71042
+ pagination.total,
70705
71043
  " total rows \xB7 page ",
70706
71044
  cp,
70707
71045
  " of ",
@@ -70712,7 +71050,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70712
71050
  "button",
70713
71051
  {
70714
71052
  onClick: () => goToPage(cp - 1),
70715
- disabled: !pagination2.prev_page_url,
71053
+ disabled: !pagination.prev_page_url,
70716
71054
  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",
70717
71055
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ChevronLeft, { className: "h-4 w-4" })
70718
71056
  }
@@ -70735,7 +71073,7 @@ ${n2.shaderPreludeCode.vertexSource}`, define: n2.shaderDefine }, defaultProject
70735
71073
  "button",
70736
71074
  {
70737
71075
  onClick: () => goToPage(cp + 1),
70738
- disabled: !pagination2.next_page_url,
71076
+ disabled: !pagination.next_page_url,
70739
71077
  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",
70740
71078
  children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ChevronRight, { className: "h-4 w-4" })
70741
71079
  }
@@ -77199,6 +77537,7 @@ lucide-react/dist/esm/icons/minus.js:
77199
77537
  lucide-react/dist/esm/icons/moon.js:
77200
77538
  lucide-react/dist/esm/icons/panel-left-close.js:
77201
77539
  lucide-react/dist/esm/icons/panel-left-open.js:
77540
+ lucide-react/dist/esm/icons/paperclip.js:
77202
77541
  lucide-react/dist/esm/icons/pencil.js:
77203
77542
  lucide-react/dist/esm/icons/pin.js:
77204
77543
  lucide-react/dist/esm/icons/plus.js: