@bsol-oss/react-datatable5 7.6.2 → 7.7.0
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/index.js +2209 -14
- package/dist/index.mjs +2201 -6
- package/package.json +4 -5
package/dist/index.mjs
CHANGED
|
@@ -10,7 +10,11 @@ import { FaUpDown, FaGripLinesVertical } from 'react-icons/fa6';
|
|
|
10
10
|
import { BiDownArrow, BiUpArrow } from 'react-icons/bi';
|
|
11
11
|
import { CgClose } from 'react-icons/cg';
|
|
12
12
|
import { IoMdEye, IoMdCheckbox } from 'react-icons/io';
|
|
13
|
-
import
|
|
13
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
14
|
+
import { bind, bindAll } from 'bind-event-listener';
|
|
15
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
16
|
+
import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';
|
|
17
|
+
import rafSchd from 'raf-schd';
|
|
14
18
|
import invariant from 'tiny-invariant';
|
|
15
19
|
import { HiMiniEllipsisHorizontal, HiChevronLeft, HiChevronRight } from 'react-icons/hi2';
|
|
16
20
|
import { flexRender, makeStateUpdater, functionalUpdate, useReactTable, getCoreRowModel, getFilteredRowModel, getSortedRowModel, getPaginationRowModel, createColumnHelper } from '@tanstack/react-table';
|
|
@@ -24,9 +28,6 @@ import axios from 'axios';
|
|
|
24
28
|
import { useDebounce } from '@uidotdev/usehooks';
|
|
25
29
|
import { useFormContext, useForm, FormProvider } from 'react-hook-form';
|
|
26
30
|
import dayjs from 'dayjs';
|
|
27
|
-
import { dropTargetForExternal } from '@atlaskit/pragmatic-drag-and-drop/external/adapter';
|
|
28
|
-
import { getFiles } from '@atlaskit/pragmatic-drag-and-drop/external/file';
|
|
29
|
-
import { getText } from '@atlaskit/pragmatic-drag-and-drop/external/text';
|
|
30
31
|
|
|
31
32
|
const DataTableContext = createContext({
|
|
32
33
|
table: {},
|
|
@@ -438,6 +439,1896 @@ const EditSortingButton = ({ text, icon = jsx(MdOutlineSort, {}), title = "Edit
|
|
|
438
439
|
return (jsx(Fragment, { children: jsxs(DialogRoot, { size: ["full", "full", "md", "md"], children: [jsx(DialogBackdrop, {}), jsx(DialogTrigger, { children: jsxs(Button$1, { as: "div", variant: "ghost", onClick: sortingModal.onOpen, children: [icon, " ", text] }) }), jsxs(DialogContent, { children: [jsx(DialogCloseTrigger, {}), jsxs(DialogHeader, { children: [jsx(DialogTitle, {}), title] }), jsx(DialogBody, { children: jsxs(Flex, { flexFlow: "column", gap: "0.25rem", children: [jsx(TableSorter, {}), jsx(ResetSortingButton, {})] }) }), jsx(DialogFooter, {})] })] }) }));
|
|
439
440
|
};
|
|
440
441
|
|
|
442
|
+
// pulling this into a separate file so adapter(s) that don't
|
|
443
|
+
// need the honey pot can pay as little as possible for it.
|
|
444
|
+
var honeyPotDataAttribute = 'data-pdnd-honey-pot';
|
|
445
|
+
|
|
446
|
+
function isHoneyPotElement(target) {
|
|
447
|
+
return target instanceof Element && target.hasAttribute(honeyPotDataAttribute);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
function getElementFromPointWithoutHoneypot(client) {
|
|
451
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
452
|
+
var _document$elementsFro = document.elementsFromPoint(client.x, client.y),
|
|
453
|
+
_document$elementsFro2 = _slicedToArray(_document$elementsFro, 2),
|
|
454
|
+
top = _document$elementsFro2[0],
|
|
455
|
+
second = _document$elementsFro2[1];
|
|
456
|
+
if (!top) {
|
|
457
|
+
return null;
|
|
458
|
+
}
|
|
459
|
+
if (isHoneyPotElement(top)) {
|
|
460
|
+
return second !== null && second !== void 0 ? second : null;
|
|
461
|
+
}
|
|
462
|
+
return top;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Maximum possible z-index
|
|
466
|
+
// https://stackoverflow.com/questions/491052/minimum-and-maximum-value-of-z-index
|
|
467
|
+
var maxZIndex = 2147483647;
|
|
468
|
+
|
|
469
|
+
function ownKeys$2(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
470
|
+
function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$2(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$2(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
471
|
+
var honeyPotSize = 2;
|
|
472
|
+
var halfHoneyPotSize = honeyPotSize / 2;
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* `clientX` and `clientY` can be in sub pixels (eg `2.332`)
|
|
476
|
+
* However, browser hitbox testing is commonly do to the closest pixel.
|
|
477
|
+
*
|
|
478
|
+
* → https://issues.chromium.org/issues/40940531
|
|
479
|
+
*
|
|
480
|
+
* To be sure that the honey pot will be over the `client` position,
|
|
481
|
+
* we `.floor()` `clientX` and`clientY` and then make it `2px` in size.
|
|
482
|
+
**/
|
|
483
|
+
function floorToClosestPixel(point) {
|
|
484
|
+
return {
|
|
485
|
+
x: Math.floor(point.x),
|
|
486
|
+
y: Math.floor(point.y)
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* We want to make sure the honey pot sits around the users position.
|
|
492
|
+
* This seemed to be the most resilient while testing.
|
|
493
|
+
*/
|
|
494
|
+
function pullBackByHalfHoneyPotSize(point) {
|
|
495
|
+
return {
|
|
496
|
+
x: point.x - halfHoneyPotSize,
|
|
497
|
+
y: point.y - halfHoneyPotSize
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* Prevent the honey pot from changing the window size.
|
|
503
|
+
* This is super unlikely to occur, but just being safe.
|
|
504
|
+
*/
|
|
505
|
+
function preventGoingBackwardsOffScreen(point) {
|
|
506
|
+
return {
|
|
507
|
+
x: Math.max(point.x, 0),
|
|
508
|
+
y: Math.max(point.y, 0)
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Prevent the honey pot from changing the window size.
|
|
514
|
+
* This is super unlikely to occur, but just being safe.
|
|
515
|
+
*/
|
|
516
|
+
function preventGoingForwardsOffScreen(point) {
|
|
517
|
+
return {
|
|
518
|
+
x: Math.min(point.x, window.innerWidth - honeyPotSize),
|
|
519
|
+
y: Math.min(point.y, window.innerHeight - honeyPotSize)
|
|
520
|
+
};
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
/**
|
|
524
|
+
* Create a `2x2` `DOMRect` around the `client` position
|
|
525
|
+
*/
|
|
526
|
+
function getHoneyPotRectFor(_ref) {
|
|
527
|
+
var client = _ref.client;
|
|
528
|
+
var point = preventGoingForwardsOffScreen(preventGoingBackwardsOffScreen(pullBackByHalfHoneyPotSize(floorToClosestPixel(client))));
|
|
529
|
+
|
|
530
|
+
// When debugging, it is helpful to
|
|
531
|
+
// make this element a bit bigger
|
|
532
|
+
return DOMRect.fromRect({
|
|
533
|
+
x: point.x,
|
|
534
|
+
y: point.y,
|
|
535
|
+
width: honeyPotSize,
|
|
536
|
+
height: honeyPotSize
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
function getRectStyles(_ref2) {
|
|
540
|
+
var clientRect = _ref2.clientRect;
|
|
541
|
+
return {
|
|
542
|
+
left: "".concat(clientRect.left, "px"),
|
|
543
|
+
top: "".concat(clientRect.top, "px"),
|
|
544
|
+
width: "".concat(clientRect.width, "px"),
|
|
545
|
+
height: "".concat(clientRect.height, "px")
|
|
546
|
+
};
|
|
547
|
+
}
|
|
548
|
+
function isWithin(_ref3) {
|
|
549
|
+
var client = _ref3.client,
|
|
550
|
+
clientRect = _ref3.clientRect;
|
|
551
|
+
return (
|
|
552
|
+
// is within horizontal bounds
|
|
553
|
+
client.x >= clientRect.x && client.x <= clientRect.x + clientRect.width &&
|
|
554
|
+
// is within vertical bounds
|
|
555
|
+
client.y >= clientRect.y && client.y <= clientRect.y + clientRect.height
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
/**
|
|
559
|
+
* The honey pot fix is designed to get around a painful bug in all browsers.
|
|
560
|
+
*
|
|
561
|
+
* [Overview](https://www.youtube.com/watch?v=udE9qbFTeQg)
|
|
562
|
+
*
|
|
563
|
+
* **Background**
|
|
564
|
+
*
|
|
565
|
+
* When a drag starts, browsers incorrectly think that the users pointer is
|
|
566
|
+
* still depressed where the drag started. Any element that goes under this position
|
|
567
|
+
* will be entered into, causing `"mouseenter"` events and `":hover"` styles to be applied.
|
|
568
|
+
*
|
|
569
|
+
* _This is a violation of the spec_
|
|
570
|
+
*
|
|
571
|
+
* > "From the moment that the user agent is to initiate the drag-and-drop operation,
|
|
572
|
+
* > until the end of the drag-and-drop operation, device input events
|
|
573
|
+
* > (e.g. mouse and keyboard events) must be suppressed."
|
|
574
|
+
* >
|
|
575
|
+
* > - https://html.spec.whatwg.org/multipage/dnd.html#drag-and-drop-processing-model
|
|
576
|
+
*
|
|
577
|
+
* _Some impacts_
|
|
578
|
+
*
|
|
579
|
+
* - `":hover"` styles being applied where they shouldn't (looks messy)
|
|
580
|
+
* - components such as tooltips responding to `"mouseenter"` can show during a drag,
|
|
581
|
+
* and on an element the user isn't even over
|
|
582
|
+
*
|
|
583
|
+
* Bug: https://issues.chromium.org/issues/41129937
|
|
584
|
+
*
|
|
585
|
+
* **Honey pot fix**
|
|
586
|
+
*
|
|
587
|
+
* 1. Create an element where the browser thinks the depressed pointer is
|
|
588
|
+
* to absorb the incorrect pointer events
|
|
589
|
+
* 2. Remove that element when it is no longer needed
|
|
590
|
+
*/
|
|
591
|
+
function mountHoneyPot(_ref4) {
|
|
592
|
+
var initial = _ref4.initial;
|
|
593
|
+
var element = document.createElement('div');
|
|
594
|
+
element.setAttribute(honeyPotDataAttribute, 'true');
|
|
595
|
+
|
|
596
|
+
// can shift during the drag thanks to Firefox
|
|
597
|
+
var clientRect = getHoneyPotRectFor({
|
|
598
|
+
client: initial
|
|
599
|
+
});
|
|
600
|
+
Object.assign(element.style, _objectSpread$2(_objectSpread$2({
|
|
601
|
+
// Setting a background color explicitly to avoid any inherited styles.
|
|
602
|
+
// Looks like this could be `opacity: 0`, but worried that _might_
|
|
603
|
+
// cause the element to be ignored on some platforms.
|
|
604
|
+
// When debugging, set backgroundColor to something like "red".
|
|
605
|
+
backgroundColor: 'transparent',
|
|
606
|
+
position: 'fixed',
|
|
607
|
+
// Being explicit to avoid inheriting styles
|
|
608
|
+
padding: 0,
|
|
609
|
+
margin: 0,
|
|
610
|
+
boxSizing: 'border-box'
|
|
611
|
+
}, getRectStyles({
|
|
612
|
+
clientRect: clientRect
|
|
613
|
+
})), {}, {
|
|
614
|
+
// We want this element to absorb pointer events,
|
|
615
|
+
// it's kind of the whole point 😉
|
|
616
|
+
pointerEvents: 'auto',
|
|
617
|
+
// Want to make sure the honey pot is top of everything else.
|
|
618
|
+
// Don't need to worry about native drag previews, as they will
|
|
619
|
+
// have been rendered (and removed) before the honey pot is rendered
|
|
620
|
+
zIndex: maxZIndex
|
|
621
|
+
}));
|
|
622
|
+
document.body.appendChild(element);
|
|
623
|
+
|
|
624
|
+
/**
|
|
625
|
+
* 🦊 In firefox we can get `"pointermove"` events after the drag
|
|
626
|
+
* has started, which is a spec violation.
|
|
627
|
+
* The final `"pointermove"` will reveal where the "depressed" position
|
|
628
|
+
* is for our honey pot fix.
|
|
629
|
+
*/
|
|
630
|
+
var unbindPointerMove = bind(window, {
|
|
631
|
+
type: 'pointermove',
|
|
632
|
+
listener: function listener(event) {
|
|
633
|
+
var client = {
|
|
634
|
+
x: event.clientX,
|
|
635
|
+
y: event.clientY
|
|
636
|
+
};
|
|
637
|
+
clientRect = getHoneyPotRectFor({
|
|
638
|
+
client: client
|
|
639
|
+
});
|
|
640
|
+
Object.assign(element.style, getRectStyles({
|
|
641
|
+
clientRect: clientRect
|
|
642
|
+
}));
|
|
643
|
+
},
|
|
644
|
+
// using capture so we are less likely to be impacted by event stopping
|
|
645
|
+
options: {
|
|
646
|
+
capture: true
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
return function finish(_ref5) {
|
|
650
|
+
var current = _ref5.current;
|
|
651
|
+
// Don't need this any more
|
|
652
|
+
unbindPointerMove();
|
|
653
|
+
|
|
654
|
+
// If the user is hover the honey pot, we remove it
|
|
655
|
+
// so that the user can continue to interact with the page normally.
|
|
656
|
+
if (isWithin({
|
|
657
|
+
client: current,
|
|
658
|
+
clientRect: clientRect
|
|
659
|
+
})) {
|
|
660
|
+
element.remove();
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
function cleanup() {
|
|
664
|
+
unbindPostDragEvents();
|
|
665
|
+
element.remove();
|
|
666
|
+
}
|
|
667
|
+
var unbindPostDragEvents = bindAll(window, [{
|
|
668
|
+
type: 'pointerdown',
|
|
669
|
+
listener: cleanup
|
|
670
|
+
}, {
|
|
671
|
+
type: 'pointermove',
|
|
672
|
+
listener: cleanup
|
|
673
|
+
}, {
|
|
674
|
+
type: 'focusin',
|
|
675
|
+
listener: cleanup
|
|
676
|
+
}, {
|
|
677
|
+
type: 'focusout',
|
|
678
|
+
listener: cleanup
|
|
679
|
+
},
|
|
680
|
+
// a 'pointerdown' should happen before 'dragstart', but just being super safe
|
|
681
|
+
{
|
|
682
|
+
type: 'dragstart',
|
|
683
|
+
listener: cleanup
|
|
684
|
+
},
|
|
685
|
+
// if the user has dragged something out of the window
|
|
686
|
+
// and then is dragging something back into the window
|
|
687
|
+
// the first events we will see are "dragenter" (and then "dragover").
|
|
688
|
+
// So if we see any of these we need to clear the post drag fix.
|
|
689
|
+
{
|
|
690
|
+
type: 'dragenter',
|
|
691
|
+
listener: cleanup
|
|
692
|
+
}, {
|
|
693
|
+
type: 'dragover',
|
|
694
|
+
listener: cleanup
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
// Not adding a "wheel" event listener, as "wheel" by itself does not
|
|
698
|
+
// resolve the bug.
|
|
699
|
+
], {
|
|
700
|
+
// Using `capture` so less likely to be impacted by other code stopping events
|
|
701
|
+
capture: true
|
|
702
|
+
});
|
|
703
|
+
};
|
|
704
|
+
}
|
|
705
|
+
function makeHoneyPotFix() {
|
|
706
|
+
var latestPointerMove = null;
|
|
707
|
+
function bindEvents() {
|
|
708
|
+
// For sanity, only collecting this value from when events are first bound.
|
|
709
|
+
// This prevents the case where a super old "pointermove" could be used
|
|
710
|
+
// from a prior interaction.
|
|
711
|
+
latestPointerMove = null;
|
|
712
|
+
return bind(window, {
|
|
713
|
+
type: 'pointermove',
|
|
714
|
+
listener: function listener(event) {
|
|
715
|
+
latestPointerMove = {
|
|
716
|
+
x: event.clientX,
|
|
717
|
+
y: event.clientY
|
|
718
|
+
};
|
|
719
|
+
},
|
|
720
|
+
// listening for pointer move in capture phase
|
|
721
|
+
// so we are less likely to be impacted by events being stopped.
|
|
722
|
+
options: {
|
|
723
|
+
capture: true
|
|
724
|
+
}
|
|
725
|
+
});
|
|
726
|
+
}
|
|
727
|
+
function getOnPostDispatch() {
|
|
728
|
+
var finish = null;
|
|
729
|
+
return function onPostEvent(_ref6) {
|
|
730
|
+
var eventName = _ref6.eventName,
|
|
731
|
+
payload = _ref6.payload;
|
|
732
|
+
// We are adding the honey pot `onDragStart` so we don't
|
|
733
|
+
// impact the creation of the native drag preview.
|
|
734
|
+
if (eventName === 'onDragStart') {
|
|
735
|
+
var _latestPointerMove;
|
|
736
|
+
var input = payload.location.initial.input;
|
|
737
|
+
|
|
738
|
+
// Sometimes there will be no latest "pointermove" (eg iOS).
|
|
739
|
+
// In which case, we use the start position of the drag.
|
|
740
|
+
var initial = (_latestPointerMove = latestPointerMove) !== null && _latestPointerMove !== void 0 ? _latestPointerMove : {
|
|
741
|
+
x: input.clientX,
|
|
742
|
+
y: input.clientY
|
|
743
|
+
};
|
|
744
|
+
|
|
745
|
+
// Don't need to defensively call `finish()` as `onDrop` from
|
|
746
|
+
// one interaction is guaranteed to be called before `onDragStart`
|
|
747
|
+
// of the next.
|
|
748
|
+
finish = mountHoneyPot({
|
|
749
|
+
initial: initial
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
if (eventName === 'onDrop') {
|
|
753
|
+
var _finish;
|
|
754
|
+
var _input = payload.location.current.input;
|
|
755
|
+
(_finish = finish) === null || _finish === void 0 || _finish({
|
|
756
|
+
current: {
|
|
757
|
+
x: _input.clientX,
|
|
758
|
+
y: _input.clientY
|
|
759
|
+
}
|
|
760
|
+
});
|
|
761
|
+
finish = null;
|
|
762
|
+
// this interaction is finished, we want to use
|
|
763
|
+
// the latest "pointermove" for each interaction
|
|
764
|
+
latestPointerMove = null;
|
|
765
|
+
}
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
return {
|
|
769
|
+
bindEvents: bindEvents,
|
|
770
|
+
getOnPostDispatch: getOnPostDispatch
|
|
771
|
+
};
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
/** Provide a function that you only ever want to be called a single time */
|
|
775
|
+
function once(fn) {
|
|
776
|
+
var cache = null;
|
|
777
|
+
return function wrapped() {
|
|
778
|
+
if (!cache) {
|
|
779
|
+
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
780
|
+
args[_key] = arguments[_key];
|
|
781
|
+
}
|
|
782
|
+
var result = fn.apply(this, args);
|
|
783
|
+
cache = {
|
|
784
|
+
result: result
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
return cache.result;
|
|
788
|
+
};
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
// using `cache` as our `isFirefox()` result will not change in a browser
|
|
792
|
+
|
|
793
|
+
/**
|
|
794
|
+
* Returns `true` if a `Firefox` browser
|
|
795
|
+
* */
|
|
796
|
+
var isFirefox = once(function isFirefox() {
|
|
797
|
+
if (process.env.NODE_ENV === 'test') {
|
|
798
|
+
return false;
|
|
799
|
+
}
|
|
800
|
+
return navigator.userAgent.includes('Firefox');
|
|
801
|
+
});
|
|
802
|
+
|
|
803
|
+
// using `cache` as our `isSafari()` result will not change in a browser
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* Returns `true` if a `Safari` browser.
|
|
807
|
+
* Returns `true` if the browser is running on iOS (they are all Safari).
|
|
808
|
+
* */
|
|
809
|
+
var isSafari = once(function isSafari() {
|
|
810
|
+
if (process.env.NODE_ENV === 'test') {
|
|
811
|
+
return false;
|
|
812
|
+
}
|
|
813
|
+
var _navigator = navigator,
|
|
814
|
+
userAgent = _navigator.userAgent;
|
|
815
|
+
return userAgent.includes('AppleWebKit') && !userAgent.includes('Chrome');
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
/* For "dragenter" events, the browser should set `relatedTarget` to the previous element.
|
|
819
|
+
* For external drag operations, our first "dragenter" event should have a `event.relatedTarget` of `null`.
|
|
820
|
+
*
|
|
821
|
+
* Unfortunately in Safari `event.relatedTarget` is *always* set to `null`
|
|
822
|
+
* Safari bug: https://bugs.webkit.org/show_bug.cgi?id=242627
|
|
823
|
+
* To work around this we count "dragenter" and "dragleave" events */
|
|
824
|
+
|
|
825
|
+
// Using symbols for event properties so we don't clash with
|
|
826
|
+
// anything on the `event` object
|
|
827
|
+
var symbols = {
|
|
828
|
+
isLeavingWindow: Symbol('leaving'),
|
|
829
|
+
isEnteringWindow: Symbol('entering')
|
|
830
|
+
};
|
|
831
|
+
function isEnteringWindowInSafari(_ref) {
|
|
832
|
+
var dragEnter = _ref.dragEnter;
|
|
833
|
+
if (!isSafari()) {
|
|
834
|
+
return false;
|
|
835
|
+
}
|
|
836
|
+
return dragEnter.hasOwnProperty(symbols.isEnteringWindow);
|
|
837
|
+
}
|
|
838
|
+
function isLeavingWindowInSafari(_ref2) {
|
|
839
|
+
var dragLeave = _ref2.dragLeave;
|
|
840
|
+
if (!isSafari()) {
|
|
841
|
+
return false;
|
|
842
|
+
}
|
|
843
|
+
return dragLeave.hasOwnProperty(symbols.isLeavingWindow);
|
|
844
|
+
}
|
|
845
|
+
(function fixSafari() {
|
|
846
|
+
// Don't do anything when server side rendering
|
|
847
|
+
if (typeof window === 'undefined') {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
// rather than checking the userAgent for "jsdom" we can do this check
|
|
852
|
+
// so that the check will be removed completely in production code
|
|
853
|
+
if (process.env.NODE_ENV === 'test') {
|
|
854
|
+
return;
|
|
855
|
+
}
|
|
856
|
+
if (!isSafari()) {
|
|
857
|
+
return;
|
|
858
|
+
}
|
|
859
|
+
function getInitialState() {
|
|
860
|
+
return {
|
|
861
|
+
enterCount: 0,
|
|
862
|
+
isOverWindow: false
|
|
863
|
+
};
|
|
864
|
+
}
|
|
865
|
+
var state = getInitialState();
|
|
866
|
+
function resetState() {
|
|
867
|
+
state = getInitialState();
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// These event listeners are bound _forever_ and _never_ removed
|
|
871
|
+
// We don't bother cleaning up these event listeners (for now)
|
|
872
|
+
// as this workaround is only for Safari
|
|
873
|
+
|
|
874
|
+
// This is how the event count works:
|
|
875
|
+
//
|
|
876
|
+
// lift (+1 enterCount)
|
|
877
|
+
// - dragstart(draggable) [enterCount: 0]
|
|
878
|
+
// - dragenter(draggable) [enterCount: 1]
|
|
879
|
+
// leaving draggable (+0 enterCount)
|
|
880
|
+
// - dragenter(document.body) [enterCount: 2]
|
|
881
|
+
// - dragleave(draggable) [enterCount: 1]
|
|
882
|
+
// leaving window (-1 enterCount)
|
|
883
|
+
// - dragleave(document.body) [enterCount: 0] {leaving the window}
|
|
884
|
+
|
|
885
|
+
// Things to note:
|
|
886
|
+
// - dragenter and dragleave bubble
|
|
887
|
+
// - the first dragenter when entering a window might not be on `window`
|
|
888
|
+
// - it could be on an element that is pressed up against the window
|
|
889
|
+
// - (so we cannot rely on `event.target` values)
|
|
890
|
+
|
|
891
|
+
bindAll(window, [{
|
|
892
|
+
type: 'dragstart',
|
|
893
|
+
listener: function listener() {
|
|
894
|
+
state.enterCount = 0;
|
|
895
|
+
// drag start occurs in the source window
|
|
896
|
+
state.isOverWindow = true;
|
|
897
|
+
// When a drag first starts it will also trigger a "dragenter" on the draggable element
|
|
898
|
+
}
|
|
899
|
+
}, {
|
|
900
|
+
type: 'drop',
|
|
901
|
+
listener: resetState
|
|
902
|
+
}, {
|
|
903
|
+
type: 'dragend',
|
|
904
|
+
listener: resetState
|
|
905
|
+
}, {
|
|
906
|
+
type: 'dragenter',
|
|
907
|
+
listener: function listener(event) {
|
|
908
|
+
if (!state.isOverWindow && state.enterCount === 0) {
|
|
909
|
+
// Patching the `event` object
|
|
910
|
+
// The `event` object is shared with all event listeners for the event
|
|
911
|
+
// @ts-expect-error: adding property to the event object
|
|
912
|
+
event[symbols.isEnteringWindow] = true;
|
|
913
|
+
}
|
|
914
|
+
state.isOverWindow = true;
|
|
915
|
+
state.enterCount++;
|
|
916
|
+
}
|
|
917
|
+
}, {
|
|
918
|
+
type: 'dragleave',
|
|
919
|
+
listener: function listener(event) {
|
|
920
|
+
state.enterCount--;
|
|
921
|
+
if (state.isOverWindow && state.enterCount === 0) {
|
|
922
|
+
// Patching the `event` object as it is shared with all event listeners
|
|
923
|
+
// The `event` object is shared with all event listeners for the event
|
|
924
|
+
// @ts-expect-error: adding property to the event object
|
|
925
|
+
event[symbols.isLeavingWindow] = true;
|
|
926
|
+
state.isOverWindow = false;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}],
|
|
930
|
+
// using `capture: true` so that adding event listeners
|
|
931
|
+
// in bubble phase will have the correct symbols
|
|
932
|
+
{
|
|
933
|
+
capture: true
|
|
934
|
+
});
|
|
935
|
+
})();
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Does the `EventTarget` look like a `Node` based on "duck typing".
|
|
939
|
+
*
|
|
940
|
+
* Helpful when the `Node` might be outside of the current document
|
|
941
|
+
* so we cannot to an `target instanceof Node` check.
|
|
942
|
+
*/
|
|
943
|
+
function isNodeLike(target) {
|
|
944
|
+
return 'nodeName' in target;
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
/**
|
|
948
|
+
* Is an `EventTarget` a `Node` from another `window`?
|
|
949
|
+
*/
|
|
950
|
+
function isFromAnotherWindow(eventTarget) {
|
|
951
|
+
return isNodeLike(eventTarget) && eventTarget.ownerDocument !== document;
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
function isLeavingWindow(_ref) {
|
|
955
|
+
var dragLeave = _ref.dragLeave;
|
|
956
|
+
var type = dragLeave.type,
|
|
957
|
+
relatedTarget = dragLeave.relatedTarget;
|
|
958
|
+
if (type !== 'dragleave') {
|
|
959
|
+
return false;
|
|
960
|
+
}
|
|
961
|
+
if (isSafari()) {
|
|
962
|
+
return isLeavingWindowInSafari({
|
|
963
|
+
dragLeave: dragLeave
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
// Standard check: if going to `null` we are leaving the `window`
|
|
968
|
+
if (relatedTarget == null) {
|
|
969
|
+
return true;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
/**
|
|
973
|
+
* 🦊 Exception: `iframe` in Firefox (`125.0`)
|
|
974
|
+
*
|
|
975
|
+
* Case 1: parent `window` → child `iframe`
|
|
976
|
+
* `dragLeave.relatedTarget` is element _inside_ the child `iframe`
|
|
977
|
+
* (foreign element)
|
|
978
|
+
*
|
|
979
|
+
* Case 2: child `iframe` → parent `window`
|
|
980
|
+
* `dragLeave.relatedTarget` is the `iframe` in the parent `window`
|
|
981
|
+
* (foreign element)
|
|
982
|
+
*/
|
|
983
|
+
|
|
984
|
+
if (isFirefox()) {
|
|
985
|
+
return isFromAnotherWindow(relatedTarget);
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* 🌏 Exception: `iframe` in Chrome (`124.0`)
|
|
990
|
+
*
|
|
991
|
+
* Case 1: parent `window` → child `iframe`
|
|
992
|
+
* `dragLeave.relatedTarget` is the `iframe` in the parent `window`
|
|
993
|
+
*
|
|
994
|
+
* Case 2: child `iframe` → parent `window`
|
|
995
|
+
* `dragLeave.relatedTarget` is `null` *(standard check)*
|
|
996
|
+
*/
|
|
997
|
+
|
|
998
|
+
// Case 2
|
|
999
|
+
// Using `instanceof` check as the element will be in the same `window`
|
|
1000
|
+
return relatedTarget instanceof HTMLIFrameElement;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
function getBindingsForBrokenDrags(_ref) {
|
|
1004
|
+
var onDragEnd = _ref.onDragEnd;
|
|
1005
|
+
return [
|
|
1006
|
+
// ## Detecting drag ending for removed draggables
|
|
1007
|
+
//
|
|
1008
|
+
// If a draggable element is removed during a drag and the user drops:
|
|
1009
|
+
// 1. if over a valid drop target: we get a "drop" event to know the drag is finished
|
|
1010
|
+
// 2. if not over a valid drop target (or cancelled): we get nothing
|
|
1011
|
+
// The "dragend" event will not fire on the source draggable if it has been
|
|
1012
|
+
// removed from the DOM.
|
|
1013
|
+
// So we need to figure out if a drag operation has finished by looking at other events
|
|
1014
|
+
// We can do this by looking at other events
|
|
1015
|
+
|
|
1016
|
+
// ### First detection: "pointermove" events
|
|
1017
|
+
|
|
1018
|
+
// 1. "pointermove" events cannot fire during a drag and drop operation
|
|
1019
|
+
// according to the spec. So if we get a "pointermove" it means that
|
|
1020
|
+
// the drag and drop operations has finished. So if we get a "pointermove"
|
|
1021
|
+
// we know that the drag is over
|
|
1022
|
+
// 2. 🦊😤 Drag and drop operations are _supposed_ to suppress
|
|
1023
|
+
// other pointer events. However, firefox will allow a few
|
|
1024
|
+
// pointer event to get through after a drag starts.
|
|
1025
|
+
// The most I've seen is 3
|
|
1026
|
+
{
|
|
1027
|
+
type: 'pointermove',
|
|
1028
|
+
listener: function () {
|
|
1029
|
+
var callCount = 0;
|
|
1030
|
+
return function listener() {
|
|
1031
|
+
// Using 20 as it is far bigger than the most observed (3)
|
|
1032
|
+
if (callCount < 20) {
|
|
1033
|
+
callCount++;
|
|
1034
|
+
return;
|
|
1035
|
+
}
|
|
1036
|
+
onDragEnd();
|
|
1037
|
+
};
|
|
1038
|
+
}()
|
|
1039
|
+
},
|
|
1040
|
+
// ### Second detection: "pointerdown" events
|
|
1041
|
+
|
|
1042
|
+
// If we receive this event then we know that a drag operation has finished
|
|
1043
|
+
// and potentially another one is about to start.
|
|
1044
|
+
// Note: `pointerdown` fires on all browsers / platforms before "dragstart"
|
|
1045
|
+
{
|
|
1046
|
+
type: 'pointerdown',
|
|
1047
|
+
listener: onDragEnd
|
|
1048
|
+
}];
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
function getInput(event) {
|
|
1052
|
+
return {
|
|
1053
|
+
altKey: event.altKey,
|
|
1054
|
+
button: event.button,
|
|
1055
|
+
buttons: event.buttons,
|
|
1056
|
+
ctrlKey: event.ctrlKey,
|
|
1057
|
+
metaKey: event.metaKey,
|
|
1058
|
+
shiftKey: event.shiftKey,
|
|
1059
|
+
clientX: event.clientX,
|
|
1060
|
+
clientY: event.clientY,
|
|
1061
|
+
pageX: event.pageX,
|
|
1062
|
+
pageY: event.pageY
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
var scheduleOnDrag = rafSchd(function (fn) {
|
|
1067
|
+
return fn();
|
|
1068
|
+
});
|
|
1069
|
+
var dragStart = function () {
|
|
1070
|
+
var scheduled = null;
|
|
1071
|
+
function schedule(fn) {
|
|
1072
|
+
var frameId = requestAnimationFrame(function () {
|
|
1073
|
+
scheduled = null;
|
|
1074
|
+
fn();
|
|
1075
|
+
});
|
|
1076
|
+
scheduled = {
|
|
1077
|
+
frameId: frameId,
|
|
1078
|
+
fn: fn
|
|
1079
|
+
};
|
|
1080
|
+
}
|
|
1081
|
+
function flush() {
|
|
1082
|
+
if (scheduled) {
|
|
1083
|
+
cancelAnimationFrame(scheduled.frameId);
|
|
1084
|
+
scheduled.fn();
|
|
1085
|
+
scheduled = null;
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
return {
|
|
1089
|
+
schedule: schedule,
|
|
1090
|
+
flush: flush
|
|
1091
|
+
};
|
|
1092
|
+
}();
|
|
1093
|
+
function makeDispatch(_ref) {
|
|
1094
|
+
var source = _ref.source,
|
|
1095
|
+
initial = _ref.initial,
|
|
1096
|
+
dispatchEvent = _ref.dispatchEvent;
|
|
1097
|
+
var previous = {
|
|
1098
|
+
dropTargets: []
|
|
1099
|
+
};
|
|
1100
|
+
function safeDispatch(args) {
|
|
1101
|
+
dispatchEvent(args);
|
|
1102
|
+
previous = {
|
|
1103
|
+
dropTargets: args.payload.location.current.dropTargets
|
|
1104
|
+
};
|
|
1105
|
+
}
|
|
1106
|
+
var dispatch = {
|
|
1107
|
+
start: function start(_ref2) {
|
|
1108
|
+
var nativeSetDragImage = _ref2.nativeSetDragImage;
|
|
1109
|
+
// Ensuring that both `onGenerateDragPreview` and `onDragStart` get the same location.
|
|
1110
|
+
// We do this so that `previous` is`[]` in `onDragStart` (which is logical)
|
|
1111
|
+
var location = {
|
|
1112
|
+
current: initial,
|
|
1113
|
+
previous: previous,
|
|
1114
|
+
initial: initial
|
|
1115
|
+
};
|
|
1116
|
+
// a `onGenerateDragPreview` does _not_ add another entry for `previous`
|
|
1117
|
+
// onDragPreview
|
|
1118
|
+
safeDispatch({
|
|
1119
|
+
eventName: 'onGenerateDragPreview',
|
|
1120
|
+
payload: {
|
|
1121
|
+
source: source,
|
|
1122
|
+
location: location,
|
|
1123
|
+
nativeSetDragImage: nativeSetDragImage
|
|
1124
|
+
}
|
|
1125
|
+
});
|
|
1126
|
+
dragStart.schedule(function () {
|
|
1127
|
+
safeDispatch({
|
|
1128
|
+
eventName: 'onDragStart',
|
|
1129
|
+
payload: {
|
|
1130
|
+
source: source,
|
|
1131
|
+
location: location
|
|
1132
|
+
}
|
|
1133
|
+
});
|
|
1134
|
+
});
|
|
1135
|
+
},
|
|
1136
|
+
dragUpdate: function dragUpdate(_ref3) {
|
|
1137
|
+
var current = _ref3.current;
|
|
1138
|
+
dragStart.flush();
|
|
1139
|
+
scheduleOnDrag.cancel();
|
|
1140
|
+
safeDispatch({
|
|
1141
|
+
eventName: 'onDropTargetChange',
|
|
1142
|
+
payload: {
|
|
1143
|
+
source: source,
|
|
1144
|
+
location: {
|
|
1145
|
+
initial: initial,
|
|
1146
|
+
previous: previous,
|
|
1147
|
+
current: current
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
},
|
|
1152
|
+
drag: function drag(_ref4) {
|
|
1153
|
+
var current = _ref4.current;
|
|
1154
|
+
scheduleOnDrag(function () {
|
|
1155
|
+
dragStart.flush();
|
|
1156
|
+
var location = {
|
|
1157
|
+
initial: initial,
|
|
1158
|
+
previous: previous,
|
|
1159
|
+
current: current
|
|
1160
|
+
};
|
|
1161
|
+
safeDispatch({
|
|
1162
|
+
eventName: 'onDrag',
|
|
1163
|
+
payload: {
|
|
1164
|
+
source: source,
|
|
1165
|
+
location: location
|
|
1166
|
+
}
|
|
1167
|
+
});
|
|
1168
|
+
});
|
|
1169
|
+
},
|
|
1170
|
+
drop: function drop(_ref5) {
|
|
1171
|
+
var current = _ref5.current,
|
|
1172
|
+
updatedSourcePayload = _ref5.updatedSourcePayload;
|
|
1173
|
+
dragStart.flush();
|
|
1174
|
+
scheduleOnDrag.cancel();
|
|
1175
|
+
safeDispatch({
|
|
1176
|
+
eventName: 'onDrop',
|
|
1177
|
+
payload: {
|
|
1178
|
+
source: updatedSourcePayload !== null && updatedSourcePayload !== void 0 ? updatedSourcePayload : source,
|
|
1179
|
+
location: {
|
|
1180
|
+
current: current,
|
|
1181
|
+
previous: previous,
|
|
1182
|
+
initial: initial
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
});
|
|
1186
|
+
}
|
|
1187
|
+
};
|
|
1188
|
+
return dispatch;
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
var globalState = {
|
|
1192
|
+
isActive: false
|
|
1193
|
+
};
|
|
1194
|
+
function canStart() {
|
|
1195
|
+
return !globalState.isActive;
|
|
1196
|
+
}
|
|
1197
|
+
function getNativeSetDragImage(event) {
|
|
1198
|
+
if (event.dataTransfer) {
|
|
1199
|
+
// need to use `.bind` as `setDragImage` is required
|
|
1200
|
+
// to be run with `event.dataTransfer` as the "this" context
|
|
1201
|
+
return event.dataTransfer.setDragImage.bind(event.dataTransfer);
|
|
1202
|
+
}
|
|
1203
|
+
return null;
|
|
1204
|
+
}
|
|
1205
|
+
function hasHierarchyChanged(_ref) {
|
|
1206
|
+
var current = _ref.current,
|
|
1207
|
+
next = _ref.next;
|
|
1208
|
+
if (current.length !== next.length) {
|
|
1209
|
+
return true;
|
|
1210
|
+
}
|
|
1211
|
+
// not checking stickiness, data or dropEffect,
|
|
1212
|
+
// just whether the hierarchy has changed
|
|
1213
|
+
for (var i = 0; i < current.length; i++) {
|
|
1214
|
+
if (current[i].element !== next[i].element) {
|
|
1215
|
+
return true;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
return false;
|
|
1219
|
+
}
|
|
1220
|
+
function start(_ref2) {
|
|
1221
|
+
var event = _ref2.event,
|
|
1222
|
+
dragType = _ref2.dragType,
|
|
1223
|
+
getDropTargetsOver = _ref2.getDropTargetsOver,
|
|
1224
|
+
dispatchEvent = _ref2.dispatchEvent;
|
|
1225
|
+
if (!canStart()) {
|
|
1226
|
+
return;
|
|
1227
|
+
}
|
|
1228
|
+
var initial = getStartLocation({
|
|
1229
|
+
event: event,
|
|
1230
|
+
dragType: dragType,
|
|
1231
|
+
getDropTargetsOver: getDropTargetsOver
|
|
1232
|
+
});
|
|
1233
|
+
globalState.isActive = true;
|
|
1234
|
+
var state = {
|
|
1235
|
+
current: initial
|
|
1236
|
+
};
|
|
1237
|
+
|
|
1238
|
+
// Setting initial drop effect for the drag
|
|
1239
|
+
setDropEffectOnEvent({
|
|
1240
|
+
event: event,
|
|
1241
|
+
current: initial.dropTargets
|
|
1242
|
+
});
|
|
1243
|
+
var dispatch = makeDispatch({
|
|
1244
|
+
source: dragType.payload,
|
|
1245
|
+
dispatchEvent: dispatchEvent,
|
|
1246
|
+
initial: initial
|
|
1247
|
+
});
|
|
1248
|
+
function updateState(next) {
|
|
1249
|
+
// only looking at whether hierarchy has changed to determine whether something as 'changed'
|
|
1250
|
+
var hasChanged = hasHierarchyChanged({
|
|
1251
|
+
current: state.current.dropTargets,
|
|
1252
|
+
next: next.dropTargets
|
|
1253
|
+
});
|
|
1254
|
+
|
|
1255
|
+
// Always updating the state to include latest data, dropEffect and stickiness
|
|
1256
|
+
// Only updating consumers if the hierarchy has changed in some way
|
|
1257
|
+
// Consumers can get the latest data by using `onDrag`
|
|
1258
|
+
state.current = next;
|
|
1259
|
+
if (hasChanged) {
|
|
1260
|
+
dispatch.dragUpdate({
|
|
1261
|
+
current: state.current
|
|
1262
|
+
});
|
|
1263
|
+
}
|
|
1264
|
+
}
|
|
1265
|
+
function onUpdateEvent(event) {
|
|
1266
|
+
var input = getInput(event);
|
|
1267
|
+
|
|
1268
|
+
// If we are over the honey pot, we need to get the element
|
|
1269
|
+
// that the user would have been over if not for the honey pot
|
|
1270
|
+
var target = isHoneyPotElement(event.target) ? getElementFromPointWithoutHoneypot({
|
|
1271
|
+
x: input.clientX,
|
|
1272
|
+
y: input.clientY
|
|
1273
|
+
}) : event.target;
|
|
1274
|
+
var nextDropTargets = getDropTargetsOver({
|
|
1275
|
+
target: target,
|
|
1276
|
+
input: input,
|
|
1277
|
+
source: dragType.payload,
|
|
1278
|
+
current: state.current.dropTargets
|
|
1279
|
+
});
|
|
1280
|
+
if (nextDropTargets.length) {
|
|
1281
|
+
// 🩸 must call `event.preventDefault()` to allow a browser drop to occur
|
|
1282
|
+
event.preventDefault();
|
|
1283
|
+
setDropEffectOnEvent({
|
|
1284
|
+
event: event,
|
|
1285
|
+
current: nextDropTargets
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
updateState({
|
|
1289
|
+
dropTargets: nextDropTargets,
|
|
1290
|
+
input: input
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
function cancel() {
|
|
1294
|
+
// The spec behaviour is that when a drag is cancelled, or when dropping on no drop targets,
|
|
1295
|
+
// a "dragleave" event is fired on the active drop target before a "dragend" event.
|
|
1296
|
+
// We are replicating that behaviour in `cancel` if there are any active drop targets to
|
|
1297
|
+
// ensure consistent behaviour.
|
|
1298
|
+
//
|
|
1299
|
+
// Note: When cancelling, or dropping on no drop targets, a "dragleave" event
|
|
1300
|
+
// will have already cleared the dropTargets to `[]` (as that particular "dragleave" has a `relatedTarget` of `null`)
|
|
1301
|
+
|
|
1302
|
+
if (state.current.dropTargets.length) {
|
|
1303
|
+
updateState({
|
|
1304
|
+
dropTargets: [],
|
|
1305
|
+
input: state.current.input
|
|
1306
|
+
});
|
|
1307
|
+
}
|
|
1308
|
+
dispatch.drop({
|
|
1309
|
+
current: state.current,
|
|
1310
|
+
updatedSourcePayload: null
|
|
1311
|
+
});
|
|
1312
|
+
finish();
|
|
1313
|
+
}
|
|
1314
|
+
function finish() {
|
|
1315
|
+
globalState.isActive = false;
|
|
1316
|
+
unbindEvents();
|
|
1317
|
+
}
|
|
1318
|
+
var unbindEvents = bindAll(window, [{
|
|
1319
|
+
// 👋 Note: we are repurposing the `dragover` event as our `drag` event
|
|
1320
|
+
// this is because firefox does not publish pointer coordinates during
|
|
1321
|
+
// a `drag` event, but does for every other type of drag event
|
|
1322
|
+
// `dragover` fires on all elements that are being dragged over
|
|
1323
|
+
// Because we are binding to `window` - our `dragover` is effectively the same as a `drag`
|
|
1324
|
+
// 🦊😤
|
|
1325
|
+
type: 'dragover',
|
|
1326
|
+
listener: function listener(event) {
|
|
1327
|
+
// We need to regularly calculate the drop targets in order to allow:
|
|
1328
|
+
// - dynamic `canDrop()` checks
|
|
1329
|
+
// - rapid updating `getData()` calls to attach data in response to user input (eg for edge detection)
|
|
1330
|
+
// Sadly we cannot schedule inspecting changes resulting from this event
|
|
1331
|
+
// we need to be able to conditionally cancel the event with `event.preventDefault()`
|
|
1332
|
+
// to enable the correct native drop experience.
|
|
1333
|
+
|
|
1334
|
+
// 1. check to see if anything has changed
|
|
1335
|
+
onUpdateEvent(event);
|
|
1336
|
+
|
|
1337
|
+
// 2. let consumers know a move has occurred
|
|
1338
|
+
// This will include the latest 'input' values
|
|
1339
|
+
dispatch.drag({
|
|
1340
|
+
current: state.current
|
|
1341
|
+
});
|
|
1342
|
+
}
|
|
1343
|
+
}, {
|
|
1344
|
+
type: 'dragenter',
|
|
1345
|
+
listener: onUpdateEvent
|
|
1346
|
+
}, {
|
|
1347
|
+
type: 'dragleave',
|
|
1348
|
+
listener: function listener(event) {
|
|
1349
|
+
if (!isLeavingWindow({
|
|
1350
|
+
dragLeave: event
|
|
1351
|
+
})) {
|
|
1352
|
+
return;
|
|
1353
|
+
}
|
|
1354
|
+
|
|
1355
|
+
/**
|
|
1356
|
+
* At this point we don't know if a drag is being cancelled,
|
|
1357
|
+
* or if a drag is leaving the `window`.
|
|
1358
|
+
*
|
|
1359
|
+
* Both have:
|
|
1360
|
+
* 1. "dragleave" (with `relatedTarget: null`)
|
|
1361
|
+
* 2. "dragend" (a "dragend" can occur when outside the `window`)
|
|
1362
|
+
*
|
|
1363
|
+
* **Clearing drop targets**
|
|
1364
|
+
*
|
|
1365
|
+
* For either case we are clearing the the drop targets
|
|
1366
|
+
*
|
|
1367
|
+
* - cancelling: we clear drop targets in `"dragend"` anyway
|
|
1368
|
+
* - leaving the `window`: we clear the drop targets (to clear stickiness)
|
|
1369
|
+
*
|
|
1370
|
+
* **Leaving the window and finishing the drag**
|
|
1371
|
+
*
|
|
1372
|
+
* _internal drags_
|
|
1373
|
+
*
|
|
1374
|
+
* - The drag continues when the user is outside the `window`
|
|
1375
|
+
* and can resume if the user drags back over the `window`,
|
|
1376
|
+
* or end when the user drops in an external `window`.
|
|
1377
|
+
* - We will get a `"dragend"`, or we can listen for other
|
|
1378
|
+
* events to determine the drag is finished when the user re-enters the `window`).
|
|
1379
|
+
*
|
|
1380
|
+
* _external drags_
|
|
1381
|
+
*
|
|
1382
|
+
* - We conclude the drag operation.
|
|
1383
|
+
* - We have no idea if the user will drag back over the `window`,
|
|
1384
|
+
* or if the drag ends elsewhere.
|
|
1385
|
+
* - We will create a new drag if the user re-enters the `window`.
|
|
1386
|
+
*
|
|
1387
|
+
* **Not updating `input`**
|
|
1388
|
+
*
|
|
1389
|
+
* 🐛 Bug[Chrome] the final `"dragleave"` has default input values (eg `clientX == 0`)
|
|
1390
|
+
* Workaround: intentionally not updating `input` in "dragleave"
|
|
1391
|
+
* rather than the users current input values
|
|
1392
|
+
* - [Conversation](https://twitter.com/alexandereardon/status/1642697633864241152)
|
|
1393
|
+
* - [Bug](https://bugs.chromium.org/p/chromium/issues/detail?id=1429937)
|
|
1394
|
+
**/
|
|
1395
|
+
|
|
1396
|
+
updateState({
|
|
1397
|
+
input: state.current.input,
|
|
1398
|
+
dropTargets: []
|
|
1399
|
+
});
|
|
1400
|
+
if (dragType.startedFrom === 'external') {
|
|
1401
|
+
cancel();
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
}, {
|
|
1405
|
+
// A "drop" can only happen if the browser allowed the drop
|
|
1406
|
+
type: 'drop',
|
|
1407
|
+
listener: function listener(event) {
|
|
1408
|
+
// Capture the final input.
|
|
1409
|
+
// We are capturing the final `input` for the
|
|
1410
|
+
// most accurate honey pot experience
|
|
1411
|
+
state.current = {
|
|
1412
|
+
dropTargets: state.current.dropTargets,
|
|
1413
|
+
input: getInput(event)
|
|
1414
|
+
};
|
|
1415
|
+
|
|
1416
|
+
/** If there are no drop targets, then we will get
|
|
1417
|
+
* a "drop" event if:
|
|
1418
|
+
* - `preventUnhandled()` is being used
|
|
1419
|
+
* - there is an unmanaged drop target (eg another library)
|
|
1420
|
+
* In these cases, it's up to the consumer
|
|
1421
|
+
* to handle the drop if it's not over one of our drop targets
|
|
1422
|
+
* - `preventUnhandled()` will cancel the "drop"
|
|
1423
|
+
* - unmanaged drop targets can handle the "drop" how they want to
|
|
1424
|
+
* We won't call `event.preventDefault()` in this call path */
|
|
1425
|
+
|
|
1426
|
+
if (!state.current.dropTargets.length) {
|
|
1427
|
+
cancel();
|
|
1428
|
+
return;
|
|
1429
|
+
}
|
|
1430
|
+
event.preventDefault();
|
|
1431
|
+
|
|
1432
|
+
// applying the latest drop effect to the event
|
|
1433
|
+
setDropEffectOnEvent({
|
|
1434
|
+
event: event,
|
|
1435
|
+
current: state.current.dropTargets
|
|
1436
|
+
});
|
|
1437
|
+
dispatch.drop({
|
|
1438
|
+
current: state.current,
|
|
1439
|
+
// When dropping something native, we need to extract the latest
|
|
1440
|
+
// `.items` from the "drop" event as it is now accessible
|
|
1441
|
+
updatedSourcePayload: dragType.type === 'external' ? dragType.getDropPayload(event) : null
|
|
1442
|
+
});
|
|
1443
|
+
finish();
|
|
1444
|
+
}
|
|
1445
|
+
}, {
|
|
1446
|
+
// "dragend" fires when on the drag source (eg a draggable element)
|
|
1447
|
+
// when the drag is finished.
|
|
1448
|
+
// "dragend" will fire after "drop" (if there was a successful drop)
|
|
1449
|
+
// "dragend" does not fire if the draggable source has been removed during the drag
|
|
1450
|
+
// or for external drag sources (eg files)
|
|
1451
|
+
|
|
1452
|
+
// This "dragend" listener will not fire if there was a successful drop
|
|
1453
|
+
// as we will have already removed the event listener
|
|
1454
|
+
|
|
1455
|
+
type: 'dragend',
|
|
1456
|
+
listener: function listener(event) {
|
|
1457
|
+
// In firefox, the position of the "dragend" event can
|
|
1458
|
+
// be a bit different to the last "dragover" event.
|
|
1459
|
+
// Updating the input so we can get the best possible
|
|
1460
|
+
// information for the honey pot.
|
|
1461
|
+
state.current = {
|
|
1462
|
+
dropTargets: state.current.dropTargets,
|
|
1463
|
+
input: getInput(event)
|
|
1464
|
+
};
|
|
1465
|
+
cancel();
|
|
1466
|
+
}
|
|
1467
|
+
}].concat(_toConsumableArray(getBindingsForBrokenDrags({
|
|
1468
|
+
onDragEnd: cancel
|
|
1469
|
+
}))),
|
|
1470
|
+
// Once we have started a managed drag operation it is important that we see / own all drag events
|
|
1471
|
+
// We got one adoption bug pop up where some code was stopping (`event.stopPropagation()`)
|
|
1472
|
+
// all "drop" events in the bubble phase on the `document.body`.
|
|
1473
|
+
// This meant that we never saw the "drop" event.
|
|
1474
|
+
{
|
|
1475
|
+
capture: true
|
|
1476
|
+
});
|
|
1477
|
+
dispatch.start({
|
|
1478
|
+
nativeSetDragImage: getNativeSetDragImage(event)
|
|
1479
|
+
});
|
|
1480
|
+
}
|
|
1481
|
+
function setDropEffectOnEvent(_ref3) {
|
|
1482
|
+
var _current$;
|
|
1483
|
+
var event = _ref3.event,
|
|
1484
|
+
current = _ref3.current;
|
|
1485
|
+
// setting the `dropEffect` to be the innerMost drop targets dropEffect
|
|
1486
|
+
var innerMost = (_current$ = current[0]) === null || _current$ === void 0 ? void 0 : _current$.dropEffect;
|
|
1487
|
+
if (innerMost != null && event.dataTransfer) {
|
|
1488
|
+
event.dataTransfer.dropEffect = innerMost;
|
|
1489
|
+
}
|
|
1490
|
+
}
|
|
1491
|
+
function getStartLocation(_ref4) {
|
|
1492
|
+
var event = _ref4.event,
|
|
1493
|
+
dragType = _ref4.dragType,
|
|
1494
|
+
getDropTargetsOver = _ref4.getDropTargetsOver;
|
|
1495
|
+
var input = getInput(event);
|
|
1496
|
+
|
|
1497
|
+
// When dragging from outside of the browser,
|
|
1498
|
+
// the drag is not being sourced from any local drop targets
|
|
1499
|
+
if (dragType.startedFrom === 'external') {
|
|
1500
|
+
return {
|
|
1501
|
+
input: input,
|
|
1502
|
+
dropTargets: []
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
var dropTargets = getDropTargetsOver({
|
|
1506
|
+
input: input,
|
|
1507
|
+
source: dragType.payload,
|
|
1508
|
+
target: event.target,
|
|
1509
|
+
current: []
|
|
1510
|
+
});
|
|
1511
|
+
return {
|
|
1512
|
+
input: input,
|
|
1513
|
+
dropTargets: dropTargets
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
var lifecycle = {
|
|
1517
|
+
canStart: canStart,
|
|
1518
|
+
start: start
|
|
1519
|
+
};
|
|
1520
|
+
|
|
1521
|
+
// Extending `Map` to allow us to link Key and Values together
|
|
1522
|
+
|
|
1523
|
+
var ledger = new Map();
|
|
1524
|
+
function registerUsage(_ref) {
|
|
1525
|
+
var typeKey = _ref.typeKey,
|
|
1526
|
+
mount = _ref.mount;
|
|
1527
|
+
var entry = ledger.get(typeKey);
|
|
1528
|
+
if (entry) {
|
|
1529
|
+
entry.usageCount++;
|
|
1530
|
+
return entry;
|
|
1531
|
+
}
|
|
1532
|
+
var initial = {
|
|
1533
|
+
typeKey: typeKey,
|
|
1534
|
+
unmount: mount(),
|
|
1535
|
+
usageCount: 1
|
|
1536
|
+
};
|
|
1537
|
+
ledger.set(typeKey, initial);
|
|
1538
|
+
return initial;
|
|
1539
|
+
}
|
|
1540
|
+
function register(args) {
|
|
1541
|
+
var entry = registerUsage(args);
|
|
1542
|
+
return function unregister() {
|
|
1543
|
+
entry.usageCount--;
|
|
1544
|
+
if (entry.usageCount > 0) {
|
|
1545
|
+
return;
|
|
1546
|
+
}
|
|
1547
|
+
// Only a single usage left, remove it
|
|
1548
|
+
entry.unmount();
|
|
1549
|
+
ledger.delete(args.typeKey);
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/** Create a new combined function that will call all the provided functions */
|
|
1554
|
+
function combine() {
|
|
1555
|
+
for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
1556
|
+
fns[_key] = arguments[_key];
|
|
1557
|
+
}
|
|
1558
|
+
return function cleanup() {
|
|
1559
|
+
fns.forEach(function (fn) {
|
|
1560
|
+
return fn();
|
|
1561
|
+
});
|
|
1562
|
+
};
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
function addAttribute(element, _ref) {
|
|
1566
|
+
var attribute = _ref.attribute,
|
|
1567
|
+
value = _ref.value;
|
|
1568
|
+
element.setAttribute(attribute, value);
|
|
1569
|
+
return function () {
|
|
1570
|
+
return element.removeAttribute(attribute);
|
|
1571
|
+
};
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
function ownKeys$1(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
1575
|
+
function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys$1(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys$1(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1576
|
+
function _createForOfIteratorHelper$1(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray$1(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
1577
|
+
function _unsupportedIterableToArray$1(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray$1(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray$1(r, a) : void 0; } }
|
|
1578
|
+
function _arrayLikeToArray$1(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
1579
|
+
function copyReverse(array) {
|
|
1580
|
+
return array.slice(0).reverse();
|
|
1581
|
+
}
|
|
1582
|
+
function makeDropTarget(_ref) {
|
|
1583
|
+
var typeKey = _ref.typeKey,
|
|
1584
|
+
defaultDropEffect = _ref.defaultDropEffect;
|
|
1585
|
+
var registry = new WeakMap();
|
|
1586
|
+
var dropTargetDataAtt = "data-drop-target-for-".concat(typeKey);
|
|
1587
|
+
var dropTargetSelector = "[".concat(dropTargetDataAtt, "]");
|
|
1588
|
+
function addToRegistry(args) {
|
|
1589
|
+
registry.set(args.element, args);
|
|
1590
|
+
return function () {
|
|
1591
|
+
return registry.delete(args.element);
|
|
1592
|
+
};
|
|
1593
|
+
}
|
|
1594
|
+
function dropTargetForConsumers(args) {
|
|
1595
|
+
// Guardrail: warn if the draggable element is already registered
|
|
1596
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
1597
|
+
var existing = registry.get(args.element);
|
|
1598
|
+
if (existing) {
|
|
1599
|
+
// eslint-disable-next-line no-console
|
|
1600
|
+
console.warn("You have already registered a [".concat(typeKey, "] dropTarget on the same element"), {
|
|
1601
|
+
existing: existing,
|
|
1602
|
+
proposed: args
|
|
1603
|
+
});
|
|
1604
|
+
}
|
|
1605
|
+
if (args.element instanceof HTMLIFrameElement) {
|
|
1606
|
+
// eslint-disable-next-line no-console
|
|
1607
|
+
console.warn("\n We recommend not registering <iframe> elements as drop targets\n as it can result in some strange browser event ordering.\n " // Removing newlines and excessive whitespace
|
|
1608
|
+
.replace(/\s{2,}/g, ' ').trim());
|
|
1609
|
+
}
|
|
1610
|
+
}
|
|
1611
|
+
return combine(addAttribute(args.element, {
|
|
1612
|
+
attribute: dropTargetDataAtt,
|
|
1613
|
+
value: 'true'
|
|
1614
|
+
}), addToRegistry(args));
|
|
1615
|
+
}
|
|
1616
|
+
function getActualDropTargets(_ref2) {
|
|
1617
|
+
var _args$getData, _args$getData2, _args$getDropEffect, _args$getDropEffect2;
|
|
1618
|
+
var source = _ref2.source,
|
|
1619
|
+
target = _ref2.target,
|
|
1620
|
+
input = _ref2.input,
|
|
1621
|
+
_ref2$result = _ref2.result,
|
|
1622
|
+
result = _ref2$result === void 0 ? [] : _ref2$result;
|
|
1623
|
+
if (target == null) {
|
|
1624
|
+
return result;
|
|
1625
|
+
}
|
|
1626
|
+
if (!(target instanceof Element)) {
|
|
1627
|
+
// For "text-selection" drags, the original `target`
|
|
1628
|
+
// is not an `Element`, so we need to start looking from
|
|
1629
|
+
// the parent element
|
|
1630
|
+
if (target instanceof Node) {
|
|
1631
|
+
return getActualDropTargets({
|
|
1632
|
+
source: source,
|
|
1633
|
+
target: target.parentElement,
|
|
1634
|
+
input: input,
|
|
1635
|
+
result: result
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
// not sure what we are working with,
|
|
1640
|
+
// so we can exit.
|
|
1641
|
+
return result;
|
|
1642
|
+
}
|
|
1643
|
+
var closest = target.closest(dropTargetSelector);
|
|
1644
|
+
|
|
1645
|
+
// Cannot find anything else
|
|
1646
|
+
if (closest == null) {
|
|
1647
|
+
return result;
|
|
1648
|
+
}
|
|
1649
|
+
var args = registry.get(closest);
|
|
1650
|
+
|
|
1651
|
+
// error: something had a dropTargetSelector but we could not
|
|
1652
|
+
// find a match. For now, failing silently
|
|
1653
|
+
if (args == null) {
|
|
1654
|
+
return result;
|
|
1655
|
+
}
|
|
1656
|
+
var feedback = {
|
|
1657
|
+
input: input,
|
|
1658
|
+
source: source,
|
|
1659
|
+
element: args.element
|
|
1660
|
+
};
|
|
1661
|
+
|
|
1662
|
+
// if dropping is not allowed, skip this drop target
|
|
1663
|
+
// and continue looking up the DOM tree
|
|
1664
|
+
if (args.canDrop && !args.canDrop(feedback)) {
|
|
1665
|
+
return getActualDropTargets({
|
|
1666
|
+
source: source,
|
|
1667
|
+
target: args.element.parentElement,
|
|
1668
|
+
input: input,
|
|
1669
|
+
result: result
|
|
1670
|
+
});
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
// calculate our new record
|
|
1674
|
+
var data = (_args$getData = (_args$getData2 = args.getData) === null || _args$getData2 === void 0 ? void 0 : _args$getData2.call(args, feedback)) !== null && _args$getData !== void 0 ? _args$getData : {};
|
|
1675
|
+
var dropEffect = (_args$getDropEffect = (_args$getDropEffect2 = args.getDropEffect) === null || _args$getDropEffect2 === void 0 ? void 0 : _args$getDropEffect2.call(args, feedback)) !== null && _args$getDropEffect !== void 0 ? _args$getDropEffect : defaultDropEffect;
|
|
1676
|
+
var record = {
|
|
1677
|
+
data: data,
|
|
1678
|
+
element: args.element,
|
|
1679
|
+
dropEffect: dropEffect,
|
|
1680
|
+
// we are collecting _actual_ drop targets, so these are
|
|
1681
|
+
// being applied _not_ due to stickiness
|
|
1682
|
+
isActiveDueToStickiness: false
|
|
1683
|
+
};
|
|
1684
|
+
return getActualDropTargets({
|
|
1685
|
+
source: source,
|
|
1686
|
+
target: args.element.parentElement,
|
|
1687
|
+
input: input,
|
|
1688
|
+
// Using bubble ordering. Same ordering as `event.getPath()`
|
|
1689
|
+
result: [].concat(_toConsumableArray(result), [record])
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1692
|
+
function notifyCurrent(_ref3) {
|
|
1693
|
+
var eventName = _ref3.eventName,
|
|
1694
|
+
payload = _ref3.payload;
|
|
1695
|
+
var _iterator = _createForOfIteratorHelper$1(payload.location.current.dropTargets),
|
|
1696
|
+
_step;
|
|
1697
|
+
try {
|
|
1698
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1699
|
+
var _entry$eventName;
|
|
1700
|
+
var record = _step.value;
|
|
1701
|
+
var entry = registry.get(record.element);
|
|
1702
|
+
var args = _objectSpread$1(_objectSpread$1({}, payload), {}, {
|
|
1703
|
+
self: record
|
|
1704
|
+
});
|
|
1705
|
+
entry === null || entry === void 0 || (_entry$eventName = entry[eventName]) === null || _entry$eventName === void 0 || _entry$eventName.call(entry,
|
|
1706
|
+
// I cannot seem to get the types right here.
|
|
1707
|
+
// TS doesn't seem to like that one event can need `nativeSetDragImage`
|
|
1708
|
+
// @ts-expect-error
|
|
1709
|
+
args);
|
|
1710
|
+
}
|
|
1711
|
+
} catch (err) {
|
|
1712
|
+
_iterator.e(err);
|
|
1713
|
+
} finally {
|
|
1714
|
+
_iterator.f();
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
var actions = {
|
|
1718
|
+
onGenerateDragPreview: notifyCurrent,
|
|
1719
|
+
onDrag: notifyCurrent,
|
|
1720
|
+
onDragStart: notifyCurrent,
|
|
1721
|
+
onDrop: notifyCurrent,
|
|
1722
|
+
onDropTargetChange: function onDropTargetChange(_ref4) {
|
|
1723
|
+
var payload = _ref4.payload;
|
|
1724
|
+
var isCurrent = new Set(payload.location.current.dropTargets.map(function (record) {
|
|
1725
|
+
return record.element;
|
|
1726
|
+
}));
|
|
1727
|
+
var visited = new Set();
|
|
1728
|
+
var _iterator2 = _createForOfIteratorHelper$1(payload.location.previous.dropTargets),
|
|
1729
|
+
_step2;
|
|
1730
|
+
try {
|
|
1731
|
+
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
|
|
1732
|
+
var _entry$onDropTargetCh;
|
|
1733
|
+
var record = _step2.value;
|
|
1734
|
+
visited.add(record.element);
|
|
1735
|
+
var entry = registry.get(record.element);
|
|
1736
|
+
var isOver = isCurrent.has(record.element);
|
|
1737
|
+
var args = _objectSpread$1(_objectSpread$1({}, payload), {}, {
|
|
1738
|
+
self: record
|
|
1739
|
+
});
|
|
1740
|
+
entry === null || entry === void 0 || (_entry$onDropTargetCh = entry.onDropTargetChange) === null || _entry$onDropTargetCh === void 0 || _entry$onDropTargetCh.call(entry, args);
|
|
1741
|
+
|
|
1742
|
+
// if we cannot find the drop target in the current array, then it has been left
|
|
1743
|
+
if (!isOver) {
|
|
1744
|
+
var _entry$onDragLeave;
|
|
1745
|
+
entry === null || entry === void 0 || (_entry$onDragLeave = entry.onDragLeave) === null || _entry$onDragLeave === void 0 || _entry$onDragLeave.call(entry, args);
|
|
1746
|
+
}
|
|
1747
|
+
}
|
|
1748
|
+
} catch (err) {
|
|
1749
|
+
_iterator2.e(err);
|
|
1750
|
+
} finally {
|
|
1751
|
+
_iterator2.f();
|
|
1752
|
+
}
|
|
1753
|
+
var _iterator3 = _createForOfIteratorHelper$1(payload.location.current.dropTargets),
|
|
1754
|
+
_step3;
|
|
1755
|
+
try {
|
|
1756
|
+
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
|
|
1757
|
+
var _entry$onDropTargetCh2, _entry$onDragEnter;
|
|
1758
|
+
var _record = _step3.value;
|
|
1759
|
+
// already published an update to this drop target
|
|
1760
|
+
if (visited.has(_record.element)) {
|
|
1761
|
+
continue;
|
|
1762
|
+
}
|
|
1763
|
+
// at this point we have a new drop target that is being entered into
|
|
1764
|
+
var _args = _objectSpread$1(_objectSpread$1({}, payload), {}, {
|
|
1765
|
+
self: _record
|
|
1766
|
+
});
|
|
1767
|
+
var _entry = registry.get(_record.element);
|
|
1768
|
+
_entry === null || _entry === void 0 || (_entry$onDropTargetCh2 = _entry.onDropTargetChange) === null || _entry$onDropTargetCh2 === void 0 || _entry$onDropTargetCh2.call(_entry, _args);
|
|
1769
|
+
_entry === null || _entry === void 0 || (_entry$onDragEnter = _entry.onDragEnter) === null || _entry$onDragEnter === void 0 || _entry$onDragEnter.call(_entry, _args);
|
|
1770
|
+
}
|
|
1771
|
+
} catch (err) {
|
|
1772
|
+
_iterator3.e(err);
|
|
1773
|
+
} finally {
|
|
1774
|
+
_iterator3.f();
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
};
|
|
1778
|
+
function dispatchEvent(args) {
|
|
1779
|
+
actions[args.eventName](args);
|
|
1780
|
+
}
|
|
1781
|
+
function getIsOver(_ref5) {
|
|
1782
|
+
var source = _ref5.source,
|
|
1783
|
+
target = _ref5.target,
|
|
1784
|
+
input = _ref5.input,
|
|
1785
|
+
current = _ref5.current;
|
|
1786
|
+
var actual = getActualDropTargets({
|
|
1787
|
+
source: source,
|
|
1788
|
+
target: target,
|
|
1789
|
+
input: input
|
|
1790
|
+
});
|
|
1791
|
+
|
|
1792
|
+
// stickiness is only relevant when we have less
|
|
1793
|
+
// drop targets than we did before
|
|
1794
|
+
if (actual.length >= current.length) {
|
|
1795
|
+
return actual;
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
// less 'actual' drop targets than before,
|
|
1799
|
+
// we need to see if 'stickiness' applies
|
|
1800
|
+
|
|
1801
|
+
// An old drop target will continue to be dropped on if:
|
|
1802
|
+
// 1. it has the same parent
|
|
1803
|
+
// 2. nothing exists in it's previous index
|
|
1804
|
+
|
|
1805
|
+
var lastCaptureOrdered = copyReverse(current);
|
|
1806
|
+
var actualCaptureOrdered = copyReverse(actual);
|
|
1807
|
+
var resultCaptureOrdered = [];
|
|
1808
|
+
for (var index = 0; index < lastCaptureOrdered.length; index++) {
|
|
1809
|
+
var _argsForLast$getIsSti;
|
|
1810
|
+
var last = lastCaptureOrdered[index];
|
|
1811
|
+
var fresh = actualCaptureOrdered[index];
|
|
1812
|
+
|
|
1813
|
+
// if a record is in the new index -> use that
|
|
1814
|
+
// it will have the latest data + dropEffect
|
|
1815
|
+
if (fresh != null) {
|
|
1816
|
+
resultCaptureOrdered.push(fresh);
|
|
1817
|
+
continue;
|
|
1818
|
+
}
|
|
1819
|
+
|
|
1820
|
+
// At this point we have no drop target in the old spot
|
|
1821
|
+
// Check to see if we can use a previous sticky drop target
|
|
1822
|
+
|
|
1823
|
+
// The "parent" is the one inside of `resultCaptureOrdered`
|
|
1824
|
+
// (the parent might be a drop target that was sticky)
|
|
1825
|
+
var parent = resultCaptureOrdered[index - 1];
|
|
1826
|
+
var lastParent = lastCaptureOrdered[index - 1];
|
|
1827
|
+
|
|
1828
|
+
// Stickiness is based on parent relationships, so if the parent relationship has change
|
|
1829
|
+
// then we can stop our search
|
|
1830
|
+
if ((parent === null || parent === void 0 ? void 0 : parent.element) !== (lastParent === null || lastParent === void 0 ? void 0 : lastParent.element)) {
|
|
1831
|
+
break;
|
|
1832
|
+
}
|
|
1833
|
+
|
|
1834
|
+
// We need to check whether the old drop target can still be dropped on
|
|
1835
|
+
|
|
1836
|
+
var argsForLast = registry.get(last.element);
|
|
1837
|
+
|
|
1838
|
+
// We cannot drop on a drop target that is no longer mounted
|
|
1839
|
+
if (!argsForLast) {
|
|
1840
|
+
break;
|
|
1841
|
+
}
|
|
1842
|
+
var feedback = {
|
|
1843
|
+
input: input,
|
|
1844
|
+
source: source,
|
|
1845
|
+
element: argsForLast.element
|
|
1846
|
+
};
|
|
1847
|
+
|
|
1848
|
+
// We cannot drop on a drop target that no longer allows being dropped on
|
|
1849
|
+
if (argsForLast.canDrop && !argsForLast.canDrop(feedback)) {
|
|
1850
|
+
break;
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
// We cannot drop on a drop target that is no longer sticky
|
|
1854
|
+
if (!((_argsForLast$getIsSti = argsForLast.getIsSticky) !== null && _argsForLast$getIsSti !== void 0 && _argsForLast$getIsSti.call(argsForLast, feedback))) {
|
|
1855
|
+
break;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
// Note: intentionally not recollecting `getData()` or `getDropEffect()`
|
|
1859
|
+
// Previous values for `data` and `dropEffect` will be borrowed
|
|
1860
|
+
// This is to prevent things like the 'closest edge' changing when
|
|
1861
|
+
// no longer over a drop target.
|
|
1862
|
+
// We could change our mind on this behaviour in the future
|
|
1863
|
+
|
|
1864
|
+
resultCaptureOrdered.push(_objectSpread$1(_objectSpread$1({}, last), {}, {
|
|
1865
|
+
// making it clear to consumers this drop target is active due to stickiness
|
|
1866
|
+
isActiveDueToStickiness: true
|
|
1867
|
+
}));
|
|
1868
|
+
}
|
|
1869
|
+
|
|
1870
|
+
// return bubble ordered result
|
|
1871
|
+
return copyReverse(resultCaptureOrdered);
|
|
1872
|
+
}
|
|
1873
|
+
return {
|
|
1874
|
+
dropTargetForConsumers: dropTargetForConsumers,
|
|
1875
|
+
getIsOver: getIsOver,
|
|
1876
|
+
dispatchEvent: dispatchEvent
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
|
|
1881
|
+
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
|
|
1882
|
+
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
|
|
1883
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
1884
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
1885
|
+
function makeMonitor() {
|
|
1886
|
+
var registry = new Set();
|
|
1887
|
+
var dragging = null;
|
|
1888
|
+
function tryAddToActive(monitor) {
|
|
1889
|
+
if (!dragging) {
|
|
1890
|
+
return;
|
|
1891
|
+
}
|
|
1892
|
+
// Monitor is allowed to monitor events if:
|
|
1893
|
+
// 1. It has no `canMonitor` function (default is that a monitor can listen to everything)
|
|
1894
|
+
// 2. `canMonitor` returns true
|
|
1895
|
+
if (!monitor.canMonitor || monitor.canMonitor(dragging.canMonitorArgs)) {
|
|
1896
|
+
dragging.active.add(monitor);
|
|
1897
|
+
}
|
|
1898
|
+
}
|
|
1899
|
+
function monitorForConsumers(args) {
|
|
1900
|
+
// We are giving each `args` a new reference so that you
|
|
1901
|
+
// can create multiple monitors with the same `args`.
|
|
1902
|
+
var entry = _objectSpread({}, args);
|
|
1903
|
+
registry.add(entry);
|
|
1904
|
+
|
|
1905
|
+
// if there is an active drag we need to see if this new monitor is relevant
|
|
1906
|
+
tryAddToActive(entry);
|
|
1907
|
+
return function cleanup() {
|
|
1908
|
+
registry.delete(entry);
|
|
1909
|
+
|
|
1910
|
+
// We need to stop publishing events during a drag to this monitor!
|
|
1911
|
+
if (dragging) {
|
|
1912
|
+
dragging.active.delete(entry);
|
|
1913
|
+
}
|
|
1914
|
+
};
|
|
1915
|
+
}
|
|
1916
|
+
function dispatchEvent(_ref) {
|
|
1917
|
+
var eventName = _ref.eventName,
|
|
1918
|
+
payload = _ref.payload;
|
|
1919
|
+
if (eventName === 'onGenerateDragPreview') {
|
|
1920
|
+
dragging = {
|
|
1921
|
+
canMonitorArgs: {
|
|
1922
|
+
initial: payload.location.initial,
|
|
1923
|
+
source: payload.source
|
|
1924
|
+
},
|
|
1925
|
+
active: new Set()
|
|
1926
|
+
};
|
|
1927
|
+
var _iterator = _createForOfIteratorHelper(registry),
|
|
1928
|
+
_step;
|
|
1929
|
+
try {
|
|
1930
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
1931
|
+
var monitor = _step.value;
|
|
1932
|
+
tryAddToActive(monitor);
|
|
1933
|
+
}
|
|
1934
|
+
} catch (err) {
|
|
1935
|
+
_iterator.e(err);
|
|
1936
|
+
} finally {
|
|
1937
|
+
_iterator.f();
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
// This should never happen.
|
|
1942
|
+
if (!dragging) {
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
|
|
1946
|
+
// Creating an array from the set _before_ iterating
|
|
1947
|
+
// This is so that monitors added during the current event will not be called.
|
|
1948
|
+
// This behaviour matches native EventTargets where an event listener
|
|
1949
|
+
// cannot add another event listener during an active event to the same
|
|
1950
|
+
// event target in the same event (for us we have a single global event target)
|
|
1951
|
+
var active = Array.from(dragging.active);
|
|
1952
|
+
for (var _i = 0, _active = active; _i < _active.length; _i++) {
|
|
1953
|
+
var _monitor = _active[_i];
|
|
1954
|
+
// A monitor can be removed by another monitor during an event.
|
|
1955
|
+
// We need to check that the monitor is still registered before calling it
|
|
1956
|
+
if (dragging.active.has(_monitor)) {
|
|
1957
|
+
var _monitor$eventName;
|
|
1958
|
+
// @ts-expect-error: I cannot get this type working!
|
|
1959
|
+
(_monitor$eventName = _monitor[eventName]) === null || _monitor$eventName === void 0 || _monitor$eventName.call(_monitor, payload);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
if (eventName === 'onDrop') {
|
|
1963
|
+
dragging.active.clear();
|
|
1964
|
+
dragging = null;
|
|
1965
|
+
}
|
|
1966
|
+
}
|
|
1967
|
+
return {
|
|
1968
|
+
dispatchEvent: dispatchEvent,
|
|
1969
|
+
monitorForConsumers: monitorForConsumers
|
|
1970
|
+
};
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1973
|
+
function makeAdapter(_ref) {
|
|
1974
|
+
var typeKey = _ref.typeKey,
|
|
1975
|
+
mount = _ref.mount,
|
|
1976
|
+
dispatchEventToSource = _ref.dispatchEventToSource,
|
|
1977
|
+
onPostDispatch = _ref.onPostDispatch,
|
|
1978
|
+
defaultDropEffect = _ref.defaultDropEffect;
|
|
1979
|
+
var monitorAPI = makeMonitor();
|
|
1980
|
+
var dropTargetAPI = makeDropTarget({
|
|
1981
|
+
typeKey: typeKey,
|
|
1982
|
+
defaultDropEffect: defaultDropEffect
|
|
1983
|
+
});
|
|
1984
|
+
function dispatchEvent(args) {
|
|
1985
|
+
// 1. forward the event to source
|
|
1986
|
+
dispatchEventToSource === null || dispatchEventToSource === void 0 || dispatchEventToSource(args);
|
|
1987
|
+
|
|
1988
|
+
// 2. forward the event to relevant dropTargets
|
|
1989
|
+
dropTargetAPI.dispatchEvent(args);
|
|
1990
|
+
|
|
1991
|
+
// 3. forward event to monitors
|
|
1992
|
+
monitorAPI.dispatchEvent(args);
|
|
1993
|
+
|
|
1994
|
+
// 4. post consumer dispatch (used for honey pot fix)
|
|
1995
|
+
onPostDispatch === null || onPostDispatch === void 0 || onPostDispatch(args);
|
|
1996
|
+
}
|
|
1997
|
+
function start(_ref2) {
|
|
1998
|
+
var event = _ref2.event,
|
|
1999
|
+
dragType = _ref2.dragType;
|
|
2000
|
+
lifecycle.start({
|
|
2001
|
+
event: event,
|
|
2002
|
+
dragType: dragType,
|
|
2003
|
+
getDropTargetsOver: dropTargetAPI.getIsOver,
|
|
2004
|
+
dispatchEvent: dispatchEvent
|
|
2005
|
+
});
|
|
2006
|
+
}
|
|
2007
|
+
function registerUsage() {
|
|
2008
|
+
function mountAdapter() {
|
|
2009
|
+
var api = {
|
|
2010
|
+
canStart: lifecycle.canStart,
|
|
2011
|
+
start: start
|
|
2012
|
+
};
|
|
2013
|
+
return mount(api);
|
|
2014
|
+
}
|
|
2015
|
+
return register({
|
|
2016
|
+
typeKey: typeKey,
|
|
2017
|
+
mount: mountAdapter
|
|
2018
|
+
});
|
|
2019
|
+
}
|
|
2020
|
+
return {
|
|
2021
|
+
registerUsage: registerUsage,
|
|
2022
|
+
dropTarget: dropTargetAPI.dropTargetForConsumers,
|
|
2023
|
+
monitor: monitorAPI.monitorForConsumers
|
|
2024
|
+
};
|
|
2025
|
+
}
|
|
2026
|
+
|
|
2027
|
+
// using `cache` as our `isAndroid()` result will not change in a browser
|
|
2028
|
+
var isAndroid = once(function isAndroid() {
|
|
2029
|
+
return navigator.userAgent.toLocaleLowerCase().includes('android');
|
|
2030
|
+
});
|
|
2031
|
+
var androidFallbackText = 'pdnd:android-fallback';
|
|
2032
|
+
|
|
2033
|
+
// Why we put the media types in their own files:
|
|
2034
|
+
//
|
|
2035
|
+
// - we are not putting them all in one file as not all adapters need all types
|
|
2036
|
+
// - we are not putting them in the external helpers as some things just need the
|
|
2037
|
+
// types and not the external functions code
|
|
2038
|
+
var textMediaType = 'text/plain';
|
|
2039
|
+
|
|
2040
|
+
// Why we put the media types in their own files:
|
|
2041
|
+
//
|
|
2042
|
+
// - we are not putting them all in one file as not all adapters need all types
|
|
2043
|
+
// - we are not putting them in the external helpers as some things just need the
|
|
2044
|
+
// types and not the external functions code
|
|
2045
|
+
var URLMediaType = 'text/uri-list';
|
|
2046
|
+
|
|
2047
|
+
/**
|
|
2048
|
+
* This key has been pulled into a separate module
|
|
2049
|
+
* so that the external adapter does not need to import
|
|
2050
|
+
* the element adapter
|
|
2051
|
+
*/
|
|
2052
|
+
var elementAdapterNativeDataKey = 'application/vnd.pdnd';
|
|
2053
|
+
|
|
2054
|
+
var draggableRegistry = new WeakMap();
|
|
2055
|
+
function addToRegistry(args) {
|
|
2056
|
+
draggableRegistry.set(args.element, args);
|
|
2057
|
+
return function cleanup() {
|
|
2058
|
+
draggableRegistry.delete(args.element);
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
var honeyPotFix = makeHoneyPotFix();
|
|
2062
|
+
var adapter$1 = makeAdapter({
|
|
2063
|
+
typeKey: 'element',
|
|
2064
|
+
defaultDropEffect: 'move',
|
|
2065
|
+
mount: function mount(api) {
|
|
2066
|
+
/** Binding event listeners the `document` rather than `window` so that
|
|
2067
|
+
* this adapter always gets preference over the text adapter.
|
|
2068
|
+
* `document` is the first `EventTarget` under `window`
|
|
2069
|
+
* https://twitter.com/alexandereardon/status/1604658588311465985
|
|
2070
|
+
*/
|
|
2071
|
+
return combine(honeyPotFix.bindEvents(), bind(document, {
|
|
2072
|
+
type: 'dragstart',
|
|
2073
|
+
listener: function listener(event) {
|
|
2074
|
+
var _entry$dragHandle, _entry$getInitialData, _entry$getInitialData2, _entry$dragHandle2, _entry$getInitialData3, _entry$getInitialData4;
|
|
2075
|
+
if (!api.canStart(event)) {
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
|
|
2079
|
+
// If the "dragstart" event is cancelled, then a drag won't start
|
|
2080
|
+
// There will be no further drag operation events (eg no "dragend" event)
|
|
2081
|
+
if (event.defaultPrevented) {
|
|
2082
|
+
return;
|
|
2083
|
+
}
|
|
2084
|
+
|
|
2085
|
+
// Technically `dataTransfer` can be `null` according to the types
|
|
2086
|
+
// But that behaviour does not seem to appear in the spec.
|
|
2087
|
+
// If there is not `dataTransfer`, we can assume something is wrong and not
|
|
2088
|
+
// start a drag
|
|
2089
|
+
if (!event.dataTransfer) {
|
|
2090
|
+
// Including this code on "test" and "development" environments:
|
|
2091
|
+
// - Browser tests commonly run against "development" builds
|
|
2092
|
+
// - Unit tests commonly run in "test"
|
|
2093
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2094
|
+
// eslint-disable-next-line no-console
|
|
2095
|
+
console.warn("\n It appears as though you have are not testing DragEvents correctly.\n\n - If you are unit testing, ensure you have polyfilled DragEvent.\n - If you are browser testing, ensure you are dispatching drag events correctly.\n\n Please see our testing guides for more information:\n https://atlassian.design/components/pragmatic-drag-and-drop/core-package/testing\n ".replace(/ {2}/g, ''));
|
|
2096
|
+
}
|
|
2097
|
+
return;
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
// the closest parent that is a draggable element will be marked as
|
|
2101
|
+
// the `event.target` for the event
|
|
2102
|
+
var target = event.target;
|
|
2103
|
+
|
|
2104
|
+
// this source is only for elements
|
|
2105
|
+
// Note: only HTMLElements can have the "draggable" attribute
|
|
2106
|
+
if (!(target instanceof HTMLElement)) {
|
|
2107
|
+
return null;
|
|
2108
|
+
}
|
|
2109
|
+
|
|
2110
|
+
// see if the thing being dragged is owned by us
|
|
2111
|
+
var entry = draggableRegistry.get(target);
|
|
2112
|
+
|
|
2113
|
+
// no matching element found
|
|
2114
|
+
// → dragging an element with `draggable="true"` that is not controlled by us
|
|
2115
|
+
if (!entry) {
|
|
2116
|
+
return null;
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
/**
|
|
2120
|
+
* A text selection drag _can_ have the `draggable` element be
|
|
2121
|
+
* the `event.target` if the user is dragging the text selection
|
|
2122
|
+
* from the `draggable`.
|
|
2123
|
+
*
|
|
2124
|
+
* To know if the `draggable` is being dragged, we look at whether any
|
|
2125
|
+
* `"text/plain"` data is being dragged. If it is, then a text selection
|
|
2126
|
+
* drag is occurring.
|
|
2127
|
+
*
|
|
2128
|
+
* This behaviour has been validated on:
|
|
2129
|
+
*
|
|
2130
|
+
* - Chrome@128 on Android@14
|
|
2131
|
+
* - Chrome@128 on iOS@17.6.1
|
|
2132
|
+
* - Chrome@128 on Windows@11
|
|
2133
|
+
* - Chrome@128 on MacOS@14.6.1
|
|
2134
|
+
* - Firefox@129 on Windows@11 (not possible for user to select text in a draggable)
|
|
2135
|
+
* - Firefox@129 on MacOS@14.6.1 (not possible for user to select text in a draggable)
|
|
2136
|
+
*
|
|
2137
|
+
* Note: Could usually just use: `event.dataTransfer.types.includes(textMediaType)`
|
|
2138
|
+
* but unfortunately ProseMirror is always setting `""` as the dragged text
|
|
2139
|
+
*
|
|
2140
|
+
* Note: Unfortunately editor is (heavily) leaning on the current functionality today
|
|
2141
|
+
* and unwinding it will be a decent amount of effort. So for now, a text selection
|
|
2142
|
+
* where the `event.target` is a `draggable` element will still trigger the
|
|
2143
|
+
* element adapter.
|
|
2144
|
+
*
|
|
2145
|
+
* // Future state:
|
|
2146
|
+
* if(event.dataTransfer.getData(textMediaType)) {
|
|
2147
|
+
* return;
|
|
2148
|
+
* }
|
|
2149
|
+
*
|
|
2150
|
+
*/
|
|
2151
|
+
|
|
2152
|
+
var input = getInput(event);
|
|
2153
|
+
var feedback = {
|
|
2154
|
+
element: entry.element,
|
|
2155
|
+
dragHandle: (_entry$dragHandle = entry.dragHandle) !== null && _entry$dragHandle !== void 0 ? _entry$dragHandle : null,
|
|
2156
|
+
input: input
|
|
2157
|
+
};
|
|
2158
|
+
|
|
2159
|
+
// Check: does the draggable want to allow dragging?
|
|
2160
|
+
if (entry.canDrag && !entry.canDrag(feedback)) {
|
|
2161
|
+
// cancel drag operation if we cannot drag
|
|
2162
|
+
event.preventDefault();
|
|
2163
|
+
return null;
|
|
2164
|
+
}
|
|
2165
|
+
|
|
2166
|
+
// Check: is there a drag handle and is the user using it?
|
|
2167
|
+
if (entry.dragHandle) {
|
|
2168
|
+
// technically don't need this util, but just being
|
|
2169
|
+
// consistent with how we look up what is under the users
|
|
2170
|
+
// cursor.
|
|
2171
|
+
var over = getElementFromPointWithoutHoneypot({
|
|
2172
|
+
x: input.clientX,
|
|
2173
|
+
y: input.clientY
|
|
2174
|
+
});
|
|
2175
|
+
|
|
2176
|
+
// if we are not dragging from the drag handle (or something inside the drag handle)
|
|
2177
|
+
// then we will cancel the active drag
|
|
2178
|
+
if (!entry.dragHandle.contains(over)) {
|
|
2179
|
+
event.preventDefault();
|
|
2180
|
+
return null;
|
|
2181
|
+
}
|
|
2182
|
+
}
|
|
2183
|
+
|
|
2184
|
+
/**
|
|
2185
|
+
* **Goal**
|
|
2186
|
+
* Pass information to other applications
|
|
2187
|
+
*
|
|
2188
|
+
* **Approach**
|
|
2189
|
+
* Put data into the native data store
|
|
2190
|
+
*
|
|
2191
|
+
* **What about the native adapter?**
|
|
2192
|
+
* When the element adapter puts native data into the native data store
|
|
2193
|
+
* the native adapter is not triggered in the current window,
|
|
2194
|
+
* but a native adapter in an external window _can_ be triggered
|
|
2195
|
+
*
|
|
2196
|
+
* **Why bake this into core?**
|
|
2197
|
+
* This functionality could be pulled out and exposed inside of
|
|
2198
|
+
* `onGenerateDragPreview`. But decided to make it a part of the
|
|
2199
|
+
* base API as it felt like a common enough use case and ended
|
|
2200
|
+
* up being a similar amount of code to include this function as
|
|
2201
|
+
* it was to expose the hook for it
|
|
2202
|
+
*/
|
|
2203
|
+
var nativeData = (_entry$getInitialData = (_entry$getInitialData2 = entry.getInitialDataForExternal) === null || _entry$getInitialData2 === void 0 ? void 0 : _entry$getInitialData2.call(entry, feedback)) !== null && _entry$getInitialData !== void 0 ? _entry$getInitialData : null;
|
|
2204
|
+
if (nativeData) {
|
|
2205
|
+
for (var _i = 0, _Object$entries = Object.entries(nativeData); _i < _Object$entries.length; _i++) {
|
|
2206
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i], 2),
|
|
2207
|
+
key = _Object$entries$_i[0],
|
|
2208
|
+
data = _Object$entries$_i[1];
|
|
2209
|
+
event.dataTransfer.setData(key, data !== null && data !== void 0 ? data : '');
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
/**
|
|
2214
|
+
* 📱 For Android devices, a drag operation will not start unless
|
|
2215
|
+
* "text/plain" or "text/uri-list" data exists in the native data store
|
|
2216
|
+
* https://twitter.com/alexandereardon/status/1732189803754713424
|
|
2217
|
+
*
|
|
2218
|
+
* Tested on:
|
|
2219
|
+
* Device: Google Pixel 5
|
|
2220
|
+
* Android version: 14 (November 5, 2023)
|
|
2221
|
+
* Chrome version: 120.0
|
|
2222
|
+
*/
|
|
2223
|
+
if (isAndroid() && !event.dataTransfer.types.includes(textMediaType) && !event.dataTransfer.types.includes(URLMediaType)) {
|
|
2224
|
+
event.dataTransfer.setData(textMediaType, androidFallbackText);
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
/**
|
|
2228
|
+
* 1. Must set any media type for `iOS15` to work
|
|
2229
|
+
* 2. We are also doing adding data so that the native adapter
|
|
2230
|
+
* can know that the element adapter has handled this drag
|
|
2231
|
+
*
|
|
2232
|
+
* We used to wrap this `setData()` in a `try/catch` for Firefox,
|
|
2233
|
+
* but it looks like that was not needed.
|
|
2234
|
+
*
|
|
2235
|
+
* Tested using: https://codesandbox.io/s/checking-firefox-throw-behaviour-on-dragstart-qt8h4f
|
|
2236
|
+
*
|
|
2237
|
+
* - ✅ Firefox@70.0 (Oct 2019) on macOS Sonoma
|
|
2238
|
+
* - ✅ Firefox@70.0 (Oct 2019) on macOS Big Sur
|
|
2239
|
+
* - ✅ Firefox@70.0 (Oct 2019) on Windows 10
|
|
2240
|
+
*
|
|
2241
|
+
* // just checking a few more combinations to be super safe
|
|
2242
|
+
*
|
|
2243
|
+
* - ✅ Chrome@78 (Oct 2019) on macOS Big Sur
|
|
2244
|
+
* - ✅ Chrome@78 (Oct 2019) on Windows 10
|
|
2245
|
+
* - ✅ Safari@14.1 on macOS Big Sur
|
|
2246
|
+
*/
|
|
2247
|
+
event.dataTransfer.setData(elementAdapterNativeDataKey, '');
|
|
2248
|
+
var payload = {
|
|
2249
|
+
element: entry.element,
|
|
2250
|
+
dragHandle: (_entry$dragHandle2 = entry.dragHandle) !== null && _entry$dragHandle2 !== void 0 ? _entry$dragHandle2 : null,
|
|
2251
|
+
data: (_entry$getInitialData3 = (_entry$getInitialData4 = entry.getInitialData) === null || _entry$getInitialData4 === void 0 ? void 0 : _entry$getInitialData4.call(entry, feedback)) !== null && _entry$getInitialData3 !== void 0 ? _entry$getInitialData3 : {}
|
|
2252
|
+
};
|
|
2253
|
+
var dragType = {
|
|
2254
|
+
type: 'element',
|
|
2255
|
+
payload: payload,
|
|
2256
|
+
startedFrom: 'internal'
|
|
2257
|
+
};
|
|
2258
|
+
api.start({
|
|
2259
|
+
event: event,
|
|
2260
|
+
dragType: dragType
|
|
2261
|
+
});
|
|
2262
|
+
}
|
|
2263
|
+
}));
|
|
2264
|
+
},
|
|
2265
|
+
dispatchEventToSource: function dispatchEventToSource(_ref) {
|
|
2266
|
+
var _draggableRegistry$ge, _draggableRegistry$ge2;
|
|
2267
|
+
var eventName = _ref.eventName,
|
|
2268
|
+
payload = _ref.payload;
|
|
2269
|
+
// During a drag operation, a draggable can be:
|
|
2270
|
+
// - remounted with different functions
|
|
2271
|
+
// - removed completely
|
|
2272
|
+
// So we need to get the latest entry from the registry in order
|
|
2273
|
+
// to call the latest event functions
|
|
2274
|
+
|
|
2275
|
+
(_draggableRegistry$ge = draggableRegistry.get(payload.source.element)) === null || _draggableRegistry$ge === void 0 || (_draggableRegistry$ge2 = _draggableRegistry$ge[eventName]) === null || _draggableRegistry$ge2 === void 0 || _draggableRegistry$ge2.call(_draggableRegistry$ge,
|
|
2276
|
+
// I cannot seem to get the types right here.
|
|
2277
|
+
// TS doesn't seem to like that one event can need `nativeSetDragImage`
|
|
2278
|
+
// @ts-expect-error
|
|
2279
|
+
payload);
|
|
2280
|
+
},
|
|
2281
|
+
onPostDispatch: honeyPotFix.getOnPostDispatch()
|
|
2282
|
+
});
|
|
2283
|
+
var dropTargetForElements = adapter$1.dropTarget;
|
|
2284
|
+
var monitorForElements = adapter$1.monitor;
|
|
2285
|
+
function draggable(args) {
|
|
2286
|
+
// Guardrail: warn if the drag handle is not contained in draggable element
|
|
2287
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2288
|
+
if (args.dragHandle && !args.element.contains(args.dragHandle)) {
|
|
2289
|
+
// eslint-disable-next-line no-console
|
|
2290
|
+
console.warn('Drag handle element must be contained in draggable element', {
|
|
2291
|
+
element: args.element,
|
|
2292
|
+
dragHandle: args.dragHandle
|
|
2293
|
+
});
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
// Guardrail: warn if the draggable element is already registered
|
|
2297
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
2298
|
+
var existing = draggableRegistry.get(args.element);
|
|
2299
|
+
if (existing) {
|
|
2300
|
+
// eslint-disable-next-line no-console
|
|
2301
|
+
console.warn('You have already registered a `draggable` on the same element', {
|
|
2302
|
+
existing: existing,
|
|
2303
|
+
proposed: args
|
|
2304
|
+
});
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
return combine(
|
|
2308
|
+
// making the draggable register the adapter rather than drop targets
|
|
2309
|
+
// this is because you *must* have a draggable element to start a drag
|
|
2310
|
+
// but you _might_ not have any drop targets immediately
|
|
2311
|
+
// (You might create drop targets async)
|
|
2312
|
+
adapter$1.registerUsage(), addToRegistry(args), addAttribute(args.element, {
|
|
2313
|
+
attribute: 'draggable',
|
|
2314
|
+
value: 'true'
|
|
2315
|
+
}));
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
/** Common event payload for all events */
|
|
2319
|
+
|
|
2320
|
+
/** A map containing payloads for all events */
|
|
2321
|
+
|
|
2322
|
+
/** Common event payload for all drop target events */
|
|
2323
|
+
|
|
2324
|
+
/** A map containing payloads for all events on drop targets */
|
|
2325
|
+
|
|
2326
|
+
/** Arguments given to all feedback functions (eg `canDrag()`) on for a `draggable()` */
|
|
2327
|
+
|
|
2328
|
+
/** Arguments given to all feedback functions (eg `canDrop()`) on a `dropTargetForElements()` */
|
|
2329
|
+
|
|
2330
|
+
/** Arguments given to all monitor feedback functions (eg `canMonitor()`) for a `monitorForElements` */
|
|
2331
|
+
|
|
441
2332
|
const CheckboxCard = React.forwardRef(function CheckboxCard(props, ref) {
|
|
442
2333
|
const { inputProps, label, description, icon, addon, indicator = jsx(CheckboxCard$1.Indicator, {}), indicatorPlacement = "end", ...rest } = props;
|
|
443
2334
|
const hasContent = label || description || icon;
|
|
@@ -694,11 +2585,12 @@ const snakeToLabel = (str) => {
|
|
|
694
2585
|
};
|
|
695
2586
|
|
|
696
2587
|
const RecordDisplay = ({ object, boxProps }) => {
|
|
2588
|
+
console.log(object, "dkfos");
|
|
697
2589
|
if (object === null) {
|
|
698
2590
|
return jsx(Fragment, { children: "null" });
|
|
699
2591
|
}
|
|
700
|
-
return (jsx(Grid, { rowGap: 1, overflow: "auto", ...boxProps, children: Object.entries(object).map(([field, value]) => {
|
|
701
|
-
return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: "auto 1fr", children: [jsx(Text, { color: "gray.400", children: snakeToLabel(field) }), jsx(
|
|
2592
|
+
return (jsx(Grid, { rowGap: 1, padding: 1, overflow: "auto", ...boxProps, children: Object.entries(object).map(([field, value]) => {
|
|
2593
|
+
return (jsxs(Grid, { columnGap: 2, gridTemplateColumns: "auto 1fr", children: [jsx(Text, { color: "gray.400", children: snakeToLabel(field) }), typeof value === "object" ? (jsx(RecordDisplay, { object: value })) : (jsx(Text, { children: JSON.stringify(value) }))] }, field));
|
|
702
2594
|
}) }));
|
|
703
2595
|
};
|
|
704
2596
|
|
|
@@ -2161,6 +4053,309 @@ const TagPicker = ({ column }) => {
|
|
|
2161
4053
|
}), errors[`${column}`] && (jsx(Text, { color: "red.400", children: (errors[`${column}`]?.message ?? "No error message") }))] }));
|
|
2162
4054
|
};
|
|
2163
4055
|
|
|
4056
|
+
function isEnteringWindow(_ref) {
|
|
4057
|
+
var dragEnter = _ref.dragEnter;
|
|
4058
|
+
var type = dragEnter.type,
|
|
4059
|
+
relatedTarget = dragEnter.relatedTarget;
|
|
4060
|
+
if (type !== 'dragenter') {
|
|
4061
|
+
return false;
|
|
4062
|
+
}
|
|
4063
|
+
if (isSafari()) {
|
|
4064
|
+
return isEnteringWindowInSafari({
|
|
4065
|
+
dragEnter: dragEnter
|
|
4066
|
+
});
|
|
4067
|
+
}
|
|
4068
|
+
|
|
4069
|
+
// standard check
|
|
4070
|
+
if (relatedTarget == null) {
|
|
4071
|
+
return true;
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
/**
|
|
4075
|
+
* 🦊 Exception: `iframe` in Firefox (`125.0`)
|
|
4076
|
+
*
|
|
4077
|
+
* Case 1: parent `window` → child `iframe`
|
|
4078
|
+
* `relatedTarget` is the `iframe` element in the parent `window`
|
|
4079
|
+
* (foreign element)
|
|
4080
|
+
*
|
|
4081
|
+
* Case 2: child `iframe` → parent `window`
|
|
4082
|
+
* `relatedTarget` is an element inside the child `iframe`
|
|
4083
|
+
* (foreign element)
|
|
4084
|
+
*/
|
|
4085
|
+
|
|
4086
|
+
if (isFirefox()) {
|
|
4087
|
+
return isFromAnotherWindow(relatedTarget);
|
|
4088
|
+
}
|
|
4089
|
+
|
|
4090
|
+
/**
|
|
4091
|
+
* 🌏 Exception: `iframe` in Chrome (`124.0`)
|
|
4092
|
+
*
|
|
4093
|
+
* Case 1: parent `window` → child `iframe`
|
|
4094
|
+
* `relatedTarget` is `null` *(standard check)*
|
|
4095
|
+
*
|
|
4096
|
+
* Case 2: child `iframe` → parent `window`
|
|
4097
|
+
* `relatedTarget` is the `iframe` element in the parent `window`
|
|
4098
|
+
*/
|
|
4099
|
+
|
|
4100
|
+
// Case 2
|
|
4101
|
+
// Using `instanceof` check as the element will be in the same `window`
|
|
4102
|
+
return relatedTarget instanceof HTMLIFrameElement;
|
|
4103
|
+
}
|
|
4104
|
+
|
|
4105
|
+
function isAnAvailableType(_ref) {
|
|
4106
|
+
var type = _ref.type,
|
|
4107
|
+
value = _ref.value;
|
|
4108
|
+
// We don't want to expose our private elementAdapter key / value
|
|
4109
|
+
if (type === elementAdapterNativeDataKey) {
|
|
4110
|
+
return false;
|
|
4111
|
+
}
|
|
4112
|
+
// Not exposing "text/plain" if it contains the android fallback text
|
|
4113
|
+
// We _could_ add an `isAndroid()` check, but it's probably safest
|
|
4114
|
+
// to trim this data out, regardless of what OS we see it on.
|
|
4115
|
+
if (type === textMediaType && value === androidFallbackText) {
|
|
4116
|
+
return false;
|
|
4117
|
+
}
|
|
4118
|
+
return true;
|
|
4119
|
+
}
|
|
4120
|
+
function getAvailableTypes(transfer) {
|
|
4121
|
+
return Array.from(transfer.types).filter(function (type) {
|
|
4122
|
+
return isAnAvailableType({
|
|
4123
|
+
type: type,
|
|
4124
|
+
value: transfer.getData(type)
|
|
4125
|
+
});
|
|
4126
|
+
});
|
|
4127
|
+
}
|
|
4128
|
+
function getAvailableItems(dataTransfer) {
|
|
4129
|
+
// item.kind is 'string' | 'file'
|
|
4130
|
+
// For 'string' item.type is the mimeType (eg 'text/plain')
|
|
4131
|
+
// For 'file' item.type is the file type (eg 'image/jpg')
|
|
4132
|
+
|
|
4133
|
+
return Array.from(dataTransfer.items).filter(function (item) {
|
|
4134
|
+
return item.kind === 'file' || isAnAvailableType({
|
|
4135
|
+
type: item.type,
|
|
4136
|
+
value: dataTransfer.getData(item.type)
|
|
4137
|
+
});
|
|
4138
|
+
});
|
|
4139
|
+
}
|
|
4140
|
+
var didDragStartLocally = false;
|
|
4141
|
+
var adapter = makeAdapter({
|
|
4142
|
+
typeKey: 'external',
|
|
4143
|
+
// for external drags, we are generally making a copy of something that is being dragged
|
|
4144
|
+
defaultDropEffect: 'copy',
|
|
4145
|
+
mount: function mount(api) {
|
|
4146
|
+
// Binding to the `window` so that the element adapter
|
|
4147
|
+
// has a chance to get in first on the`document`.
|
|
4148
|
+
// We are giving preference to the element adapter.
|
|
4149
|
+
return bind(window, {
|
|
4150
|
+
type: 'dragenter',
|
|
4151
|
+
listener: function listener(event) {
|
|
4152
|
+
// drag operation was started within the document, it won't be an "external" drag
|
|
4153
|
+
if (didDragStartLocally) {
|
|
4154
|
+
return;
|
|
4155
|
+
}
|
|
4156
|
+
|
|
4157
|
+
// Note: not checking if event was cancelled (`event.defaultPrevented`) as
|
|
4158
|
+
// cancelling a "dragenter" accepts the drag operation (not prevent it)
|
|
4159
|
+
|
|
4160
|
+
// Something has gone wrong with our drag event
|
|
4161
|
+
if (!event.dataTransfer) {
|
|
4162
|
+
// Including this code on "test" and "development" environments:
|
|
4163
|
+
// - Browser tests commonly run against "development" builds
|
|
4164
|
+
// - Unit tests commonly run in "test"
|
|
4165
|
+
if (process.env.NODE_ENV !== 'production') {
|
|
4166
|
+
// eslint-disable-next-line no-console
|
|
4167
|
+
console.warn("\n It appears as though you have are not testing DragEvents correctly.\n\n - If you are unit testing, ensure you have polyfilled DragEvent.\n - If you are browser testing, ensure you are dispatching drag events correctly.\n\n Please see our testing guides for more information:\n https://atlassian.design/components/pragmatic-drag-and-drop/core-package/testing\n ".replace(/ {2}/g, ''));
|
|
4168
|
+
}
|
|
4169
|
+
return;
|
|
4170
|
+
}
|
|
4171
|
+
if (!api.canStart(event)) {
|
|
4172
|
+
return;
|
|
4173
|
+
}
|
|
4174
|
+
if (!isEnteringWindow({
|
|
4175
|
+
dragEnter: event
|
|
4176
|
+
})) {
|
|
4177
|
+
return;
|
|
4178
|
+
}
|
|
4179
|
+
|
|
4180
|
+
// Note: not checking types for `elementAdapterNativeDataKey` as we expect to see that
|
|
4181
|
+
// key when pdnd started the drag in another document
|
|
4182
|
+
var types = getAvailableTypes(event.dataTransfer);
|
|
4183
|
+
if (!types.length) {
|
|
4184
|
+
return;
|
|
4185
|
+
}
|
|
4186
|
+
var locked = {
|
|
4187
|
+
types: types,
|
|
4188
|
+
items: [],
|
|
4189
|
+
getStringData: function getStringData() {
|
|
4190
|
+
return null;
|
|
4191
|
+
}
|
|
4192
|
+
};
|
|
4193
|
+
api.start({
|
|
4194
|
+
event: event,
|
|
4195
|
+
dragType: {
|
|
4196
|
+
type: 'external',
|
|
4197
|
+
startedFrom: 'external',
|
|
4198
|
+
payload: locked,
|
|
4199
|
+
getDropPayload: function getDropPayload(event) {
|
|
4200
|
+
// this would be a platform error
|
|
4201
|
+
// trying to handle it gracefully rather than throwing (for now)
|
|
4202
|
+
if (!event.dataTransfer) {
|
|
4203
|
+
return locked;
|
|
4204
|
+
}
|
|
4205
|
+
var items = getAvailableItems(event.dataTransfer);
|
|
4206
|
+
// need to use `.bind` as `getData` is required
|
|
4207
|
+
// to be run with `event.dataTransfer` as the "this" context
|
|
4208
|
+
var nativeGetData = event.dataTransfer.getData.bind(event.dataTransfer);
|
|
4209
|
+
return {
|
|
4210
|
+
types: types,
|
|
4211
|
+
items: items,
|
|
4212
|
+
// return `null` if there is no result, otherwise string
|
|
4213
|
+
getStringData: function getStringData(mediaType) {
|
|
4214
|
+
// not dragging the requested type
|
|
4215
|
+
// return `null` (no result)
|
|
4216
|
+
if (!types.includes(mediaType)) {
|
|
4217
|
+
return null;
|
|
4218
|
+
}
|
|
4219
|
+
|
|
4220
|
+
// nativeGetData will return `""` when there is no value,
|
|
4221
|
+
// but at this point we know we will only get explicitly set
|
|
4222
|
+
// values back as we have checked the `types`.
|
|
4223
|
+
// `""` can be an explicitly set value.
|
|
4224
|
+
var value = nativeGetData(mediaType);
|
|
4225
|
+
|
|
4226
|
+
// not exposing data for unavailable types
|
|
4227
|
+
if (!isAnAvailableType({
|
|
4228
|
+
type: mediaType,
|
|
4229
|
+
value: value
|
|
4230
|
+
})) {
|
|
4231
|
+
return null;
|
|
4232
|
+
}
|
|
4233
|
+
return value;
|
|
4234
|
+
}
|
|
4235
|
+
};
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
});
|
|
4239
|
+
}
|
|
4240
|
+
});
|
|
4241
|
+
}
|
|
4242
|
+
});
|
|
4243
|
+
|
|
4244
|
+
/**
|
|
4245
|
+
* Some events don't make sense for the external adapter
|
|
4246
|
+
*
|
|
4247
|
+
* `onGenerateDragPreview`
|
|
4248
|
+
* The browser creates the drag preview for external drags, so we don't
|
|
4249
|
+
* need an event to generate the preview for _monitors_ or the _dropTarget_
|
|
4250
|
+
*
|
|
4251
|
+
* `onDragStart`
|
|
4252
|
+
* An external drag can never start from in the `window`, so _dropTarget_'s
|
|
4253
|
+
* don't need `onDragStart`
|
|
4254
|
+
*/
|
|
4255
|
+
|
|
4256
|
+
function dropTargetForExternal(args) {
|
|
4257
|
+
// not removing unused events, just leaning on the type system
|
|
4258
|
+
return adapter.dropTarget(args);
|
|
4259
|
+
}
|
|
4260
|
+
(function startup() {
|
|
4261
|
+
// server side rendering check
|
|
4262
|
+
if (typeof window === 'undefined') {
|
|
4263
|
+
return;
|
|
4264
|
+
}
|
|
4265
|
+
|
|
4266
|
+
// A shared single usage registration as we want to capture
|
|
4267
|
+
// all external drag operations, even if there are no drop targets
|
|
4268
|
+
// on the page yet
|
|
4269
|
+
adapter.registerUsage();
|
|
4270
|
+
// independent of pdnd, we need to keep track of
|
|
4271
|
+
// all drag operations so that we can know if a drag operation
|
|
4272
|
+
// has started locally
|
|
4273
|
+
|
|
4274
|
+
var idle = {
|
|
4275
|
+
type: 'idle'
|
|
4276
|
+
};
|
|
4277
|
+
var state = idle;
|
|
4278
|
+
function clear() {
|
|
4279
|
+
if (state.type !== 'dragging') {
|
|
4280
|
+
return;
|
|
4281
|
+
}
|
|
4282
|
+
didDragStartLocally = false;
|
|
4283
|
+
state.cleanup();
|
|
4284
|
+
state = idle;
|
|
4285
|
+
}
|
|
4286
|
+
function bindEndEvents() {
|
|
4287
|
+
return bindAll(window, [{
|
|
4288
|
+
type: 'dragend',
|
|
4289
|
+
listener: clear
|
|
4290
|
+
}].concat(_toConsumableArray(getBindingsForBrokenDrags({
|
|
4291
|
+
onDragEnd: clear
|
|
4292
|
+
}))),
|
|
4293
|
+
// we want to make sure we get all the events,
|
|
4294
|
+
// and this helps avoid not seeing events when folks stop
|
|
4295
|
+
// them later on the event path
|
|
4296
|
+
{
|
|
4297
|
+
capture: true
|
|
4298
|
+
});
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
// we always keep this event listener active
|
|
4302
|
+
bind(window, {
|
|
4303
|
+
type: 'dragstart',
|
|
4304
|
+
listener: function listener() {
|
|
4305
|
+
// something bad has happened if this is true!
|
|
4306
|
+
if (state.type !== 'idle') {
|
|
4307
|
+
return;
|
|
4308
|
+
}
|
|
4309
|
+
// set our global flag
|
|
4310
|
+
didDragStartLocally = true;
|
|
4311
|
+
state = {
|
|
4312
|
+
type: 'dragging',
|
|
4313
|
+
cleanup: bindEndEvents()
|
|
4314
|
+
};
|
|
4315
|
+
},
|
|
4316
|
+
// binding in the capture phase so these listeners are called
|
|
4317
|
+
// before our listeners in the adapters `mount` function
|
|
4318
|
+
options: {
|
|
4319
|
+
capture: true
|
|
4320
|
+
}
|
|
4321
|
+
});
|
|
4322
|
+
})();
|
|
4323
|
+
|
|
4324
|
+
/** Common event payload for all events */
|
|
4325
|
+
|
|
4326
|
+
/** A map containing payloads for all events */
|
|
4327
|
+
|
|
4328
|
+
/** Common event payload for all drop target events */
|
|
4329
|
+
|
|
4330
|
+
/** A map containing payloads for all events on drop targets */
|
|
4331
|
+
|
|
4332
|
+
/** Arguments given to all feedback functions (eg `canDrop()`) on a `dropTargetForExternal` */
|
|
4333
|
+
|
|
4334
|
+
/** Arguments given to all monitor feedback functions (eg `canMonitor()`) for a `monitorForExternal` */
|
|
4335
|
+
|
|
4336
|
+
/** Obtain an array of the dragged `File`s */
|
|
4337
|
+
function getFiles(_ref2) {
|
|
4338
|
+
var source = _ref2.source;
|
|
4339
|
+
return source.items
|
|
4340
|
+
// unlike other media types, for files:
|
|
4341
|
+
// item.kind is 'file'
|
|
4342
|
+
// item.type is the type of file eg 'image/jpg'
|
|
4343
|
+
// for other media types, item.type is the mime format
|
|
4344
|
+
.filter(function (item) {
|
|
4345
|
+
return item.kind === 'file';
|
|
4346
|
+
}).map(function (item) {
|
|
4347
|
+
return item.getAsFile();
|
|
4348
|
+
}).filter(function (file) {
|
|
4349
|
+
return file != null;
|
|
4350
|
+
});
|
|
4351
|
+
}
|
|
4352
|
+
|
|
4353
|
+
/* Get the plain text that a user is dragging */
|
|
4354
|
+
function getText(_ref2) {
|
|
4355
|
+
var source = _ref2.source;
|
|
4356
|
+
return source.getStringData(textMediaType);
|
|
4357
|
+
}
|
|
4358
|
+
|
|
2164
4359
|
const FileDropzone = ({ children = undefined, gridProps = {}, onDrop = () => { }, placeholder = "Drop files here or click to upload", }) => {
|
|
2165
4360
|
const ref = useRef(null);
|
|
2166
4361
|
const [isDraggedOver, setIsDraggedOver] = useState(false);
|