From 8ab1faafb667aa5d874e3b9323cefc975fd80097 Mon Sep 17 00:00:00 2001 From: Alex Andreev Date: Thu, 4 Aug 2022 15:59:30 +0300 Subject: [PATCH] Introduce TableList generic component Signed-off-by: Alex Andreev --- src/renderer/components/list/list.tsx | 4 +- .../components/table-list/table-list.tsx | 158 ++++++++++++++++++ 2 files changed, 160 insertions(+), 2 deletions(-) create mode 100644 src/renderer/components/table-list/table-list.tsx diff --git a/src/renderer/components/list/list.tsx b/src/renderer/components/list/list.tsx index 83bbdd2024..d9add12257 100644 --- a/src/renderer/components/list/list.tsx +++ b/src/renderer/components/list/list.tsx @@ -11,7 +11,7 @@ import { SearchInput } from "../input"; import type { TableOptions } from '@tanstack/react-table' import { getCoreRowModel } from '@tanstack/react-table' -import { Table } from "../table/react-table"; +import { TableList } from "../table-list/table-list"; export type SearchFilter = (item: T) => string; @@ -43,7 +43,7 @@ export function List({ columns, data, title, filters }: ListProps) { /> - extends TableOptions { + className?: string; + selectable?: boolean; + configurable?: boolean; +} + +export function TableList({ + columns, + data, + className, + selectable = true, + configurable = true, +}: TableProps) { + const [sorting, setSorting] = React.useState([]) + const tableColumns = useMemo(() => { + const cols = [ ...columns ]; + const columnHelper = createColumnHelper() + + if (selectable) { + cols.unshift( + columnHelper.display({ + id: "select", + header: ({ table }) => ( + + ), + cell: ({ row }) => ( + + ), + }) + ) + } + + if (configurable) { + cols.push( + columnHelper.display({ + id: "config", + header: () => , + }) + ) + } + + return cols; + }, [data]); + + const table = useReactTable({ + data, + columns: tableColumns, + getCoreRowModel: getCoreRowModel(), + state: { + sorting, + }, + onSortingChange: setSorting, + getSortedRowModel: getSortedRowModel(), + }); + + return ( +
+ ) +} + +function IndeterminateCheckbox({ + indeterminate, + className = '', + ...rest +}: { indeterminate?: boolean } & HTMLProps) { + const ref = React.useRef(null!) + + React.useEffect(() => { + if (typeof indeterminate === 'boolean') { + ref.current.indeterminate = !rest.checked && indeterminate + } + }, [ref, indeterminate]) + + return ( + + ) +} + +interface Dependencies { + id: string; +} + +interface Props { + table: TableType +} + +function NonInjectableColumnConfigMenu(props: Dependencies & Props) { + const id = `${props.id}-column-config`; + const [open, setOpen] = React.useState(false); + + return ( + <> + + setOpen(true)} + close={() => setOpen(false)} + closeOnScroll + closeOnClickItem + closeOnClickOutside + usePortal + > + {props.table.getAllLeafColumns().map(column => { + return ( + + + + ) + })} + + + ); +} + +export const ColumnConfigMenu = withInjectables(NonInjectableColumnConfigMenu, { + getProps: (di, props) => ({ + id: di.inject(getRandomIdInjectable)(), + ...props, + }), +}); \ No newline at end of file