@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,171 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { useMemo, useCallback } from 'use-memo-one';
|
|
4
|
+
import type { DraggableRubric, DraggableDescriptor } from '../../types';
|
|
5
|
+
import getStyle from './get-style';
|
|
6
|
+
import useDraggablePublisher, {
|
|
7
|
+
type Args as PublisherArgs,
|
|
8
|
+
} from '../use-draggable-publisher/use-draggable-publisher';
|
|
9
|
+
import AppContext from '../context/app-context';
|
|
10
|
+
import DroppableContext from '../context/droppable-context';
|
|
11
|
+
import type {
|
|
12
|
+
Props,
|
|
13
|
+
Provided,
|
|
14
|
+
DraggableStyle,
|
|
15
|
+
DragHandleProps,
|
|
16
|
+
} from './draggable-types';
|
|
17
|
+
import { useValidation, useClonePropValidation } from './use-validation';
|
|
18
|
+
import useRequiredContext from '../use-required-context';
|
|
19
|
+
|
|
20
|
+
function preventHtml5Dnd(event: DragEvent) {
|
|
21
|
+
event.preventDefault();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default function Draggable(props: Props) {
|
|
25
|
+
// reference to DOM node
|
|
26
|
+
const ref = useRef<?HTMLElement>(null);
|
|
27
|
+
const setRef = useCallback((el: ?HTMLElement) => {
|
|
28
|
+
ref.current = el;
|
|
29
|
+
}, []);
|
|
30
|
+
const getRef = useCallback((): ?HTMLElement => ref.current, []);
|
|
31
|
+
|
|
32
|
+
// context
|
|
33
|
+
const {
|
|
34
|
+
contextId,
|
|
35
|
+
dragHandleUsageInstructionsId,
|
|
36
|
+
registry,
|
|
37
|
+
} = useRequiredContext(AppContext);
|
|
38
|
+
const { type, droppableId } = useRequiredContext(DroppableContext);
|
|
39
|
+
|
|
40
|
+
const descriptor: DraggableDescriptor = useMemo(
|
|
41
|
+
() => ({
|
|
42
|
+
id: props.draggableId,
|
|
43
|
+
index: props.index,
|
|
44
|
+
type,
|
|
45
|
+
droppableId,
|
|
46
|
+
}),
|
|
47
|
+
[props.draggableId, props.index, type, droppableId],
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
// props
|
|
51
|
+
const {
|
|
52
|
+
// ownProps
|
|
53
|
+
children,
|
|
54
|
+
draggableId,
|
|
55
|
+
isEnabled,
|
|
56
|
+
shouldRespectForcePress,
|
|
57
|
+
canDragInteractiveElements,
|
|
58
|
+
isClone,
|
|
59
|
+
|
|
60
|
+
// mapProps
|
|
61
|
+
mapped,
|
|
62
|
+
|
|
63
|
+
// dispatchProps
|
|
64
|
+
dropAnimationFinished: dropAnimationFinishedAction,
|
|
65
|
+
} = props;
|
|
66
|
+
|
|
67
|
+
// Validating props and innerRef
|
|
68
|
+
useValidation(props, contextId, getRef);
|
|
69
|
+
|
|
70
|
+
// Clones do not speak to the dimension marshal
|
|
71
|
+
// We are violating the rules of hooks here: conditional hooks.
|
|
72
|
+
// In this specific use case it is okay as an item will always either be a
|
|
73
|
+
// clone or not for it's whole lifecycle
|
|
74
|
+
/* eslint-disable react-hooks/rules-of-hooks */
|
|
75
|
+
|
|
76
|
+
// Being super sure that isClone is not changing during a draggable lifecycle
|
|
77
|
+
useClonePropValidation(isClone);
|
|
78
|
+
if (!isClone) {
|
|
79
|
+
const forPublisher: PublisherArgs = useMemo(
|
|
80
|
+
() => ({
|
|
81
|
+
descriptor,
|
|
82
|
+
registry,
|
|
83
|
+
getDraggableRef: getRef,
|
|
84
|
+
canDragInteractiveElements,
|
|
85
|
+
shouldRespectForcePress,
|
|
86
|
+
isEnabled,
|
|
87
|
+
}),
|
|
88
|
+
[
|
|
89
|
+
descriptor,
|
|
90
|
+
registry,
|
|
91
|
+
getRef,
|
|
92
|
+
canDragInteractiveElements,
|
|
93
|
+
shouldRespectForcePress,
|
|
94
|
+
isEnabled,
|
|
95
|
+
],
|
|
96
|
+
);
|
|
97
|
+
useDraggablePublisher(forPublisher);
|
|
98
|
+
}
|
|
99
|
+
/* eslint-enable react-hooks/rules-of-hooks */
|
|
100
|
+
|
|
101
|
+
const dragHandleProps: ?DragHandleProps = useMemo(
|
|
102
|
+
() =>
|
|
103
|
+
isEnabled
|
|
104
|
+
? {
|
|
105
|
+
// See `draggable-types` for an explanation of why these are used
|
|
106
|
+
tabIndex: 0,
|
|
107
|
+
role: 'button',
|
|
108
|
+
'aria-describedby': dragHandleUsageInstructionsId,
|
|
109
|
+
'data-rbd-drag-handle-draggable-id': draggableId,
|
|
110
|
+
'data-rbd-drag-handle-context-id': contextId,
|
|
111
|
+
draggable: false,
|
|
112
|
+
onDragStart: preventHtml5Dnd,
|
|
113
|
+
}
|
|
114
|
+
: null,
|
|
115
|
+
[contextId, dragHandleUsageInstructionsId, draggableId, isEnabled],
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
const onMoveEnd = useCallback(
|
|
119
|
+
(event: TransitionEvent) => {
|
|
120
|
+
if (mapped.type !== 'DRAGGING') {
|
|
121
|
+
return;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!mapped.dropping) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// There might be other properties on the element that are
|
|
129
|
+
// being transitioned. We do not want those to end a drop animation!
|
|
130
|
+
if (event.propertyName !== 'transform') {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
dropAnimationFinishedAction();
|
|
135
|
+
},
|
|
136
|
+
[dropAnimationFinishedAction, mapped],
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const provided: Provided = useMemo(() => {
|
|
140
|
+
const style: DraggableStyle = getStyle(mapped);
|
|
141
|
+
const onTransitionEnd =
|
|
142
|
+
mapped.type === 'DRAGGING' && mapped.dropping ? onMoveEnd : null;
|
|
143
|
+
|
|
144
|
+
const result: Provided = {
|
|
145
|
+
innerRef: setRef,
|
|
146
|
+
draggableProps: {
|
|
147
|
+
'data-rbd-draggable-context-id': contextId,
|
|
148
|
+
'data-rbd-draggable-id': draggableId,
|
|
149
|
+
style,
|
|
150
|
+
onTransitionEnd,
|
|
151
|
+
},
|
|
152
|
+
dragHandleProps,
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
return result;
|
|
156
|
+
}, [contextId, dragHandleProps, draggableId, mapped, onMoveEnd, setRef]);
|
|
157
|
+
|
|
158
|
+
const rubric: DraggableRubric = useMemo(
|
|
159
|
+
() => ({
|
|
160
|
+
draggableId: descriptor.id,
|
|
161
|
+
type: descriptor.type,
|
|
162
|
+
source: {
|
|
163
|
+
index: descriptor.index,
|
|
164
|
+
droppableId: descriptor.droppableId,
|
|
165
|
+
},
|
|
166
|
+
}),
|
|
167
|
+
[descriptor.droppableId, descriptor.id, descriptor.index, descriptor.type],
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
return children(provided, mapped.snapshot, rubric);
|
|
171
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import type { BoxModel } from 'css-box-model';
|
|
3
|
+
import { combine, transforms, transitions } from '../../animation';
|
|
4
|
+
import type { DraggableDimension } from '../../types';
|
|
5
|
+
import type {
|
|
6
|
+
DraggingStyle,
|
|
7
|
+
NotDraggingStyle,
|
|
8
|
+
ZIndexOptions,
|
|
9
|
+
DropAnimation,
|
|
10
|
+
SecondaryMapProps,
|
|
11
|
+
DraggingMapProps,
|
|
12
|
+
DraggableStyle,
|
|
13
|
+
MappedProps,
|
|
14
|
+
} from './draggable-types';
|
|
15
|
+
|
|
16
|
+
export const zIndexOptions: ZIndexOptions = {
|
|
17
|
+
dragging: 5000,
|
|
18
|
+
dropAnimating: 4500,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const getDraggingTransition = (
|
|
22
|
+
shouldAnimateDragMovement: boolean,
|
|
23
|
+
dropping: ?DropAnimation,
|
|
24
|
+
): string => {
|
|
25
|
+
if (dropping) {
|
|
26
|
+
return transitions.drop(dropping.duration);
|
|
27
|
+
}
|
|
28
|
+
if (shouldAnimateDragMovement) {
|
|
29
|
+
return transitions.snap;
|
|
30
|
+
}
|
|
31
|
+
return transitions.fluid;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const getDraggingOpacity = (
|
|
35
|
+
isCombining: boolean,
|
|
36
|
+
isDropAnimating: boolean,
|
|
37
|
+
): ?number => {
|
|
38
|
+
// if not combining: no not impact opacity
|
|
39
|
+
if (!isCombining) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return isDropAnimating ? combine.opacity.drop : combine.opacity.combining;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const getShouldDraggingAnimate = (dragging: DraggingMapProps): boolean => {
|
|
47
|
+
if (dragging.forceShouldAnimate != null) {
|
|
48
|
+
return dragging.forceShouldAnimate;
|
|
49
|
+
}
|
|
50
|
+
return dragging.mode === 'SNAP';
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
function getDraggingStyle(dragging: DraggingMapProps): DraggingStyle {
|
|
54
|
+
const dimension: DraggableDimension = dragging.dimension;
|
|
55
|
+
const box: BoxModel = dimension.client;
|
|
56
|
+
const { offset, combineWith, dropping } = dragging;
|
|
57
|
+
|
|
58
|
+
const isCombining: boolean = Boolean(combineWith);
|
|
59
|
+
|
|
60
|
+
const shouldAnimate: boolean = getShouldDraggingAnimate(dragging);
|
|
61
|
+
const isDropAnimating: boolean = Boolean(dropping);
|
|
62
|
+
|
|
63
|
+
const transform: ?string = isDropAnimating
|
|
64
|
+
? transforms.drop(offset, isCombining)
|
|
65
|
+
: transforms.moveTo(offset);
|
|
66
|
+
|
|
67
|
+
const style: DraggingStyle = {
|
|
68
|
+
// ## Placement
|
|
69
|
+
position: 'fixed',
|
|
70
|
+
// As we are applying the margins we need to align to the start of the marginBox
|
|
71
|
+
top: box.marginBox.top,
|
|
72
|
+
left: box.marginBox.left,
|
|
73
|
+
|
|
74
|
+
// ## Sizing
|
|
75
|
+
// Locking these down as pulling the node out of the DOM could cause it to change size
|
|
76
|
+
boxSizing: 'border-box',
|
|
77
|
+
width: box.borderBox.width,
|
|
78
|
+
height: box.borderBox.height,
|
|
79
|
+
|
|
80
|
+
// ## Movement
|
|
81
|
+
// Opting out of the standard css transition for the dragging item
|
|
82
|
+
transition: getDraggingTransition(shouldAnimate, dropping),
|
|
83
|
+
transform,
|
|
84
|
+
opacity: getDraggingOpacity(isCombining, isDropAnimating),
|
|
85
|
+
// ## Layering
|
|
86
|
+
zIndex: isDropAnimating
|
|
87
|
+
? zIndexOptions.dropAnimating
|
|
88
|
+
: zIndexOptions.dragging,
|
|
89
|
+
|
|
90
|
+
// ## Blocking any pointer events on the dragging or dropping item
|
|
91
|
+
// global styles on cover while dragging
|
|
92
|
+
pointerEvents: 'none',
|
|
93
|
+
};
|
|
94
|
+
return style;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function getSecondaryStyle(secondary: SecondaryMapProps): NotDraggingStyle {
|
|
98
|
+
return {
|
|
99
|
+
transform: transforms.moveTo(secondary.offset),
|
|
100
|
+
// transition style is applied in the head
|
|
101
|
+
transition: secondary.shouldAnimateDisplacement ? null : 'none',
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export default function getStyle(mapped: MappedProps): DraggableStyle {
|
|
106
|
+
return mapped.type === 'DRAGGING'
|
|
107
|
+
? getDraggingStyle(mapped)
|
|
108
|
+
: getSecondaryStyle(mapped);
|
|
109
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
import { invariant } from '../../invariant';
|
|
4
|
+
import { isInteger } from '../../native-with-fallback';
|
|
5
|
+
import type { DraggableId, ContextId } from '../../types';
|
|
6
|
+
import type { Props } from './draggable-types';
|
|
7
|
+
import checkIsValidInnerRef from '../check-is-valid-inner-ref';
|
|
8
|
+
import findDragHandle from '../get-elements/find-drag-handle';
|
|
9
|
+
import useDevSetupWarning from '../use-dev-setup-warning';
|
|
10
|
+
import useDev from '../use-dev';
|
|
11
|
+
|
|
12
|
+
export function useValidation(
|
|
13
|
+
props: Props,
|
|
14
|
+
contextId: ContextId,
|
|
15
|
+
getRef: () => ?HTMLElement,
|
|
16
|
+
) {
|
|
17
|
+
// running after every update in development
|
|
18
|
+
useDevSetupWarning(() => {
|
|
19
|
+
function prefix(id: DraggableId): string {
|
|
20
|
+
return `Draggable[id: ${id}]: `;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// wrapping entire block for better minification
|
|
24
|
+
const id: ?DraggableId = props.draggableId;
|
|
25
|
+
invariant(id, 'Draggable requires a draggableId');
|
|
26
|
+
invariant(
|
|
27
|
+
typeof id === 'string',
|
|
28
|
+
`Draggable requires a [string] draggableId.
|
|
29
|
+
Provided: [type: ${typeof id}] (value: ${id})`,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
invariant(
|
|
33
|
+
isInteger(props.index),
|
|
34
|
+
`${prefix(id)} requires an integer index prop`,
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
if (props.mapped.type === 'DRAGGING') {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Checking provided ref (only when not dragging as it might be removed)
|
|
42
|
+
checkIsValidInnerRef(getRef());
|
|
43
|
+
|
|
44
|
+
// Checking that drag handle is provided
|
|
45
|
+
// Only running check when enabled.
|
|
46
|
+
// When not enabled there is no drag handle props
|
|
47
|
+
if (props.isEnabled) {
|
|
48
|
+
invariant(
|
|
49
|
+
findDragHandle(contextId, id),
|
|
50
|
+
`${prefix(id)} Unable to find drag handle`,
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// we expect isClone not to change for entire component's life
|
|
57
|
+
export function useClonePropValidation(isClone: boolean) {
|
|
58
|
+
useDev(() => {
|
|
59
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
60
|
+
const initialRef = useRef<boolean>(isClone);
|
|
61
|
+
|
|
62
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
63
|
+
useDevSetupWarning(() => {
|
|
64
|
+
invariant(
|
|
65
|
+
isClone === initialRef.current,
|
|
66
|
+
'Draggable isClone prop value changed during component life',
|
|
67
|
+
);
|
|
68
|
+
}, [isClone]);
|
|
69
|
+
});
|
|
70
|
+
}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
// @flow
|
|
2
|
+
// eslint-disable-next-line no-unused-vars
|
|
3
|
+
import { Component } from 'react';
|
|
4
|
+
import { connect } from 'react-redux';
|
|
5
|
+
import memoizeOne from 'memoize-one';
|
|
6
|
+
import { invariant } from '../../invariant';
|
|
7
|
+
import type {
|
|
8
|
+
State,
|
|
9
|
+
DroppableId,
|
|
10
|
+
DraggableId,
|
|
11
|
+
CompletedDrag,
|
|
12
|
+
DraggableDimension,
|
|
13
|
+
DimensionMap,
|
|
14
|
+
TypeId,
|
|
15
|
+
Critical,
|
|
16
|
+
DraggableRubric,
|
|
17
|
+
DraggableDescriptor,
|
|
18
|
+
} from '../../types';
|
|
19
|
+
import type {
|
|
20
|
+
MapProps,
|
|
21
|
+
OwnProps,
|
|
22
|
+
DefaultProps,
|
|
23
|
+
Selector,
|
|
24
|
+
DispatchProps,
|
|
25
|
+
StateSnapshot,
|
|
26
|
+
UseClone,
|
|
27
|
+
DraggableChildrenFn,
|
|
28
|
+
} from './droppable-types';
|
|
29
|
+
import Droppable from './droppable';
|
|
30
|
+
import isStrictEqual from '../is-strict-equal';
|
|
31
|
+
import whatIsDraggedOver from '../../state/droppable/what-is-dragged-over';
|
|
32
|
+
import { updateViewportMaxScroll as updateViewportMaxScrollAction } from '../../state/action-creators';
|
|
33
|
+
import StoreContext from '../context/store-context';
|
|
34
|
+
import whatIsDraggedOverFromResult from '../../state/droppable/what-is-dragged-over-from-result';
|
|
35
|
+
|
|
36
|
+
const isMatchingType = (type: TypeId, critical: Critical): boolean =>
|
|
37
|
+
type === critical.droppable.type;
|
|
38
|
+
|
|
39
|
+
const getDraggable = (
|
|
40
|
+
critical: Critical,
|
|
41
|
+
dimensions: DimensionMap,
|
|
42
|
+
): DraggableDimension => dimensions.draggables[critical.draggable.id];
|
|
43
|
+
|
|
44
|
+
// Returning a function to ensure each
|
|
45
|
+
// Droppable gets its own selector
|
|
46
|
+
export const makeMapStateToProps = (): Selector => {
|
|
47
|
+
const idleWithAnimation: MapProps = {
|
|
48
|
+
placeholder: null,
|
|
49
|
+
shouldAnimatePlaceholder: true,
|
|
50
|
+
snapshot: {
|
|
51
|
+
isDraggingOver: false,
|
|
52
|
+
draggingOverWith: null,
|
|
53
|
+
draggingFromThisWith: null,
|
|
54
|
+
isUsingPlaceholder: false,
|
|
55
|
+
},
|
|
56
|
+
useClone: null,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const idleWithoutAnimation = {
|
|
60
|
+
...idleWithAnimation,
|
|
61
|
+
shouldAnimatePlaceholder: false,
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const getDraggableRubric = memoizeOne(
|
|
65
|
+
(descriptor: DraggableDescriptor): DraggableRubric => ({
|
|
66
|
+
draggableId: descriptor.id,
|
|
67
|
+
type: descriptor.type,
|
|
68
|
+
source: {
|
|
69
|
+
index: descriptor.index,
|
|
70
|
+
droppableId: descriptor.droppableId,
|
|
71
|
+
},
|
|
72
|
+
}),
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
const getMapProps = memoizeOne(
|
|
76
|
+
(
|
|
77
|
+
id: DroppableId,
|
|
78
|
+
isEnabled: boolean,
|
|
79
|
+
isDraggingOverForConsumer: boolean,
|
|
80
|
+
isDraggingOverForImpact: boolean,
|
|
81
|
+
dragging: DraggableDimension,
|
|
82
|
+
// snapshot: StateSnapshot,
|
|
83
|
+
renderClone: ?DraggableChildrenFn,
|
|
84
|
+
): MapProps => {
|
|
85
|
+
const draggableId: DraggableId = dragging.descriptor.id;
|
|
86
|
+
const isHome: boolean = dragging.descriptor.droppableId === id;
|
|
87
|
+
|
|
88
|
+
if (isHome) {
|
|
89
|
+
const useClone: ?UseClone = renderClone
|
|
90
|
+
? {
|
|
91
|
+
render: renderClone,
|
|
92
|
+
dragging: getDraggableRubric(dragging.descriptor),
|
|
93
|
+
}
|
|
94
|
+
: null;
|
|
95
|
+
|
|
96
|
+
const snapshot: StateSnapshot = {
|
|
97
|
+
isDraggingOver: isDraggingOverForConsumer,
|
|
98
|
+
draggingOverWith: isDraggingOverForConsumer ? draggableId : null,
|
|
99
|
+
draggingFromThisWith: draggableId,
|
|
100
|
+
isUsingPlaceholder: true,
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
placeholder: dragging.placeholder,
|
|
105
|
+
shouldAnimatePlaceholder: false,
|
|
106
|
+
snapshot,
|
|
107
|
+
useClone,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!isEnabled) {
|
|
112
|
+
return idleWithoutAnimation;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// not over foreign list - return idle
|
|
116
|
+
if (!isDraggingOverForImpact) {
|
|
117
|
+
return idleWithAnimation;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const snapshot: StateSnapshot = {
|
|
121
|
+
isDraggingOver: isDraggingOverForConsumer,
|
|
122
|
+
draggingOverWith: draggableId,
|
|
123
|
+
draggingFromThisWith: null,
|
|
124
|
+
isUsingPlaceholder: true,
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
placeholder: dragging.placeholder,
|
|
129
|
+
// Animating placeholder in foreign list
|
|
130
|
+
shouldAnimatePlaceholder: true,
|
|
131
|
+
snapshot,
|
|
132
|
+
useClone: null,
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
const selector = (state: State, ownProps: OwnProps): MapProps => {
|
|
138
|
+
// not checking if item is disabled as we need the home list to display a placeholder
|
|
139
|
+
|
|
140
|
+
const id: DroppableId = ownProps.droppableId;
|
|
141
|
+
const type: TypeId = ownProps.type;
|
|
142
|
+
const isEnabled: boolean = !ownProps.isDropDisabled;
|
|
143
|
+
const renderClone: ?DraggableChildrenFn = ownProps.renderClone;
|
|
144
|
+
|
|
145
|
+
if (state.isDragging) {
|
|
146
|
+
const critical: Critical = state.critical;
|
|
147
|
+
if (!isMatchingType(type, critical)) {
|
|
148
|
+
return idleWithoutAnimation;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const dragging: DraggableDimension = getDraggable(
|
|
152
|
+
critical,
|
|
153
|
+
state.dimensions,
|
|
154
|
+
);
|
|
155
|
+
const isDraggingOver: boolean = whatIsDraggedOver(state.impact) === id;
|
|
156
|
+
|
|
157
|
+
return getMapProps(
|
|
158
|
+
id,
|
|
159
|
+
isEnabled,
|
|
160
|
+
isDraggingOver,
|
|
161
|
+
isDraggingOver,
|
|
162
|
+
dragging,
|
|
163
|
+
renderClone,
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (state.phase === 'DROP_ANIMATING') {
|
|
168
|
+
const completed: CompletedDrag = state.completed;
|
|
169
|
+
if (!isMatchingType(type, completed.critical)) {
|
|
170
|
+
return idleWithoutAnimation;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const dragging: DraggableDimension = getDraggable(
|
|
174
|
+
completed.critical,
|
|
175
|
+
state.dimensions,
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
// Snapshot based on result and not impact
|
|
179
|
+
// The result might be null (cancel) but the impact is populated
|
|
180
|
+
// to move everything back
|
|
181
|
+
return getMapProps(
|
|
182
|
+
id,
|
|
183
|
+
isEnabled,
|
|
184
|
+
whatIsDraggedOverFromResult(completed.result) === id,
|
|
185
|
+
whatIsDraggedOver(completed.impact) === id,
|
|
186
|
+
dragging,
|
|
187
|
+
renderClone,
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
if (state.phase === 'IDLE' && state.completed && !state.shouldFlush) {
|
|
192
|
+
const completed: CompletedDrag = state.completed;
|
|
193
|
+
if (!isMatchingType(type, completed.critical)) {
|
|
194
|
+
return idleWithoutAnimation;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// Looking at impact as this controls the placeholder
|
|
198
|
+
const wasOver: boolean = whatIsDraggedOver(completed.impact) === id;
|
|
199
|
+
const wasCombining: boolean = Boolean(
|
|
200
|
+
completed.impact.at && completed.impact.at.type === 'COMBINE',
|
|
201
|
+
);
|
|
202
|
+
const isHome: boolean = completed.critical.droppable.id === id;
|
|
203
|
+
|
|
204
|
+
if (wasOver) {
|
|
205
|
+
// if reordering we need to cut an animation immediately
|
|
206
|
+
// if merging: animate placeholder closed after drop
|
|
207
|
+
return wasCombining ? idleWithAnimation : idleWithoutAnimation;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// we need to animate the home placeholder closed if it is not
|
|
211
|
+
// being dropped into
|
|
212
|
+
if (isHome) {
|
|
213
|
+
return idleWithAnimation;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return idleWithoutAnimation;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// default: including when flushed
|
|
220
|
+
return idleWithoutAnimation;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
return selector;
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const mapDispatchToProps: DispatchProps = {
|
|
227
|
+
updateViewportMaxScroll: updateViewportMaxScrollAction,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
function getBody(): HTMLElement {
|
|
231
|
+
invariant(document.body, 'document.body is not ready');
|
|
232
|
+
return document.body;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const defaultProps = ({
|
|
236
|
+
mode: 'standard',
|
|
237
|
+
type: 'DEFAULT',
|
|
238
|
+
direction: 'vertical',
|
|
239
|
+
isDropDisabled: false,
|
|
240
|
+
isCombineEnabled: false,
|
|
241
|
+
ignoreContainerClipping: false,
|
|
242
|
+
renderClone: null,
|
|
243
|
+
getContainerForClone: getBody,
|
|
244
|
+
}: DefaultProps);
|
|
245
|
+
|
|
246
|
+
// Abstract class allows to specify props and defaults to component.
|
|
247
|
+
// All other ways give any or do not let add default props.
|
|
248
|
+
// eslint-disable-next-line
|
|
249
|
+
/*::
|
|
250
|
+
class DroppableType extends Component<OwnProps> {
|
|
251
|
+
static defaultProps = defaultProps;
|
|
252
|
+
}
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
// Leaning heavily on the default shallow equality checking
|
|
256
|
+
// that `connect` provides.
|
|
257
|
+
// It avoids needing to do it own within `Droppable`
|
|
258
|
+
const ConnectedDroppable: typeof DroppableType = connect(
|
|
259
|
+
// returning a function so each component can do its own memoization
|
|
260
|
+
makeMapStateToProps,
|
|
261
|
+
// no dispatch props for droppable
|
|
262
|
+
mapDispatchToProps,
|
|
263
|
+
// mergeProps - using default
|
|
264
|
+
null,
|
|
265
|
+
// $FlowFixMe: current react-redux type does not know about context property
|
|
266
|
+
{
|
|
267
|
+
// Ensuring our context does not clash with consumers
|
|
268
|
+
context: StoreContext,
|
|
269
|
+
// pure: true is default value, but being really clear
|
|
270
|
+
pure: true,
|
|
271
|
+
// When pure, compares the result of mapStateToProps to its previous value.
|
|
272
|
+
// Default value: shallowEqual
|
|
273
|
+
// Switching to a strictEqual as we return a memoized object on changes
|
|
274
|
+
areStatePropsEqual: isStrictEqual,
|
|
275
|
+
},
|
|
276
|
+
)(Droppable);
|
|
277
|
+
|
|
278
|
+
ConnectedDroppable.defaultProps = defaultProps;
|
|
279
|
+
|
|
280
|
+
export default ConnectedDroppable;
|