From 4613810969e6a787d66d447a781c50a3f44f5004 Mon Sep 17 00:00:00 2001 From: DanisAvko Date: Thu, 12 Sep 2024 17:42:17 +0300 Subject: [PATCH] fix(BaseTable): calc aria-rowindex fixed --- src/components/BaseTable/BaseTable.tsx | 15 ++++-- .../__stories__/BaseTable.stories.tsx | 5 ++ .../GroupingWithVirtualizationStory.tsx | 54 +++++++++++++++++++ src/utils/getAriaRowIndexMap.ts | 20 +++++++ src/utils/index.ts | 1 + src/utils/shouldRenderFooterRow.ts | 2 +- 6 files changed, 93 insertions(+), 4 deletions(-) create mode 100644 src/components/BaseTable/__stories__/stories/GroupingWithVirtualizationStory.tsx create mode 100644 src/utils/getAriaRowIndexMap.ts diff --git a/src/components/BaseTable/BaseTable.tsx b/src/components/BaseTable/BaseTable.tsx index 5ddccf3..5feafd2 100644 --- a/src/components/BaseTable/BaseTable.tsx +++ b/src/components/BaseTable/BaseTable.tsx @@ -3,7 +3,12 @@ import React from 'react'; import type {Row, Table} from '@tanstack/react-table'; import type {VirtualItem, Virtualizer} from '@tanstack/react-virtual'; -import {getAriaMultiselectable, getCellClassModes, shouldRenderFooterRow} from '../../utils'; +import { + getAriaMultiselectable, + getAriaRowIndexMap, + getCellClassModes, + shouldRenderFooterRow, +} from '../../utils'; import {BaseDraggableRow} from '../BaseDraggableRow'; import type {BaseFooterRowProps} from '../BaseFooterRow'; import {BaseFooterRow} from '../BaseFooterRow'; @@ -145,12 +150,16 @@ export const BaseTable = React.forwardRef( const {rows} = table.getRowModel(); + const ariaRowIndexMap = React.useMemo(() => { + return getAriaRowIndexMap(rows); + }, [rows]); + const headerGroups = withHeader && table.getHeaderGroups(); const footerGroups = withFooter && table.getFooterGroups(); const colCount = table.getVisibleLeafColumns().length; const headerRowCount = headerGroups ? headerGroups.length : 0; - const bodyRowCount = rows.length; + const bodyRowCount = Object.keys(ariaRowIndexMap).length; const footerRowCount = footerGroups ? footerGroups.length : 0; const rowCount = bodyRowCount + headerRowCount + footerRowCount; @@ -195,7 +204,7 @@ export const BaseTable = React.forwardRef( rowVirtualizer, table, virtualItem: rowVirtualizer ? (virtualItemOrRow as VirtualItem) : undefined, - 'aria-rowindex': headerRowCount + row.index + 1, + 'aria-rowindex': headerRowCount + ariaRowIndexMap[row.id], 'aria-selected': table.options.enableRowSelection ? row.getIsSelected() : undefined, diff --git a/src/components/BaseTable/__stories__/BaseTable.stories.tsx b/src/components/BaseTable/__stories__/BaseTable.stories.tsx index 729282c..604cbc8 100644 --- a/src/components/BaseTable/__stories__/BaseTable.stories.tsx +++ b/src/components/BaseTable/__stories__/BaseTable.stories.tsx @@ -8,6 +8,7 @@ import {EmptyContentStory} from './stories/EmptyContentStory'; import {GroupingStory} from './stories/GroupingStory'; import {GroupingStory2} from './stories/GroupingStory2'; import {GroupingWithSelectionStory} from './stories/GroupingWithSelectionStory'; +import {GroupingWithVirtualizationStory} from './stories/GroupingWithVirtualizationStory'; import {HeaderGroupsStory} from './stories/HeaderGroupsStory'; import {ReorderingStory} from './stories/ReorderingStory'; import {ReorderingTreeStory} from './stories/ReorderingTreeStory'; @@ -85,6 +86,10 @@ export const WindowVirtualization: StoryObj = render: WindowVirtualizationStory, }; +export const GroupingWithVirtualization: StoryObj = { + render: GroupingWithVirtualizationStory, +}; + export const ReorderingWithVirtualization: StoryObj = { render: ReorderingWithVirtualizationStory, }; diff --git a/src/components/BaseTable/__stories__/stories/GroupingWithVirtualizationStory.tsx b/src/components/BaseTable/__stories__/stories/GroupingWithVirtualizationStory.tsx new file mode 100644 index 0000000..44cb9b6 --- /dev/null +++ b/src/components/BaseTable/__stories__/stories/GroupingWithVirtualizationStory.tsx @@ -0,0 +1,54 @@ +import React from 'react'; + +import type {ExpandedState, Row} from '@tanstack/react-table'; + +import {useTable, useWindowRowVirtualizer} from '../../../../hooks'; +import {BaseTable} from '../../BaseTable'; +import {columns} from '../constants/columns'; +import type {Item} from '../types'; +import {generateData} from '../utils'; + +import {cnVirtualizationStory} from './VirtualizationStory.classname'; + +const data = generateData(300); +const grouping: Array = ['status', 'age']; + +import './VirtualizationStory.scss'; + +const getGroupTitle = (row: Row) => row.getValue('name'); +const getIsGroupHeaderRow = (row: Row) => row.getIsGrouped(); + +export const GroupingWithVirtualizationStory = () => { + const [expanded, setExpanded] = React.useState({}); + + const table = useTable({ + columns, + data, + getRowId: (item) => item.id, + enableExpanding: true, + enableGrouping: true, + onExpandedChange: setExpanded, + state: { + expanded, + grouping, + }, + }); + + const rowVirtualizer = useWindowRowVirtualizer({ + count: table.getRowModel().rows.length, + estimateSize: () => 20, + overscan: 5, + }); + + return ( + + ); +}; diff --git a/src/utils/getAriaRowIndexMap.ts b/src/utils/getAriaRowIndexMap.ts new file mode 100644 index 0000000..f306be0 --- /dev/null +++ b/src/utils/getAriaRowIndexMap.ts @@ -0,0 +1,20 @@ +import type {Row} from '@tanstack/react-table'; + +export const getAriaRowIndexMap = (rows: Row[]) => { + let rowIndex = 1; + + return rows.reduce>((acc, row, index, arr) => { + const newMap = { + ...acc, + [row.id]: rowIndex, + }; + + const nextRow = arr[index + 1]; + if (nextRow?.parentId !== row.id) { + rowIndex += row.getLeafRows().length; + } + rowIndex++; + + return newMap; + }, {}); +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index e377fc8..aa3d3f6 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,5 +1,6 @@ export * from './cn'; export * from './getAriaMultiselectable'; +export * from './getAriaRowIndexMap'; export * from './getAriaSort'; export * from './getCellClassModes'; export * from './getCellStyles'; diff --git a/src/utils/shouldRenderFooterRow.ts b/src/utils/shouldRenderFooterRow.ts index 069d475..a308384 100644 --- a/src/utils/shouldRenderFooterRow.ts +++ b/src/utils/shouldRenderFooterRow.ts @@ -1,5 +1,5 @@ import type {HeaderGroup} from '@tanstack/react-table'; export const shouldRenderFooterRow = (footerGroup: HeaderGroup) => { - return footerGroup.headers.every((header) => !header.column.columnDef.footer); + return footerGroup.headers.some((header) => header.column.columnDef.footer); };