Updated tanstack table to v8.x (#2564)
parent
a4527a7942
commit
8beebce2e4
@ -1,23 +1,65 @@
|
||||
import { PluginHook, TableInstance, TableOptions, useTable } from "react-table";
|
||||
import BaseTable, { TableStyleProps } from "./BaseTable";
|
||||
import { useDefaultSettings } from "./plugins";
|
||||
import { MutableRefObject, useEffect, useMemo } from "react";
|
||||
import {
|
||||
getCoreRowModel,
|
||||
Row,
|
||||
Table,
|
||||
TableOptions,
|
||||
useReactTable,
|
||||
} from "@tanstack/react-table";
|
||||
import BaseTable, { TableStyleProps } from "@/components/tables/BaseTable";
|
||||
import { usePageSize } from "@/utilities/storage";
|
||||
|
||||
export type SimpleTableProps<T extends object> = TableOptions<T> & {
|
||||
plugins?: PluginHook<T>[];
|
||||
instanceRef?: React.MutableRefObject<TableInstance<T> | null>;
|
||||
export type SimpleTableProps<T extends object> = Omit<
|
||||
TableOptions<T>,
|
||||
"getCoreRowModel"
|
||||
> & {
|
||||
instanceRef?: MutableRefObject<Table<T> | null>;
|
||||
tableStyles?: TableStyleProps<T>;
|
||||
onRowSelectionChanged?: (selectedRows: Row<T>[]) => void;
|
||||
onAllRowsExpandedChanged?: (isAllRowsExpanded: boolean) => void;
|
||||
};
|
||||
|
||||
export default function SimpleTable<T extends object>(
|
||||
props: SimpleTableProps<T>,
|
||||
) {
|
||||
const { plugins, instanceRef, tableStyles, ...options } = props;
|
||||
const {
|
||||
instanceRef,
|
||||
tableStyles,
|
||||
onRowSelectionChanged,
|
||||
onAllRowsExpandedChanged,
|
||||
...options
|
||||
} = props;
|
||||
|
||||
const instance = useTable(options, useDefaultSettings, ...(plugins ?? []));
|
||||
const pageSize = usePageSize();
|
||||
|
||||
const instance = useReactTable({
|
||||
...options,
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
autoResetPageIndex: false,
|
||||
autoResetExpanded: false,
|
||||
pageCount: pageSize,
|
||||
});
|
||||
|
||||
if (instanceRef) {
|
||||
instanceRef.current = instance;
|
||||
}
|
||||
|
||||
return <BaseTable tableStyles={tableStyles} {...instance}></BaseTable>;
|
||||
const selectedRows = instance.getSelectedRowModel().rows;
|
||||
|
||||
const memoizedRows = useMemo(() => selectedRows, [selectedRows]);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const memoizedRowSelectionChanged = useMemo(() => onRowSelectionChanged, []);
|
||||
|
||||
const isAllRowsExpanded = instance.getIsAllRowsExpanded();
|
||||
|
||||
useEffect(() => {
|
||||
memoizedRowSelectionChanged?.(memoizedRows);
|
||||
}, [memoizedRowSelectionChanged, memoizedRows]);
|
||||
|
||||
useEffect(() => {
|
||||
onAllRowsExpandedChanged?.(isAllRowsExpanded);
|
||||
}, [onAllRowsExpandedChanged, isAllRowsExpanded]);
|
||||
|
||||
return <BaseTable tableStyles={tableStyles} instance={instance}></BaseTable>;
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
export { default as useCustomSelection } from "./useCustomSelection";
|
||||
export { default as useDefaultSettings } from "./useDefaultSettings";
|
@ -1,113 +0,0 @@
|
||||
import { forwardRef, useEffect, useRef } from "react";
|
||||
import {
|
||||
CellProps,
|
||||
Column,
|
||||
ColumnInstance,
|
||||
ensurePluginOrder,
|
||||
HeaderProps,
|
||||
Hooks,
|
||||
MetaBase,
|
||||
TableInstance,
|
||||
TableToggleCommonProps,
|
||||
} from "react-table";
|
||||
import { Checkbox as MantineCheckbox } from "@mantine/core";
|
||||
|
||||
const pluginName = "useCustomSelection";
|
||||
|
||||
const checkboxId = "---selection---";
|
||||
|
||||
interface CheckboxProps {
|
||||
idIn: string;
|
||||
disabled?: boolean;
|
||||
}
|
||||
|
||||
const Checkbox = forwardRef<
|
||||
HTMLInputElement,
|
||||
TableToggleCommonProps & CheckboxProps
|
||||
>(({ indeterminate, checked, disabled, idIn, ...rest }, ref) => {
|
||||
const defaultRef = useRef<HTMLInputElement>(null);
|
||||
const resolvedRef = ref || defaultRef;
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof resolvedRef === "object" && resolvedRef.current) {
|
||||
resolvedRef.current.indeterminate = indeterminate ?? false;
|
||||
|
||||
if (disabled) {
|
||||
resolvedRef.current.checked = false;
|
||||
} else {
|
||||
resolvedRef.current.checked = checked ?? false;
|
||||
}
|
||||
}
|
||||
}, [resolvedRef, indeterminate, checked, disabled]);
|
||||
|
||||
return (
|
||||
<MantineCheckbox
|
||||
key={idIn}
|
||||
disabled={disabled}
|
||||
ref={resolvedRef}
|
||||
{...rest}
|
||||
></MantineCheckbox>
|
||||
);
|
||||
});
|
||||
|
||||
function useCustomSelection<T extends object>(hooks: Hooks<T>) {
|
||||
hooks.visibleColumns.push(visibleColumns);
|
||||
hooks.useInstance.push(useInstance);
|
||||
}
|
||||
|
||||
useCustomSelection.pluginName = pluginName;
|
||||
|
||||
function useInstance<T extends object>(instance: TableInstance<T>) {
|
||||
const {
|
||||
plugins,
|
||||
rows,
|
||||
onSelect,
|
||||
canSelect,
|
||||
state: { selectedRowIds },
|
||||
} = instance;
|
||||
|
||||
ensurePluginOrder(plugins, ["useRowSelect"], pluginName);
|
||||
|
||||
useEffect(() => {
|
||||
// Performance
|
||||
let items = Object.keys(selectedRowIds).flatMap(
|
||||
(v) => rows.find((n) => n.id === v)?.original ?? [],
|
||||
);
|
||||
|
||||
if (canSelect) {
|
||||
items = items.filter((v) => canSelect(v));
|
||||
}
|
||||
|
||||
onSelect && onSelect(items);
|
||||
}, [selectedRowIds, onSelect, rows, canSelect]);
|
||||
}
|
||||
|
||||
function visibleColumns<T extends object>(
|
||||
columns: ColumnInstance<T>[],
|
||||
meta: MetaBase<T>,
|
||||
): Column<T>[] {
|
||||
const { instance } = meta;
|
||||
const checkbox: Column<T> = {
|
||||
id: checkboxId,
|
||||
Header: ({ getToggleAllRowsSelectedProps }: HeaderProps<T>) => (
|
||||
<Checkbox
|
||||
idIn="table-header-selection"
|
||||
{...getToggleAllRowsSelectedProps()}
|
||||
></Checkbox>
|
||||
),
|
||||
Cell: ({ row }: CellProps<T>) => {
|
||||
const canSelect = instance.canSelect;
|
||||
const disabled = (canSelect && !canSelect(row.original)) ?? false;
|
||||
return (
|
||||
<Checkbox
|
||||
idIn={`table-cell-${row.index}`}
|
||||
disabled={disabled}
|
||||
{...row.getToggleRowSelectedProps()}
|
||||
></Checkbox>
|
||||
);
|
||||
},
|
||||
};
|
||||
return [checkbox, ...columns];
|
||||
}
|
||||
|
||||
export default useCustomSelection;
|
@ -1,33 +0,0 @@
|
||||
import { Hooks, TableOptions } from "react-table";
|
||||
import { usePageSize } from "@/utilities/storage";
|
||||
|
||||
const pluginName = "useLocalSettings";
|
||||
|
||||
function useDefaultSettings<T extends object>(hooks: Hooks<T>) {
|
||||
hooks.useOptions.push(useOptions);
|
||||
}
|
||||
useDefaultSettings.pluginName = pluginName;
|
||||
|
||||
function useOptions<T extends object>(options: TableOptions<T>) {
|
||||
const pageSize = usePageSize();
|
||||
|
||||
if (options.autoResetPage === undefined) {
|
||||
options.autoResetPage = false;
|
||||
}
|
||||
|
||||
if (options.autoResetExpanded === undefined) {
|
||||
options.autoResetExpanded = false;
|
||||
}
|
||||
|
||||
if (options.initialState === undefined) {
|
||||
options.initialState = {};
|
||||
}
|
||||
|
||||
if (options.initialState.pageSize === undefined) {
|
||||
options.initialState.pageSize = pageSize;
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
export default useDefaultSettings;
|
Loading…
Reference in new issue