@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.js
CHANGED
|
@@ -421,7 +421,7 @@ var Card = ({
|
|
|
421
421
|
{
|
|
422
422
|
className: cn(
|
|
423
423
|
"rounded-2xl md:rounded-3xl bg-card text-card-foreground transition-[transform,box-shadow,border-color,background-color] duration-300 ease-soft",
|
|
424
|
-
"shadow-sm md:hover:shadow-md
|
|
424
|
+
"shadow-sm md:hover:shadow-md border border-border",
|
|
425
425
|
hoverable && "md:hover:-translate-y-0.5 md:hover:border-primary/15",
|
|
426
426
|
clickable && "cursor-pointer active:translate-y-px md:hover:bg-accent/5",
|
|
427
427
|
"backdrop-blur-sm",
|
|
@@ -12970,6 +12970,103 @@ function DataTablePagination({
|
|
|
12970
12970
|
] });
|
|
12971
12971
|
}
|
|
12972
12972
|
|
|
12973
|
+
// ../../components/ui/DataTable/utils/headers.ts
|
|
12974
|
+
function isLeafColumn(col) {
|
|
12975
|
+
return !col.children || col.children.length === 0;
|
|
12976
|
+
}
|
|
12977
|
+
function getLeafColumns(columns) {
|
|
12978
|
+
const leaves = [];
|
|
12979
|
+
function traverse(cols) {
|
|
12980
|
+
for (const col of cols) {
|
|
12981
|
+
if (isLeafColumn(col)) {
|
|
12982
|
+
leaves.push(col);
|
|
12983
|
+
} else if (col.children) {
|
|
12984
|
+
traverse(col.children);
|
|
12985
|
+
}
|
|
12986
|
+
}
|
|
12987
|
+
}
|
|
12988
|
+
traverse(columns);
|
|
12989
|
+
return leaves;
|
|
12990
|
+
}
|
|
12991
|
+
function getHeaderDepth(columns) {
|
|
12992
|
+
function getDepth(cols) {
|
|
12993
|
+
if (!cols || cols.length === 0) return 0;
|
|
12994
|
+
let maxDepth = 1;
|
|
12995
|
+
for (const col of cols) {
|
|
12996
|
+
if (col.children && col.children.length > 0) {
|
|
12997
|
+
maxDepth = Math.max(maxDepth, 1 + getDepth(col.children));
|
|
12998
|
+
}
|
|
12999
|
+
}
|
|
13000
|
+
return maxDepth;
|
|
13001
|
+
}
|
|
13002
|
+
return getDepth(columns);
|
|
13003
|
+
}
|
|
13004
|
+
function getColSpan(col) {
|
|
13005
|
+
if (col.colSpan !== void 0) return col.colSpan;
|
|
13006
|
+
if (isLeafColumn(col)) return 1;
|
|
13007
|
+
return col.children.reduce((sum, child) => sum + getColSpan(child), 0);
|
|
13008
|
+
}
|
|
13009
|
+
function getRowSpan(col, maxDepth, currentDepth) {
|
|
13010
|
+
if (col.rowSpan !== void 0) return col.rowSpan;
|
|
13011
|
+
if (isLeafColumn(col)) {
|
|
13012
|
+
return maxDepth - currentDepth + 1;
|
|
13013
|
+
}
|
|
13014
|
+
return 1;
|
|
13015
|
+
}
|
|
13016
|
+
function buildHeaderRows(columns) {
|
|
13017
|
+
const maxDepth = getHeaderDepth(columns);
|
|
13018
|
+
const rows = Array.from({ length: maxDepth }, () => []);
|
|
13019
|
+
function buildCell(col, rowIndex, colIndex) {
|
|
13020
|
+
const colSpan = getColSpan(col);
|
|
13021
|
+
const rowSpan = getRowSpan(col, maxDepth, rowIndex + 1);
|
|
13022
|
+
const isLeaf = isLeafColumn(col);
|
|
13023
|
+
rows[rowIndex].push({
|
|
13024
|
+
column: col,
|
|
13025
|
+
colSpan,
|
|
13026
|
+
rowSpan,
|
|
13027
|
+
isLeaf,
|
|
13028
|
+
rowIndex,
|
|
13029
|
+
colIndex
|
|
13030
|
+
});
|
|
13031
|
+
if (col.children && col.children.length > 0) {
|
|
13032
|
+
let childColIndex = colIndex;
|
|
13033
|
+
for (const child of col.children) {
|
|
13034
|
+
childColIndex = buildCell(child, rowIndex + 1, childColIndex);
|
|
13035
|
+
}
|
|
13036
|
+
}
|
|
13037
|
+
return colIndex + colSpan;
|
|
13038
|
+
}
|
|
13039
|
+
let currentColIndex = 0;
|
|
13040
|
+
for (const col of columns) {
|
|
13041
|
+
currentColIndex = buildCell(col, 0, currentColIndex);
|
|
13042
|
+
}
|
|
13043
|
+
return rows;
|
|
13044
|
+
}
|
|
13045
|
+
function filterVisibleColumns(columns, visibleKeys) {
|
|
13046
|
+
return columns.map((col) => {
|
|
13047
|
+
if (col.children) {
|
|
13048
|
+
const visibleChildren = filterVisibleColumns(col.children, visibleKeys);
|
|
13049
|
+
if (visibleChildren.length > 0) {
|
|
13050
|
+
return { ...col, children: visibleChildren };
|
|
13051
|
+
}
|
|
13052
|
+
return null;
|
|
13053
|
+
}
|
|
13054
|
+
return visibleKeys.has(col.key) ? col : null;
|
|
13055
|
+
}).filter((col) => col !== null);
|
|
13056
|
+
}
|
|
13057
|
+
function getLeafColumnsWithFixedInheritance(columns, inheritedFixed) {
|
|
13058
|
+
const leaves = [];
|
|
13059
|
+
for (const col of columns) {
|
|
13060
|
+
const effectiveFixed = col.fixed ?? inheritedFixed;
|
|
13061
|
+
if (isLeafColumn(col)) {
|
|
13062
|
+
leaves.push({ ...col, fixed: effectiveFixed });
|
|
13063
|
+
} else if (col.children) {
|
|
13064
|
+
leaves.push(...getLeafColumnsWithFixedInheritance(col.children, effectiveFixed));
|
|
13065
|
+
}
|
|
13066
|
+
}
|
|
13067
|
+
return leaves;
|
|
13068
|
+
}
|
|
13069
|
+
|
|
12973
13070
|
// ../../components/ui/DataTable/components/Toolbar.tsx
|
|
12974
13071
|
import { jsx as jsx58, jsxs as jsxs52 } from "react/jsx-runtime";
|
|
12975
13072
|
function DataTableToolbar({
|
|
@@ -13004,36 +13101,39 @@ function DataTableToolbar({
|
|
|
13004
13101
|
]
|
|
13005
13102
|
}
|
|
13006
13103
|
),
|
|
13007
|
-
enableColumnVisibilityToggle &&
|
|
13008
|
-
|
|
13009
|
-
|
|
13010
|
-
|
|
13011
|
-
|
|
13012
|
-
|
|
13104
|
+
enableColumnVisibilityToggle && (() => {
|
|
13105
|
+
const leafCols = getLeafColumns(columns);
|
|
13106
|
+
return /* @__PURE__ */ jsx58(
|
|
13107
|
+
DropdownMenu_default,
|
|
13108
|
+
{
|
|
13109
|
+
trigger: /* @__PURE__ */ jsxs52(Button_default, { variant: "ghost", size: "sm", className: "h-8 px-2", children: [
|
|
13110
|
+
/* @__PURE__ */ jsx58("svg", { className: "w-4 h-4 mr-1", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsx58(
|
|
13111
|
+
"path",
|
|
13112
|
+
{
|
|
13113
|
+
strokeLinecap: "round",
|
|
13114
|
+
strokeLinejoin: "round",
|
|
13115
|
+
strokeWidth: 2,
|
|
13116
|
+
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"
|
|
13117
|
+
}
|
|
13118
|
+
) }),
|
|
13119
|
+
labels?.columns || t("columns")
|
|
13120
|
+
] }),
|
|
13121
|
+
children: leafCols.map((c) => /* @__PURE__ */ jsxs52(
|
|
13122
|
+
DropdownMenuItem,
|
|
13013
13123
|
{
|
|
13014
|
-
|
|
13015
|
-
|
|
13016
|
-
|
|
13017
|
-
|
|
13018
|
-
|
|
13019
|
-
|
|
13020
|
-
|
|
13021
|
-
] }),
|
|
13022
|
-
children: columns.map((c) => /* @__PURE__ */ jsxs52(
|
|
13023
|
-
DropdownMenuItem,
|
|
13024
|
-
{
|
|
13025
|
-
onClick: () => {
|
|
13026
|
-
setVisibleCols((prev) => prev.includes(c.key) ? prev.filter((k) => k !== c.key) : [...prev, c.key]);
|
|
13124
|
+
onClick: () => {
|
|
13125
|
+
setVisibleCols((prev) => prev.includes(c.key) ? prev.filter((k) => k !== c.key) : [...prev, c.key]);
|
|
13126
|
+
},
|
|
13127
|
+
children: [
|
|
13128
|
+
/* @__PURE__ */ jsx58("input", { type: "checkbox", className: "mr-2 rounded-md border-border", readOnly: true, checked: visibleCols.includes(c.key) }),
|
|
13129
|
+
/* @__PURE__ */ jsx58("span", { className: "truncate", children: c.title })
|
|
13130
|
+
]
|
|
13027
13131
|
},
|
|
13028
|
-
|
|
13029
|
-
|
|
13030
|
-
|
|
13031
|
-
|
|
13032
|
-
|
|
13033
|
-
c.key
|
|
13034
|
-
))
|
|
13035
|
-
}
|
|
13036
|
-
),
|
|
13132
|
+
c.key
|
|
13133
|
+
))
|
|
13134
|
+
}
|
|
13135
|
+
);
|
|
13136
|
+
})(),
|
|
13037
13137
|
enableHeaderAlignToggle && /* @__PURE__ */ jsx58(
|
|
13038
13138
|
DropdownMenu_default,
|
|
13039
13139
|
{
|
|
@@ -13108,32 +13208,40 @@ import React50 from "react";
|
|
|
13108
13208
|
// ../../components/ui/DataTable/utils/columns.ts
|
|
13109
13209
|
function getColumnWidth(col, fallback = 150) {
|
|
13110
13210
|
if (typeof col.width === "number") return col.width;
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13211
|
+
if (col.width) {
|
|
13212
|
+
const raw = String(col.width);
|
|
13213
|
+
const parsed = parseInt(raw, 10);
|
|
13214
|
+
if (Number.isFinite(parsed) && parsed > 0) return parsed;
|
|
13215
|
+
}
|
|
13216
|
+
if (col.children && col.children.length > 0) {
|
|
13217
|
+
return col.children.reduce((sum, child) => sum + getColumnWidth(child, fallback), 0);
|
|
13218
|
+
}
|
|
13219
|
+
return fallback;
|
|
13114
13220
|
}
|
|
13115
13221
|
|
|
13116
13222
|
// ../../components/ui/DataTable/hooks/useStickyColumns.ts
|
|
13117
|
-
function useStickyColumns(
|
|
13223
|
+
function useStickyColumns(columns, visibleKeys) {
|
|
13224
|
+
const visibleColumns = React50.useMemo(() => filterVisibleColumns(columns, visibleKeys), [columns, visibleKeys]);
|
|
13225
|
+
const leafColumns = React50.useMemo(() => getLeafColumnsWithFixedInheritance(visibleColumns), [visibleColumns]);
|
|
13118
13226
|
const stickyPositions = React50.useMemo(() => {
|
|
13119
13227
|
const positions = {};
|
|
13120
13228
|
let leftOffset = 0;
|
|
13121
|
-
for (const col of
|
|
13229
|
+
for (const col of leafColumns) {
|
|
13122
13230
|
if (col.fixed === "left") {
|
|
13123
13231
|
positions[col.key] = { left: leftOffset };
|
|
13124
13232
|
leftOffset += getColumnWidth(col);
|
|
13125
13233
|
}
|
|
13126
13234
|
}
|
|
13127
13235
|
let rightOffset = 0;
|
|
13128
|
-
for (let i =
|
|
13129
|
-
const col =
|
|
13236
|
+
for (let i = leafColumns.length - 1; i >= 0; i--) {
|
|
13237
|
+
const col = leafColumns[i];
|
|
13130
13238
|
if (col.fixed === "right") {
|
|
13131
13239
|
positions[col.key] = { right: rightOffset };
|
|
13132
13240
|
rightOffset += getColumnWidth(col);
|
|
13133
13241
|
}
|
|
13134
13242
|
}
|
|
13135
13243
|
return positions;
|
|
13136
|
-
}, [
|
|
13244
|
+
}, [leafColumns]);
|
|
13137
13245
|
const getStickyColumnStyle = React50.useCallback(
|
|
13138
13246
|
(col) => {
|
|
13139
13247
|
if (!col.fixed) return {};
|
|
@@ -13163,7 +13271,109 @@ function useStickyColumns(visibleColumns) {
|
|
|
13163
13271
|
isStripedRow ? "bg-muted!" : "bg-card!"
|
|
13164
13272
|
);
|
|
13165
13273
|
}, []);
|
|
13166
|
-
|
|
13274
|
+
const getStickyHeaderCellStyle = React50.useCallback(
|
|
13275
|
+
(headerCell) => {
|
|
13276
|
+
const col = headerCell.column;
|
|
13277
|
+
if (headerCell.isLeaf) {
|
|
13278
|
+
return getStickyColumnStyle(col);
|
|
13279
|
+
}
|
|
13280
|
+
const descendants = getLeafColumns([col]);
|
|
13281
|
+
const stickyDescendants = descendants.filter((d) => d.fixed);
|
|
13282
|
+
if (stickyDescendants.length === 0) return {};
|
|
13283
|
+
const firstSticky = stickyDescendants[0];
|
|
13284
|
+
const lastSticky = stickyDescendants[stickyDescendants.length - 1];
|
|
13285
|
+
if (firstSticky.fixed === "left") {
|
|
13286
|
+
const pos = stickyPositions[firstSticky.key];
|
|
13287
|
+
return pos?.left !== void 0 ? { left: pos.left } : {};
|
|
13288
|
+
}
|
|
13289
|
+
if (lastSticky.fixed === "right") {
|
|
13290
|
+
const pos = stickyPositions[lastSticky.key];
|
|
13291
|
+
return pos?.right !== void 0 ? { right: pos.right } : {};
|
|
13292
|
+
}
|
|
13293
|
+
return {};
|
|
13294
|
+
},
|
|
13295
|
+
[stickyPositions, getStickyColumnStyle]
|
|
13296
|
+
);
|
|
13297
|
+
return {
|
|
13298
|
+
getStickyColumnStyle,
|
|
13299
|
+
getStickyHeaderClass,
|
|
13300
|
+
getStickyCellClass,
|
|
13301
|
+
getStickyHeaderCellStyle
|
|
13302
|
+
};
|
|
13303
|
+
}
|
|
13304
|
+
|
|
13305
|
+
// ../../components/ui/DataTable/utils/validation.ts
|
|
13306
|
+
function validateColumns(columns) {
|
|
13307
|
+
const warnings = [];
|
|
13308
|
+
const keys = /* @__PURE__ */ new Set();
|
|
13309
|
+
function validate(cols, path = "") {
|
|
13310
|
+
for (const col of cols) {
|
|
13311
|
+
const fullPath = path ? `${path}.${col.key}` : col.key;
|
|
13312
|
+
if (keys.has(col.key)) {
|
|
13313
|
+
warnings.push(`Duplicate key "${col.key}" at ${fullPath}`);
|
|
13314
|
+
}
|
|
13315
|
+
keys.add(col.key);
|
|
13316
|
+
const isGroup = col.children && col.children.length > 0;
|
|
13317
|
+
if (isGroup) {
|
|
13318
|
+
if (col.dataIndex) {
|
|
13319
|
+
warnings.push(`Group column "${fullPath}" has dataIndex (will be ignored)`);
|
|
13320
|
+
}
|
|
13321
|
+
if (col.sortable) {
|
|
13322
|
+
warnings.push(`Group column "${fullPath}" has sortable (will be ignored)`);
|
|
13323
|
+
}
|
|
13324
|
+
if (col.filter) {
|
|
13325
|
+
warnings.push(`Group column "${fullPath}" has filter (will be ignored)`);
|
|
13326
|
+
}
|
|
13327
|
+
if (col.render) {
|
|
13328
|
+
warnings.push(`Group column "${fullPath}" has render function (will be ignored)`);
|
|
13329
|
+
}
|
|
13330
|
+
if (col.colSpan !== void 0) {
|
|
13331
|
+
const actualColSpan = getColSpan(col);
|
|
13332
|
+
if (col.colSpan !== actualColSpan) {
|
|
13333
|
+
warnings.push(
|
|
13334
|
+
`Column "${fullPath}" has colSpan=${col.colSpan} but structure suggests ${actualColSpan} (based on ${col.children.length} children)`
|
|
13335
|
+
);
|
|
13336
|
+
}
|
|
13337
|
+
}
|
|
13338
|
+
if (col.fixed) {
|
|
13339
|
+
const conflictingChildren = col.children.filter((c) => c.fixed && c.fixed !== col.fixed);
|
|
13340
|
+
if (conflictingChildren.length > 0) {
|
|
13341
|
+
warnings.push(
|
|
13342
|
+
`Group column "${fullPath}" has fixed="${col.fixed}" but children have different fixed values: ${conflictingChildren.map((c) => c.key).join(", ")}`
|
|
13343
|
+
);
|
|
13344
|
+
}
|
|
13345
|
+
}
|
|
13346
|
+
validate(col.children, fullPath);
|
|
13347
|
+
} else {
|
|
13348
|
+
if (col.children !== void 0) {
|
|
13349
|
+
warnings.push(`Leaf column "${fullPath}" has children property (should be omitted for leaf columns)`);
|
|
13350
|
+
}
|
|
13351
|
+
}
|
|
13352
|
+
}
|
|
13353
|
+
}
|
|
13354
|
+
validate(columns);
|
|
13355
|
+
const depth = getHeaderDepth(columns);
|
|
13356
|
+
if (depth > 4) {
|
|
13357
|
+
warnings.push(`Header depth is ${depth} rows. Consider simplifying - too many header rows may impact user experience.`);
|
|
13358
|
+
}
|
|
13359
|
+
function checkMixedSticky(cols, parentPath = "") {
|
|
13360
|
+
for (const col of cols) {
|
|
13361
|
+
if (col.children && col.children.length > 0) {
|
|
13362
|
+
const childrenFixed = col.children.map((c) => c.fixed);
|
|
13363
|
+
const hasStickyChild = childrenFixed.some((f) => f !== void 0);
|
|
13364
|
+
const hasNonStickyChild = childrenFixed.some((f) => f === void 0);
|
|
13365
|
+
if (hasStickyChild && hasNonStickyChild) {
|
|
13366
|
+
const fullPath = parentPath ? `${parentPath}.${col.key}` : col.key;
|
|
13367
|
+
warnings.push(
|
|
13368
|
+
`Group column "${fullPath}" has mixed sticky children (some fixed, some not). This may cause visual separation when scrolling.`
|
|
13369
|
+
);
|
|
13370
|
+
}
|
|
13371
|
+
checkMixedSticky(col.children, parentPath ? `${parentPath}.${col.key}` : col.key);
|
|
13372
|
+
}
|
|
13373
|
+
}
|
|
13374
|
+
}
|
|
13375
|
+
checkMixedSticky(columns);
|
|
13376
|
+
return warnings;
|
|
13167
13377
|
}
|
|
13168
13378
|
|
|
13169
13379
|
// ../../components/ui/DataTable/DataTable.tsx
|
|
@@ -13199,6 +13409,12 @@ function DataTable({
|
|
|
13199
13409
|
const [density, setDensity] = React51.useState("normal");
|
|
13200
13410
|
const [curPage, setCurPage] = React51.useState(page);
|
|
13201
13411
|
const { curPageSize, setCurPageSize } = usePageSizeStorage({ pageSize, storageKey });
|
|
13412
|
+
React51.useEffect(() => {
|
|
13413
|
+
if (process.env.NODE_ENV === "development") {
|
|
13414
|
+
const warnings = validateColumns(columns);
|
|
13415
|
+
warnings.forEach((w) => console.warn(`[DataTable] ${w}`));
|
|
13416
|
+
}
|
|
13417
|
+
}, [columns]);
|
|
13202
13418
|
React51.useEffect(() => {
|
|
13203
13419
|
const newColKeys = columns.filter((c) => c.visible !== false).map((c) => c.key);
|
|
13204
13420
|
setVisibleCols((prev) => {
|
|
@@ -13223,11 +13439,19 @@ function DataTable({
|
|
|
13223
13439
|
const densityRowClass = density === "compact" ? "h-9" : density === "comfortable" ? "h-14" : "h-12";
|
|
13224
13440
|
const cellPadding = density === "compact" ? "py-1.5 px-3" : density === "comfortable" ? "py-3 px-4" : "py-2.5 px-4";
|
|
13225
13441
|
const visibleColsSet = React51.useMemo(() => new Set(visibleCols), [visibleCols]);
|
|
13226
|
-
const visibleColumns =
|
|
13227
|
-
|
|
13228
|
-
|
|
13442
|
+
const visibleColumns = React51.useMemo(() => {
|
|
13443
|
+
return filterVisibleColumns(columns, visibleColsSet);
|
|
13444
|
+
}, [columns, visibleColsSet]);
|
|
13445
|
+
const leafColumns = React51.useMemo(() => {
|
|
13446
|
+
return getLeafColumns(visibleColumns);
|
|
13229
13447
|
}, [visibleColumns]);
|
|
13230
|
-
const
|
|
13448
|
+
const totalColumnsWidth = React51.useMemo(() => {
|
|
13449
|
+
return leafColumns.reduce((sum, col) => sum + getColumnWidth(col), 0);
|
|
13450
|
+
}, [leafColumns]);
|
|
13451
|
+
const { getStickyCellClass, getStickyColumnStyle, getStickyHeaderClass, getStickyHeaderCellStyle } = useStickyColumns(
|
|
13452
|
+
columns,
|
|
13453
|
+
visibleColsSet
|
|
13454
|
+
);
|
|
13231
13455
|
const getRowKey = (row, idx) => {
|
|
13232
13456
|
if (!rowKey) return String(idx);
|
|
13233
13457
|
if (typeof rowKey === "function") return String(rowKey(row));
|
|
@@ -13283,127 +13507,150 @@ function DataTable({
|
|
|
13283
13507
|
}
|
|
13284
13508
|
return null;
|
|
13285
13509
|
};
|
|
13286
|
-
const
|
|
13287
|
-
|
|
13510
|
+
const headerRows = React51.useMemo(() => buildHeaderRows(visibleColumns), [visibleColumns]);
|
|
13511
|
+
const renderHeaderContent = (col, isLeaf) => {
|
|
13512
|
+
if (!isLeaf) {
|
|
13513
|
+
return /* @__PURE__ */ jsx59(
|
|
13514
|
+
"div",
|
|
13515
|
+
{
|
|
13516
|
+
className: cn(
|
|
13517
|
+
"flex items-center gap-1 min-h-10",
|
|
13518
|
+
col.align === "right" && "justify-end",
|
|
13519
|
+
col.align === "center" && "justify-center",
|
|
13520
|
+
!col.align && "justify-start"
|
|
13521
|
+
),
|
|
13522
|
+
children: /* @__PURE__ */ jsx59("span", { className: "font-medium text-sm whitespace-nowrap", children: col.title })
|
|
13523
|
+
}
|
|
13524
|
+
);
|
|
13525
|
+
}
|
|
13526
|
+
const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
|
|
13527
|
+
const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
|
|
13528
|
+
const titleContent = /* @__PURE__ */ jsxs53("div", { className: "flex items-center gap-1", children: [
|
|
13529
|
+
/* @__PURE__ */ jsx59("span", { className: "font-medium text-sm whitespace-nowrap", children: col.title }),
|
|
13530
|
+
col.sortable && /* @__PURE__ */ jsx59(
|
|
13531
|
+
"button",
|
|
13532
|
+
{
|
|
13533
|
+
className: cn(
|
|
13534
|
+
"p-1 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13535
|
+
sort?.key === col.key ? "opacity-100 bg-accent" : "opacity-60 hover:opacity-100"
|
|
13536
|
+
),
|
|
13537
|
+
onClick: () => {
|
|
13538
|
+
setCurPage(1);
|
|
13539
|
+
setSort((s) => {
|
|
13540
|
+
if (!s || s.key !== col.key) return { key: col.key, order: "asc" };
|
|
13541
|
+
if (s.order === "asc") return { key: col.key, order: "desc" };
|
|
13542
|
+
return null;
|
|
13543
|
+
});
|
|
13544
|
+
},
|
|
13545
|
+
"aria-label": "Sort",
|
|
13546
|
+
title: `Sort by ${String(col.title)}`,
|
|
13547
|
+
children: /* @__PURE__ */ jsxs53("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
|
|
13548
|
+
/* @__PURE__ */ jsx59(
|
|
13549
|
+
"path",
|
|
13550
|
+
{
|
|
13551
|
+
d: "M7 8l3-3 3 3",
|
|
13552
|
+
stroke: "currentColor",
|
|
13553
|
+
strokeWidth: "1.5",
|
|
13554
|
+
strokeLinecap: "round",
|
|
13555
|
+
strokeLinejoin: "round",
|
|
13556
|
+
opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
|
|
13557
|
+
}
|
|
13558
|
+
),
|
|
13559
|
+
/* @__PURE__ */ jsx59(
|
|
13560
|
+
"path",
|
|
13561
|
+
{
|
|
13562
|
+
d: "M7 12l3 3 3-3",
|
|
13563
|
+
stroke: "currentColor",
|
|
13564
|
+
strokeWidth: "1.5",
|
|
13565
|
+
strokeLinecap: "round",
|
|
13566
|
+
strokeLinejoin: "round",
|
|
13567
|
+
opacity: sort?.key === col.key && sort.order === "desc" ? 1 : 0.4
|
|
13568
|
+
}
|
|
13569
|
+
)
|
|
13570
|
+
] })
|
|
13571
|
+
}
|
|
13572
|
+
)
|
|
13573
|
+
] });
|
|
13574
|
+
const filterContent = col.filter ? /* @__PURE__ */ jsx59(
|
|
13575
|
+
Popover,
|
|
13576
|
+
{
|
|
13577
|
+
placement: "bottom-start",
|
|
13578
|
+
trigger: /* @__PURE__ */ jsx59(
|
|
13579
|
+
"button",
|
|
13580
|
+
{
|
|
13581
|
+
className: cn(
|
|
13582
|
+
"p-1.5 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13583
|
+
filters[col.key] ? "bg-accent text-primary" : "text-muted-foreground"
|
|
13584
|
+
),
|
|
13585
|
+
"aria-label": "Filter",
|
|
13586
|
+
title: `Filter by ${String(col.title)}`,
|
|
13587
|
+
children: /* @__PURE__ */ jsx59(FilterIcon, { className: "w-4 h-4" })
|
|
13588
|
+
}
|
|
13589
|
+
),
|
|
13590
|
+
children: /* @__PURE__ */ jsxs53("div", { className: "p-3 w-64 space-y-3", children: [
|
|
13591
|
+
/* @__PURE__ */ jsxs53("div", { className: "flex items-center justify-between", children: [
|
|
13592
|
+
/* @__PURE__ */ jsx59("div", { className: "text-sm font-medium", children: col.title }),
|
|
13593
|
+
filters[col.key] !== void 0 && filters[col.key] !== null && filters[col.key] !== "" && /* @__PURE__ */ jsx59(
|
|
13594
|
+
"button",
|
|
13595
|
+
{
|
|
13596
|
+
onClick: () => {
|
|
13597
|
+
setCurPage(1);
|
|
13598
|
+
setFilters((f) => ({ ...f, [col.key]: void 0 }));
|
|
13599
|
+
},
|
|
13600
|
+
className: "text-xs text-destructive hover:underline",
|
|
13601
|
+
children: t("clearFilter")
|
|
13602
|
+
}
|
|
13603
|
+
)
|
|
13604
|
+
] }),
|
|
13605
|
+
renderFilterControl(col)
|
|
13606
|
+
] })
|
|
13607
|
+
}
|
|
13608
|
+
) : null;
|
|
13609
|
+
return /* @__PURE__ */ jsx59(
|
|
13610
|
+
"div",
|
|
13611
|
+
{
|
|
13612
|
+
className: cn(
|
|
13613
|
+
"flex items-center gap-2 select-none min-h-10",
|
|
13614
|
+
isRightAlign && "justify-end",
|
|
13615
|
+
isCenterAlign && "justify-center",
|
|
13616
|
+
!isRightAlign && !isCenterAlign && "justify-start"
|
|
13617
|
+
),
|
|
13618
|
+
children: isRightAlign ? /* @__PURE__ */ jsxs53(Fragment22, { children: [
|
|
13619
|
+
filterContent,
|
|
13620
|
+
titleContent
|
|
13621
|
+
] }) : /* @__PURE__ */ jsxs53(Fragment22, { children: [
|
|
13622
|
+
titleContent,
|
|
13623
|
+
filterContent
|
|
13624
|
+
] })
|
|
13625
|
+
}
|
|
13626
|
+
);
|
|
13627
|
+
};
|
|
13628
|
+
const renderHeader = /* @__PURE__ */ jsx59(Fragment22, { children: headerRows.map((row, rowIndex) => /* @__PURE__ */ jsx59(TableRow, { children: row.map((headerCell, cellIndex) => {
|
|
13629
|
+
const { column: col, colSpan, rowSpan, isLeaf } = headerCell;
|
|
13630
|
+
const prevCell = cellIndex > 0 ? row[cellIndex - 1] : null;
|
|
13631
|
+
const prevCol = prevCell?.column;
|
|
13288
13632
|
const isAfterFixedLeft = prevCol?.fixed === "left";
|
|
13289
|
-
const showBorderLeft = columnDividers &&
|
|
13633
|
+
const showBorderLeft = columnDividers && cellIndex > 0 && !isAfterFixedLeft && !col.fixed;
|
|
13290
13634
|
return /* @__PURE__ */ jsx59(
|
|
13291
13635
|
TableHead,
|
|
13292
13636
|
{
|
|
13293
|
-
|
|
13637
|
+
colSpan,
|
|
13638
|
+
rowSpan,
|
|
13639
|
+
style: {
|
|
13640
|
+
width: col.width,
|
|
13641
|
+
...getStickyHeaderCellStyle(headerCell)
|
|
13642
|
+
},
|
|
13294
13643
|
className: cn(
|
|
13295
13644
|
(col.align === "right" || !col.align && headerAlign === "right") && "text-right",
|
|
13296
13645
|
(col.align === "center" || !col.align && headerAlign === "center") && "text-center",
|
|
13297
13646
|
showBorderLeft && "border-l border-border/60",
|
|
13298
13647
|
getStickyHeaderClass(col)
|
|
13299
13648
|
),
|
|
13300
|
-
children: (
|
|
13301
|
-
const isRightAlign = col.align === "right" || !col.align && headerAlign === "right";
|
|
13302
|
-
const isCenterAlign = col.align === "center" || !col.align && headerAlign === "center";
|
|
13303
|
-
const titleContent = /* @__PURE__ */ jsxs53("div", { className: cn("flex items-center gap-1", !col.fixed && "min-w-0 shrink"), children: [
|
|
13304
|
-
/* @__PURE__ */ jsx59("span", { className: cn("font-medium text-sm", !col.fixed && "truncate"), children: col.title }),
|
|
13305
|
-
col.sortable && /* @__PURE__ */ jsx59(
|
|
13306
|
-
"button",
|
|
13307
|
-
{
|
|
13308
|
-
className: cn(
|
|
13309
|
-
"p-1 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13310
|
-
sort?.key === col.key ? "opacity-100 bg-accent" : "opacity-60 hover:opacity-100"
|
|
13311
|
-
),
|
|
13312
|
-
onClick: () => {
|
|
13313
|
-
setCurPage(1);
|
|
13314
|
-
setSort((s) => {
|
|
13315
|
-
if (!s || s.key !== col.key) return { key: col.key, order: "asc" };
|
|
13316
|
-
if (s.order === "asc") return { key: col.key, order: "desc" };
|
|
13317
|
-
return null;
|
|
13318
|
-
});
|
|
13319
|
-
},
|
|
13320
|
-
"aria-label": "Sort",
|
|
13321
|
-
title: `Sort by ${String(col.title)}`,
|
|
13322
|
-
children: /* @__PURE__ */ jsxs53("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "none", className: "inline-block", children: [
|
|
13323
|
-
/* @__PURE__ */ jsx59(
|
|
13324
|
-
"path",
|
|
13325
|
-
{
|
|
13326
|
-
d: "M7 8l3-3 3 3",
|
|
13327
|
-
stroke: "currentColor",
|
|
13328
|
-
strokeWidth: "1.5",
|
|
13329
|
-
strokeLinecap: "round",
|
|
13330
|
-
strokeLinejoin: "round",
|
|
13331
|
-
opacity: sort?.key === col.key && sort.order === "asc" ? 1 : 0.4
|
|
13332
|
-
}
|
|
13333
|
-
),
|
|
13334
|
-
/* @__PURE__ */ jsx59(
|
|
13335
|
-
"path",
|
|
13336
|
-
{
|
|
13337
|
-
d: "M7 12l3 3 3-3",
|
|
13338
|
-
stroke: "currentColor",
|
|
13339
|
-
strokeWidth: "1.5",
|
|
13340
|
-
strokeLinecap: "round",
|
|
13341
|
-
strokeLinejoin: "round",
|
|
13342
|
-
opacity: sort?.key === col.key && sort.order === "desc" ? 1 : 0.4
|
|
13343
|
-
}
|
|
13344
|
-
)
|
|
13345
|
-
] })
|
|
13346
|
-
}
|
|
13347
|
-
)
|
|
13348
|
-
] });
|
|
13349
|
-
const filterContent = col.filter ? /* @__PURE__ */ jsx59(
|
|
13350
|
-
Popover,
|
|
13351
|
-
{
|
|
13352
|
-
placement: "bottom-start",
|
|
13353
|
-
trigger: /* @__PURE__ */ jsx59(
|
|
13354
|
-
"button",
|
|
13355
|
-
{
|
|
13356
|
-
className: cn(
|
|
13357
|
-
"p-1.5 rounded-lg transition-all duration-200 hover:bg-accent",
|
|
13358
|
-
filters[col.key] ? "bg-accent text-primary" : "text-muted-foreground"
|
|
13359
|
-
),
|
|
13360
|
-
"aria-label": "Filter",
|
|
13361
|
-
title: `Filter by ${String(col.title)}`,
|
|
13362
|
-
children: /* @__PURE__ */ jsx59(FilterIcon, { className: "w-4 h-4" })
|
|
13363
|
-
}
|
|
13364
|
-
),
|
|
13365
|
-
children: /* @__PURE__ */ jsxs53("div", { className: "p-3 w-64 space-y-3", children: [
|
|
13366
|
-
/* @__PURE__ */ jsxs53("div", { className: "flex items-center justify-between", children: [
|
|
13367
|
-
/* @__PURE__ */ jsx59("div", { className: "text-sm font-medium", children: col.title }),
|
|
13368
|
-
filters[col.key] !== void 0 && filters[col.key] !== null && filters[col.key] !== "" && /* @__PURE__ */ jsx59(
|
|
13369
|
-
"button",
|
|
13370
|
-
{
|
|
13371
|
-
onClick: () => {
|
|
13372
|
-
setCurPage(1);
|
|
13373
|
-
setFilters((f) => ({ ...f, [col.key]: void 0 }));
|
|
13374
|
-
},
|
|
13375
|
-
className: "text-xs text-destructive hover:underline",
|
|
13376
|
-
children: t("clearFilter")
|
|
13377
|
-
}
|
|
13378
|
-
)
|
|
13379
|
-
] }),
|
|
13380
|
-
renderFilterControl(col)
|
|
13381
|
-
] })
|
|
13382
|
-
}
|
|
13383
|
-
) : null;
|
|
13384
|
-
return /* @__PURE__ */ jsx59(
|
|
13385
|
-
"div",
|
|
13386
|
-
{
|
|
13387
|
-
className: cn(
|
|
13388
|
-
"flex items-center gap-2 select-none min-h-10",
|
|
13389
|
-
isRightAlign && "justify-end",
|
|
13390
|
-
isCenterAlign && "justify-center",
|
|
13391
|
-
!isRightAlign && !isCenterAlign && "justify-start"
|
|
13392
|
-
),
|
|
13393
|
-
children: isRightAlign ? /* @__PURE__ */ jsxs53(Fragment22, { children: [
|
|
13394
|
-
filterContent,
|
|
13395
|
-
titleContent
|
|
13396
|
-
] }) : /* @__PURE__ */ jsxs53(Fragment22, { children: [
|
|
13397
|
-
titleContent,
|
|
13398
|
-
filterContent
|
|
13399
|
-
] })
|
|
13400
|
-
}
|
|
13401
|
-
);
|
|
13402
|
-
})()
|
|
13649
|
+
children: renderHeaderContent(col, isLeaf)
|
|
13403
13650
|
},
|
|
13404
13651
|
col.key
|
|
13405
13652
|
);
|
|
13406
|
-
}) });
|
|
13653
|
+
}) }, `header-row-${rowIndex}`)) });
|
|
13407
13654
|
const processedData = React51.useMemo(() => {
|
|
13408
13655
|
if (isServerMode) return data;
|
|
13409
13656
|
let result = [...data];
|
|
@@ -13479,7 +13726,7 @@ function DataTable({
|
|
|
13479
13726
|
style: { minWidth: totalColumnsWidth > 0 ? `${totalColumnsWidth}px` : void 0 },
|
|
13480
13727
|
children: [
|
|
13481
13728
|
/* @__PURE__ */ jsx59(TableHeader, { children: renderHeader }),
|
|
13482
|
-
/* @__PURE__ */ jsx59(TableBody, { children: loading2 ? /* @__PURE__ */ jsx59(TableRow, { children: /* @__PURE__ */ jsx59(TableCell, { colSpan:
|
|
13729
|
+
/* @__PURE__ */ jsx59(TableBody, { children: loading2 ? /* @__PURE__ */ jsx59(TableRow, { children: /* @__PURE__ */ jsx59(TableCell, { colSpan: leafColumns.length, className: "text-center py-8", children: /* @__PURE__ */ jsxs53("div", { className: "flex items-center justify-center gap-2 text-muted-foreground", children: [
|
|
13483
13730
|
/* @__PURE__ */ jsxs53("svg", { className: "animate-spin h-4 w-4", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [
|
|
13484
13731
|
/* @__PURE__ */ jsx59("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
|
|
13485
13732
|
/* @__PURE__ */ jsx59(
|
|
@@ -13495,7 +13742,7 @@ function DataTable({
|
|
|
13495
13742
|
t("loading"),
|
|
13496
13743
|
"\u2026"
|
|
13497
13744
|
] })
|
|
13498
|
-
] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ jsx59(TableRow, { children: /* @__PURE__ */ jsx59(TableCell, { colSpan:
|
|
13745
|
+
] }) }) }) : !displayedData || displayedData.length === 0 ? /* @__PURE__ */ jsx59(TableRow, { children: /* @__PURE__ */ jsx59(TableCell, { colSpan: leafColumns.length, className: "text-center py-6 text-muted-foreground", children: t("noData") }) }) : displayedData.map((row, idx) => {
|
|
13499
13746
|
const isLastRow = idx === displayedData.length - 1;
|
|
13500
13747
|
return /* @__PURE__ */ jsx59(
|
|
13501
13748
|
TableRow,
|
|
@@ -13505,10 +13752,10 @@ function DataTable({
|
|
|
13505
13752
|
contentVisibility: "auto",
|
|
13506
13753
|
containIntrinsicSize: density === "compact" ? "0 36px" : density === "comfortable" ? "0 56px" : "0 48px"
|
|
13507
13754
|
},
|
|
13508
|
-
children:
|
|
13755
|
+
children: leafColumns.map((col, colIdx) => {
|
|
13509
13756
|
const value = col.dataIndex ? row[col.dataIndex] : void 0;
|
|
13510
13757
|
const isStripedRow = striped && idx % 2 === 0;
|
|
13511
|
-
const prevCol = colIdx > 0 ?
|
|
13758
|
+
const prevCol = colIdx > 0 ? leafColumns[colIdx - 1] : null;
|
|
13512
13759
|
const isAfterFixedLeft = prevCol?.fixed === "left";
|
|
13513
13760
|
const showBorderLeft = columnDividers && colIdx > 0 && !isAfterFixedLeft && !col.fixed;
|
|
13514
13761
|
return /* @__PURE__ */ jsx59(
|
|
@@ -13520,8 +13767,8 @@ function DataTable({
|
|
|
13520
13767
|
col.align === "right" && "text-right",
|
|
13521
13768
|
col.align === "center" && "text-center",
|
|
13522
13769
|
showBorderLeft && "border-l border-border/60",
|
|
13523
|
-
isLastRow && col ===
|
|
13524
|
-
isLastRow && col ===
|
|
13770
|
+
isLastRow && col === leafColumns[0] && "rounded-bl-2xl md:rounded-bl-3xl",
|
|
13771
|
+
isLastRow && col === leafColumns[leafColumns.length - 1] && "rounded-br-2xl md:rounded-br-3xl",
|
|
13525
13772
|
getStickyCellClass(col, isStripedRow),
|
|
13526
13773
|
!col.fixed && isStripedRow && "bg-muted/50"
|
|
13527
13774
|
),
|