react-science 15.0.0 → 16.1.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 (120) hide show
  1. package/lib/components/accordion/accordion.d.ts +29 -7
  2. package/lib/components/accordion/accordion.d.ts.map +1 -1
  3. package/lib/components/accordion/accordion.js +24 -9
  4. package/lib/components/accordion/accordion.js.map +1 -1
  5. package/lib/components/accordion/accordion_context.d.ts +8 -15
  6. package/lib/components/accordion/accordion_context.d.ts.map +1 -1
  7. package/lib/components/accordion/accordion_context.js +7 -25
  8. package/lib/components/accordion/accordion_context.js.map +1 -1
  9. package/lib/components/accordion/accordion_context_provider.d.ts +7 -0
  10. package/lib/components/accordion/accordion_context_provider.d.ts.map +1 -0
  11. package/lib/components/accordion/accordion_context_provider.js +62 -0
  12. package/lib/components/accordion/accordion_context_provider.js.map +1 -0
  13. package/lib/components/accordion/accordion_context_utils.d.ts +15 -0
  14. package/lib/components/accordion/accordion_context_utils.d.ts.map +1 -0
  15. package/lib/components/accordion/accordion_context_utils.js +4 -0
  16. package/lib/components/accordion/accordion_context_utils.js.map +1 -0
  17. package/lib/components/accordion/accordion_hooks.d.ts +8 -0
  18. package/lib/components/accordion/accordion_hooks.d.ts.map +1 -0
  19. package/lib/components/accordion/accordion_hooks.js +16 -0
  20. package/lib/components/accordion/accordion_hooks.js.map +1 -0
  21. package/lib/components/accordion/index.d.ts +2 -3
  22. package/lib/components/accordion/index.d.ts.map +1 -1
  23. package/lib/components/accordion/index.js +2 -3
  24. package/lib/components/accordion/index.js.map +1 -1
  25. package/lib/components/table/flash_row/flashed_row_context.d.ts +3 -0
  26. package/lib/components/table/flash_row/flashed_row_context.d.ts.map +1 -0
  27. package/lib/components/table/flash_row/flashed_row_context.js +10 -0
  28. package/lib/components/table/flash_row/flashed_row_context.js.map +1 -0
  29. package/lib/components/table/{reorder_rows/dropped_item_provider.d.ts → flash_row/flashed_row_provider.d.ts} +2 -2
  30. package/lib/components/table/flash_row/flashed_row_provider.d.ts.map +1 -0
  31. package/lib/components/table/flash_row/flashed_row_provider.js +8 -0
  32. package/lib/components/table/flash_row/flashed_row_provider.js.map +1 -0
  33. package/lib/components/table/flash_row/use_flash_row_effect.d.ts +3 -0
  34. package/lib/components/table/flash_row/use_flash_row_effect.d.ts.map +1 -0
  35. package/lib/components/table/flash_row/use_flash_row_effect.js +21 -0
  36. package/lib/components/table/flash_row/use_flash_row_effect.js.map +1 -0
  37. package/lib/components/table/index.d.ts +1 -0
  38. package/lib/components/table/index.d.ts.map +1 -1
  39. package/lib/components/table/index.js +1 -0
  40. package/lib/components/table/index.js.map +1 -1
  41. package/lib/components/table/preview_table.d.ts +5 -0
  42. package/lib/components/table/preview_table.d.ts.map +1 -0
  43. package/lib/components/table/preview_table.js +8 -0
  44. package/lib/components/table/preview_table.js.map +1 -0
  45. package/lib/components/table/preview_table_context.d.ts +9 -0
  46. package/lib/components/table/preview_table_context.d.ts.map +1 -0
  47. package/lib/components/table/preview_table_context.js +15 -0
  48. package/lib/components/table/preview_table_context.js.map +1 -0
  49. package/lib/components/table/reorder_rows/draggable_row_tr.d.ts +3 -3
  50. package/lib/components/table/reorder_rows/draggable_row_tr.d.ts.map +1 -1
  51. package/lib/components/table/reorder_rows/draggable_row_tr.js +14 -20
  52. package/lib/components/table/reorder_rows/draggable_row_tr.js.map +1 -1
  53. package/lib/components/table/reorder_rows/table_drag_row_handler.d.ts +3 -1
  54. package/lib/components/table/reorder_rows/table_drag_row_handler.d.ts.map +1 -1
  55. package/lib/components/table/reorder_rows/table_drag_row_handler.js +12 -2
  56. package/lib/components/table/reorder_rows/table_drag_row_handler.js.map +1 -1
  57. package/lib/components/table/reorder_rows/use_drop_monitor.js +4 -4
  58. package/lib/components/table/reorder_rows/use_drop_monitor.js.map +1 -1
  59. package/lib/components/table/table_body.d.ts.map +1 -1
  60. package/lib/components/table/table_body.js +3 -3
  61. package/lib/components/table/table_body.js.map +1 -1
  62. package/lib/components/table/table_root.d.ts +5 -1
  63. package/lib/components/table/table_root.d.ts.map +1 -1
  64. package/lib/components/table/table_root.js +44 -45
  65. package/lib/components/table/table_root.js.map +1 -1
  66. package/lib/components/table/table_row.d.ts +8 -0
  67. package/lib/components/table/table_row.d.ts.map +1 -0
  68. package/lib/components/table/table_row.js +10 -0
  69. package/lib/components/table/table_row.js.map +1 -0
  70. package/lib/components/table/table_scroll_container.d.ts +33 -0
  71. package/lib/components/table/table_scroll_container.d.ts.map +1 -0
  72. package/lib/components/table/table_scroll_container.js +33 -0
  73. package/lib/components/table/table_scroll_container.js.map +1 -0
  74. package/lib/components/table/table_utils.d.ts +13 -4
  75. package/lib/components/table/table_utils.d.ts.map +1 -1
  76. package/lib/components/table/use_table_scroll.d.ts +20 -1
  77. package/lib/components/table/use_table_scroll.d.ts.map +1 -1
  78. package/lib/components/table/use_table_scroll.js +16 -8
  79. package/lib/components/table/use_table_scroll.js.map +1 -1
  80. package/package.json +1 -1
  81. package/src/components/accordion/accordion.tsx +65 -20
  82. package/src/components/accordion/accordion_context.ts +17 -37
  83. package/src/components/accordion/accordion_context_provider.tsx +79 -0
  84. package/src/components/accordion/accordion_context_utils.ts +22 -0
  85. package/src/components/accordion/accordion_hooks.ts +32 -0
  86. package/src/components/accordion/index.ts +2 -6
  87. package/src/components/table/flash_row/flashed_row_context.ts +23 -0
  88. package/src/components/table/flash_row/flashed_row_provider.tsx +13 -0
  89. package/src/components/table/flash_row/use_flash_row_effect.ts +30 -0
  90. package/src/components/table/index.ts +1 -0
  91. package/src/components/table/preview_table.tsx +18 -0
  92. package/src/components/table/preview_table_context.ts +33 -0
  93. package/src/components/table/reorder_rows/draggable_row_tr.tsx +21 -27
  94. package/src/components/table/reorder_rows/table_drag_row_handler.tsx +25 -4
  95. package/src/components/table/reorder_rows/use_drop_monitor.ts +4 -4
  96. package/src/components/table/table_body.tsx +6 -8
  97. package/src/components/table/table_root.tsx +112 -123
  98. package/src/components/table/table_row.tsx +17 -0
  99. package/src/components/table/table_scroll_container.tsx +103 -0
  100. package/src/components/table/table_utils.ts +20 -4
  101. package/src/components/table/use_table_scroll.ts +48 -20
  102. package/lib/components/accordion/accordion_context.provider.d.ts +0 -13
  103. package/lib/components/accordion/accordion_context.provider.d.ts.map +0 -1
  104. package/lib/components/accordion/accordion_context.provider.js +0 -55
  105. package/lib/components/accordion/accordion_context.provider.js.map +0 -1
  106. package/lib/components/accordion/accordion_context.utils.d.ts +0 -23
  107. package/lib/components/accordion/accordion_context.utils.d.ts.map +0 -1
  108. package/lib/components/accordion/accordion_context.utils.js +0 -40
  109. package/lib/components/accordion/accordion_context.utils.js.map +0 -1
  110. package/lib/components/table/reorder_rows/dropped_item_context.d.ts +0 -3
  111. package/lib/components/table/reorder_rows/dropped_item_context.d.ts.map +0 -1
  112. package/lib/components/table/reorder_rows/dropped_item_context.js +0 -10
  113. package/lib/components/table/reorder_rows/dropped_item_context.js.map +0 -1
  114. package/lib/components/table/reorder_rows/dropped_item_provider.d.ts.map +0 -1
  115. package/lib/components/table/reorder_rows/dropped_item_provider.js +0 -8
  116. package/lib/components/table/reorder_rows/dropped_item_provider.js.map +0 -1
  117. package/src/components/accordion/accordion_context.provider.tsx +0 -91
  118. package/src/components/accordion/accordion_context.utils.ts +0 -66
  119. package/src/components/table/reorder_rows/dropped_item_context.ts +0 -23
  120. package/src/components/table/reorder_rows/dropped_item_provider.tsx +0 -13
@@ -10,20 +10,21 @@ import {
10
10
  attachClosestEdge,
11
11
  extractClosestEdge,
12
12
  } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
13
- import { Colors } from '@blueprintjs/core';
14
13
  import type { Row, RowData } from '@tanstack/react-table';
15
14
  import { useEffect, useMemo, useRef, useState } from 'react';
16
15
  import { createPortal } from 'react-dom';
17
16
 
18
17
  import { assert } from '../../utils/index.js';
18
+ import { useFlashRowEffect } from '../flash_row/use_flash_row_effect.js';
19
+ import { PreviewTable } from '../preview_table.js';
20
+ import { useIsPreviewTable } from '../preview_table_context.js';
19
21
  import type {
20
22
  TableRowPreviewRenderer,
21
- TableRowTrProps,
23
+ TableRowTrRenderProps,
22
24
  } from '../table_utils.js';
23
25
 
24
26
  import type { DraggableRowContext } from './draggable_row_context.js';
25
27
  import { draggableRowContext } from './draggable_row_context.js';
26
- import { useDroppedItemContext } from './dropped_item_context.js';
27
28
  import type { DraggableItemState } from './item_data.js';
28
29
  import { getItemData, isItemData } from './item_data.js';
29
30
  import { useItemOrder } from './item_order_context.js';
@@ -32,7 +33,7 @@ export interface TableDraggableRowTrProps<TData extends RowData> {
32
33
  /**
33
34
  * Props to be spread on the `tr` element.
34
35
  */
35
- trProps: TableRowTrProps;
36
+ trProps: TableRowTrRenderProps;
36
37
  /**
37
38
  * Row data.
38
39
  */
@@ -40,21 +41,29 @@ export interface TableDraggableRowTrProps<TData extends RowData> {
40
41
  /**
41
42
  * Preview of the row being dragged.
42
43
  */
43
- renderRowPreview: TableRowPreviewRenderer<TData>;
44
+ renderRowPreview?: TableRowPreviewRenderer<TData>;
44
45
  }
45
46
 
46
47
  export function TableDraggableRowTr<TData extends RowData>(
47
48
  props: TableDraggableRowTrProps<TData>,
48
49
  ) {
49
- const { trProps, row, renderRowPreview } = props;
50
+ const {
51
+ trProps,
52
+ row,
53
+ renderRowPreview = (row) => <PreviewTable row={row} />,
54
+ } = props;
50
55
  const { instanceId } = useItemOrder();
51
- const innerRef = useRef<HTMLTableRowElement>(null);
56
+ const isPreview = useIsPreviewTable();
57
+ const tableRowRef = useRef<HTMLTableRowElement>(null);
52
58
  const [state, setState] = useState<DraggableItemState>(idleState);
53
- const [droppedItemId, setDroppedItemId] = useDroppedItemContext();
54
59
 
55
60
  const dragHandleRef = useRef<HTMLButtonElement>(null);
56
61
  useEffect(() => {
57
- const trElement = innerRef.current;
62
+ if (isPreview) {
63
+ // No drag and drop in preview
64
+ return;
65
+ }
66
+ const trElement = tableRowRef.current;
58
67
  assert(trElement, 'tr ref is null');
59
68
  assert(dragHandleRef.current, 'dragHandleRef is null');
60
69
 
@@ -125,14 +134,9 @@ export function TableDraggableRowTr<TData extends RowData>(
125
134
  },
126
135
  }),
127
136
  );
128
- }, [row, instanceId]);
137
+ }, [row, instanceId, isPreview]);
129
138
 
130
- useEffect(() => {
131
- if (droppedItemId === row.id && innerRef.current) {
132
- triggerPostFlash(innerRef.current);
133
- setDroppedItemId(undefined);
134
- }
135
- }, [droppedItemId, row.id, setDroppedItemId]);
139
+ useFlashRowEffect(row.id, tableRowRef);
136
140
 
137
141
  const value = useMemo<DraggableRowContext>(() => {
138
142
  return {
@@ -144,7 +148,7 @@ export function TableDraggableRowTr<TData extends RowData>(
144
148
  return (
145
149
  <>
146
150
  <draggableRowContext.Provider value={value}>
147
- <tr {...trProps} ref={innerRef} />
151
+ <tr {...trProps} ref={tableRowRef} />
148
152
  </draggableRowContext.Provider>
149
153
  {state.type === 'preview' &&
150
154
  createPortal(renderRowPreview(row), state.container)}
@@ -154,13 +158,3 @@ export function TableDraggableRowTr<TData extends RowData>(
154
158
 
155
159
  const idleState: DraggableItemState = { type: 'idle' };
156
160
  const draggingState: DraggableItemState = { type: 'dragging' };
157
-
158
- function triggerPostFlash(element: HTMLElement) {
159
- element.animate(
160
- [{ backgroundColor: Colors.BLUE5, opacity: 0.5 }, { opacity: 0.5 }],
161
- {
162
- duration: 250,
163
- iterations: 1,
164
- },
165
- );
166
- }
@@ -1,18 +1,39 @@
1
+ import type { ButtonProps } from '@blueprintjs/core';
1
2
  import { Button } from '@blueprintjs/core';
2
3
 
4
+ import { useIsPreviewTable } from '../preview_table_context.js';
5
+
3
6
  import { useTableDraggableRowContext } from './draggable_row_context.js';
4
7
  import { TableDropIndicator } from './drop_indicator.js';
5
8
 
6
- export function TableDragRowHandler() {
9
+ export type TableDragRowHandlerProps = ButtonProps;
10
+
11
+ export function TableDragRowHandler(props: TableDragRowHandlerProps) {
12
+ const isInPreview = useIsPreviewTable();
13
+ if (isInPreview) {
14
+ // Do not render the drag handler in the preview table.
15
+ return null;
16
+ }
17
+ return <InternalTableDragRowHandler {...props} />;
18
+ }
19
+
20
+ function InternalTableDragRowHandler(props: TableDragRowHandlerProps) {
21
+ const {
22
+ icon = 'drag-handle-vertical',
23
+ variant = 'minimal',
24
+ style,
25
+ ...otherProps
26
+ } = props;
7
27
  const { dragHandleRef, state } = useTableDraggableRowContext();
8
28
  return (
9
29
  <>
10
30
  <Button
11
- icon="drag-handle-horizontal"
12
31
  type="button"
32
+ icon={icon}
13
33
  ref={dragHandleRef}
14
- variant="minimal"
15
- style={{ cursor: 'grab' }}
34
+ variant={variant}
35
+ {...otherProps}
36
+ style={{ cursor: 'grab', ...style }}
16
37
  />
17
38
  {state?.type === 'is-over' && state.closestEdge && (
18
39
  <TableDropIndicator edge={state.closestEdge} />
@@ -7,8 +7,8 @@ import type { RefObject } from 'react';
7
7
  import { useEffect } from 'react';
8
8
 
9
9
  import { assert } from '../../utils/index.js';
10
+ import { useFlashedRowContext } from '../flash_row/flashed_row_context.js';
10
11
 
11
- import { useDroppedItemContext } from './dropped_item_context.js';
12
12
  import { isItemData } from './item_data.js';
13
13
  import { useItemOrder } from './item_order_context.js';
14
14
 
@@ -23,7 +23,7 @@ export function useDropMonitor(
23
23
  enabled: boolean,
24
24
  ) {
25
25
  const { reorderItem, items } = useItemOrder();
26
- const [, setDroppedItem] = useDroppedItemContext();
26
+ const [, setFlashedRow] = useFlashedRowContext();
27
27
  useEffect(() => {
28
28
  const scrollContainer = scrollElementRef.current;
29
29
  assert(scrollContainer, 'Missing scroll container ref');
@@ -61,7 +61,7 @@ export function useDropMonitor(
61
61
  indexOfTarget,
62
62
  closestEdgeOfTarget,
63
63
  });
64
- setDroppedItem(sourceData.id);
64
+ setFlashedRow(sourceData.id);
65
65
  },
66
66
  }),
67
67
  autoScrollForElements({
@@ -70,5 +70,5 @@ export function useDropMonitor(
70
70
  }),
71
71
  );
72
72
  }
73
- }, [items, reorderItem, scrollElementRef, setDroppedItem, enabled]);
73
+ }, [items, reorderItem, scrollElementRef, setFlashedRow, enabled]);
74
74
  }
@@ -1,4 +1,3 @@
1
- import { Tag } from '@blueprintjs/core';
2
1
  import type { Row, RowData } from '@tanstack/react-table';
3
2
  import type { VirtualItem, Virtualizer } from '@tanstack/react-virtual';
4
3
  import { notUndefined } from '@tanstack/react-virtual';
@@ -6,12 +5,13 @@ import type { ReactNode } from 'react';
6
5
  import { Fragment } from 'react';
7
6
 
8
7
  import { TableDraggableRowTr } from './reorder_rows/index.js';
8
+ import { TableRowTr } from './table_row.js';
9
9
  import { TableRowCell } from './table_row_cell.js';
10
10
  import type {
11
11
  GetTdProps,
12
12
  TableRowPreviewRenderer,
13
- TableRowTrProps,
14
13
  TableRowTrRenderer,
14
+ TableRowTrRenderProps,
15
15
  } from './table_utils.js';
16
16
 
17
17
  interface TableBodyProps<TData extends RowData> {
@@ -111,7 +111,7 @@ function getTrRenderProps<TData extends RowData>(
111
111
  row: Row<TData>,
112
112
  getTdProps: GetTdProps<TData> | undefined,
113
113
  virtualItem?: RenderRowVirtualItem,
114
- ): TableRowTrProps {
114
+ ): TableRowTrRenderProps {
115
115
  const index = virtualItem ? virtualItem.index : row.index;
116
116
 
117
117
  return {
@@ -142,8 +142,8 @@ function getDefaultRenderRowTr(
142
142
  }
143
143
  }
144
144
 
145
- const defaultRenderRowTr: TableRowTrRenderer<unknown> = (trProps) => (
146
- <tr {...trProps} />
145
+ const defaultRenderRowTr: TableRowTrRenderer<unknown> = (trProps, row) => (
146
+ <TableRowTr trProps={{ ...trProps }} row={row} />
147
147
  );
148
148
 
149
149
  function getDefaultRenderDraggableRowTr(
@@ -153,9 +153,7 @@ function getDefaultRenderDraggableRowTr(
153
153
  <TableDraggableRowTr
154
154
  trProps={trProps}
155
155
  row={row}
156
- renderRowPreview={
157
- renderRowPreview ?? ((row) => <Tag>Row {row.index + 1}</Tag>)
158
- }
156
+ renderRowPreview={renderRowPreview}
159
157
  />
160
158
  );
161
159
  }
@@ -1,21 +1,29 @@
1
1
  import { HTMLTable } from '@blueprintjs/core';
2
2
  import styled from '@emotion/styled';
3
- import type { Header, RowData, TableOptions } from '@tanstack/react-table';
3
+ import type {
4
+ Header,
5
+ RowData,
6
+ Table as TanstackTable,
7
+ TableOptions,
8
+ } from '@tanstack/react-table';
4
9
  import {
5
10
  getCoreRowModel,
6
11
  getSortedRowModel,
7
12
  useReactTable,
8
13
  } from '@tanstack/react-table';
9
14
  import { useVirtualizer } from '@tanstack/react-virtual';
10
- import type { ReactNode, RefObject, TableHTMLAttributes } from 'react';
11
- import { useEffect, useRef } from 'react';
15
+ import type { RefObject, TableHTMLAttributes } from 'react';
16
+ import { useEffect, useMemo, useRef } from 'react';
17
+ import { match } from 'ts-pattern';
12
18
 
13
- import { DroppedItemProvider } from './reorder_rows/dropped_item_provider.js';
19
+ import { FlashedRowProvider } from './flash_row/flashed_row_provider.js';
20
+ import type { PreviewTablePropsContextValue } from './preview_table_context.js';
21
+ import { PreviewTablePropsContextProvider } from './preview_table_context.js';
14
22
  import { ItemOrderProvider } from './reorder_rows/item_order_provider.js';
15
- import { useDropMonitor } from './reorder_rows/use_drop_monitor.js';
16
23
  import { TableBody } from './table_body.js';
17
24
  import { TableHeader } from './table_header.js';
18
25
  import type { HeaderCellRenderer } from './table_header_cell.js';
26
+ import { ScrollContainer } from './table_scroll_container.js';
19
27
  import type {
20
28
  GetTdProps,
21
29
  Scroller,
@@ -25,33 +33,40 @@ import type {
25
33
  VirtualScroller,
26
34
  } from './table_utils.js';
27
35
  import { useTableColumns } from './use_table_columns.js';
28
- import { useTableScroll } from './use_table_scroll.js';
36
+
37
+ const nonForwardedProps = new Set<keyof TableProps<unknown>>([
38
+ 'striped',
39
+ 'stickyHeader',
40
+ 'noHeader',
41
+ ]) as Set<string>;
29
42
 
30
43
  const CustomHTMLTable = styled(HTMLTable, {
31
- shouldForwardProp: (prop) => prop !== 'striped' && prop !== 'stickyHeader',
32
- })<{ stickyHeader: boolean }>`
44
+ shouldForwardProp: (prop) => !nonForwardedProps.has(prop),
45
+ })<{ stickyHeader: boolean; noHeader: boolean }>`
33
46
  /* When using a sticky header, ensure that the borders are located below the last header instead of above the first row. */
34
- ${(props) => {
35
- if (!props.stickyHeader) return '';
36
-
37
- return `
47
+ ${(props) =>
48
+ match(props)
49
+ .with({ stickyHeader: false, noHeader: false }, () => '')
50
+ .otherwise(
51
+ (props) => `
38
52
  thead tr:last-child {
39
53
  box-shadow: inset 0 -1px #11141826;
40
54
  }
41
55
 
42
56
  tbody tr:first-of-type td {
43
- box-shadow: ${
44
- props.bordered
45
- ? 'inset 1px 0 0 0 #11141826 !important'
46
- : 'none !important'
47
- };
57
+ box-shadow: ${match(props)
58
+ .with(
59
+ { bordered: true },
60
+ () => 'inset 1px 0 0 0 #11141826 !important',
61
+ )
62
+ .otherwise(() => 'none !important')};
48
63
  }
49
64
 
50
65
  tbody tr:first-of-type td:first-of-type {
51
66
  box-shadow: none !important;
52
67
  }
53
- `;
54
- }}
68
+ `,
69
+ )}
55
70
 
56
71
  /* Blueprint's HTMLTable \`striped\` prop's implementation is based on nth-child odd / even */
57
72
  /* We cannot use that with virtualization, so we override its implementation here. */
@@ -88,6 +103,10 @@ interface TableBaseProps<TData extends RowData> {
88
103
  * Alternate between gray and white background for each row.
89
104
  */
90
105
  striped?: boolean;
106
+ /**
107
+ * Do not render the table header.
108
+ */
109
+ noHeader?: boolean;
91
110
  /**
92
111
  * Enable header rows which stick to the top of the table.
93
112
  */
@@ -134,7 +153,7 @@ interface TableBaseProps<TData extends RowData> {
134
153
  * A ref which will be set with a callback to scroll to a row in the
135
154
  * table, specified by the row's ID.
136
155
  */
137
- scrollToRowRef?: RefObject<VirtualScroller | ScrollToOptions | undefined>;
156
+ scrollToRowRef?: RefObject<VirtualScroller | Scroller | undefined>;
138
157
 
139
158
  /**
140
159
  * An accessor which should return a unique identifier for the row.
@@ -199,6 +218,7 @@ export function Table<TData extends RowData>(props: TableProps<TData>) {
199
218
  compact = false,
200
219
  interactive = false,
201
220
  striped = false,
221
+ noHeader = false,
202
222
  stickyHeader = false,
203
223
 
204
224
  reactTable,
@@ -212,9 +232,11 @@ export function Table<TData extends RowData>(props: TableProps<TData>) {
212
232
  getRowId,
213
233
  onRowOrderChanged,
214
234
  renderRowPreview,
235
+
236
+ scrollToRowRef,
215
237
  } = props;
216
238
  const isReorderingEnabled = !!onRowOrderChanged;
217
- const scrollElementRef = useRef<HTMLDivElement>(null);
239
+ const virtualScrollElementRef = useRef<HTMLDivElement>(null);
218
240
  const columnDefs = useTableColumns(columns);
219
241
  const table = useReactTable<TData>({
220
242
  ...reactTable,
@@ -228,13 +250,13 @@ export function Table<TData extends RowData>(props: TableProps<TData>) {
228
250
  const tanstackVirtualizer = useVirtualizer({
229
251
  enabled: virtualizeRows,
230
252
  count: data.length,
231
- getScrollElement: () => scrollElementRef.current,
253
+ getScrollElement: () => virtualScrollElementRef.current,
232
254
  estimateSize:
233
255
  (props.virtualizeRows && props.estimatedRowHeight) || (() => 0),
234
256
  overscan: 5,
235
257
  });
236
258
 
237
- const tableRef = useTableScroll(props, table, tanstackVirtualizer);
259
+ const tableRef = useRef<HTMLTableElement>(null);
238
260
 
239
261
  // Make the table component compatible with styled components libraries.
240
262
  let finalClassName: string | undefined;
@@ -251,113 +273,80 @@ export function Table<TData extends RowData>(props: TableProps<TData>) {
251
273
  props as TableProps<unknown>,
252
274
  tableHeaders as Array<Header<unknown, unknown>>,
253
275
  );
276
+
277
+ const tablePreviewProps = useMemo<PreviewTablePropsContextValue<TData>>(
278
+ () => ({
279
+ className,
280
+ getTdProps,
281
+ renderRowTr,
282
+ columns,
283
+ compact,
284
+ }),
285
+ [className, getTdProps, renderRowTr, columns, compact],
286
+ );
254
287
  return (
255
- <DroppedItemProvider>
256
- <ItemOrderProvider
257
- items={table.getRowModel().rows}
258
- onOrderChanged={(items) => {
259
- onRowOrderChanged?.(items.map((item) => item.original));
260
- }}
288
+ <FlashedRowProvider>
289
+ <PreviewTablePropsContextProvider
290
+ value={tablePreviewProps as PreviewTablePropsContextValue<unknown>}
261
291
  >
262
- <Container
263
- virtualizeRows={virtualizeRows}
264
- scrollRef={
265
- virtualizeRows
266
- ? scrollElementRef
267
- : props.scrollableElementRef || tableRef
268
- }
269
- isReorderingEnabled={isReorderingEnabled}
292
+ <ItemOrderProvider
293
+ items={table.getRowModel().rows}
294
+ onOrderChanged={(items) => {
295
+ onRowOrderChanged?.(items.map((item) => item.original));
296
+ }}
270
297
  >
271
- <CustomHTMLTable
272
- ref={tableRef}
273
- bordered={bordered}
274
- compact={compact}
275
- interactive={interactive}
276
- striped={striped}
277
- stickyHeader={stickyHeader}
278
- {...tableProps}
279
- className={finalClassName}
298
+ <ScrollContainer
299
+ virtualizeRows={virtualizeRows}
300
+ virtualizer={tanstackVirtualizer}
301
+ table={table as TanstackTable<unknown>}
302
+ scrollRef={
303
+ virtualizeRows
304
+ ? // When virtualized, ScrollContainer will render a scrollable element associated to this ref.
305
+ virtualScrollElementRef
306
+ : // When not virtualized, ScrollContainer does not render a container, only its children,
307
+ // And the scrollable element is provided by the user or by default, the <table> element.
308
+ props.scrollableElementRef || tableRef
309
+ }
310
+ scrollToRowRef={scrollToRowRef}
311
+ isReorderingEnabled={isReorderingEnabled}
280
312
  >
281
- <TableHeader
282
- sticky={stickyHeader}
283
- headers={tableHeaders}
284
- renderHeaderCell={renderHeaderCell}
285
- />
286
- <TableBody
287
- rows={table.getRowModel().rows}
288
- renderRowTr={renderRowTr}
289
- getTdProps={getTdProps}
290
- virtualizer={tanstackVirtualizer}
291
- virtualizeRows={virtualizeRows}
292
- renderRowPreview={renderRowPreview}
293
- isReorderingEnabled={isReorderingEnabled}
294
- />
295
- </CustomHTMLTable>
296
- </Container>
297
- </ItemOrderProvider>
298
- </DroppedItemProvider>
299
- );
300
- }
301
-
302
- const ScrollRefDiv = styled.div`
303
- height: 100%;
304
- overflow: auto;
305
- `;
306
-
307
- interface ContainerProps {
308
- virtualizeRows?: boolean;
309
- children: ReactNode;
310
- scrollRef: RefObject<Element>;
311
- isReorderingEnabled: boolean;
312
- }
313
-
314
- function Container(props: ContainerProps) {
315
- const { virtualizeRows, scrollRef, isReorderingEnabled, children } = props;
316
- if (virtualizeRows) {
317
- return (
318
- <ContainerVirtual
319
- scrollElementRef={scrollRef}
320
- enabled={isReorderingEnabled}
321
- >
322
- {children}
323
- </ContainerVirtual>
324
- );
325
- }
326
- return (
327
- <ContainerTable scrollElementRef={scrollRef} enabled={isReorderingEnabled}>
328
- {children}
329
- </ContainerTable>
313
+ <CustomHTMLTable
314
+ // Props which are not forwarded to the HTMLTable component
315
+ striped={striped}
316
+ noHeader={noHeader}
317
+ stickyHeader={stickyHeader}
318
+ // Props which are forwarded to the HTMLTable component
319
+ ref={tableRef}
320
+ bordered={bordered}
321
+ compact={compact}
322
+ interactive={interactive}
323
+ {...tableProps}
324
+ className={finalClassName}
325
+ >
326
+ {!noHeader && (
327
+ <TableHeader
328
+ sticky={stickyHeader}
329
+ headers={tableHeaders}
330
+ renderHeaderCell={renderHeaderCell}
331
+ />
332
+ )}
333
+ <TableBody
334
+ rows={table.getRowModel().rows}
335
+ renderRowTr={renderRowTr}
336
+ getTdProps={getTdProps}
337
+ virtualizer={tanstackVirtualizer}
338
+ virtualizeRows={virtualizeRows}
339
+ renderRowPreview={renderRowPreview}
340
+ isReorderingEnabled={isReorderingEnabled}
341
+ />
342
+ </CustomHTMLTable>
343
+ </ScrollContainer>
344
+ </ItemOrderProvider>
345
+ </PreviewTablePropsContextProvider>
346
+ </FlashedRowProvider>
330
347
  );
331
348
  }
332
349
 
333
- interface ContainerWithReorderingProps {
334
- scrollElementRef: RefObject<Element>;
335
- enabled: boolean;
336
- children: ReactNode;
337
- }
338
-
339
- function ContainerVirtual(props: ContainerWithReorderingProps) {
340
- const { scrollElementRef, enabled, children } = props;
341
- useDropMonitor(scrollElementRef, enabled);
342
-
343
- return (
344
- <ScrollRefDiv ref={scrollElementRef as RefObject<HTMLDivElement>}>
345
- {children}
346
- </ScrollRefDiv>
347
- );
348
- }
349
-
350
- interface ContainerTableProps {
351
- scrollElementRef: RefObject<Element>;
352
- enabled: boolean;
353
- children: ReactNode;
354
- }
355
- function ContainerTable(props: ContainerTableProps) {
356
- const { scrollElementRef, enabled, children } = props;
357
- useDropMonitor(scrollElementRef, enabled);
358
- return <>{children}</>;
359
- }
360
-
361
350
  function useCheckProps(
362
351
  props: TableProps<unknown>,
363
352
  headers: Array<Header<unknown, unknown>>,
@@ -0,0 +1,17 @@
1
+ import type { Row } from '@tanstack/react-table';
2
+ import type { JSX } from 'react';
3
+ import { useRef } from 'react';
4
+
5
+ import { useFlashRowEffect } from './flash_row/use_flash_row_effect.js';
6
+
7
+ export interface TableRowTrProps {
8
+ row: Row<unknown>;
9
+ trProps: JSX.IntrinsicElements['tr'];
10
+ }
11
+
12
+ export function TableRowTr(props: TableRowTrProps) {
13
+ const { row, trProps } = props;
14
+ const tableRowRef = useRef<HTMLTableRowElement>(null);
15
+ useFlashRowEffect(row.id, tableRowRef);
16
+ return <tr ref={tableRowRef} {...trProps} />;
17
+ }
@@ -0,0 +1,103 @@
1
+ import styled from '@emotion/styled';
2
+ import type { Virtualizer } from '@tanstack/react-virtual';
3
+ import type { Table as TanstackTable } from '@tanstack/table-core';
4
+ import type { ReactNode, RefObject } from 'react';
5
+
6
+ import { useDropMonitor } from './reorder_rows/use_drop_monitor.js';
7
+ import type { TableProps } from './table_root.js';
8
+ import { useTableScroll } from './use_table_scroll.js';
9
+
10
+ const ScrollRefDiv = styled.div`
11
+ height: 100%;
12
+ overflow: auto;
13
+ `;
14
+
15
+ interface ScrollContainerProps {
16
+ /**
17
+ * Whether the table rows are virtualized.
18
+ */
19
+ virtualizeRows?: boolean;
20
+ /**
21
+ * The tanstack virtualizer.
22
+ */
23
+ virtualizer: Virtualizer<HTMLDivElement, Element>;
24
+ /**
25
+ * The tanstack table.
26
+ */
27
+ table: TanstackTable<unknown>;
28
+ /**
29
+ * A ref to the effective scroll container.
30
+ */
31
+ scrollRef: RefObject<Element>;
32
+ /**
33
+ * The user provided ref to attach the scroll callbacks to.
34
+ * It is set by the ScrollContainer component if the table is virtualized.
35
+ * It is an external ref when the table is not virtualized.
36
+ */
37
+ scrollToRowRef?: TableProps<unknown>['scrollToRowRef'];
38
+ isReorderingEnabled: boolean;
39
+ children: ReactNode;
40
+ }
41
+
42
+ export function ScrollContainer(props: ScrollContainerProps) {
43
+ const {
44
+ virtualizeRows,
45
+ table,
46
+ virtualizer,
47
+ scrollRef,
48
+ scrollToRowRef,
49
+ isReorderingEnabled,
50
+ children,
51
+ } = props;
52
+ useTableScroll({
53
+ virtualizeRows,
54
+ table,
55
+ virtualizer,
56
+ scrollRef,
57
+ scrollToRowRef,
58
+ });
59
+ if (virtualizeRows) {
60
+ return (
61
+ <ContainerVirtual
62
+ scrollElementRef={scrollRef}
63
+ isReorderingEnabled={isReorderingEnabled}
64
+ >
65
+ {children}
66
+ </ContainerVirtual>
67
+ );
68
+ }
69
+ return (
70
+ <NoContainer scrollElementRef={scrollRef} enabled={isReorderingEnabled}>
71
+ {children}
72
+ </NoContainer>
73
+ );
74
+ }
75
+
76
+ interface ContainerWithReorderingProps {
77
+ scrollElementRef: RefObject<Element>;
78
+ isReorderingEnabled: boolean;
79
+ children: ReactNode;
80
+ }
81
+
82
+ function ContainerVirtual(props: ContainerWithReorderingProps) {
83
+ const { scrollElementRef, isReorderingEnabled, children } = props;
84
+ useDropMonitor(scrollElementRef, isReorderingEnabled);
85
+
86
+ return (
87
+ <ScrollRefDiv ref={scrollElementRef as RefObject<HTMLDivElement>}>
88
+ {children}
89
+ </ScrollRefDiv>
90
+ );
91
+ }
92
+
93
+ interface NoContainerProps {
94
+ scrollElementRef: RefObject<Element>;
95
+ enabled: boolean;
96
+ children: ReactNode;
97
+ }
98
+
99
+ function NoContainer(props: NoContainerProps) {
100
+ const { scrollElementRef, enabled, children } = props;
101
+ useDropMonitor(scrollElementRef, enabled);
102
+ return <>{children}</>;
103
+ }