@underverse-ui/underverse 0.2.74 → 0.2.76
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 +403 -156
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -2
- package/dist/index.d.ts +11 -2
- package/dist/index.js +403 -156
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -594,7 +594,7 @@ var Card = ({
|
|
|
594
594
|
{
|
|
595
595
|
className: cn(
|
|
596
596
|
"rounded-2xl md:rounded-3xl bg-card text-card-foreground transition-[transform,box-shadow,border-color,background-color] duration-300 ease-soft",
|
|
597
|
-
"shadow-sm md:hover:shadow-md
|
|
597
|
+
"shadow-sm md:hover:shadow-md border border-border",
|
|
598
598
|
hoverable && "md:hover:-translate-y-0.5 md:hover:border-primary/15",
|
|
599
599
|
clickable && "cursor-pointer active:translate-y-px md:hover:bg-accent/5",
|
|
600
600
|
"backdrop-blur-sm",
|
|
@@ -13143,6 +13143,103 @@ function DataTablePagination({
|
|
|
13143
13143
|
] });
|
|
13144
13144
|
}
|
|
13145
13145
|
|
|
13146
|
+
// ../../components/ui/DataTable/utils/headers.ts
|
|
13147
|
+
function isLeafColumn(col) {
|
|
13148
|
+
return !col.children || col.children.length === 0;
|
|
13149
|
+
}
|
|
13150
|
+
function getLeafColumns(columns) {
|
|
13151
|
+
const leaves = [];
|
|
13152
|
+
function traverse(cols) {
|
|
13153
|
+
for (const col of cols) {
|
|
13154
|
+
if (isLeafColumn(col)) {
|
|
13155
|
+
leaves.push(col);
|
|
13156
|
+
} else if (col.children) {
|
|
13157
|
+
traverse(col.children);
|
|
13158
|
+
}
|
|
13159
|
+
}
|
|
13160
|
+
}
|
|
13161
|
+
traverse(columns);
|
|
13162
|
+
return leaves;
|
|
13163
|
+
}
|
|
13164
|
+
function getHeaderDepth(columns) {
|
|
13165
|
+
function getDepth(cols) {
|
|
13166
|
+
if (!cols || cols.length === 0) return 0;
|
|
13167
|
+
let maxDepth = 1;
|
|
13168
|
+
for (const col of cols) {
|
|
13169
|
+
if (col.children && col.children.length > 0) {
|
|
13170
|
+
maxDepth = Math.max(maxDepth, 1 + getDepth(col.children));
|
|
13171
|
+
}
|
|
13172
|
+
}
|
|
13173
|
+
return maxDepth;
|
|
13174
|
+
}
|
|
13175
|
+
return getDepth(columns);
|
|
13176
|
+
}
|
|
13177
|
+
function getColSpan(col) {
|
|
13178
|
+
if (col.colSpan !== void 0) return col.colSpan;
|
|
13179
|
+
if (isLeafColumn(col)) return 1;
|
|
13180
|
+
return col.children.reduce((sum, child) => sum + getColSpan(child), 0);
|
|
13181
|
+
}
|
|
13182
|
+
function getRowSpan(col, maxDepth, currentDepth) {
|
|
13183
|
+
if (col.rowSpan !== void 0) return col.rowSpan;
|
|
13184
|
+
if (isLeafColumn(col)) {
|
|
13185
|
+
return maxDepth - currentDepth + 1;
|
|
13186
|
+
}
|
|
13187
|
+
return 1;
|
|
13188
|
+
}
|
|
13189
|
+
function buildHeaderRows(columns) {
|
|
13190
|
+
const maxDepth = getHeaderDepth(columns);
|
|
13191
|
+
const rows = Array.from({ length: maxDepth }, () => []);
|
|
13192
|
+
function buildCell(col, rowIndex, colIndex) {
|
|
13193
|
+
const colSpan = getColSpan(col);
|
|
13194
|
+
const rowSpan = getRowSpan(col, maxDepth, rowIndex + 1);
|
|
13195
|
+
const isLeaf = isLeafColumn(col);
|
|
13196
|
+
rows[rowIndex].push({
|
|
13197
|
+
column: col,
|
|
13198
|
+
colSpan,
|
|
13199
|
+
rowSpan,
|
|
13200
|
+
isLeaf,
|
|
13201
|
+
rowIndex,
|
|
13202
|
+
colIndex
|
|
13203
|
+
});
|
|
13204
|
+
if (col.children && col.children.length > 0) {
|
|
13205
|
+
let childColIndex = colIndex;
|
|
13206
|
+
for (const child of col.children) {
|
|
13207
|
+
childColIndex = buildCell(child, rowIndex + 1, childColIndex);
|
|
13208
|
+
}
|
|
13209
|
+
}
|
|
13210
|
+
return colIndex + colSpan;
|
|
13211
|
+
}
|
|
13212
|
+
let currentColIndex = 0;
|
|
13213
|
+
for (const col of columns) {
|
|
13214
|
+
currentColIndex = buildCell(col, 0, currentColIndex);
|
|
13215
|
+
}
|
|
13216
|
+
return rows;
|
|
13217
|
+
}
|
|
13218
|
+
function filterVisibleColumns(columns, visibleKeys) {
|
|
13219
|
+
return columns.map((col) => {
|
|
13220
|
+
if (col.children) {
|
|
13221
|
+
const visibleChildren = filterVisibleColumns(col.children, visibleKeys);
|
|
13222
|
+
if (visibleChildren.length > 0) {
|
|
13223
|
+
return { ...col, children: visibleChildren };
|
|
13224
|
+
}
|
|
13225
|
+
return null;
|
|
13226
|
+
}
|
|
13227
|
+
return visibleKeys.has(col.key) ? col : null;
|
|
13228
|
+
}).filter((col) => col !== null);
|
|
13229
|
+
}
|
|
13230
|
+
function getLeafColumnsWithFixedInheritance(columns, inheritedFixed) {
|
|
13231
|
+
const leaves = [];
|
|
13232
|
+
for (const col of columns) {
|
|
13233
|
+
const effectiveFixed = col.fixed ?? inheritedFixed;
|
|
13234
|
+
if (isLeafColumn(col)) {
|
|
13235
|
+
leaves.push({ ...col, fixed: effectiveFixed });
|
|
13236
|
+
} else if (col.children) {
|
|
13237
|
+
leaves.push(...getLeafColumnsWithFixedInheritance(col.children, effectiveFixed));
|
|
13238
|
+
}
|
|
13239
|
+
}
|
|
13240
|
+
return leaves;
|
|
13241
|
+
}
|
|
13242
|
+
|
|
13146
13243
|
// ../../components/ui/DataTable/components/Toolbar.tsx
|
|
13147
13244
|
var import_jsx_runtime58 = require("react/jsx-runtime");
|
|
13148
13245
|
function DataTableToolbar({
|
|
@@ -13177,36 +13274,39 @@ function DataTableToolbar({
|
|
|
13177
13274
|
]
|
|
13178
13275
|
}
|
|
13179
13276
|
),
|
|
13180
|
-
enableColumnVisibilityToggle &&
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13277
|
+
enableColumnVisibilityToggle && (() => {
|
|
13278
|
+
const leafCols = getLeafColumns(columns);
|
|
13279
|
+
return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
13280
|
+
DropdownMenu_default,
|
|
13281
|
+
{
|
|
13282
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
|
|
13283
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
13284
|
+
"path",
|
|
13285
|
+
{
|
|
13286
|
+
strokeLinecap: "round",
|
|
13287
|
+
strokeLinejoin: "round",
|
|
13288
|
+
strokeWidth: 2,
|
|
13289
|
+
d: "M9 17V7m0 10a2 2 0 01-2 2H5a2 2 0 01-2-2V7a2 2 0 012-2h2a2 2 0 012 2m0 10a2 2 0 002 2h2a2 2 0 002-2M9 7a2 2 0 012-2h2a2 2 0 012 2m0 10V7m0 10a2 2 0 002 2h2a2 2 0 002-2V7a2 2 0 00-2-2h-2a2 2 0 00-2 2"
|
|
13290
|
+
}
|
|
13291
|
+
) }),
|
|
13292
|
+
labels?.columns || t("columns")
|
|
13293
|
+
] }),
|
|
13294
|
+
children: leafCols.map((c) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
13295
|
+
DropdownMenuItem,
|
|
13186
13296
|
{
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
] }),
|
|
13195
|
-
children: columns.map((c) => /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(
|
|
13196
|
-
DropdownMenuItem,
|
|
13197
|
-
{
|
|
13198
|
-
onClick: () => {
|
|
13199
|
-
setVisibleCols((prev) => prev.includes(c.key) ? prev.filter((k) => k !== c.key) : [...prev, c.key]);
|
|
13297
|
+
onClick: () => {
|
|
13298
|
+
setVisibleCols((prev) => prev.includes(c.key) ? prev.filter((k) => k !== c.key) : [...prev, c.key]);
|
|
13299
|
+
},
|
|
13300
|
+
children: [
|
|
13301
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("input", { type: "checkbox", className: "mr-2 rounded-md border-border", readOnly: true, checked: visibleCols.includes(c.key) }),
|
|
13302
|
+
/* @__PURE__ */ (0, import_jsx_runtime58.jsx)("span", { className: "truncate", children: c.title })
|
|
13303
|
+
]
|
|
13200
13304
|
},
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13205
|
-
|
|
13206
|
-
c.key
|
|
13207
|
-
))
|
|
13208
|
-
}
|
|
13209
|
-
),
|
|
13305
|
+
c.key
|
|
13306
|
+
))
|
|
13307
|
+
}
|
|
13308
|
+
);
|
|
13309
|
+
})(),
|
|
13210
13310
|
enableHeaderAlignToggle && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
|
|
13211
13311
|
DropdownMenu_default,
|
|
13212
13312
|
{
|
|
@@ -13281,32 +13381,40 @@ var import_react34 = __toESM(require("react"), 1);
|
|
|
13281
13381
|
// ../../components/ui/DataTable/utils/columns.ts
|
|
13282
13382
|
function getColumnWidth(col, fallback = 150) {
|
|
13283
13383
|
if (typeof col.width === "number") return col.width;
|
|
13284
|
-
|
|
13285
|
-
|
|
13286
|
-
|
|
13384
|
+
if (col.width) {
|
|
13385
|
+
const raw = String(col.width);
|
|
13386
|
+
const parsed = parseInt(raw, 10);
|
|
13387
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
13388
|
+
}
|
|
13389
|
+
if (col.children && col.children.length > 0) {
|
|
13390
|
+
return col.children.reduce((sum, child) => sum + getColumnWidth(child, fallback), 0);
|
|
13391
|
+
}
|
|
13392
|
+
return fallback;
|
|
13287
13393
|
}
|
|
13288
13394
|
|
|
13289
13395
|
// ../../components/ui/DataTable/hooks/useStickyColumns.ts
|
|
13290
|
-
function useStickyColumns(
|
|
13396
|
+
function useStickyColumns(columns, visibleKeys) {
|
|
13397
|
+
const visibleColumns = import_react34.default.useMemo(() => filterVisibleColumns(columns, visibleKeys), [columns, visibleKeys]);
|
|
13398
|
+
const leafColumns = import_react34.default.useMemo(() => getLeafColumnsWithFixedInheritance(visibleColumns), [visibleColumns]);
|
|
13291
13399
|
const stickyPositions = import_react34.default.useMemo(() => {
|
|
13292
13400
|
const positions = {};
|
|
13293
13401
|
let leftOffset = 0;
|
|
13294
|
-
for (const col of
|
|
13402
|
+
for (const col of leafColumns) {
|
|
13295
13403
|
if (col.fixed === "left") {
|
|
13296
13404
|
positions[col.key] = { left: leftOffset };
|
|
13297
13405
|
leftOffset += getColumnWidth(col);
|
|
13298
13406
|
}
|
|
13299
13407
|
}
|
|
13300
13408
|
let rightOffset = 0;
|
|
13301
|
-
for (let i =
|
|
13302
|
-
const col =
|
|
13409
|
+
for (let i = leafColumns.length - 1; i >= 0; i--) {
|
|
13410
|
+
const col = leafColumns[i];
|
|
13303
13411
|
if (col.fixed === "right") {
|
|
13304
13412
|
positions[col.key] = { right: rightOffset };
|
|
13305
13413
|
rightOffset += getColumnWidth(col);
|
|
13306
13414
|
}
|
|
13307
13415
|
}
|
|
13308
13416
|
return positions;
|
|
13309
|
-
}, [
|
|
13417
|
+
}, [leafColumns]);
|
|
13310
13418
|
const getStickyColumnStyle = import_react34.default.useCallback(
|
|
13311
13419
|
(col) => {
|
|
13312
13420
|
if (!col.fixed) return {};
|
|
@@ -13336,7 +13444,109 @@ function useStickyColumns(visibleColumns) {
|
|
|
13336
13444
|
isStripedRow ? "bg-muted!" : "bg-card!"
|
|
13337
13445
|
);
|
|
13338
13446
|
}, []);
|
|
13339
|
-
|
|
13447
|
+
const getStickyHeaderCellStyle = import_react34.default.useCallback(
|
|
13448
|
+
(headerCell) => {
|
|
13449
|
+
const col = headerCell.column;
|
|
13450
|
+
if (headerCell.isLeaf) {
|
|
13451
|
+
return getStickyColumnStyle(col);
|
|
13452
|
+
}
|
|
13453
|
+
const descendants = getLeafColumns([col]);
|
|
13454
|
+
const stickyDescendants = descendants.filter((d) => d.fixed);
|
|
13455
|
+
if (stickyDescendants.length === 0) return {};
|
|
13456
|
+
const firstSticky = stickyDescendants[0];
|
|
13457
|
+
const lastSticky = stickyDescendants[stickyDescendants.length - 1];
|
|
13458
|
+
if (firstSticky.fixed === "left") {
|
|
13459
|
+
const pos = stickyPositions[firstSticky.key];
|
|
13460
|
+
return pos?.left !== void 0 ? { left: pos.left } : {};
|
|
13461
|
+
}
|
|
13462
|
+
if (lastSticky.fixed === "right") {
|
|
13463
|
+
const pos = stickyPositions[lastSticky.key];
|
|
13464
|
+
return pos?.right !== void 0 ? { right: pos.right } : {};
|
|
13465
|
+
}
|
|
13466
|
+
return {};
|
|
13467
|
+
},
|
|
13468
|
+
[stickyPositions, getStickyColumnStyle]
|
|
13469
|
+
);
|
|
13470
|
+
return {
|
|
13471
|
+
getStickyColumnStyle,
|
|
13472
|
+
getStickyHeaderClass,
|
|
13473
|
+
getStickyCellClass,
|
|
13474
|
+
getStickyHeaderCellStyle
|
|
13475
|
+
};
|
|
13476
|
+
}
|
|
13477
|
+
|
|
13478
|
+
// ../../components/ui/DataTable/utils/validation.ts
|
|
13479
|
+
function validateColumns(columns) {
|
|
13480
|
+
const warnings = [];
|
|
13481
|
+
const keys = /* @__PURE__ */ new Set();
|
|
13482
|
+
function validate(cols, path = "") {
|
|
13483
|
+
for (const col of cols) {
|
|
13484
|
+
const fullPath = path ? `${path}.${col.key}` : col.key;
|
|
13485
|
+
if (keys.has(col.key)) {
|
|
13486
|
+
warnings.push(`Duplicate key "${col.key}" at ${fullPath}`);
|
|
13487
|
+
}
|
|
13488
|
+
keys.add(col.key);
|
|
13489
|
+
const isGroup = col.children && col.children.length > 0;
|
|
13490
|
+
if (isGroup) {
|
|
13491
|
+
if (col.dataIndex) {
|
|
13492
|
+
warnings.push(`Group column "${fullPath}" has dataIndex (will be ignored)`);
|
|
13493
|
+
}
|
|
13494
|
+
if (col.sortable) {
|
|
13495
|
+
warnings.push(`Group column "${fullPath}" has sortable (will be ignored)`);
|
|
13496
|
+
}
|
|
13497
|
+
if (col.filter) {
|
|
13498
|
+
warnings.push(`Group column "${fullPath}" has filter (will be ignored)`);
|
|
13499
|
+
}
|
|
13500
|
+
if (col.render) {
|
|
13501
|
+
warnings.push(`Group column "${fullPath}" has render function (will be ignored)`);
|
|
13502
|
+
}
|
|
13503
|
+
if (col.colSpan !== void 0) {
|
|
13504
|
+
const actualColSpan = getColSpan(col);
|
|
13505
|
+
if (col.colSpan !== actualColSpan) {
|
|
13506
|
+
warnings.push(
|
|
13507
|
+
`Column "${fullPath}" has colSpan=${col.colSpan} but structure suggests ${actualColSpan} (based on ${col.children.length} children)`
|
|
13508
|
+
);
|
|
13509
|
+
}
|
|
13510
|
+
}
|
|
13511
|
+
if (col.fixed) {
|
|
13512
|
+
const conflictingChildren = col.children.filter((c) => c.fixed && c.fixed !== col.fixed);
|
|
13513
|
+
if (conflictingChildren.length > 0) {
|
|
13514
|
+
warnings.push(
|
|
13515
|
+
`Group column "${fullPath}" has fixed="${col.fixed}" but children have different fixed values: ${conflictingChildren.map((c) => c.key).join(", ")}`
|
|
13516
|
+
);
|
|
13517
|
+
}
|
|
13518
|
+
}
|
|
13519
|
+
validate(col.children, fullPath);
|
|
13520
|
+
} else {
|
|
13521
|
+
if (col.children !== void 0) {
|
|
13522
|
+
warnings.push(`Leaf column "${fullPath}" has children property (should be omitted for leaf columns)`);
|
|
13523
|
+
}
|
|
13524
|
+
}
|
|
13525
|
+
}
|
|
13526
|
+
}
|
|
13527
|
+
validate(columns);
|
|
13528
|
+
const depth = getHeaderDepth(columns);
|
|
13529
|
+
if (depth > 4) {
|
|
13530
|
+
warnings.push(`Header depth is ${depth} rows. Consider simplifying - too many header rows may impact user experience.`);
|
|
13531
|
+
}
|
|
13532
|
+
function checkMixedSticky(cols, parentPath = "") {
|
|
13533
|
+
for (const col of cols) {
|
|
13534
|
+
if (col.children && col.children.length > 0) {
|
|
13535
|
+
const childrenFixed = col.children.map((c) => c.fixed);
|
|
13536
|
+
const hasStickyChild = childrenFixed.some((f) => f !== void 0);
|
|
13537
|
+
const hasNonStickyChild = childrenFixed.some((f) => f === void 0);
|
|
13538
|
+
if (hasStickyChild && hasNonStickyChild) {
|
|
13539
|
+
const fullPath = parentPath ? `${parentPath}.${col.key}` : col.key;
|
|
13540
|
+
warnings.push(
|
|
13541
|
+
`Group column "${fullPath}" has mixed sticky children (some fixed, some not). This may cause visual separation when scrolling.`
|
|
13542
|
+
);
|
|
13543
|
+
}
|
|
13544
|
+
checkMixedSticky(col.children, parentPath ? `${parentPath}.${col.key}` : col.key);
|
|
13545
|
+
}
|
|
13546
|
+
}
|
|
13547
|
+
}
|
|
13548
|
+
checkMixedSticky(columns);
|
|
13549
|
+
return warnings;
|
|
13340
13550
|
}
|
|
13341
13551
|
|
|
13342
13552
|
// ../../components/ui/DataTable/DataTable.tsx
|
|
@@ -13372,6 +13582,12 @@ function DataTable({
|
|
|
13372
13582
|
const [density, setDensity] = import_react35.default.useState("normal");
|
|
13373
13583
|
const [curPage, setCurPage] = import_react35.default.useState(page);
|
|
13374
13584
|
const { curPageSize, setCurPageSize } = usePageSizeStorage({ pageSize, storageKey });
|
|
13585
|
+
import_react35.default.useEffect(() => {
|
|
13586
|
+
if (process.env.NODE_ENV === "development") {
|
|
13587
|
+
const warnings = validateColumns(columns);
|
|
13588
|
+
warnings.forEach((w) => console.warn(`[DataTable] ${w}`));
|
|
13589
|
+
}
|
|
13590
|
+
}, [columns]);
|
|
13375
13591
|
import_react35.default.useEffect(() => {
|
|
13376
13592
|
const newColKeys = columns.filter((c) => c.visible !== false).map((c) => c.key);
|
|
13377
13593
|
setVisibleCols((prev) => {
|
|
@@ -13396,11 +13612,19 @@ function DataTable({
|
|
|
13396
13612
|
const densityRowClass = density === "compact" ? "h-9" : density === "comfortable" ? "h-14" : "h-12";
|
|
13397
13613
|
const cellPadding = density === "compact" ? "py-1.5 px-3" : density === "comfortable" ? "py-3 px-4" : "py-2.5 px-4";
|
|
13398
13614
|
const visibleColsSet = import_react35.default.useMemo(() => new Set(visibleCols), [visibleCols]);
|
|
13399
|
-
const visibleColumns =
|
|
13400
|
-
|
|
13401
|
-
|
|
13615
|
+
const visibleColumns = import_react35.default.useMemo(() => {
|
|
13616
|
+
return filterVisibleColumns(columns, visibleColsSet);
|
|
13617
|
+
}, [columns, visibleColsSet]);
|
|
13618
|
+
const leafColumns = import_react35.default.useMemo(() => {
|
|
13619
|
+
return getLeafColumns(visibleColumns);
|
|
13402
13620
|
}, [visibleColumns]);
|
|
13403
|
-
const
|
|
13621
|
+
const totalColumnsWidth = import_react35.default.useMemo(() => {
|
|
13622
|
+
return leafColumns.reduce((sum, col) => sum + getColumnWidth(col), 0);
|
|
13623
|
+
}, [leafColumns]);
|
|
13624
|
+
const { getStickyCellClass, getStickyColumnStyle, getStickyHeaderClass, getStickyHeaderCellStyle } = useStickyColumns(
|
|
13625
|
+
columns,
|
|
13626
|
+
visibleColsSet
|
|
13627
|
+
);
|
|
13404
13628
|
const getRowKey = (row, idx) => {
|
|
13405
13629
|
if (!rowKey) return String(idx);
|
|
13406
13630
|
if (typeof rowKey === "function") return String(rowKey(row));
|
|
@@ -13456,127 +13680,150 @@ function DataTable({
|
|
|
13456
13680
|
}
|
|
13457
13681
|
return null;
|
|
13458
13682
|
};
|
|
13459
|
-
const
|
|
13460
|
-
|
|
13683
|
+
const headerRows = import_react35.default.useMemo(() => buildHeaderRows(visibleColumns), [visibleColumns]);
|
|
13684
|
+
const renderHeaderContent = (col, isLeaf) => {
|
|
13685
|
+
if (!isLeaf) {
|
|
13686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13687
|
+
"div",
|
|
13688
|
+
{
|
|
13689
|
+
className: cn(
|
|
13690
|
+
"flex items-center gap-1 min-h-10",
|
|
13691
|
+
col.align === "right" && "justify-end",
|
|
13692
|
+
col.align === "center" && "justify-center",
|
|
13693
|
+
!col.align && "justify-start"
|
|
13694
|
+
),
|
|
13695
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "font-medium text-sm whitespace-nowrap", children: col.title })
|
|
13696
|
+
}
|
|
13697
|
+
);
|
|
13698
|
+
}
|
|
13699
|
+
const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
|
|
13700
|
+
const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
|
|
13701
|
+
const titleContent = /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex items-center gap-1", children: [
|
|
13702
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: "font-medium text-sm whitespace-nowrap", children: col.title }),
|
|
13703
|
+
col.sortable && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13704
|
+
"button",
|
|
13705
|
+
{
|
|
13706
|
+
className: cn(
|
|
13707
|
+
"p-1 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13708
|
+
sort?.key === col.key ? "opacity-100 bg-accent" : "opacity-60 hover:opacity-100"
|
|
13709
|
+
),
|
|
13710
|
+
onClick: () => {
|
|
13711
|
+
setCurPage(1);
|
|
13712
|
+
setSort((s) => {
|
|
13713
|
+
if (!s || s.key !== col.key) return { key: col.key, order: "asc" };
|
|
13714
|
+
if (s.order === "asc") return { key: col.key, order: "desc" };
|
|
13715
|
+
return null;
|
|
13716
|
+
});
|
|
13717
|
+
},
|
|
13718
|
+
"aria-label": "Sort",
|
|
13719
|
+
title: `Sort by ${String(col.title)}`,
|
|
13720
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
|
|
13721
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13722
|
+
"path",
|
|
13723
|
+
{
|
|
13724
|
+
d: "M7 8l3-3 3 3",
|
|
13725
|
+
stroke: "currentColor",
|
|
13726
|
+
strokeWidth: "1.5",
|
|
13727
|
+
strokeLinecap: "round",
|
|
13728
|
+
strokeLinejoin: "round",
|
|
13729
|
+
opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
|
|
13730
|
+
}
|
|
13731
|
+
),
|
|
13732
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13733
|
+
"path",
|
|
13734
|
+
{
|
|
13735
|
+
d: "M7 12l3 3 3-3",
|
|
13736
|
+
stroke: "currentColor",
|
|
13737
|
+
strokeWidth: "1.5",
|
|
13738
|
+
strokeLinecap: "round",
|
|
13739
|
+
strokeLinejoin: "round",
|
|
13740
|
+
opacity: sort?.key === col.key && sort.order === "desc" ? 1 : 0.4
|
|
13741
|
+
}
|
|
13742
|
+
)
|
|
13743
|
+
] })
|
|
13744
|
+
}
|
|
13745
|
+
)
|
|
13746
|
+
] });
|
|
13747
|
+
const filterContent = col.filter ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13748
|
+
Popover,
|
|
13749
|
+
{
|
|
13750
|
+
placement: "bottom-start",
|
|
13751
|
+
trigger: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13752
|
+
"button",
|
|
13753
|
+
{
|
|
13754
|
+
className: cn(
|
|
13755
|
+
"p-1.5 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13756
|
+
filters[col.key] ? "bg-accent text-primary" : "text-muted-foreground"
|
|
13757
|
+
),
|
|
13758
|
+
"aria-label": "Filter",
|
|
13759
|
+
title: `Filter by ${String(col.title)}`,
|
|
13760
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_lucide_react27.Filter, { className: "w-4 h-4" })
|
|
13761
|
+
}
|
|
13762
|
+
),
|
|
13763
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "p-3 w-64 space-y-3", children: [
|
|
13764
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
13765
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "text-sm font-medium", children: col.title }),
|
|
13766
|
+
filters[col.key] !== void 0 && filters[col.key] !== null && filters[col.key] !== "" && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13767
|
+
"button",
|
|
13768
|
+
{
|
|
13769
|
+
onClick: () => {
|
|
13770
|
+
setCurPage(1);
|
|
13771
|
+
setFilters((f) => ({ ...f, [col.key]: void 0 }));
|
|
13772
|
+
},
|
|
13773
|
+
className: "text-xs text-destructive hover:underline",
|
|
13774
|
+
children: t("clearFilter")
|
|
13775
|
+
}
|
|
13776
|
+
)
|
|
13777
|
+
] }),
|
|
13778
|
+
renderFilterControl(col)
|
|
13779
|
+
] })
|
|
13780
|
+
}
|
|
13781
|
+
) : null;
|
|
13782
|
+
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13783
|
+
"div",
|
|
13784
|
+
{
|
|
13785
|
+
className: cn(
|
|
13786
|
+
"flex items-center gap-2 select-none min-h-10",
|
|
13787
|
+
isRightAlign && "justify-end",
|
|
13788
|
+
isCenterAlign && "justify-center",
|
|
13789
|
+
!isRightAlign && !isCenterAlign && "justify-start"
|
|
13790
|
+
),
|
|
13791
|
+
children: isRightAlign ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
|
|
13792
|
+
filterContent,
|
|
13793
|
+
titleContent
|
|
13794
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
|
|
13795
|
+
titleContent,
|
|
13796
|
+
filterContent
|
|
13797
|
+
] })
|
|
13798
|
+
}
|
|
13799
|
+
);
|
|
13800
|
+
};
|
|
13801
|
+
const renderHeader = /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_jsx_runtime59.Fragment, { children: headerRows.map((row, rowIndex) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableRow, { children: row.map((headerCell, cellIndex) => {
|
|
13802
|
+
const { column: col, colSpan, rowSpan, isLeaf } = headerCell;
|
|
13803
|
+
const prevCell = cellIndex > 0 ? row[cellIndex - 1] : null;
|
|
13804
|
+
const prevCol = prevCell?.column;
|
|
13461
13805
|
const isAfterFixedLeft = prevCol?.fixed === "left";
|
|
13462
|
-
const showBorderLeft = columnDividers &&
|
|
13806
|
+
const showBorderLeft = columnDividers && cellIndex > 0 && !isAfterFixedLeft && !col.fixed;
|
|
13463
13807
|
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13464
13808
|
TableHead,
|
|
13465
13809
|
{
|
|
13466
|
-
|
|
13810
|
+
colSpan,
|
|
13811
|
+
rowSpan,
|
|
13812
|
+
style: {
|
|
13813
|
+
width: col.width,
|
|
13814
|
+
...getStickyHeaderCellStyle(headerCell)
|
|
13815
|
+
},
|
|
13467
13816
|
className: cn(
|
|
13468
13817
|
(col.align === "right" || !col.align && headerAlign === "right") && "text-right",
|
|
13469
13818
|
(col.align === "center" || !col.align && headerAlign === "center") && "text-center",
|
|
13470
13819
|
showBorderLeft && "border-l border-border/60",
|
|
13471
13820
|
getStickyHeaderClass(col)
|
|
13472
13821
|
),
|
|
13473
|
-
children: (
|
|
13474
|
-
const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
|
|
13475
|
-
const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
|
|
13476
|
-
const titleContent = /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: cn("flex items-center gap-1", !col.fixed && "min-w-0 shrink"), children: [
|
|
13477
|
-
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("span", { className: cn("font-medium text-sm", !col.fixed && "truncate"), children: col.title }),
|
|
13478
|
-
col.sortable && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13479
|
-
"button",
|
|
13480
|
-
{
|
|
13481
|
-
className: cn(
|
|
13482
|
-
"p-1 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13483
|
-
sort?.key === col.key ? "opacity-100 bg-accent" : "opacity-60 hover:opacity-100"
|
|
13484
|
-
),
|
|
13485
|
-
onClick: () => {
|
|
13486
|
-
setCurPage(1);
|
|
13487
|
-
setSort((s) => {
|
|
13488
|
-
if (!s || s.key !== col.key) return { key: col.key, order: "asc" };
|
|
13489
|
-
if (s.order === "asc") return { key: col.key, order: "desc" };
|
|
13490
|
-
return null;
|
|
13491
|
-
});
|
|
13492
|
-
},
|
|
13493
|
-
"aria-label": "Sort",
|
|
13494
|
-
title: `Sort by ${String(col.title)}`,
|
|
13495
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
|
|
13496
|
-
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13497
|
-
"path",
|
|
13498
|
-
{
|
|
13499
|
-
d: "M7 8l3-3 3 3",
|
|
13500
|
-
stroke: "currentColor",
|
|
13501
|
-
strokeWidth: "1.5",
|
|
13502
|
-
strokeLinecap: "round",
|
|
13503
|
-
strokeLinejoin: "round",
|
|
13504
|
-
opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
|
|
13505
|
-
}
|
|
13506
|
-
),
|
|
13507
|
-
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13508
|
-
"path",
|
|
13509
|
-
{
|
|
13510
|
-
d: "M7 12l3 3 3-3",
|
|
13511
|
-
stroke: "currentColor",
|
|
13512
|
-
strokeWidth: "1.5",
|
|
13513
|
-
strokeLinecap: "round",
|
|
13514
|
-
strokeLinejoin: "round",
|
|
13515
|
-
opacity: sort?.key === col.key && sort.order === "desc" ? 1 : 0.4
|
|
13516
|
-
}
|
|
13517
|
-
)
|
|
13518
|
-
] })
|
|
13519
|
-
}
|
|
13520
|
-
)
|
|
13521
|
-
] });
|
|
13522
|
-
const filterContent = col.filter ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13523
|
-
Popover,
|
|
13524
|
-
{
|
|
13525
|
-
placement: "bottom-start",
|
|
13526
|
-
trigger: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13527
|
-
"button",
|
|
13528
|
-
{
|
|
13529
|
-
className: cn(
|
|
13530
|
-
"p-1.5 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13531
|
-
filters[col.key] ? "bg-accent text-primary" : "text-muted-foreground"
|
|
13532
|
-
),
|
|
13533
|
-
"aria-label": "Filter",
|
|
13534
|
-
title: `Filter by ${String(col.title)}`,
|
|
13535
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(import_lucide_react27.Filter, { className: "w-4 h-4" })
|
|
13536
|
-
}
|
|
13537
|
-
),
|
|
13538
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "p-3 w-64 space-y-3", children: [
|
|
13539
|
-
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex items-center justify-between", children: [
|
|
13540
|
-
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("div", { className: "text-sm font-medium", children: col.title }),
|
|
13541
|
-
filters[col.key] !== void 0 && filters[col.key] !== null && filters[col.key] !== "" && /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13542
|
-
"button",
|
|
13543
|
-
{
|
|
13544
|
-
onClick: () => {
|
|
13545
|
-
setCurPage(1);
|
|
13546
|
-
setFilters((f) => ({ ...f, [col.key]: void 0 }));
|
|
13547
|
-
},
|
|
13548
|
-
className: "text-xs text-destructive hover:underline",
|
|
13549
|
-
children: t("clearFilter")
|
|
13550
|
-
}
|
|
13551
|
-
)
|
|
13552
|
-
] }),
|
|
13553
|
-
renderFilterControl(col)
|
|
13554
|
-
] })
|
|
13555
|
-
}
|
|
13556
|
-
) : null;
|
|
13557
|
-
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13558
|
-
"div",
|
|
13559
|
-
{
|
|
13560
|
-
className: cn(
|
|
13561
|
-
"flex items-center gap-2 select-none min-h-10",
|
|
13562
|
-
isRightAlign && "justify-end",
|
|
13563
|
-
isCenterAlign && "justify-center",
|
|
13564
|
-
!isRightAlign && !isCenterAlign && "justify-start"
|
|
13565
|
-
),
|
|
13566
|
-
children: isRightAlign ? /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
|
|
13567
|
-
filterContent,
|
|
13568
|
-
titleContent
|
|
13569
|
-
] }) : /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)(import_jsx_runtime59.Fragment, { children: [
|
|
13570
|
-
titleContent,
|
|
13571
|
-
filterContent
|
|
13572
|
-
] })
|
|
13573
|
-
}
|
|
13574
|
-
);
|
|
13575
|
-
})()
|
|
13822
|
+
children: renderHeaderContent(col, isLeaf)
|
|
13576
13823
|
},
|
|
13577
13824
|
col.key
|
|
13578
13825
|
);
|
|
13579
|
-
}) });
|
|
13826
|
+
}) }, `header-row-${rowIndex}`)) });
|
|
13580
13827
|
const processedData = import_react35.default.useMemo(() => {
|
|
13581
13828
|
if (isServerMode) return data;
|
|
13582
13829
|
let result = [...data];
|
|
@@ -13652,7 +13899,7 @@ function DataTable({
|
|
|
13652
13899
|
style: { minWidth: totalColumnsWidth > 0 ? `${totalColumnsWidth}px` : void 0 },
|
|
13653
13900
|
children: [
|
|
13654
13901
|
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableHeader, { children: renderHeader }),
|
|
13655
|
-
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableBody, { children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableCell, { colSpan:
|
|
13902
|
+
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableBody, { children: loading2 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableCell, { colSpan: leafColumns.length, className: "text-center py-8", children: /* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
|
|
13656
13903
|
/* @__PURE__ */ (0, import_jsx_runtime59.jsxs)("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
|
|
13657
13904
|
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
13658
13905
|
/* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
@@ -13668,7 +13915,7 @@ function DataTable({
|
|
|
13668
13915
|
t("loading"),
|
|
13669
13916
|
"\u2026"
|
|
13670
13917
|
] })
|
|
13671
|
-
] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableCell, { colSpan:
|
|
13918
|
+
] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableRow, { children: /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(TableCell, { colSpan: leafColumns.length, className: "text-center py-6 text-muted-foreground", children: t("noData") }) }) : displayedData.map((row, idx) => {
|
|
13672
13919
|
const isLastRow = idx === displayedData.length - 1;
|
|
13673
13920
|
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
13674
13921
|
TableRow,
|
|
@@ -13678,10 +13925,10 @@ function DataTable({
|
|
|
13678
13925
|
contentVisibility: "auto",
|
|
13679
13926
|
containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
|
|
13680
13927
|
},
|
|
13681
|
-
children:
|
|
13928
|
+
children: leafColumns.map((col, colIdx) => {
|
|
13682
13929
|
const value = col.dataIndex ? row[col.dataIndex] : void 0;
|
|
13683
13930
|
const isStripedRow = striped && idx % 2 === 0;
|
|
13684
|
-
const prevCol = colIdx > 0 ?
|
|
13931
|
+
const prevCol = colIdx > 0 ? leafColumns[colIdx - 1] : null;
|
|
13685
13932
|
const isAfterFixedLeft = prevCol?.fixed === "left";
|
|
13686
13933
|
const showBorderLeft = columnDividers && colIdx > 0 && !isAfterFixedLeft && !col.fixed;
|
|
13687
13934
|
return /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
|
|
@@ -13693,8 +13940,8 @@ function DataTable({
|
|
|
13693
13940
|
col.align === "right" && "text-right",
|
|
13694
13941
|
col.align === "center" && "text-center",
|
|
13695
13942
|
showBorderLeft && "border-l border-border/60",
|
|
13696
|
-
isLastRow && col ===
|
|
13697
|
-
isLastRow && col ===
|
|
13943
|
+
isLastRow && col === leafColumns[0] && "rounded-bl-2xl md:rounded-bl-3xl",
|
|
13944
|
+
isLastRow && col === leafColumns[leafColumns.length - 1] && "rounded-br-2xl md:rounded-br-3xl",
|
|
13698
13945
|
getStickyCellClass(col, isStripedRow),
|
|
13699
13946
|
!col.fixed && isStripedRow && "bg-muted/50"
|
|
13700
13947
|
),
|