@planningcenter/react-beautiful-dnd 13.2.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/CHANGELOG.md +35 -0
- package/LICENSE +13 -0
- package/README.md +178 -0
- package/dist/react-beautiful-dnd.cjs.js +8728 -0
- package/dist/react-beautiful-dnd.cjs.js.flow +3 -0
- package/dist/react-beautiful-dnd.esm.js +8715 -0
- package/dist/react-beautiful-dnd.js +11726 -0
- package/dist/react-beautiful-dnd.min.js +1 -0
- package/package.json +155 -0
- package/src/animation.js +75 -0
- package/src/debug/middleware/action-timing-average.js +52 -0
- package/src/debug/middleware/action-timing.js +16 -0
- package/src/debug/middleware/log.js +26 -0
- package/src/debug/middleware/user-timing.js +16 -0
- package/src/debug/timings.js +86 -0
- package/src/dev-warning.js +50 -0
- package/src/empty.js +6 -0
- package/src/index.js +67 -0
- package/src/invariant.js +33 -0
- package/src/native-with-fallback.js +69 -0
- package/src/screen-reader-message-preset.js +134 -0
- package/src/state/action-creators.js +328 -0
- package/src/state/auto-scroller/auto-scroller-types.js +8 -0
- package/src/state/auto-scroller/can-scroll.js +160 -0
- package/src/state/auto-scroller/fluid-scroller/config.js +25 -0
- package/src/state/auto-scroller/fluid-scroller/did-start-in-scrollable-area.js +1 -0
- package/src/state/auto-scroller/fluid-scroller/get-best-scrollable-droppable.js +77 -0
- package/src/state/auto-scroller/fluid-scroller/get-droppable-scroll-change.js +50 -0
- package/src/state/auto-scroller/fluid-scroller/get-percentage.js +25 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/adjust-for-size-limits.js +30 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/buffer-thresholds/calc-axis-scroll-conditions.js +68 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/buffer-thresholds/get-scroll-conditions.js +56 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/buffer-thresholds/index.js +66 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/dampen-value-by-time.js +48 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/get-distance-thresholds.js +31 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/get-value-from-distance.js +67 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/get-value.js +51 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/index.js +50 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/min-scroll.js +4 -0
- package/src/state/auto-scroller/fluid-scroller/get-scroll/index.js +139 -0
- package/src/state/auto-scroller/fluid-scroller/get-window-scroll-change.js +43 -0
- package/src/state/auto-scroller/fluid-scroller/index.js +99 -0
- package/src/state/auto-scroller/fluid-scroller/scroll.js +80 -0
- package/src/state/auto-scroller/index.js +59 -0
- package/src/state/auto-scroller/jump-scroller.js +139 -0
- package/src/state/axis.js +26 -0
- package/src/state/calculate-drag-impact/calculate-reorder-impact.js +136 -0
- package/src/state/can-start-drag.js +29 -0
- package/src/state/create-store.js +97 -0
- package/src/state/did-start-after-critical.js +9 -0
- package/src/state/dimension-marshal/dimension-marshal-types.js +46 -0
- package/src/state/dimension-marshal/dimension-marshal.js +218 -0
- package/src/state/dimension-marshal/get-initial-publish.js +66 -0
- package/src/state/dimension-marshal/while-dragging-publisher.js +146 -0
- package/src/state/dimension-structures.js +35 -0
- package/src/state/droppable/get-droppable.js +101 -0
- package/src/state/droppable/is-home-of.js +7 -0
- package/src/state/droppable/scroll-droppable.js +53 -0
- package/src/state/droppable/should-use-placeholder.js +7 -0
- package/src/state/droppable/util/clip.js +17 -0
- package/src/state/droppable/util/get-subject.js +63 -0
- package/src/state/droppable/what-is-dragged-over-from-result.js +16 -0
- package/src/state/droppable/what-is-dragged-over.js +16 -0
- package/src/state/droppable/with-placeholder.js +174 -0
- package/src/state/get-center-from-impact/get-client-border-box-center/get-client-from-page-border-box-center.js +29 -0
- package/src/state/get-center-from-impact/get-client-border-box-center/index.js +44 -0
- package/src/state/get-center-from-impact/get-page-border-box-center/index.js +70 -0
- package/src/state/get-center-from-impact/get-page-border-box-center/when-combining.js +39 -0
- package/src/state/get-center-from-impact/get-page-border-box-center/when-reordering.js +112 -0
- package/src/state/get-center-from-impact/move-relative-to.js +66 -0
- package/src/state/get-combined-item-displacement.js +34 -0
- package/src/state/get-displaced-by.js +17 -0
- package/src/state/get-displacement-groups.js +130 -0
- package/src/state/get-drag-impact/get-combine-impact.js +130 -0
- package/src/state/get-drag-impact/get-reorder-impact.js +143 -0
- package/src/state/get-drag-impact/index.js +93 -0
- package/src/state/get-draggables-inside-droppable.js +31 -0
- package/src/state/get-droppable-over.js +158 -0
- package/src/state/get-frame.js +10 -0
- package/src/state/get-home-location.js +7 -0
- package/src/state/get-impact-location.js +16 -0
- package/src/state/get-is-displaced.js +11 -0
- package/src/state/get-lift-effect.js +82 -0
- package/src/state/get-max-scroll.js +30 -0
- package/src/state/is-movement-allowed.js +6 -0
- package/src/state/is-within.js +9 -0
- package/src/state/middleware/auto-scroll.js +38 -0
- package/src/state/middleware/dimension-marshal-stopper.js +20 -0
- package/src/state/middleware/drop/drop-animation-finish-middleware.js +21 -0
- package/src/state/middleware/drop/drop-animation-flush-on-scroll-middleware.js +63 -0
- package/src/state/middleware/drop/drop-middleware.js +146 -0
- package/src/state/middleware/drop/get-drop-duration.js +47 -0
- package/src/state/middleware/drop/get-drop-impact.js +77 -0
- package/src/state/middleware/drop/get-new-home-client-offset.js +54 -0
- package/src/state/middleware/drop/index.js +2 -0
- package/src/state/middleware/focus.js +42 -0
- package/src/state/middleware/lift.js +66 -0
- package/src/state/middleware/pending-drop.js +37 -0
- package/src/state/middleware/responders/async-marshal.js +55 -0
- package/src/state/middleware/responders/expiring-announce.js +44 -0
- package/src/state/middleware/responders/index.js +2 -0
- package/src/state/middleware/responders/is-equal.js +57 -0
- package/src/state/middleware/responders/publisher.js +253 -0
- package/src/state/middleware/responders/responders-middleware.js +75 -0
- package/src/state/middleware/scroll-listener.js +31 -0
- package/src/state/middleware/style.js +22 -0
- package/src/state/middleware/util/validate-dimensions.js +71 -0
- package/src/state/move-in-direction/index.js +84 -0
- package/src/state/move-in-direction/move-cross-axis/get-best-cross-axis-droppable.js +168 -0
- package/src/state/move-in-direction/move-cross-axis/get-closest-draggable.js +79 -0
- package/src/state/move-in-direction/move-cross-axis/index.js +109 -0
- package/src/state/move-in-direction/move-cross-axis/move-to-new-droppable.js +121 -0
- package/src/state/move-in-direction/move-cross-axis/without-starting-displacement.js +31 -0
- package/src/state/move-in-direction/move-in-direction-types.js +9 -0
- package/src/state/move-in-direction/move-to-next-place/index.js +132 -0
- package/src/state/move-in-direction/move-to-next-place/is-totally-visible-in-new-location.js +52 -0
- package/src/state/move-in-direction/move-to-next-place/move-to-next-combine/index.js +97 -0
- package/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-combine.js +52 -0
- package/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-reorder.js +43 -0
- package/src/state/move-in-direction/move-to-next-place/move-to-next-index/index.js +86 -0
- package/src/state/no-impact.js +33 -0
- package/src/state/patch-dimension-map.js +11 -0
- package/src/state/patch-droppable-map.js +10 -0
- package/src/state/position.js +58 -0
- package/src/state/post-reducer/when-moving/refresh-snap.js +67 -0
- package/src/state/post-reducer/when-moving/update.js +120 -0
- package/src/state/publish-while-dragging-in-virtual/adjust-additions-for-scroll-changes.js +58 -0
- package/src/state/publish-while-dragging-in-virtual/index.js +158 -0
- package/src/state/publish-while-dragging-in-virtual/offset-draggable.js +35 -0
- package/src/state/recompute-placeholders.js +99 -0
- package/src/state/rect.js +7 -0
- package/src/state/reducer.js +457 -0
- package/src/state/registry/create-registry.js +162 -0
- package/src/state/registry/registry-types.js +98 -0
- package/src/state/registry/use-registry.js +20 -0
- package/src/state/remove-draggable-from-list.js +13 -0
- package/src/state/scroll-viewport.js +34 -0
- package/src/state/spacing.js +45 -0
- package/src/state/store-types.js +16 -0
- package/src/state/update-displacement-visibility/recompute.js +54 -0
- package/src/state/update-displacement-visibility/speculatively-increase.js +111 -0
- package/src/state/visibility/is-partially-visible-through-frame.js +60 -0
- package/src/state/visibility/is-position-in-frame.js +12 -0
- package/src/state/visibility/is-totally-visible-through-frame-on-axis.js +19 -0
- package/src/state/visibility/is-totally-visible-through-frame.js +18 -0
- package/src/state/visibility/is-visible.js +102 -0
- package/src/state/with-scroll-change/with-all-displacement.js +15 -0
- package/src/state/with-scroll-change/with-droppable-displacement.js +13 -0
- package/src/state/with-scroll-change/with-droppable-scroll.js +13 -0
- package/src/state/with-scroll-change/with-viewport-displacement.js +7 -0
- package/src/types.js +542 -0
- package/src/view/animate-in-out/animate-in-out.jsx +95 -0
- package/src/view/animate-in-out/index.js +2 -0
- package/src/view/check-is-valid-inner-ref.js +15 -0
- package/src/view/context/app-context.js +19 -0
- package/src/view/context/droppable-context.js +11 -0
- package/src/view/context/store-context.js +5 -0
- package/src/view/data-attributes.js +37 -0
- package/src/view/drag-drop-context/app.jsx +273 -0
- package/src/view/drag-drop-context/check-doctype.js +39 -0
- package/src/view/drag-drop-context/check-react-version.js +71 -0
- package/src/view/drag-drop-context/drag-drop-context-types.js +7 -0
- package/src/view/drag-drop-context/drag-drop-context.jsx +68 -0
- package/src/view/drag-drop-context/error-boundary.jsx +88 -0
- package/src/view/drag-drop-context/index.js +2 -0
- package/src/view/drag-drop-context/use-startup-validation.js +13 -0
- package/src/view/drag-drop-context/use-unique-context-id.js +13 -0
- package/src/view/draggable/connected-draggable.js +372 -0
- package/src/view/draggable/draggable-api.jsx +48 -0
- package/src/view/draggable/draggable-types.js +191 -0
- package/src/view/draggable/draggable.jsx +171 -0
- package/src/view/draggable/get-style.js +109 -0
- package/src/view/draggable/index.js +2 -0
- package/src/view/draggable/use-validation.js +70 -0
- package/src/view/droppable/connected-droppable.js +280 -0
- package/src/view/droppable/droppable-types.js +91 -0
- package/src/view/droppable/droppable.jsx +167 -0
- package/src/view/droppable/index.js +2 -0
- package/src/view/droppable/use-validation.js +101 -0
- package/src/view/event-bindings/bind-events.js +39 -0
- package/src/view/event-bindings/event-types.js +14 -0
- package/src/view/get-body-element.js +8 -0
- package/src/view/get-border-box-center-position.js +5 -0
- package/src/view/get-document-element.js +8 -0
- package/src/view/get-elements/find-drag-handle.js +38 -0
- package/src/view/get-elements/find-draggable.js +30 -0
- package/src/view/is-strict-equal.js +2 -0
- package/src/view/is-type-of-element/is-element.js +6 -0
- package/src/view/is-type-of-element/is-html-element.js +6 -0
- package/src/view/is-type-of-element/is-svg-element.js +12 -0
- package/src/view/key-codes.js +13 -0
- package/src/view/placeholder/index.js +2 -0
- package/src/view/placeholder/placeholder-types.js +16 -0
- package/src/view/placeholder/placeholder.jsx +198 -0
- package/src/view/scroll-listener.js +72 -0
- package/src/view/throw-if-invalid-inner-ref.js +15 -0
- package/src/view/use-announcer/index.js +2 -0
- package/src/view/use-announcer/use-announcer.js +80 -0
- package/src/view/use-dev-setup-warning.js +22 -0
- package/src/view/use-dev.js +9 -0
- package/src/view/use-draggable-publisher/get-dimension.js +44 -0
- package/src/view/use-draggable-publisher/index.js +2 -0
- package/src/view/use-draggable-publisher/use-draggable-publisher.js +87 -0
- package/src/view/use-droppable-publisher/check-for-nested-scroll-container.js +27 -0
- package/src/view/use-droppable-publisher/get-closest-scrollable.js +95 -0
- package/src/view/use-droppable-publisher/get-dimension.js +139 -0
- package/src/view/use-droppable-publisher/get-env.js +31 -0
- package/src/view/use-droppable-publisher/get-listener-options.js +12 -0
- package/src/view/use-droppable-publisher/get-scroll.js +7 -0
- package/src/view/use-droppable-publisher/index.js +2 -0
- package/src/view/use-droppable-publisher/is-in-fixed-container.js +21 -0
- package/src/view/use-droppable-publisher/use-droppable-publisher.js +283 -0
- package/src/view/use-focus-marshal/focus-marshal-types.js +13 -0
- package/src/view/use-focus-marshal/index.js +2 -0
- package/src/view/use-focus-marshal/use-focus-marshal.js +129 -0
- package/src/view/use-hidden-text-element/index.js +2 -0
- package/src/view/use-hidden-text-element/use-hidden-text-element.js +60 -0
- package/src/view/use-isomorphic-layout-effect.js +18 -0
- package/src/view/use-previous-ref.js +14 -0
- package/src/view/use-required-context.js +9 -0
- package/src/view/use-sensor-marshal/closest.js +50 -0
- package/src/view/use-sensor-marshal/find-closest-draggable-id-from-event.js +50 -0
- package/src/view/use-sensor-marshal/index.js +5 -0
- package/src/view/use-sensor-marshal/is-event-in-interactive-element.js +66 -0
- package/src/view/use-sensor-marshal/lock.js +48 -0
- package/src/view/use-sensor-marshal/sensors/use-keyboard-sensor.js +243 -0
- package/src/view/use-sensor-marshal/sensors/use-mouse-sensor.js +386 -0
- package/src/view/use-sensor-marshal/sensors/use-touch-sensor.js +461 -0
- package/src/view/use-sensor-marshal/sensors/util/prevent-standard-key-events.js +19 -0
- package/src/view/use-sensor-marshal/sensors/util/supported-page-visibility-event-name.js +29 -0
- package/src/view/use-sensor-marshal/use-sensor-marshal.js +495 -0
- package/src/view/use-sensor-marshal/use-validate-sensor-hooks.js +20 -0
- package/src/view/use-style-marshal/get-styles.js +170 -0
- package/src/view/use-style-marshal/index.js +2 -0
- package/src/view/use-style-marshal/style-marshal-types.js +8 -0
- package/src/view/use-style-marshal/use-style-marshal.js +126 -0
- package/src/view/use-unique-id.js +25 -0
- package/src/view/visually-hidden-style.js +16 -0
- package/src/view/window/get-max-window-scroll.js +19 -0
- package/src/view/window/get-viewport.js +49 -0
- package/src/view/window/get-window-from-el.js +3 -0
- package/src/view/window/get-window-scroll.js +30 -0
- package/src/view/window/scroll-window.js +7 -0
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { type Rect, type Spacing, expand, getRect } from 'css-box-model';
|
|
3
|
+
import type {
|
|
4
|
+
DraggableId,
|
|
5
|
+
Displacement,
|
|
6
|
+
DraggableDimension,
|
|
7
|
+
DroppableDimension,
|
|
8
|
+
DisplacementGroups,
|
|
9
|
+
DisplacedBy,
|
|
10
|
+
} from '../types';
|
|
11
|
+
import { isPartiallyVisible } from './visibility/is-visible';
|
|
12
|
+
|
|
13
|
+
type Args = {|
|
|
14
|
+
afterDragging: DraggableDimension[],
|
|
15
|
+
destination: DroppableDimension,
|
|
16
|
+
displacedBy: DisplacedBy,
|
|
17
|
+
last: ?DisplacementGroups,
|
|
18
|
+
viewport: Rect,
|
|
19
|
+
forceShouldAnimate?: boolean,
|
|
20
|
+
|};
|
|
21
|
+
|
|
22
|
+
const getShouldAnimate = (
|
|
23
|
+
id,
|
|
24
|
+
last: ?DisplacementGroups,
|
|
25
|
+
forceShouldAnimate: ?boolean,
|
|
26
|
+
) => {
|
|
27
|
+
// Use a forced value if provided
|
|
28
|
+
if (typeof forceShouldAnimate === 'boolean') {
|
|
29
|
+
return forceShouldAnimate;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// nothing to gauge animation from
|
|
33
|
+
if (!last) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const { invisible, visible } = last;
|
|
38
|
+
|
|
39
|
+
// it was previously invisible - no animation
|
|
40
|
+
if (invisible[id]) {
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const previous: ?Displacement = visible[id];
|
|
45
|
+
|
|
46
|
+
return previous ? previous.shouldAnimate : true;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// Note: it is also an optimisation to not render the displacement on
|
|
50
|
+
// items when they are not longer visible.
|
|
51
|
+
// This prevents a lot of .render() calls when leaving / entering a list
|
|
52
|
+
|
|
53
|
+
function getTarget(
|
|
54
|
+
draggable: DraggableDimension,
|
|
55
|
+
displacedBy: DisplacedBy,
|
|
56
|
+
): Rect {
|
|
57
|
+
const marginBox: Rect = draggable.page.marginBox;
|
|
58
|
+
|
|
59
|
+
// ## Visibility overscanning
|
|
60
|
+
// We are expanding rather than offsetting the marginBox.
|
|
61
|
+
// In some cases we want
|
|
62
|
+
// - the target based on the starting position (such as when dropping outside of any list)
|
|
63
|
+
// - the target based on the items position without starting displacement (such as when moving inside a list)
|
|
64
|
+
// To keep things simple we just expand the whole area for this check
|
|
65
|
+
// The worst case is some minor redundant offscreen movements
|
|
66
|
+
const expandBy: Spacing = {
|
|
67
|
+
// pull backwards into viewport
|
|
68
|
+
top: displacedBy.point.y,
|
|
69
|
+
right: 0,
|
|
70
|
+
bottom: 0,
|
|
71
|
+
// pull backwards into viewport
|
|
72
|
+
left: displacedBy.point.x,
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
return getRect(expand(marginBox, expandBy));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export default function getDisplacementGroups({
|
|
79
|
+
afterDragging,
|
|
80
|
+
destination,
|
|
81
|
+
displacedBy,
|
|
82
|
+
viewport,
|
|
83
|
+
forceShouldAnimate,
|
|
84
|
+
last,
|
|
85
|
+
}: Args): DisplacementGroups {
|
|
86
|
+
return afterDragging.reduce(
|
|
87
|
+
function process(
|
|
88
|
+
groups: DisplacementGroups,
|
|
89
|
+
draggable: DraggableDimension,
|
|
90
|
+
): DisplacementGroups {
|
|
91
|
+
const target: Rect = getTarget(draggable, displacedBy);
|
|
92
|
+
const id: DraggableId = draggable.descriptor.id;
|
|
93
|
+
|
|
94
|
+
groups.all.push(id);
|
|
95
|
+
|
|
96
|
+
const isVisible: boolean = isPartiallyVisible({
|
|
97
|
+
target,
|
|
98
|
+
destination,
|
|
99
|
+
viewport,
|
|
100
|
+
withDroppableDisplacement: true,
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (!isVisible) {
|
|
104
|
+
groups.invisible[draggable.descriptor.id] = true;
|
|
105
|
+
return groups;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// item is visible
|
|
109
|
+
|
|
110
|
+
const shouldAnimate: boolean = getShouldAnimate(
|
|
111
|
+
id,
|
|
112
|
+
last,
|
|
113
|
+
forceShouldAnimate,
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
const displacement: Displacement = {
|
|
117
|
+
draggableId: id,
|
|
118
|
+
shouldAnimate,
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
groups.visible[id] = displacement;
|
|
122
|
+
return groups;
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
all: [],
|
|
126
|
+
visible: {},
|
|
127
|
+
invisible: {},
|
|
128
|
+
},
|
|
129
|
+
);
|
|
130
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type { Rect } from 'css-box-model';
|
|
3
|
+
import type {
|
|
4
|
+
DraggableId,
|
|
5
|
+
Axis,
|
|
6
|
+
DraggableDimension,
|
|
7
|
+
DroppableDimension,
|
|
8
|
+
DragImpact,
|
|
9
|
+
LiftEffect,
|
|
10
|
+
DisplacedBy,
|
|
11
|
+
} from '../../types';
|
|
12
|
+
import { find } from '../../native-with-fallback';
|
|
13
|
+
import getDidStartAfterCritical from '../did-start-after-critical';
|
|
14
|
+
import getDisplacedBy from '../get-displaced-by';
|
|
15
|
+
import getIsDisplaced from '../get-is-displaced';
|
|
16
|
+
import removeDraggableFromList from '../remove-draggable-from-list';
|
|
17
|
+
|
|
18
|
+
type Args = {|
|
|
19
|
+
draggable: DraggableDimension,
|
|
20
|
+
pageBorderBoxWithDroppableScroll: Rect,
|
|
21
|
+
previousImpact: DragImpact,
|
|
22
|
+
destination: DroppableDimension,
|
|
23
|
+
insideDestination: DraggableDimension[],
|
|
24
|
+
afterCritical: LiftEffect,
|
|
25
|
+
|};
|
|
26
|
+
|
|
27
|
+
// exported for testing
|
|
28
|
+
export const combineThresholdDivisor: number = 4;
|
|
29
|
+
|
|
30
|
+
export default ({
|
|
31
|
+
draggable,
|
|
32
|
+
pageBorderBoxWithDroppableScroll: targetRect,
|
|
33
|
+
previousImpact,
|
|
34
|
+
destination,
|
|
35
|
+
insideDestination,
|
|
36
|
+
afterCritical,
|
|
37
|
+
}: Args): ?DragImpact => {
|
|
38
|
+
if (!destination.isCombineEnabled) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
const axis: Axis = destination.axis;
|
|
42
|
+
const displacedBy: DisplacedBy = getDisplacedBy(
|
|
43
|
+
destination.axis,
|
|
44
|
+
draggable.displaceBy,
|
|
45
|
+
);
|
|
46
|
+
const displacement: number = displacedBy.value;
|
|
47
|
+
|
|
48
|
+
const targetStart: number = targetRect[axis.start];
|
|
49
|
+
const targetEnd: number = targetRect[axis.end];
|
|
50
|
+
|
|
51
|
+
const withoutDragging: DraggableDimension[] = removeDraggableFromList(
|
|
52
|
+
draggable,
|
|
53
|
+
insideDestination,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
const combineWith: ?DraggableDimension = find(
|
|
57
|
+
withoutDragging,
|
|
58
|
+
(child: DraggableDimension): boolean => {
|
|
59
|
+
const id: DraggableId = child.descriptor.id;
|
|
60
|
+
const childRect: Rect = child.page.borderBox;
|
|
61
|
+
const childSize: number = childRect[axis.size];
|
|
62
|
+
const threshold: number = childSize / combineThresholdDivisor;
|
|
63
|
+
|
|
64
|
+
const didStartAfterCritical: boolean = getDidStartAfterCritical(
|
|
65
|
+
id,
|
|
66
|
+
afterCritical,
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const isDisplaced: boolean = getIsDisplaced({
|
|
70
|
+
displaced: previousImpact.displaced,
|
|
71
|
+
id,
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
/*
|
|
75
|
+
Only combining when in the combine region
|
|
76
|
+
As soon as a boundary is hit then no longer combining
|
|
77
|
+
*/
|
|
78
|
+
|
|
79
|
+
if (didStartAfterCritical) {
|
|
80
|
+
// In original position
|
|
81
|
+
// Will combine with item when inside a band
|
|
82
|
+
if (isDisplaced) {
|
|
83
|
+
return (
|
|
84
|
+
targetEnd > childRect[axis.start] + threshold &&
|
|
85
|
+
targetEnd < childRect[axis.end] - threshold
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// child is now 'displaced' backwards from where it started
|
|
90
|
+
// want to combine when we move backwards onto it
|
|
91
|
+
return (
|
|
92
|
+
targetStart > childRect[axis.start] - displacement + threshold &&
|
|
93
|
+
targetStart < childRect[axis.end] - displacement - threshold
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// item has moved forwards
|
|
98
|
+
if (isDisplaced) {
|
|
99
|
+
return (
|
|
100
|
+
targetEnd > childRect[axis.start] + displacement + threshold &&
|
|
101
|
+
targetEnd < childRect[axis.end] + displacement - threshold
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// is in resting position - being moved backwards on to
|
|
106
|
+
return (
|
|
107
|
+
targetStart > childRect[axis.start] + threshold &&
|
|
108
|
+
targetStart < childRect[axis.end] - threshold
|
|
109
|
+
);
|
|
110
|
+
},
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
if (!combineWith) {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
const impact: DragImpact = {
|
|
118
|
+
// no change to displacement when combining
|
|
119
|
+
displacedBy,
|
|
120
|
+
displaced: previousImpact.displaced,
|
|
121
|
+
at: {
|
|
122
|
+
type: 'COMBINE',
|
|
123
|
+
combine: {
|
|
124
|
+
draggableId: combineWith.descriptor.id,
|
|
125
|
+
droppableId: destination.descriptor.id,
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
return impact;
|
|
130
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { type Rect } from 'css-box-model';
|
|
3
|
+
import type {
|
|
4
|
+
DraggableId,
|
|
5
|
+
DraggableDimension,
|
|
6
|
+
DroppableDimension,
|
|
7
|
+
DragImpact,
|
|
8
|
+
Axis,
|
|
9
|
+
DisplacementGroups,
|
|
10
|
+
Viewport,
|
|
11
|
+
DisplacedBy,
|
|
12
|
+
LiftEffect,
|
|
13
|
+
} from '../../types';
|
|
14
|
+
import getDisplacedBy from '../get-displaced-by';
|
|
15
|
+
import removeDraggableFromList from '../remove-draggable-from-list';
|
|
16
|
+
import isHomeOf from '../droppable/is-home-of';
|
|
17
|
+
import { find } from '../../native-with-fallback';
|
|
18
|
+
import getDidStartAfterCritical from '../did-start-after-critical';
|
|
19
|
+
import calculateReorderImpact from '../calculate-drag-impact/calculate-reorder-impact';
|
|
20
|
+
import getIsDisplaced from '../get-is-displaced';
|
|
21
|
+
|
|
22
|
+
type Args = {|
|
|
23
|
+
pageBorderBoxWithDroppableScroll: Rect,
|
|
24
|
+
draggable: DraggableDimension,
|
|
25
|
+
destination: DroppableDimension,
|
|
26
|
+
insideDestination: DraggableDimension[],
|
|
27
|
+
last: DisplacementGroups,
|
|
28
|
+
viewport: Viewport,
|
|
29
|
+
afterCritical: LiftEffect,
|
|
30
|
+
|};
|
|
31
|
+
|
|
32
|
+
type AtIndexArgs = {|
|
|
33
|
+
draggable: DraggableDimension,
|
|
34
|
+
closest: ?DraggableDimension,
|
|
35
|
+
inHomeList: boolean,
|
|
36
|
+
|};
|
|
37
|
+
|
|
38
|
+
function atIndex({ draggable, closest, inHomeList }: AtIndexArgs): ?number {
|
|
39
|
+
if (!closest) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!inHomeList) {
|
|
44
|
+
return closest.descriptor.index;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (closest.descriptor.index > draggable.descriptor.index) {
|
|
48
|
+
return closest.descriptor.index - 1;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return closest.descriptor.index;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export default ({
|
|
55
|
+
pageBorderBoxWithDroppableScroll: targetRect,
|
|
56
|
+
draggable,
|
|
57
|
+
destination,
|
|
58
|
+
insideDestination,
|
|
59
|
+
last,
|
|
60
|
+
viewport,
|
|
61
|
+
afterCritical,
|
|
62
|
+
}: Args): DragImpact => {
|
|
63
|
+
const axis: Axis = destination.axis;
|
|
64
|
+
const displacedBy: DisplacedBy = getDisplacedBy(
|
|
65
|
+
destination.axis,
|
|
66
|
+
draggable.displaceBy,
|
|
67
|
+
);
|
|
68
|
+
const displacement: number = displacedBy.value;
|
|
69
|
+
|
|
70
|
+
const targetStart: number = targetRect[axis.start];
|
|
71
|
+
const targetEnd: number = targetRect[axis.end];
|
|
72
|
+
|
|
73
|
+
const withoutDragging: DraggableDimension[] = removeDraggableFromList(
|
|
74
|
+
draggable,
|
|
75
|
+
insideDestination,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
const closest: ?DraggableDimension = find(
|
|
79
|
+
withoutDragging,
|
|
80
|
+
(child: DraggableDimension): boolean => {
|
|
81
|
+
const id: DraggableId = child.descriptor.id;
|
|
82
|
+
const childCenter: number = child.page.borderBox.center[axis.line];
|
|
83
|
+
|
|
84
|
+
const didStartAfterCritical: boolean = getDidStartAfterCritical(
|
|
85
|
+
id,
|
|
86
|
+
afterCritical,
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
const isDisplaced: boolean = getIsDisplaced({ displaced: last, id });
|
|
90
|
+
|
|
91
|
+
/*
|
|
92
|
+
Note: we change things when moving *past* the child center - not when it hits the center
|
|
93
|
+
If we make it when we *hit* the child center then there can be
|
|
94
|
+
a hit on the next update causing a flicker.
|
|
95
|
+
|
|
96
|
+
- Update 1: targetBottom hits center => displace backwards
|
|
97
|
+
- Update 2: targetStart is now hitting the displaced center => displace forwards
|
|
98
|
+
- Update 3: goto 1 (boom)
|
|
99
|
+
*/
|
|
100
|
+
|
|
101
|
+
if (didStartAfterCritical) {
|
|
102
|
+
// Continue to displace while targetEnd before the childCenter
|
|
103
|
+
// Move once we *move forward past* the childCenter
|
|
104
|
+
if (isDisplaced) {
|
|
105
|
+
return targetEnd <= childCenter;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Has been moved backwards from where it started
|
|
109
|
+
// Displace forwards when targetStart *moves backwards past* the displaced childCenter
|
|
110
|
+
return targetStart < childCenter - displacement;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Item has been shifted forward.
|
|
114
|
+
// Remove displacement when targetEnd moves forward past the displaced center
|
|
115
|
+
if (isDisplaced) {
|
|
116
|
+
return targetEnd <= childCenter + displacement;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Item is behind the dragging item
|
|
120
|
+
// We want to displace it if the targetStart goes *backwards past* the childCenter
|
|
121
|
+
return targetStart < childCenter;
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
const newIndex: ?number = atIndex({
|
|
126
|
+
draggable,
|
|
127
|
+
closest,
|
|
128
|
+
inHomeList: isHomeOf(draggable, destination),
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
// TODO: index cannot be null?
|
|
132
|
+
// otherwise return null from there and return empty impact
|
|
133
|
+
// that was calculate reorder impact does not need to account for a null index
|
|
134
|
+
return calculateReorderImpact({
|
|
135
|
+
draggable,
|
|
136
|
+
insideDestination,
|
|
137
|
+
destination,
|
|
138
|
+
viewport,
|
|
139
|
+
last,
|
|
140
|
+
displacedBy,
|
|
141
|
+
index: newIndex,
|
|
142
|
+
});
|
|
143
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { type Position, type Rect } from 'css-box-model';
|
|
3
|
+
import type {
|
|
4
|
+
DroppableId,
|
|
5
|
+
DraggableDimension,
|
|
6
|
+
DroppableDimension,
|
|
7
|
+
DraggableDimensionMap,
|
|
8
|
+
DroppableDimensionMap,
|
|
9
|
+
DragImpact,
|
|
10
|
+
Viewport,
|
|
11
|
+
LiftEffect,
|
|
12
|
+
} from '../../types';
|
|
13
|
+
import getDroppableOver from '../get-droppable-over';
|
|
14
|
+
import getDraggablesInsideDroppable from '../get-draggables-inside-droppable';
|
|
15
|
+
import withDroppableScroll from '../with-scroll-change/with-droppable-scroll';
|
|
16
|
+
import getReorderImpact from './get-reorder-impact';
|
|
17
|
+
import getCombineImpact from './get-combine-impact';
|
|
18
|
+
import noImpact from '../no-impact';
|
|
19
|
+
import { offsetRectByPosition } from '../rect';
|
|
20
|
+
|
|
21
|
+
type Args = {|
|
|
22
|
+
pageOffset: Position,
|
|
23
|
+
draggable: DraggableDimension,
|
|
24
|
+
// all dimensions in system
|
|
25
|
+
draggables: DraggableDimensionMap,
|
|
26
|
+
droppables: DroppableDimensionMap,
|
|
27
|
+
previousImpact: DragImpact,
|
|
28
|
+
viewport: Viewport,
|
|
29
|
+
afterCritical: LiftEffect,
|
|
30
|
+
|};
|
|
31
|
+
|
|
32
|
+
export default ({
|
|
33
|
+
pageOffset,
|
|
34
|
+
draggable,
|
|
35
|
+
draggables,
|
|
36
|
+
droppables,
|
|
37
|
+
previousImpact,
|
|
38
|
+
viewport,
|
|
39
|
+
afterCritical,
|
|
40
|
+
}: Args): DragImpact => {
|
|
41
|
+
const pageBorderBox: Rect = offsetRectByPosition(
|
|
42
|
+
draggable.page.borderBox,
|
|
43
|
+
pageOffset,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const destinationId: ?DroppableId = getDroppableOver({
|
|
47
|
+
pageBorderBox,
|
|
48
|
+
draggable,
|
|
49
|
+
droppables,
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// not dragging over anything
|
|
53
|
+
|
|
54
|
+
if (!destinationId) {
|
|
55
|
+
// A big design decision was made here to collapse the home list
|
|
56
|
+
// when not over any list. This yielded the most consistently beautiful experience.
|
|
57
|
+
return noImpact;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const destination: DroppableDimension = droppables[destinationId];
|
|
61
|
+
const insideDestination: DraggableDimension[] = getDraggablesInsideDroppable(
|
|
62
|
+
destination.descriptor.id,
|
|
63
|
+
draggables,
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Where the element actually is now.
|
|
67
|
+
// Need to take into account the change of scroll in the droppable
|
|
68
|
+
const pageBorderBoxWithDroppableScroll: Rect = withDroppableScroll(
|
|
69
|
+
destination,
|
|
70
|
+
pageBorderBox,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// checking combine first so we combine before any reordering
|
|
74
|
+
return (
|
|
75
|
+
getCombineImpact({
|
|
76
|
+
pageBorderBoxWithDroppableScroll,
|
|
77
|
+
draggable,
|
|
78
|
+
previousImpact,
|
|
79
|
+
destination,
|
|
80
|
+
insideDestination,
|
|
81
|
+
afterCritical,
|
|
82
|
+
}) ||
|
|
83
|
+
getReorderImpact({
|
|
84
|
+
pageBorderBoxWithDroppableScroll,
|
|
85
|
+
draggable,
|
|
86
|
+
destination,
|
|
87
|
+
insideDestination,
|
|
88
|
+
last: previousImpact.displaced,
|
|
89
|
+
viewport,
|
|
90
|
+
afterCritical,
|
|
91
|
+
})
|
|
92
|
+
);
|
|
93
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import memoizeOne from 'memoize-one';
|
|
3
|
+
import { toDraggableList } from './dimension-structures';
|
|
4
|
+
import type {
|
|
5
|
+
DraggableDimension,
|
|
6
|
+
DroppableId,
|
|
7
|
+
DraggableDimensionMap,
|
|
8
|
+
} from '../types';
|
|
9
|
+
|
|
10
|
+
export default memoizeOne(
|
|
11
|
+
(
|
|
12
|
+
// using droppableId to avoid cache busted when we
|
|
13
|
+
// update the droppable (such as when it scrolls)
|
|
14
|
+
droppableId: DroppableId,
|
|
15
|
+
draggables: DraggableDimensionMap,
|
|
16
|
+
): DraggableDimension[] => {
|
|
17
|
+
const result = toDraggableList(draggables)
|
|
18
|
+
.filter(
|
|
19
|
+
(draggable: DraggableDimension): boolean =>
|
|
20
|
+
droppableId === draggable.descriptor.droppableId,
|
|
21
|
+
)
|
|
22
|
+
// Dimensions are not guarenteed to be ordered in the same order as keys
|
|
23
|
+
// So we need to sort them so they are in the correct order
|
|
24
|
+
.sort(
|
|
25
|
+
(a: DraggableDimension, b: DraggableDimension): number =>
|
|
26
|
+
a.descriptor.index - b.descriptor.index,
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
return result;
|
|
30
|
+
},
|
|
31
|
+
);
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { type Position, type Rect } from 'css-box-model';
|
|
3
|
+
import type {
|
|
4
|
+
DroppableDimension,
|
|
5
|
+
DroppableDimensionMap,
|
|
6
|
+
DroppableId,
|
|
7
|
+
DraggableDimension,
|
|
8
|
+
Axis,
|
|
9
|
+
} from '../types';
|
|
10
|
+
import { toDroppableList } from './dimension-structures';
|
|
11
|
+
import isPositionInFrame from './visibility/is-position-in-frame';
|
|
12
|
+
import { distance, patch } from './position';
|
|
13
|
+
import isWithin from './is-within';
|
|
14
|
+
|
|
15
|
+
// https://stackoverflow.com/questions/306316/determine-if-two-rectangles-overlap-each-other
|
|
16
|
+
// https://silentmatt.com/rectangle-intersection/
|
|
17
|
+
function getHasOverlap(first: Rect, second: Rect): boolean {
|
|
18
|
+
return (
|
|
19
|
+
first.left < second.right &&
|
|
20
|
+
first.right > second.left &&
|
|
21
|
+
first.top < second.bottom &&
|
|
22
|
+
first.bottom > second.top
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
type Args = {|
|
|
27
|
+
pageBorderBox: Rect,
|
|
28
|
+
draggable: DraggableDimension,
|
|
29
|
+
droppables: DroppableDimensionMap,
|
|
30
|
+
|};
|
|
31
|
+
|
|
32
|
+
type WithDistance = {|
|
|
33
|
+
distance: number,
|
|
34
|
+
id: DroppableId,
|
|
35
|
+
|};
|
|
36
|
+
|
|
37
|
+
type GetFurthestArgs = {|
|
|
38
|
+
pageBorderBox: Rect,
|
|
39
|
+
draggable: DraggableDimension,
|
|
40
|
+
candidates: DroppableDimension[],
|
|
41
|
+
|};
|
|
42
|
+
|
|
43
|
+
function getFurthestAway({
|
|
44
|
+
pageBorderBox,
|
|
45
|
+
draggable,
|
|
46
|
+
candidates,
|
|
47
|
+
}: GetFurthestArgs): ?DroppableId {
|
|
48
|
+
// We are not comparing the center of the home list with the target list as it would
|
|
49
|
+
// give preference to giant lists
|
|
50
|
+
|
|
51
|
+
// We are measuring the distance from where the draggable started
|
|
52
|
+
// to where it is *hitting* the candidate
|
|
53
|
+
// Note: The hit point might technically not be in the bounds of the candidate
|
|
54
|
+
|
|
55
|
+
const startCenter: Position = draggable.page.borderBox.center;
|
|
56
|
+
const sorted: WithDistance[] = candidates
|
|
57
|
+
.map((candidate: DroppableDimension): WithDistance => {
|
|
58
|
+
const axis: Axis = candidate.axis;
|
|
59
|
+
const target: Position = patch(
|
|
60
|
+
candidate.axis.line,
|
|
61
|
+
// use the current center of the dragging item on the main axis
|
|
62
|
+
pageBorderBox.center[axis.line],
|
|
63
|
+
// use the center of the list on the cross axis
|
|
64
|
+
candidate.page.borderBox.center[axis.crossAxisLine],
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
id: candidate.descriptor.id,
|
|
69
|
+
distance: distance(startCenter, target),
|
|
70
|
+
};
|
|
71
|
+
})
|
|
72
|
+
// largest value will be first
|
|
73
|
+
.sort((a: WithDistance, b: WithDistance) => b.distance - a.distance);
|
|
74
|
+
|
|
75
|
+
// just being safe
|
|
76
|
+
return sorted[0] ? sorted[0].id : null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export default function getDroppableOver({
|
|
80
|
+
pageBorderBox,
|
|
81
|
+
draggable,
|
|
82
|
+
droppables,
|
|
83
|
+
}: Args): ?DroppableId {
|
|
84
|
+
// We know at this point that some overlap has to exist
|
|
85
|
+
const candidates: DroppableDimension[] = toDroppableList(droppables).filter(
|
|
86
|
+
(item: DroppableDimension): boolean => {
|
|
87
|
+
// Cannot be a candidate when disabled
|
|
88
|
+
if (!item.isEnabled) {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Cannot be a candidate when there is no visible area
|
|
93
|
+
const active: ?Rect = item.subject.active;
|
|
94
|
+
if (!active) {
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Cannot be a candidate when dragging item is not over the droppable at all
|
|
99
|
+
if (!getHasOverlap(pageBorderBox, active)) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 1. Candidate if the center position is over a droppable
|
|
104
|
+
if (isPositionInFrame(active)(pageBorderBox.center)) {
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 2. Candidate if an edge is over the cross axis half way point
|
|
109
|
+
// 3. Candidate if dragging item is totally over droppable on cross axis
|
|
110
|
+
|
|
111
|
+
const axis: Axis = item.axis;
|
|
112
|
+
const childCenter: number = active.center[axis.crossAxisLine];
|
|
113
|
+
const crossAxisStart: number = pageBorderBox[axis.crossAxisStart];
|
|
114
|
+
const crossAxisEnd: number = pageBorderBox[axis.crossAxisEnd];
|
|
115
|
+
|
|
116
|
+
const isContained = isWithin(
|
|
117
|
+
active[axis.crossAxisStart],
|
|
118
|
+
active[axis.crossAxisEnd],
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
const isStartContained: boolean = isContained(crossAxisStart);
|
|
122
|
+
const isEndContained: boolean = isContained(crossAxisEnd);
|
|
123
|
+
|
|
124
|
+
// Dragging item is totally covering the active area
|
|
125
|
+
if (!isStartContained && !isEndContained) {
|
|
126
|
+
return true;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* edges must go beyond the center line in order to avoid
|
|
131
|
+
* cases were both conditions are satisfied.
|
|
132
|
+
*/
|
|
133
|
+
if (isStartContained) {
|
|
134
|
+
return crossAxisStart < childCenter;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return crossAxisEnd > childCenter;
|
|
138
|
+
},
|
|
139
|
+
);
|
|
140
|
+
|
|
141
|
+
if (!candidates.length) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Only one candidate - use that!
|
|
146
|
+
if (candidates.length === 1) {
|
|
147
|
+
return candidates[0].descriptor.id;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Multiple options returned
|
|
151
|
+
// Should only occur with really large items
|
|
152
|
+
// Going to use fallback: distance from home
|
|
153
|
+
return getFurthestAway({
|
|
154
|
+
pageBorderBox,
|
|
155
|
+
draggable,
|
|
156
|
+
candidates,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { invariant } from '../invariant';
|
|
3
|
+
|
|
4
|
+
import type { DroppableDimension, Scrollable } from '../types';
|
|
5
|
+
|
|
6
|
+
export default (droppable: DroppableDimension): Scrollable => {
|
|
7
|
+
const frame: ?Scrollable = droppable.frame;
|
|
8
|
+
invariant(frame, 'Expected Droppable to have a frame');
|
|
9
|
+
return frame;
|
|
10
|
+
};
|