@react-aria/dnd 3.0.0-alpha.6 → 3.0.0-alpha.9

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.
package/dist/module.js CHANGED
@@ -1,10 +1,10 @@
1
- import {useRef as $fP8tg$useRef, useState as $fP8tg$useState, useEffect as $fP8tg$useEffect, useCallback as $fP8tg$useCallback} from "react";
2
- import $fP8tg$reactdom from "react-dom";
1
+ import $fP8tg$react, {useRef as $fP8tg$useRef, useState as $fP8tg$useState, useEffect as $fP8tg$useEffect, useCallback as $fP8tg$useCallback, useImperativeHandle as $fP8tg$useImperativeHandle} from "react";
3
2
  import {useGlobalListeners as $fP8tg$useGlobalListeners, useDescription as $fP8tg$useDescription, useId as $fP8tg$useId, useLayoutEffect as $fP8tg$useLayoutEffect, mergeProps as $fP8tg$mergeProps, getScrollParent as $fP8tg$getScrollParent, isWebKit as $fP8tg$isWebKit, isIOS as $fP8tg$isIOS, chain as $fP8tg$chain} from "@react-aria/utils";
4
3
  import {useMessageFormatter as $fP8tg$useMessageFormatter} from "@react-aria/i18n";
5
4
  import {announce as $fP8tg$announce} from "@react-aria/live-announcer";
6
5
  import {ariaHideOutside as $fP8tg$ariaHideOutside} from "@react-aria/overlays";
7
6
  import {useInteractionModality as $fP8tg$useInteractionModality, getInteractionModality as $fP8tg$getInteractionModality, setInteractionModality as $fP8tg$setInteractionModality, useFocus as $fP8tg$useFocus} from "@react-aria/interactions";
7
+ import {flushSync as $fP8tg$flushSync} from "react-dom";
8
8
 
9
9
  function $parcel$interopDefault(a) {
10
10
  return a && a.__esModule ? a.default : a;
@@ -347,6 +347,7 @@ class $67560de7c78cb232$var$DragSession {
347
347
  window.addEventListener('focus', this.onFocus, true);
348
348
  window.addEventListener('blur', this.onBlur, true);
349
349
  document.addEventListener('click', this.onClick, true);
350
+ document.addEventListener('pointerdown', this.onPointerDown, true);
350
351
  for (let event of $67560de7c78cb232$var$CANCELED_EVENTS)document.addEventListener(event, this.cancelEvent, true);
351
352
  this.mutationObserver = new MutationObserver(()=>this.updateValidDropTargets()
352
353
  );
@@ -358,6 +359,7 @@ class $67560de7c78cb232$var$DragSession {
358
359
  window.removeEventListener('focus', this.onFocus, true);
359
360
  window.removeEventListener('blur', this.onBlur, true);
360
361
  document.removeEventListener('click', this.onClick, true);
362
+ document.removeEventListener('pointerdown', this.onPointerDown, true);
361
363
  for (let event of $67560de7c78cb232$var$CANCELED_EVENTS)document.removeEventListener(event, this.cancelEvent, true);
362
364
  this.mutationObserver.disconnect();
363
365
  this.restoreAriaHidden();
@@ -407,19 +409,26 @@ class $67560de7c78cb232$var$DragSession {
407
409
  }
408
410
  onClick(e) {
409
411
  this.cancelEvent(e);
410
- if (e.detail !== 0) return;
411
- if (e.target === this.dragTarget.element) {
412
- this.cancel();
413
- return;
414
- }
415
- let dropTarget = this.validDropTargets.find((target)=>target.element.contains(e.target)
416
- );
417
- if (dropTarget) {
418
- let item = $67560de7c78cb232$var$dropItems.get(e.target);
419
- this.setCurrentDropTarget(dropTarget, item);
420
- this.drop(item);
412
+ if (e.detail === 0 || this.isVirtualClick) {
413
+ if (e.target === this.dragTarget.element) {
414
+ this.cancel();
415
+ return;
416
+ }
417
+ let dropTarget = this.validDropTargets.find((target)=>target.element.contains(e.target)
418
+ );
419
+ if (dropTarget) {
420
+ let item = $67560de7c78cb232$var$dropItems.get(e.target);
421
+ this.setCurrentDropTarget(dropTarget, item);
422
+ this.drop(item);
423
+ }
421
424
  }
422
425
  }
426
+ onPointerDown(e) {
427
+ // Android Talkback double tap has e.detail = 1 for onClick. Detect the virtual click in onPointerDown before onClick fires
428
+ // so we can properly perform cancel and drop operations.
429
+ this.cancelEvent(e);
430
+ this.isVirtualClick = $67560de7c78cb232$var$isVirtualPointerEvent(e);
431
+ }
423
432
  cancelEvent(e) {
424
433
  var ref;
425
434
  // Allow focusin and focusout on the drag target so focus ring works properly.
@@ -604,6 +613,7 @@ class $67560de7c78cb232$var$DragSession {
604
613
  this.onFocus = this.onFocus.bind(this);
605
614
  this.onBlur = this.onBlur.bind(this);
606
615
  this.onClick = this.onClick.bind(this);
616
+ this.onPointerDown = this.onPointerDown.bind(this);
607
617
  this.cancelEvent = this.cancelEvent.bind(this);
608
618
  }
609
619
  }
@@ -617,6 +627,14 @@ function $67560de7c78cb232$var$findValidDropTargets(options) {
617
627
  return true;
618
628
  });
619
629
  }
630
+ function $67560de7c78cb232$var$isVirtualPointerEvent(event) {
631
+ // If the pointer size is zero, then we assume it's from a screen reader.
632
+ // Android TalkBack double tap will sometimes return a event with width and height of 1
633
+ // and pointerType === 'mouse' so we need to check for a specific combination of event attributes.
634
+ // Cannot use "event.pressure === 0" as the sole check due to Safari pointer events always returning pressure === 0
635
+ // instead of .5, see https://bugs.webkit.org/show_bug.cgi?id=206216
636
+ return event.width === 0 && event.height === 0 || event.width === 1 && event.height === 1 && event.pressure === 0 && event.detail === 0;
637
+ }
620
638
 
621
639
 
622
640
 
@@ -799,7 +817,6 @@ $c530af5bd0e7e6c6$exports = {
799
817
 
800
818
 
801
819
 
802
-
803
820
  const $8253ed7ece74b463$var$MESSAGES = {
804
821
  keyboard: {
805
822
  start: 'dragDescriptionKeyboard',
@@ -825,6 +842,13 @@ function $8253ed7ece74b463$export$7941f8aafa4b6021(options) {
825
842
  let [isDragging, setDragging] = $fP8tg$useState(false);
826
843
  let { addGlobalListener: addGlobalListener , removeAllGlobalListeners: removeAllGlobalListeners } = $fP8tg$useGlobalListeners();
827
844
  let onDragStart = (e1)=>{
845
+ var ref;
846
+ if (e1.defaultPrevented) return;
847
+ if (typeof options.onDragStart === 'function') options.onDragStart({
848
+ type: 'dragstart',
849
+ x: e1.clientX,
850
+ y: e1.clientY
851
+ });
828
852
  let items = options.getItems();
829
853
  $7252cd45fc48c07c$export$f9c1490890ddd063(e1.dataTransfer, items);
830
854
  if (typeof options.getAllowedDropOperations === 'function') {
@@ -833,38 +857,25 @@ function $8253ed7ece74b463$export$7941f8aafa4b6021(options) {
833
857
  for (let operation of allowedOperations)allowed |= $103790afe9474d1c$export$60b7b4bcf3903d8e[operation] || $103790afe9474d1c$export$60b7b4bcf3903d8e.none;
834
858
  e1.dataTransfer.effectAllowed = $103790afe9474d1c$export$dd0165308d8bff45[allowed] || 'none';
835
859
  }
836
- // If there is a renderPreview function, use it to render a custom preview image that will
860
+ // If there is a preview option, use it to render a custom preview image that will
837
861
  // appear under the pointer while dragging. If not, the element itself is dragged by the browser.
838
- if (typeof options.renderPreview === 'function') {
839
- let preview = options.renderPreview(items);
840
- if (preview) {
841
- // Create an off-screen div to render the preview into.
842
- let node = document.createElement('div');
843
- node.style.zIndex = '-100';
844
- node.style.position = 'absolute';
845
- node.style.top = '0';
846
- node.style.left = '-100000px';
847
- document.body.appendChild(node);
848
- // Call renderPreview to get a JSX element, and render it into the div with React DOM.
849
- $fP8tg$reactdom.render(preview, node);
850
- // Compute the offset that the preview will appear under the mouse.
851
- // If possible, this is based on the point the user clicked on the target.
852
- // If the preview is much smaller, then just use the center point of the preview.
853
- let size = node.getBoundingClientRect();
854
- let rect = e1.currentTarget.getBoundingClientRect();
855
- let x = e1.clientX - rect.x;
856
- let y = e1.clientY - rect.y;
857
- if (x > size.width || y > size.height) {
858
- x = size.width / 2;
859
- y = size.height / 2;
860
- }
861
- e1.dataTransfer.setDragImage(node, x, y);
862
- // Remove the preview from the DOM after a frame so the browser has time to paint.
863
- requestAnimationFrame(()=>{
864
- document.body.removeChild(node);
865
- });
862
+ if (typeof ((ref = options.preview) === null || ref === void 0 ? void 0 : ref.current) === 'function') options.preview.current(items, (node)=>{
863
+ // Compute the offset that the preview will appear under the mouse.
864
+ // If possible, this is based on the point the user clicked on the target.
865
+ // If the preview is much smaller, then just use the center point of the preview.
866
+ let size = node.getBoundingClientRect();
867
+ let rect = e1.currentTarget.getBoundingClientRect();
868
+ let x = e1.clientX - rect.x;
869
+ let y = e1.clientY - rect.y;
870
+ if (x > size.width || y > size.height) {
871
+ x = size.width / 2;
872
+ y = size.height / 2;
866
873
  }
867
- }
874
+ // Rounding height to an even number prevents blurry preview seen on some screens
875
+ let height = 2 * Math.round(rect.height / 2);
876
+ node.style.height = `${height}px`;
877
+ e1.dataTransfer.setDragImage(node, x, y);
878
+ });
868
879
  // Enforce that drops are handled by useDrop.
869
880
  addGlobalListener(window, 'drop', (e)=>{
870
881
  if (!$67560de7c78cb232$export$7454aff2e161f241(e.target)) {
@@ -876,11 +887,6 @@ function $8253ed7ece74b463$export$7941f8aafa4b6021(options) {
876
887
  capture: true,
877
888
  once: true
878
889
  });
879
- if (typeof options.onDragStart === 'function') options.onDragStart({
880
- type: 'dragstart',
881
- x: e1.clientX,
882
- y: e1.clientY
883
- });
884
890
  state.x = e1.clientX;
885
891
  state.y = e1.clientY;
886
892
  // Wait a frame before we set dragging to true so that the browser has time to
@@ -1253,10 +1259,6 @@ function $4b52e4eff84e5217$export$f4e2f423c21f7b04(props, state1, ref2) {
1253
1259
  localState.nextTarget = null;
1254
1260
  return 'cancel';
1255
1261
  }
1256
- if (state1.isDropTarget(target)) {
1257
- localState.nextTarget = target;
1258
- return localState.dropOperation;
1259
- }
1260
1262
  localState.dropOperation = state1.getDropOperation(target, types, allowedOperations);
1261
1263
  // If the target doesn't accept the drop, see if the root accepts it instead.
1262
1264
  if (localState.dropOperation === 'cancel') {
@@ -1706,9 +1708,7 @@ function $fd98cf7cbf233429$export$b35afafff42da2d9(props, state) {
1706
1708
  getItems () {
1707
1709
  return state.getItems(props.key);
1708
1710
  },
1709
- renderPreview () {
1710
- return state.renderPreview(props.key);
1711
- },
1711
+ preview: state.preview,
1712
1712
  onDragStart (e) {
1713
1713
  state.startDrag(props.key, e);
1714
1714
  },
@@ -1720,12 +1720,12 @@ function $fd98cf7cbf233429$export$b35afafff42da2d9(props, state) {
1720
1720
  }
1721
1721
  });
1722
1722
  let item = state.collection.getItem(props.key);
1723
- let numSelectedKeys = state.selectionManager.selectedKeys.size;
1723
+ let numKeysForDrag = state.getKeysForDrag(props.key).size;
1724
1724
  let isSelected = state.selectionManager.isSelected(props.key);
1725
1725
  let message;
1726
1726
  var ref;
1727
- if (isSelected && numSelectedKeys > 1) message = formatMessage('dragSelectedItems', {
1728
- count: numSelectedKeys
1727
+ if (isSelected && numKeysForDrag > 1) message = formatMessage('dragSelectedItems', {
1728
+ count: numKeysForDrag
1729
1729
  });
1730
1730
  else message = formatMessage('dragItem', {
1731
1731
  itemText: (ref = item === null || item === void 0 ? void 0 : item.textValue) !== null && ref !== void 0 ? ref : ''
@@ -1828,5 +1828,41 @@ function $9fcc7f0d70d084ee$export$2314ca2a3e892862(options1) {
1828
1828
 
1829
1829
 
1830
1830
 
1831
- export {$8253ed7ece74b463$export$7941f8aafa4b6021 as useDrag, $5c06e4929e123553$export$ccdee5eaf73cf661 as useDrop, $4b52e4eff84e5217$export$f4e2f423c21f7b04 as useDroppableCollection, $bfaab576ce1c580e$export$f7b0c5d28b66b6a5 as useDroppableItem, $ddf25448c71fc93a$export$8d0e41d2815afac5 as useDropIndicator, $fd98cf7cbf233429$export$b35afafff42da2d9 as useDraggableItem, $9fcc7f0d70d084ee$export$2314ca2a3e892862 as useClipboard};
1831
+ function $ad0e3f3d9c50e4ba$var$DragPreview(props, ref) {
1832
+ let render = props.children;
1833
+ let [children, setChildren] = $fP8tg$useState(null);
1834
+ let domRef = $fP8tg$useRef(null);
1835
+ $fP8tg$useImperativeHandle(ref, ()=>(items, callback)=>{
1836
+ // This will be called during the onDragStart event by useDrag. We need to render the
1837
+ // preview synchronously before this event returns so we can call event.dataTransfer.setDragImage.
1838
+ $fP8tg$flushSync(()=>{
1839
+ setChildren(render(items));
1840
+ });
1841
+ // Yield back to useDrag to set the drag image.
1842
+ callback(domRef.current);
1843
+ // Remove the preview from the DOM after a frame so the browser has time to paint.
1844
+ requestAnimationFrame(()=>{
1845
+ setChildren(null);
1846
+ });
1847
+ }
1848
+ , [
1849
+ render
1850
+ ]);
1851
+ if (!children) return null;
1852
+ return(/*#__PURE__*/ $fP8tg$react.createElement("div", {
1853
+ style: {
1854
+ zIndex: -100,
1855
+ position: 'absolute',
1856
+ top: 0,
1857
+ left: -100000
1858
+ },
1859
+ ref: domRef
1860
+ }, children));
1861
+ }
1862
+ let $ad0e3f3d9c50e4ba$export$905ab40ac2179daa = /*#__PURE__*/ $fP8tg$react.forwardRef($ad0e3f3d9c50e4ba$var$DragPreview);
1863
+
1864
+
1865
+
1866
+
1867
+ export {$ad0e3f3d9c50e4ba$export$905ab40ac2179daa as DragPreview, $8253ed7ece74b463$export$7941f8aafa4b6021 as useDrag, $5c06e4929e123553$export$ccdee5eaf73cf661 as useDrop, $4b52e4eff84e5217$export$f4e2f423c21f7b04 as useDroppableCollection, $bfaab576ce1c580e$export$f7b0c5d28b66b6a5 as useDroppableItem, $ddf25448c71fc93a$export$8d0e41d2815afac5 as useDropIndicator, $fd98cf7cbf233429$export$b35afafff42da2d9 as useDraggableItem, $9fcc7f0d70d084ee$export$2314ca2a3e892862 as useClipboard};
1832
1868
  //# sourceMappingURL=module.js.map