@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,372 @@
1
+ // @flow
2
+ import { type Position } from 'css-box-model';
3
+ // eslint-disable-next-line
4
+ import { Component } from 'react';
5
+ import memoizeOne from 'memoize-one';
6
+ import { connect } from 'react-redux';
7
+ import Draggable from './draggable';
8
+ import { origin, negate } from '../../state/position';
9
+ import isStrictEqual from '../is-strict-equal';
10
+ import * as animation from '../../animation';
11
+ import { dropAnimationFinished as dropAnimationFinishedAction } from '../../state/action-creators';
12
+ import type {
13
+ State,
14
+ DraggableId,
15
+ DroppableId,
16
+ DraggableDimension,
17
+ Displacement,
18
+ CompletedDrag,
19
+ DragImpact,
20
+ MovementMode,
21
+ DropResult,
22
+ LiftEffect,
23
+ Combine,
24
+ } from '../../types';
25
+ import type {
26
+ MapProps,
27
+ OwnProps,
28
+ DispatchProps,
29
+ Selector,
30
+ StateSnapshot,
31
+ DropAnimation,
32
+ } from './draggable-types';
33
+ import whatIsDraggedOver from '../../state/droppable/what-is-dragged-over';
34
+ import StoreContext from '../context/store-context';
35
+ import whatIsDraggedOverFromResult from '../../state/droppable/what-is-dragged-over-from-result';
36
+ import { tryGetCombine } from '../../state/get-impact-location';
37
+
38
+ const getCombineWithFromResult = (result: DropResult): ?DraggableId => {
39
+ return result.combine ? result.combine.draggableId : null;
40
+ };
41
+
42
+ const getCombineWithFromImpact = (impact: DragImpact): ?DraggableId => {
43
+ return impact.at && impact.at.type === 'COMBINE'
44
+ ? impact.at.combine.draggableId
45
+ : null;
46
+ };
47
+
48
+ type TrySelect = (state: State, ownProps: OwnProps) => ?MapProps;
49
+
50
+ function getDraggableSelector(): TrySelect {
51
+ const memoizedOffset = memoizeOne((x: number, y: number): Position => ({
52
+ x,
53
+ y,
54
+ }));
55
+
56
+ const getMemoizedSnapshot = memoizeOne(
57
+ (
58
+ mode: MovementMode,
59
+ isClone: boolean,
60
+ draggingOver: ?DroppableId,
61
+ combineWith: ?DraggableId,
62
+ dropping: ?DropAnimation,
63
+ ): StateSnapshot => ({
64
+ isDragging: true,
65
+ isClone,
66
+ isDropAnimating: Boolean(dropping),
67
+ dropAnimation: dropping,
68
+ mode,
69
+ draggingOver,
70
+ combineWith,
71
+ combineTargetFor: null,
72
+ }),
73
+ );
74
+
75
+ const getMemoizedProps = memoizeOne((
76
+ offset: Position,
77
+ mode: MovementMode,
78
+ dimension: DraggableDimension,
79
+ isClone: boolean,
80
+ // the id of the droppable you are over
81
+ draggingOver: ?DroppableId,
82
+ // the id of a draggable you are grouping with
83
+ combineWith: ?DraggableId,
84
+ forceShouldAnimate: ?boolean,
85
+ ): MapProps => ({
86
+ mapped: {
87
+ type: 'DRAGGING',
88
+ dropping: null,
89
+ draggingOver,
90
+ combineWith,
91
+ mode,
92
+ offset,
93
+ dimension,
94
+ forceShouldAnimate,
95
+ snapshot: getMemoizedSnapshot(
96
+ mode,
97
+ isClone,
98
+ draggingOver,
99
+ combineWith,
100
+ null,
101
+ ),
102
+ },
103
+ }));
104
+
105
+ const selector: TrySelect = (state: State, ownProps: OwnProps): ?MapProps => {
106
+ // Dragging
107
+ if (state.isDragging) {
108
+ // not the dragging item
109
+ if (state.critical.draggable.id !== ownProps.draggableId) {
110
+ return null;
111
+ }
112
+
113
+ const offset: Position = state.current.client.offset;
114
+ const dimension: DraggableDimension =
115
+ state.dimensions.draggables[ownProps.draggableId];
116
+ // const shouldAnimateDragMovement: boolean = state.shouldAnimate;
117
+ const draggingOver: ?DroppableId = whatIsDraggedOver(state.impact);
118
+ const combineWith: ?DraggableId = getCombineWithFromImpact(state.impact);
119
+ const forceShouldAnimate: ?boolean = state.forceShouldAnimate;
120
+
121
+ return getMemoizedProps(
122
+ memoizedOffset(offset.x, offset.y),
123
+ state.movementMode,
124
+ dimension,
125
+ ownProps.isClone,
126
+ draggingOver,
127
+ combineWith,
128
+ forceShouldAnimate,
129
+ );
130
+ }
131
+
132
+ // Dropping
133
+ if (state.phase === 'DROP_ANIMATING') {
134
+ const completed: CompletedDrag = state.completed;
135
+ if (completed.result.draggableId !== ownProps.draggableId) {
136
+ return null;
137
+ }
138
+
139
+ const isClone: boolean = ownProps.isClone;
140
+ const dimension: DraggableDimension =
141
+ state.dimensions.draggables[ownProps.draggableId];
142
+ const result: DropResult = completed.result;
143
+ const mode: MovementMode = result.mode;
144
+ // these need to be pulled from the result as they can be different to the final impact
145
+ const draggingOver: ?DroppableId = whatIsDraggedOverFromResult(result);
146
+ const combineWith: ?DraggableId = getCombineWithFromResult(result);
147
+ const duration: number = state.dropDuration;
148
+
149
+ // not memoized as it is the only execution
150
+ const dropping: DropAnimation = {
151
+ duration,
152
+ curve: animation.curves.drop,
153
+ moveTo: state.newHomeClientOffset,
154
+ opacity: combineWith ? animation.combine.opacity.drop : null,
155
+ scale: combineWith ? animation.combine.scale.drop : null,
156
+ };
157
+
158
+ return {
159
+ mapped: {
160
+ type: 'DRAGGING',
161
+ offset: state.newHomeClientOffset,
162
+ dimension,
163
+ dropping,
164
+ draggingOver,
165
+ combineWith,
166
+ mode,
167
+ forceShouldAnimate: null,
168
+ snapshot: getMemoizedSnapshot(
169
+ mode,
170
+ isClone,
171
+ draggingOver,
172
+ combineWith,
173
+ dropping,
174
+ ),
175
+ },
176
+ };
177
+ }
178
+
179
+ return null;
180
+ };
181
+
182
+ return selector;
183
+ }
184
+
185
+ function getSecondarySnapshot(combineTargetFor: ?DraggableId): StateSnapshot {
186
+ return {
187
+ isDragging: false,
188
+ isDropAnimating: false,
189
+ isClone: false,
190
+ dropAnimation: null,
191
+ mode: null,
192
+ draggingOver: null,
193
+ combineTargetFor,
194
+ combineWith: null,
195
+ };
196
+ }
197
+
198
+ const atRest: MapProps = {
199
+ mapped: {
200
+ type: 'SECONDARY',
201
+ offset: origin,
202
+ combineTargetFor: null,
203
+ shouldAnimateDisplacement: true,
204
+ snapshot: getSecondarySnapshot(null),
205
+ },
206
+ };
207
+
208
+ function getSecondarySelector(): TrySelect {
209
+ const memoizedOffset = memoizeOne((x: number, y: number): Position => ({
210
+ x,
211
+ y,
212
+ }));
213
+
214
+ const getMemoizedSnapshot = memoizeOne(getSecondarySnapshot);
215
+
216
+ const getMemoizedProps = memoizeOne(
217
+ (
218
+ offset: Position,
219
+ combineTargetFor: ?DraggableId = null,
220
+ shouldAnimateDisplacement: boolean,
221
+ ): MapProps => ({
222
+ mapped: {
223
+ type: 'SECONDARY',
224
+ offset,
225
+ combineTargetFor,
226
+ shouldAnimateDisplacement,
227
+ snapshot: getMemoizedSnapshot(combineTargetFor),
228
+ },
229
+ }),
230
+ );
231
+
232
+ // Is we are the combine target for something then we need to publish that
233
+ // otherwise we will return null to get the default props
234
+ const getFallback = (combineTargetFor: ?DraggableId): ?MapProps => {
235
+ return combineTargetFor
236
+ ? getMemoizedProps(origin, combineTargetFor, true)
237
+ : null;
238
+ };
239
+
240
+ const getProps = (
241
+ ownId: DraggableId,
242
+ draggingId: DraggableId,
243
+ impact: DragImpact,
244
+ afterCritical: LiftEffect,
245
+ ): ?MapProps => {
246
+ const visualDisplacement: ?Displacement = impact.displaced.visible[ownId];
247
+ const isAfterCriticalInVirtualList: boolean = Boolean(
248
+ afterCritical.inVirtualList && afterCritical.effected[ownId],
249
+ );
250
+
251
+ const combine: ?Combine = tryGetCombine(impact);
252
+ const combineTargetFor: ?DraggableId =
253
+ combine && combine.draggableId === ownId ? draggingId : null;
254
+
255
+ if (!visualDisplacement) {
256
+ if (!isAfterCriticalInVirtualList) {
257
+ return getFallback(combineTargetFor);
258
+ }
259
+
260
+ // After critical but not visibly displaced in a virtual list
261
+ // This can occur if:
262
+ // 1. the item is not visible (displaced.invisible)
263
+ // 2. We have moved out of the home list.
264
+
265
+ // Don't need to do anything - item is invisible
266
+ if (impact.displaced.invisible[ownId]) {
267
+ return null;
268
+ }
269
+
270
+ // We are no longer over the home list.
271
+ // We need to move backwards to close the gap that the dragging item has left
272
+ const change: Position = negate(afterCritical.displacedBy.point);
273
+ const offset: Position = memoizedOffset(change.x, change.y);
274
+ return getMemoizedProps(offset, combineTargetFor, true);
275
+ }
276
+
277
+ if (isAfterCriticalInVirtualList) {
278
+ // In a virtual list the removal of a dragging item does
279
+ // not cause the list to collapse. So when something is 'displaced'
280
+ // we can just leave it in the original spot.
281
+ return getFallback(combineTargetFor);
282
+ }
283
+ const displaceBy: Position = impact.displacedBy.point;
284
+ const offset: Position = memoizedOffset(displaceBy.x, displaceBy.y);
285
+
286
+ return getMemoizedProps(
287
+ offset,
288
+ combineTargetFor,
289
+ visualDisplacement.shouldAnimate,
290
+ );
291
+ };
292
+
293
+ const selector: TrySelect = (state: State, ownProps: OwnProps): ?MapProps => {
294
+ // Dragging
295
+ if (state.isDragging) {
296
+ // we do not care about the dragging item
297
+ if (state.critical.draggable.id === ownProps.draggableId) {
298
+ return null;
299
+ }
300
+
301
+ return getProps(
302
+ ownProps.draggableId,
303
+ state.critical.draggable.id,
304
+ state.impact,
305
+ state.afterCritical,
306
+ );
307
+ }
308
+
309
+ // Dropping
310
+ if (state.phase === 'DROP_ANIMATING') {
311
+ const completed: CompletedDrag = state.completed;
312
+ // do nothing if this was the dragging item
313
+ if (completed.result.draggableId === ownProps.draggableId) {
314
+ return null;
315
+ }
316
+ return getProps(
317
+ ownProps.draggableId,
318
+ completed.result.draggableId,
319
+ completed.impact,
320
+ completed.afterCritical,
321
+ );
322
+ }
323
+
324
+ // Otherwise
325
+ return null;
326
+ };
327
+
328
+ return selector;
329
+ }
330
+
331
+ // Returning a function to ensure each
332
+ // Draggable gets its own selector
333
+ export const makeMapStateToProps = (): Selector => {
334
+ const draggingSelector: TrySelect = getDraggableSelector();
335
+ const secondarySelector: TrySelect = getSecondarySelector();
336
+
337
+ const selector = (state: State, ownProps: OwnProps): MapProps =>
338
+ draggingSelector(state, ownProps) ||
339
+ secondarySelector(state, ownProps) ||
340
+ atRest;
341
+
342
+ return selector;
343
+ };
344
+
345
+ const mapDispatchToProps: DispatchProps = {
346
+ dropAnimationFinished: dropAnimationFinishedAction,
347
+ };
348
+
349
+ // Leaning heavily on the default shallow equality checking
350
+ // that `connect` provides.
351
+ // It avoids needing to do it own within `<Draggable />`
352
+ const ConnectedDraggable = connect(
353
+ // returning a function so each component can do its own memoization
354
+ makeMapStateToProps,
355
+ mapDispatchToProps,
356
+ // mergeProps: use default
357
+ null,
358
+ // options
359
+ // $FlowFixMe: current react-redux type does not know about context property
360
+ {
361
+ // Using our own context for the store to avoid clashing with consumers
362
+ context: StoreContext,
363
+ // Default value, but being really clear
364
+ pure: true,
365
+ // When pure, compares the result of mapStateToProps to its previous value.
366
+ // Default value: shallowEqual
367
+ // Switching to a strictEqual as we return a memoized object on changes
368
+ areStatePropsEqual: isStrictEqual,
369
+ },
370
+ )(Draggable);
371
+
372
+ export default ConnectedDraggable;
@@ -0,0 +1,48 @@
1
+ // @flow
2
+ import React from 'react';
3
+ import type { DraggableId } from '../../types';
4
+ import type { PublicOwnProps, PrivateOwnProps } from './draggable-types';
5
+ import ConnectedDraggable from './connected-draggable';
6
+ import useRequiredContext from '../use-required-context';
7
+ import DroppableContext, {
8
+ type DroppableContextValue,
9
+ } from '../context/droppable-context';
10
+
11
+ // We can use this to render a draggable with more control
12
+ // It is used by a Droppable to render a clone
13
+ export function PrivateDraggable(props: PrivateOwnProps) {
14
+ const droppableContext: DroppableContextValue = useRequiredContext(
15
+ DroppableContext,
16
+ );
17
+ // The droppable can render a clone of the draggable item.
18
+ // In that case we unmount the existing dragging item
19
+ const isUsingCloneFor: ?DraggableId = droppableContext.isUsingCloneFor;
20
+ if (isUsingCloneFor === props.draggableId && !props.isClone) {
21
+ return null;
22
+ }
23
+
24
+ return <ConnectedDraggable {...props} />;
25
+ }
26
+
27
+ // What we give to consumers
28
+ export function PublicDraggable(props: PublicOwnProps) {
29
+ // default values for props
30
+ const isEnabled: boolean =
31
+ typeof props.isDragDisabled === 'boolean' ? !props.isDragDisabled : true;
32
+ const canDragInteractiveElements: boolean = Boolean(
33
+ props.disableInteractiveElementBlocking,
34
+ );
35
+ const shouldRespectForcePress: boolean = Boolean(
36
+ props.shouldRespectForcePress,
37
+ );
38
+
39
+ return (
40
+ <PrivateDraggable
41
+ {...props}
42
+ isClone={false}
43
+ isEnabled={isEnabled}
44
+ canDragInteractiveElements={canDragInteractiveElements}
45
+ shouldRespectForcePress={shouldRespectForcePress}
46
+ />
47
+ );
48
+ }
@@ -0,0 +1,191 @@
1
+ // @flow
2
+ import { type Position } from 'css-box-model';
3
+ import { type Node } from 'react';
4
+ import type {
5
+ DraggableId,
6
+ DroppableId,
7
+ DraggableDimension,
8
+ State,
9
+ MovementMode,
10
+ ContextId,
11
+ ElementId,
12
+ DraggableRubric,
13
+ } from '../../types';
14
+ import { dropAnimationFinished } from '../../state/action-creators';
15
+
16
+ export type DraggingStyle = {|
17
+ position: 'fixed',
18
+ top: number,
19
+ left: number,
20
+ boxSizing: 'border-box',
21
+ width: number,
22
+ height: number,
23
+ transition: string,
24
+ transform: ?string,
25
+ zIndex: number,
26
+
27
+ // for combining
28
+ opacity: ?number,
29
+
30
+ // Avoiding any processing of mouse events.
31
+ // This is already applied by the shared styles during a drag.
32
+ // During a drop it prevents a draggable from being dragged.
33
+ // canStartDrag() will prevent drags in some cases for non primary draggable.
34
+ // It is also a minor performance optimisation
35
+ pointerEvents: 'none',
36
+ |};
37
+
38
+ export type NotDraggingStyle = {|
39
+ transform: ?string,
40
+ // null: use the global animation style
41
+ // none: skip animation (used in certain displacement situations)
42
+ transition: null | 'none',
43
+ |};
44
+
45
+ export type DraggableStyle = DraggingStyle | NotDraggingStyle;
46
+
47
+ export type ZIndexOptions = {|
48
+ dragging: number,
49
+ dropAnimating: number,
50
+ |};
51
+
52
+ // Props that can be spread onto the element directly
53
+ export type DraggableProps = {|
54
+ // inline style
55
+ style: ?DraggableStyle,
56
+ // used for shared global styles
57
+ 'data-rbd-draggable-context-id': ContextId,
58
+ // used for lookups
59
+ 'data-rbd-draggable-id': DraggableId,
60
+ // used to know when a transition ends
61
+ onTransitionEnd: ?(event: TransitionEvent) => void,
62
+ |};
63
+
64
+ export type DragHandleProps = {|
65
+ // what draggable the handle belongs to
66
+ 'data-rbd-drag-handle-draggable-id': DraggableId,
67
+
68
+ // What DragDropContext the drag handle is in
69
+ 'data-rbd-drag-handle-context-id': ContextId,
70
+
71
+ // We need a drag handle to be a widget in order to correctly set accessibility properties
72
+ // Note: JAWS and VoiceOver don't need the element to be a 'widget' to read the accessibility properties, but NVDA does
73
+ // Using `role="button"` but leaving the public API as a string to allow for changing without a major
74
+ role: string,
75
+
76
+ // Overriding default role to have a more descriptive text ("Draggable item")
77
+ // Sadly we cannot use this right now due an issue with lighthouse
78
+ // https://github.com/atlassian/react-beautiful-dnd/issues/1742
79
+ // 'aria-roledescription': string,
80
+
81
+ // Using the description property of the drag handle to provide usage instructions
82
+ 'aria-describedby': ElementId,
83
+
84
+ // Allow tabbing to this element
85
+ // Adding a tab index marks the element as interactive content: https://www.w3.org/TR/html51/dom.html#kinds-of-content-interactive-content
86
+ tabIndex: number,
87
+
88
+ // Opting out of html5 drag and drop
89
+ draggable: boolean,
90
+ onDragStart: (event: DragEvent) => void,
91
+ |};
92
+
93
+ export type Provided = {|
94
+ draggableProps: DraggableProps,
95
+ // will be null if the draggable is disabled
96
+ dragHandleProps: ?DragHandleProps,
97
+ // The following props will be removed once we move to react 16
98
+ innerRef: (?HTMLElement) => void,
99
+ |};
100
+
101
+ // to easily enable patching of styles
102
+ export type DropAnimation = {|
103
+ duration: number,
104
+ curve: string,
105
+ moveTo: Position,
106
+ opacity: ?number,
107
+ scale: ?number,
108
+ |};
109
+
110
+ export type StateSnapshot = {|
111
+ isDragging: boolean,
112
+ isDropAnimating: boolean,
113
+ isClone: boolean,
114
+ dropAnimation: ?DropAnimation,
115
+ draggingOver: ?DroppableId,
116
+ combineWith: ?DraggableId,
117
+ combineTargetFor: ?DraggableId,
118
+ mode: ?MovementMode,
119
+ |};
120
+
121
+ export type DispatchProps = {|
122
+ dropAnimationFinished: typeof dropAnimationFinished,
123
+ |};
124
+
125
+ export type DraggingMapProps = {|
126
+ type: 'DRAGGING',
127
+ offset: Position,
128
+ mode: MovementMode,
129
+ dropping: ?DropAnimation,
130
+ draggingOver: ?DraggableId,
131
+ combineWith: ?DraggableId,
132
+ dimension: DraggableDimension,
133
+ forceShouldAnimate: ?boolean,
134
+ snapshot: StateSnapshot,
135
+ |};
136
+
137
+ export type SecondaryMapProps = {|
138
+ type: 'SECONDARY',
139
+ offset: Position,
140
+ combineTargetFor: ?DraggableId,
141
+ shouldAnimateDisplacement: boolean,
142
+ snapshot: StateSnapshot,
143
+ |};
144
+
145
+ export type MappedProps = DraggingMapProps | SecondaryMapProps;
146
+
147
+ export type MapProps = {|
148
+ // when an item is being displaced by a dragging item,
149
+ // we need to know if that movement should be animated
150
+ mapped: MappedProps,
151
+ // dragging: ?DraggingMapProps,
152
+ // secondary: ?SecondaryMapProps,
153
+ |};
154
+
155
+ export type ChildrenFn = (
156
+ Provided,
157
+ StateSnapshot,
158
+ DraggableRubric,
159
+ ) => Node | null;
160
+
161
+ export type PublicOwnProps = {|
162
+ draggableId: DraggableId,
163
+ index: number,
164
+ children: ChildrenFn,
165
+
166
+ // optional own props
167
+ isDragDisabled?: boolean,
168
+ disableInteractiveElementBlocking?: boolean,
169
+ shouldRespectForcePress?: boolean,
170
+ |};
171
+
172
+ export type PrivateOwnProps = {|
173
+ ...PublicOwnProps,
174
+ isClone: boolean,
175
+ // no longer optional
176
+ isEnabled: boolean,
177
+ canDragInteractiveElements: boolean,
178
+ shouldRespectForcePress: boolean,
179
+ |};
180
+
181
+ export type OwnProps = {|
182
+ ...PrivateOwnProps,
183
+ |};
184
+
185
+ export type Props = {|
186
+ ...MapProps,
187
+ ...DispatchProps,
188
+ ...OwnProps,
189
+ |};
190
+
191
+ export type Selector = (state: State, ownProps: OwnProps) => MapProps;