react-science 13.0.2 → 15.0.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 (150) hide show
  1. package/lib/components/activity_bar/activity_bar.js +1 -1
  2. package/lib/components/activity_bar/activity_bar.js.map +1 -1
  3. package/lib/components/activity_panel/activity_panel.js +1 -1
  4. package/lib/components/activity_panel/activity_panel.js.map +1 -1
  5. package/lib/components/drop-zone/DropZone.js +1 -1
  6. package/lib/components/drop-zone/DropZone.js.map +1 -1
  7. package/lib/components/forms/radio-button-group/RadioButton.js +4 -4
  8. package/lib/components/forms/radio-button-group/RadioButton.js.map +1 -1
  9. package/lib/components/forms/radio-button-group/RadioButtonGroup.d.ts +2 -2
  10. package/lib/components/forms/radio-button-group/RadioButtonGroup.d.ts.map +1 -1
  11. package/lib/components/forms/radio-button-group/RadioButtonGroup.js +8 -8
  12. package/lib/components/forms/radio-button-group/RadioButtonGroup.js.map +1 -1
  13. package/lib/components/forms/styles.d.ts +0 -1
  14. package/lib/components/forms/styles.d.ts.map +1 -1
  15. package/lib/components/forms/styles.js.map +1 -1
  16. package/lib/components/header/PanelHeader.d.ts.map +1 -1
  17. package/lib/components/header/PanelHeader.js +1 -1
  18. package/lib/components/header/PanelHeader.js.map +1 -1
  19. package/lib/components/index.d.ts +1 -1
  20. package/lib/components/index.js +1 -1
  21. package/lib/components/info-panel/InfoPanel.js +2 -2
  22. package/lib/components/info-panel/InfoPanel.js.map +1 -1
  23. package/lib/components/logger/FifoLoggerDialog.js +1 -1
  24. package/lib/components/logger/FifoLoggerDialog.js.map +1 -1
  25. package/lib/components/split_pane/index.d.ts +3 -0
  26. package/lib/components/split_pane/index.d.ts.map +1 -0
  27. package/lib/components/split_pane/index.js +3 -0
  28. package/lib/components/split_pane/index.js.map +1 -0
  29. package/lib/components/{split-pane/SplitPane.d.ts → split_pane/split_pane.d.ts} +7 -5
  30. package/lib/components/split_pane/split_pane.d.ts.map +1 -0
  31. package/lib/components/{split-pane/SplitPane.js → split_pane/split_pane.js} +25 -32
  32. package/lib/components/split_pane/split_pane.js.map +1 -0
  33. package/lib/components/split_pane/split_pane_helpers.d.ts +9 -0
  34. package/lib/components/split_pane/split_pane_helpers.d.ts.map +1 -0
  35. package/lib/components/split_pane/split_pane_helpers.js +10 -0
  36. package/lib/components/split_pane/split_pane_helpers.js.map +1 -0
  37. package/lib/components/{split-pane/useSplitPaneSize.d.ts → split_pane/use_split_pane_size.d.ts} +5 -3
  38. package/lib/components/split_pane/use_split_pane_size.d.ts.map +1 -0
  39. package/lib/components/split_pane/use_split_pane_size.js +78 -0
  40. package/lib/components/split_pane/use_split_pane_size.js.map +1 -0
  41. package/lib/components/table/index.d.ts +1 -0
  42. package/lib/components/table/index.d.ts.map +1 -1
  43. package/lib/components/table/index.js +1 -0
  44. package/lib/components/table/index.js.map +1 -1
  45. package/lib/components/table/reorder_rows/draggable_row_context.d.ts +9 -0
  46. package/lib/components/table/reorder_rows/draggable_row_context.d.ts.map +1 -0
  47. package/lib/components/table/reorder_rows/draggable_row_context.js +10 -0
  48. package/lib/components/table/reorder_rows/draggable_row_context.js.map +1 -0
  49. package/lib/components/table/reorder_rows/draggable_row_tr.d.ts +18 -0
  50. package/lib/components/table/reorder_rows/draggable_row_tr.d.ts.map +1 -0
  51. package/lib/components/table/reorder_rows/draggable_row_tr.js +107 -0
  52. package/lib/components/table/reorder_rows/draggable_row_tr.js.map +1 -0
  53. package/lib/components/table/reorder_rows/drop_indicator.d.ts +18 -0
  54. package/lib/components/table/reorder_rows/drop_indicator.d.ts.map +1 -0
  55. package/lib/components/table/reorder_rows/drop_indicator.js +19 -0
  56. package/lib/components/table/reorder_rows/drop_indicator.js.map +1 -0
  57. package/lib/components/table/reorder_rows/dropped_item_context.d.ts +3 -0
  58. package/lib/components/table/reorder_rows/dropped_item_context.d.ts.map +1 -0
  59. package/lib/components/table/reorder_rows/dropped_item_context.js +10 -0
  60. package/lib/components/table/reorder_rows/dropped_item_context.js.map +1 -0
  61. package/lib/components/table/reorder_rows/dropped_item_provider.d.ts +5 -0
  62. package/lib/components/table/reorder_rows/dropped_item_provider.d.ts.map +1 -0
  63. package/lib/components/table/reorder_rows/dropped_item_provider.js +8 -0
  64. package/lib/components/table/reorder_rows/dropped_item_provider.js.map +1 -0
  65. package/lib/components/table/reorder_rows/index.d.ts +5 -0
  66. package/lib/components/table/reorder_rows/index.d.ts.map +1 -0
  67. package/lib/components/table/reorder_rows/index.js +5 -0
  68. package/lib/components/table/reorder_rows/index.js.map +1 -0
  69. package/lib/components/table/reorder_rows/item_data.d.ts +26 -0
  70. package/lib/components/table/reorder_rows/item_data.d.ts.map +1 -0
  71. package/lib/components/table/reorder_rows/item_data.js +13 -0
  72. package/lib/components/table/reorder_rows/item_data.js.map +1 -0
  73. package/lib/components/table/reorder_rows/item_order_context.d.ts +15 -0
  74. package/lib/components/table/reorder_rows/item_order_context.d.ts.map +1 -0
  75. package/lib/components/table/reorder_rows/item_order_context.js +10 -0
  76. package/lib/components/table/reorder_rows/item_order_context.js.map +1 -0
  77. package/lib/components/table/reorder_rows/item_order_provider.d.ts +10 -0
  78. package/lib/components/table/reorder_rows/item_order_provider.d.ts.map +1 -0
  79. package/lib/components/table/reorder_rows/item_order_provider.js +34 -0
  80. package/lib/components/table/reorder_rows/item_order_provider.js.map +1 -0
  81. package/lib/components/table/reorder_rows/table_drag_row_handler.d.ts +2 -0
  82. package/lib/components/table/reorder_rows/table_drag_row_handler.d.ts.map +1 -0
  83. package/lib/components/table/reorder_rows/table_drag_row_handler.js +9 -0
  84. package/lib/components/table/reorder_rows/table_drag_row_handler.js.map +1 -0
  85. package/lib/components/table/reorder_rows/use_drop_monitor.d.ts +9 -0
  86. package/lib/components/table/reorder_rows/use_drop_monitor.d.ts.map +1 -0
  87. package/lib/components/table/reorder_rows/use_drop_monitor.js +57 -0
  88. package/lib/components/table/reorder_rows/use_drop_monitor.js.map +1 -0
  89. package/lib/components/table/table_body.d.ts +4 -1
  90. package/lib/components/table/table_body.d.ts.map +1 -1
  91. package/lib/components/table/table_body.js +20 -6
  92. package/lib/components/table/table_body.js.map +1 -1
  93. package/lib/components/table/table_root.d.ts +37 -1
  94. package/lib/components/table/table_root.d.ts.map +1 -1
  95. package/lib/components/table/table_root.js +41 -7
  96. package/lib/components/table/table_root.js.map +1 -1
  97. package/lib/components/table/table_row_cell.d.ts +2 -1
  98. package/lib/components/table/table_row_cell.d.ts.map +1 -1
  99. package/lib/components/table/table_row_cell.js +2 -2
  100. package/lib/components/table/table_row_cell.js.map +1 -1
  101. package/lib/components/table/table_utils.d.ts +11 -2
  102. package/lib/components/table/table_utils.d.ts.map +1 -1
  103. package/lib/components/table/table_utils.js.map +1 -1
  104. package/lib/components/toolbar/Toolbar.js +2 -2
  105. package/lib/components/toolbar/Toolbar.js.map +1 -1
  106. package/lib/components/toolbar/TooltipHelpContent.js +2 -2
  107. package/package.json +19 -16
  108. package/src/components/activity_bar/activity_bar.tsx +1 -1
  109. package/src/components/activity_panel/activity_panel.tsx +1 -1
  110. package/src/components/drop-zone/DropZone.tsx +1 -1
  111. package/src/components/forms/radio-button-group/RadioButton.tsx +7 -7
  112. package/src/components/forms/radio-button-group/RadioButtonGroup.tsx +15 -11
  113. package/src/components/forms/styles.ts +0 -2
  114. package/src/components/header/PanelHeader.tsx +6 -1
  115. package/src/components/index.ts +1 -1
  116. package/src/components/info-panel/InfoPanel.tsx +2 -2
  117. package/src/components/logger/FifoLoggerDialog.tsx +2 -2
  118. package/src/components/split_pane/index.ts +2 -0
  119. package/src/components/{split-pane/SplitPane.tsx → split_pane/split_pane.tsx} +63 -56
  120. package/src/components/split_pane/split_pane_helpers.ts +19 -0
  121. package/src/components/split_pane/use_split_pane_size.tsx +120 -0
  122. package/src/components/table/index.ts +1 -0
  123. package/src/components/table/reorder_rows/draggable_row_context.ts +23 -0
  124. package/src/components/table/reorder_rows/draggable_row_tr.tsx +166 -0
  125. package/src/components/table/reorder_rows/drop_indicator.tsx +28 -0
  126. package/src/components/table/reorder_rows/dropped_item_context.ts +23 -0
  127. package/src/components/table/reorder_rows/dropped_item_provider.tsx +13 -0
  128. package/src/components/table/reorder_rows/index.ts +4 -0
  129. package/src/components/table/reorder_rows/item_data.ts +33 -0
  130. package/src/components/table/reorder_rows/item_order_context.ts +27 -0
  131. package/src/components/table/reorder_rows/item_order_provider.tsx +61 -0
  132. package/src/components/table/reorder_rows/table_drag_row_handler.tsx +22 -0
  133. package/src/components/table/reorder_rows/use_drop_monitor.ts +74 -0
  134. package/src/components/table/table_body.tsx +58 -9
  135. package/src/components/table/table_root.tsx +167 -35
  136. package/src/components/table/table_row_cell.tsx +5 -3
  137. package/src/components/table/table_utils.ts +16 -2
  138. package/src/components/toolbar/Toolbar.tsx +2 -2
  139. package/src/components/toolbar/TooltipHelpContent.tsx +2 -2
  140. package/lib/components/split-pane/SplitPane.d.ts.map +0 -1
  141. package/lib/components/split-pane/SplitPane.js.map +0 -1
  142. package/lib/components/split-pane/index.d.ts +0 -2
  143. package/lib/components/split-pane/index.d.ts.map +0 -1
  144. package/lib/components/split-pane/index.js +0 -2
  145. package/lib/components/split-pane/index.js.map +0 -1
  146. package/lib/components/split-pane/useSplitPaneSize.d.ts.map +0 -1
  147. package/lib/components/split-pane/useSplitPaneSize.js +0 -60
  148. package/lib/components/split-pane/useSplitPaneSize.js.map +0 -1
  149. package/src/components/split-pane/index.ts +0 -1
  150. package/src/components/split-pane/useSplitPaneSize.tsx +0 -99
@@ -0,0 +1,166 @@
1
+ import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
2
+ import type { ElementDragPayload } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
3
+ import {
4
+ draggable,
5
+ dropTargetForElements,
6
+ } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
7
+ import { pointerOutsideOfPreview } from '@atlaskit/pragmatic-drag-and-drop/element/pointer-outside-of-preview';
8
+ import { setCustomNativeDragPreview } from '@atlaskit/pragmatic-drag-and-drop/element/set-custom-native-drag-preview';
9
+ import {
10
+ attachClosestEdge,
11
+ extractClosestEdge,
12
+ } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
13
+ import { Colors } from '@blueprintjs/core';
14
+ import type { Row, RowData } from '@tanstack/react-table';
15
+ import { useEffect, useMemo, useRef, useState } from 'react';
16
+ import { createPortal } from 'react-dom';
17
+
18
+ import { assert } from '../../utils/index.js';
19
+ import type {
20
+ TableRowPreviewRenderer,
21
+ TableRowTrProps,
22
+ } from '../table_utils.js';
23
+
24
+ import type { DraggableRowContext } from './draggable_row_context.js';
25
+ import { draggableRowContext } from './draggable_row_context.js';
26
+ import { useDroppedItemContext } from './dropped_item_context.js';
27
+ import type { DraggableItemState } from './item_data.js';
28
+ import { getItemData, isItemData } from './item_data.js';
29
+ import { useItemOrder } from './item_order_context.js';
30
+
31
+ export interface TableDraggableRowTrProps<TData extends RowData> {
32
+ /**
33
+ * Props to be spread on the `tr` element.
34
+ */
35
+ trProps: TableRowTrProps;
36
+ /**
37
+ * Row data.
38
+ */
39
+ row: Row<TData>;
40
+ /**
41
+ * Preview of the row being dragged.
42
+ */
43
+ renderRowPreview: TableRowPreviewRenderer<TData>;
44
+ }
45
+
46
+ export function TableDraggableRowTr<TData extends RowData>(
47
+ props: TableDraggableRowTrProps<TData>,
48
+ ) {
49
+ const { trProps, row, renderRowPreview } = props;
50
+ const { instanceId } = useItemOrder();
51
+ const innerRef = useRef<HTMLTableRowElement>(null);
52
+ const [state, setState] = useState<DraggableItemState>(idleState);
53
+ const [droppedItemId, setDroppedItemId] = useDroppedItemContext();
54
+
55
+ const dragHandleRef = useRef<HTMLButtonElement>(null);
56
+ useEffect(() => {
57
+ const trElement = innerRef.current;
58
+ assert(trElement, 'tr ref is null');
59
+ assert(dragHandleRef.current, 'dragHandleRef is null');
60
+
61
+ function canDrop({ source }: { source: ElementDragPayload }): boolean {
62
+ return (
63
+ isItemData(source.data) &&
64
+ source.data.instanceId === instanceId &&
65
+ source.data.id !== row.id
66
+ );
67
+ }
68
+
69
+ const data = getItemData(row as Row<unknown>, instanceId);
70
+
71
+ return combine(
72
+ draggable({
73
+ element: trElement,
74
+ dragHandle: dragHandleRef.current,
75
+ getInitialData: () => data,
76
+ onGenerateDragPreview({ nativeSetDragImage }) {
77
+ setCustomNativeDragPreview({
78
+ nativeSetDragImage,
79
+ getOffset: pointerOutsideOfPreview({
80
+ x: '8px',
81
+ y: '8px',
82
+ }),
83
+ render({ container }) {
84
+ setState({ type: 'preview', container });
85
+
86
+ return () => setState(draggingState);
87
+ },
88
+ });
89
+ },
90
+ onDragStart() {
91
+ setState(draggingState);
92
+ },
93
+ onDrop() {
94
+ setState(idleState);
95
+ },
96
+ }),
97
+ dropTargetForElements({
98
+ element: trElement,
99
+ canDrop,
100
+ getIsSticky: () => false,
101
+ getData({ input }) {
102
+ return attachClosestEdge(data, {
103
+ element: trElement,
104
+ input,
105
+ allowedEdges: ['top', 'bottom'],
106
+ });
107
+ },
108
+ onDrag({ self }) {
109
+ const closestEdge = extractClosestEdge(self.data);
110
+ setState((current) => {
111
+ if (
112
+ current.type === 'is-over' &&
113
+ current.closestEdge === closestEdge
114
+ ) {
115
+ return current;
116
+ }
117
+ return { type: 'is-over', closestEdge };
118
+ });
119
+ },
120
+ onDragLeave() {
121
+ setState(idleState);
122
+ },
123
+ onDrop() {
124
+ setState(idleState);
125
+ },
126
+ }),
127
+ );
128
+ }, [row, instanceId]);
129
+
130
+ useEffect(() => {
131
+ if (droppedItemId === row.id && innerRef.current) {
132
+ triggerPostFlash(innerRef.current);
133
+ setDroppedItemId(undefined);
134
+ }
135
+ }, [droppedItemId, row.id, setDroppedItemId]);
136
+
137
+ const value = useMemo<DraggableRowContext>(() => {
138
+ return {
139
+ dragHandleRef,
140
+ state,
141
+ };
142
+ }, [state]);
143
+
144
+ return (
145
+ <>
146
+ <draggableRowContext.Provider value={value}>
147
+ <tr {...trProps} ref={innerRef} />
148
+ </draggableRowContext.Provider>
149
+ {state.type === 'preview' &&
150
+ createPortal(renderRowPreview(row), state.container)}
151
+ </>
152
+ );
153
+ }
154
+
155
+ const idleState: DraggableItemState = { type: 'idle' };
156
+ 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
+ }
@@ -0,0 +1,28 @@
1
+ import type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/types';
2
+ import { Colors } from '@blueprintjs/core';
3
+ import styled from '@emotion/styled';
4
+
5
+ export interface TableDropIndicatorProps {
6
+ /**
7
+ * The edge (top or bottom) on which to render the drop indicator
8
+ * with respect to the nearest relatively positioned element.
9
+ */
10
+ edge: Edge;
11
+ }
12
+
13
+ /**
14
+ * An absolutely positioned line which indicates where a dragged item will
15
+ * be dropped.
16
+ *
17
+ */
18
+ export const TableDropIndicator = styled.div<TableDropIndicatorProps>`
19
+ position: absolute;
20
+ z-index: 1;
21
+ background-color: ${Colors.BLUE3};
22
+ height: 2px;
23
+ left: 0;
24
+ right: 0;
25
+ pointer-events: none;
26
+ ${(props) => props.edge === 'top' && 'top: -1px;'}
27
+ ${(props) => props.edge === 'bottom' && 'bottom: -1px;'}
28
+ `;
@@ -0,0 +1,23 @@
1
+ import type { useState } from 'react';
2
+ import { createContext, useContext } from 'react';
3
+
4
+ /**
5
+ * ID of the dropped item
6
+ */
7
+ type DroppedItemContextValue = ReturnType<typeof useState<string>>;
8
+
9
+ export const droppedItemContext = createContext<DroppedItemContextValue | null>(
10
+ null,
11
+ );
12
+
13
+ export function useDroppedItemContext() {
14
+ const context = useContext(droppedItemContext);
15
+
16
+ if (!context) {
17
+ throw new Error(
18
+ 'useDroppedItemId must be used within a DroppedItemProvider',
19
+ );
20
+ }
21
+
22
+ return context;
23
+ }
@@ -0,0 +1,13 @@
1
+ import { useState } from 'react';
2
+ import type { ReactNode } from 'react';
3
+
4
+ import { droppedItemContext } from './dropped_item_context.js';
5
+
6
+ export function DroppedItemProvider(props: { children: ReactNode }) {
7
+ const value = useState<string>();
8
+ return (
9
+ <droppedItemContext.Provider value={value}>
10
+ {props.children}
11
+ </droppedItemContext.Provider>
12
+ );
13
+ }
@@ -0,0 +1,4 @@
1
+ export * from './table_drag_row_handler.js';
2
+ export { useTableDraggableRowContext } from './draggable_row_context.js';
3
+ export * from './draggable_row_tr.js';
4
+ export * from './drop_indicator.js';
@@ -0,0 +1,33 @@
1
+ import type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/types';
2
+ import type { Row } from '@tanstack/react-table';
3
+
4
+ const itemKey = Symbol('table-item-data');
5
+ export interface ItemData {
6
+ [itemKey]: true;
7
+ instanceId: symbol;
8
+ id: string;
9
+ index: number;
10
+ [key: string]: unknown;
11
+ [key: symbol]: unknown;
12
+ }
13
+
14
+ export function getItemData(row: Row<unknown>, instanceId: symbol): ItemData {
15
+ return {
16
+ [itemKey]: true,
17
+ id: row.id,
18
+ index: row.index,
19
+ instanceId,
20
+ };
21
+ }
22
+
23
+ export function isItemData(
24
+ data: Record<string | symbol, unknown>,
25
+ ): data is ItemData {
26
+ return data[itemKey] === true;
27
+ }
28
+
29
+ export type DraggableItemState =
30
+ | { type: 'idle' }
31
+ | { type: 'preview'; container: HTMLElement }
32
+ | { type: 'dragging' }
33
+ | { type: 'is-over'; closestEdge: Edge | null };
@@ -0,0 +1,27 @@
1
+ import type { Edge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/types';
2
+ import type { Row } from '@tanstack/react-table';
3
+ import { createContext, useContext } from 'react';
4
+
5
+ export type ReorderItemCallback = (args: {
6
+ startIndex: number;
7
+ indexOfTarget: number;
8
+ closestEdgeOfTarget: Edge | null;
9
+ }) => void;
10
+
11
+ export interface ItemOrderContextValue<T = unknown> {
12
+ items: Array<Row<T>>;
13
+ reorderItem: ReorderItemCallback;
14
+ instanceId: symbol;
15
+ }
16
+
17
+ export const itemOrderContext = createContext<ItemOrderContextValue | null>(
18
+ null,
19
+ );
20
+
21
+ export function useItemOrder() {
22
+ const context = useContext(itemOrderContext);
23
+ if (!context) {
24
+ throw new Error('useItemOrder must be used within a ListContextProvider');
25
+ }
26
+ return context;
27
+ }
@@ -0,0 +1,61 @@
1
+ import { reorder } from '@atlaskit/pragmatic-drag-and-drop/reorder';
2
+ import { getReorderDestinationIndex } from '@atlaskit/pragmatic-drag-and-drop-hitbox/util/get-reorder-destination-index';
3
+ import type { Row } from '@tanstack/react-table';
4
+ import type { ReactNode } from 'react';
5
+ import { useCallback, useMemo, useState } from 'react';
6
+
7
+ import type { ReorderItemCallback } from './item_order_context.js';
8
+ import { itemOrderContext } from './item_order_context.js';
9
+
10
+ interface ItemOrderProviderProps<T> {
11
+ items: Array<Row<T>>;
12
+ onOrderChanged: (items: Array<Row<T>>) => void;
13
+ children: ReactNode;
14
+ }
15
+
16
+ export function ItemOrderProvider<T = unknown>(
17
+ props: ItemOrderProviderProps<T>,
18
+ ) {
19
+ // Isolated instances of this component from one another
20
+ const [instanceId] = useState(() => Symbol('table-instance-id'));
21
+ const { items, onOrderChanged, children } = props;
22
+ const reorderItem = useCallback<ReorderItemCallback>(
23
+ ({ startIndex, indexOfTarget, closestEdgeOfTarget }) => {
24
+ const finishIndex = getReorderDestinationIndex({
25
+ startIndex,
26
+ closestEdgeOfTarget,
27
+ indexOfTarget,
28
+ axis: 'vertical',
29
+ });
30
+
31
+ if (finishIndex === startIndex) {
32
+ // If there is no change, we skip the update
33
+ return;
34
+ }
35
+
36
+ onOrderChanged(
37
+ reorder({
38
+ list: items,
39
+ startIndex,
40
+ finishIndex,
41
+ }),
42
+ );
43
+ },
44
+ [items, onOrderChanged],
45
+ );
46
+
47
+ const value = useMemo(
48
+ () => ({
49
+ reorderItem,
50
+ items: items as Array<Row<unknown>>,
51
+ instanceId,
52
+ }),
53
+ [reorderItem, items, instanceId],
54
+ );
55
+
56
+ return (
57
+ <itemOrderContext.Provider value={value}>
58
+ {children}
59
+ </itemOrderContext.Provider>
60
+ );
61
+ }
@@ -0,0 +1,22 @@
1
+ import { Button } from '@blueprintjs/core';
2
+
3
+ import { useTableDraggableRowContext } from './draggable_row_context.js';
4
+ import { TableDropIndicator } from './drop_indicator.js';
5
+
6
+ export function TableDragRowHandler() {
7
+ const { dragHandleRef, state } = useTableDraggableRowContext();
8
+ return (
9
+ <>
10
+ <Button
11
+ icon="drag-handle-horizontal"
12
+ type="button"
13
+ ref={dragHandleRef}
14
+ variant="minimal"
15
+ style={{ cursor: 'grab' }}
16
+ />
17
+ {state?.type === 'is-over' && state.closestEdge && (
18
+ <TableDropIndicator edge={state.closestEdge} />
19
+ )}
20
+ </>
21
+ );
22
+ }
@@ -0,0 +1,74 @@
1
+ import { combine } from '@atlaskit/pragmatic-drag-and-drop/combine';
2
+ import type { ElementDragPayload } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
3
+ import { monitorForElements } from '@atlaskit/pragmatic-drag-and-drop/element/adapter';
4
+ import { autoScrollForElements } from '@atlaskit/pragmatic-drag-and-drop-auto-scroll/element';
5
+ import { extractClosestEdge } from '@atlaskit/pragmatic-drag-and-drop-hitbox/closest-edge';
6
+ import type { RefObject } from 'react';
7
+ import { useEffect } from 'react';
8
+
9
+ import { assert } from '../../utils/index.js';
10
+
11
+ import { useDroppedItemContext } from './dropped_item_context.js';
12
+ import { isItemData } from './item_data.js';
13
+ import { useItemOrder } from './item_order_context.js';
14
+
15
+ /**
16
+ * Monitor drop events.
17
+ * Check if they can be acted on to reorder items.
18
+ * @param scrollElementRef The element to auto-scroll when dragging elements.
19
+ * @param enabled Enable or disable the monitoring.
20
+ */
21
+ export function useDropMonitor(
22
+ scrollElementRef: RefObject<Element>,
23
+ enabled: boolean,
24
+ ) {
25
+ const { reorderItem, items } = useItemOrder();
26
+ const [, setDroppedItem] = useDroppedItemContext();
27
+ useEffect(() => {
28
+ const scrollContainer = scrollElementRef.current;
29
+ assert(scrollContainer, 'Missing scroll container ref');
30
+
31
+ if (enabled) {
32
+ function canRespond({ source }: { source: ElementDragPayload }) {
33
+ return isItemData(source.data);
34
+ }
35
+ return combine(
36
+ monitorForElements({
37
+ canMonitor: canRespond,
38
+ onDrop({ location, source }) {
39
+ const target = location.current.dropTargets[0];
40
+ if (!target) {
41
+ return;
42
+ }
43
+
44
+ const sourceData = source.data;
45
+ const targetData = target.data;
46
+ if (!isItemData(sourceData) || !isItemData(targetData)) {
47
+ return;
48
+ }
49
+
50
+ const indexOfTarget = items.findIndex(
51
+ (item) => item.id === targetData.id,
52
+ );
53
+ if (indexOfTarget === -1) {
54
+ return;
55
+ }
56
+
57
+ const closestEdgeOfTarget = extractClosestEdge(targetData);
58
+
59
+ reorderItem({
60
+ startIndex: sourceData.index,
61
+ indexOfTarget,
62
+ closestEdgeOfTarget,
63
+ });
64
+ setDroppedItem(sourceData.id);
65
+ },
66
+ }),
67
+ autoScrollForElements({
68
+ canScroll: canRespond,
69
+ element: scrollContainer,
70
+ }),
71
+ );
72
+ }
73
+ }, [items, reorderItem, scrollElementRef, setDroppedItem, enabled]);
74
+ }
@@ -1,23 +1,37 @@
1
+ import { Tag } from '@blueprintjs/core';
1
2
  import type { Row, RowData } from '@tanstack/react-table';
2
3
  import type { VirtualItem, Virtualizer } from '@tanstack/react-virtual';
3
4
  import { notUndefined } from '@tanstack/react-virtual';
4
5
  import type { ReactNode } from 'react';
5
6
  import { Fragment } from 'react';
6
7
 
8
+ import { TableDraggableRowTr } from './reorder_rows/index.js';
7
9
  import { TableRowCell } from './table_row_cell.js';
8
- import type { TableRowTrProps, TableRowTrRenderer } from './table_utils.js';
10
+ import type {
11
+ GetTdProps,
12
+ TableRowPreviewRenderer,
13
+ TableRowTrProps,
14
+ TableRowTrRenderer,
15
+ } from './table_utils.js';
9
16
 
10
17
  interface TableBodyProps<TData extends RowData> {
11
18
  rows: Array<Row<TData>>;
19
+ getTdProps?: GetTdProps<TData>;
12
20
  renderRowTr: TableRowTrRenderer<TData> | undefined;
13
21
  virtualizeRows?: boolean;
14
22
  virtualizer: Virtualizer<HTMLDivElement, Element>;
23
+ isReorderingEnabled: boolean;
24
+ renderRowPreview?: TableRowPreviewRenderer<TData>;
15
25
  }
16
26
 
17
27
  export function TableBody<TData extends RowData>(props: TableBodyProps<TData>) {
18
28
  const {
19
29
  rows,
20
- renderRowTr = defaultRenderRowTr as TableRowTrRenderer<TData>,
30
+ getTdProps,
31
+ renderRowTr = getDefaultRenderRowTr(
32
+ props.isReorderingEnabled,
33
+ props.renderRowPreview as TableRowPreviewRenderer<unknown>,
34
+ ) as TableRowTrRenderer<TData>,
21
35
  virtualizer,
22
36
  virtualizeRows,
23
37
  } = props;
@@ -43,7 +57,7 @@ export function TableBody<TData extends RowData>(props: TableBodyProps<TData>) {
43
57
  key={virtualItem.index}
44
58
  row={rows[virtualItem.index]}
45
59
  renderRowTr={(row) => {
46
- const trProps = getTrRenderProps<TData>(row, {
60
+ const trProps = getTrRenderProps<TData>(row, getTdProps, {
47
61
  ...virtualItem,
48
62
  virtualIndex: index,
49
63
  });
@@ -65,7 +79,9 @@ export function TableBody<TData extends RowData>(props: TableBodyProps<TData>) {
65
79
  <TableRow
66
80
  key={row.id}
67
81
  row={row}
68
- renderRowTr={(row) => renderRowTr(getTrRenderProps(row), row)}
82
+ renderRowTr={(row) =>
83
+ renderRowTr(getTrRenderProps(row, getTdProps), row)
84
+ }
69
85
  />
70
86
  ))}
71
87
  </tbody>
@@ -84,10 +100,6 @@ function TableRow<TData>({
84
100
  return <Fragment>{renderRowTr(row)}</Fragment>;
85
101
  }
86
102
 
87
- const defaultRenderRowTr: TableRowTrRenderer<unknown> = (trProps) => (
88
- <tr {...trProps} />
89
- );
90
-
91
103
  type RenderRowVirtualItem = VirtualItem & {
92
104
  /**
93
105
  * The index of the element within the virtual list being currently rendered.
@@ -97,6 +109,7 @@ type RenderRowVirtualItem = VirtualItem & {
97
109
 
98
110
  function getTrRenderProps<TData extends RowData>(
99
111
  row: Row<TData>,
112
+ getTdProps: GetTdProps<TData> | undefined,
100
113
  virtualItem?: RenderRowVirtualItem,
101
114
  ): TableRowTrProps {
102
115
  const index = virtualItem ? virtualItem.index : row.index;
@@ -104,9 +117,45 @@ function getTrRenderProps<TData extends RowData>(
104
117
  return {
105
118
  // index is 0-indexed, so odd rows are even indices
106
119
  className: index % 2 === 0 ? 'odd' : '',
120
+ style: { position: 'relative' },
107
121
  children: row
108
122
  .getVisibleCells()
109
- .map((cell) => <TableRowCell key={cell.id} cell={cell} />),
123
+ .map((cell) => (
124
+ <TableRowCell<TData>
125
+ key={cell.id}
126
+ cell={cell}
127
+ getTdProps={getTdProps}
128
+ />
129
+ )),
110
130
  'data-row-id': row.id,
111
131
  };
112
132
  }
133
+
134
+ function getDefaultRenderRowTr(
135
+ isReorderingEnabled: boolean,
136
+ renderRowPreview: TableRowPreviewRenderer<unknown> | undefined,
137
+ ): TableRowTrRenderer<unknown> {
138
+ if (isReorderingEnabled) {
139
+ return getDefaultRenderDraggableRowTr(renderRowPreview);
140
+ } else {
141
+ return defaultRenderRowTr;
142
+ }
143
+ }
144
+
145
+ const defaultRenderRowTr: TableRowTrRenderer<unknown> = (trProps) => (
146
+ <tr {...trProps} />
147
+ );
148
+
149
+ function getDefaultRenderDraggableRowTr(
150
+ renderRowPreview: TableRowPreviewRenderer<unknown> | undefined,
151
+ ): TableRowTrRenderer<unknown> {
152
+ return (trProps, row) => (
153
+ <TableDraggableRowTr
154
+ trProps={trProps}
155
+ row={row}
156
+ renderRowPreview={
157
+ renderRowPreview ?? ((row) => <Tag>Row {row.index + 1}</Tag>)
158
+ }
159
+ />
160
+ );
161
+ }