Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 9 additions & 9 deletions packages/@react-spectrum/dnd/src/useDragAndDrop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,10 @@ import {
} from '@react-stately/dnd';
import {JSX, useMemo} from 'react';

interface DraggableCollectionStateOpts extends Omit<DraggableCollectionStateOptions, 'getItems'> {}
interface DraggableCollectionStateOpts<T> extends Omit<DraggableCollectionStateOptions<T>, 'getItems'> {}

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

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

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

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

let hooks = {} as DragHooks & DropHooks & {isVirtualDragging?: () => boolean, renderPreview?: (keys: Set<Key>, draggedKey: Key) => JSX.Element};
if (isDraggable) {
hooks.useDraggableCollectionState = function useDraggableCollectionStateOverride(props: DraggableCollectionStateOpts) {
hooks.useDraggableCollectionState = function useDraggableCollectionStateOverride(props: DraggableCollectionStateOpts<T>) {
return useDraggableCollectionState({...props, ...options, getItems: options.getItems!});
};
hooks.useDraggableCollection = useDraggableCollection;
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-spectrum/list/src/ListView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@ export interface SpectrumListViewProps<T> extends Omit<AriaGridListProps<T>, 'ke
/**
* The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the ListView.
*/
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks']
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>['dragAndDropHooks']
}

interface ListViewContextValue<T> {
state: ListState<T>,
dragState: DraggableCollectionState | null,
dropState: DroppableCollectionState | null,
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks'],
dragAndDropHooks?: DragAndDropHooks<T>['dragAndDropHooks'],
onAction?: (key: Key) => void,
isListDraggable: boolean,
isListDroppable: boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ import {useListData} from '@react-stately/data';

export function DragExample(props: {listViewProps: SpectrumListViewProps<any>, dragHookOptions: DragAndDropOptions, getAllowedDropOperationsAction?: () => void}): JSX.Element {
let {listViewProps, dragHookOptions} = props;
let getItems = (keys) => [...keys].map(key => {
let item = items.find(item => item.key === key);
let getItems = (keys, items) => items.map(item => {
return {
'text/plain': item.name
};
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-spectrum/table/src/TableViewBase.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export interface TableContextValue<T> {
state: TableState<T> | TreeGridState<T>,
dragState: DraggableCollectionState | null,
dropState: DroppableCollectionState | null,
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks'],
dragAndDropHooks?: DragAndDropHooks<T>['dragAndDropHooks'],
isTableDraggable: boolean,
isTableDroppable: boolean,
layout: TableViewLayout<T>,
Expand Down
2 changes: 1 addition & 1 deletion packages/@react-spectrum/table/src/TableViewWrapper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export interface SpectrumTableProps<T> extends TableProps<T>, SpectrumSelectionP
* The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the TableView.
* @version beta
*/
dragAndDropHooks?: DragAndDropHooks['dragAndDropHooks'],
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>['dragAndDropHooks'],
/**
* 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.
* @version alpha
Expand Down
15 changes: 12 additions & 3 deletions packages/@react-stately/dnd/src/useDraggableCollectionState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {Collection, DraggableCollectionEndEvent, DraggableCollectionProps, DragI
import {MultipleSelectionManager} from '@react-stately/selection';
import {useRef, useState} from 'react';

export interface DraggableCollectionStateOptions extends DraggableCollectionProps {
export interface DraggableCollectionStateOptions<T = object> extends DraggableCollectionProps<T> {
/** A collection of items. */
collection: Collection<Node<unknown>>,
/** An interface for reading and updating multiple selection state. */
Expand Down Expand Up @@ -55,7 +55,7 @@ export interface DraggableCollectionState {
/**
* Manages state for a draggable collection.
*/
export function useDraggableCollectionState(props: DraggableCollectionStateOptions): DraggableCollectionState {
export function useDraggableCollectionState<T = object>(props: DraggableCollectionStateOptions<T>): DraggableCollectionState {
let {
getItems,
isDisabled,
Expand Down Expand Up @@ -118,7 +118,16 @@ export function useDraggableCollectionState(props: DraggableCollectionStateOptio
},
getKeysForDrag: getKeys,
getItems(key) {
return getItems(getKeys(key));
let keys = getKeys(key);
let items: any[] = [];
for (let key of keys) {
let value = collection.getItem(key)?.value;
if (value != null) {
items.push(value);
}
}

return getItems(getKeys(key), items);
},
isDisabled,
preview,
Expand Down
4 changes: 2 additions & 2 deletions packages/@react-types/shared/src/dnd.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -277,15 +277,15 @@ export interface DraggableCollectionEndEvent extends DragEndEvent {

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

export interface DraggableCollectionProps {
export interface DraggableCollectionProps<T = object> {
/** Handler that is called when a drag operation is started. */
onDragStart?: (e: DraggableCollectionStartEvent) => void,
/** Handler that is called when the drag is moved. */
onDragMove?: (e: DraggableCollectionMoveEvent) => void,
/** Handler that is called when the drag operation is ended, either as a result of a drop or a cancellation. */
onDragEnd?: (e: DraggableCollectionEndEvent) => void,
/** A function that returns the items being dragged. */
getItems: (keys: Set<Key>) => DragItem[],
getItems: (keys: Set<Key>, items: T[]) => DragItem[],
/** The ref of the element that will be rendered as the drag preview while dragging. */
preview?: RefObject<DragPreviewRenderer | null>,
/** Function that returns the drop operations that are allowed for the dragged items. If not provided, all drop operations are allowed. */
Expand Down
2 changes: 1 addition & 1 deletion packages/react-aria-components/src/GridList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ export interface GridListProps<T> extends Omit<AriaGridListProps<T>, 'children'>
*/
selectionBehavior?: SelectionBehavior,
/** The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the GridList. */
dragAndDropHooks?: DragAndDropHooks,
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>,
/** Provides content to display when there are no items in the list. */
renderEmptyState?: (props: GridListRenderProps) => ReactNode,
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/react-aria-components/src/ListBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export interface ListBoxProps<T> extends Omit<AriaListBoxProps<T>, 'children' |
*/
selectionBehavior?: SelectionBehavior,
/** The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the ListBox. */
dragAndDropHooks?: DragAndDropHooks,
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>,
/** Provides content to display when there are no items in the list. */
renderEmptyState?: (props: ListBoxRenderProps) => ReactNode,
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/react-aria-components/src/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ export interface TreeProps<T> extends Omit<AriaTreeProps<T>, 'children'>, Multip
*/
disabledBehavior?: DisabledBehavior,
/** The drag and drop hooks returned by `useDragAndDrop` used to enable drag and drop behavior for the Tree. */
dragAndDropHooks?: DragAndDropHooks
dragAndDropHooks?: DragAndDropHooks<NoInfer<T>>
}


Expand Down
18 changes: 9 additions & 9 deletions packages/react-aria-components/src/useDragAndDrop.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ import {
import {isVirtualDragging} from '@react-aria/dnd';
import {JSX, useMemo} from 'react';

interface DraggableCollectionStateOpts extends Omit<DraggableCollectionStateOptions, 'getItems'> {}
interface DraggableCollectionStateOpts<T = object> extends Omit<DraggableCollectionStateOptions<T>, 'getItems'> {}

interface DragHooks {
useDraggableCollectionState?: (props: DraggableCollectionStateOpts) => DraggableCollectionState,
interface DragHooks<T = object> {
useDraggableCollectionState?: (props: DraggableCollectionStateOpts<T>) => DraggableCollectionState,
useDraggableCollection?: (props: DraggableCollectionOptions, state: DraggableCollectionState, ref: RefObject<HTMLElement | null>) => void,
useDraggableItem?: (props: DraggableItemProps, state: DraggableCollectionState) => DraggableItemResult,
DragPreview?: typeof DragPreview,
Expand All @@ -64,19 +64,19 @@ interface DropHooks {
ListDropTargetDelegate: typeof ListDropTargetDelegate
}

export type DragAndDropHooks = DragHooks & DropHooks
export type DragAndDropHooks<T = object> = DragHooks<T> & DropHooks

export interface DragAndDrop {
export interface DragAndDrop<T = object> {
/** Drag and drop hooks for the collection element. */
dragAndDropHooks: DragAndDropHooks
dragAndDropHooks: DragAndDropHooks<T>
}

export interface DragAndDropOptions extends Omit<DraggableCollectionProps, 'preview' | 'getItems'>, DroppableCollectionProps {
export interface DragAndDropOptions<T = object> extends Omit<DraggableCollectionProps, 'preview' | 'getItems'>, DroppableCollectionProps {
/**
* A function that returns the items being dragged. If not specified, we assume that the collection is not draggable.
* @default () => []
*/
getItems?: (keys: Set<Key>) => DragItem[],
getItems?: (keys: Set<Key>, items: T[]) => DragItem[],
/**
* A function that renders a drag preview, which is shown under the user's cursor while dragging.
* By default, a copy of the dragged element is rendered.
Expand All @@ -97,7 +97,7 @@ export interface DragAndDropOptions extends Omit<DraggableCollectionProps, 'prev
/**
* Provides the hooks required to enable drag and drop behavior for a drag and drop compatible collection component.
*/
export function useDragAndDrop(options: DragAndDropOptions): DragAndDrop {
export function useDragAndDrop<T = object>(options: DragAndDropOptions<T>): DragAndDrop<T> {
let dragAndDropHooks = useMemo(() => {
let {
onDrop,
Expand Down
4 changes: 2 additions & 2 deletions packages/react-aria-components/stories/ListBox.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,8 +148,8 @@ export const ListBoxDnd: AlbumListBoxStory = (props) => {
initialItems: albums
});

let {dragAndDropHooks} = useDragAndDrop({
getItems: (keys) => [...keys].map(key => ({'text/plain': list.getItem(key)?.title ?? ''})),
let {dragAndDropHooks} = useDragAndDrop<Album>({
getItems: (keys, items) => items.map(item => ({'text/plain': item.title ?? ''})),
onReorder(e) {
if (e.target.dropPosition === 'before') {
list.moveBefore(e.target.key, e.keys);
Expand Down