diff --git a/packages/mantine-react-table/src/hooks/useMRT_DisplayColumns.tsx b/packages/mantine-react-table/src/hooks/useMRT_DisplayColumns.tsx index c7841e284..6174dfe59 100644 --- a/packages/mantine-react-table/src/hooks/useMRT_DisplayColumns.tsx +++ b/packages/mantine-react-table/src/hooks/useMRT_DisplayColumns.tsx @@ -6,12 +6,14 @@ import { MRT_ExpandAllButton } from '../buttons/MRT_ExpandAllButton'; import { MRT_ExpandButton } from '../buttons/MRT_ExpandButton'; import { MRT_ToggleRowActionMenuButton } from '../buttons/MRT_ToggleRowActionMenuButton'; import { MRT_SelectCheckbox } from '../inputs/MRT_SelectCheckbox'; -import { - type MRT_ColumnDef, - type MRT_ColumnOrderState, - type MRT_GroupingState, - type MRT_DefinedTableOptions, - type MRT_Row, +import type { + MRT_ColumnDef, + MRT_ColumnOrderState, + MRT_DefinedTableOptions, + MRT_DisplayColumnIds, + MRT_GroupingState, + MRT_Localization, + MRT_Row, } from '../types'; interface Params = {}> { @@ -21,135 +23,168 @@ interface Params = {}> { tableOptions: MRT_DefinedTableOptions; } -export const useMRT_DisplayColumns = = {}>({ - creatingRow, - columnOrder, - grouping, - tableOptions, -}: Params) => { - return useMemo( - () => - ( - [ - (tableOptions.state?.columnOrder ?? columnOrder).includes( - 'mrt-row-pin', - ) && { - Cell: ({ row, table }) => ( - - ), - header: tableOptions.localization.pin, - size: 60, - ...tableOptions.defaultDisplayColumn, - ...tableOptions.displayColumnDefOptions?.['mrt-row-pin'], - id: 'mrt-row-pin', - }, - (tableOptions.state?.columnOrder ?? columnOrder).includes( - 'mrt-row-drag', - ) && { - Cell: ({ row, rowRef, table }) => ( - } - table={table} - /> - ), - header: tableOptions.localization.move, - size: 60, - ...tableOptions.defaultDisplayColumn, - ...tableOptions.displayColumnDefOptions?.['mrt-row-drag'], - id: 'mrt-row-drag', - }, - ((tableOptions.state?.columnOrder ?? columnOrder).includes( - 'mrt-row-actions', - ) || - (creatingRow && tableOptions.createDisplayMode === 'row')) && { - Cell: ({ cell, row, table }) => ( - - ), - header: tableOptions.localization.actions, - size: 70, - ...tableOptions.defaultDisplayColumn, - ...tableOptions.displayColumnDefOptions?.['mrt-row-actions'], - id: 'mrt-row-actions', - }, - (tableOptions.state?.columnOrder ?? columnOrder).includes( - 'mrt-row-expand', - ) && - showExpandColumn( - tableOptions, - tableOptions.state?.grouping ?? grouping, - ) && { - Cell: ({ row, table }) => ( - - ), - Header: tableOptions.enableExpandAll - ? ({ table }) => - : null, - header: tableOptions.localization.expand, - size: 60, - ...tableOptions.defaultDisplayColumn, - ...tableOptions.displayColumnDefOptions?.['mrt-row-expand'], - id: 'mrt-row-expand', - }, - (tableOptions.state?.columnOrder ?? columnOrder).includes( - 'mrt-row-select', - ) && { - Cell: ({ row, table }) => ( - - ), - Header: - tableOptions.enableSelectAll && - tableOptions.enableMultiRowSelection - ? ({ table }) => - : null, - header: tableOptions.localization.select, - size: 60, - ...tableOptions.defaultDisplayColumn, - ...tableOptions.displayColumnDefOptions?.['mrt-row-select'], - id: 'mrt-row-select', - }, - (tableOptions.state?.columnOrder ?? columnOrder).includes( - 'mrt-row-numbers', - ) && { - Cell: ({ row }) => row.index + 1, - Header: () => tableOptions.localization.rowNumber, - header: tableOptions.localization.rowNumbers, - size: 60, - ...tableOptions.defaultDisplayColumn, - ...tableOptions.displayColumnDefOptions?.['mrt-row-numbers'], - id: 'mrt-row-numbers', - }, - ] as MRT_ColumnDef[] - ).filter(Boolean), - [ - columnOrder, - grouping, - tableOptions.displayColumnDefOptions, - tableOptions.editDisplayMode, - tableOptions.enableColumnDragging, - tableOptions.enableColumnFilterModes, - tableOptions.enableColumnOrdering, - tableOptions.enableEditing, - tableOptions.enableExpandAll, - tableOptions.enableExpanding, - tableOptions.enableGrouping, - tableOptions.enableRowActions, - tableOptions.enableRowDragging, - tableOptions.enableRowNumbers, - tableOptions.enableRowOrdering, - tableOptions.enableRowSelection, - tableOptions.enableSelectAll, - tableOptions.localization, - tableOptions.positionActionsColumn, - tableOptions.renderDetailPanel, - tableOptions.renderRowActionMenuItems, - tableOptions.renderRowActions, - tableOptions.state?.columnOrder, - tableOptions.state?.grouping, - ], - ); +export const useMRT_DisplayColumns = = {}>( + params: Params, +) => { + const { creatingRow, columnOrder, grouping, tableOptions } = params; + return useMemo(() => { + const order = tableOptions.state?.columnOrder ?? columnOrder; + const displayColumns = [ + makePinColumn(params, order), + makeDragColumn(params, order), + makeRowActionsColumn(params, order), + makeExpandColumn(params, order), + makeRowSelectColumn(params, order), + makeRowNumbersColumn(params, order), + ].filter((x) => x) as MRT_ColumnDef[]; + return displayColumns; + }, [ + creatingRow, + columnOrder, + grouping, + tableOptions.displayColumnDefOptions, + tableOptions.editDisplayMode, + tableOptions.enableColumnDragging, + tableOptions.enableColumnFilterModes, + tableOptions.enableColumnOrdering, + tableOptions.enableEditing, + tableOptions.enableExpandAll, + tableOptions.enableExpanding, + tableOptions.enableGrouping, + tableOptions.enableRowActions, + tableOptions.enableRowDragging, + tableOptions.enableRowNumbers, + tableOptions.enableRowOrdering, + tableOptions.enableRowSelection, + tableOptions.enableSelectAll, + tableOptions.localization, + tableOptions.positionActionsColumn, + tableOptions.renderDetailPanel, + tableOptions.renderRowActionMenuItems, + tableOptions.renderRowActions, + tableOptions.state?.columnOrder, + tableOptions.state?.grouping, + ]); }; + +function makePinColumn = {}>( + { tableOptions }: Params, + order: MRT_ColumnOrderState, +): MRT_ColumnDef | undefined { + const id: MRT_DisplayColumnIds = 'mrt-row-pin'; + if (order.includes(id)) + return { + Cell: ({ row, table }) => ( + + ), + ...defaultDisplayColumnProps(tableOptions, id, 'pin'), + }; + return undefined; +} + +function makeDragColumn = {}>( + { tableOptions }: Params, + order: MRT_ColumnOrderState, +): MRT_ColumnDef | undefined { + const id: MRT_DisplayColumnIds = 'mrt-row-drag'; + if (order.includes(id)) + return { + Cell: ({ row, rowRef, table }) => ( + } + table={table} + /> + ), + ...defaultDisplayColumnProps(tableOptions, id, 'move'), + }; + return undefined; +} + +function makeRowActionsColumn = {}>( + { tableOptions, creatingRow }: Params, + order: MRT_ColumnOrderState, +): MRT_ColumnDef | undefined { + const id: MRT_DisplayColumnIds = 'mrt-row-actions'; + if ( + order.includes(id) || + (creatingRow && tableOptions.createDisplayMode === 'row') || + tableOptions.enableEditing + ) + return { + Cell: ({ cell, row, table }) => ( + + ), + ...defaultDisplayColumnProps(tableOptions, id, 'actions', 70), + }; + return undefined; +} + +function makeExpandColumn = {}>( + { tableOptions, grouping }: Params, + order: MRT_ColumnOrderState, +): MRT_ColumnDef | undefined { + const id: MRT_DisplayColumnIds = 'mrt-row-expand'; + if ( + order.includes(id) && + showExpandColumn(tableOptions, tableOptions.state?.grouping ?? grouping) + ) + return { + Cell: ({ row, table }) => , + Header: tableOptions.enableExpandAll + ? ({ table }) => + : null, + ...defaultDisplayColumnProps(tableOptions, id, 'expand'), + }; + return undefined; +} + +function makeRowSelectColumn = {}>( + { tableOptions }: Params, + order: MRT_ColumnOrderState, +): MRT_ColumnDef | undefined { + const id: MRT_DisplayColumnIds = 'mrt-row-select'; + if (order.includes(id)) + return { + Cell: ({ row, table }) => , + Header: + tableOptions.enableSelectAll && tableOptions.enableMultiRowSelection + ? ({ table }) => + : null, + ...defaultDisplayColumnProps(tableOptions, id, 'select'), + }; + return undefined; +} + +function makeRowNumbersColumn = {}>( + { tableOptions }: Params, + order: MRT_ColumnOrderState, +): MRT_ColumnDef | undefined { + const id: MRT_DisplayColumnIds = 'mrt-row-numbers'; + if (order.includes(id) || tableOptions.enableRowNumbers) + return { + Cell: ({ row }) => row.index + 1, + Header: () => tableOptions.localization.rowNumber, + ...defaultDisplayColumnProps(tableOptions, id, 'rowNumbers'), + }; + return undefined; +} + +function defaultDisplayColumnProps = {}>( + { + defaultDisplayColumn, + displayColumnDefOptions, + localization, + }: MRT_DefinedTableOptions, + id: MRT_DisplayColumnIds, + header: keyof MRT_Localization, + size = 60, +) { + return { + size, + header: localization[header]!, + ...defaultDisplayColumn, + ...displayColumnDefOptions?.[id], + id, + }; +} diff --git a/packages/mantine-react-table/stories/features/Editing.stories.tsx b/packages/mantine-react-table/stories/features/Editing.stories.tsx index 188423048..4fcd2fd0e 100644 --- a/packages/mantine-react-table/stories/features/Editing.stories.tsx +++ b/packages/mantine-react-table/stories/features/Editing.stories.tsx @@ -5,9 +5,10 @@ import { MRT_EditActionButtons, type MRT_Cell, type MRT_TableOptions, + type MRT_ColumnOrderState, } from '../../src'; import { faker } from '@faker-js/faker'; -import { Flex, Stack, Title } from '@mantine/core'; +import { Flex, Stack, Switch, Title } from '@mantine/core'; const meta: Meta = { title: 'Features/Editing Examples', @@ -90,7 +91,6 @@ const data: Person[] = [...Array(100)].map(() => ({ export const EditingEnabledEditModeModalDefault = () => { const [tableData, setTableData] = useState(data); - const handleSaveRow: MRT_TableOptions['onEditingRowSave'] = ({ exitEditingMode, row, @@ -101,33 +101,36 @@ export const EditingEnabledEditModeModalDefault = () => { exitEditingMode(); }; + const columns = [ + { + header: 'First Name', + accessorKey: 'firstName', + }, + { + header: 'Last Name', + accessorKey: 'lastName', + }, + { + header: 'Address', + accessorKey: 'address', + }, + { + header: 'State', + accessorKey: 'state', + }, + { + header: 'Phone Number', + accessorKey: 'phoneNumber', + enableEditing: false, + }, + ]; + return ( ); @@ -1042,3 +1045,116 @@ export const EnableEditingConditionallyTable = () => { /> ); }; + +export const EditingTurnedOnDynamically = () => { + const [tableData, setTableData] = useState(data); + const handleSaveRow: MRT_TableOptions['onEditingRowSave'] = ({ + exitEditingMode, + row, + values, + }) => { + tableData[row.index] = values; + setTableData([...tableData]); + exitEditingMode(); + }; + + const columns = [ + { + header: 'First Name', + accessorKey: 'firstName', + }, + { + header: 'Last Name', + accessorKey: 'lastName', + }, + { + header: 'Address', + accessorKey: 'address', + }, + { + header: 'State', + accessorKey: 'state', + }, + { + header: 'Phone Number', + accessorKey: 'phoneNumber', + enableEditing: false, + }, + ]; + + const [enableRowNumbers, _setEnableRowNumbers] = useState(false); + const [enableEditing, _setEnableEditing] = useState(false); + + const [columnOrder, setColumnOrder] = useState(() => { + return [ + enableEditing && 'mrt-row-actions', + enableRowNumbers && 'mrt-row-numbers', + ...columns.map((c) => c.accessorKey), + ].filter(Boolean) as MRT_ColumnOrderState; + }); + + const updateColumnOrder = ({ + enableEditing, + enableRowNumbers, + }: { + enableEditing: boolean; + enableRowNumbers: boolean; + }) => { + let newColumnOrder = columnOrder; + if (enableRowNumbers) { + newColumnOrder = ['mrt-row-numbers', ...newColumnOrder]; + } else { + newColumnOrder = newColumnOrder.filter( + (col) => col !== 'mrt-row-numbers', + ); + } + if (enableEditing) { + newColumnOrder = ['mrt-row-actions', ...newColumnOrder]; + } else { + newColumnOrder = newColumnOrder.filter( + (col) => col !== 'mrt-row-actions', + ); + } + setColumnOrder(newColumnOrder); + }; + + const setEnableEditing = (value: boolean) => { + _setEnableEditing(value); + updateColumnOrder({ + enableEditing: value, + enableRowNumbers, + }); + }; + + const setEnableRowNumbers = (value: boolean) => { + _setEnableRowNumbers(value); + updateColumnOrder({ + enableEditing, + enableRowNumbers: value, + }); + }; + + return ( + + setEnableEditing(e.currentTarget.checked)} + label="Enable Editing" + />{' '} + setEnableRowNumbers(e.currentTarget.checked)} + label="Enable Row Numbers" + /> + + + ); +};