@coveord/plasma-mantine 52.11.0 → 52.12.0

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 (52) hide show
  1. package/.turbo/turbo-build.log +3 -3
  2. package/.turbo/turbo-test.log +33 -33
  3. package/dist/.tsbuildinfo +1 -1
  4. package/dist/cjs/components/table/Table.types.d.ts +4 -0
  5. package/dist/cjs/components/table/Table.types.d.ts.map +1 -1
  6. package/dist/cjs/components/table/TablePagination.d.ts +6 -0
  7. package/dist/cjs/components/table/TablePagination.d.ts.map +1 -1
  8. package/dist/cjs/components/table/TablePagination.js +3 -1
  9. package/dist/cjs/components/table/TablePagination.js.map +1 -1
  10. package/dist/cjs/components/table/TablePerPage.d.ts +6 -0
  11. package/dist/cjs/components/table/TablePerPage.d.ts.map +1 -1
  12. package/dist/cjs/components/table/TablePerPage.js +6 -4
  13. package/dist/cjs/components/table/TablePerPage.js.map +1 -1
  14. package/dist/cjs/components/table/Th.d.ts.map +1 -1
  15. package/dist/cjs/components/table/Th.js +12 -5
  16. package/dist/cjs/components/table/Th.js.map +1 -1
  17. package/dist/cjs/components/table/layouts/RowLayout.d.ts.map +1 -1
  18. package/dist/cjs/components/table/layouts/RowLayout.js +13 -5
  19. package/dist/cjs/components/table/layouts/RowLayout.js.map +1 -1
  20. package/dist/cjs/components/table/useRowSelection.d.ts.map +1 -1
  21. package/dist/cjs/components/table/useRowSelection.js +8 -2
  22. package/dist/cjs/components/table/useRowSelection.js.map +1 -1
  23. package/dist/esm/components/table/Table.types.d.ts +4 -0
  24. package/dist/esm/components/table/Table.types.d.ts.map +1 -1
  25. package/dist/esm/components/table/Table.types.js.map +1 -1
  26. package/dist/esm/components/table/TablePagination.d.ts +6 -0
  27. package/dist/esm/components/table/TablePagination.d.ts.map +1 -1
  28. package/dist/esm/components/table/TablePagination.js +3 -1
  29. package/dist/esm/components/table/TablePagination.js.map +1 -1
  30. package/dist/esm/components/table/TablePerPage.d.ts +6 -0
  31. package/dist/esm/components/table/TablePerPage.d.ts.map +1 -1
  32. package/dist/esm/components/table/TablePerPage.js +6 -4
  33. package/dist/esm/components/table/TablePerPage.js.map +1 -1
  34. package/dist/esm/components/table/Th.d.ts.map +1 -1
  35. package/dist/esm/components/table/Th.js +12 -5
  36. package/dist/esm/components/table/Th.js.map +1 -1
  37. package/dist/esm/components/table/layouts/RowLayout.d.ts.map +1 -1
  38. package/dist/esm/components/table/layouts/RowLayout.js +13 -5
  39. package/dist/esm/components/table/layouts/RowLayout.js.map +1 -1
  40. package/dist/esm/components/table/useRowSelection.d.ts.map +1 -1
  41. package/dist/esm/components/table/useRowSelection.js +9 -3
  42. package/dist/esm/components/table/useRowSelection.js.map +1 -1
  43. package/package.json +27 -27
  44. package/src/components/table/Table.types.ts +4 -0
  45. package/src/components/table/TablePagination.tsx +8 -1
  46. package/src/components/table/TablePerPage.tsx +11 -3
  47. package/src/components/table/Th.tsx +12 -5
  48. package/src/components/table/__tests__/TablePagination.spec.tsx +33 -0
  49. package/src/components/table/__tests__/TablePerPage.spec.tsx +39 -3
  50. package/src/components/table/layouts/RowLayout.tsx +21 -5
  51. package/src/components/table/layouts/__tests__/RowLayout.spec.tsx +90 -0
  52. package/src/components/table/useRowSelection.ts +7 -3
@@ -1,5 +1,5 @@
1
1
  import {ColumnDef, createColumnHelper} from '@tanstack/table-core';
2
- import {render, screen, userEvent} from '@test-utils';
2
+ import {render, screen, userEvent, waitFor} from '@test-utils';
3
3
 
4
4
  import {Table} from '../Table';
5
5
 
@@ -69,7 +69,7 @@ describe('Table.PerPage', () => {
69
69
  });
70
70
 
71
71
  it('calls onChange when changing the number of items per page', async () => {
72
- const user = userEvent.setup({delay: null});
72
+ const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
73
73
  const onChange = vi.fn();
74
74
  render(
75
75
  <Table data={[{name: 'fruit'}, {name: 'vegetable'}]} columns={columns} onChange={onChange}>
@@ -87,7 +87,7 @@ describe('Table.PerPage', () => {
87
87
  });
88
88
 
89
89
  it('resets page index when changing the number of items per page', async () => {
90
- const user = userEvent.setup({delay: null});
90
+ const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
91
91
  const onChange = vi.fn();
92
92
  render(
93
93
  <Table
@@ -109,4 +109,40 @@ describe('Table.PerPage', () => {
109
109
  expect.objectContaining({pagination: expect.objectContaining({pageIndex: 0})})
110
110
  );
111
111
  });
112
+
113
+ it('triggers the onChangePage Callback with the right parameters', async () => {
114
+ const user = userEvent.setup({advanceTimers: vi.advanceTimersByTime});
115
+ const onPerPageChange = vi.fn();
116
+ render(
117
+ <Table
118
+ data={[{name: 'fruit'}, {name: 'vegetable'}]}
119
+ columns={columns}
120
+ initialState={{pagination: {pageIndex: 1, pageSize: 50}}}
121
+ >
122
+ <Table.Footer>
123
+ <Table.Pagination totalPages={2} />
124
+ <Table.PerPage onPerPageChange={onPerPageChange} />
125
+ </Table.Footer>
126
+ </Table>
127
+ );
128
+
129
+ onPerPageChange.mockReset();
130
+
131
+ await user.click(screen.getByRole('radio', {name: /100/i}));
132
+
133
+ await waitFor(() => {
134
+ expect(onPerPageChange).toHaveBeenCalledWith(100);
135
+ });
136
+ });
137
+
138
+ it('renders nothing when there are no pages to show', () => {
139
+ render(
140
+ <Table data={[]} columns={columns} initialState={{globalFilter: 'filter'}}>
141
+ <Table.Footer data-testid="table-footer">
142
+ <Table.PerPage />
143
+ </Table.Footer>
144
+ </Table>
145
+ );
146
+ expect(screen.getByTestId('table-footer')).toBeEmptyDOMElement();
147
+ });
112
148
  });
@@ -96,7 +96,13 @@ const RowLayoutHeader = <T,>({table}: TableLayoutProps<T>) => {
96
96
  return <>{headers}</>;
97
97
  };
98
98
 
99
- const RowLayoutBody = <T,>({table, doubleClickAction, getExpandChildren, loading}: TableLayoutProps<T>) => {
99
+ const RowLayoutBody = <T,>({
100
+ table,
101
+ doubleClickAction,
102
+ getExpandChildren,
103
+ loading,
104
+ keepSelection,
105
+ }: TableLayoutProps<T>) => {
100
106
  const {multiRowSelectionEnabled, disableRowSelection} = useTable();
101
107
  const {classes, cx} = useStyles({disableRowSelection, multiRowSelectionEnabled});
102
108
 
@@ -108,11 +114,12 @@ const RowLayoutBody = <T,>({table, doubleClickAction, getExpandChildren, loading
108
114
  const rows = table.getRowModel().rows.map((row) => {
109
115
  const rowChildren = getExpandChildren?.(row.original) ?? null;
110
116
  const isSelected = !!row.getIsSelected();
117
+ const shouldKeepSelection = keepSelection && isSelected;
111
118
  const onClick = (event: MouseEvent<HTMLTableRowElement>) => {
112
119
  if (rowChildren) {
113
120
  toggleCollapsible(event.currentTarget);
114
121
  }
115
- if (!disableRowSelection && !multiRowSelectionEnabled) {
122
+ if (!disableRowSelection && !multiRowSelectionEnabled && !shouldKeepSelection) {
116
123
  row.toggleSelected();
117
124
  }
118
125
  };
@@ -130,8 +137,13 @@ const RowLayoutBody = <T,>({table, doubleClickAction, getExpandChildren, loading
130
137
  data-testid={row.id}
131
138
  >
132
139
  {row.getVisibleCells().map((cell) => {
133
- const size = cell.column.getSize();
134
- const width = size !== defaultColumnSizing.size ? size : undefined;
140
+ const columnSizing = {
141
+ ...defaultColumnSizing,
142
+ size: cell.column.columnDef.size,
143
+ minSize: cell.column.columnDef.minSize,
144
+ maxSize: cell.column.columnDef.maxSize,
145
+ };
146
+
135
147
  const onCollapsibleCellClick = (event: MouseEvent<HTMLTableCellElement>) => {
136
148
  if (cell.column.id === TableSelectableColumn.id && !disableRowSelection) {
137
149
  event.stopPropagation();
@@ -142,7 +154,11 @@ const RowLayoutBody = <T,>({table, doubleClickAction, getExpandChildren, loading
142
154
  <td
143
155
  key={cell.id}
144
156
  data-testid={cell.id}
145
- style={{width}}
157
+ style={{
158
+ width: columnSizing.size,
159
+ minWidth: columnSizing.minSize,
160
+ maxWidth: columnSizing.maxSize,
161
+ }}
146
162
  className={cx(classes.cell, {
147
163
  [classes.rowCollapsibleButtonCell]: cell.column.id === TableCollapsibleColumn.id,
148
164
  })}
@@ -2,6 +2,7 @@ import {ColumnDef, createColumnHelper} from '@tanstack/table-core';
2
2
  import {render, screen, userEvent, waitFor, within} from '@test-utils';
3
3
  import {FunctionComponent} from 'react';
4
4
  import {Table} from '../../Table';
5
+ import {TableLayouts} from '../TableLayouts';
5
6
 
6
7
  describe('RowLayout', () => {
7
8
  type RowData = {id: string; firstName: string; lastName?: string};
@@ -204,6 +205,95 @@ describe('RowLayout', () => {
204
205
  expect(doubleClickSpy).toHaveBeenCalledWith({id: '🆔-1', firstName: 'Mario'});
205
206
  });
206
207
 
208
+ it('toggles row selection when clicking on a selected row', async () => {
209
+ const user = userEvent.setup();
210
+
211
+ render(
212
+ <div>
213
+ <Table
214
+ getRowId={({id}) => id}
215
+ data={[
216
+ {id: '🆔-1', firstName: 'first', lastName: 'last'},
217
+ {id: '🆔-2', firstName: 'patate', lastName: 'king'},
218
+ ]}
219
+ columns={columns}
220
+ />
221
+ </div>
222
+ );
223
+
224
+ await user.click(screen.getByRole('row', {name: /patate king/i}));
225
+ expect(screen.getByRole('row', {name: /patate king/i, selected: true})).toBeInTheDocument();
226
+ expect(screen.queryByRole('row', {name: /patate king/i, selected: false})).not.toBeInTheDocument();
227
+
228
+ await user.click(screen.getByRole('row', {name: /patate king/i}));
229
+ expect(screen.getByRole('row', {name: /patate king/i, selected: false})).toBeInTheDocument();
230
+ expect(screen.queryByRole('row', {name: /patate king/i, selected: true})).not.toBeInTheDocument();
231
+ });
232
+
233
+ it('prevents row toggle if keepSelection is true', async () => {
234
+ const user = userEvent.setup();
235
+
236
+ render(
237
+ <div>
238
+ <Table
239
+ getRowId={({id}) => id}
240
+ data={[
241
+ {id: '🆔-1', firstName: 'first', lastName: 'last'},
242
+ {id: '🆔-2', firstName: 'patate', lastName: 'king'},
243
+ ]}
244
+ columns={columns}
245
+ layouts={[
246
+ {
247
+ ...TableLayouts.Rows,
248
+ Body: (props) => <TableLayouts.Rows.Body {...props} keepSelection />,
249
+ },
250
+ ]}
251
+ />
252
+ </div>
253
+ );
254
+
255
+ await user.click(screen.getByRole('row', {name: /patate king/i}));
256
+ expect(screen.getByRole('row', {name: /patate king/i, selected: true})).toBeInTheDocument();
257
+ expect(screen.queryByRole('row', {name: /patate king/i, selected: false})).not.toBeInTheDocument();
258
+
259
+ await user.click(screen.getByRole('row', {name: /patate king/i}));
260
+ expect(screen.getByRole('row', {name: /patate king/i, selected: true})).toBeInTheDocument();
261
+ expect(screen.queryByRole('row', {name: /patate king/i, selected: false})).not.toBeInTheDocument();
262
+ });
263
+
264
+ it('allows selection of another row if keepSelection is true', async () => {
265
+ const user = userEvent.setup();
266
+
267
+ render(
268
+ <div>
269
+ <Table
270
+ getRowId={({id}) => id}
271
+ data={[
272
+ {id: '🆔-1', firstName: 'first', lastName: 'last'},
273
+ {id: '🆔-2', firstName: 'patate', lastName: 'king'},
274
+ ]}
275
+ columns={columns}
276
+ layouts={[
277
+ {
278
+ ...TableLayouts.Rows,
279
+ Body: (props) => <TableLayouts.Rows.Body {...props} keepSelection />,
280
+ },
281
+ ]}
282
+ />
283
+ </div>
284
+ );
285
+
286
+ await user.click(screen.getByRole('row', {name: /patate king/i}));
287
+ expect(screen.getByRole('row', {name: /patate king/i, selected: true})).toBeInTheDocument();
288
+ expect(screen.queryByRole('row', {name: /patate king/i, selected: false})).not.toBeInTheDocument();
289
+
290
+ await user.click(screen.getByRole('row', {name: /first last/i}));
291
+ expect(screen.getByRole('row', {name: /patate king/i, selected: false})).toBeInTheDocument();
292
+ expect(screen.queryByRole('row', {name: /patate king/i, selected: true})).not.toBeInTheDocument();
293
+ expect(screen.getByRole('row', {name: /first last/i, selected: true})).toBeInTheDocument();
294
+ expect(screen.queryByRole('row', {name: /first last/i, selected: false})).not.toBeInTheDocument();
295
+ });
296
+
207
297
  describe('when multi row selection is enabled', () => {
208
298
  it('displays a checkbox as the first cell of each row', () => {
209
299
  render(
@@ -1,4 +1,4 @@
1
- import {useClickOutside} from '@mantine/hooks';
1
+ import {useClickOutside, useDidUpdate} from '@mantine/hooks';
2
2
  import {functionalUpdate, RowSelectionState, Table} from '@tanstack/table-core';
3
3
  import isEqual from 'fast-deep-equal';
4
4
 
@@ -24,6 +24,12 @@ export const useRowSelection = <T>(
24
24
  [outsideClickRef.current, ...additionalRootNodes]
25
25
  );
26
26
 
27
+ // Need to call this outside of the onRowSelectionChange of the table to avoid rendering conflicts if the callback queues an update in a parent component.
28
+ // See this warning introduced in React v.16.13.0: https://legacy.reactjs.org/blog/2020/02/26/react-v16.13.0.html#warnings-for-some-updates-during-render
29
+ useDidUpdate(() => {
30
+ onRowSelectionChange?.(getSelectedRows());
31
+ }, [table.getState().rowSelection]);
32
+
27
33
  table.setOptions((prev) => ({
28
34
  ...prev,
29
35
  onRowSelectionChange: (rowSelectionUpdater) => {
@@ -50,8 +56,6 @@ export const useRowSelection = <T>(
50
56
  }
51
57
  });
52
58
 
53
- onRowSelectionChange?.(Object.values(newRowSelection));
54
-
55
59
  return {
56
60
  ...old,
57
61
  rowSelection: newRowSelection as RowSelectionState,