@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.
Files changed (243) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/LICENSE +13 -0
  3. package/README.md +178 -0
  4. package/dist/react-beautiful-dnd.cjs.js +8728 -0
  5. package/dist/react-beautiful-dnd.cjs.js.flow +3 -0
  6. package/dist/react-beautiful-dnd.esm.js +8715 -0
  7. package/dist/react-beautiful-dnd.js +11726 -0
  8. package/dist/react-beautiful-dnd.min.js +1 -0
  9. package/package.json +155 -0
  10. package/src/animation.js +75 -0
  11. package/src/debug/middleware/action-timing-average.js +52 -0
  12. package/src/debug/middleware/action-timing.js +16 -0
  13. package/src/debug/middleware/log.js +26 -0
  14. package/src/debug/middleware/user-timing.js +16 -0
  15. package/src/debug/timings.js +86 -0
  16. package/src/dev-warning.js +50 -0
  17. package/src/empty.js +6 -0
  18. package/src/index.js +67 -0
  19. package/src/invariant.js +33 -0
  20. package/src/native-with-fallback.js +69 -0
  21. package/src/screen-reader-message-preset.js +134 -0
  22. package/src/state/action-creators.js +328 -0
  23. package/src/state/auto-scroller/auto-scroller-types.js +8 -0
  24. package/src/state/auto-scroller/can-scroll.js +160 -0
  25. package/src/state/auto-scroller/fluid-scroller/config.js +25 -0
  26. package/src/state/auto-scroller/fluid-scroller/did-start-in-scrollable-area.js +1 -0
  27. package/src/state/auto-scroller/fluid-scroller/get-best-scrollable-droppable.js +77 -0
  28. package/src/state/auto-scroller/fluid-scroller/get-droppable-scroll-change.js +50 -0
  29. package/src/state/auto-scroller/fluid-scroller/get-percentage.js +25 -0
  30. package/src/state/auto-scroller/fluid-scroller/get-scroll/adjust-for-size-limits.js +30 -0
  31. package/src/state/auto-scroller/fluid-scroller/get-scroll/buffer-thresholds/calc-axis-scroll-conditions.js +68 -0
  32. package/src/state/auto-scroller/fluid-scroller/get-scroll/buffer-thresholds/get-scroll-conditions.js +56 -0
  33. package/src/state/auto-scroller/fluid-scroller/get-scroll/buffer-thresholds/index.js +66 -0
  34. package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/dampen-value-by-time.js +48 -0
  35. package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/get-distance-thresholds.js +31 -0
  36. package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/get-value-from-distance.js +67 -0
  37. package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/get-value.js +51 -0
  38. package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/index.js +50 -0
  39. package/src/state/auto-scroller/fluid-scroller/get-scroll/get-scroll-on-axis/min-scroll.js +4 -0
  40. package/src/state/auto-scroller/fluid-scroller/get-scroll/index.js +139 -0
  41. package/src/state/auto-scroller/fluid-scroller/get-window-scroll-change.js +43 -0
  42. package/src/state/auto-scroller/fluid-scroller/index.js +99 -0
  43. package/src/state/auto-scroller/fluid-scroller/scroll.js +80 -0
  44. package/src/state/auto-scroller/index.js +59 -0
  45. package/src/state/auto-scroller/jump-scroller.js +139 -0
  46. package/src/state/axis.js +26 -0
  47. package/src/state/calculate-drag-impact/calculate-reorder-impact.js +136 -0
  48. package/src/state/can-start-drag.js +29 -0
  49. package/src/state/create-store.js +97 -0
  50. package/src/state/did-start-after-critical.js +9 -0
  51. package/src/state/dimension-marshal/dimension-marshal-types.js +46 -0
  52. package/src/state/dimension-marshal/dimension-marshal.js +218 -0
  53. package/src/state/dimension-marshal/get-initial-publish.js +66 -0
  54. package/src/state/dimension-marshal/while-dragging-publisher.js +146 -0
  55. package/src/state/dimension-structures.js +35 -0
  56. package/src/state/droppable/get-droppable.js +101 -0
  57. package/src/state/droppable/is-home-of.js +7 -0
  58. package/src/state/droppable/scroll-droppable.js +53 -0
  59. package/src/state/droppable/should-use-placeholder.js +7 -0
  60. package/src/state/droppable/util/clip.js +17 -0
  61. package/src/state/droppable/util/get-subject.js +63 -0
  62. package/src/state/droppable/what-is-dragged-over-from-result.js +16 -0
  63. package/src/state/droppable/what-is-dragged-over.js +16 -0
  64. package/src/state/droppable/with-placeholder.js +174 -0
  65. package/src/state/get-center-from-impact/get-client-border-box-center/get-client-from-page-border-box-center.js +29 -0
  66. package/src/state/get-center-from-impact/get-client-border-box-center/index.js +44 -0
  67. package/src/state/get-center-from-impact/get-page-border-box-center/index.js +70 -0
  68. package/src/state/get-center-from-impact/get-page-border-box-center/when-combining.js +39 -0
  69. package/src/state/get-center-from-impact/get-page-border-box-center/when-reordering.js +112 -0
  70. package/src/state/get-center-from-impact/move-relative-to.js +66 -0
  71. package/src/state/get-combined-item-displacement.js +34 -0
  72. package/src/state/get-displaced-by.js +17 -0
  73. package/src/state/get-displacement-groups.js +130 -0
  74. package/src/state/get-drag-impact/get-combine-impact.js +130 -0
  75. package/src/state/get-drag-impact/get-reorder-impact.js +143 -0
  76. package/src/state/get-drag-impact/index.js +93 -0
  77. package/src/state/get-draggables-inside-droppable.js +31 -0
  78. package/src/state/get-droppable-over.js +158 -0
  79. package/src/state/get-frame.js +10 -0
  80. package/src/state/get-home-location.js +7 -0
  81. package/src/state/get-impact-location.js +16 -0
  82. package/src/state/get-is-displaced.js +11 -0
  83. package/src/state/get-lift-effect.js +82 -0
  84. package/src/state/get-max-scroll.js +30 -0
  85. package/src/state/is-movement-allowed.js +6 -0
  86. package/src/state/is-within.js +9 -0
  87. package/src/state/middleware/auto-scroll.js +38 -0
  88. package/src/state/middleware/dimension-marshal-stopper.js +20 -0
  89. package/src/state/middleware/drop/drop-animation-finish-middleware.js +21 -0
  90. package/src/state/middleware/drop/drop-animation-flush-on-scroll-middleware.js +63 -0
  91. package/src/state/middleware/drop/drop-middleware.js +146 -0
  92. package/src/state/middleware/drop/get-drop-duration.js +47 -0
  93. package/src/state/middleware/drop/get-drop-impact.js +77 -0
  94. package/src/state/middleware/drop/get-new-home-client-offset.js +54 -0
  95. package/src/state/middleware/drop/index.js +2 -0
  96. package/src/state/middleware/focus.js +42 -0
  97. package/src/state/middleware/lift.js +66 -0
  98. package/src/state/middleware/pending-drop.js +37 -0
  99. package/src/state/middleware/responders/async-marshal.js +55 -0
  100. package/src/state/middleware/responders/expiring-announce.js +44 -0
  101. package/src/state/middleware/responders/index.js +2 -0
  102. package/src/state/middleware/responders/is-equal.js +57 -0
  103. package/src/state/middleware/responders/publisher.js +253 -0
  104. package/src/state/middleware/responders/responders-middleware.js +75 -0
  105. package/src/state/middleware/scroll-listener.js +31 -0
  106. package/src/state/middleware/style.js +22 -0
  107. package/src/state/middleware/util/validate-dimensions.js +71 -0
  108. package/src/state/move-in-direction/index.js +84 -0
  109. package/src/state/move-in-direction/move-cross-axis/get-best-cross-axis-droppable.js +168 -0
  110. package/src/state/move-in-direction/move-cross-axis/get-closest-draggable.js +79 -0
  111. package/src/state/move-in-direction/move-cross-axis/index.js +109 -0
  112. package/src/state/move-in-direction/move-cross-axis/move-to-new-droppable.js +121 -0
  113. package/src/state/move-in-direction/move-cross-axis/without-starting-displacement.js +31 -0
  114. package/src/state/move-in-direction/move-in-direction-types.js +9 -0
  115. package/src/state/move-in-direction/move-to-next-place/index.js +132 -0
  116. package/src/state/move-in-direction/move-to-next-place/is-totally-visible-in-new-location.js +52 -0
  117. package/src/state/move-in-direction/move-to-next-place/move-to-next-combine/index.js +97 -0
  118. package/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-combine.js +52 -0
  119. package/src/state/move-in-direction/move-to-next-place/move-to-next-index/from-reorder.js +43 -0
  120. package/src/state/move-in-direction/move-to-next-place/move-to-next-index/index.js +86 -0
  121. package/src/state/no-impact.js +33 -0
  122. package/src/state/patch-dimension-map.js +11 -0
  123. package/src/state/patch-droppable-map.js +10 -0
  124. package/src/state/position.js +58 -0
  125. package/src/state/post-reducer/when-moving/refresh-snap.js +67 -0
  126. package/src/state/post-reducer/when-moving/update.js +120 -0
  127. package/src/state/publish-while-dragging-in-virtual/adjust-additions-for-scroll-changes.js +58 -0
  128. package/src/state/publish-while-dragging-in-virtual/index.js +158 -0
  129. package/src/state/publish-while-dragging-in-virtual/offset-draggable.js +35 -0
  130. package/src/state/recompute-placeholders.js +99 -0
  131. package/src/state/rect.js +7 -0
  132. package/src/state/reducer.js +457 -0
  133. package/src/state/registry/create-registry.js +162 -0
  134. package/src/state/registry/registry-types.js +98 -0
  135. package/src/state/registry/use-registry.js +20 -0
  136. package/src/state/remove-draggable-from-list.js +13 -0
  137. package/src/state/scroll-viewport.js +34 -0
  138. package/src/state/spacing.js +45 -0
  139. package/src/state/store-types.js +16 -0
  140. package/src/state/update-displacement-visibility/recompute.js +54 -0
  141. package/src/state/update-displacement-visibility/speculatively-increase.js +111 -0
  142. package/src/state/visibility/is-partially-visible-through-frame.js +60 -0
  143. package/src/state/visibility/is-position-in-frame.js +12 -0
  144. package/src/state/visibility/is-totally-visible-through-frame-on-axis.js +19 -0
  145. package/src/state/visibility/is-totally-visible-through-frame.js +18 -0
  146. package/src/state/visibility/is-visible.js +102 -0
  147. package/src/state/with-scroll-change/with-all-displacement.js +15 -0
  148. package/src/state/with-scroll-change/with-droppable-displacement.js +13 -0
  149. package/src/state/with-scroll-change/with-droppable-scroll.js +13 -0
  150. package/src/state/with-scroll-change/with-viewport-displacement.js +7 -0
  151. package/src/types.js +542 -0
  152. package/src/view/animate-in-out/animate-in-out.jsx +95 -0
  153. package/src/view/animate-in-out/index.js +2 -0
  154. package/src/view/check-is-valid-inner-ref.js +15 -0
  155. package/src/view/context/app-context.js +19 -0
  156. package/src/view/context/droppable-context.js +11 -0
  157. package/src/view/context/store-context.js +5 -0
  158. package/src/view/data-attributes.js +37 -0
  159. package/src/view/drag-drop-context/app.jsx +273 -0
  160. package/src/view/drag-drop-context/check-doctype.js +39 -0
  161. package/src/view/drag-drop-context/check-react-version.js +71 -0
  162. package/src/view/drag-drop-context/drag-drop-context-types.js +7 -0
  163. package/src/view/drag-drop-context/drag-drop-context.jsx +68 -0
  164. package/src/view/drag-drop-context/error-boundary.jsx +88 -0
  165. package/src/view/drag-drop-context/index.js +2 -0
  166. package/src/view/drag-drop-context/use-startup-validation.js +13 -0
  167. package/src/view/drag-drop-context/use-unique-context-id.js +13 -0
  168. package/src/view/draggable/connected-draggable.js +372 -0
  169. package/src/view/draggable/draggable-api.jsx +48 -0
  170. package/src/view/draggable/draggable-types.js +191 -0
  171. package/src/view/draggable/draggable.jsx +171 -0
  172. package/src/view/draggable/get-style.js +109 -0
  173. package/src/view/draggable/index.js +2 -0
  174. package/src/view/draggable/use-validation.js +70 -0
  175. package/src/view/droppable/connected-droppable.js +280 -0
  176. package/src/view/droppable/droppable-types.js +91 -0
  177. package/src/view/droppable/droppable.jsx +167 -0
  178. package/src/view/droppable/index.js +2 -0
  179. package/src/view/droppable/use-validation.js +101 -0
  180. package/src/view/event-bindings/bind-events.js +39 -0
  181. package/src/view/event-bindings/event-types.js +14 -0
  182. package/src/view/get-body-element.js +8 -0
  183. package/src/view/get-border-box-center-position.js +5 -0
  184. package/src/view/get-document-element.js +8 -0
  185. package/src/view/get-elements/find-drag-handle.js +38 -0
  186. package/src/view/get-elements/find-draggable.js +30 -0
  187. package/src/view/is-strict-equal.js +2 -0
  188. package/src/view/is-type-of-element/is-element.js +6 -0
  189. package/src/view/is-type-of-element/is-html-element.js +6 -0
  190. package/src/view/is-type-of-element/is-svg-element.js +12 -0
  191. package/src/view/key-codes.js +13 -0
  192. package/src/view/placeholder/index.js +2 -0
  193. package/src/view/placeholder/placeholder-types.js +16 -0
  194. package/src/view/placeholder/placeholder.jsx +198 -0
  195. package/src/view/scroll-listener.js +72 -0
  196. package/src/view/throw-if-invalid-inner-ref.js +15 -0
  197. package/src/view/use-announcer/index.js +2 -0
  198. package/src/view/use-announcer/use-announcer.js +80 -0
  199. package/src/view/use-dev-setup-warning.js +22 -0
  200. package/src/view/use-dev.js +9 -0
  201. package/src/view/use-draggable-publisher/get-dimension.js +44 -0
  202. package/src/view/use-draggable-publisher/index.js +2 -0
  203. package/src/view/use-draggable-publisher/use-draggable-publisher.js +87 -0
  204. package/src/view/use-droppable-publisher/check-for-nested-scroll-container.js +27 -0
  205. package/src/view/use-droppable-publisher/get-closest-scrollable.js +95 -0
  206. package/src/view/use-droppable-publisher/get-dimension.js +139 -0
  207. package/src/view/use-droppable-publisher/get-env.js +31 -0
  208. package/src/view/use-droppable-publisher/get-listener-options.js +12 -0
  209. package/src/view/use-droppable-publisher/get-scroll.js +7 -0
  210. package/src/view/use-droppable-publisher/index.js +2 -0
  211. package/src/view/use-droppable-publisher/is-in-fixed-container.js +21 -0
  212. package/src/view/use-droppable-publisher/use-droppable-publisher.js +283 -0
  213. package/src/view/use-focus-marshal/focus-marshal-types.js +13 -0
  214. package/src/view/use-focus-marshal/index.js +2 -0
  215. package/src/view/use-focus-marshal/use-focus-marshal.js +129 -0
  216. package/src/view/use-hidden-text-element/index.js +2 -0
  217. package/src/view/use-hidden-text-element/use-hidden-text-element.js +60 -0
  218. package/src/view/use-isomorphic-layout-effect.js +18 -0
  219. package/src/view/use-previous-ref.js +14 -0
  220. package/src/view/use-required-context.js +9 -0
  221. package/src/view/use-sensor-marshal/closest.js +50 -0
  222. package/src/view/use-sensor-marshal/find-closest-draggable-id-from-event.js +50 -0
  223. package/src/view/use-sensor-marshal/index.js +5 -0
  224. package/src/view/use-sensor-marshal/is-event-in-interactive-element.js +66 -0
  225. package/src/view/use-sensor-marshal/lock.js +48 -0
  226. package/src/view/use-sensor-marshal/sensors/use-keyboard-sensor.js +243 -0
  227. package/src/view/use-sensor-marshal/sensors/use-mouse-sensor.js +386 -0
  228. package/src/view/use-sensor-marshal/sensors/use-touch-sensor.js +461 -0
  229. package/src/view/use-sensor-marshal/sensors/util/prevent-standard-key-events.js +19 -0
  230. package/src/view/use-sensor-marshal/sensors/util/supported-page-visibility-event-name.js +29 -0
  231. package/src/view/use-sensor-marshal/use-sensor-marshal.js +495 -0
  232. package/src/view/use-sensor-marshal/use-validate-sensor-hooks.js +20 -0
  233. package/src/view/use-style-marshal/get-styles.js +170 -0
  234. package/src/view/use-style-marshal/index.js +2 -0
  235. package/src/view/use-style-marshal/style-marshal-types.js +8 -0
  236. package/src/view/use-style-marshal/use-style-marshal.js +126 -0
  237. package/src/view/use-unique-id.js +25 -0
  238. package/src/view/visually-hidden-style.js +16 -0
  239. package/src/view/window/get-max-window-scroll.js +19 -0
  240. package/src/view/window/get-viewport.js +49 -0
  241. package/src/view/window/get-window-from-el.js +3 -0
  242. package/src/view/window/get-window-scroll.js +30 -0
  243. 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,2 @@
1
+ // @flow
2
+ export { PublicDraggable as default } from './draggable-api';
@@ -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;