@trackunit/react-table 0.0.175 → 0.0.177

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.js CHANGED
@@ -345,6 +345,7 @@ const Table = (_a) => {
345
345
  rowHeight,
346
346
  });
347
347
  const hasResults = props.getRowModel().rows.length > 0;
348
+ console.log("onRowClick", props.onRowClick);
348
349
  return (jsxRuntime.jsxs(reactComponents.Card, { className: `flex flex-col overflow-hidden ${props.className || ""}`, dataTestId: props.dataTestId, children: [(props.headerLeftActions || props.headerRightActions) && (jsxRuntime.jsxs("div", { className: "z-default flex justify-between gap-2 p-2", children: [jsxRuntime.jsx("div", { className: "flex", children: props.headerLeftActions }), jsxRuntime.jsx("div", { className: "flex", children: props.headerRightActions })] })), jsxRuntime.jsx("div", { className: "min-h[500px] h-full overflow-x-auto overflow-y-scroll border-b border-t border-gray-300", ref: tableContainerRef, onScroll: e => fetchMoreOnBottomReached(e.target), children: jsxRuntime.jsxs(reactTableBaseComponents.TableRoot, { style: {
349
350
  height: getTotalSize() > 0 ? getTotalSize() : "100%",
350
351
  width: "100%",
@@ -366,7 +367,14 @@ const Table = (_a) => {
366
367
  return (jsxRuntime.jsx(reactTableBaseComponents.Tr, { layout: "flex", style: {
367
368
  height: `${virtualRow.size}px`,
368
369
  transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
369
- }, onClick: () => (props.onRowClick ? props.onRowClick(row) : row.getToggleSelectedHandler()), className: `${(props.onRowClick || row.getCanSelect()) && "cursor-pointer"} hover:bg-neutral-100`, dataTestId: `table-body-row-${virtualRow.index}`, children: row === null || row === void 0 ? void 0 : row.getVisibleCells().map(cell => {
370
+ }, onClick: () => {
371
+ if (props.onRowClick) {
372
+ props.onRowClick(row);
373
+ }
374
+ else if (row.getCanSelect()) {
375
+ row.toggleSelected();
376
+ }
377
+ }, className: `${(props.onRowClick || row.getCanSelect()) && "cursor-pointer"} hover:bg-neutral-100`, dataTestId: `table-body-row-${virtualRow.index}`, children: row === null || row === void 0 ? void 0 : row.getVisibleCells().map(cell => {
370
378
  return (jsxRuntime.jsx(reactTableBaseComponents.Td, { key: cell.id,
371
379
  style: {
372
380
  width: cell.column.getSize(),
@@ -686,6 +694,79 @@ const useTable = (_a) => {
686
694
  return memoizedTable;
687
695
  };
688
696
 
697
+ /**
698
+ * `useTableSelection` is a custom hook that provides functionality for row selection in a table.
699
+ * It returns an object containing methods and values related to row selection.
700
+ *
701
+ * @template TData - The type of data in the table. It must extend `selectableTableData`, which means it should at least have an `id` field.
702
+ * @returns {TableSelectionReturn<TData>} An object containing:
703
+ * - `selectionColumn`: A `ColumnDef` object for the selection column, which includes a checkbox in each cell and header.
704
+ * - `rowSelection`: The current state of row selection.
705
+ * - `setRowSelection`: A function to update the row selection state.
706
+ * @example
707
+ * const {
708
+ * selectionColumn,
709
+ * rowSelection,
710
+ * setRowSelection,
711
+ * } = useTableSelection<MyDataType>();
712
+ *
713
+ * const columns = [selectionColumn, ...otherColumns]
714
+ *
715
+ * const tableProps = useTable({
716
+ * ...selectionTableProps,
717
+ * state: {
718
+ * ...selectionTableState,
719
+ * },
720
+ * data,
721
+ * columns
722
+ * });
723
+ */
724
+ const useTableSelection = ({ data, }) => {
725
+ const [rowSelection, setRowSelection] = React.useState({});
726
+ const toggleRowSelectionState = React.useCallback((id) => {
727
+ setRowSelection(prevRowSelection => (Object.assign(Object.assign({}, prevRowSelection), { [id]: !prevRowSelection[id] })));
728
+ }, []);
729
+ const selectedIds = React.useMemo(() => Object.entries(rowSelection)
730
+ .filter(([_, selected]) => selected)
731
+ .map(([id]) => id), [rowSelection]);
732
+ const columnHelper = React.useMemo(() => reactTable.createColumnHelper(), []);
733
+ const selectionColumn = React.useMemo(() => columnHelper.accessor(row => row.id, {
734
+ cell: ({ row }) => (jsxRuntime.jsx(reactFormComponents.Checkbox, { className: "ml-1",
735
+ checked: row.getIsSelected(),
736
+ disabled: !row.getCanSelect(),
737
+ indeterminate: row.getIsSomeSelected(),
738
+ onChange: row.getToggleSelectedHandler(),
739
+ stopPropagation: true })),
740
+ header: ({ table }) => (jsxRuntime.jsx(reactFormComponents.Checkbox, { checked: table.getIsAllRowsSelected(),
741
+ indeterminate: table.getIsSomeRowsSelected(),
742
+ onChange: table.getToggleAllRowsSelectedHandler() })),
743
+ id: "selection",
744
+ enableSorting: false,
745
+ enableResizing: false,
746
+ size: 55,
747
+ meta: {
748
+ required: true,
749
+ alignment: "left",
750
+ },
751
+ }), [columnHelper]);
752
+ const selectionTableState = React.useMemo(() => ({
753
+ rowSelection,
754
+ }), [rowSelection]);
755
+ const selectionTableProps = React.useMemo(() => ({
756
+ onRowSelectionChange: setRowSelection,
757
+ getRowId: row => row.id,
758
+ enableRowSelection: true,
759
+ }), []);
760
+ return React.useMemo(() => ({
761
+ toggleRowSelectionState,
762
+ selectionColumn,
763
+ selectedIds,
764
+ selectionTableState,
765
+ selectionTableProps,
766
+ setRowSelection,
767
+ }), [selectedIds, selectionColumn, selectionTableProps, selectionTableState, toggleRowSelectionState]);
768
+ };
769
+
689
770
  //TODO: find a more appropriate place for this file
690
771
  /**
691
772
  * Convert a sorting state from the TUSort format to the TanStack format.
@@ -752,3 +833,4 @@ exports.fromTanStackToTUSort = fromTanStackToTUSort;
752
833
  exports.fromTanStackToTUSortSite = fromTanStackToTUSortSite;
753
834
  exports.useRelayPagination = useRelayPagination;
754
835
  exports.useTable = useTable;
836
+ exports.useTableSelection = useTableSelection;
package/index.esm.js CHANGED
@@ -5,11 +5,11 @@ import * as React from 'react';
5
5
  import { useMemo, Children, cloneElement, useCallback, useEffect, useRef, useState } from 'react';
6
6
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
7
7
  import { Link } from 'react-router-dom';
8
- import { flexRender, useReactTable, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
8
+ import { flexRender, useReactTable, getSortedRowModel, getCoreRowModel, createColumnHelper } from '@tanstack/react-table';
9
9
  export { createColumnHelper } from '@tanstack/react-table';
10
10
  import { TableRoot, Thead, Tr, Th, SortIndicator, ResizeHandle, Tbody, Td } from '@trackunit/react-table-base-components';
11
11
  import { useVirtualizer } from '@tanstack/react-virtual';
12
- import { Toggle, RadioGroup, RadioItem } from '@trackunit/react-form-components';
12
+ import { Toggle, RadioGroup, RadioItem, Checkbox } from '@trackunit/react-form-components';
13
13
  import update from 'immutability-helper';
14
14
  import { DndProvider, useDrop, useDrag } from 'react-dnd';
15
15
  import { HTML5Backend } from 'react-dnd-html5-backend';
@@ -320,6 +320,7 @@ const Table = (_a) => {
320
320
  rowHeight,
321
321
  });
322
322
  const hasResults = props.getRowModel().rows.length > 0;
323
+ console.log("onRowClick", props.onRowClick);
323
324
  return (jsxs(Card, { className: `flex flex-col overflow-hidden ${props.className || ""}`, dataTestId: props.dataTestId, children: [(props.headerLeftActions || props.headerRightActions) && (jsxs("div", { className: "z-default flex justify-between gap-2 p-2", children: [jsx("div", { className: "flex", children: props.headerLeftActions }), jsx("div", { className: "flex", children: props.headerRightActions })] })), jsx("div", { className: "min-h[500px] h-full overflow-x-auto overflow-y-scroll border-b border-t border-gray-300", ref: tableContainerRef, onScroll: e => fetchMoreOnBottomReached(e.target), children: jsxs(TableRoot, { style: {
324
325
  height: getTotalSize() > 0 ? getTotalSize() : "100%",
325
326
  width: "100%",
@@ -341,7 +342,14 @@ const Table = (_a) => {
341
342
  return (jsx(Tr, { layout: "flex", style: {
342
343
  height: `${virtualRow.size}px`,
343
344
  transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
344
- }, onClick: () => (props.onRowClick ? props.onRowClick(row) : row.getToggleSelectedHandler()), className: `${(props.onRowClick || row.getCanSelect()) && "cursor-pointer"} hover:bg-neutral-100`, dataTestId: `table-body-row-${virtualRow.index}`, children: row === null || row === void 0 ? void 0 : row.getVisibleCells().map(cell => {
345
+ }, onClick: () => {
346
+ if (props.onRowClick) {
347
+ props.onRowClick(row);
348
+ }
349
+ else if (row.getCanSelect()) {
350
+ row.toggleSelected();
351
+ }
352
+ }, className: `${(props.onRowClick || row.getCanSelect()) && "cursor-pointer"} hover:bg-neutral-100`, dataTestId: `table-body-row-${virtualRow.index}`, children: row === null || row === void 0 ? void 0 : row.getVisibleCells().map(cell => {
345
353
  return (jsx(Td, { key: cell.id,
346
354
  style: {
347
355
  width: cell.column.getSize(),
@@ -661,6 +669,79 @@ const useTable = (_a) => {
661
669
  return memoizedTable;
662
670
  };
663
671
 
672
+ /**
673
+ * `useTableSelection` is a custom hook that provides functionality for row selection in a table.
674
+ * It returns an object containing methods and values related to row selection.
675
+ *
676
+ * @template TData - The type of data in the table. It must extend `selectableTableData`, which means it should at least have an `id` field.
677
+ * @returns {TableSelectionReturn<TData>} An object containing:
678
+ * - `selectionColumn`: A `ColumnDef` object for the selection column, which includes a checkbox in each cell and header.
679
+ * - `rowSelection`: The current state of row selection.
680
+ * - `setRowSelection`: A function to update the row selection state.
681
+ * @example
682
+ * const {
683
+ * selectionColumn,
684
+ * rowSelection,
685
+ * setRowSelection,
686
+ * } = useTableSelection<MyDataType>();
687
+ *
688
+ * const columns = [selectionColumn, ...otherColumns]
689
+ *
690
+ * const tableProps = useTable({
691
+ * ...selectionTableProps,
692
+ * state: {
693
+ * ...selectionTableState,
694
+ * },
695
+ * data,
696
+ * columns
697
+ * });
698
+ */
699
+ const useTableSelection = ({ data, }) => {
700
+ const [rowSelection, setRowSelection] = useState({});
701
+ const toggleRowSelectionState = useCallback((id) => {
702
+ setRowSelection(prevRowSelection => (Object.assign(Object.assign({}, prevRowSelection), { [id]: !prevRowSelection[id] })));
703
+ }, []);
704
+ const selectedIds = useMemo(() => Object.entries(rowSelection)
705
+ .filter(([_, selected]) => selected)
706
+ .map(([id]) => id), [rowSelection]);
707
+ const columnHelper = useMemo(() => createColumnHelper(), []);
708
+ const selectionColumn = useMemo(() => columnHelper.accessor(row => row.id, {
709
+ cell: ({ row }) => (jsx(Checkbox, { className: "ml-1",
710
+ checked: row.getIsSelected(),
711
+ disabled: !row.getCanSelect(),
712
+ indeterminate: row.getIsSomeSelected(),
713
+ onChange: row.getToggleSelectedHandler(),
714
+ stopPropagation: true })),
715
+ header: ({ table }) => (jsx(Checkbox, { checked: table.getIsAllRowsSelected(),
716
+ indeterminate: table.getIsSomeRowsSelected(),
717
+ onChange: table.getToggleAllRowsSelectedHandler() })),
718
+ id: "selection",
719
+ enableSorting: false,
720
+ enableResizing: false,
721
+ size: 55,
722
+ meta: {
723
+ required: true,
724
+ alignment: "left",
725
+ },
726
+ }), [columnHelper]);
727
+ const selectionTableState = useMemo(() => ({
728
+ rowSelection,
729
+ }), [rowSelection]);
730
+ const selectionTableProps = useMemo(() => ({
731
+ onRowSelectionChange: setRowSelection,
732
+ getRowId: row => row.id,
733
+ enableRowSelection: true,
734
+ }), []);
735
+ return useMemo(() => ({
736
+ toggleRowSelectionState,
737
+ selectionColumn,
738
+ selectedIds,
739
+ selectionTableState,
740
+ selectionTableProps,
741
+ setRowSelection,
742
+ }), [selectedIds, selectionColumn, selectionTableProps, selectionTableState, toggleRowSelectionState]);
743
+ };
744
+
664
745
  //TODO: find a more appropriate place for this file
665
746
  /**
666
747
  * Convert a sorting state from the TUSort format to the TanStack format.
@@ -712,4 +793,4 @@ const fromTanStackToTUSortSite = (input) => {
712
793
  */
713
794
  setupLibraryTranslations();
714
795
 
715
- export { ActionSheet, ColumnFilter, RowSpacing, Sorting, Table, fromTUSortToTanStack, fromTUSortToTanStackSite, fromTanStackToTUSort, fromTanStackToTUSortSite, useRelayPagination, useTable };
796
+ export { ActionSheet, ColumnFilter, RowSpacing, Sorting, Table, fromTUSortToTanStack, fromTUSortToTanStackSite, fromTanStackToTUSort, fromTanStackToTUSortSite, useRelayPagination, useTable, useTableSelection };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-table",
3
- "version": "0.0.175",
3
+ "version": "0.0.177",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
package/src/index.d.ts CHANGED
@@ -7,5 +7,6 @@ export * from "./menus/Sorting";
7
7
  export * from "./types";
8
8
  export * from "./useRelayPagination";
9
9
  export * from "./useTable";
10
+ export * from "./useTableSelection";
10
11
  export * from "./utils";
11
12
  export type SortingState = ColumnSort[];
@@ -0,0 +1,72 @@
1
+ import { ColumnDef, RowSelectionState } from "@tanstack/react-table";
2
+ import { Dispatch, SetStateAction } from "react";
3
+ type selectableTableData = {
4
+ id: string;
5
+ } & object;
6
+ export interface TableSelectionReturn<TData extends selectableTableData> {
7
+ /**
8
+ * An array of the ids of the currently selected rows.
9
+ */
10
+ selectedIds: TData["id"][];
11
+ /**
12
+ * The current state of row selection.
13
+ * Pass this to the `state` prop of the `useTable` Hook.
14
+ */
15
+ selectionTableState: {
16
+ rowSelection?: RowSelectionState | undefined;
17
+ };
18
+ /**
19
+ * Props to pass to the `useTable` Hook.
20
+ */
21
+ selectionTableProps: {
22
+ onRowSelectionChange: Dispatch<SetStateAction<RowSelectionState>>;
23
+ getRowId: (row: TData) => TData["id"];
24
+ enableRowSelection: true;
25
+ };
26
+ /**
27
+ * A function to update the row selection state.
28
+ * Pass this to the `onRowSelectionChange` prop of the `useTable` Hook.
29
+ */
30
+ setRowSelection: Dispatch<SetStateAction<RowSelectionState>>;
31
+ /**
32
+ * A `ColumnDef` object for the selection column, which includes a checkbox in each cell and header.
33
+ */
34
+ selectionColumn: ColumnDef<TData, string>;
35
+ /**
36
+ * A function to toggle the selection state of a single row.
37
+ * This is usefull for example when you want to select a row when clicking on it, instead of the checkbox.
38
+ */
39
+ toggleRowSelectionState: (id: TData["id"]) => void;
40
+ }
41
+ export interface TableSelectionProps<TData extends selectableTableData> {
42
+ data: TData[];
43
+ }
44
+ /**
45
+ * `useTableSelection` is a custom hook that provides functionality for row selection in a table.
46
+ * It returns an object containing methods and values related to row selection.
47
+ *
48
+ * @template TData - The type of data in the table. It must extend `selectableTableData`, which means it should at least have an `id` field.
49
+ * @returns {TableSelectionReturn<TData>} An object containing:
50
+ * - `selectionColumn`: A `ColumnDef` object for the selection column, which includes a checkbox in each cell and header.
51
+ * - `rowSelection`: The current state of row selection.
52
+ * - `setRowSelection`: A function to update the row selection state.
53
+ * @example
54
+ * const {
55
+ * selectionColumn,
56
+ * rowSelection,
57
+ * setRowSelection,
58
+ * } = useTableSelection<MyDataType>();
59
+ *
60
+ * const columns = [selectionColumn, ...otherColumns]
61
+ *
62
+ * const tableProps = useTable({
63
+ * ...selectionTableProps,
64
+ * state: {
65
+ * ...selectionTableState,
66
+ * },
67
+ * data,
68
+ * columns
69
+ * });
70
+ */
71
+ export declare const useTableSelection: <TData extends selectableTableData>({ data, }: TableSelectionProps<TData>) => TableSelectionReturn<TData>;
72
+ export {};