@underverse-ui/underverse 0.2.67 → 0.2.69

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -13011,7 +13011,7 @@ var Table = import_react31.default.forwardRef(({ className, containerClassName,
13011
13011
  }
13012
13012
  ));
13013
13013
  Table.displayName = "Table";
13014
- var TableHeader = import_react31.default.forwardRef(({ className, children, filterRow, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("thead", { ref, className: cn("[&_tr]:border-b [&_tr]:border-border", "bg-muted/50", className), ...props, children: [
13014
+ var TableHeader = import_react31.default.forwardRef(({ className, children, filterRow, ...props }, ref) => /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("thead", { ref, className: cn("[&_tr]:border-b [&_tr]:border-border", "bg-muted", className), ...props, children: [
13015
13015
  children,
13016
13016
  filterRow
13017
13017
  ] }));
@@ -13080,6 +13080,8 @@ function DataTable({
13080
13080
  columnDividers = false,
13081
13081
  className,
13082
13082
  storageKey,
13083
+ stickyHeader = true,
13084
+ maxHeight = 500,
13083
13085
  labels
13084
13086
  }) {
13085
13087
  const t = useTranslations("Common");
@@ -13167,11 +13169,11 @@ function DataTable({
13167
13169
  const getStickyColumnClass = (col, isHeader = false) => {
13168
13170
  if (!col.fixed) return "";
13169
13171
  return cn(
13170
- "sticky z-10 bg-background",
13171
- col.fixed === "left" && "shadow-[2px_0_5px_-2px_rgba(0,0,0,0.1)]",
13172
- col.fixed === "right" && "shadow-[-2px_0_5px_-2px_rgba(0,0,0,0.1)]",
13173
- isHeader && "z-20"
13174
- // Header cần z-index cao hơn
13172
+ "sticky",
13173
+ col.fixed === "left" && "left-0 shadow-[2px_0_5px_-2px_rgba(0,0,0,0.15)]",
13174
+ col.fixed === "right" && "right-0 shadow-[-2px_0_5px_-2px_rgba(0,0,0,0.15)]",
13175
+ // Header fixed column cần z-index cao hơn thead (z-30) để không bị che
13176
+ isHeader ? "z-50 bg-muted!" : "z-10 bg-card!"
13175
13177
  );
13176
13178
  };
13177
13179
  const getStickyColumnStyle = (col) => {
@@ -13239,129 +13241,144 @@ function DataTable({
13239
13241
  }
13240
13242
  return null;
13241
13243
  };
13242
- const renderHeader = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableRow, { children: visibleColumns.map((col, colIdx) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13243
- TableHead,
13244
- {
13245
- style: { width: col.width, ...getStickyColumnStyle(col) },
13246
- className: cn(
13247
- // Use column-specific align if defined, otherwise use global headerAlign
13248
- (col.align === "right" || !col.align && headerAlign === "right") && "text-right",
13249
- (col.align === "center" || !col.align && headerAlign === "center") && "text-center",
13250
- columnDividers && colIdx > 0 && "border-l border-border/60",
13251
- getStickyColumnClass(col, true)
13252
- ),
13253
- children: (() => {
13254
- const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
13255
- const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
13256
- const titleContent = /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center gap-1 min-w-0 shrink", children: [
13257
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: "truncate font-medium text-sm", children: col.title }),
13258
- col.sortable && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13259
- "button",
13244
+ const renderHeader = /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableRow, { children: visibleColumns.map((col, colIdx) => {
13245
+ const prevCol = colIdx > 0 ? visibleColumns[colIdx - 1] : null;
13246
+ const isAfterFixedLeft = prevCol?.fixed === "left";
13247
+ const showBorderLeft = columnDividers && colIdx > 0 && !isAfterFixedLeft && !col.fixed;
13248
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13249
+ TableHead,
13250
+ {
13251
+ style: { width: col.width, ...getStickyColumnStyle(col) },
13252
+ className: cn(
13253
+ // Use column-specific align if defined, otherwise use global headerAlign
13254
+ (col.align === "right" || !col.align && headerAlign === "right") && "text-right",
13255
+ (col.align === "center" || !col.align && headerAlign === "center") && "text-center",
13256
+ showBorderLeft && "border-l border-border/60",
13257
+ getStickyColumnClass(col, true)
13258
+ ),
13259
+ children: (() => {
13260
+ const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
13261
+ const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
13262
+ const titleContent = /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
13263
+ "div",
13260
13264
  {
13261
13265
  className: cn(
13262
- "p-1 rounded-lg transition-all duration-200 hover:bg-accent",
13263
- sort?.key === col.key ? "opacity-100 bg-accent" : "opacity-60 hover:opacity-100"
13266
+ "flex items-center gap-1",
13267
+ // Cột fixed không cần shrink đã có width cố định
13268
+ !col.fixed && "min-w-0 shrink"
13264
13269
  ),
13265
- onClick: () => {
13266
- setCurPage(1);
13267
- setSort((s) => {
13268
- if (!s || s.key !== col.key) return { key: col.key, order: "asc" };
13269
- if (s.order === "asc") return { key: col.key, order: "desc" };
13270
- return null;
13271
- });
13272
- },
13273
- "aria-label": "Sort",
13274
- title: `Sort by ${String(col.title)}`,
13275
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
13276
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13277
- "path",
13278
- {
13279
- d: "M7 8l3-3 3 3",
13280
- stroke: "currentColor",
13281
- strokeWidth: "1.5",
13282
- strokeLinecap: "round",
13283
- strokeLinejoin: "round",
13284
- opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
13285
- }
13286
- ),
13287
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13288
- "path",
13270
+ children: [
13271
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("span", { className: cn("font-medium text-sm", !col.fixed && "truncate"), children: col.title }),
13272
+ col.sortable && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13273
+ "button",
13289
13274
  {
13290
- d: "M7 12l3 3 3-3",
13291
- stroke: "currentColor",
13292
- strokeWidth: "1.5",
13293
- strokeLinecap: "round",
13294
- strokeLinejoin: "round",
13295
- opacity: sort?.key === col.key && sort.order === "desc" ? 1 : 0.4
13275
+ className: cn(
13276
+ "p-1 rounded-lg transition-all duration-200 hover:bg-accent",
13277
+ sort?.key === col.key ? "opacity-100 bg-accent" : "opacity-60 hover:opacity-100"
13278
+ ),
13279
+ onClick: () => {
13280
+ setCurPage(1);
13281
+ setSort((s) => {
13282
+ if (!s || s.key !== col.key) return { key: col.key, order: "asc" };
13283
+ if (s.order === "asc") return { key: col.key, order: "desc" };
13284
+ return null;
13285
+ });
13286
+ },
13287
+ "aria-label": "Sort",
13288
+ title: `Sort by ${String(col.title)}`,
13289
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
13290
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13291
+ "path",
13292
+ {
13293
+ d: "M7 8l3-3 3 3",
13294
+ stroke: "currentColor",
13295
+ strokeWidth: "1.5",
13296
+ strokeLinecap: "round",
13297
+ strokeLinejoin: "round",
13298
+ opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
13299
+ }
13300
+ ),
13301
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13302
+ "path",
13303
+ {
13304
+ d: "M7 12l3 3 3-3",
13305
+ stroke: "currentColor",
13306
+ strokeWidth: "1.5",
13307
+ strokeLinecap: "round",
13308
+ strokeLinejoin: "round",
13309
+ opacity: sort?.key === col.key && sort.order === "desc" ? 1 : 0.4
13310
+ }
13311
+ )
13312
+ ] })
13296
13313
  }
13297
13314
  )
13298
- ] })
13315
+ ]
13299
13316
  }
13300
- )
13301
- ] });
13302
- const filterContent = col.filter && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13303
- Popover,
13304
- {
13305
- placement: isRightAlign ? "bottom-end" : "bottom-start",
13306
- trigger: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13307
- "button",
13308
- {
13309
- className: cn(
13310
- "p-1.5 rounded-lg hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
13311
- "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
13312
- filters[col.key] && "bg-accent text-foreground"
13313
- ),
13314
- "aria-label": "Filter",
13315
- title: "Filter",
13316
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react27.Filter, { className: "h-4 w-4" })
13317
- }
13318
- ),
13319
- children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "w-48 p-2 space-y-2", children: [
13320
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: [
13321
- "Filter ",
13322
- col.title
13323
- ] }),
13324
- renderFilterControl(col),
13325
- filters[col.key] && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13317
+ );
13318
+ const filterContent = col.filter && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13319
+ Popover,
13320
+ {
13321
+ placement: isRightAlign ? "bottom-end" : "bottom-start",
13322
+ trigger: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13326
13323
  "button",
13327
13324
  {
13328
- onClick: () => {
13329
- setCurPage(1);
13330
- setFilters((f) => {
13331
- const newFilters = { ...f };
13332
- delete newFilters[col.key];
13333
- return newFilters;
13334
- });
13335
- },
13336
- className: "text-xs text-destructive hover:underline",
13337
- children: t("clearFilter")
13325
+ className: cn(
13326
+ "p-1.5 rounded-lg hover:bg-accent text-muted-foreground hover:text-foreground transition-colors",
13327
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background",
13328
+ filters[col.key] && "bg-accent text-foreground"
13329
+ ),
13330
+ "aria-label": "Filter",
13331
+ title: "Filter",
13332
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(import_lucide_react27.Filter, { className: "h-4 w-4" })
13338
13333
  }
13339
- )
13340
- ] })
13341
- }
13342
- );
13343
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13344
- "div",
13345
- {
13346
- className: cn(
13347
- "flex items-center gap-2 select-none min-h-10",
13348
- isRightAlign && "justify-end",
13349
- isCenterAlign && "justify-center",
13350
- !isRightAlign && !isCenterAlign && "justify-start"
13351
- ),
13352
- children: isRightAlign ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
13353
- filterContent,
13354
- titleContent
13355
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
13356
- titleContent,
13357
- filterContent
13358
- ] })
13359
- }
13360
- );
13361
- })()
13362
- },
13363
- col.key
13364
- )) });
13334
+ ),
13335
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "w-48 p-2 space-y-2", children: [
13336
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "text-xs font-medium text-muted-foreground mb-2", children: [
13337
+ "Filter ",
13338
+ col.title
13339
+ ] }),
13340
+ renderFilterControl(col),
13341
+ filters[col.key] && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13342
+ "button",
13343
+ {
13344
+ onClick: () => {
13345
+ setCurPage(1);
13346
+ setFilters((f) => {
13347
+ const newFilters = { ...f };
13348
+ delete newFilters[col.key];
13349
+ return newFilters;
13350
+ });
13351
+ },
13352
+ className: "text-xs text-destructive hover:underline",
13353
+ children: t("clearFilter")
13354
+ }
13355
+ )
13356
+ ] })
13357
+ }
13358
+ );
13359
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13360
+ "div",
13361
+ {
13362
+ className: cn(
13363
+ "flex items-center gap-2 select-none min-h-10",
13364
+ isRightAlign && "justify-end",
13365
+ isCenterAlign && "justify-center",
13366
+ !isRightAlign && !isCenterAlign && "justify-start"
13367
+ ),
13368
+ children: isRightAlign ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
13369
+ filterContent,
13370
+ titleContent
13371
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
13372
+ titleContent,
13373
+ filterContent
13374
+ ] })
13375
+ }
13376
+ );
13377
+ })()
13378
+ },
13379
+ col.key
13380
+ );
13381
+ }) });
13365
13382
  const isServerMode = Boolean(onQueryChange);
13366
13383
  const processedData = import_react32.default.useMemo(() => {
13367
13384
  if (isServerMode) return data;
@@ -13466,69 +13483,91 @@ function DataTable({
13466
13483
  toolbar
13467
13484
  ] })
13468
13485
  ] }),
13469
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: cn("relative rounded-2xl md:rounded-3xl border border-border/50 overflow-hidden", loading2 && "opacity-60 pointer-events-none"), children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
13470
- Table,
13486
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13487
+ "div",
13471
13488
  {
13472
- containerClassName: "border-0 md:border-0 rounded-none md:rounded-none shadow-none bg-transparent",
13473
- className: "[&_thead]:sticky [&_thead]:top-0 [&_thead]:z-5 [&_thead]:bg-background [&_thead]:backdrop-blur-sm",
13474
- children: [
13475
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableHeader, { children: renderHeader }),
13476
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableBody, { children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableCell, { colSpan: visibleColumns.length, className: "text-center py-8", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
13477
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
13478
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
13479
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13480
- "path",
13481
- {
13482
- className: "opacity-75",
13483
- fill: "currentColor",
13484
- d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
13485
- }
13486
- )
13487
- ] }),
13488
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "text-sm", children: [
13489
- t("loading"),
13490
- "\u2026"
13491
- ] })
13492
- ] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: t("noData") }) }) : displayedData.map((row, idx) => {
13493
- const isLastRow = idx === displayedData.length - 1;
13494
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13495
- TableRow,
13496
- {
13497
- className: cn(densityRowClass, striped && idx % 2 === 0 && "bg-muted/50"),
13498
- style: {
13499
- // content-visibility: auto for rendering performance (skip off-screen rows)
13500
- contentVisibility: "auto",
13501
- containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
13502
- },
13503
- children: visibleColumns.map((col, colIdx) => {
13504
- const value = col.dataIndex ? row[col.dataIndex] : void 0;
13505
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13506
- TableCell,
13489
+ className: cn("relative rounded-2xl md:rounded-3xl border border-border/50", loading2 && "opacity-60 pointer-events-none"),
13490
+ style: stickyHeader ? {
13491
+ maxHeight: typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight,
13492
+ overflowY: "auto",
13493
+ overflowX: "auto"
13494
+ } : { overflowX: "auto" },
13495
+ children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
13496
+ Table,
13497
+ {
13498
+ containerClassName: cn("border-0 md:border-0 rounded-none md:rounded-none shadow-none bg-transparent", "overflow-visible"),
13499
+ className: cn(
13500
+ "table-fixed",
13501
+ stickyHeader && ["[&_thead]:sticky", "[&_thead]:top-0", "[&_thead]:z-20", "[&_thead]:shadow-[0_1px_3px_rgba(0,0,0,0.1)]"]
13502
+ ),
13503
+ children: [
13504
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableHeader, { children: renderHeader }),
13505
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableBody, { children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableCell, { colSpan: visibleColumns.length, className: "text-center py-8", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
13506
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
13507
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
13508
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13509
+ "path",
13507
13510
  {
13508
- style: getStickyColumnStyle(col),
13509
- className: cn(
13510
- cellPadding,
13511
- col.align === "right" && "text-right",
13512
- col.align === "center" && "text-center",
13513
- columnDividers && colIdx > 0 && "border-l border-border/60",
13514
- isLastRow && col === visibleColumns[0] && "rounded-bl-2xl md:rounded-bl-3xl",
13515
- isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-2xl md:rounded-br-3xl",
13516
- getStickyColumnClass(col),
13517
- // Giữ màu nền striped cho cột cố định
13518
- col.fixed && striped && idx % 2 === 0 && "bg-muted/50!"
13519
- ),
13520
- children: col.render ? col.render(value, row, idx) : String(value ?? "")
13511
+ className: "opacity-75",
13512
+ fill: "currentColor",
13513
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
13514
+ }
13515
+ )
13516
+ ] }),
13517
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("span", { className: "text-sm", children: [
13518
+ t("loading"),
13519
+ "\u2026"
13520
+ ] })
13521
+ ] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(TableCell, { colSpan: visibleColumns.length, className: "text-center py-6 text-muted-foreground", children: t("noData") }) }) : displayedData.map((row, idx) => {
13522
+ const isLastRow = idx === displayedData.length - 1;
13523
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13524
+ TableRow,
13525
+ {
13526
+ className: cn(densityRowClass),
13527
+ style: {
13528
+ // content-visibility: auto for rendering performance (skip off-screen rows)
13529
+ contentVisibility: "auto",
13530
+ containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
13521
13531
  },
13522
- col.key
13523
- );
13524
- })
13525
- },
13526
- getRowKey(row, idx)
13527
- );
13528
- }) })
13529
- ]
13532
+ children: visibleColumns.map((col, colIdx) => {
13533
+ const value = col.dataIndex ? row[col.dataIndex] : void 0;
13534
+ const isStripedRow = striped && idx % 2 === 0;
13535
+ const prevCol = colIdx > 0 ? visibleColumns[colIdx - 1] : null;
13536
+ const isAfterFixedLeft = prevCol?.fixed === "left";
13537
+ const showBorderLeft = columnDividers && colIdx > 0 && !isAfterFixedLeft && !col.fixed;
13538
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
13539
+ TableCell,
13540
+ {
13541
+ style: getStickyColumnStyle(col),
13542
+ className: cn(
13543
+ cellPadding,
13544
+ col.align === "right" && "text-right",
13545
+ col.align === "center" && "text-center",
13546
+ showBorderLeft && "border-l border-border/60",
13547
+ isLastRow && col === visibleColumns[0] && "rounded-bl-2xl md:rounded-bl-3xl",
13548
+ isLastRow && col === visibleColumns[visibleColumns.length - 1] && "rounded-br-2xl md:rounded-br-3xl",
13549
+ // Cột cố định cần solid background
13550
+ col.fixed ? cn(
13551
+ "sticky z-10",
13552
+ col.fixed === "left" && "left-0 shadow-[2px_0_5px_-2px_rgba(0,0,0,0.15)]",
13553
+ col.fixed === "right" && "right-0 shadow-[-2px_0_5px_-2px_rgba(0,0,0,0.15)]",
13554
+ isStripedRow ? "bg-muted!" : "bg-card!"
13555
+ ) : isStripedRow && "bg-muted/50"
13556
+ ),
13557
+ children: col.render ? col.render(value, row, idx) : String(value ?? "")
13558
+ },
13559
+ col.key
13560
+ );
13561
+ })
13562
+ },
13563
+ getRowKey(row, idx)
13564
+ );
13565
+ }) })
13566
+ ]
13567
+ }
13568
+ )
13530
13569
  }
13531
- ) }),
13570
+ ),
13532
13571
  totalItems > 0 && Math.ceil(totalItems / curPageSize) > 1 && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "flex items-center justify-between gap-2 px-1 pt-3 text-xs text-muted-foreground", children: [
13533
13572
  /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "tabular-nums", children: [
13534
13573
  (curPage - 1) * curPageSize + 1,