@trackunit/react-table 0.0.589 → 0.0.591

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
@@ -7,14 +7,14 @@ var sharedUtils = require('@trackunit/shared-utils');
7
7
  var React = require('react');
8
8
  var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
9
9
  var reactRouter = require('@tanstack/react-router');
10
- var reactTable = require('@tanstack/react-table');
11
- var reactTableBaseComponents = require('@trackunit/react-table-base-components');
12
- var reactTablePagination = require('@trackunit/react-table-pagination');
13
- var tailwindMerge = require('tailwind-merge');
14
10
  var reactFormComponents = require('@trackunit/react-form-components');
15
11
  var update = require('immutability-helper');
16
12
  var reactDnd = require('react-dnd');
17
13
  var reactDndHtml5Backend = require('react-dnd-html5-backend');
14
+ var reactTable = require('@tanstack/react-table');
15
+ var reactTableBaseComponents = require('@trackunit/react-table-base-components');
16
+ var reactTablePagination = require('@trackunit/react-table-pagination');
17
+ var tailwindMerge = require('tailwind-merge');
18
18
  var reactCoreContextsApi = require('@trackunit/react-core-contexts-api');
19
19
 
20
20
  function _interopNamespaceDefault(e) {
@@ -289,94 +289,6 @@ const ActionSheet = ({ actions, dropdownActions, moreActions = [], selections, r
289
289
  moreActions: moreActions.map(action => actionDataToMenuItem(action, dataTestId)) })] }));
290
290
  };
291
291
 
292
- /**
293
- * Table component for displaying large sets of data in tables with infinite scroll, sorting, filtering and others.
294
- *
295
- * @param {ReactTable} props - The props for the Table component
296
- * @returns {JSX.Element} Table component
297
- */
298
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
299
- const Table = ({ rowHeight = 75, ...props }) => {
300
- var _a, _b, _c;
301
- //we need a reference to the scrolling element for logic down below
302
- const tableContainerRef = React.useRef(null);
303
- const [t] = useTranslation();
304
- const { fetchMoreOnBottomReached, getVirtualItems, getTotalSize } = reactTablePagination.useInfiniteScroll({
305
- pagination: props.pagination || reactTablePagination.noPagination,
306
- containerRef: tableContainerRef,
307
- rowSize: props.getRowModel().rows.length || 0,
308
- rowHeight,
309
- });
310
- const hasResults = props.getRowModel().rows.length > 0;
311
- return (jsxRuntime.jsxs(reactComponents.Card, { className: tailwindMerge.twMerge("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 items-center", children: props.headerLeftActions }), jsxRuntime.jsx("div", { className: "flex items-center", children: props.headerRightActions })] })) : null, jsxRuntime.jsx("div", { className: "h-full overflow-x-auto overflow-y-scroll border-b border-t border-gray-300", onScroll: e => fetchMoreOnBottomReached(e.target), ref: tableContainerRef, children: jsxRuntime.jsxs(reactTableBaseComponents.TableRoot, { style: {
312
- height: hasResults ? "auto" : "100%",
313
- width: "100%",
314
- position: "relative",
315
- }, children: [jsxRuntime.jsx(reactTableBaseComponents.Thead, { className: "z-default", children: props.getHeaderGroups().map(headerGroup => (jsxRuntime.jsx(reactTableBaseComponents.Tr, { className: "flex", children: headerGroup.headers.map(header => {
316
- var _a, _b, _c, _d, _e, _f;
317
- const tooltipLabel = (_b = (_a = header.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.tootipLabel) !== null && _b !== void 0 ? _b : (typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : "");
318
- return (jsxRuntime.jsxs(reactTableBaseComponents.Th, { className: "relative", style: {
319
- width: header.getSize(),
320
- minWidth: header.column.columnDef.minSize,
321
- maxWidth: header.column.columnDef.maxSize,
322
- textAlign: ((_c = header.column.columnDef.meta) === null || _c === void 0 ? void 0 : _c.alignment) || "left",
323
- flexGrow: ((_d = header.column.columnDef.meta) === null || _d === void 0 ? void 0 : _d.shouldGrow) ? 1 : 0,
324
- }, tooltipLabel: tooltipLabel, children: [header.isPlaceholder ? null : (jsxRuntime.jsxs("div", { className: `${header.column.getCanSort() ? "cursor-pointer select-none flex" : "flex"} items-center gap-2 py-2 overflow-hidden pr-3 w-full`,
325
- onClick: header.column.getToggleSortingHandler(), children: [jsxRuntime.jsxs("span", { className: "overflow-hidden text-ellipsis whitespace-nowrap", children: [reactTable.flexRender(header.column.columnDef.header, header.getContext()), ((_e = header.column.columnDef.meta) === null || _e === void 0 ? void 0 : _e.subHeader) ? (jsxRuntime.jsx(reactComponents.Text, { size: "small", subtle: true, children: header.column.columnDef.meta.subHeader })) : null] }), header.column.getCanSort() ? (jsxRuntime.jsx(reactTableBaseComponents.SortIndicator, { sortingState: header.column.getIsSorted() })) : null] })), !((_f = header.column.columnDef.meta) === null || _f === void 0 ? void 0 : _f.shouldGrow) && header.column.getCanResize() ? (jsxRuntime.jsx(reactTableBaseComponents.ResizeHandle, { isResizing: header.column.getIsResizing(), onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler() })) : null] }, header.id));
326
- }) }, headerGroup.id))) }), hasResults ? (jsxRuntime.jsx(reactTableBaseComponents.Tbody, { className: "text-sm font-normal", style: {
327
- height: `${getTotalSize()}px`,
328
- flexGrow: 1,
329
- }, children: getVirtualItems().map((virtualRow, index) => {
330
- const row = props.getRowModel().rows[virtualRow.index];
331
- if (!row) {
332
- return null;
333
- }
334
- else {
335
- return (jsxRuntime.jsx(reactTableBaseComponents.Tr, { className: reactComponents.cvaInteractableItem({
336
- cursor: !!props.onRowClick || row.getCanSelect() ? "pointer" : "default",
337
- selected: "auto",
338
- }), dataTestId: `table-body-row-${virtualRow.index}`, layout: "flex", onClick: () => {
339
- if (props.onRowClick) {
340
- props.onRowClick(row);
341
- }
342
- else if (row.getCanSelect()) {
343
- row.toggleSelected();
344
- }
345
- }, style: {
346
- height: `${virtualRow.size}px`,
347
- transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
348
- }, children: row.getVisibleCells().map(cell => {
349
- var _a, _b;
350
- return (jsxRuntime.jsx(reactTableBaseComponents.Td, { onClick: event => {
351
- // prevent onRowClick action when clicking on a "selectable" cell with checkbox
352
- if (props.selectionColId && cell.column.id === props.selectionColId) {
353
- event.stopPropagation();
354
- }
355
- }, style: {
356
- width: cell.column.getSize(),
357
- minWidth: cell.column.columnDef.minSize,
358
- maxWidth: cell.column.columnDef.maxSize,
359
- textAlign: ((_a = cell.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.alignment) || "left",
360
- flexGrow: ((_b = cell.column.columnDef.meta) === null || _b === void 0 ? void 0 : _b.shouldGrow) ? 1 : 0,
361
- }, children: jsxRuntime.jsx("div", { className: "grid h-full items-center", children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }) }, cell.id));
362
- }) }, row.id));
363
- }
364
- }) })) : (jsxRuntime.jsx("tbody", { className: cvaTBody({ emptyState: !props.loading && !props.noDataMessage }), children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { className: "b-0", children: props.loading ? (jsxRuntime.jsx(reactComponents.Spinner, { centering: "centered", containerClassName: "absolute inset-0" })) : props.noDataMessage ? (props.noDataMessage) : (jsxRuntime.jsx(reactComponents.EmptyState, { className: "absolute inset-0", description: t("table.noResults"), image: "SEARCH_DOCUMENT", ...props.emptyState })) }) }) }))] }) }), props.hideFooter ? null : (jsxRuntime.jsxs("div", { className: "flex items-center p-2", children: [jsxRuntime.jsx("div", { className: "whitespace-nowrap text-xs font-medium text-neutral-600", children: t("table.pagination.full", {
365
- count: props.getRowModel().rows.length,
366
- total: ((_b = (_a = props.pagination) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.count) || 0,
367
- }) }), ((_c = props.pagination) === null || _c === void 0 ? void 0 : _c.isLoading) ? (jsxRuntime.jsx("span", { className: "ml-2", children: jsxRuntime.jsx(reactComponents.Spinner, { size: "small" }) })) : null, props.footerRightActions ? jsxRuntime.jsx("div", { className: "flex flex-1 justify-end", children: props.footerRightActions }) : null] }))] }));
368
- };
369
- const cvaTBody = cssClassVarianceUtilities.cvaMerge(["min-h-[40dvh]"], {
370
- variants: {
371
- emptyState: {
372
- true: "min-h-[400px]",
373
- },
374
- },
375
- defaultVariants: {
376
- emptyState: false,
377
- },
378
- });
379
-
380
292
  const cvaColumnFilterGrabbable = cssClassVarianceUtilities.cvaMerge(["flex", "items-center", "justify-center"], {
381
293
  variants: {
382
294
  disabled: {
@@ -582,6 +494,103 @@ const Sorting = ({ columns, }) => {
582
494
  }) }), jsxRuntime.jsxs(reactFormComponents.RadioGroup, { id: "sortOrder", onChange: onSelectOrder, value: currentSortDirection, children: [jsxRuntime.jsx(reactFormComponents.RadioItem, { className: "w-full", label: t("table.sorting.ascending"), value: "asc" }), jsxRuntime.jsx(reactFormComponents.RadioItem, { className: "w-full", label: t("table.sorting.descending"), value: "desc" })] })] }) })] }) }));
583
495
  };
584
496
 
497
+ /**
498
+ * Table component for displaying large sets of data in tables with infinite scroll, sorting, filtering and others.
499
+ *
500
+ * @param {ReactTable} props - The props for the Table component
501
+ * @returns {JSX.Element} Table component
502
+ */
503
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
504
+ const Table = ({ rowHeight = 75, ...props }) => {
505
+ var _a, _b, _c;
506
+ //we need a reference to the scrolling element for logic down below
507
+ const tableContainerRef = React.useRef(null);
508
+ const [t] = useTranslation();
509
+ const { fetchMoreOnBottomReached, getVirtualItems, getTotalSize } = reactTablePagination.useInfiniteScroll({
510
+ pagination: props.pagination || reactTablePagination.noPagination,
511
+ containerRef: tableContainerRef,
512
+ rowSize: props.getRowModel().rows.length || 0,
513
+ rowHeight,
514
+ });
515
+ const hasResults = props.getRowModel().rows.length > 0;
516
+ return (jsxRuntime.jsxs(reactComponents.Card, { className: tailwindMerge.twMerge("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 items-center", children: props.headerLeftActions }), jsxRuntime.jsx("div", { className: "flex items-center", children: props.headerRightActions })] })) : null, jsxRuntime.jsx("div", { className: "h-full overflow-x-auto overflow-y-scroll border-b border-t border-gray-300", onScroll: e => fetchMoreOnBottomReached(e.target), ref: tableContainerRef, children: jsxRuntime.jsxs(reactTableBaseComponents.TableRoot, { style: {
517
+ height: hasResults ? "auto" : "100%",
518
+ width: "100%",
519
+ position: "relative",
520
+ }, children: [jsxRuntime.jsx(reactTableBaseComponents.Thead, { className: "z-default", children: props.getHeaderGroups().map(headerGroup => (jsxRuntime.jsx(reactTableBaseComponents.Tr, { className: "flex", children: headerGroup.headers.map(header => {
521
+ var _a, _b, _c, _d, _e, _f;
522
+ const tooltipLabel = (_b = (_a = header.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.tootipLabel) !== null && _b !== void 0 ? _b : (typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : "");
523
+ return (jsxRuntime.jsxs(reactTableBaseComponents.Th, { className: "relative", style: {
524
+ width: header.getSize(),
525
+ minWidth: header.column.columnDef.minSize,
526
+ maxWidth: header.column.columnDef.maxSize,
527
+ textAlign: ((_c = header.column.columnDef.meta) === null || _c === void 0 ? void 0 : _c.alignment) || "left",
528
+ flexGrow: ((_d = header.column.columnDef.meta) === null || _d === void 0 ? void 0 : _d.shouldGrow) ? 1 : 0,
529
+ }, tooltipLabel: tooltipLabel, children: [header.isPlaceholder ? null : (jsxRuntime.jsxs("div", { className: `${header.column.getCanSort() ? "cursor-pointer select-none flex" : "flex"} items-center gap-2 py-2 overflow-hidden pr-3 w-full`,
530
+ onClick: header.column.getToggleSortingHandler(), children: [jsxRuntime.jsxs("span", { className: "overflow-hidden text-ellipsis whitespace-nowrap", children: [reactTable.flexRender(header.column.columnDef.header, header.getContext()), ((_e = header.column.columnDef.meta) === null || _e === void 0 ? void 0 : _e.subHeader) ? (jsxRuntime.jsx(reactComponents.Text, { size: "small", subtle: true, children: header.column.columnDef.meta.subHeader })) : null] }), header.column.getCanSort() ? (jsxRuntime.jsx(reactTableBaseComponents.SortIndicator, { sortingState: header.column.getIsSorted() })) : null] })), !((_f = header.column.columnDef.meta) === null || _f === void 0 ? void 0 : _f.shouldGrow) && header.column.getCanResize() ? (jsxRuntime.jsx(reactTableBaseComponents.ResizeHandle, { isResizing: header.column.getIsResizing(), onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler() })) : null] }, header.id));
531
+ }) }, headerGroup.id))) }), hasResults ? (jsxRuntime.jsx(reactTableBaseComponents.Tbody, { className: "text-sm font-normal", style: {
532
+ height: `${getTotalSize()}px`,
533
+ flexGrow: 1,
534
+ }, children: getVirtualItems().map((virtualRow, index) => {
535
+ const row = props.getRowModel().rows[virtualRow.index];
536
+ if (!row) {
537
+ return null;
538
+ }
539
+ else {
540
+ return (jsxRuntime.jsx(reactTableBaseComponents.Tr, { className: reactComponents.cvaInteractableItem({
541
+ cursor: !!props.onRowClick || row.getCanSelect() ? "pointer" : "default",
542
+ selected: "auto",
543
+ }), dataTestId: `table-body-row-${virtualRow.index}`, layout: "flex", onClick: () => {
544
+ if (props.onRowClick) {
545
+ props.onRowClick(row);
546
+ }
547
+ else if (row.getCanSelect()) {
548
+ row.toggleSelected();
549
+ }
550
+ }, style: {
551
+ height: `${virtualRow.size}px`,
552
+ transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
553
+ }, children: row.getVisibleCells().map(cell => {
554
+ var _a, _b;
555
+ return (jsxRuntime.jsx(reactTableBaseComponents.Td, { onClick: event => {
556
+ // prevent onRowClick action when clicking on a "selectable" cell with checkbox
557
+ if (props.selectionColId && cell.column.id === props.selectionColId) {
558
+ event.stopPropagation();
559
+ }
560
+ }, style: {
561
+ width: cell.column.getSize(),
562
+ minWidth: cell.column.columnDef.minSize,
563
+ maxWidth: cell.column.columnDef.maxSize,
564
+ textAlign: ((_a = cell.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.alignment) || "left",
565
+ flexGrow: ((_b = cell.column.columnDef.meta) === null || _b === void 0 ? void 0 : _b.shouldGrow) ? 1 : 0,
566
+ }, children: jsxRuntime.jsx("div", { className: "grid h-full items-center", children: reactTable.flexRender(cell.column.columnDef.cell, cell.getContext()) }) }, cell.id));
567
+ }) }, row.id));
568
+ }
569
+ }) })) : (jsxRuntime.jsx("tbody", { className: cvaTBody({ emptyState: !props.loading && !props.noDataMessage }), children: jsxRuntime.jsx("tr", { children: jsxRuntime.jsx("td", { className: "b-0", children: props.loading ? (jsxRuntime.jsx(reactComponents.Spinner, { centering: "centered", containerClassName: "absolute inset-0" })) : props.noDataMessage ? (props.noDataMessage) : (jsxRuntime.jsx(reactComponents.EmptyState, { className: "absolute inset-0", description: t("table.noResults"), image: "SEARCH_DOCUMENT", ...props.emptyState })) }) }) }))] }) }), props.hideFooter ? null : (jsxRuntime.jsxs("div", { className: "flex items-center p-2", children: [jsxRuntime.jsx("div", { className: "whitespace-nowrap text-xs font-medium text-neutral-600", children: t("table.pagination.full", {
570
+ count: props.getRowModel().rows.length,
571
+ total: ((_b = (_a = props.pagination) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.count) || 0,
572
+ }) }), ((_c = props.pagination) === null || _c === void 0 ? void 0 : _c.isLoading) ? (jsxRuntime.jsx("span", { className: "ml-2", children: jsxRuntime.jsx(reactComponents.Spinner, { size: "small" }) })) : null, props.footerRightActions ? jsxRuntime.jsx("div", { className: "flex flex-1 justify-end", children: props.footerRightActions }) : null] }))] }));
573
+ };
574
+ const cvaTBody = cssClassVarianceUtilities.cvaMerge(["min-h-[40dvh]"], {
575
+ variants: {
576
+ emptyState: {
577
+ true: "min-h-[400px]",
578
+ },
579
+ },
580
+ defaultVariants: {
581
+ emptyState: false,
582
+ },
583
+ });
584
+
585
+ /**
586
+ * Creates and returns a memoized instance of a columnHelper
587
+ */
588
+ const useColumnHelper = () => {
589
+ return React.useMemo(() => {
590
+ return reactTable.createColumnHelper();
591
+ }, []);
592
+ };
593
+
585
594
  /**
586
595
  * Hook for managing and controlling a table's state and behavior.
587
596
  *
@@ -627,12 +636,12 @@ const useTable = ({ onTableStateChange, initialState, columns, ...reactTableProp
627
636
  const [columnSizing, setColumnSizing] = React.useState(((_d = reactTableProps.state) === null || _d === void 0 ? void 0 : _d.columnSizing) || (initialState === null || initialState === void 0 ? void 0 : initialState.columnSizing) || {});
628
637
  React.useEffect(() => {
629
638
  if (initialState && sharedUtils.objectKeys(initialState).length > 0) {
630
- setColumnVisibility(initialState.columnVisibility || {});
631
- setColumnOrder(initialState.columnOrder || []);
639
+ setColumnVisibility(updatedInitialColumnVisibility);
640
+ setColumnOrder(updatedInitialColumnOrder);
632
641
  setSorting(initialState.sorting || []);
633
642
  setColumnSizing(initialState.columnSizing || {});
634
643
  }
635
- }, [initialState, initialState === null || initialState === void 0 ? void 0 : initialState.columnVisibility, initialState === null || initialState === void 0 ? void 0 : initialState.sorting, initialState === null || initialState === void 0 ? void 0 : initialState.columnSizing]);
644
+ }, [initialState, updatedInitialColumnOrder, updatedInitialColumnVisibility]);
636
645
  const state = React.useMemo(() => {
637
646
  return {
638
647
  sorting,
@@ -817,5 +826,6 @@ exports.Sorting = Sorting;
817
826
  exports.Table = Table;
818
827
  exports.fromTUSortToTanStack = fromTUSortToTanStack;
819
828
  exports.fromTanStackToTUSort = fromTanStackToTUSort;
829
+ exports.useColumnHelper = useColumnHelper;
820
830
  exports.useTable = useTable;
821
831
  exports.useTableSelection = useTableSelection;
package/index.esm.js CHANGED
@@ -1,20 +1,20 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation } from '@trackunit/i18n-library-translation';
3
- import { MenuItem, Icon, Button, useOverflowItems, MoreMenu, MenuList, Spacer, Card, Text, cvaInteractableItem, Spinner, EmptyState, Tooltip, Popover, PopoverTrigger, PopoverContent } from '@trackunit/react-components';
3
+ import { MenuItem, Icon, Button, useOverflowItems, MoreMenu, MenuList, Spacer, Tooltip, Popover, PopoverTrigger, PopoverContent, Text, Card, cvaInteractableItem, Spinner, EmptyState } from '@trackunit/react-components';
4
4
  import { objectValues, nonNullable, objectKeys, objectEntries } from '@trackunit/shared-utils';
5
5
  import * as React from 'react';
6
- import { useMemo, Children, cloneElement, useRef, useEffect, useState, useCallback } from 'react';
6
+ import { useMemo, Children, cloneElement, useEffect, useRef, useState, useCallback } from 'react';
7
7
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
8
8
  import { Link } from '@tanstack/react-router';
9
- import { flexRender, useReactTable, getSortedRowModel, getCoreRowModel, createColumnHelper } from '@tanstack/react-table';
10
- export { createColumnHelper } from '@tanstack/react-table';
11
- import { TableRoot, Thead, Tr, Th, SortIndicator, ResizeHandle, Tbody, Td } from '@trackunit/react-table-base-components';
12
- import { useInfiniteScroll, noPagination } from '@trackunit/react-table-pagination';
13
- import { twMerge } from 'tailwind-merge';
14
9
  import { Toggle, RadioGroup, RadioItem, Checkbox } from '@trackunit/react-form-components';
15
10
  import update from 'immutability-helper';
16
11
  import { DndProvider, useDrop, useDrag } from 'react-dnd';
17
12
  import { HTML5Backend } from 'react-dnd-html5-backend';
13
+ import { flexRender, createColumnHelper, useReactTable, getSortedRowModel, getCoreRowModel } from '@tanstack/react-table';
14
+ export { createColumnHelper } from '@tanstack/react-table';
15
+ import { TableRoot, Thead, Tr, Th, SortIndicator, ResizeHandle, Tbody, Td } from '@trackunit/react-table-base-components';
16
+ import { useInfiniteScroll, noPagination } from '@trackunit/react-table-pagination';
17
+ import { twMerge } from 'tailwind-merge';
18
18
  import { SortOrder, validateStringAsAssetSortByProperty } from '@trackunit/react-core-contexts-api';
19
19
 
20
20
  var defaultTranslations = {
@@ -270,94 +270,6 @@ const ActionSheet = ({ actions, dropdownActions, moreActions = [], selections, r
270
270
  moreActions: moreActions.map(action => actionDataToMenuItem(action, dataTestId)) })] }));
271
271
  };
272
272
 
273
- /**
274
- * Table component for displaying large sets of data in tables with infinite scroll, sorting, filtering and others.
275
- *
276
- * @param {ReactTable} props - The props for the Table component
277
- * @returns {JSX.Element} Table component
278
- */
279
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
280
- const Table = ({ rowHeight = 75, ...props }) => {
281
- var _a, _b, _c;
282
- //we need a reference to the scrolling element for logic down below
283
- const tableContainerRef = useRef(null);
284
- const [t] = useTranslation();
285
- const { fetchMoreOnBottomReached, getVirtualItems, getTotalSize } = useInfiniteScroll({
286
- pagination: props.pagination || noPagination,
287
- containerRef: tableContainerRef,
288
- rowSize: props.getRowModel().rows.length || 0,
289
- rowHeight,
290
- });
291
- const hasResults = props.getRowModel().rows.length > 0;
292
- return (jsxs(Card, { className: twMerge("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 items-center", children: props.headerLeftActions }), jsx("div", { className: "flex items-center", children: props.headerRightActions })] })) : null, jsx("div", { className: "h-full overflow-x-auto overflow-y-scroll border-b border-t border-gray-300", onScroll: e => fetchMoreOnBottomReached(e.target), ref: tableContainerRef, children: jsxs(TableRoot, { style: {
293
- height: hasResults ? "auto" : "100%",
294
- width: "100%",
295
- position: "relative",
296
- }, children: [jsx(Thead, { className: "z-default", children: props.getHeaderGroups().map(headerGroup => (jsx(Tr, { className: "flex", children: headerGroup.headers.map(header => {
297
- var _a, _b, _c, _d, _e, _f;
298
- const tooltipLabel = (_b = (_a = header.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.tootipLabel) !== null && _b !== void 0 ? _b : (typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : "");
299
- return (jsxs(Th, { className: "relative", style: {
300
- width: header.getSize(),
301
- minWidth: header.column.columnDef.minSize,
302
- maxWidth: header.column.columnDef.maxSize,
303
- textAlign: ((_c = header.column.columnDef.meta) === null || _c === void 0 ? void 0 : _c.alignment) || "left",
304
- flexGrow: ((_d = header.column.columnDef.meta) === null || _d === void 0 ? void 0 : _d.shouldGrow) ? 1 : 0,
305
- }, tooltipLabel: tooltipLabel, children: [header.isPlaceholder ? null : (jsxs("div", { className: `${header.column.getCanSort() ? "cursor-pointer select-none flex" : "flex"} items-center gap-2 py-2 overflow-hidden pr-3 w-full`,
306
- onClick: header.column.getToggleSortingHandler(), children: [jsxs("span", { className: "overflow-hidden text-ellipsis whitespace-nowrap", children: [flexRender(header.column.columnDef.header, header.getContext()), ((_e = header.column.columnDef.meta) === null || _e === void 0 ? void 0 : _e.subHeader) ? (jsx(Text, { size: "small", subtle: true, children: header.column.columnDef.meta.subHeader })) : null] }), header.column.getCanSort() ? (jsx(SortIndicator, { sortingState: header.column.getIsSorted() })) : null] })), !((_f = header.column.columnDef.meta) === null || _f === void 0 ? void 0 : _f.shouldGrow) && header.column.getCanResize() ? (jsx(ResizeHandle, { isResizing: header.column.getIsResizing(), onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler() })) : null] }, header.id));
307
- }) }, headerGroup.id))) }), hasResults ? (jsx(Tbody, { className: "text-sm font-normal", style: {
308
- height: `${getTotalSize()}px`,
309
- flexGrow: 1,
310
- }, children: getVirtualItems().map((virtualRow, index) => {
311
- const row = props.getRowModel().rows[virtualRow.index];
312
- if (!row) {
313
- return null;
314
- }
315
- else {
316
- return (jsx(Tr, { className: cvaInteractableItem({
317
- cursor: !!props.onRowClick || row.getCanSelect() ? "pointer" : "default",
318
- selected: "auto",
319
- }), dataTestId: `table-body-row-${virtualRow.index}`, layout: "flex", onClick: () => {
320
- if (props.onRowClick) {
321
- props.onRowClick(row);
322
- }
323
- else if (row.getCanSelect()) {
324
- row.toggleSelected();
325
- }
326
- }, style: {
327
- height: `${virtualRow.size}px`,
328
- transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
329
- }, children: row.getVisibleCells().map(cell => {
330
- var _a, _b;
331
- return (jsx(Td, { onClick: event => {
332
- // prevent onRowClick action when clicking on a "selectable" cell with checkbox
333
- if (props.selectionColId && cell.column.id === props.selectionColId) {
334
- event.stopPropagation();
335
- }
336
- }, style: {
337
- width: cell.column.getSize(),
338
- minWidth: cell.column.columnDef.minSize,
339
- maxWidth: cell.column.columnDef.maxSize,
340
- textAlign: ((_a = cell.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.alignment) || "left",
341
- flexGrow: ((_b = cell.column.columnDef.meta) === null || _b === void 0 ? void 0 : _b.shouldGrow) ? 1 : 0,
342
- }, children: jsx("div", { className: "grid h-full items-center", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }) }, cell.id));
343
- }) }, row.id));
344
- }
345
- }) })) : (jsx("tbody", { className: cvaTBody({ emptyState: !props.loading && !props.noDataMessage }), children: jsx("tr", { children: jsx("td", { className: "b-0", children: props.loading ? (jsx(Spinner, { centering: "centered", containerClassName: "absolute inset-0" })) : props.noDataMessage ? (props.noDataMessage) : (jsx(EmptyState, { className: "absolute inset-0", description: t("table.noResults"), image: "SEARCH_DOCUMENT", ...props.emptyState })) }) }) }))] }) }), props.hideFooter ? null : (jsxs("div", { className: "flex items-center p-2", children: [jsx("div", { className: "whitespace-nowrap text-xs font-medium text-neutral-600", children: t("table.pagination.full", {
346
- count: props.getRowModel().rows.length,
347
- total: ((_b = (_a = props.pagination) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.count) || 0,
348
- }) }), ((_c = props.pagination) === null || _c === void 0 ? void 0 : _c.isLoading) ? (jsx("span", { className: "ml-2", children: jsx(Spinner, { size: "small" }) })) : null, props.footerRightActions ? jsx("div", { className: "flex flex-1 justify-end", children: props.footerRightActions }) : null] }))] }));
349
- };
350
- const cvaTBody = cvaMerge(["min-h-[40dvh]"], {
351
- variants: {
352
- emptyState: {
353
- true: "min-h-[400px]",
354
- },
355
- },
356
- defaultVariants: {
357
- emptyState: false,
358
- },
359
- });
360
-
361
273
  const cvaColumnFilterGrabbable = cvaMerge(["flex", "items-center", "justify-center"], {
362
274
  variants: {
363
275
  disabled: {
@@ -563,6 +475,103 @@ const Sorting = ({ columns, }) => {
563
475
  }) }), jsxs(RadioGroup, { id: "sortOrder", onChange: onSelectOrder, value: currentSortDirection, children: [jsx(RadioItem, { className: "w-full", label: t("table.sorting.ascending"), value: "asc" }), jsx(RadioItem, { className: "w-full", label: t("table.sorting.descending"), value: "desc" })] })] }) })] }) }));
564
476
  };
565
477
 
478
+ /**
479
+ * Table component for displaying large sets of data in tables with infinite scroll, sorting, filtering and others.
480
+ *
481
+ * @param {ReactTable} props - The props for the Table component
482
+ * @returns {JSX.Element} Table component
483
+ */
484
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
485
+ const Table = ({ rowHeight = 75, ...props }) => {
486
+ var _a, _b, _c;
487
+ //we need a reference to the scrolling element for logic down below
488
+ const tableContainerRef = useRef(null);
489
+ const [t] = useTranslation();
490
+ const { fetchMoreOnBottomReached, getVirtualItems, getTotalSize } = useInfiniteScroll({
491
+ pagination: props.pagination || noPagination,
492
+ containerRef: tableContainerRef,
493
+ rowSize: props.getRowModel().rows.length || 0,
494
+ rowHeight,
495
+ });
496
+ const hasResults = props.getRowModel().rows.length > 0;
497
+ return (jsxs(Card, { className: twMerge("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 items-center", children: props.headerLeftActions }), jsx("div", { className: "flex items-center", children: props.headerRightActions })] })) : null, jsx("div", { className: "h-full overflow-x-auto overflow-y-scroll border-b border-t border-gray-300", onScroll: e => fetchMoreOnBottomReached(e.target), ref: tableContainerRef, children: jsxs(TableRoot, { style: {
498
+ height: hasResults ? "auto" : "100%",
499
+ width: "100%",
500
+ position: "relative",
501
+ }, children: [jsx(Thead, { className: "z-default", children: props.getHeaderGroups().map(headerGroup => (jsx(Tr, { className: "flex", children: headerGroup.headers.map(header => {
502
+ var _a, _b, _c, _d, _e, _f;
503
+ const tooltipLabel = (_b = (_a = header.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.tootipLabel) !== null && _b !== void 0 ? _b : (typeof header.column.columnDef.header === "string" ? header.column.columnDef.header : "");
504
+ return (jsxs(Th, { className: "relative", style: {
505
+ width: header.getSize(),
506
+ minWidth: header.column.columnDef.minSize,
507
+ maxWidth: header.column.columnDef.maxSize,
508
+ textAlign: ((_c = header.column.columnDef.meta) === null || _c === void 0 ? void 0 : _c.alignment) || "left",
509
+ flexGrow: ((_d = header.column.columnDef.meta) === null || _d === void 0 ? void 0 : _d.shouldGrow) ? 1 : 0,
510
+ }, tooltipLabel: tooltipLabel, children: [header.isPlaceholder ? null : (jsxs("div", { className: `${header.column.getCanSort() ? "cursor-pointer select-none flex" : "flex"} items-center gap-2 py-2 overflow-hidden pr-3 w-full`,
511
+ onClick: header.column.getToggleSortingHandler(), children: [jsxs("span", { className: "overflow-hidden text-ellipsis whitespace-nowrap", children: [flexRender(header.column.columnDef.header, header.getContext()), ((_e = header.column.columnDef.meta) === null || _e === void 0 ? void 0 : _e.subHeader) ? (jsx(Text, { size: "small", subtle: true, children: header.column.columnDef.meta.subHeader })) : null] }), header.column.getCanSort() ? (jsx(SortIndicator, { sortingState: header.column.getIsSorted() })) : null] })), !((_f = header.column.columnDef.meta) === null || _f === void 0 ? void 0 : _f.shouldGrow) && header.column.getCanResize() ? (jsx(ResizeHandle, { isResizing: header.column.getIsResizing(), onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler() })) : null] }, header.id));
512
+ }) }, headerGroup.id))) }), hasResults ? (jsx(Tbody, { className: "text-sm font-normal", style: {
513
+ height: `${getTotalSize()}px`,
514
+ flexGrow: 1,
515
+ }, children: getVirtualItems().map((virtualRow, index) => {
516
+ const row = props.getRowModel().rows[virtualRow.index];
517
+ if (!row) {
518
+ return null;
519
+ }
520
+ else {
521
+ return (jsx(Tr, { className: cvaInteractableItem({
522
+ cursor: !!props.onRowClick || row.getCanSelect() ? "pointer" : "default",
523
+ selected: "auto",
524
+ }), dataTestId: `table-body-row-${virtualRow.index}`, layout: "flex", onClick: () => {
525
+ if (props.onRowClick) {
526
+ props.onRowClick(row);
527
+ }
528
+ else if (row.getCanSelect()) {
529
+ row.toggleSelected();
530
+ }
531
+ }, style: {
532
+ height: `${virtualRow.size}px`,
533
+ transform: `translateY(${virtualRow.start - index * virtualRow.size}px)`,
534
+ }, children: row.getVisibleCells().map(cell => {
535
+ var _a, _b;
536
+ return (jsx(Td, { onClick: event => {
537
+ // prevent onRowClick action when clicking on a "selectable" cell with checkbox
538
+ if (props.selectionColId && cell.column.id === props.selectionColId) {
539
+ event.stopPropagation();
540
+ }
541
+ }, style: {
542
+ width: cell.column.getSize(),
543
+ minWidth: cell.column.columnDef.minSize,
544
+ maxWidth: cell.column.columnDef.maxSize,
545
+ textAlign: ((_a = cell.column.columnDef.meta) === null || _a === void 0 ? void 0 : _a.alignment) || "left",
546
+ flexGrow: ((_b = cell.column.columnDef.meta) === null || _b === void 0 ? void 0 : _b.shouldGrow) ? 1 : 0,
547
+ }, children: jsx("div", { className: "grid h-full items-center", children: flexRender(cell.column.columnDef.cell, cell.getContext()) }) }, cell.id));
548
+ }) }, row.id));
549
+ }
550
+ }) })) : (jsx("tbody", { className: cvaTBody({ emptyState: !props.loading && !props.noDataMessage }), children: jsx("tr", { children: jsx("td", { className: "b-0", children: props.loading ? (jsx(Spinner, { centering: "centered", containerClassName: "absolute inset-0" })) : props.noDataMessage ? (props.noDataMessage) : (jsx(EmptyState, { className: "absolute inset-0", description: t("table.noResults"), image: "SEARCH_DOCUMENT", ...props.emptyState })) }) }) }))] }) }), props.hideFooter ? null : (jsxs("div", { className: "flex items-center p-2", children: [jsx("div", { className: "whitespace-nowrap text-xs font-medium text-neutral-600", children: t("table.pagination.full", {
551
+ count: props.getRowModel().rows.length,
552
+ total: ((_b = (_a = props.pagination) === null || _a === void 0 ? void 0 : _a.pageInfo) === null || _b === void 0 ? void 0 : _b.count) || 0,
553
+ }) }), ((_c = props.pagination) === null || _c === void 0 ? void 0 : _c.isLoading) ? (jsx("span", { className: "ml-2", children: jsx(Spinner, { size: "small" }) })) : null, props.footerRightActions ? jsx("div", { className: "flex flex-1 justify-end", children: props.footerRightActions }) : null] }))] }));
554
+ };
555
+ const cvaTBody = cvaMerge(["min-h-[40dvh]"], {
556
+ variants: {
557
+ emptyState: {
558
+ true: "min-h-[400px]",
559
+ },
560
+ },
561
+ defaultVariants: {
562
+ emptyState: false,
563
+ },
564
+ });
565
+
566
+ /**
567
+ * Creates and returns a memoized instance of a columnHelper
568
+ */
569
+ const useColumnHelper = () => {
570
+ return useMemo(() => {
571
+ return createColumnHelper();
572
+ }, []);
573
+ };
574
+
566
575
  /**
567
576
  * Hook for managing and controlling a table's state and behavior.
568
577
  *
@@ -608,12 +617,12 @@ const useTable = ({ onTableStateChange, initialState, columns, ...reactTableProp
608
617
  const [columnSizing, setColumnSizing] = useState(((_d = reactTableProps.state) === null || _d === void 0 ? void 0 : _d.columnSizing) || (initialState === null || initialState === void 0 ? void 0 : initialState.columnSizing) || {});
609
618
  useEffect(() => {
610
619
  if (initialState && objectKeys(initialState).length > 0) {
611
- setColumnVisibility(initialState.columnVisibility || {});
612
- setColumnOrder(initialState.columnOrder || []);
620
+ setColumnVisibility(updatedInitialColumnVisibility);
621
+ setColumnOrder(updatedInitialColumnOrder);
613
622
  setSorting(initialState.sorting || []);
614
623
  setColumnSizing(initialState.columnSizing || {});
615
624
  }
616
- }, [initialState, initialState === null || initialState === void 0 ? void 0 : initialState.columnVisibility, initialState === null || initialState === void 0 ? void 0 : initialState.sorting, initialState === null || initialState === void 0 ? void 0 : initialState.columnSizing]);
625
+ }, [initialState, updatedInitialColumnOrder, updatedInitialColumnVisibility]);
617
626
  const state = useMemo(() => {
618
627
  return {
619
628
  sorting,
@@ -787,4 +796,4 @@ const fromTanStackToTUSort = (input) => {
787
796
  */
788
797
  setupLibraryTranslations();
789
798
 
790
- export { ActionSheet, ColumnFilter, RowSpacing, Sorting, Table, fromTUSortToTanStack, fromTanStackToTUSort, useTable, useTableSelection };
799
+ export { ActionSheet, ColumnFilter, RowSpacing, Sorting, Table, fromTUSortToTanStack, fromTanStackToTUSort, useColumnHelper, useTable, useTableSelection };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-table",
3
- "version": "0.0.589",
3
+ "version": "0.0.591",
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
@@ -1,10 +1,11 @@
1
1
  import { ColumnSort } from "@tanstack/react-table";
2
2
  export * from "./ActionSheet";
3
- export * from "./Table";
4
3
  export * from "./menus/ColumnFilter";
5
4
  export * from "./menus/RowSpacing";
6
5
  export * from "./menus/Sorting";
6
+ export * from "./Table";
7
7
  export * from "./types";
8
+ export * from "./useColumnHelper";
8
9
  export * from "./useTable";
9
10
  export * from "./useTableSelection";
10
11
  export * from "./utils";
@@ -0,0 +1,5 @@
1
+ import { RowData } from "@tanstack/react-table";
2
+ /**
3
+ * Creates and returns a memoized instance of a columnHelper
4
+ */
5
+ export declare const useColumnHelper: <TData extends RowData>() => import("@tanstack/react-table").ColumnHelper<TData>;