react-spectrum icon indicating copy to clipboard operation
react-spectrum copied to clipboard

add previewOffset option to useDrag

Open hipstersmoothie opened this issue 2 years ago • 4 comments

Closes #5409

✅ Pull Request Checklist:

  • [x] Included link to corresponding React Spectrum GitHub Issue.
  • [x] Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • [x] Filled out test instructions.
  • [x] Updated documentation (if it already exists for this component).
  • [x] Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

Go to the story I added and drag.

https://github.com/adobe/react-spectrum/assets/1192452/ebe0358e-cc59-463b-9a92-9de5d495edb7

hipstersmoothie avatar Nov 11 '23 20:11 hipstersmoothie

GET_BUILD

snowystinger avatar Dec 07 '23 02:12 snowystinger

## API Changes

unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any', access: 'private' } unknown top level export { type: 'any', access: 'private' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'identifier', name: 'Column' } unknown top level export { type: 'identifier', name: 'Column' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown type { type: 'link' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' } unknown top level export { type: 'any' }

@react-aria/dnd

DragOptions

 DragOptions {
   getAllowedDropOperations?: () => Array<DropOperation>
   getItems: () => Array<DragItem>
   hasDragButton?: boolean
   onDragEnd?: (DragEndEvent) => void
   onDragMove?: (DragMoveEvent) => void
   onDragStart?: (DragStartEvent) => void
   preview?: RefObject<DragPreviewRenderer>
+  previewOffset?: {
+    x: number
+  y: number
+} | 'center' | (DOMRect) => {
+    x: number
+  y: number
 }
+}

it changed:

  • useDrag

rspbot avatar Dec 07 '23 02:12 rspbot

Hey, thank you for your patience! We finally got an API discussion on this. We'd like to change it so that the value can be changed if the drag preview changes. Such as if you have multiple Drag Previews for multiple data types.

We will need to update this in two places. https://github.com/adobe/react-spectrum/blob/main/packages/%40react-spectrum/dnd/src/useDragAndDrop.ts#L70 and https://github.com/adobe/react-spectrum/blob/d330a9dc13dd8376f5d2f8cdffcd7bce53a8fbf4/packages/%40react-aria/dnd/src/DragPreview.tsx#L18

The return type of both of these should be altered to be

JSX.Element | {element: JSX.Element, x:number, y:number}

Below is a rough sketch of the steps to implement it, there may be some holes.

Then in DragPreview we'd change the useImperativeHandler to something along these lines

useImperativeHandle(ref, () => (items: DragItem[], callback: (node: HTMLElement, x?: number, y?: number) => void) => {
    // This will be called during the onDragStart event by useDrag. We need to render the
    // preview synchronously before this event returns so we can call event.dataTransfer.setDragImage.
    let result = render(items);
    flushSync(() => {
      setChildren(result.element);
    });

    // Yield back to useDrag to set the drag image.
    callback(domRef.current, result.x, result.y);
    ...

And in https://github.com/adobe/react-spectrum/blob/d330a9dc13dd8376f5d2f8cdffcd7bce53a8fbf4/packages/%40react-aria/dnd/stories/dnd.stories.tsx#L449 we can use it roughly like so

          return {
            element: (
              <div className={classNames(dndStyles, 'draggable', 'is-drag-preview', {'is-dragging-multiple': selectedKeys.size > 1})}>
                ...
              </div>
            ),
            x: 50,
            y: 50
          }

And then in useDrag https://github.com/adobe/react-spectrum/blob/d330a9dc13dd8376f5d2f8cdffcd7bce53a8fbf4/packages/%40react-aria/dnd/src/useDrag.ts#L132

    if (typeof options.preview?.current === 'function') {
      // console.log('options', options.preview.current)
      options.preview.current(items, (node, xUser, yUser) => {

snowystinger avatar Jan 12 '24 04:01 snowystinger

Going to close this one for now. We can reopen if it's picked up again or someone else can make a new PR

snowystinger avatar Aug 09 '24 00:08 snowystinger