Skip to content

Commit 795cd18

Browse files
authored
feat: Pass item objects to useDragAndDrop getItems in addition to keys (#8711)
1 parent af9785c commit 795cd18

File tree

12 files changed

+42
-34
lines changed

12 files changed

+42
-34
lines changed

packages/@react-spectrum/dnd/src/useDragAndDrop.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ import {
3939
} from '@react-stately/dnd';
4040
import {JSX, useMemo} from 'react';
4141

42-
interface DraggableCollectionStateOpts extends Omit<DraggableCollectionStateOptions, 'getItems'> {}
42+
interface DraggableCollectionStateOpts<T> extends Omit<DraggableCollectionStateOptions<T>, 'getItems'> {}
4343

44-
interface DragHooks {
45-
useDraggableCollectionState?: (props: DraggableCollectionStateOpts) => DraggableCollectionState,
44+
interface DragHooks<T = object> {
45+
useDraggableCollectionState?: (props: DraggableCollectionStateOpts<T>) => DraggableCollectionState,
4646
useDraggableCollection?: (props: DraggableCollectionOptions, state: DraggableCollectionState, ref: RefObject<HTMLElement | null>) => void,
4747
useDraggableItem?: (props: DraggableItemProps, state: DraggableCollectionState) => DraggableItemResult,
4848
DragPreview?: typeof DragPreview
@@ -55,25 +55,25 @@ interface DropHooks {
5555
useDropIndicator?: (props: DropIndicatorProps, state: DroppableCollectionState, ref: RefObject<HTMLElement | null>) => DropIndicatorAria
5656
}
5757

58-
export interface DragAndDropHooks {
58+
export interface DragAndDropHooks<T = object> {
5959
/** Drag and drop hooks for the collection element. */
60-
dragAndDropHooks: DragHooks & DropHooks & {isVirtualDragging?: () => boolean, renderPreview?: (keys: Set<Key>, draggedKey: Key) => JSX.Element}
60+
dragAndDropHooks: DragHooks<T> & DropHooks & {isVirtualDragging?: () => boolean, renderPreview?: (keys: Set<Key>, draggedKey: Key) => JSX.Element}
6161
}
6262

63-
export interface DragAndDropOptions extends Omit<DraggableCollectionProps, 'preview' | 'getItems'>, Omit<DroppableCollectionProps, 'onMove'> {
63+
export interface DragAndDropOptions<T = object> extends Omit<DraggableCollectionProps, 'preview' | 'getItems'>, Omit<DroppableCollectionProps, 'onMove'> {
6464
/**
6565
* A function that returns the items being dragged. If not specified, we assume that the collection is not draggable.
6666
* @default () => []
6767
*/
68-
getItems?: (keys: Set<Key>) => DragItem[],
68+
getItems?: (keys: Set<Key>, items: T[]) => DragItem[],
6969
/** Provide a custom drag preview. `draggedKey` represents the key of the item the user actually dragged. */
7070
renderPreview?: (keys: Set<Key>, draggedKey: Key) => JSX.Element
7171
}
7272

7373
/**
7474
* Provides the hooks required to enable drag and drop behavior for a drag and drop compatible React Spectrum component.
7575
*/
76-
export function useDragAndDrop(options: DragAndDropOptions): DragAndDropHooks {
76+
export function useDragAndDrop<T = object>(options: DragAndDropOptions<T>): DragAndDropHooks {
7777
let dragAndDropHooks = useMemo(() => {
7878
let {
7979
onDrop,
@@ -90,7 +90,7 @@ export function useDragAndDrop(options: DragAndDropOptions): DragAndDropHooks {
9090

9191
let hooks = {} as DragHooks & DropHooks & {isVirtualDragging?: () => boolean, renderPreview?: (keys: Set<Key>, draggedKey: Key) => JSX.Element};
9292
if (isDraggable) {
93-
hooks.useDraggableCollectionState = function useDraggableCollectionStateOverride(props: DraggableCollectionStateOpts) {
93+
hooks.useDraggableCollectionState = function useDraggableCollectionStateOverride(props: DraggableCollectionStateOpts<T>) {
9494
return useDraggableCollectionState({...props, ...options, getItems: options.getItems!});
9595
};
9696
hooks.useDraggableCollection = useDraggableCollection;

packages/@react-spectrum/list/src/ListView.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ export interface SpectrumListViewProps<T> extends Omit<AriaGridListProps<T>, 'ke
5959
/**
6060
* The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the ListView.
6161
*/
62-
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks']
62+
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>['dragAndDropHooks']
6363
}
6464

6565
interface ListViewContextValue<T> {
6666
state: ListState<T>,
6767
dragState: DraggableCollectionState | null,
6868
dropState: DroppableCollectionState | null,
69-
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks'],
69+
dragAndDropHooks?: DragAndDropHooks<T>['dragAndDropHooks'],
7070
onAction?: (key: Key) => void,
7171
isListDraggable: boolean,
7272
isListDroppable: boolean,

packages/@react-spectrum/list/stories/ListViewDnDExamples.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,7 @@ import {useListData} from '@react-stately/data';
1616

1717
export function DragExample(props: {listViewProps: SpectrumListViewProps<any>, dragHookOptions: DragAndDropOptions, getAllowedDropOperationsAction?: () => void}): JSX.Element {
1818
let {listViewProps, dragHookOptions} = props;
19-
let getItems = (keys) => [...keys].map(key => {
20-
let item = items.find(item => item.key === key);
19+
let getItems = (keys, items) => items.map(item => {
2120
return {
2221
'text/plain': item.name
2322
};

packages/@react-spectrum/table/src/TableViewBase.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ export interface TableContextValue<T> {
110110
state: TableState<T> | TreeGridState<T>,
111111
dragState: DraggableCollectionState | null,
112112
dropState: DroppableCollectionState | null,
113-
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks'],
113+
dragAndDropHooks?: DragAndDropHooks<T>['dragAndDropHooks'],
114114
isTableDraggable: boolean,
115115
isTableDroppable: boolean,
116116
layout: TableViewLayout<T>,

packages/@react-spectrum/table/src/TableViewWrapper.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export interface SpectrumTableProps<T> extends TableProps<T>, SpectrumSelectionP
5959
* The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the TableView.
6060
* @version beta
6161
*/
62-
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks'],
62+
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>['dragAndDropHooks'],
6363
/**
6464
* Whether the TableView should support expandable rows. Requires the feature flag to be enabled first, see https://react-spectrum.adobe.com/react-spectrum/TableView.html#expandable-rows.
6565
* @version alpha

packages/@react-stately/dnd/src/useDraggableCollectionState.ts

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {Collection, DraggableCollectionEndEvent, DraggableCollectionProps, DragI
1414
import {MultipleSelectionManager} from '@react-stately/selection';
1515
import {useRef, useState} from 'react';
1616

17-
export interface DraggableCollectionStateOptions extends DraggableCollectionProps {
17+
export interface DraggableCollectionStateOptions<T = object> extends DraggableCollectionProps<T> {
1818
/** A collection of items. */
1919
collection: Collection<Node<unknown>>,
2020
/** An interface for reading and updating multiple selection state. */
@@ -55,7 +55,7 @@ export interface DraggableCollectionState {
5555
/**
5656
* Manages state for a draggable collection.
5757
*/
58-
export function useDraggableCollectionState(props: DraggableCollectionStateOptions): DraggableCollectionState {
58+
export function useDraggableCollectionState<T = object>(props: DraggableCollectionStateOptions<T>): DraggableCollectionState {
5959
let {
6060
getItems,
6161
isDisabled,
@@ -118,7 +118,16 @@ export function useDraggableCollectionState(props: DraggableCollectionStateOptio
118118
},
119119
getKeysForDrag: getKeys,
120120
getItems(key) {
121-
return getItems(getKeys(key));
121+
let keys = getKeys(key);
122+
let items: any[] = [];
123+
for (let key of keys) {
124+
let value = collection.getItem(key)?.value;
125+
if (value != null) {
126+
items.push(value);
127+
}
128+
}
129+
130+
return getItems(getKeys(key), items);
122131
},
123132
isDisabled,
124133
preview,

packages/@react-types/shared/src/dnd.d.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,15 +277,15 @@ export interface DraggableCollectionEndEvent extends DragEndEvent {
277277

278278
export type DragPreviewRenderer = (items: DragItem[], callback: (node: HTMLElement | null, x?: number, y?: number) => void) => void;
279279

280-
export interface DraggableCollectionProps {
280+
export interface DraggableCollectionProps<T = object> {
281281
/** Handler that is called when a drag operation is started. */
282282
onDragStart?: (e: DraggableCollectionStartEvent) => void,
283283
/** Handler that is called when the drag is moved. */
284284
onDragMove?: (e: DraggableCollectionMoveEvent) => void,
285285
/** Handler that is called when the drag operation is ended, either as a result of a drop or a cancellation. */
286286
onDragEnd?: (e: DraggableCollectionEndEvent) => void,
287287
/** A function that returns the items being dragged. */
288-
getItems: (keys: Set<Key>) => DragItem[],
288+
getItems: (keys: Set<Key>, items: T[]) => DragItem[],
289289
/** The ref of the element that will be rendered as the drag preview while dragging. */
290290
preview?: RefObject<DragPreviewRenderer | null>,
291291
/** Function that returns the drop operations that are allowed for the dragged items. If not provided, all drop operations are allowed. */

packages/react-aria-components/src/GridList.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export interface GridListProps<T> extends Omit<AriaGridListProps<T>, 'children'>
6868
*/
6969
selectionBehavior?: SelectionBehavior,
7070
/** The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the GridList. */
71-
dragAndDropHooks?: DragAndDropHooks,
71+
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>,
7272
/** Provides content to display when there are no items in the list. */
7373
renderEmptyState?: (props: GridListRenderProps) => ReactNode,
7474
/**

packages/react-aria-components/src/ListBox.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export interface ListBoxProps<T> extends Omit<AriaListBoxProps<T>, 'children' |
6464
*/
6565
selectionBehavior?: SelectionBehavior,
6666
/** The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the ListBox. */
67-
dragAndDropHooks?: DragAndDropHooks,
67+
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>,
6868
/** Provides content to display when there are no items in the list. */
6969
renderEmptyState?: (props: ListBoxRenderProps) => ReactNode,
7070
/**

packages/react-aria-components/src/Tree.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ export interface TreeProps<T> extends Omit<AriaTreeProps<T>, 'children'>, Multip
148148
*/
149149
disabledBehavior?: DisabledBehavior,
150150
/** The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the Tree. */
151-
dragAndDropHooks?: DragAndDropHooks
151+
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>
152152
}
153153

154154

0 commit comments

Comments
 (0)