@synerise/ds-table-new 0.1.0 → 1.0.2

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.
Files changed (62) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +57 -1
  3. package/dist/Table.d.ts +1 -1
  4. package/dist/Table.js +29 -3
  5. package/dist/Table.styles.d.ts +0 -1
  6. package/dist/Table.styles.js +0 -5
  7. package/dist/Table.types.d.ts +164 -10
  8. package/dist/VirtualTable.d.ts +1 -1
  9. package/dist/VirtualTable.js +33 -3
  10. package/dist/components/BackToTopButton/BackToTopButton.d.ts +11 -0
  11. package/dist/components/BackToTopButton/BackToTopButton.js +34 -0
  12. package/dist/components/BackToTopButton/BackToTopButton.styles.d.ts +3 -0
  13. package/dist/components/BackToTopButton/BackToTopButton.styles.js +8 -0
  14. package/dist/components/BaseTable/BaseTable.d.ts +1 -1
  15. package/dist/components/BaseTable/BaseTable.js +10 -5
  16. package/dist/components/BaseTable/BaseTable.styles.js +1 -1
  17. package/dist/components/Cell/LabelsWithShowMore/Modal/Modal.js +9 -14
  18. package/dist/components/ItemsMenu/ItemsMenu.d.ts +7 -0
  19. package/dist/components/ItemsMenu/ItemsMenu.js +9 -0
  20. package/dist/components/ItemsMenu/ItemsMenu.styles.d.ts +3 -0
  21. package/dist/components/ItemsMenu/ItemsMenu.styles.js +10 -0
  22. package/dist/components/TableBody/TableBody.d.ts +1 -1
  23. package/dist/components/TableBody/TableBody.js +26 -5
  24. package/dist/components/TableBody/TableBody.styles.d.ts +4 -1
  25. package/dist/components/TableBody/TableBody.styles.js +2 -2
  26. package/dist/components/TableBody/TableCell/TableCell.d.ts +2 -1
  27. package/dist/components/TableBody/TableCell/TableCell.js +2 -1
  28. package/dist/components/TableBody/TableCell/TableCell.styles.d.ts +4 -1
  29. package/dist/components/TableBody/TableCell/TableCell.styles.js +7 -2
  30. package/dist/components/TableBody/TableRow/TableRow.d.ts +1 -3
  31. package/dist/components/TableBody/TableRow/TableRow.js +3 -5
  32. package/dist/components/TableBody/TableRow/TableRowVirtual.js +3 -2
  33. package/dist/components/TableBody/TableRowSelection/TableRowSelection.js +2 -1
  34. package/dist/components/TableColumns/TableColumns.js +2 -1
  35. package/dist/components/TableColumns/TableColumns.styles.d.ts +4 -1
  36. package/dist/components/TableColumns/TableColumns.styles.js +7 -2
  37. package/dist/components/TableHeader/TableHeader.d.ts +1 -1
  38. package/dist/components/TableHeader/TableHeader.js +14 -6
  39. package/dist/components/TableHeader/TableHeaderSelection/TableHeaderSelection.js +37 -16
  40. package/dist/components/TableHeader/TableLimit/TableLimit.js +4 -3
  41. package/dist/components/TableHeader/TableLimit/TableLimit.styles.d.ts +0 -1
  42. package/dist/components/TableHeader/TableLimit/TableLimit.styles.js +0 -5
  43. package/dist/components/TableHorizontalScroll/TableHorizontalScroll.js +7 -11
  44. package/dist/components/TreeTable/TreeTable.d.ts +3 -0
  45. package/dist/components/TreeTable/TreeTable.js +106 -0
  46. package/dist/components/TreeTable/TreeTable.styles.d.ts +15 -0
  47. package/dist/components/TreeTable/TreeTable.styles.js +46 -0
  48. package/dist/components/TreeTable/TreeTable.types.d.ts +26 -0
  49. package/dist/components/TreeTable/TreeTable.types.js +1 -0
  50. package/dist/hooks/useDefaultTexts.js +19 -15
  51. package/dist/hooks/useTable.d.ts +7 -2
  52. package/dist/hooks/useTable.js +23 -2
  53. package/dist/hooks/useTableHighlight.d.ts +5 -0
  54. package/dist/hooks/useTableHighlight.js +33 -0
  55. package/dist/hooks/useTableSearch.d.ts +13 -0
  56. package/dist/hooks/useTableSearch.js +36 -0
  57. package/dist/index.d.ts +2 -0
  58. package/dist/index.js +2 -0
  59. package/dist/types/table.d.ts +1 -0
  60. package/dist/utils/legacyColumnConfigAdapter.d.ts +1 -1
  61. package/dist/utils/legacyColumnConfigAdapter.js +8 -5
  62. package/package.json +6 -7
@@ -1,9 +1,8 @@
1
- import { jsxs, Fragment, jsx } from "react/jsx-runtime";
1
+ import { jsx, Fragment, jsxs } from "react/jsx-runtime";
2
2
  import { forwardRef, useState, useRef, useCallback } from "react";
3
3
  import { useMergeRefs } from "@floating-ui/react";
4
- import Scrollbar from "@synerise/ds-scrollbar";
5
4
  import { useResizeObserver } from "@synerise/ds-utils";
6
- import { HorizontalScrollContainer, LeftShadow, HorizontalScrollWrapper, RightShadow, ScrollbarWrapper } from "./TableHorizontalScroll.styles.js";
5
+ import { HorizontalScrollContainer, LeftShadow, HorizontalScrollWrapper, RightShadow } from "./TableHorizontalScroll.styles.js";
7
6
  const TableHorizontalScroll = forwardRef(({
8
7
  children,
9
8
  stickyLeft = 0,
@@ -27,14 +26,11 @@ const TableHorizontalScroll = forwardRef(({
27
26
  calculateOffsets(event.currentTarget);
28
27
  }, [calculateOffsets]);
29
28
  useResizeObserver(wrapperRef, () => wrapperRef.current && calculateOffsets(wrapperRef.current));
30
- return /* @__PURE__ */ jsxs(Fragment, { children: [
31
- /* @__PURE__ */ jsxs(HorizontalScrollContainer, { showLeftShadow: !isMaxLeft, showRightShadow: !isMaxRight, ...rest, children: [
32
- /* @__PURE__ */ jsx(LeftShadow, { offset: stickyLeft }),
33
- /* @__PURE__ */ jsx(HorizontalScrollWrapper, { ref: mergedRef, onScroll: handleScroll, children }),
34
- /* @__PURE__ */ jsx(RightShadow, { offset: stickyRight })
35
- ] }),
36
- /* @__PURE__ */ jsx(ScrollbarWrapper, { children: /* @__PURE__ */ jsx(Scrollbar, {}) })
37
- ] });
29
+ return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsxs(HorizontalScrollContainer, { showLeftShadow: !isMaxLeft, showRightShadow: !isMaxRight, ...rest, children: [
30
+ /* @__PURE__ */ jsx(LeftShadow, { offset: stickyLeft }),
31
+ /* @__PURE__ */ jsx(HorizontalScrollWrapper, { ref: mergedRef, onScroll: handleScroll, children }),
32
+ /* @__PURE__ */ jsx(RightShadow, { offset: stickyRight })
33
+ ] }) });
38
34
  });
39
35
  export {
40
36
  TableHorizontalScroll
@@ -0,0 +1,3 @@
1
+ import { default as React } from 'react';
2
+ import { TreeTableProps } from './TreeTable.types';
3
+ export declare const TreeTable: <TData extends object, TValue>({ data, columns, childrenColumnName, defaultExpandAllRows, expandedRowKeys: controlledExpandedKeys, onExpandRow, expandIconColumnIndex, rowKey, ...props }: TreeTableProps<TData, TValue>) => React.JSX.Element;
@@ -0,0 +1,106 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useState, useEffect, useMemo } from "react";
3
+ import { Expander } from "@synerise/ds-button";
4
+ import { theme } from "@synerise/ds-core";
5
+ import Icon, { ChildRowLeftDownM } from "@synerise/ds-icon";
6
+ import { Table } from "../../Table.js";
7
+ import { IndentBar, TreeCellWrapper, IndentsContainer, ExpanderWrapper, INDENT_SIZE, TreeTableRoot } from "./TreeTable.styles.js";
8
+ const getAllKeys = (data, childrenKey, getRowKey) => {
9
+ const keys = [];
10
+ const traverse = (rows) => {
11
+ for (const row of rows) {
12
+ keys.push(getRowKey(row));
13
+ const children = row[childrenKey];
14
+ if (children?.length) {
15
+ traverse(children);
16
+ }
17
+ }
18
+ };
19
+ traverse(data);
20
+ return keys;
21
+ };
22
+ const TreeTable = ({
23
+ data,
24
+ columns,
25
+ childrenColumnName,
26
+ defaultExpandAllRows,
27
+ expandedRowKeys: controlledExpandedKeys,
28
+ onExpandRow,
29
+ expandIconColumnIndex = 0,
30
+ rowKey,
31
+ ...props
32
+ }) => {
33
+ const childrenKey = childrenColumnName ?? "children";
34
+ const getRowKey = useCallback((row) => {
35
+ if (typeof rowKey === "function") {
36
+ return rowKey(row);
37
+ }
38
+ if (typeof rowKey === "string") {
39
+ return String(row[rowKey]);
40
+ }
41
+ return String(row.key ?? row.id ?? "");
42
+ }, [rowKey]);
43
+ const [internalExpandedKeys, setInternalExpandedKeys] = useState(() => {
44
+ if (defaultExpandAllRows) {
45
+ return getAllKeys(data, childrenKey, getRowKey);
46
+ }
47
+ return [];
48
+ });
49
+ useEffect(() => {
50
+ if (defaultExpandAllRows) {
51
+ setInternalExpandedKeys(getAllKeys(data, childrenKey, getRowKey));
52
+ }
53
+ }, [data, defaultExpandAllRows, childrenKey, getRowKey]);
54
+ const expandedKeys = controlledExpandedKeys ?? internalExpandedKeys;
55
+ const toggleExpand = useCallback((key) => {
56
+ const isExpanded = expandedKeys.includes(key);
57
+ onExpandRow?.(key, !isExpanded);
58
+ if (!controlledExpandedKeys) {
59
+ setInternalExpandedKeys((prev) => isExpanded ? prev.filter((k) => k !== key) : [...prev, key]);
60
+ }
61
+ }, [expandedKeys, onExpandRow, controlledExpandedKeys]);
62
+ const hasChildren = useCallback((row) => {
63
+ const children = row[childrenKey];
64
+ return !!children?.length;
65
+ }, [childrenKey]);
66
+ const treeColumns = useMemo(() => {
67
+ if (!columns.length || expandIconColumnIndex < 0) {
68
+ return columns;
69
+ }
70
+ const targetIndex = Math.min(expandIconColumnIndex, columns.length - 1);
71
+ return columns.map((col, index) => {
72
+ if (index !== targetIndex) {
73
+ return col;
74
+ }
75
+ return {
76
+ ...col,
77
+ cell: (info) => {
78
+ const depth = info.row.depth;
79
+ const rowData = info.row.original;
80
+ const rowId = getRowKey(rowData);
81
+ const isParent = hasChildren(rowData);
82
+ const isExpanded = expandedKeys.includes(rowId);
83
+ const indents = Array.from({
84
+ length: depth
85
+ }, (_, i) => /* @__PURE__ */ jsx(IndentBar, { $level: i, $active: i + 1 === depth }, i));
86
+ const originalCell = typeof col.cell === "function" ? col.cell(info) : info.getValue();
87
+ return /* @__PURE__ */ jsxs(TreeCellWrapper, { $indentWidth: depth * INDENT_SIZE, children: [
88
+ depth > 0 && /* @__PURE__ */ jsx(IndentsContainer, { $depth: depth, children: indents }),
89
+ /* @__PURE__ */ jsx(ExpanderWrapper, { children: isParent ? /* @__PURE__ */ jsx(Expander, { expanded: isExpanded, onClick: (e) => {
90
+ e.stopPropagation();
91
+ toggleExpand(rowId);
92
+ } }) : depth > 0 ? /* @__PURE__ */ jsx(Icon, { component: /* @__PURE__ */ jsx(ChildRowLeftDownM, {}), color: theme.palette["grey-400"] }) : null }),
93
+ originalCell
94
+ ] });
95
+ }
96
+ };
97
+ });
98
+ }, [columns, expandIconColumnIndex, getRowKey, hasChildren, expandedKeys, toggleExpand]);
99
+ return /* @__PURE__ */ jsx(TreeTableRoot, { children: /* @__PURE__ */ jsx(Table, { data, columns: treeColumns, rowKey, expandable: {
100
+ childrenColumnName: childrenKey,
101
+ expandedRowKeys: expandedKeys
102
+ }, ...props }) });
103
+ };
104
+ export {
105
+ TreeTable
106
+ };
@@ -0,0 +1,15 @@
1
+ declare const INDENT_SIZE = 42;
2
+ declare const LEVEL_COLORS: string[];
3
+ export declare const IndentsContainer: import('styled-components').StyledComponent<"div", any, {
4
+ $depth: number;
5
+ }, never>;
6
+ export declare const IndentBar: import('styled-components').StyledComponent<"span", any, {
7
+ $level: number;
8
+ $active: boolean;
9
+ }, never>;
10
+ export declare const ExpanderWrapper: import('styled-components').StyledComponent<"span", any, {}, never>;
11
+ export declare const TreeCellWrapper: import('styled-components').StyledComponent<"div", any, {
12
+ $indentWidth: number;
13
+ }, never>;
14
+ export declare const TreeTableRoot: import('styled-components').StyledComponent<"div", any, {}, never>;
15
+ export { INDENT_SIZE, LEVEL_COLORS };
@@ -0,0 +1,46 @@
1
+ import styled from "styled-components";
2
+ const INDENT_SIZE = 42;
3
+ const LEVEL_COLORS = ["yellow", "green", "cyan", "violet", "orange", "purple", "blue", "grey"];
4
+ const getColorHue = (active, level) => {
5
+ if (level === LEVEL_COLORS.indexOf("cyan") && active) {
6
+ return "500";
7
+ }
8
+ return active ? "600" : "200";
9
+ };
10
+ const IndentsContainer = /* @__PURE__ */ styled.div.withConfig({
11
+ displayName: "TreeTablestyles__IndentsContainer",
12
+ componentId: "sc-1t443rr-0"
13
+ })(["position:absolute;top:0;left:36px;height:100%;width:", "px;display:flex;"], ({
14
+ $depth
15
+ }) => $depth * INDENT_SIZE);
16
+ const IndentBar = /* @__PURE__ */ styled.span.withConfig({
17
+ displayName: "TreeTablestyles__IndentBar",
18
+ componentId: "sc-1t443rr-1"
19
+ })(["width:", "px;position:relative;&:before{content:'';position:absolute;top:0;left:0;height:100%;width:2px;background-color:", ";}"], INDENT_SIZE, ({
20
+ $level,
21
+ $active,
22
+ theme
23
+ }) => $level >= 0 ? theme.palette[`${LEVEL_COLORS[$level % LEVEL_COLORS.length]}-${getColorHue($active, $level)}`] : theme.palette["grey-600"]);
24
+ const ExpanderWrapper = /* @__PURE__ */ styled.span.withConfig({
25
+ displayName: "TreeTablestyles__ExpanderWrapper",
26
+ componentId: "sc-1t443rr-2"
27
+ })(["display:inline-flex;align-items:center;justify-content:flex-start;width:24px;margin-right:8px;flex-shrink:0;"]);
28
+ const TreeCellWrapper = /* @__PURE__ */ styled.div.withConfig({
29
+ displayName: "TreeTablestyles__TreeCellWrapper",
30
+ componentId: "sc-1t443rr-3"
31
+ })(["display:flex;align-items:center;width:100%;padding-left:", "px;"], ({
32
+ $indentWidth
33
+ }) => $indentWidth);
34
+ const TreeTableRoot = /* @__PURE__ */ styled.div.withConfig({
35
+ displayName: "TreeTablestyles__TreeTableRoot",
36
+ componentId: "sc-1t443rr-4"
37
+ })(["td{position:relative;font-weight:500;}"]);
38
+ export {
39
+ ExpanderWrapper,
40
+ INDENT_SIZE,
41
+ IndentBar,
42
+ IndentsContainer,
43
+ LEVEL_COLORS,
44
+ TreeCellWrapper,
45
+ TreeTableRoot
46
+ };
@@ -0,0 +1,26 @@
1
+ import { TableProps } from '../../Table.types';
2
+ export type TreeTableProps<TData, TValue> = Omit<TableProps<TData, TValue>, 'expandable'> & {
3
+ /**
4
+ * Property name on row data containing child rows.
5
+ * @default 'children'
6
+ */
7
+ childrenColumnName?: keyof TData;
8
+ /**
9
+ * Start with all rows expanded.
10
+ */
11
+ defaultExpandAllRows?: boolean;
12
+ /**
13
+ * Controlled expanded row keys. When provided, expand state is managed externally.
14
+ */
15
+ expandedRowKeys?: string[];
16
+ /**
17
+ * Called when a row's expand state changes (click on expander or row).
18
+ */
19
+ onExpandRow?: (key: string, expanded: boolean) => void;
20
+ /**
21
+ * Index of the column where the expand icon is rendered.
22
+ * Set to -1 to hide the expand icon entirely.
23
+ * @default 0
24
+ */
25
+ expandIconColumnIndex?: number;
26
+ };
@@ -4,21 +4,25 @@ const useDefaultTexts = (defaultTexts) => {
4
4
  const intl = useIntl();
5
5
  return useMemo(() => ({
6
6
  infiniteScrollLoading: intl.formatMessage({
7
- id: "DS.TABLE.INFINITE-SCROLL-LOADING",
7
+ id: "DS.TABLE.INFINITE_SCROLL.LOADING",
8
8
  defaultMessage: "Loading"
9
9
  }),
10
10
  infiniteScrollError: intl.formatMessage({
11
- id: "DS.TABLE.INFINITE-SCROLL-ERROR",
11
+ id: "DS.TABLE.INFINITE_SCROLL.ERROR",
12
12
  defaultMessage: "An error occurred"
13
13
  }),
14
14
  infiniteScrollRetry: intl.formatMessage({
15
- id: "DS.TABLE.INFINITE-SCROLL-RETRY",
15
+ id: "DS.TABLE.INFINITE_SCROLL.RETRY",
16
16
  defaultMessage: "Retry"
17
17
  }),
18
18
  infiniteScrollNoMoreData: intl.formatMessage({
19
- id: "DS.TABLE.INFINITE-SCROLL-NO-MORE-DATA",
19
+ id: "DS.TABLE.INFINITE_SCROLL.NO_MORE_DATA",
20
20
  defaultMessage: "There are no more items to load"
21
21
  }),
22
+ infiniteScrollBackToTop: intl.formatMessage({
23
+ id: "DS.TABLE.INFINITE_SCROLL.BACK_TO_TOP",
24
+ defaultMessage: "Back to top"
25
+ }),
22
26
  columnSortClear: intl.formatMessage({
23
27
  id: "DS.TABLE.COLUMN.SORT_CLEAR",
24
28
  defaultMessage: "Clear"
@@ -48,43 +52,43 @@ const useDefaultTexts = (defaultTexts) => {
48
52
  defaultMessage: "selected"
49
53
  }),
50
54
  selectAll: intl.formatMessage({
51
- id: "DS.TABLE.SELECT-ALL",
55
+ id: "DS.TABLE.SELECT_ALL",
52
56
  defaultMessage: "Select visible"
53
57
  }),
54
58
  selectAllTooltip: intl.formatMessage({
55
- id: "DS.TABLE.SELECT-ALL-TOOLTIP",
59
+ id: "DS.TABLE.SELECT_ALL_BUTTON_TOOLTIP",
56
60
  defaultMessage: "Select all"
57
61
  }),
58
62
  selectGlobalAll: intl.formatMessage({
59
- id: "DS.TABLE.SELECT-GLOBAL-ALL",
63
+ id: "DS.TABLE.SELECT_GLOBAL_ALL",
60
64
  defaultMessage: "Select all"
61
65
  }),
62
66
  selectInvert: intl.formatMessage({
63
- id: "DS.TABLE.SELECT-INVERT",
64
- defaultMessage: "Inverse selection"
67
+ id: "DS.TABLE.SELECT_INVERT",
68
+ defaultMessage: "Invert selection"
65
69
  }),
66
70
  selectionLimitWarning: intl.formatMessage({
67
- id: "DS.TABLE.SELECTION-LIMIT",
71
+ id: "DS.TABLE.SELECTION_LIMIT",
68
72
  defaultMessage: "You have reached max limit"
69
73
  }),
70
74
  selectionOptionsTooltip: intl.formatMessage({
71
- id: "DS.TABLE.SELECTIONS-MENU-TOOLTIP",
75
+ id: "DS.TABLE.SELECTIONS_MENU_TOOLTIP",
72
76
  defaultMessage: "Batch selection options"
73
77
  }),
74
78
  unselectAll: intl.formatMessage({
75
- id: "DS.TABLE.UNSELECT-ALL",
79
+ id: "DS.TABLE.UNSELECT_ALL",
76
80
  defaultMessage: "Unselect visible"
77
81
  }),
78
82
  unselectGlobalAll: intl.formatMessage({
79
- id: "DS.TABLE.UNSELECT-GLOBAL-ALL",
83
+ id: "DS.TABLE.UNSELECT_GLOBAL_ALL",
80
84
  defaultMessage: "Unselect all"
81
85
  }),
82
86
  emptyText: intl.formatMessage({
83
- id: "DS.TABLE.NO-DATA",
87
+ id: "DS.TABLE.NO_DATA",
84
88
  defaultMessage: "No data"
85
89
  }),
86
90
  selectRowTooltip: intl.formatMessage({
87
- id: "DS.TABLE.SELECT-ROW",
91
+ id: "DS.TABLE.SELECT_ROW_TOOLTIP",
88
92
  defaultMessage: "Select"
89
93
  }),
90
94
  ...defaultTexts
@@ -1,14 +1,19 @@
1
1
  import { MutableRefObject } from 'react';
2
2
  import { SharedTableProps, TableProps, VirtualTableProps } from '../Table.types';
3
- type UseTableProps<TData, TValue> = Pick<VirtualTableProps<TData, TValue>, 'infiniteScroll'> & Pick<TableProps<TData, TValue>, 'pagination'> & Pick<SharedTableProps<TData, TValue>, 'data' | 'selectionConfig' | 'columns' | 'rowKey' | 'onSort' | 'expandable' | 'selectedRowKeys'> & {
3
+ type UseTableProps<TData, TValue> = Pick<VirtualTableProps<TData, TValue>, 'infiniteScroll'> & Pick<TableProps<TData, TValue>, 'pagination'> & Pick<SharedTableProps<TData, TValue>, 'data' | 'selectionConfig' | 'columns' | 'rowKey' | 'onSort' | 'expandable' | 'selectedRowKeys' | 'matchesSearchQuery' | 'filterData' | 'onSearchQueryChange'> & {
4
4
  wrapperRef: MutableRefObject<HTMLDivElement | null>;
5
5
  requireColumnSizing?: boolean;
6
6
  };
7
- export declare const useTable: <TData, TValue>({ data, selectionConfig, columns, rowKey, wrapperRef, infiniteScroll, pagination, onSort, expandable, selectedRowKeys, requireColumnSizing, }: UseTableProps<TData, TValue>) => {
7
+ export declare const useTable: <TData, TValue>({ data, selectionConfig, columns, rowKey, wrapperRef, infiniteScroll, pagination, onSort, expandable, selectedRowKeys, matchesSearchQuery, filterData, onSearchQueryChange, requireColumnSizing, }: UseTableProps<TData, TValue>) => {
8
8
  table: import('@tanstack/react-table').Table<TData>;
9
9
  paginationProps: {} | {};
10
10
  hasPagination: boolean;
11
11
  columnSizing: import('@tanstack/react-table').ColumnSizingState;
12
12
  isColumnSizingReady: boolean;
13
+ searchQuery: string;
14
+ setSearchQuery: (query: string) => void;
15
+ handleSearchClear: () => void;
16
+ hasBuiltInSearch: boolean;
17
+ totalDataCount: number;
13
18
  };
14
19
  export {};
@@ -7,6 +7,7 @@ import { getChildrenColumnName } from "../utils/getChildrenColumnName.js";
7
7
  import { getPaginationConfig } from "../utils/getPaginationConfig.js";
8
8
  import { useColumnSizing } from "./useColumnSizing.js";
9
9
  import { useRowKey } from "./useRowKey.js";
10
+ import { useTableSearch } from "./useTableSearch.js";
10
11
  const useTable = ({
11
12
  data,
12
13
  selectionConfig,
@@ -18,6 +19,9 @@ const useTable = ({
18
19
  onSort,
19
20
  expandable,
20
21
  selectedRowKeys,
22
+ matchesSearchQuery,
23
+ filterData,
24
+ onSearchQueryChange,
21
25
  requireColumnSizing = true
22
26
  }) => {
23
27
  const [rowSelection, setRowSelection] = useState({});
@@ -33,6 +37,18 @@ const useTable = ({
33
37
  useLayoutEffect(() => {
34
38
  dataRef.current = data;
35
39
  }, [data]);
40
+ const {
41
+ displayData,
42
+ searchQuery,
43
+ setSearchQuery,
44
+ handleClear: handleSearchClear,
45
+ hasBuiltInSearch
46
+ } = useTableSearch({
47
+ data,
48
+ matchesSearchQuery,
49
+ filterData,
50
+ onSearchQueryChange
51
+ });
36
52
  const {
37
53
  getRowKey
38
54
  } = useRowKey(rowKey);
@@ -117,7 +133,7 @@ const useTable = ({
117
133
  const expandedKeys = expandable?.expandedRowKeys ? arrayToTrueMap(expandable?.expandedRowKeys) : void 0;
118
134
  const table = useReactTable({
119
135
  getRowId: memoizedGetRowKey,
120
- data,
136
+ data: displayData,
121
137
  columns,
122
138
  getSubRows: childrenColumnName ? getSubRows : void 0,
123
139
  getCoreRowModel: getCoreRowModel(),
@@ -160,7 +176,12 @@ const useTable = ({
160
176
  paginationProps,
161
177
  hasPagination,
162
178
  columnSizing,
163
- isColumnSizingReady
179
+ isColumnSizingReady,
180
+ searchQuery,
181
+ setSearchQuery,
182
+ handleSearchClear,
183
+ hasBuiltInSearch,
184
+ totalDataCount: data.length
164
185
  };
165
186
  };
166
187
  export {
@@ -0,0 +1,5 @@
1
+ import { MutableRefObject } from 'react';
2
+ import { HighlightOptions } from '../Table.types';
3
+ export declare const useTableHighlight: (containerRef: MutableRefObject<HTMLElement | null>) => {
4
+ highlightRow: (rowKey: string, options?: HighlightOptions) => void;
5
+ };
@@ -0,0 +1,33 @@
1
+ import { useCallback } from "react";
2
+ const HIGHLIGHT_CLASS = "ds-table-row-highlight";
3
+ const DEFAULT_HIGHLIGHT_DURATION = 600;
4
+ const useTableHighlight = (containerRef) => {
5
+ const highlightRow = useCallback((rowKey, options) => {
6
+ const container = containerRef.current;
7
+ if (!container) {
8
+ return;
9
+ }
10
+ const escapedKey = CSS.escape(rowKey);
11
+ const row = container.querySelector(`tr[data-key="${escapedKey}"], tr[data-row-key="${escapedKey}"]`);
12
+ if (!row) {
13
+ return;
14
+ }
15
+ const duration = options?.duration ?? DEFAULT_HIGHLIGHT_DURATION;
16
+ const el = row;
17
+ el.classList.remove(HIGHLIGHT_CLASS);
18
+ void el.offsetHeight;
19
+ el.style.setProperty("--ds-highlight-duration", `${duration}ms`);
20
+ el.classList.add(HIGHLIGHT_CLASS);
21
+ const onEnd = () => {
22
+ el.classList.remove(HIGHLIGHT_CLASS);
23
+ el.removeEventListener("animationend", onEnd);
24
+ };
25
+ el.addEventListener("animationend", onEnd);
26
+ }, [containerRef]);
27
+ return {
28
+ highlightRow
29
+ };
30
+ };
31
+ export {
32
+ useTableHighlight
33
+ };
@@ -0,0 +1,13 @@
1
+ import { SharedTableProps } from '../Table.types';
2
+ type UseTableSearchProps<TData> = Pick<SharedTableProps<TData, unknown>, 'matchesSearchQuery' | 'filterData' | 'onSearchQueryChange'> & {
3
+ data: TData[];
4
+ };
5
+ type UseTableSearchResult<TData> = {
6
+ displayData: TData[];
7
+ searchQuery: string;
8
+ setSearchQuery: (query: string) => void;
9
+ handleClear: () => void;
10
+ hasBuiltInSearch: boolean;
11
+ };
12
+ export declare const useTableSearch: <TData>({ data, matchesSearchQuery, filterData, onSearchQueryChange, }: UseTableSearchProps<TData>) => UseTableSearchResult<TData>;
13
+ export {};
@@ -0,0 +1,36 @@
1
+ import { useState, useCallback, useMemo } from "react";
2
+ const useTableSearch = ({
3
+ data,
4
+ matchesSearchQuery,
5
+ filterData,
6
+ onSearchQueryChange
7
+ }) => {
8
+ const [searchQuery, setSearchQueryState] = useState("");
9
+ const hasBuiltInSearch = !!matchesSearchQuery;
10
+ const setSearchQuery = useCallback((query) => {
11
+ setSearchQueryState(query);
12
+ onSearchQueryChange?.(query);
13
+ }, [onSearchQueryChange]);
14
+ const handleClear = useCallback(() => {
15
+ setSearchQuery("");
16
+ }, [setSearchQuery]);
17
+ const displayData = useMemo(() => {
18
+ if (matchesSearchQuery && searchQuery) {
19
+ return data.filter((row) => matchesSearchQuery(searchQuery, row));
20
+ }
21
+ if (filterData) {
22
+ return data.filter(filterData);
23
+ }
24
+ return data;
25
+ }, [data, matchesSearchQuery, searchQuery, filterData]);
26
+ return {
27
+ displayData,
28
+ searchQuery,
29
+ setSearchQuery,
30
+ handleClear,
31
+ hasBuiltInSearch
32
+ };
33
+ };
34
+ export {
35
+ useTableSearch
36
+ };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export { Table } from './Table';
2
+ export { TreeTable } from './components/TreeTable/TreeTable';
2
3
  export { VirtualTable } from './VirtualTable';
3
4
  /** @deprecated */
4
5
  export * as TableCell from './components/Cell';
5
6
  export * from './components/Cell';
6
7
  export * from './Table.types';
8
+ export type { TreeTableProps } from './components/TreeTable/TreeTable.types';
7
9
  export * from './Table.const';
8
10
  export { legacyColumnConfigAdapter } from './utils/legacyColumnConfigAdapter';
9
11
  export { type ColumnDef, type Row, type CellContext, type HeaderContext, } from '@tanstack/react-table';
package/dist/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import { Table } from "./Table.js";
2
+ import { TreeTable } from "./components/TreeTable/TreeTable.js";
2
3
  import { VirtualTable } from "./VirtualTable.js";
3
4
  import * as components_Cell_index from "./components/Cell/index.js";
4
5
  import { ACTION_COLUMN_ID, BOTTOM_BORDER_WIDTH, DEFAULT_CELL_HEIGHT, DEFAULT_PAGINATION_CONFIG, DEFAULT_STICKY_VALUE, EMPTY_SORT_STATE, EXPANDED_ROW_PROPERTY, INFINITE_LOADER_ITEM_HEIGHT, INFINITE_SCROLL_PADDING_START, INFINITE_SCROLL_TRIGGER_THRESHOLD, SELECTION_ALL, SELECTION_COLUMN_ID, SELECTION_INVERT } from "./Table.const.js";
@@ -45,6 +46,7 @@ export {
45
46
  components_Cell_index as TableCell,
46
47
  TagIconCell,
47
48
  TagsGroupCell,
49
+ TreeTable,
48
50
  VirtualTable,
49
51
  legacyColumnConfigAdapter
50
52
  };
@@ -7,6 +7,7 @@ declare module '@tanstack/react-table' {
7
7
  maxWidth?: number | string;
8
8
  width?: number | string;
9
9
  fixed?: 'left' | 'right';
10
+ align?: 'left' | 'center' | 'right';
10
11
  style?: CSSProperties<HTMLTableHeaderCellElement>;
11
12
  sortRender?: 'string' | 'default';
12
13
  sortOrder?: 'ascend' | 'descend' | null;
@@ -1,3 +1,3 @@
1
- import { VirtualColumnType as LegacyColumnType } from '@synerise/ds-table';
2
1
  import { ColumnDef } from '@tanstack/react-table';
2
+ import { LegacyColumnType } from '../Table.types';
3
3
  export declare const legacyColumnConfigAdapter: <DataType, DataValue>(columns: Array<LegacyColumnType<DataType>>) => ColumnDef<DataType, DataValue>[];
@@ -11,7 +11,6 @@ const getSortStateApiAdapter = (headerContext) => {
11
11
  });
12
12
  return {
13
13
  columnsSortState: legacyColumnSortState,
14
- // get sort order for column by key
15
14
  getColumnSortOrder: (key) => {
16
15
  switch (headerContext.table.getColumn(key)?.getIsSorted()) {
17
16
  case "asc":
@@ -48,10 +47,10 @@ const getSortingConfig = (sorter) => {
48
47
  if (typeof sorter === "function") {
49
48
  sortFn = sorter;
50
49
  }
51
- if ("compare" in sorter && sorter.compare) {
50
+ if (typeof sorter === "object" && "compare" in sorter && sorter.compare) {
52
51
  sortFn = sorter.compare;
53
52
  enableMultiSort = !!sorter.multiple;
54
- multiSortOrder = sorter.multiple;
53
+ multiSortOrder = typeof sorter.multiple === "number" ? sorter.multiple : void 0;
55
54
  }
56
55
  return {
57
56
  sortingFn: sortFn ? (rowA, rowB, _columnId) => {
@@ -77,17 +76,21 @@ const legacyColumnConfigAdapter = (columns) => {
77
76
  return typeof column.title === "function" ? column.title({}) : column.title;
78
77
  },
79
78
  cell: (info) => {
80
- return column.render?.(info.getValue(), info.row.original, info.column.getIndex()) || info.getValue();
79
+ return column.render?.(info.getValue(), info.row.original, info.column.getIndex()) ?? info.getValue();
81
80
  },
82
81
  meta: {
83
82
  minWidth: column.minWidth,
84
83
  maxWidth: column.maxWidth,
85
84
  width: column.width,
86
85
  fixed: column.fixed,
86
+ align: column.align,
87
87
  sortOrder: column.sortOrder,
88
88
  sortRender: typeof column.sortRender === "string" ? column.sortRender : void 0,
89
89
  renderCustomSortButton: customSortRender,
90
90
  multipleSortingOrder: multiSortOrder,
91
+ getCellTooltipProps: column.getCellTooltipProps,
92
+ dataIndex: column.dataIndex,
93
+ title: typeof column.title === "string" ? column.title : void 0,
91
94
  childCell: (info) => {
92
95
  if (column.childRender) {
93
96
  const rowData = {
@@ -97,7 +100,7 @@ const legacyColumnConfigAdapter = (columns) => {
97
100
  };
98
101
  return column.childRender(info.getValue(), rowData, info.column.getIndex());
99
102
  }
100
- return column.render?.(info.getValue(), info.row.original, info.column.getIndex()) || info.getValue();
103
+ return column.render?.(info.getValue(), info.row.original, info.column.getIndex()) ?? info.getValue();
101
104
  }
102
105
  },
103
106
  enablePinning: !!column.fixed,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synerise/ds-table-new",
3
- "version": "0.1.0",
3
+ "version": "1.0.2",
4
4
  "description": "TableNew UI Component for the Synerise Design System",
5
5
  "license": "ISC",
6
6
  "repository": "Synerise/synerise-design",
@@ -38,22 +38,21 @@
38
38
  "@synerise/ds-button": "^1.5.20",
39
39
  "@synerise/ds-checkbox": "^1.2.23",
40
40
  "@synerise/ds-copy-icon": "^1.2.4",
41
- "@synerise/ds-dropdown": "^1.3.4",
41
+ "@synerise/ds-dropdown": "^1.3.5",
42
42
  "@synerise/ds-flag": "^1.0.10",
43
43
  "@synerise/ds-icon": "^1.15.3",
44
44
  "@synerise/ds-inline-alert": "^1.1.17",
45
45
  "@synerise/ds-input": "^1.7.0",
46
46
  "@synerise/ds-input-number": "^1.2.37",
47
47
  "@synerise/ds-loader": "^1.0.15",
48
- "@synerise/ds-modal": "^1.4.3",
48
+ "@synerise/ds-modal": "^1.4.4",
49
49
  "@synerise/ds-pagination": "^1.0.55",
50
50
  "@synerise/ds-result": "^1.0.51",
51
51
  "@synerise/ds-scrollbar": "^1.2.19",
52
- "@synerise/ds-search": "^1.5.12",
52
+ "@synerise/ds-search": "^1.5.13",
53
53
  "@synerise/ds-skeleton": "^1.0.47",
54
- "@synerise/ds-table": "^1.10.0",
55
54
  "@synerise/ds-tag": "^1.4.20",
56
- "@synerise/ds-tags": "^1.5.30",
55
+ "@synerise/ds-tags": "^1.5.31",
57
56
  "@synerise/ds-tooltip": "^1.4.12",
58
57
  "@synerise/ds-typography": "^1.1.15",
59
58
  "@synerise/ds-utils": "^1.8.0",
@@ -72,5 +71,5 @@
72
71
  "react-intl": ">= 3.12.0 <= 6.8",
73
72
  "styled-components": "^5.3.3"
74
73
  },
75
- "gitHead": "ce3c6d75efe8573a2b274853636f959b75a6cd32"
74
+ "gitHead": "4766ad0a45eea48ac75745bc9e7525f5dccc71e0"
76
75
  }