From d02abcc385de65f6d66be4d0bc927cffae4d14d6 Mon Sep 17 00:00:00 2001 From: Kevin Van Cott Date: Mon, 26 Feb 2024 02:59:35 -0600 Subject: [PATCH] refactor column info stuff --- .../pages/changelog.mdx | 8 +++ .../pages/docs/getting-started/install.mdx | 2 +- .../docs/getting-started/migrating-to-v2.mdx | 2 + packages/material-react-table/README.md | 51 +++++++++++-------- packages/material-react-table/package.json | 6 +-- .../src/components/body/MRT_TableBodyCell.tsx | 4 +- .../src/components/head/MRT_TableHead.tsx | 22 ++++---- .../src/components/head/MRT_TableHeadCell.tsx | 22 ++------ .../head/MRT_TableHeadCellFilterContainer.tsx | 18 ++----- .../head/MRT_TableHeadCellFilterLabel.tsx | 18 +++---- .../inputs/MRT_FilterRangeFields.tsx | 4 -- .../components/inputs/MRT_FilterTextField.tsx | 12 +++-- .../src/utils/column.utils.ts | 48 ++++++++++------- .../features/Virtualization.stories.tsx | 5 +- 14 files changed, 114 insertions(+), 108 deletions(-) diff --git a/apps/material-react-table-docs/pages/changelog.mdx b/apps/material-react-table-docs/pages/changelog.mdx index 5bd315dc7..4e6396be1 100644 --- a/apps/material-react-table-docs/pages/changelog.mdx +++ b/apps/material-react-table-docs/pages/changelog.mdx @@ -7,6 +7,14 @@ import Head from 'next/head'; ## MRT V2 Changelog +> Note: As of v2.12.0, the React and ReactDom peer dependencies have been moved back down to React v17 in order to help more people upgrade to MRT v2 without having to upgrade to React v18. + +### Version 2.12.0 - 2024-02-26 + +- **Marked React 17 as a peer dependency instead of React 18 since concurrent features are not yet being utilized under the hood in MRT** +- Filter label tooltip will show label instead of value when a label is provided to filterSelectOptions +- Fixed Column and Row Dragging element animation to not go back to where it started when dragging + ### Version 2.11.3 - 2024-02-14 - Upgraded to TanStack Table v8.12.0 for new column pinning/sizing/pinning instance APIs and better column resizing performance diff --git a/apps/material-react-table-docs/pages/docs/getting-started/install.mdx b/apps/material-react-table-docs/pages/docs/getting-started/install.mdx index cba37103b..de2626c6e 100644 --- a/apps/material-react-table-docs/pages/docs/getting-started/install.mdx +++ b/apps/material-react-table-docs/pages/docs/getting-started/install.mdx @@ -20,7 +20,7 @@ import { FAQs } from '../../../components/mdx/FAQs'; > 3. `@mui/icons-material` (v5) > 4. `@emotion/react` (v11) > 5. `@emotion/styled` (v11) -> 6. `react` and `react-dom` (v18) - (MRT v2 will eventually use React 18 concurrent mode) +> 6. `react` and `react-dom` (v17+) ### Quick Install diff --git a/apps/material-react-table-docs/pages/docs/getting-started/migrating-to-v2.mdx b/apps/material-react-table-docs/pages/docs/getting-started/migrating-to-v2.mdx index d6a1ff9e1..1060e7015 100644 --- a/apps/material-react-table-docs/pages/docs/getting-started/migrating-to-v2.mdx +++ b/apps/material-react-table-docs/pages/docs/getting-started/migrating-to-v2.mdx @@ -15,6 +15,8 @@ import { InstallCommand } from '../../../components/mdx/InstallCommand'; This should be an easy to moderate upgrade for most developers. The only breaking changes have to do with the removed `tableInstanceRef`, some renamed props/options, and new column sizing behaviors. +> Note: As of v2.12.0, the React and ReactDom peer dependencies have been moved back down to React v17 in order to help more people upgrade to MRT v2 without having to upgrade to React v18. + ### New Feature Highlights 1. New optional but recommended `useMaterialReactTable` hook that allows you to create the `table` instance in your own scope diff --git a/packages/material-react-table/README.md b/packages/material-react-table/README.md index d7bec35ec..9ed179712 100644 --- a/packages/material-react-table/README.md +++ b/packages/material-react-table/README.md @@ -16,9 +16,6 @@ View [Documentation](https://www.material-react-table.com/) - - - + + + ## About ### _Quickly Create React Data Tables with Material Design_ -### __Built with [Material UI V5](https://mui.com) and [TanStack Table V8](https://tanstack.com/table/v8)__ +### **Built with [Material UI V5](https://mui.com) and [TanStack Table V8](https://tanstack.com/table/v8)** -MRT +MRT > Want to use Mantine instead of Material UI? Check out [Mantine React Table](https://www.mantine-react-table.com) @@ -46,19 +50,19 @@ View [Documentation](https://www.material-react-table.com/) ### Quick Examples - - [Basic Table](https://www.material-react-table.com/docs/examples/basic/) (See Default Features) - - [Minimal Table](https://www.material-react-table.com/docs/examples/minimal/) (Turn off Features like Pagination, Sorting, Filtering, and Toolbars) - - [Advanced Table](https://www.material-react-table.com/docs/examples/advanced/) (See some of the Advanced Features) - - [Custom Headless Table](https://www.material-react-table.com/docs/examples/custom-headless/) (Build your own table markup) - - [Dragging / Ordering Examples](https://www.material-react-table.com/docs/examples/column-ordering/) (Drag and Drop) - - [Editing (CRUD) Examples](https://www.material-react-table.com/docs/examples/editing-crud/) (Create, Edit, and Delete Rows) - - [Expanding / Grouping Examples](https://www.material-react-table.com/docs/examples/aggregation-and-grouping/) (Sum, Average, Count, etc.) - - [Filtering Examples](https://www.material-react-table.com/docs/examples/filter-variants/) (Faceted Values, Switching Filters, etc.) - - [Sticky Pinning Examples](https://www.material-react-table.com/docs/examples/sticky-header/) (Sticky Headers, Sticky Columns, Sticky Rows, etc.) - - [Remote Data Fetching Examples](https://www.material-react-table.com/docs/examples/react-query/) (Server-side Pagination, Sorting, and Filtering) - - [Virtualized Examples](https://www.material-react-table.com/docs/examples/virtualized/) (10,000 rows at once!) - - [Infinite Scrolling](https://www.material-react-table.com/docs/examples/infinite-scrolling/) (Fetch data as you scroll) - - [Localization (i18n)](https://www.material-react-table.com/docs/guides/localization#built-in-locale-examples) (Over a dozen languages built-in) +- [Basic Table](https://www.material-react-table.com/docs/examples/basic/) (See Default Features) +- [Minimal Table](https://www.material-react-table.com/docs/examples/minimal/) (Turn off Features like Pagination, Sorting, Filtering, and Toolbars) +- [Advanced Table](https://www.material-react-table.com/docs/examples/advanced/) (See some of the Advanced Features) +- [Custom Headless Table](https://www.material-react-table.com/docs/examples/custom-headless/) (Build your own table markup) +- [Dragging / Ordering Examples](https://www.material-react-table.com/docs/examples/column-ordering/) (Drag and Drop) +- [Editing (CRUD) Examples](https://www.material-react-table.com/docs/examples/editing-crud/) (Create, Edit, and Delete Rows) +- [Expanding / Grouping Examples](https://www.material-react-table.com/docs/examples/aggregation-and-grouping/) (Sum, Average, Count, etc.) +- [Filtering Examples](https://www.material-react-table.com/docs/examples/filter-variants/) (Faceted Values, Switching Filters, etc.) +- [Sticky Pinning Examples](https://www.material-react-table.com/docs/examples/sticky-header/) (Sticky Headers, Sticky Columns, Sticky Rows, etc.) +- [Remote Data Fetching Examples](https://www.material-react-table.com/docs/examples/react-query/) (Server-side Pagination, Sorting, and Filtering) +- [Virtualized Examples](https://www.material-react-table.com/docs/examples/virtualized/) (10,000 rows at once!) +- [Infinite Scrolling](https://www.material-react-table.com/docs/examples/infinite-scrolling/) (Fetch data as you scroll) +- [Localization (i18n)](https://www.material-react-table.com/docs/guides/localization#built-in-locale-examples) (Over a dozen languages built-in) View additional [storybook examples](https://www.material-react-table.dev/) @@ -68,7 +72,7 @@ _All features can easily be enabled/disabled_ _**Fully Fleshed out [Docs](https://www.material-react-table.com/docs/guides#guides) are available for all features**_ -- [x] 30-54kb gzipped - [Bundlephobia](https://bundlephobia.com/package/material-react-table) +- [x] 30-56kb gzipped - [Bundlephobia](https://bundlephobia.com/package/material-react-table) - [x] Advanced TypeScript Generics Support (TypeScript Optional) - [x] Aggregation and Grouping (Sum, Average, Count, etc.) - [x] Cell Actions (Right-click Context Menu) @@ -132,7 +136,10 @@ npm install material-react-table ```jsx import { useMemo, useState, useEffect } from 'react'; -import { MaterialReactTable, useMaterialReactTable } from 'material-react-table'; +import { + MaterialReactTable, + useMaterialReactTable, +} from 'material-react-table'; //data must be stable reference (useState, useMemo, useQuery, defined outside of component, etc.) const data = [ @@ -144,7 +151,7 @@ const data = [ name: 'Sara', age: 25, }, -] +]; export default function App() { const columns = useMemo( @@ -185,7 +192,7 @@ export default function App() { const someEventHandler = () => { //read the table state during an event from the table instance console.log(table.getState().sorting); - } + }; return ( //other more lightweight MRT sub components also available diff --git a/packages/material-react-table/package.json b/packages/material-react-table/package.json index a389dafae..b21edc347 100644 --- a/packages/material-react-table/package.json +++ b/packages/material-react-table/package.json @@ -1,5 +1,5 @@ { - "version": "2.11.3", + "version": "2.12.0", "license": "MIT", "name": "material-react-table", "description": "A fully featured Material UI V5 implementation of TanStack React Table V8, written from the ground up in TypeScript.", @@ -111,8 +111,8 @@ "@mui/icons-material": ">=5.11", "@mui/material": ">=5.13", "@mui/x-date-pickers": ">=6.15.0", - "react": ">=18.0", - "react-dom": ">=18.0" + "react": ">=17.0", + "react-dom": ">=17.0" }, "dependencies": { "@tanstack/match-sorter-utils": "8.11.8", diff --git a/packages/material-react-table/src/components/body/MRT_TableBodyCell.tsx b/packages/material-react-table/src/components/body/MRT_TableBodyCell.tsx index f8fe024cf..fec561c59 100644 --- a/packages/material-react-table/src/components/body/MRT_TableBodyCell.tsx +++ b/packages/material-react-table/src/components/body/MRT_TableBodyCell.tsx @@ -211,7 +211,9 @@ export const MRT_TableBodyCell = ({ }; const handleDragOver = (e: DragEvent) => { - e.preventDefault(); + if (columnDef.enableColumnOrdering !== false) { + e.preventDefault(); + } }; const handleContextMenu = (e: MouseEvent) => { diff --git a/packages/material-react-table/src/components/head/MRT_TableHead.tsx b/packages/material-react-table/src/components/head/MRT_TableHead.tsx index 1f6d74b5a..dbb2e60ff 100644 --- a/packages/material-react-table/src/components/head/MRT_TableHead.tsx +++ b/packages/material-react-table/src/components/head/MRT_TableHead.tsx @@ -20,8 +20,6 @@ export const MRT_TableHead = ({ ...rest }: MRT_TableHeadProps) => { const { - getHeaderGroups, - getSelectedRowModel, getState, options: { enableStickyHeader, @@ -60,7 +58,7 @@ export const MRT_TableHead = ({ })} > {positionToolbarAlertBanner === 'head-overlay' && - (showAlertBanner || getSelectedRowModel().rows.length > 0) ? ( + (showAlertBanner || table.getSelectedRowModel().rows.length > 0) ? ( ({ ) : ( - getHeaderGroups().map((headerGroup) => ( - - )) + table + .getHeaderGroups() + .map((headerGroup) => ( + + )) )} ); diff --git a/packages/material-react-table/src/components/head/MRT_TableHeadCell.tsx b/packages/material-react-table/src/components/head/MRT_TableHeadCell.tsx index 0f83a756f..0ea0cbf88 100644 --- a/packages/material-react-table/src/components/head/MRT_TableHeadCell.tsx +++ b/packages/material-react-table/src/components/head/MRT_TableHeadCell.tsx @@ -15,7 +15,6 @@ import { type MRT_RowData, type MRT_TableInstance, } from '../../types'; -import { useColumnFilterInfo } from '../../utils/column.utils'; import { getCommonMRTCellStyles } from '../../utils/style.utils'; import { parseFromValuesOrFunc } from '../../utils/utils'; @@ -75,11 +74,6 @@ export const MRT_TableHeadCell = ({ ...rest, }; - const columnFilterInfo = useColumnFilterInfo({ - header, - table, - }); - const isColumnPinned = enableColumnPinning && columnDef.columnDefType !== 'group' && @@ -148,7 +142,9 @@ export const MRT_TableHeadCell = ({ }; const handleDragOver = (e: DragEvent) => { - e.preventDefault(); + if (columnDef.enableColumnOrdering !== false) { + e.preventDefault(); + } }; const HeaderElement = @@ -282,11 +278,7 @@ export const MRT_TableHeadCell = ({ {HeaderElement} {column.getCanFilter() && ( - + )} {column.getCanSort() && ( @@ -322,11 +314,7 @@ export const MRT_TableHeadCell = ({ )} {columnFilterDisplayMode === 'subheader' && column.getCanFilter() && ( - + )} ); diff --git a/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterContainer.tsx b/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterContainer.tsx index b8d3c92af..47075ae89 100644 --- a/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterContainer.tsx +++ b/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterContainer.tsx @@ -4,7 +4,7 @@ import { type MRT_RowData, type MRT_TableInstance, } from '../../types'; -import { type ColumnFilterInfo } from '../../utils/column.utils'; +import { getColumnFilterInfo } from '../../utils/column.utils'; import { MRT_FilterCheckbox } from '../inputs/MRT_FilterCheckbox'; import { MRT_FilterRangeFields } from '../inputs/MRT_FilterRangeFields'; import { MRT_FilterRangeSlider } from '../inputs/MRT_FilterRangeSlider'; @@ -13,13 +13,11 @@ import { MRT_FilterTextField } from '../inputs/MRT_FilterTextField'; export interface MRT_TableHeadCellFilterContainerProps< TData extends MRT_RowData, > extends CollapseProps { - columnFilterInfo: ColumnFilterInfo; header: MRT_Header; table: MRT_TableInstance; } export const MRT_TableHeadCellFilterContainer = ({ - columnFilterInfo, header, table, ...rest @@ -31,7 +29,7 @@ export const MRT_TableHeadCellFilterContainer = ({ const { showColumnFilters } = getState(); const { column } = header; const { columnDef } = column; - const { isRangeFilter } = columnFilterInfo; + const { isRangeFilter } = getColumnFilterInfo({ header, table }); return ( ({ ) : columnDef.filterVariant === 'range-slider' ? ( ) : isRangeFilter ? ( - + ) : ( - + )} ); diff --git a/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterLabel.tsx b/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterLabel.tsx index 90a8b1bce..d28c03443 100644 --- a/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterLabel.tsx +++ b/packages/material-react-table/src/components/head/MRT_TableHeadCellFilterLabel.tsx @@ -10,18 +10,19 @@ import { type MRT_RowData, type MRT_TableInstance, } from '../../types'; -import { type ColumnFilterInfo } from '../../utils/column.utils'; +import { + getColumnFilterInfo, + useDropdownOptions, +} from '../../utils/column.utils'; import { getValueAndLabel, parseFromValuesOrFunc } from '../../utils/utils'; export interface MRT_TableHeadCellFilterLabelProps extends IconButtonProps { - columnFilterInfo: ColumnFilterInfo; header: MRT_Header; table: MRT_TableInstance; } export const MRT_TableHeadCellFilterLabel = ({ - columnFilterInfo, header, table, ...rest @@ -44,11 +45,12 @@ export const MRT_TableHeadCellFilterLabel = ({ const { currentFilterOption, - dropdownOptions, isMultiSelectFilter, isRangeFilter, isSelectFilter, - } = columnFilterInfo; + } = getColumnFilterInfo({ header, table }); + + const dropdownOptions = useDropdownOptions({ header, table }); const getSelectLabel = (index?: number) => getValueAndLabel( @@ -169,11 +171,7 @@ export const MRT_TableHeadCellFilterLabel = ({ }} > - + )} diff --git a/packages/material-react-table/src/components/inputs/MRT_FilterRangeFields.tsx b/packages/material-react-table/src/components/inputs/MRT_FilterRangeFields.tsx index 5279c2cc4..4251fcef8 100644 --- a/packages/material-react-table/src/components/inputs/MRT_FilterRangeFields.tsx +++ b/packages/material-react-table/src/components/inputs/MRT_FilterRangeFields.tsx @@ -5,18 +5,15 @@ import { type MRT_RowData, type MRT_TableInstance, } from '../../types'; -import { type ColumnFilterInfo } from '../../utils/column.utils'; import { parseFromValuesOrFunc } from '../../utils/utils'; export interface MRT_FilterRangeFieldsProps extends BoxProps { - columnFilterInfo: ColumnFilterInfo; header: MRT_Header; table: MRT_TableInstance; } export const MRT_FilterRangeFields = ({ - columnFilterInfo, header, table, ...rest @@ -33,7 +30,6 @@ export const MRT_FilterRangeFields = ({ > {[0, 1].map((rangeFilterIndex) => ( extends TextFieldProps<'standard'> { - columnFilterInfo: ColumnFilterInfo; header: MRT_Header; rangeFilterIndex?: number; table: MRT_TableInstance; } export const MRT_FilterTextField = ({ - columnFilterInfo, header, rangeFilterIndex, table, @@ -116,7 +117,6 @@ export const MRT_FilterTextField = ({ const { allowedColumnFilterOptions, currentFilterOption, - dropdownOptions, facetedUniqueValues, isAutocompleteFilter, isDateFilter, @@ -124,7 +124,9 @@ export const MRT_FilterTextField = ({ isRangeFilter, isSelectFilter, isTextboxFilter, - } = columnFilterInfo; + } = getColumnFilterInfo({ header, table }); + + const dropdownOptions = useDropdownOptions({ header, table }); const filterChipLabel = ['empty', 'notEmpty'].includes(currentFilterOption) ? //@ts-ignore diff --git a/packages/material-react-table/src/utils/column.utils.ts b/packages/material-react-table/src/utils/column.utils.ts index 42a0ba915..8ee7b743a 100644 --- a/packages/material-react-table/src/utils/column.utils.ts +++ b/packages/material-react-table/src/utils/column.utils.ts @@ -126,9 +126,7 @@ export const getDefaultColumnFilterFn = ( return 'fuzzy'; }; -export type ColumnFilterInfo = ReturnType; - -export const useColumnFilterInfo = ({ +export const getColumnFilterInfo = ({ header, table, }: { @@ -163,7 +161,36 @@ export const useColumnFilterInfo = ({ const facetedUniqueValues = column.getFacetedUniqueValues(); - const dropdownOptions = useMemo( + return { + allowedColumnFilterOptions, + currentFilterOption, + facetedUniqueValues, + isAutocompleteFilter, + isDateFilter, + isMultiSelectFilter, + isRangeFilter, + isSelectFilter, + isTextboxFilter, + } as const; +}; + +export const useDropdownOptions = ({ + header, + table, +}: { + header: MRT_Header; + table: MRT_TableInstance; +}): DropdownOption[] | undefined => { + const { column } = header; + const { columnDef } = column; + const { + facetedUniqueValues, + isAutocompleteFilter, + isMultiSelectFilter, + isSelectFilter, + } = getColumnFilterInfo({ header, table }); + + return useMemo( () => columnDef.filterSelectOptions ?? ((isSelectFilter || isMultiSelectFilter || isAutocompleteFilter) && @@ -179,17 +206,4 @@ export const useColumnFilterInfo = ({ isSelectFilter, ], ); - - return { - allowedColumnFilterOptions, - currentFilterOption, - dropdownOptions, - facetedUniqueValues, - isAutocompleteFilter, - isDateFilter, - isMultiSelectFilter, - isRangeFilter, - isSelectFilter, - isTextboxFilter, - } as const; }; diff --git a/packages/material-react-table/stories/features/Virtualization.stories.tsx b/packages/material-react-table/stories/features/Virtualization.stories.tsx index 740f55035..674273e11 100644 --- a/packages/material-react-table/stories/features/Virtualization.stories.tsx +++ b/packages/material-react-table/stories/features/Virtualization.stories.tsx @@ -73,7 +73,7 @@ const longColumns: MRT_ColumnDef[] = [ }, ]; -const longData = [...Array(500)].map(() => ({ +const longData = [...Array(1000)].map(() => ({ address: faker.location.streetAddress(), city: faker.location.city(), country: faker.location.country(), @@ -107,7 +107,6 @@ export const EnableRowVirtualizationComfortable = () => ( data={longData} enableBottomToolbar={false} enablePagination={false} - enableRowNumbers enableRowVirtualization /> ); @@ -118,7 +117,6 @@ export const EnableRowVirtualizationSpacious = () => ( data={longData} enableBottomToolbar={false} enablePagination={false} - enableRowNumbers enableRowVirtualization initialState={{ density: 'spacious' }} /> @@ -129,6 +127,7 @@ export const EnableRowVirtualizationTallContent = () => ( columns={longColumns} data={longData} enableBottomToolbar={false} + enableColumnResizing enablePagination={false} enableRowNumbers enableRowVirtualization