@purpurds/table 8.7.0 → 8.8.1

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.
@@ -1,15 +1,11 @@
1
1
  import { default as React } from 'react';
2
2
 
3
- export declare function useDragHandle(): {
4
- mouseDownActive: boolean;
5
- handleMouseDown: () => void;
6
- };
7
3
  export type TableColumnDragHandleProps = {
8
- onMouseDown: () => void;
9
4
  overlayActive?: boolean;
10
5
  isFirstColumn: boolean;
11
6
  isLastColumn: boolean;
12
7
  columnDragAriaLabel: string;
8
+ [key: string]: unknown;
13
9
  };
14
- export declare function TableColumnDragHandle({ onMouseDown, overlayActive, isFirstColumn, isLastColumn, columnDragAriaLabel, }: TableColumnDragHandleProps): React.JSX.Element;
10
+ export declare function TableColumnDragHandle({ overlayActive, isFirstColumn, isLastColumn, columnDragAriaLabel, ...dragListeners }: TableColumnDragHandleProps): React.JSX.Element;
15
11
  //# sourceMappingURL=use-drag-handle.hook.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"use-drag-handle.hook.d.ts","sourceRoot":"","sources":["../src/use-drag-handle.hook.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AASxC,wBAAgB,aAAa;;;EAa5B;AAED,MAAM,MAAM,0BAA0B,GAAG;IACvC,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,WAAW,EACX,aAAa,EACb,aAAa,EACb,YAAY,EACZ,mBAAmB,GACpB,EAAE,0BAA0B,qBAqB5B"}
1
+ {"version":3,"file":"use-drag-handle.hook.d.ts","sourceRoot":"","sources":["../src/use-drag-handle.hook.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B,MAAM,MAAM,0BAA0B,GAAG;IACvC,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,aAAa,EAAE,OAAO,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;IAE5B,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB,CAAC;AAEF,wBAAgB,qBAAqB,CAAC,EACpC,aAAa,EACb,aAAa,EACb,YAAY,EACZ,mBAAmB,EACnB,GAAG,aAAa,EACjB,EAAE,0BAA0B,qBAgB5B"}
@@ -1,8 +1,9 @@
1
1
  import { KeyboardCoordinateGetter } from '@dnd-kit/core';
2
2
 
3
3
  /**
4
- * Enhanced keyboard coordinate handler that better handles columns of different widths
5
- * by positioning the dragged column appropriately within target columns
4
+ * Simple keyboard coordinate handler that moves the drag overlay
5
+ * left or right incrementally and lets collision detection determine
6
+ * which column we're over.
6
7
  */
7
8
  export declare const enhancedColumnKeyboardCoordinates: KeyboardCoordinateGetter;
8
9
  //# sourceMappingURL=custom-keyboard-coordinates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"custom-keyboard-coordinates.d.ts","sourceRoot":"","sources":["../../src/utils/custom-keyboard-coordinates.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,wBAAwB,EAC9B,MAAM,eAAe,CAAC;AAEvB;;;GAGG;AACH,eAAO,MAAM,iCAAiC,EAAE,wBAsE/C,CAAC"}
1
+ {"version":3,"file":"custom-keyboard-coordinates.d.ts","sourceRoot":"","sources":["../../src/utils/custom-keyboard-coordinates.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,iCAAiC,EAAE,wBAoC/C,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@purpurds/table",
3
- "version": "8.7.0",
3
+ "version": "8.8.1",
4
4
  "license": "AGPL-3.0-only",
5
5
  "main": "./dist/table.cjs.js",
6
6
  "types": "./dist/table.d.ts",
@@ -21,26 +21,26 @@
21
21
  "@dnd-kit/utilities": "~3.2.2",
22
22
  "@tanstack/react-table": "~8.21.2",
23
23
  "classnames": "~2.5.0",
24
- "@purpurds/badge": "8.7.0",
25
- "@purpurds/button": "8.7.0",
26
- "@purpurds/cta-link": "8.7.0",
27
- "@purpurds/drawer": "8.7.0",
28
- "@purpurds/heading": "8.7.0",
29
- "@purpurds/icon": "8.7.0",
30
- "@purpurds/paragraph": "8.7.0",
31
- "@purpurds/link": "8.7.0",
32
- "@purpurds/select": "8.7.0",
33
- "@purpurds/skeleton": "8.7.0",
34
- "@purpurds/text-field": "8.7.0",
35
- "@purpurds/checkbox": "8.7.0",
36
- "@purpurds/visually-hidden": "8.7.0",
37
- "@purpurds/tooltip": "8.7.0",
38
- "@purpurds/tokens": "8.7.0",
39
- "@purpurds/toggle": "8.7.0"
24
+ "@purpurds/badge": "8.8.1",
25
+ "@purpurds/cta-link": "8.8.1",
26
+ "@purpurds/checkbox": "8.8.1",
27
+ "@purpurds/drawer": "8.8.1",
28
+ "@purpurds/button": "8.8.1",
29
+ "@purpurds/heading": "8.8.1",
30
+ "@purpurds/icon": "8.8.1",
31
+ "@purpurds/paragraph": "8.8.1",
32
+ "@purpurds/link": "8.8.1",
33
+ "@purpurds/text-field": "8.8.1",
34
+ "@purpurds/select": "8.8.1",
35
+ "@purpurds/skeleton": "8.8.1",
36
+ "@purpurds/toggle": "8.8.1",
37
+ "@purpurds/tokens": "8.8.1",
38
+ "@purpurds/tooltip": "8.8.1",
39
+ "@purpurds/visually-hidden": "8.8.1"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@rushstack/eslint-patch": "~1.10.0",
43
- "@storybook/react-vite": "^9.0.18",
43
+ "@storybook/react-vite": "^10.0.7",
44
44
  "@testing-library/dom": "~10.4.0",
45
45
  "@testing-library/jest-dom": "~6.4.0",
46
46
  "@testing-library/react": "~16.2.0",
@@ -54,19 +54,19 @@
54
54
  "prettier": "~2.8.8",
55
55
  "react-dom": "^19.0.0",
56
56
  "react": "^19.0.0",
57
- "storybook": "^9.0.18",
57
+ "storybook": "^10.0.7",
58
58
  "typescript": "^5.6.3",
59
59
  "vite": "^6.2.1",
60
60
  "vitest-axe": "~0.1.0",
61
61
  "vitest-canvas-mock": "~0.3.3",
62
62
  "vitest": "^3.1.2",
63
- "@purpurds/autocomplete": "8.7.0",
63
+ "@purpurds/autocomplete": "8.8.1",
64
64
  "@purpurds/component-rig": "1.0.0",
65
- "@purpurds/label": "8.7.0",
66
- "@purpurds/illustrative-icon": "8.7.0",
67
- "@purpurds/listbox": "8.7.0",
68
- "@purpurds/grid": "8.7.0",
69
- "@purpurds/pagination": "8.7.0"
65
+ "@purpurds/grid": "8.8.1",
66
+ "@purpurds/label": "8.8.1",
67
+ "@purpurds/listbox": "8.8.1",
68
+ "@purpurds/pagination": "8.8.1",
69
+ "@purpurds/illustrative-icon": "8.8.1"
70
70
  },
71
71
  "scripts": {
72
72
  "build:dev": "vite",
@@ -22,7 +22,7 @@ import c from "classnames/bind";
22
22
 
23
23
  import { DragIndicatorCircle } from "./drag-indicator-circle";
24
24
  import styles from "./table.module.scss";
25
- import { TableColumnDragHandle, useDragHandle } from "./use-drag-handle.hook";
25
+ import { TableColumnDragHandle } from "./use-drag-handle.hook";
26
26
  import { useDragIndicatorPosition } from "./use-drag-indicator-position.hook";
27
27
  import { useDropIndicator } from "./use-drop-indicator.hook";
28
28
  import { useElementVisibility } from "./use-element-visibility.hook";
@@ -100,9 +100,8 @@ export const TableColumnHeaderCell = <TData extends RowData>({
100
100
  disabled: !enableColumnDrag || activeId !== null,
101
101
  });
102
102
 
103
- const { mouseDownActive, handleMouseDown } = useDragHandle();
104
103
  const isActiveColumn = activeId === header.id || sortableId === activeId;
105
- const draggingActive = (overlayActive || isSorting || mouseDownActive) && isActiveColumn;
104
+ const draggingActive = (overlayActive || isSorting) && isActiveColumn;
106
105
  const isCheckBox = header.column.id === "row-selection" || header.id === "row-selection";
107
106
  const isRadiobutton = header.column.id === "row-radio" || header.id === "row-radio";
108
107
  const canSort = enableSorting && header.column.getCanSort();
@@ -184,12 +183,17 @@ export const TableColumnHeaderCell = <TData extends RowData>({
184
183
  aria-sort={getSortingDirection(header.column.getIsSorted())}
185
184
  aria-label={ariaLabel}
186
185
  {...(enableColumnDrag
187
- ? { ...attributes, ...listeners, id: `header-${sortableId || header.id}` }
186
+ ? {
187
+ ...attributes,
188
+ role: "columnheader", // Override the role="button" from useSortable
189
+ tabIndex: -1, // Make th non-focusable
190
+ id: `header-${sortableId || header.id}`,
191
+ }
188
192
  : {})}
189
193
  >
190
194
  {enableColumnDrag && (
191
195
  <TableColumnDragHandle
192
- onMouseDown={handleMouseDown}
196
+ {...listeners}
193
197
  overlayActive={overlayActive}
194
198
  isFirstColumn={isFirstColumn}
195
199
  isLastColumn={isLastColumn}
package/src/table.tsx CHANGED
@@ -205,7 +205,7 @@ export const Table = <TData extends RowData>({
205
205
  ...restProps,
206
206
  });
207
207
 
208
- const rowCount = useMemo(() => tanstackTable.getRowCount(), [tanstackTable]);
208
+ const rowCount = tanstackTable.getRowCount();
209
209
 
210
210
  useEffect(() => {
211
211
  if (onRowsCountChange) {
@@ -316,10 +316,6 @@ export const Table = <TData extends RowData>({
316
316
  const tableRows = tanstackTable.getRowModel().rows;
317
317
  const emptyTable = tableRows.length === 0 && Boolean(emptyTableCopy);
318
318
 
319
- const memoizedGetColumnWidths = React.useCallback(() => {
320
- return tanstackTable.getVisibleLeafColumns().map((column) => column.getSize() || "100%");
321
- }, [tanstackTable]);
322
-
323
319
  // Extract header groups to avoid complex expression in dependency array
324
320
  const headerGroups = tanstackTable.getHeaderGroups();
325
321
 
@@ -379,6 +375,13 @@ export const Table = <TData extends RowData>({
379
375
  sortingAriaLabels,
380
376
  columnDragAriaLabelsCopy,
381
377
  tanstackTable,
378
+ emptyTable,
379
+ stickyFirstColumn,
380
+ stickyHeaders,
381
+ isScrolled,
382
+ getStickyColumn,
383
+ showBorder,
384
+ activeId,
382
385
  ]
383
386
  );
384
387
 
@@ -399,7 +402,9 @@ export const Table = <TData extends RowData>({
399
402
  showBorder={showBorder}
400
403
  enableColumnDrag={enableColumnDrag}
401
404
  activeId={activeId}
402
- getColumnWidths={memoizedGetColumnWidths}
405
+ getColumnWidths={() =>
406
+ tanstackTable.getVisibleLeafColumns().map((column) => column.getSize() || "100%")
407
+ }
403
408
  variant={variant}
404
409
  emptyTableHeadingTag={emptyTableHeadingTag}
405
410
  emptyTableCopy={emptyTableCopy}
@@ -1,4 +1,4 @@
1
- import React, { useState } from "react";
1
+ import React from "react";
2
2
  import { IconDragHorizontal } from "@purpurds/icon/drag-horizontal";
3
3
  import c from "classnames/bind";
4
4
 
@@ -7,52 +7,33 @@ import styles from "./table.module.scss";
7
7
  const cx = c.bind(styles);
8
8
  const rootClassName = "purpur-table-column-header-cell";
9
9
 
10
- export function useDragHandle() {
11
- const [mouseDownActive, setMouseDownActive] = useState(false);
12
-
13
- const handleMouseDown = () => {
14
- setMouseDownActive(true);
15
- window.addEventListener("mouseup", handleMouseUp, { once: true });
16
- };
17
-
18
- const handleMouseUp = () => {
19
- setMouseDownActive(false);
20
- };
21
-
22
- return { mouseDownActive, handleMouseDown };
23
- }
24
-
25
10
  export type TableColumnDragHandleProps = {
26
- onMouseDown: () => void;
27
11
  overlayActive?: boolean;
28
12
  isFirstColumn: boolean;
29
13
  isLastColumn: boolean;
30
14
  columnDragAriaLabel: string;
15
+ // Add any additional props from listeners
16
+ [key: string]: unknown;
31
17
  };
32
18
 
33
19
  export function TableColumnDragHandle({
34
- onMouseDown,
35
20
  overlayActive,
36
21
  isFirstColumn,
37
22
  isLastColumn,
38
23
  columnDragAriaLabel,
24
+ ...dragListeners // Capture the listeners from useSortable
39
25
  }: TableColumnDragHandleProps) {
40
26
  return (
41
27
  <div
28
+ role="button"
29
+ tabIndex={0}
42
30
  className={cx(`${rootClassName}__drag-handle`, {
43
31
  [`${rootClassName}__border-radius-first-cell`]: isFirstColumn && !overlayActive,
44
32
  [`${rootClassName}__border-radius-last-cell`]: isLastColumn && !overlayActive,
45
33
  [`${rootClassName}__drag-handle--active`]: overlayActive,
46
34
  })}
47
- role="button"
48
- tabIndex={0}
49
35
  aria-label={columnDragAriaLabel}
50
- onMouseDown={onMouseDown}
51
- onKeyDown={(e) => {
52
- if (e.key === "Enter" || e.key === " ") {
53
- onMouseDown();
54
- }
55
- }}
36
+ {...dragListeners}
56
37
  >
57
38
  <IconDragHorizontal className={cx(`${rootClassName}__drag-handle-icon`)} size="sm" />
58
39
  </div>
@@ -1,102 +1,12 @@
1
1
  import React from "react";
2
- import { fireEvent, render, screen } from "@testing-library/react";
2
+ import { render, screen } from "@testing-library/react";
3
3
  import userEvent from "@testing-library/user-event";
4
4
  import { axe } from "vitest-axe";
5
5
 
6
- import { TableColumnDragHandle, useDragHandle } from "./use-drag-handle.hook";
7
-
8
- // Test component to test the hook
9
- function TestDragHandleComponent() {
10
- const { mouseDownActive, handleMouseDown } = useDragHandle();
11
-
12
- return (
13
- <div>
14
- <span data-testid="mouse-down-state">{mouseDownActive ? "active" : "inactive"}</span>
15
- <button onClick={handleMouseDown} data-testid="trigger-button">
16
- Trigger Mouse Down
17
- </button>
18
- </div>
19
- );
20
- }
21
-
22
- describe("useDragHandle Hook", () => {
23
- beforeEach(() => {
24
- // Clean up any event listeners
25
- vi.clearAllMocks();
26
- });
27
-
28
- afterEach(() => {
29
- // Clean up global event listeners
30
- const events = ["mouseup"];
31
- events.forEach((event) => {
32
- window.removeEventListener(event, () => {});
33
- });
34
- });
35
-
36
- it("should initialize with mouseDownActive as false", () => {
37
- render(<TestDragHandleComponent />);
38
-
39
- const stateElement = screen.getByTestId("mouse-down-state");
40
- expect(stateElement).toHaveTextContent("inactive");
41
- });
42
-
43
- it("should set mouseDownActive to true when handleMouseDown is called", async () => {
44
- const user = userEvent.setup();
45
- render(<TestDragHandleComponent />);
46
-
47
- const triggerButton = screen.getByTestId("trigger-button");
48
- const stateElement = screen.getByTestId("mouse-down-state");
49
-
50
- expect(stateElement).toHaveTextContent("inactive");
51
-
52
- await user.click(triggerButton);
53
-
54
- expect(stateElement).toHaveTextContent("active");
55
- });
56
-
57
- it("should reset mouseDownActive to false when mouse up event occurs", async () => {
58
- const user = userEvent.setup();
59
- render(<TestDragHandleComponent />);
60
-
61
- const triggerButton = screen.getByTestId("trigger-button");
62
- const stateElement = screen.getByTestId("mouse-down-state");
63
-
64
- // Trigger mouse down
65
- await user.click(triggerButton);
66
- expect(stateElement).toHaveTextContent("active");
67
-
68
- // Simulate mouse up on window
69
- fireEvent.mouseUp(window);
70
-
71
- expect(stateElement).toHaveTextContent("inactive");
72
- });
73
-
74
- it("should add and remove mouseup event listener correctly", async () => {
75
- const addEventListenerSpy = vi.spyOn(window, "addEventListener");
76
- const removeEventListenerSpy = vi.spyOn(window, "removeEventListener");
77
-
78
- const user = userEvent.setup();
79
- render(<TestDragHandleComponent />);
80
-
81
- const triggerButton = screen.getByTestId("trigger-button");
82
-
83
- await user.click(triggerButton);
84
-
85
- expect(addEventListenerSpy).toHaveBeenCalledWith("mouseup", expect.any(Function), {
86
- once: true,
87
- });
88
-
89
- // Trigger mouseup to remove listener
90
- fireEvent.mouseUp(window);
91
-
92
- addEventListenerSpy.mockRestore();
93
- removeEventListenerSpy.mockRestore();
94
- });
95
- });
6
+ import { TableColumnDragHandle } from "./use-drag-handle.hook";
96
7
 
97
8
  describe("TableColumnDragHandle Component", () => {
98
9
  const defaultProps = {
99
- onMouseDown: vi.fn(),
100
10
  overlayActive: false,
101
11
  isFirstColumn: false,
102
12
  isLastColumn: false,
@@ -197,81 +107,31 @@ describe("TableColumnDragHandle Component", () => {
197
107
  });
198
108
 
199
109
  describe("Event Handling", () => {
200
- it("should call onMouseDown when clicked", async () => {
201
- const user = userEvent.setup();
202
- const onMouseDownMock = vi.fn();
203
-
204
- render(<TableColumnDragHandle {...defaultProps} onMouseDown={onMouseDownMock} />);
205
-
206
- const dragHandle = screen.getByRole("button");
207
- await user.click(dragHandle);
208
-
209
- expect(onMouseDownMock).toHaveBeenCalledTimes(1);
210
- });
211
-
212
- it("should call onMouseDown when mouse down event is triggered", () => {
213
- const onMouseDownMock = vi.fn();
214
-
215
- render(<TableColumnDragHandle {...defaultProps} onMouseDown={onMouseDownMock} />);
216
-
217
- const dragHandle = screen.getByRole("button");
218
- fireEvent.mouseDown(dragHandle);
110
+ it("should pass through dragListeners props", () => {
111
+ const mockListener = vi.fn();
112
+ const dragListeners = {
113
+ onMouseDown: mockListener,
114
+ onTouchStart: mockListener,
115
+ };
219
116
 
220
- expect(onMouseDownMock).toHaveBeenCalledTimes(1);
221
- });
222
-
223
- it("should call onMouseDown when Enter key is pressed", async () => {
224
- const user = userEvent.setup();
225
- const onMouseDownMock = vi.fn();
226
-
227
- render(<TableColumnDragHandle {...defaultProps} onMouseDown={onMouseDownMock} />);
228
-
229
- const dragHandle = screen.getByRole("button");
230
- dragHandle.focus();
231
- await user.keyboard("{Enter}");
232
-
233
- expect(onMouseDownMock).toHaveBeenCalledTimes(1);
234
- });
235
-
236
- it("should call onMouseDown when Space key is pressed", async () => {
237
- const user = userEvent.setup();
238
- const onMouseDownMock = vi.fn();
239
-
240
- render(<TableColumnDragHandle {...defaultProps} onMouseDown={onMouseDownMock} />);
117
+ render(<TableColumnDragHandle {...defaultProps} {...dragListeners} />);
241
118
 
242
119
  const dragHandle = screen.getByRole("button");
243
- dragHandle.focus();
244
- await user.keyboard(" ");
245
-
246
- expect(onMouseDownMock).toHaveBeenCalledTimes(1);
247
- });
248
-
249
- it("should not call onMouseDown for other key presses", async () => {
250
- const user = userEvent.setup();
251
- const onMouseDownMock = vi.fn();
252
120
 
253
- render(<TableColumnDragHandle {...defaultProps} onMouseDown={onMouseDownMock} />);
254
-
255
- const dragHandle = screen.getByRole("button");
256
- dragHandle.focus();
257
- await user.keyboard("{Escape}");
258
-
259
- expect(onMouseDownMock).not.toHaveBeenCalled();
121
+ // Verify the listeners are attached
122
+ expect(dragHandle).toHaveAttribute("role", "button");
260
123
  });
261
124
 
262
- it("should handle multiple rapid clicks", async () => {
263
- const user = userEvent.setup();
264
- const onMouseDownMock = vi.fn();
265
-
266
- render(<TableColumnDragHandle {...defaultProps} onMouseDown={onMouseDownMock} />);
267
-
268
- const dragHandle = screen.getByRole("button");
269
-
270
- await user.click(dragHandle);
271
- await user.click(dragHandle);
272
- await user.click(dragHandle);
273
-
274
- expect(onMouseDownMock).toHaveBeenCalledTimes(3);
125
+ it("should not throw when receiving additional props", () => {
126
+ expect(() => {
127
+ render(
128
+ <TableColumnDragHandle
129
+ {...defaultProps}
130
+ data-testid="custom-test-id"
131
+ customProp="value"
132
+ />
133
+ );
134
+ }).not.toThrow();
275
135
  });
276
136
  });
277
137
 
@@ -337,19 +197,6 @@ describe("TableColumnDragHandle Component", () => {
337
197
  });
338
198
 
339
199
  describe("Props Validation", () => {
340
- it("should handle undefined onMouseDown gracefully", () => {
341
- expect(() => {
342
- render(
343
- <TableColumnDragHandle
344
- {...defaultProps}
345
- onMouseDown={
346
- undefined as unknown as Parameters<typeof TableColumnDragHandle>[0]["onMouseDown"]
347
- }
348
- />
349
- );
350
- }).not.toThrow();
351
- });
352
-
353
200
  it("should handle empty aria label", () => {
354
201
  render(<TableColumnDragHandle {...defaultProps} columnDragAriaLabel="" />);
355
202
 
@@ -1,83 +1,44 @@
1
- import {
2
- closestCorners,
3
- type DroppableContainer,
4
- getFirstCollision,
5
- KeyboardCode,
6
- type KeyboardCoordinateGetter,
7
- } from "@dnd-kit/core";
1
+ import { KeyboardCode, type KeyboardCoordinateGetter } from "@dnd-kit/core";
8
2
 
9
3
  /**
10
- * Enhanced keyboard coordinate handler that better handles columns of different widths
11
- * by positioning the dragged column appropriately within target columns
4
+ * Simple keyboard coordinate handler that moves the drag overlay
5
+ * left or right incrementally and lets collision detection determine
6
+ * which column we're over.
12
7
  */
13
8
  export const enhancedColumnKeyboardCoordinates: KeyboardCoordinateGetter = (
14
9
  event,
15
- { context: { active, collisionRect, droppableRects, droppableContainers, over } }
10
+ { currentCoordinates, context: { active, droppableRects } }
16
11
  ) => {
17
- if (!active || !collisionRect) {
12
+ if (!active || !currentCoordinates) {
18
13
  return;
19
14
  }
20
15
 
21
- // Only handle left/right movements for column dragging
22
- if (event.code === KeyboardCode.Right || event.code === KeyboardCode.Left) {
23
- event.preventDefault();
24
-
25
- const filteredContainers: DroppableContainer[] = [];
26
-
27
- droppableContainers.getEnabled().forEach((container) => {
28
- if (container?.disabled) return;
29
-
30
- const rect = droppableRects.get(container.id);
31
- if (!rect) return;
32
-
33
- // Filter based on direction
34
- if (event.code === KeyboardCode.Right && collisionRect.left < rect.left) {
35
- filteredContainers.push(container);
36
- } else if (event.code === KeyboardCode.Left && collisionRect.left > rect.left) {
37
- filteredContainers.push(container);
38
- }
39
- });
40
-
41
- // Sort containers by distance (nearest first) for left movement
42
- if (event.code === KeyboardCode.Left && filteredContainers.length > 0) {
43
- filteredContainers.sort((a, b) => {
44
- const rectA = droppableRects.get(a.id);
45
- const rectB = droppableRects.get(b.id);
46
- if (!rectA || !rectB) return 0;
47
-
48
- // Sort by closest to furthest from the current position (for left movement)
49
- return rectB.left - rectA.left;
50
- });
51
- }
16
+ // Only handle left/right movements
17
+ if (event.code !== KeyboardCode.Right && event.code !== KeyboardCode.Left) {
18
+ return;
19
+ }
52
20
 
53
- // Find closest target
54
- const collisions = closestCorners({
55
- active,
56
- collisionRect,
57
- droppableRects,
58
- droppableContainers: filteredContainers,
59
- pointerCoordinates: null,
60
- });
21
+ event.preventDefault();
61
22
 
62
- let targetId = getFirstCollision(collisions, "id");
23
+ // Get the active column's width to determine appropriate step size
24
+ const activeRect = droppableRects.get(active.id);
25
+ if (!activeRect) {
26
+ return;
27
+ }
63
28
 
64
- // Get second collision if first is current "over" element
65
- if (targetId === over?.id && collisions.length > 1) {
66
- targetId = collisions[1].id;
67
- }
29
+ // Move by half the width of the active column or max 100px
30
+ const stepSize = Math.min(activeRect.width * 0.5, 100);
68
31
 
69
- if (targetId) {
70
- const targetRect = droppableRects.get(targetId);
32
+ let newX: number;
71
33
 
72
- if (targetRect) {
73
- return {
74
- x: targetRect.left + targetRect.width * 0.35,
75
- y: targetRect.top + targetRect.height / 2,
76
- };
77
- }
78
- }
34
+ if (event.code === KeyboardCode.Right) {
35
+ newX = currentCoordinates.x + stepSize;
36
+ } else {
37
+ newX = currentCoordinates.x - stepSize;
79
38
  }
80
39
 
81
- // For other keys, we don't handle them
82
- return;
40
+ return {
41
+ x: newX,
42
+ y: currentCoordinates.y,
43
+ };
83
44
  };