diff --git a/packages/@react-aria/selection/src/useSelectableItem.ts b/packages/@react-aria/selection/src/useSelectableItem.ts index 2ff6b306a3a..8db879a6085 100644 --- a/packages/@react-aria/selection/src/useSelectableItem.ts +++ b/packages/@react-aria/selection/src/useSelectableItem.ts @@ -302,7 +302,7 @@ export function useSelectableItem(options: SelectableItemOptions): SelectableIte return { itemProps: mergeProps( itemProps, - allowsSelection || hasPrimaryAction ? pressProps : {}, + (allowsSelection || hasPrimaryAction || shouldSelectOnPressUp) && !isDisabled ? pressProps : {}, longPressEnabled ? longPressProps : {}, {onDoubleClick, onDragStartCapture} ), diff --git a/packages/@react-spectrum/list/test/ListViewDnd.test.js b/packages/@react-spectrum/list/test/ListViewDnd.test.js index a685893e689..618f01d409a 100644 --- a/packages/@react-spectrum/list/test/ListViewDnd.test.js +++ b/packages/@react-spectrum/list/test/ListViewDnd.test.js @@ -228,6 +228,74 @@ describe('ListView', function () { }); }); + it('should allow drag and drop of a single row, selectionMode="none"', async function () { + let {getAllByRole, getByText} = render( + + ); + + let droppable = getByText('Drop here'); + let row = getAllByRole('row')[0]; + expect(row).toHaveAttribute('draggable', 'true'); + let cell = within(row).getByRole('gridcell'); + expect(cell).toHaveTextContent('Adobe Photoshop'); + + let dataTransfer = new DataTransfer(); + fireEvent.pointerDown(cell, {pointerType: 'mouse', button: 0, pointerId: 1, clientX: 0, clientY: 0}); + fireEvent(cell, new DragEvent('dragstart', {dataTransfer, clientX: 0, clientY: 0})); + expect([...dataTransfer.items]).toEqual([new DataTransferItem('text/plain', 'Adobe Photoshop')]); + + act(() => jest.runAllTimers()); + + expect(onDragStart).toHaveBeenCalledTimes(1); + expect(onDragStart).toHaveBeenCalledWith({ + type: 'dragstart', + keys: new Set('a'), + x: 0, + y: 0 + }); + + fireEvent.pointerMove(cell, {pointerType: 'mouse', button: 0, pointerId: 1, clientX: 1, clientY: 1}); + fireEvent(cell, new DragEvent('drag', {dataTransfer, clientX: 1, clientY: 1})); + expect(onDragMove).toHaveBeenCalledTimes(1); + expect(onDragMove).toHaveBeenCalledWith({ + type: 'dragmove', + keys: new Set('a'), + x: 1, + y: 1 + }); + + fireEvent(droppable, new DragEvent('dragenter', {dataTransfer, clientX: 1, clientY: 1})); + fireEvent.pointerUp(cell, {pointerType: 'mouse', button: 0, pointerId: 1, clientX: 1, clientY: 1}); + fireEvent(droppable, new DragEvent('drop', {dataTransfer, clientX: 1, clientY: 1})); + fireEvent(cell, new DragEvent('dragend', {dataTransfer, clientX: 1, clientY: 1})); + act(() => jest.runAllTimers()); + expect(onDrop).toHaveBeenCalledTimes(1); + expect(onDrop).toHaveBeenCalledWith({ + type: 'drop', + x: 1, + y: 1, + dropOperation: 'move', + items: [ + { + kind: 'text', + types: new Set(['text/plain']), + getText: expect.any(Function) + } + ] + }); + + expect(await onDrop.mock.calls[0][0].items[0].getText('text/plain')).toBe('Adobe Photoshop'); + expect(onDragEnd).toHaveBeenCalledTimes(1); + expect(onDragEnd).toHaveBeenCalledWith({ + type: 'dragend', + keys: new Set('a'), + x: 1, + y: 1, + dropOperation: 'move', + isInternal: false + }); + }); + it('should allow drag and drop of multiple rows', async function () { let {getAllByRole, getByText} = render( @@ -1762,6 +1830,52 @@ describe('ListView', function () { }); }); + it('should allow drag and drop of a single row, selectionMode="none"', async function () { + let {getAllByRole, getByText} = render( + + ); + + let droppable = getByText('Drop here'); + let row = getAllByRole('row')[0]; + let cell = within(row).getByRole('gridcell'); + expect(cell).toHaveTextContent('Adobe Photoshop'); + expect(row).toHaveAttribute('draggable', 'true'); + + userEvent.tab(); + let draghandle = within(cell).getAllByRole('button')[0]; + expect(draghandle).toBeTruthy(); + expect(draghandle).toHaveAttribute('draggable', 'true'); + + fireEvent.keyDown(draghandle, {key: 'Enter'}); + fireEvent.keyUp(draghandle, {key: 'Enter'}); + + expect(onDragStart).toHaveBeenCalledTimes(1); + expect(onDragStart).toHaveBeenCalledWith({ + type: 'dragstart', + keys: new Set('a'), + x: 50, + y: 25 + }); + + act(() => jest.runAllTimers()); + expect(document.activeElement).toBe(droppable); + fireEvent.keyDown(droppable, {key: 'Enter'}); + fireEvent.keyUp(droppable, {key: 'Enter'}); + + expect(onDrop).toHaveBeenCalledTimes(1); + expect(await onDrop.mock.calls[0][0].items[0].getText('text/plain')).toBe('Adobe Photoshop'); + + expect(onDragEnd).toHaveBeenCalledTimes(1); + expect(onDragEnd).toHaveBeenCalledWith({ + type: 'dragend', + keys: new Set('a'), + x: 50, + y: 25, + dropOperation: 'move', + isInternal: false + }); + }); + it('should allow drag and drop of multiple rows', async function () { let {getAllByRole, getByText} = render(