@react-aria/dnd 3.0.0-alpha.11 → 3.0.0-alpha.12

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
@@ -273,12 +273,15 @@ function $67560de7c78cb232$export$aef80212ac99c003(item) {
273
273
  $67560de7c78cb232$var$dropItems.delete(item.element);
274
274
  };
275
275
  }
276
- function $67560de7c78cb232$export$549dbcf8649bf3b2(target, stringFormatter) {
276
+ function $67560de7c78cb232$export$549dbcf8649bf3b2(target1, stringFormatter) {
277
277
  if ($67560de7c78cb232$var$dragSession) throw new Error('Cannot begin dragging while already dragging');
278
- $67560de7c78cb232$var$dragSession = new $67560de7c78cb232$var$DragSession(target, stringFormatter);
278
+ $67560de7c78cb232$var$dragSession = new $67560de7c78cb232$var$DragSession(target1, stringFormatter);
279
279
  requestAnimationFrame(()=>{
280
280
  $67560de7c78cb232$var$dragSession.setup();
281
- if ($7252cd45fc48c07c$export$1fb2158d224b542c() === 'keyboard' || $7252cd45fc48c07c$export$1fb2158d224b542c() === 'touch' && $fP8tg$getInteractionModality() === 'virtual') $67560de7c78cb232$var$dragSession.next();
281
+ if ($7252cd45fc48c07c$export$1fb2158d224b542c() === 'keyboard' || $7252cd45fc48c07c$export$1fb2158d224b542c() === 'touch' && $fP8tg$getInteractionModality() === 'virtual') {
282
+ let target = $67560de7c78cb232$var$dragSession.findNearestDropTarget();
283
+ $67560de7c78cb232$var$dragSession.setCurrentDropTarget(target);
284
+ }
282
285
  });
283
286
  for (let cb of $67560de7c78cb232$var$subscriptions)cb();
284
287
  }
@@ -504,6 +507,22 @@ class $67560de7c78cb232$var$DragSession {
504
507
  } else this.setCurrentDropTarget(this.validDropTargets[this.validDropTargets.length - 1]);
505
508
  } else this.setCurrentDropTarget(this.validDropTargets[index - 1]);
506
509
  }
510
+ findNearestDropTarget() {
511
+ let dragTargetRect = this.dragTarget.element.getBoundingClientRect();
512
+ let minDistance = Infinity;
513
+ let nearest = null;
514
+ for (let dropTarget of this.validDropTargets){
515
+ let rect = dropTarget.element.getBoundingClientRect();
516
+ let dx = rect.left - dragTargetRect.left;
517
+ let dy = rect.top - dragTargetRect.top;
518
+ let dist = dx * dx + dy * dy;
519
+ if (dist < minDistance) {
520
+ minDistance = dist;
521
+ nearest = dropTarget;
522
+ }
523
+ }
524
+ return nearest;
525
+ }
507
526
  setCurrentDropTarget(dropTarget, item) {
508
527
  if (dropTarget !== this.currentDropTarget) {
509
528
  if (this.currentDropTarget && typeof this.currentDropTarget.onDropExit === 'function') {
@@ -2090,28 +2109,66 @@ function $5c06e4929e123553$export$ccdee5eaf73cf661(options) {
2090
2109
  let state = $fP8tg$useRef({
2091
2110
  x: 0,
2092
2111
  y: 0,
2093
- dragEnterCount: 0,
2112
+ dragOverElements: new Set(),
2094
2113
  dropEffect: 'none',
2114
+ effectAllowed: 'none',
2095
2115
  dropActivateTimer: null
2096
2116
  }).current;
2117
+ let fireDropEnter = (e)=>{
2118
+ setDropTarget(true);
2119
+ if (typeof options.onDropEnter === 'function') {
2120
+ let rect = e.currentTarget.getBoundingClientRect();
2121
+ options.onDropEnter({
2122
+ type: 'dropenter',
2123
+ x: e.clientX - rect.x,
2124
+ y: e.clientY - rect.y
2125
+ });
2126
+ }
2127
+ };
2128
+ let fireDropExit = (e)=>{
2129
+ setDropTarget(false);
2130
+ if (typeof options.onDropExit === 'function') {
2131
+ let rect = e.currentTarget.getBoundingClientRect();
2132
+ options.onDropExit({
2133
+ type: 'dropexit',
2134
+ x: e.clientX - rect.x,
2135
+ y: e.clientY - rect.y
2136
+ });
2137
+ }
2138
+ };
2097
2139
  let onDragOver = (e)=>{
2098
2140
  e.preventDefault();
2099
2141
  e.stopPropagation();
2100
- if (e.clientX === state.x && e.clientY === state.y) {
2142
+ if (e.clientX === state.x && e.clientY === state.y && e.dataTransfer.effectAllowed === state.effectAllowed) {
2101
2143
  e.dataTransfer.dropEffect = state.dropEffect;
2102
2144
  return;
2103
2145
  }
2104
2146
  state.x = e.clientX;
2105
2147
  state.y = e.clientY;
2148
+ let prevDropEffect = state.dropEffect;
2149
+ // Update drop effect if allowed drop operations changed (e.g. user pressed modifier key).
2150
+ if (e.dataTransfer.effectAllowed !== state.effectAllowed) {
2151
+ let allowedOperations = $5c06e4929e123553$var$effectAllowedToOperations(e.dataTransfer.effectAllowed);
2152
+ let dropOperation = allowedOperations[0];
2153
+ if (typeof options.getDropOperation === 'function') {
2154
+ let types = new $7252cd45fc48c07c$export$7f04ce188c91447c(e.dataTransfer);
2155
+ dropOperation = $5c06e4929e123553$var$getDropOperation(e.dataTransfer.effectAllowed, options.getDropOperation(types, allowedOperations));
2156
+ }
2157
+ state.dropEffect = $103790afe9474d1c$export$5eacb0769d26d3b2[dropOperation] || 'none';
2158
+ }
2106
2159
  if (typeof options.getDropOperationForPoint === 'function') {
2107
2160
  let allowedOperations = $5c06e4929e123553$var$effectAllowedToOperations(e.dataTransfer.effectAllowed);
2108
2161
  let types = new $7252cd45fc48c07c$export$7f04ce188c91447c(e.dataTransfer);
2109
2162
  let rect = e.currentTarget.getBoundingClientRect();
2110
- let dropOperation = options.getDropOperationForPoint(types, allowedOperations, state.x - rect.x, state.y - rect.y);
2163
+ let dropOperation = $5c06e4929e123553$var$getDropOperation(e.dataTransfer.effectAllowed, options.getDropOperationForPoint(types, allowedOperations, state.x - rect.x, state.y - rect.y));
2111
2164
  state.dropEffect = $103790afe9474d1c$export$5eacb0769d26d3b2[dropOperation] || 'none';
2112
2165
  }
2166
+ state.effectAllowed = e.dataTransfer.effectAllowed;
2113
2167
  e.dataTransfer.dropEffect = state.dropEffect;
2114
- if (typeof options.onDropMove === 'function') {
2168
+ // If the drop operation changes, update state and fire events appropriately.
2169
+ if (state.dropEffect === 'none' && prevDropEffect !== 'none') fireDropExit(e);
2170
+ else if (state.dropEffect !== 'none' && prevDropEffect === 'none') fireDropEnter(e);
2171
+ if (typeof options.onDropMove === 'function' && state.dropEffect !== 'none') {
2115
2172
  let rect = e.currentTarget.getBoundingClientRect();
2116
2173
  options.onDropMove({
2117
2174
  type: 'dropmove',
@@ -2133,46 +2190,39 @@ function $5c06e4929e123553$export$ccdee5eaf73cf661(options) {
2133
2190
  };
2134
2191
  let onDragEnter = (e)=>{
2135
2192
  e.stopPropagation();
2136
- state.dragEnterCount++;
2137
- if (state.dragEnterCount > 1) return;
2193
+ state.dragOverElements.add(e.target);
2194
+ if (state.dragOverElements.size > 1) return;
2138
2195
  let allowedOperations = $5c06e4929e123553$var$effectAllowedToOperations(e.dataTransfer.effectAllowed);
2139
2196
  let dropOperation = allowedOperations[0];
2140
2197
  if (typeof options.getDropOperation === 'function') {
2141
2198
  let types = new $7252cd45fc48c07c$export$7f04ce188c91447c(e.dataTransfer);
2142
- dropOperation = options.getDropOperation(types, allowedOperations);
2199
+ dropOperation = $5c06e4929e123553$var$getDropOperation(e.dataTransfer.effectAllowed, options.getDropOperation(types, allowedOperations));
2143
2200
  }
2144
- if (dropOperation !== 'cancel') setDropTarget(true);
2145
2201
  if (typeof options.getDropOperationForPoint === 'function') {
2146
2202
  let types = new $7252cd45fc48c07c$export$7f04ce188c91447c(e.dataTransfer);
2147
2203
  let rect = e.currentTarget.getBoundingClientRect();
2148
- dropOperation = options.getDropOperationForPoint(types, allowedOperations, e.clientX - rect.x, e.clientY - rect.y);
2149
- }
2150
- state.dropEffect = $103790afe9474d1c$export$5eacb0769d26d3b2[dropOperation] || 'none';
2151
- e.dataTransfer.dropEffect = state.dropEffect;
2152
- if (typeof options.onDropEnter === 'function' && dropOperation !== 'cancel') {
2153
- let rect = e.currentTarget.getBoundingClientRect();
2154
- options.onDropEnter({
2155
- type: 'dropenter',
2156
- x: e.clientX - rect.x,
2157
- y: e.clientY - rect.y
2158
- });
2204
+ dropOperation = $5c06e4929e123553$var$getDropOperation(e.dataTransfer.effectAllowed, options.getDropOperationForPoint(types, allowedOperations, e.clientX - rect.x, e.clientY - rect.y));
2159
2205
  }
2160
2206
  state.x = e.clientX;
2161
2207
  state.y = e.clientY;
2208
+ state.effectAllowed = e.dataTransfer.effectAllowed;
2209
+ state.dropEffect = $103790afe9474d1c$export$5eacb0769d26d3b2[dropOperation] || 'none';
2210
+ e.dataTransfer.dropEffect = state.dropEffect;
2211
+ if (dropOperation !== 'cancel') fireDropEnter(e);
2162
2212
  };
2163
2213
  let onDragLeave = (e)=>{
2164
2214
  e.stopPropagation();
2165
- state.dragEnterCount--;
2166
- if (state.dragEnterCount > 0) return;
2167
- if (typeof options.onDropExit === 'function' && state.dropEffect !== 'none') {
2168
- let rect = e.currentTarget.getBoundingClientRect();
2169
- options.onDropExit({
2170
- type: 'dropexit',
2171
- x: e.clientX - rect.x,
2172
- y: e.clientY - rect.y
2173
- });
2174
- }
2175
- setDropTarget(false);
2215
+ // We would use e.relatedTarget to detect if the drag is still inside the drop target,
2216
+ // but it is always null in WebKit. https://bugs.webkit.org/show_bug.cgi?id=66547
2217
+ // Instead, we track all of the targets of dragenter events in a set, and remove them
2218
+ // in dragleave. When the set becomes empty, we've left the drop target completely.
2219
+ // We must also remove any elements that are no longer in the DOM, because dragleave
2220
+ // events will never be fired for these. This can happen, for example, with drop
2221
+ // indicators between items, which disappear when the drop target changes.
2222
+ state.dragOverElements.delete(e.target);
2223
+ for (let element of state.dragOverElements)if (!e.currentTarget.contains(element)) state.dragOverElements.delete(element);
2224
+ if (state.dragOverElements.size > 0) return;
2225
+ if (state.dropEffect !== 'none') fireDropExit(e);
2176
2226
  clearTimeout(state.dropActivateTimer);
2177
2227
  };
2178
2228
  let onDrop = (e)=>{
@@ -2197,16 +2247,8 @@ function $5c06e4929e123553$export$ccdee5eaf73cf661(options) {
2197
2247
  options.onDrop(event);
2198
2248
  }, 0);
2199
2249
  }
2200
- if (typeof options.onDropExit === 'function') {
2201
- let rect = e.currentTarget.getBoundingClientRect();
2202
- options.onDropExit({
2203
- type: 'dropexit',
2204
- x: e.clientX - rect.x,
2205
- y: e.clientY - rect.y
2206
- });
2207
- }
2208
- state.dragEnterCount = 0;
2209
- setDropTarget(false);
2250
+ state.dragOverElements.clear();
2251
+ fireDropExit(e);
2210
2252
  clearTimeout(state.dropActivateTimer);
2211
2253
  };
2212
2254
  let optionsRef = $fP8tg$useRef(options);
@@ -2252,6 +2294,11 @@ function $5c06e4929e123553$var$effectAllowedToOperations(effectAllowed) {
2252
2294
  if (allowedOperationsBits & $103790afe9474d1c$export$60b7b4bcf3903d8e.link) allowedOperations.push('link');
2253
2295
  return allowedOperations;
2254
2296
  }
2297
+ function $5c06e4929e123553$var$getDropOperation(effectAllowed, operation) {
2298
+ let allowedOperationsBits = $103790afe9474d1c$export$9bbdfc78cf083e16[effectAllowed];
2299
+ let op = $103790afe9474d1c$export$60b7b4bcf3903d8e[operation];
2300
+ return allowedOperationsBits & op ? operation : 'cancel';
2301
+ }
2255
2302
 
2256
2303
 
2257
2304
 
@@ -2329,22 +2376,23 @@ function $4b52e4eff84e5217$export$f4e2f423c21f7b04(props, state1, ref2) {
2329
2376
  let autoScroll = $80d9daea3067eff3$export$6323452ca4533ed8(ref2);
2330
2377
  let { dropProps: dropProps } = $5c06e4929e123553$export$ccdee5eaf73cf661({
2331
2378
  ref: ref2,
2332
- onDropEnter (e) {
2333
- let target = props.getDropTargetFromPoint(e.x, e.y);
2334
- state1.setTarget(target);
2379
+ onDropEnter () {
2380
+ state1.setTarget(localState.nextTarget);
2335
2381
  },
2336
2382
  onDropMove (e) {
2337
2383
  state1.setTarget(localState.nextTarget);
2338
2384
  autoScroll.move(e.x, e.y);
2339
2385
  },
2340
2386
  getDropOperationForPoint (types, allowedOperations, x, y) {
2341
- let target = props.getDropTargetFromPoint(x, y);
2342
- if (!target) {
2387
+ let isValidDropTarget = (target)=>state1.getDropOperation(target, types, allowedOperations) !== 'cancel'
2388
+ ;
2389
+ let target1 = props.dropTargetDelegate.getDropTargetFromPoint(x, y, isValidDropTarget);
2390
+ if (!target1) {
2343
2391
  localState.dropOperation = 'cancel';
2344
2392
  localState.nextTarget = null;
2345
2393
  return 'cancel';
2346
2394
  }
2347
- localState.dropOperation = state1.getDropOperation(target, types, allowedOperations);
2395
+ localState.dropOperation = state1.getDropOperation(target1, types, allowedOperations);
2348
2396
  // If the target doesn't accept the drop, see if the root accepts it instead.
2349
2397
  if (localState.dropOperation === 'cancel') {
2350
2398
  let rootTarget = {
@@ -2352,11 +2400,11 @@ function $4b52e4eff84e5217$export$f4e2f423c21f7b04(props, state1, ref2) {
2352
2400
  };
2353
2401
  let dropOperation = state1.getDropOperation(rootTarget, types, allowedOperations);
2354
2402
  if (dropOperation !== 'cancel') {
2355
- target = rootTarget;
2403
+ target1 = rootTarget;
2356
2404
  localState.dropOperation = dropOperation;
2357
2405
  }
2358
2406
  }
2359
- localState.nextTarget = localState.dropOperation === 'cancel' ? null : target;
2407
+ localState.nextTarget = localState.dropOperation === 'cancel' ? null : target1;
2360
2408
  return localState.dropOperation;
2361
2409
  },
2362
2410
  onDropExit () {
@@ -2717,7 +2765,8 @@ function $bfaab576ce1c580e$export$f7b0c5d28b66b6a5(options, state, ref) {
2717
2765
  dropProps: {
2718
2766
  ...dropProps,
2719
2767
  'aria-hidden': !dragSession || isValidDropTarget ? undefined : 'true'
2720
- }
2768
+ },
2769
+ isDropTarget: isDropTarget
2721
2770
  };
2722
2771
  }
2723
2772
 
@@ -2761,6 +2810,8 @@ function $ddf25448c71fc93a$export$8d0e41d2815afac5(props, state, ref1) {
2761
2810
  itemText: getText(after)
2762
2811
  });
2763
2812
  }
2813
+ let isDropTarget = state.isDropTarget(target);
2814
+ let ariaHidden = !dragSession ? 'true' : dropProps['aria-hidden'];
2764
2815
  return {
2765
2816
  dropIndicatorProps: {
2766
2817
  ...dropProps,
@@ -2768,9 +2819,14 @@ function $ddf25448c71fc93a$export$8d0e41d2815afac5(props, state, ref1) {
2768
2819
  'aria-roledescription': stringFormatter.format('dropIndicator'),
2769
2820
  'aria-label': label,
2770
2821
  'aria-labelledby': labelledBy,
2771
- 'aria-hidden': !dragSession ? 'true' : dropProps['aria-hidden'],
2822
+ 'aria-hidden': ariaHidden,
2772
2823
  tabIndex: -1
2773
- }
2824
+ },
2825
+ isDropTarget: isDropTarget,
2826
+ // If aria-hidden, we are either not in a drag session or the drop target is invalid.
2827
+ // In that case, there's no need to render anything at all unless we need to show the indicator visually.
2828
+ // This can happen when dragging using the native DnD API as opposed to keyboard dragging.
2829
+ isHidden: !isDropTarget && !!ariaHidden
2774
2830
  };
2775
2831
  }
2776
2832
 
@@ -2785,6 +2841,7 @@ function $fd98cf7cbf233429$export$b35afafff42da2d9(props, state) {
2785
2841
  return state.getItems(props.key);
2786
2842
  },
2787
2843
  preview: state.preview,
2844
+ getAllowedDropOperations: state.getAllowedDropOperations,
2788
2845
  onDragStart (e) {
2789
2846
  state.startDrag(props.key, e);
2790
2847
  },
@@ -2935,7 +2992,81 @@ function $ad0e3f3d9c50e4ba$var$DragPreview(props, ref) {
2935
2992
  let $ad0e3f3d9c50e4ba$export$905ab40ac2179daa = /*#__PURE__*/ $fP8tg$react.forwardRef($ad0e3f3d9c50e4ba$var$DragPreview);
2936
2993
 
2937
2994
 
2995
+ class $3ca85212bf8898e4$export$fbd65d14c79e28cc {
2996
+ getDropTargetFromPoint(x, y, isValidDropTarget) {
2997
+ if (this.collection.size === 0) return;
2998
+ let rect = this.ref.current.getBoundingClientRect();
2999
+ x += rect.x;
3000
+ y += rect.y;
3001
+ let elements = this.ref.current.querySelectorAll('[data-key]');
3002
+ let elementMap = new Map();
3003
+ for (let item of elements)if (item instanceof HTMLElement) elementMap.set(item.dataset.key, item);
3004
+ let items = [
3005
+ ...this.collection
3006
+ ];
3007
+ let low = 0;
3008
+ let high = items.length;
3009
+ while(low < high){
3010
+ let mid = Math.floor((low + high) / 2);
3011
+ let item = items[mid];
3012
+ let element = elementMap.get(String(item.key));
3013
+ let rect = element.getBoundingClientRect();
3014
+ if (y < rect.top) high = mid;
3015
+ else if (y > rect.bottom) low = mid + 1;
3016
+ else {
3017
+ let target = {
3018
+ type: 'item',
3019
+ key: item.key,
3020
+ dropPosition: 'on'
3021
+ };
3022
+ if (isValidDropTarget(target)) {
3023
+ // Otherwise, if dropping on the item is accepted, try the before/after positions if within 5px
3024
+ // of the top or bottom of the item.
3025
+ if (y <= rect.top + 5 && isValidDropTarget({
3026
+ ...target,
3027
+ dropPosition: 'before'
3028
+ })) target.dropPosition = 'before';
3029
+ else if (y >= rect.bottom - 5 && isValidDropTarget({
3030
+ ...target,
3031
+ dropPosition: 'after'
3032
+ })) target.dropPosition = 'after';
3033
+ } else {
3034
+ // If dropping on the item isn't accepted, try the target before or after depending on the y position.
3035
+ let midY = rect.top + rect.height / 2;
3036
+ if (y <= midY && isValidDropTarget({
3037
+ ...target,
3038
+ dropPosition: 'before'
3039
+ })) target.dropPosition = 'before';
3040
+ else if (y >= midY && isValidDropTarget({
3041
+ ...target,
3042
+ dropPosition: 'after'
3043
+ })) target.dropPosition = 'after';
3044
+ }
3045
+ return target;
3046
+ }
3047
+ }
3048
+ let item1 = items[Math.min(low, items.length - 1)];
3049
+ let element = elementMap.get(String(item1.key));
3050
+ rect = element.getBoundingClientRect();
3051
+ if (Math.abs(y - rect.top) < Math.abs(y - rect.bottom)) return {
3052
+ type: 'item',
3053
+ key: item1.key,
3054
+ dropPosition: 'before'
3055
+ };
3056
+ return {
3057
+ type: 'item',
3058
+ key: item1.key,
3059
+ dropPosition: 'after'
3060
+ };
3061
+ }
3062
+ constructor(collection, ref){
3063
+ this.collection = collection;
3064
+ this.ref = ref;
3065
+ }
3066
+ }
3067
+
3068
+
2938
3069
 
2939
3070
 
2940
- 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, $ad0e3f3d9c50e4ba$export$905ab40ac2179daa as DragPreview};
3071
+ 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, $ad0e3f3d9c50e4ba$export$905ab40ac2179daa as DragPreview, $3ca85212bf8898e4$export$fbd65d14c79e28cc as ListDropTargetDelegate};
2941
3072
  //# sourceMappingURL=module.js.map