diff --git a/src/components/Table/Column.tsx b/src/components/Table/Column.tsx index 35b42500..bc841fc0 100644 --- a/src/components/Table/Column.tsx +++ b/src/components/Table/Column.tsx @@ -1,3 +1,4 @@ +import { forwardRef } from "react"; import { Grid, GridProps, Typography } from "@mui/material"; import { alpha } from "@mui/material/styles"; @@ -16,20 +17,25 @@ export interface IColumnProps extends Partial { active?: boolean; } -export default function Column({ - label, - type, - secondaryItem, - children, +export const Column = forwardRef(function Column( + { + label, + type, + secondaryItem, + children, - active, - ...props -}: IColumnProps) { + active, + ...props + }: IColumnProps, + ref: React.ForwardedRef +) { return ( {label} @@ -113,4 +120,6 @@ export default function Column({ {children} ); -} +}); + +export default Column; diff --git a/src/components/Table/Table.tsx b/src/components/Table/Table.tsx index ae15b34b..2f04d79c 100644 --- a/src/components/Table/Table.tsx +++ b/src/components/Table/Table.tsx @@ -1,11 +1,12 @@ -import { useMemo, useRef, useCallback, useState, useEffect } from "react"; +import { useMemo, useRef, useState, useEffect, useCallback } from "react"; import { useAtom, useSetAtom } from "jotai"; import { useThrottledCallback } from "use-debounce"; -import { useSnackbar } from "notistack"; -import useMemoValue from "use-memo-value"; -import { DndProvider } from "react-dnd"; -import { HTML5Backend } from "react-dnd-html5-backend"; -import { isEmpty, isEqual } from "lodash-es"; +import { + DragDropContext, + DropResult, + Droppable, + Draggable, +} from "react-beautiful-dnd"; import { createColumnHelper, @@ -20,7 +21,7 @@ import { StyledResizer } from "./Styled/StyledResizer"; import ColumnHeaderComponent from "./Column"; import OutOfOrderIndicator from "./OutOfOrderIndicator"; -import { IconButton } from "@mui/material"; +import { IconButton, Portal } from "@mui/material"; import ColumnHeader, { COLUMN_HEADER_HEIGHT } from "./ColumnHeader"; import FinalColumnHeader from "./FinalColumnHeader"; @@ -111,10 +112,6 @@ export default function TableComponent() { size: columnConfig.width, enableResizing: columnConfig.resizable !== false, minSize: MIN_COL_WIDTH, - // draggable: true, - // resizable: true, - // frozen: columnConfig.fixed, - // headerRenderer: ColumnHeader, // formatter: // getFieldProp("TableCell", getFieldType(columnConfig)) ?? // function InDev() { @@ -181,6 +178,9 @@ export default function TableComponent() { columnResizeMode: "onChange", }); + // Store local columnSizing state so we can save it to table schema + // in `useSaveColumnSizing`. This could be generalized by storing the + // entire table state. const [columnSizing, setColumnSizing] = useState( table.initialState.columnSizing ); @@ -192,7 +192,6 @@ export default function TableComponent() { const { rows } = table.getRowModel(); const leafColumns = table.getVisibleLeafColumns(); - // console.log(table, selectedCell); const { handleKeyDown, focusInsideCell } = useKeyboardNavigation({ gridRef, @@ -213,6 +212,22 @@ export default function TableComponent() { } = useVirtualization(containerRef, leafColumns); useSaveColumnSizing(columnSizing, canEditColumn); + const handleDropColumn = useCallback( + (result: DropResult) => { + if (result.destination?.index === undefined || !result.draggableId) + return; + + console.log(result.draggableId, result.destination.index); + + updateColumn({ + key: result.draggableId, + index: result.destination.index, + config: {}, + }); + }, + [updateColumn] + ); + const fetchMoreOnBottomReached = useThrottledCallback( (containerElement?: HTMLDivElement | null) => { if (!containerElement) return; @@ -261,61 +276,109 @@ export default function TableComponent() { padding: `0 ${TABLE_PADDING}px`, }} > - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => { - const isSelectedCell = - (!selectedCell && header.index === 0) || - (selectedCell?.path === "_rowy_header" && - selectedCell?.columnKey === header.id); - - return ( - { - setSelectedCell({ - path: "_rowy_header", - columnKey: header.id, - }); - (e.target as HTMLDivElement).focus(); - }} + + {table.getHeaderGroups().map((headerGroup) => ( + + {(provided) => ( + - {header.column.getCanResize() && ( - - )} - - ); - })} - - ))} + {headerGroup.headers.map((header) => { + const isSelectedCell = + (!selectedCell && header.index === 0) || + (selectedCell?.path === "_rowy_header" && + selectedCell?.columnKey === header.id); + + return ( + + {(provided, snapshot) => ( + { + setSelectedCell({ + path: "_rowy_header", + columnKey: header.id, + }); + (e.target as HTMLDivElement).focus(); + }} + > +
+ + {header.column.getCanResize() && ( + + )} + + )} + + ); + })} + {provided.placeholder} + + )} + + ))} +
@@ -371,6 +434,7 @@ export default function TableComponent() { cell.column.columnDef.meta?.editable === false } aria-selected={isSelectedCell} + aria-describedby="rowy-table-cell-description" style={{ width: cell.column.getSize(), left: cell.column.getIsPinned() @@ -430,6 +494,12 @@ export default function TableComponent() { )}
+ + +
+ Press Enter to edit. +
+
); }