refactor: update configuration and enhance skeleton components for improved UI consistency
CI / changes (push) Successful in 11s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 1m5s
CI / go (push) Successful in 1m5s
CI / bird2 (push) Successful in 19s
CI / release (push) Successful in 4m22s
CI / changes (push) Successful in 11s
CI / commitlint (push) Has been skipped
CI / openapi (push) Has been skipped
CI / web (push) Successful in 1m5s
CI / go (push) Successful in 1m5s
CI / bird2 (push) Successful in 19s
CI / release (push) Successful in 4m22s
Modified .npmrc to set a new store directory. Updated eslint configuration to ignore additional paths. Adjusted tsconfig to exclude specific components and refined the SectionCardsSkeleton and AnalyticsDashboardSkeleton for better layout and loading states. Removed the deprecated DashboardQuickActions component to streamline the codebase.
This commit is contained in:
@@ -9,8 +9,9 @@ import {
|
||||
TouchEvent as ReactTouchEvent,
|
||||
Ref,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useLayoutEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from "react"
|
||||
import { useDataGrid } from "@/components/reui/data-grid/data-grid"
|
||||
@@ -19,7 +20,6 @@ import {
|
||||
Column,
|
||||
flexRender,
|
||||
Header,
|
||||
HeaderGroup,
|
||||
Row,
|
||||
Table,
|
||||
} from "@tanstack/react-table"
|
||||
@@ -28,15 +28,12 @@ import { cva } from "class-variance-authority"
|
||||
import { cn } from "@evobgp/ui/lib/utils"
|
||||
import { Checkbox } from "@evobgp/ui/components/checkbox"
|
||||
import { Spinner } from "@evobgp/ui/components/spinner"
|
||||
import { DATA_GRID_MESSAGES_RU } from "@/lib/data-grid-defaults"
|
||||
|
||||
const headerCellSpacingVariants = cva("", {
|
||||
variants: {
|
||||
size: {
|
||||
dense:
|
||||
"px-2 h-8",
|
||||
default:
|
||||
"px-3",
|
||||
dense: "px-2 h-8",
|
||||
default: "px-3",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
@@ -47,10 +44,8 @@ const headerCellSpacingVariants = cva("", {
|
||||
const bodyCellSpacingVariants = cva("", {
|
||||
variants: {
|
||||
size: {
|
||||
dense:
|
||||
"px-2 py-1.5",
|
||||
default:
|
||||
"px-3 py-2",
|
||||
dense: "px-2 py-1.5",
|
||||
default: "px-3 py-2",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
@@ -61,10 +56,8 @@ const bodyCellSpacingVariants = cva("", {
|
||||
const footerCellSpacingVariants = cva("", {
|
||||
variants: {
|
||||
size: {
|
||||
dense:
|
||||
"px-2 py-1.5",
|
||||
default:
|
||||
"px-3 py-2",
|
||||
dense: "px-2 py-1.5",
|
||||
default: "px-3 py-2",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
@@ -78,9 +71,12 @@ function getPinningStyles<TData>(column: Column<TData>): CSSProperties {
|
||||
return {
|
||||
left: isPinned === "left" ? `${column.getStart("left")}px` : undefined,
|
||||
right: isPinned === "right" ? `${column.getAfter("right")}px` : undefined,
|
||||
position: isPinned ? "sticky" : "relative",
|
||||
position: isPinned ? "sticky" : undefined,
|
||||
transform: isPinned ? "translateZ(0)" : undefined,
|
||||
contain: isPinned ? "paint" : undefined,
|
||||
width: column.getSize(),
|
||||
zIndex: isPinned ? 1 : 0,
|
||||
zIndex: isPinned ? 30 : undefined,
|
||||
backgroundClip: isPinned ? "padding-box" : undefined,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,6 +334,55 @@ function getDataGridTableResolvedRows<TData>(
|
||||
return resolvedRows
|
||||
}
|
||||
|
||||
function getDataGridTableOrderedVisibleColumns<TData>(table: Table<TData>) {
|
||||
return [
|
||||
...table.getLeftVisibleLeafColumns(),
|
||||
...table.getCenterVisibleLeafColumns(),
|
||||
...table.getRightVisibleLeafColumns(),
|
||||
] as Column<TData>[]
|
||||
}
|
||||
|
||||
function getDataGridTableOrderedVisibleCells<TData>(row: Row<TData>) {
|
||||
return [
|
||||
...row.getLeftVisibleCells(),
|
||||
...row.getCenterVisibleCells(),
|
||||
...row.getRightVisibleCells(),
|
||||
] as Cell<TData, unknown>[]
|
||||
}
|
||||
|
||||
function getDataGridTableMergedHeaderGroups<TData>(table: Table<TData>) {
|
||||
const leftHeaderGroups = table.getLeftHeaderGroups()
|
||||
const centerHeaderGroups = table.getCenterHeaderGroups()
|
||||
const rightHeaderGroups = table.getRightHeaderGroups()
|
||||
const headerGroupCount = Math.max(
|
||||
leftHeaderGroups.length,
|
||||
centerHeaderGroups.length,
|
||||
rightHeaderGroups.length
|
||||
)
|
||||
|
||||
return Array.from({ length: headerGroupCount }, (_, index) => {
|
||||
const leftGroup = leftHeaderGroups[index]
|
||||
const centerGroup = centerHeaderGroups[index]
|
||||
const rightGroup = rightHeaderGroups[index]
|
||||
|
||||
return {
|
||||
id:
|
||||
[leftGroup?.id, centerGroup?.id, rightGroup?.id]
|
||||
.filter(Boolean)
|
||||
.join(":") || `header-group-${index}`,
|
||||
headers: [
|
||||
...(leftGroup?.headers ?? []),
|
||||
...(centerGroup?.headers ?? []),
|
||||
...(rightGroup?.headers ?? []),
|
||||
] as Header<TData, unknown>[],
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function hasDataGridTableRightPinnedColumns<TData>(table: Table<TData>) {
|
||||
return (table.getState().columnPinning.right?.length ?? 0) > 0
|
||||
}
|
||||
|
||||
function DataGridTableFillCol() {
|
||||
const { props } = useDataGrid()
|
||||
|
||||
@@ -391,14 +436,17 @@ function DataGridTableFillFootCell() {
|
||||
aria-hidden="true"
|
||||
data-slot="data-grid-table-fill-foot-cell"
|
||||
style={{ width: "var(--data-grid-fill-size, 0px)" }}
|
||||
className="border-t p-0"
|
||||
className="p-0"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function DataGridTableBase({ children }: { children: ReactNode }) {
|
||||
const { props, table } = useDataGrid()
|
||||
const visibleColumns = table.getVisibleLeafColumns()
|
||||
const leftVisibleColumns = table.getLeftVisibleLeafColumns()
|
||||
const centerVisibleColumns = table.getCenterVisibleLeafColumns()
|
||||
const rightVisibleColumns = table.getRightVisibleLeafColumns()
|
||||
const hasRightPinnedColumns = hasDataGridTableRightPinnedColumns(table)
|
||||
|
||||
/**
|
||||
* Compute column widths as CSS custom properties once upfront (memoized).
|
||||
@@ -427,7 +475,7 @@ function DataGridTableBase({ children }: { children: ReactNode }) {
|
||||
<table
|
||||
data-slot="data-grid-table"
|
||||
className={cn(
|
||||
"text-foreground text-sm caption-bottom text-left align-middle font-normal rtl:text-right",
|
||||
"text-foreground caption-bottom text-left align-middle text-sm font-normal rtl:text-right",
|
||||
props.tableLayout?.columnsResizable ? "min-w-0" : "w-full min-w-full",
|
||||
props.tableLayout?.width === "auto" ? "table-auto" : "table-fixed",
|
||||
!props.tableLayout?.columnsResizable && "",
|
||||
@@ -445,7 +493,7 @@ function DataGridTableBase({ children }: { children: ReactNode }) {
|
||||
}
|
||||
>
|
||||
<colgroup>
|
||||
{visibleColumns.map((column) => (
|
||||
{[...leftVisibleColumns, ...centerVisibleColumns].map((column) => (
|
||||
<col
|
||||
key={column.id}
|
||||
style={
|
||||
@@ -457,7 +505,20 @@ function DataGridTableBase({ children }: { children: ReactNode }) {
|
||||
}
|
||||
/>
|
||||
))}
|
||||
<DataGridTableFillCol />
|
||||
{hasRightPinnedColumns ? <DataGridTableFillCol /> : null}
|
||||
{rightVisibleColumns.map((column) => (
|
||||
<col
|
||||
key={column.id}
|
||||
style={
|
||||
props.tableLayout?.columnsResizable
|
||||
? { width: `calc(var(--col-${column.id}-size) * 1px)` }
|
||||
: props.tableLayout?.width === "fixed"
|
||||
? { width: column.getSize() }
|
||||
: undefined
|
||||
}
|
||||
/>
|
||||
))}
|
||||
{!hasRightPinnedColumns ? <DataGridTableFillCol /> : null}
|
||||
</colgroup>
|
||||
{children}
|
||||
</table>
|
||||
@@ -476,6 +537,7 @@ function DataGridTableViewport({
|
||||
style?: CSSProperties
|
||||
}) {
|
||||
const { props, table } = useDataGrid()
|
||||
const didApplyAutoSizeColumnRef = useRef<string | null>(null)
|
||||
const [viewportElement, setViewportElement] = useState<HTMLDivElement | null>(
|
||||
null
|
||||
)
|
||||
@@ -483,16 +545,34 @@ function DataGridTableViewport({
|
||||
const handleViewportRef = useCallback(
|
||||
(node: HTMLDivElement | null) => {
|
||||
setViewportElement(node)
|
||||
|
||||
if (props.tableLayout?.columnsResizable && node) {
|
||||
const scrollViewport =
|
||||
(node.closest(
|
||||
'[data-slot="scroll-area-viewport"]'
|
||||
) as HTMLElement | null) ?? node.parentElement
|
||||
const measurementTarget = scrollViewport ?? node
|
||||
|
||||
setContainerWidth(measurementTarget.clientWidth)
|
||||
} else if (!node) {
|
||||
setContainerWidth(0)
|
||||
}
|
||||
|
||||
assignRef(viewportRef, node)
|
||||
},
|
||||
[viewportRef]
|
||||
[props.tableLayout?.columnsResizable, viewportRef]
|
||||
)
|
||||
const fillWidth =
|
||||
props.tableLayout?.columnsResizable && containerWidth > 0
|
||||
? Math.max(0, containerWidth - table.getTotalSize())
|
||||
: 0
|
||||
const autoSizeColumnId = table
|
||||
.getVisibleLeafColumns()
|
||||
.find(
|
||||
(column) => column.columnDef.meta?.autoSize && column.getCanResize()
|
||||
)?.id
|
||||
|
||||
useEffect(() => {
|
||||
useLayoutEffect(() => {
|
||||
if (!viewportElement || !props.tableLayout?.columnsResizable) {
|
||||
setContainerWidth(0)
|
||||
return
|
||||
@@ -520,6 +600,22 @@ function DataGridTableViewport({
|
||||
}
|
||||
}, [props.tableLayout?.columnsResizable, viewportElement])
|
||||
|
||||
useLayoutEffect(() => {
|
||||
if (!props.tableLayout?.columnsResizable) return
|
||||
if (!autoSizeColumnId || fillWidth <= 0) return
|
||||
if (didApplyAutoSizeColumnRef.current === autoSizeColumnId) return
|
||||
|
||||
const autoSizeColumn = table.getColumn(autoSizeColumnId)
|
||||
if (!autoSizeColumn) return
|
||||
|
||||
didApplyAutoSizeColumnRef.current = autoSizeColumnId
|
||||
table.setColumnSizing((old) => ({
|
||||
...old,
|
||||
[autoSizeColumnId]:
|
||||
(old[autoSizeColumnId] ?? autoSizeColumn.getSize()) + fillWidth,
|
||||
}))
|
||||
}, [autoSizeColumnId, fillWidth, props.tableLayout?.columnsResizable, table])
|
||||
|
||||
return (
|
||||
<div
|
||||
data-slot="data-grid-table-viewport"
|
||||
@@ -556,20 +652,18 @@ function DataGridTableHead({ children }: { children: ReactNode }) {
|
||||
)
|
||||
}
|
||||
|
||||
function DataGridTableHeadRow<TData>({
|
||||
function DataGridTableHeadRow({
|
||||
children,
|
||||
headerGroup,
|
||||
rowId,
|
||||
}: {
|
||||
children: ReactNode
|
||||
headerGroup: HeaderGroup<TData>
|
||||
rowId: string
|
||||
}) {
|
||||
const { props } = useDataGrid()
|
||||
|
||||
return (
|
||||
<tr
|
||||
key={headerGroup.id}
|
||||
className={cn(
|
||||
"bg-muted/40",
|
||||
props.tableLayout?.headerBorder && "[&>th]:border-b",
|
||||
props.tableLayout?.cellBorder && "*:last:border-e-0",
|
||||
props.tableLayout?.stripped && "bg-transparent",
|
||||
@@ -578,7 +672,6 @@ function DataGridTableHeadRow<TData>({
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
<DataGridTableFillHeadCell />
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
@@ -598,9 +691,13 @@ function DataGridTableHeadRowCell<TData>({
|
||||
|
||||
const { column } = header
|
||||
const isPinned = column.getIsPinned()
|
||||
const isFirstLeftPinned =
|
||||
isPinned === "left" && column.getIsFirstColumn("left")
|
||||
const isLastLeftPinned = isPinned === "left" && column.getIsLastColumn("left")
|
||||
const isFirstRightPinned =
|
||||
isPinned === "right" && column.getIsFirstColumn("right")
|
||||
const isLastRightPinned =
|
||||
isPinned === "right" && column.getIsLastColumn("right")
|
||||
const isLastVisibleColumn =
|
||||
column.getIndex() ===
|
||||
header.getContext().table.getVisibleLeafColumns().length - 1
|
||||
@@ -610,7 +707,6 @@ function DataGridTableHeadRowCell<TData>({
|
||||
|
||||
return (
|
||||
<th
|
||||
key={header.id}
|
||||
ref={dndRef}
|
||||
style={{
|
||||
...(props.tableLayout?.width === "fixed" &&
|
||||
@@ -626,23 +722,31 @@ function DataGridTableHeadRowCell<TData>({
|
||||
...(dndStyle ? dndStyle : null),
|
||||
}}
|
||||
data-pinned={isPinned || undefined}
|
||||
data-outer-pinned-col={
|
||||
isFirstLeftPinned ? "left" : isLastRightPinned ? "right" : undefined
|
||||
}
|
||||
data-last-col={
|
||||
isLastLeftPinned ? "left" : isFirstRightPinned ? "right" : undefined
|
||||
}
|
||||
className={cn(
|
||||
"text-secondary-foreground/80 h-9 relative text-left align-middle font-normal rtl:text-right [&:has([role=checkbox])]:pe-0",
|
||||
"text-foreground relative h-10 text-left align-middle font-medium rtl:text-right [&:has([role=checkbox])]:pe-0",
|
||||
headerCellSpacing,
|
||||
props.tableLayout?.headerBackground && "bg-muted",
|
||||
props.tableLayout?.cellBorder && "border-e",
|
||||
props.tableLayout?.columnsResizable &&
|
||||
column.getCanResize() &&
|
||||
"overflow-visible",
|
||||
(isPinned ? "overflow-hidden" : "overflow-visible"),
|
||||
props.tableLayout?.columnsResizable &&
|
||||
column.getCanResize() &&
|
||||
isLastVisibleColumn &&
|
||||
"pe-8",
|
||||
props.tableLayout?.columnsPinnable &&
|
||||
column.getCanPin() &&
|
||||
"[&[data-pinned][data-last-col]]:border-border data-pinned:bg-muted/90 data-pinned:backdrop-blur-xs [&:not([data-pinned]):has(+[data-pinned])_div.cursor-col-resize:last-child]:opacity-0 [&[data-last-col=left]_div.cursor-col-resize:last-child]:opacity-0 [&[data-pinned=left][data-last-col=left]]:border-e! [&[data-pinned=right]:last-child_div.cursor-col-resize:last-child]:opacity-0 [&[data-pinned=right][data-last-col=right]]:border-s!",
|
||||
cn(
|
||||
"data-pinned:bg-muted data-outer-pinned-col:bg-clip-padding data-pinned:isolate",
|
||||
"[&[data-pinned=left][data-last-col=left]]:shadow-[inset_-1px_0_0_0_var(--border)] [&[data-pinned=right]:last-child_div.cursor-col-resize:last-child]:opacity-0 [&[data-pinned=right][data-last-col=right]]:shadow-[inset_1px_0_0_0_var(--border)]",
|
||||
"[&:not([data-pinned]):has(+[data-pinned])_div.cursor-col-resize:last-child]:opacity-0 [&[data-last-col=left]_div.cursor-col-resize:last-child]:opacity-0"
|
||||
),
|
||||
header.column.columnDef.meta?.headerClassName,
|
||||
column.getIndex() === 0 ||
|
||||
column.getIndex() === header.headerGroup.headers.length - 1
|
||||
@@ -662,6 +766,7 @@ function DataGridTableHeadRowCellResize<TData>({
|
||||
}) {
|
||||
const { props, table } = useDataGrid()
|
||||
const { column } = header
|
||||
const isPinned = column.getIsPinned()
|
||||
const isLastVisibleColumn =
|
||||
column.getIndex() ===
|
||||
header.getContext().table.getVisibleLeafColumns().length - 1
|
||||
@@ -703,7 +808,9 @@ function DataGridTableHeadRowCellResize<TData>({
|
||||
"absolute top-0 h-full cursor-col-resize user-select-none touch-none z-10 flex",
|
||||
isLastVisibleColumn
|
||||
? "end-0 w-5 justify-end before:hidden"
|
||||
: "-end-2 w-5 justify-center before:absolute before:inset-y-0 before:w-px before:-translate-x-px before:bg-border",
|
||||
: isPinned
|
||||
? "end-0 w-5 justify-end before:hidden"
|
||||
: "-end-2 w-5 justify-center before:absolute before:inset-y-0 before:w-px before:-translate-x-px before:bg-border",
|
||||
column.getIsResizing() &&
|
||||
(isResizeModeOnEnd
|
||||
? "opacity-100"
|
||||
@@ -766,7 +873,7 @@ function DataGridTableResizeIndicator({
|
||||
>
|
||||
<div className="bg-primary/85 absolute inset-y-0 left-0 w-px -translate-x-1/2" />
|
||||
<div
|
||||
className="bg-primary absolute top-0 left-0 -translate-x-1/2 rounded-b-sm shadow-xs"
|
||||
className="bg-primary rounded-b-sm absolute top-0 left-0 -translate-x-1/2 shadow-xs"
|
||||
style={{
|
||||
width: 5,
|
||||
height: Math.max(headerHeight, 6),
|
||||
@@ -777,7 +884,13 @@ function DataGridTableResizeIndicator({
|
||||
}
|
||||
|
||||
function DataGridTableRowSpacer() {
|
||||
return <tbody aria-hidden="true" className="h-2"></tbody>
|
||||
return (
|
||||
<tbody
|
||||
aria-hidden="true"
|
||||
className="h-2"
|
||||
data-slot="data-grid-table-body-spacer"
|
||||
></tbody>
|
||||
)
|
||||
}
|
||||
|
||||
function DataGridTableBody({ children }: { children: ReactNode }) {
|
||||
@@ -785,8 +898,8 @@ function DataGridTableBody({ children }: { children: ReactNode }) {
|
||||
|
||||
return (
|
||||
<tbody
|
||||
data-slot="data-grid-table-body"
|
||||
className={cn(
|
||||
"[&_tr:last-child]:border-0",
|
||||
props.tableLayout?.rowRounded &&
|
||||
"[&_td:first-child]:rounded-l-lg",
|
||||
props.tableLayout?.rowRounded &&
|
||||
@@ -802,7 +915,10 @@ function DataGridTableBody({ children }: { children: ReactNode }) {
|
||||
function DataGridTableFoot({ children }: { children: ReactNode }) {
|
||||
const { props } = useDataGrid()
|
||||
return (
|
||||
<tfoot className={cn("border-t", props.tableClassNames?.footer)}>
|
||||
<tfoot
|
||||
data-slot="data-grid-table-foot"
|
||||
className={cn(props.tableClassNames?.footer)}
|
||||
>
|
||||
{children}
|
||||
</tfoot>
|
||||
)
|
||||
@@ -810,10 +926,14 @@ function DataGridTableFoot({ children }: { children: ReactNode }) {
|
||||
|
||||
function DataGridTableFootRow({ children }: { children: ReactNode }) {
|
||||
const { props } = useDataGrid()
|
||||
const footRowBottomBorderClasses = "[&:not(:last-child)>td]:border-b"
|
||||
|
||||
return (
|
||||
<tr
|
||||
data-slot="data-grid-table-foot-row"
|
||||
className={cn(
|
||||
"bg-muted/40 dark:bg-background",
|
||||
props.tableLayout?.footerBackground && "bg-muted/40 dark:bg-background",
|
||||
props.tableLayout?.rowBorder && footRowBottomBorderClasses,
|
||||
props.tableLayout?.cellBorder && "*:last:border-e-0"
|
||||
)}
|
||||
>
|
||||
@@ -840,8 +960,9 @@ function DataGridTableFootRowCell({
|
||||
<td
|
||||
colSpan={colSpan}
|
||||
className={cn(
|
||||
"text-secondary-foreground/80 border-t align-middle font-medium",
|
||||
"text-secondary-foreground/80 align-middle font-medium",
|
||||
spacing,
|
||||
props.tableLayout?.footerBackground && "bg-muted/40 dark:bg-background",
|
||||
props.tableLayout?.cellBorder && "border-e",
|
||||
className
|
||||
)}
|
||||
@@ -870,7 +991,6 @@ function DataGridTableBodyRowSkeleton({ children }: { children: ReactNode }) {
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
<DataGridTableFillBodyCell />
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
@@ -904,7 +1024,7 @@ function DataGridTableBodyRowSkeletonCell<TData>({
|
||||
column.columnDef.meta?.cellClassName,
|
||||
props.tableLayout?.columnsPinnable &&
|
||||
column.getCanPin() &&
|
||||
'[&[data-pinned][data-last-col]]:border-border data-pinned:bg-background/90 data-pinned:backdrop-blur-xs" [&[data-pinned=left][data-last-col=left]]:border-e! [&[data-pinned=right][data-last-col=right]]:border-s!',
|
||||
"data-pinned:bg-background data-pinned:isolate [&[data-pinned=left][data-last-col=left]]:shadow-[inset_-1px_0_0_0_var(--border)] [&[data-pinned=right][data-last-col=right]]:shadow-[inset_1px_0_0_0_var(--border)]",
|
||||
column.getIndex() === 0 ||
|
||||
column.getIndex() === table.getVisibleFlatColumns().length - 1
|
||||
? props.tableClassNames?.edgeCell
|
||||
@@ -934,6 +1054,9 @@ function DataGridTableBodyRow<TData>({
|
||||
const { props, table } = useDataGrid()
|
||||
const isRowPinned = row.getIsPinned()
|
||||
|
||||
const bodyRowBottomBorderClasses =
|
||||
"[&:not(:last-child)>td]:border-b [tbody:has(+tfoot)_&:last-child>td]:border-b [*:has(>[data-slot=data-grid]+[data-slot=data-grid-pagination])_[data-slot=data-grid]_&:last-child>td]:border-b"
|
||||
|
||||
return (
|
||||
<tr
|
||||
ref={(node) => {
|
||||
@@ -954,8 +1077,9 @@ function DataGridTableBodyRow<TData>({
|
||||
props.onRowClick && "cursor-pointer",
|
||||
!props.tableLayout?.stripped &&
|
||||
props.tableLayout?.rowBorder &&
|
||||
"border-border border-b [&:not(:last-child)>td]:border-b",
|
||||
props.tableLayout?.cellBorder && "*:last:border-e-0",
|
||||
bodyRowBottomBorderClasses,
|
||||
props.tableLayout?.cellBorder &&
|
||||
`*:last:border-e-0 ${bodyRowBottomBorderClasses}`,
|
||||
props.tableLayout?.stripped &&
|
||||
"odd:bg-muted/90 odd:hover:bg-muted hover:bg-transparent",
|
||||
table.options.enableRowSelection && "*:first:relative",
|
||||
@@ -969,23 +1093,22 @@ function DataGridTableBodyRow<TData>({
|
||||
)}
|
||||
>
|
||||
{children}
|
||||
<DataGridTableFillBodyCell />
|
||||
</tr>
|
||||
)
|
||||
}
|
||||
|
||||
function DataGridTableBodyRowExpandded<TData>({ row }: { row: Row<TData> }) {
|
||||
const { props, table } = useDataGrid()
|
||||
const bodyRowBottomBorderClasses =
|
||||
"[&:not(:last-child)>td]:border-b [tbody:has(+tfoot)_&:last-child>td]:border-b [*:has(>[data-slot=data-grid]+[data-slot=data-grid-pagination])_[data-slot=data-grid]_&:last-child>td]:border-b"
|
||||
|
||||
return (
|
||||
<tr
|
||||
className={cn(
|
||||
props.tableLayout?.rowBorder && "[&:not(:last-child)>td]:border-b"
|
||||
)}
|
||||
className={cn(props.tableLayout?.rowBorder && bodyRowBottomBorderClasses)}
|
||||
>
|
||||
<td
|
||||
colSpan={
|
||||
row.getVisibleCells().length +
|
||||
getDataGridTableOrderedVisibleCells(row).length +
|
||||
(props.tableLayout?.columnsResizable ? 1 : 0)
|
||||
}
|
||||
>
|
||||
@@ -1022,9 +1145,7 @@ function DataGridTableBodyRowCell<TData>({
|
||||
|
||||
return (
|
||||
<td
|
||||
key={cell.id}
|
||||
ref={dndRef}
|
||||
{...(props.tableLayout?.columnsDraggable && !isPinned ? { cell } : {})}
|
||||
style={{
|
||||
...(props.tableLayout?.columnsPinnable &&
|
||||
column.getCanPin() &&
|
||||
@@ -1048,7 +1169,11 @@ function DataGridTableBodyRowCell<TData>({
|
||||
cell.column.columnDef.meta?.cellClassName,
|
||||
props.tableLayout?.columnsPinnable &&
|
||||
column.getCanPin() &&
|
||||
'[&[data-pinned][data-last-col]]:border-border data-pinned:bg-background/90 data-pinned:backdrop-blur-xs" [&[data-pinned=left][data-last-col=left]]:border-e! [&[data-pinned=right][data-last-col=right]]:border-s!',
|
||||
cn(
|
||||
"data-pinned:bg-background data-pinned:isolate",
|
||||
"[&[data-pinned=left][data-last-col=left]]:shadow-[inset_-1px_0_0_0_var(--border)]",
|
||||
"[&[data-pinned=right][data-last-col=right]]:shadow-[inset_1px_0_0_0_var(--border)]"
|
||||
),
|
||||
column.getIndex() === 0 ||
|
||||
column.getIndex() === row.getVisibleCells().length - 1
|
||||
? props.tableClassNames?.edgeCell
|
||||
@@ -1069,6 +1194,12 @@ function DataGridTableRenderedRow<TData>({
|
||||
pinnedBoundary?: DataGridTablePinnedBoundary
|
||||
rowRef?: React.Ref<HTMLTableRowElement>
|
||||
}) {
|
||||
const { props, table } = useDataGrid()
|
||||
const leftVisibleCells = row.getLeftVisibleCells()
|
||||
const centerVisibleCells = row.getCenterVisibleCells()
|
||||
const rightVisibleCells = row.getRightVisibleCells()
|
||||
const hasRightPinnedColumns = hasDataGridTableRightPinnedColumns(table)
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<DataGridTableBodyRow
|
||||
@@ -1076,11 +1207,24 @@ function DataGridTableRenderedRow<TData>({
|
||||
pinnedBoundary={pinnedBoundary}
|
||||
rowRef={rowRef}
|
||||
>
|
||||
{row.getVisibleCells().map((cell: Cell<TData, unknown>) => (
|
||||
{[...leftVisibleCells, ...centerVisibleCells].map(
|
||||
(cell: Cell<TData, unknown>) => (
|
||||
<DataGridTableBodyRowCell cell={cell} key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</DataGridTableBodyRowCell>
|
||||
)
|
||||
)}
|
||||
{props.tableLayout?.columnsResizable && hasRightPinnedColumns ? (
|
||||
<DataGridTableFillBodyCell />
|
||||
) : null}
|
||||
{rightVisibleCells.map((cell: Cell<TData, unknown>) => (
|
||||
<DataGridTableBodyRowCell cell={cell} key={cell.id}>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</DataGridTableBodyRowCell>
|
||||
))}
|
||||
{props.tableLayout?.columnsResizable && !hasRightPinnedColumns ? (
|
||||
<DataGridTableFillBodyCell />
|
||||
) : null}
|
||||
</DataGridTableBodyRow>
|
||||
{row.getIsExpanded() && <DataGridTableBodyRowExpandded row={row} />}
|
||||
</Fragment>
|
||||
@@ -1090,16 +1234,16 @@ function DataGridTableRenderedRow<TData>({
|
||||
function DataGridTableEmpty() {
|
||||
const { table, props } = useDataGrid()
|
||||
const visibleColumnCount =
|
||||
table.getVisibleLeafColumns().length +
|
||||
getDataGridTableOrderedVisibleColumns(table).length +
|
||||
(props.tableLayout?.columnsResizable ? 1 : 0)
|
||||
|
||||
return (
|
||||
<tr>
|
||||
<td
|
||||
colSpan={Math.max(visibleColumnCount, 1)}
|
||||
className="text-muted-foreground text-sm py-6 text-center"
|
||||
className="text-muted-foreground py-6 text-center text-sm"
|
||||
>
|
||||
{props.emptyMessage || DATA_GRID_MESSAGES_RU.emptyMessage}
|
||||
{props.emptyMessage || "No data available"}
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
@@ -1110,9 +1254,9 @@ function DataGridTableLoader() {
|
||||
|
||||
return (
|
||||
<div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2">
|
||||
<div className="text-muted-foreground bg-card rounded-lg text-sm flex items-center gap-2 border px-4 py-2 leading-none font-medium">
|
||||
<div className="text-muted-foreground bg-card rounded-lg flex items-center gap-2 border px-4 py-2 text-sm leading-none font-medium">
|
||||
<Spinner className="size-5 opacity-60" />
|
||||
{props.loadingMessage || DATA_GRID_MESSAGES_RU.loadingMessage}
|
||||
{props.loadingMessage || "Loading..."}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -1124,7 +1268,7 @@ function DataGridTableRowPin<TData>({ row }: { row: Row<TData> }) {
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
aria-label={isPinned ? DATA_GRID_MESSAGES_RU.unpinRowLabel : DATA_GRID_MESSAGES_RU.pinRowLabel}
|
||||
aria-label={isPinned ? "Unpin row" : "Pin row"}
|
||||
onClick={() => {
|
||||
if (isPinned) {
|
||||
row.pin(false)
|
||||
@@ -1133,7 +1277,7 @@ function DataGridTableRowPin<TData>({ row }: { row: Row<TData> }) {
|
||||
}
|
||||
}}
|
||||
className={cn(
|
||||
"text-muted-foreground hover:text-foreground inline-flex size-7 items-center justify-center rounded-md transition-colors",
|
||||
"text-muted-foreground hover:text-foreground rounded-lg inline-flex size-7 items-center justify-center transition-colors",
|
||||
isPinned && "text-primary hover:text-primary/80"
|
||||
)}
|
||||
>
|
||||
@@ -1180,7 +1324,7 @@ function DataGridTableRowSelect<TData>({ row }: { row: Row<TData> }) {
|
||||
<Checkbox
|
||||
checked={row.getIsSelected()}
|
||||
onCheckedChange={(value) => row.toggleSelected(!!value)}
|
||||
aria-label={DATA_GRID_MESSAGES_RU.selectRowLabel}
|
||||
aria-label="Select row"
|
||||
className="align-[inherit]"
|
||||
/>
|
||||
</>
|
||||
@@ -1199,7 +1343,7 @@ function DataGridTableRowSelectAll() {
|
||||
indeterminate={isSomeSelected && !isAllSelected}
|
||||
disabled={isLoading || recordCount === 0}
|
||||
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
|
||||
aria-label={DATA_GRID_MESSAGES_RU.selectAllLabel}
|
||||
aria-label="Select all"
|
||||
className="align-[inherit]"
|
||||
/>
|
||||
)
|
||||
@@ -1210,15 +1354,31 @@ function DataGridTableBodyRows<TData>({ table }: { table: Table<TData> }) {
|
||||
const pagination = table.getState().pagination
|
||||
|
||||
if (isLoading && props.loadingMode === "skeleton" && pagination?.pageSize) {
|
||||
const leftVisibleColumns = table.getLeftVisibleLeafColumns()
|
||||
const centerVisibleColumns = table.getCenterVisibleLeafColumns()
|
||||
const rightVisibleColumns = table.getRightVisibleLeafColumns()
|
||||
const hasRightPinnedColumns = hasDataGridTableRightPinnedColumns(table)
|
||||
|
||||
return (
|
||||
<>
|
||||
{Array.from({ length: pagination.pageSize }).map((_, rowIndex) => (
|
||||
<DataGridTableBodyRowSkeleton key={rowIndex}>
|
||||
{table.getVisibleFlatColumns().map((column, colIndex) => (
|
||||
<DataGridTableBodyRowSkeletonCell column={column} key={colIndex}>
|
||||
{[...leftVisibleColumns, ...centerVisibleColumns].map((column) => (
|
||||
<DataGridTableBodyRowSkeletonCell column={column} key={column.id}>
|
||||
{column.columnDef.meta?.skeleton}
|
||||
</DataGridTableBodyRowSkeletonCell>
|
||||
))}
|
||||
{props.tableLayout?.columnsResizable && hasRightPinnedColumns ? (
|
||||
<DataGridTableFillBodyCell />
|
||||
) : null}
|
||||
{rightVisibleColumns.map((column) => (
|
||||
<DataGridTableBodyRowSkeletonCell column={column} key={column.id}>
|
||||
{column.columnDef.meta?.skeleton}
|
||||
</DataGridTableBodyRowSkeletonCell>
|
||||
))}
|
||||
{props.tableLayout?.columnsResizable && !hasRightPinnedColumns ? (
|
||||
<DataGridTableFillBodyCell />
|
||||
) : null}
|
||||
</DataGridTableBodyRowSkeleton>
|
||||
))}
|
||||
</>
|
||||
@@ -1250,7 +1410,7 @@ function DataGridTableBodyRows<TData>({ table }: { table: Table<TData> }) {
|
||||
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"
|
||||
></path>
|
||||
</svg>
|
||||
{props.loadingMessage || DATA_GRID_MESSAGES_RU.loadingMessage}
|
||||
{props.loadingMessage || "Loading..."}
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
@@ -1289,35 +1449,29 @@ const MemoizedDataGridTableBodyRows = memo(
|
||||
|
||||
function DataGridTableHeader<TData>() {
|
||||
const { table, props } = useDataGrid()
|
||||
const mergedHeaderGroups = getDataGridTableMergedHeaderGroups(table)
|
||||
const hasRightPinnedColumns = hasDataGridTableRightPinnedColumns(table)
|
||||
|
||||
return (
|
||||
<DataGridTableViewport>
|
||||
<DataGridTableBase>
|
||||
<DataGridTableHead>
|
||||
{table
|
||||
.getHeaderGroups()
|
||||
.map((headerGroup: HeaderGroup<TData>, index) => {
|
||||
return (
|
||||
<DataGridTableHeadRow headerGroup={headerGroup} key={index}>
|
||||
{headerGroup.headers.map((header, index) => {
|
||||
{mergedHeaderGroups.map((headerGroup) => {
|
||||
return (
|
||||
<DataGridTableHeadRow key={headerGroup.id} rowId={headerGroup.id}>
|
||||
{headerGroup.headers
|
||||
.filter((header) => header.column.getIsPinned() !== "right")
|
||||
.map((header) => {
|
||||
const { column } = header
|
||||
|
||||
return (
|
||||
<DataGridTableHeadRowCell header={header} key={index}>
|
||||
{header.isPlaceholder ? null : props.tableLayout
|
||||
?.columnsResizable && column.getCanResize() ? (
|
||||
<div className="truncate">
|
||||
{flexRender(
|
||||
<DataGridTableHeadRowCell header={header} key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)
|
||||
)}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
column.getCanResize() && (
|
||||
<DataGridTableHeadRowCellResize header={header} />
|
||||
@@ -1325,9 +1479,37 @@ function DataGridTableHeader<TData>() {
|
||||
</DataGridTableHeadRowCell>
|
||||
)
|
||||
})}
|
||||
</DataGridTableHeadRow>
|
||||
)
|
||||
})}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
hasRightPinnedColumns ? (
|
||||
<DataGridTableFillHeadCell />
|
||||
) : null}
|
||||
{headerGroup.headers
|
||||
.filter((header) => header.column.getIsPinned() === "right")
|
||||
.map((header) => {
|
||||
const { column } = header
|
||||
|
||||
return (
|
||||
<DataGridTableHeadRowCell header={header} key={header.id}>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
column.getCanResize() && (
|
||||
<DataGridTableHeadRowCellResize header={header} />
|
||||
)}
|
||||
</DataGridTableHeadRowCell>
|
||||
)
|
||||
})}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
!hasRightPinnedColumns ? (
|
||||
<DataGridTableFillHeadCell />
|
||||
) : null}
|
||||
</DataGridTableHeadRow>
|
||||
)
|
||||
})}
|
||||
</DataGridTableHead>
|
||||
</DataGridTableBase>
|
||||
</DataGridTableViewport>
|
||||
@@ -1342,36 +1524,36 @@ function DataGridTable<TData>({
|
||||
renderHeader?: boolean
|
||||
}) {
|
||||
const { table, props } = useDataGrid()
|
||||
const mergedHeaderGroups = getDataGridTableMergedHeaderGroups(table)
|
||||
const hasRightPinnedColumns = hasDataGridTableRightPinnedColumns(table)
|
||||
|
||||
return (
|
||||
<DataGridTableViewport>
|
||||
<DataGridTableBase>
|
||||
{renderHeader && (
|
||||
<DataGridTableHead>
|
||||
{table
|
||||
.getHeaderGroups()
|
||||
.map((headerGroup: HeaderGroup<TData>, index) => {
|
||||
return (
|
||||
<DataGridTableHeadRow headerGroup={headerGroup} key={index}>
|
||||
{headerGroup.headers.map((header, index) => {
|
||||
{mergedHeaderGroups.map((headerGroup) => {
|
||||
return (
|
||||
<DataGridTableHeadRow
|
||||
key={headerGroup.id}
|
||||
rowId={headerGroup.id}
|
||||
>
|
||||
{headerGroup.headers
|
||||
.filter((header) => header.column.getIsPinned() !== "right")
|
||||
.map((header) => {
|
||||
const { column } = header
|
||||
|
||||
return (
|
||||
<DataGridTableHeadRowCell header={header} key={index}>
|
||||
{header.isPlaceholder ? null : props.tableLayout
|
||||
?.columnsResizable && column.getCanResize() ? (
|
||||
<div className="truncate">
|
||||
{flexRender(
|
||||
<DataGridTableHeadRowCell
|
||||
header={header}
|
||||
key={header.id}
|
||||
>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
</div>
|
||||
) : (
|
||||
flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)
|
||||
)}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
column.getCanResize() && (
|
||||
<DataGridTableHeadRowCellResize header={header} />
|
||||
@@ -1379,9 +1561,40 @@ function DataGridTable<TData>({
|
||||
</DataGridTableHeadRowCell>
|
||||
)
|
||||
})}
|
||||
</DataGridTableHeadRow>
|
||||
)
|
||||
})}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
hasRightPinnedColumns ? (
|
||||
<DataGridTableFillHeadCell />
|
||||
) : null}
|
||||
{headerGroup.headers
|
||||
.filter((header) => header.column.getIsPinned() === "right")
|
||||
.map((header) => {
|
||||
const { column } = header
|
||||
|
||||
return (
|
||||
<DataGridTableHeadRowCell
|
||||
header={header}
|
||||
key={header.id}
|
||||
>
|
||||
{header.isPlaceholder
|
||||
? null
|
||||
: flexRender(
|
||||
header.column.columnDef.header,
|
||||
header.getContext()
|
||||
)}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
column.getCanResize() && (
|
||||
<DataGridTableHeadRowCellResize header={header} />
|
||||
)}
|
||||
</DataGridTableHeadRowCell>
|
||||
)
|
||||
})}
|
||||
{props.tableLayout?.columnsResizable &&
|
||||
!hasRightPinnedColumns ? (
|
||||
<DataGridTableFillHeadCell />
|
||||
) : null}
|
||||
</DataGridTableHeadRow>
|
||||
)
|
||||
})}
|
||||
</DataGridTableHead>
|
||||
)}
|
||||
|
||||
@@ -1413,6 +1626,8 @@ export {
|
||||
DataGridTableBodyRowSkeleton,
|
||||
DataGridTableBodyRowSkeletonCell,
|
||||
DataGridTableEmpty,
|
||||
DataGridTableFillBodyCell,
|
||||
DataGridTableFillHeadCell,
|
||||
DataGridTableFoot,
|
||||
DataGridTableFootRow,
|
||||
DataGridTableFootRowCell,
|
||||
@@ -1427,8 +1642,11 @@ export {
|
||||
DataGridTableRowSelectAll,
|
||||
DataGridTableRowSpacer,
|
||||
DataGridTableViewport,
|
||||
getDataGridTableMergedHeaderGroups,
|
||||
getPinningStyles,
|
||||
getDataGridTableResolvedRows,
|
||||
getDataGridTableRowSections,
|
||||
hasDataGridTableRightPinnedColumns,
|
||||
}
|
||||
|
||||
export type { DataGridTablePinnedBoundary }
|
||||
Reference in New Issue
Block a user