@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,46 @@
1
+ // @flow
2
+ import type { Position } from 'css-box-model';
3
+ import type {
4
+ UpdateDroppableScrollArgs,
5
+ UpdateDroppableIsEnabledArgs,
6
+ UpdateDroppableIsCombineEnabledArgs,
7
+ } from '../action-creators';
8
+ import type {
9
+ DroppableId,
10
+ Critical,
11
+ DimensionMap,
12
+ LiftRequest,
13
+ Published,
14
+ Viewport,
15
+ } from '../../types';
16
+
17
+ export type StartPublishingResult = {|
18
+ critical: Critical,
19
+ dimensions: DimensionMap,
20
+ viewport: Viewport,
21
+ |};
22
+
23
+ export type DimensionMarshal = {|
24
+ // it is possible for a droppable to change whether it is enabled during a drag
25
+ updateDroppableIsEnabled: (id: DroppableId, isEnabled: boolean) => void,
26
+ // it is also possible to update whether combining is enabled
27
+ updateDroppableIsCombineEnabled: (
28
+ id: DroppableId,
29
+ isEnabled: boolean,
30
+ ) => void,
31
+ updateDroppableScroll: (id: DroppableId, newScroll: Position) => void,
32
+ scrollDroppable: (id: DroppableId, change: Position) => void,
33
+ // Entry
34
+ startPublishing: (request: LiftRequest) => StartPublishingResult,
35
+ stopPublishing: () => void,
36
+ |};
37
+
38
+ export type Callbacks = {|
39
+ collectionStarting: () => mixed,
40
+ publishWhileDragging: (args: Published) => mixed,
41
+ updateDroppableScroll: (args: UpdateDroppableScrollArgs) => mixed,
42
+ updateDroppableIsEnabled: (args: UpdateDroppableIsEnabledArgs) => mixed,
43
+ updateDroppableIsCombineEnabled: (
44
+ args: UpdateDroppableIsCombineEnabledArgs,
45
+ ) => mixed,
46
+ |};
@@ -0,0 +1,218 @@
1
+ // @flow
2
+ import { type Position } from 'css-box-model';
3
+ import { invariant } from '../../invariant';
4
+ import type {
5
+ DimensionMarshal,
6
+ Callbacks,
7
+ StartPublishingResult,
8
+ } from './dimension-marshal-types';
9
+ import createPublisher, {
10
+ type WhileDraggingPublisher,
11
+ } from './while-dragging-publisher';
12
+ import getInitialPublish from './get-initial-publish';
13
+ import type {
14
+ Registry,
15
+ DroppableEntry,
16
+ DraggableEntry,
17
+ Subscriber,
18
+ Unsubscribe,
19
+ RegistryEvent,
20
+ } from '../registry/registry-types';
21
+ import type {
22
+ DroppableId,
23
+ DroppableDescriptor,
24
+ LiftRequest,
25
+ Critical,
26
+ DraggableDescriptor,
27
+ } from '../../types';
28
+ import { warning } from '../../dev-warning';
29
+
30
+ type Collection = {|
31
+ critical: Critical,
32
+ unsubscribe: Unsubscribe,
33
+ |};
34
+
35
+ function shouldPublishUpdate(
36
+ registry: Registry,
37
+ dragging: DraggableDescriptor,
38
+ entry: DraggableEntry,
39
+ ): boolean {
40
+ // do not publish updates for the critical draggable
41
+ if (entry.descriptor.id === dragging.id) {
42
+ return false;
43
+ }
44
+ // do not publish updates for draggables that are not of a type that we care about
45
+ if (entry.descriptor.type !== dragging.type) {
46
+ return false;
47
+ }
48
+
49
+ const home: DroppableEntry = registry.droppable.getById(
50
+ entry.descriptor.droppableId,
51
+ );
52
+
53
+ if (home.descriptor.mode !== 'virtual') {
54
+ warning(`
55
+ You are attempting to add or remove a Draggable [id: ${entry.descriptor.id}]
56
+ while a drag is occurring. This is only supported for virtual lists.
57
+
58
+ See https://github.com/atlassian/react-beautiful-dnd/blob/master/docs/patterns/virtual-lists.md
59
+ `);
60
+ return false;
61
+ }
62
+
63
+ return true;
64
+ }
65
+
66
+ export default (registry: Registry, callbacks: Callbacks) => {
67
+ let collection: ?Collection = null;
68
+
69
+ const publisher: WhileDraggingPublisher = createPublisher({
70
+ callbacks: {
71
+ publish: callbacks.publishWhileDragging,
72
+ collectionStarting: callbacks.collectionStarting,
73
+ },
74
+ registry,
75
+ });
76
+
77
+ const updateDroppableIsEnabled = (id: DroppableId, isEnabled: boolean) => {
78
+ invariant(
79
+ registry.droppable.exists(id),
80
+ `Cannot update is enabled flag of Droppable ${id} as it is not registered`,
81
+ );
82
+
83
+ // no need to update the application state if a collection is not occurring
84
+ if (!collection) {
85
+ return;
86
+ }
87
+
88
+ // At this point a non primary droppable dimension might not yet be published
89
+ // but may have its enabled state changed. For now we still publish this change
90
+ // and let the reducer exit early if it cannot find the dimension in the state.
91
+ callbacks.updateDroppableIsEnabled({ id, isEnabled });
92
+ };
93
+
94
+ const updateDroppableIsCombineEnabled = (
95
+ id: DroppableId,
96
+ isCombineEnabled: boolean,
97
+ ) => {
98
+ // no need to update
99
+ if (!collection) {
100
+ return;
101
+ }
102
+
103
+ invariant(
104
+ registry.droppable.exists(id),
105
+ `Cannot update isCombineEnabled flag of Droppable ${id} as it is not registered`,
106
+ );
107
+
108
+ callbacks.updateDroppableIsCombineEnabled({ id, isCombineEnabled });
109
+ };
110
+
111
+ const updateDroppableScroll = (id: DroppableId, newScroll: Position) => {
112
+ // no need to update the application state if a collection is not occurring
113
+ if (!collection) {
114
+ return;
115
+ }
116
+
117
+ invariant(
118
+ registry.droppable.exists(id),
119
+ `Cannot update the scroll on Droppable ${id} as it is not registered`,
120
+ );
121
+
122
+ callbacks.updateDroppableScroll({ id, newScroll });
123
+ };
124
+
125
+ const scrollDroppable = (id: DroppableId, change: Position) => {
126
+ if (!collection) {
127
+ return;
128
+ }
129
+ registry.droppable.getById(id).callbacks.scroll(change);
130
+ };
131
+
132
+ const stopPublishing = () => {
133
+ // This function can be called defensively
134
+ if (!collection) {
135
+ return;
136
+ }
137
+ // Stop any pending dom collections or publish
138
+ publisher.stop();
139
+
140
+ // Tell all droppables to stop watching scroll
141
+ // all good if they where not already listening
142
+ const home: DroppableDescriptor = collection.critical.droppable;
143
+ registry.droppable
144
+ .getAllByType(home.type)
145
+ .forEach((entry: DroppableEntry) => entry.callbacks.dragStopped());
146
+
147
+ // Unsubscribe from registry updates
148
+ collection.unsubscribe();
149
+ // Finally - clear our collection
150
+ collection = null;
151
+ };
152
+
153
+ const subscriber: Subscriber = (event: RegistryEvent) => {
154
+ invariant(
155
+ collection,
156
+ 'Should only be subscribed when a collection is occurring',
157
+ );
158
+ // The dragging item can be add and removed when using a clone
159
+ // We do not publish updates for the critical item
160
+ const dragging: DraggableDescriptor = collection.critical.draggable;
161
+
162
+ if (event.type === 'ADDITION') {
163
+ if (shouldPublishUpdate(registry, dragging, event.value)) {
164
+ publisher.add(event.value);
165
+ }
166
+ }
167
+ if (event.type === 'REMOVAL') {
168
+ if (shouldPublishUpdate(registry, dragging, event.value)) {
169
+ publisher.remove(event.value);
170
+ }
171
+ }
172
+ };
173
+
174
+ const startPublishing = (request: LiftRequest): StartPublishingResult => {
175
+ invariant(
176
+ !collection,
177
+ 'Cannot start capturing critical dimensions as there is already a collection',
178
+ );
179
+ const entry: DraggableEntry = registry.draggable.getById(
180
+ request.draggableId,
181
+ );
182
+ const home: DroppableEntry = registry.droppable.getById(
183
+ entry.descriptor.droppableId,
184
+ );
185
+
186
+ const critical: Critical = {
187
+ draggable: entry.descriptor,
188
+ droppable: home.descriptor,
189
+ };
190
+
191
+ const unsubscribe = registry.subscribe(subscriber);
192
+
193
+ collection = {
194
+ critical,
195
+ unsubscribe,
196
+ };
197
+
198
+ return getInitialPublish({
199
+ critical,
200
+ registry,
201
+ scrollOptions: request.scrollOptions,
202
+ });
203
+ };
204
+
205
+ const marshal: DimensionMarshal = {
206
+ // Droppable changes
207
+ updateDroppableIsEnabled,
208
+ updateDroppableIsCombineEnabled,
209
+ scrollDroppable,
210
+ updateDroppableScroll,
211
+
212
+ // Entry
213
+ startPublishing,
214
+ stopPublishing,
215
+ };
216
+
217
+ return marshal;
218
+ };
@@ -0,0 +1,66 @@
1
+ // @flow
2
+ import type { Position } from 'css-box-model';
3
+ import * as timings from '../../debug/timings';
4
+ import type { StartPublishingResult } from './dimension-marshal-types';
5
+ import type {
6
+ Registry,
7
+ DraggableEntry,
8
+ DroppableEntry,
9
+ } from '../registry/registry-types';
10
+ import { toDraggableMap, toDroppableMap } from '../dimension-structures';
11
+ import type {
12
+ DroppableDescriptor,
13
+ DroppableDimension,
14
+ DraggableDimension,
15
+ DimensionMap,
16
+ ScrollOptions,
17
+ Critical,
18
+ Viewport,
19
+ } from '../../types';
20
+ import getViewport from '../../view/window/get-viewport';
21
+
22
+ type Args = {|
23
+ critical: Critical,
24
+ scrollOptions: ScrollOptions,
25
+ registry: Registry,
26
+ |};
27
+
28
+ export default ({
29
+ critical,
30
+ scrollOptions,
31
+ registry,
32
+ }: Args): StartPublishingResult => {
33
+ const timingKey: string = 'Initial collection from DOM';
34
+ timings.start(timingKey);
35
+ const viewport: Viewport = getViewport();
36
+ const windowScroll: Position = viewport.scroll.current;
37
+
38
+ const home: DroppableDescriptor = critical.droppable;
39
+
40
+ const droppables: DroppableDimension[] = registry.droppable
41
+ .getAllByType(home.type)
42
+ .map((entry: DroppableEntry): DroppableDimension =>
43
+ entry.callbacks.getDimensionAndWatchScroll(windowScroll, scrollOptions),
44
+ );
45
+
46
+ const draggables: DraggableDimension[] = registry.draggable
47
+ .getAllByType(critical.draggable.type)
48
+ .map((entry: DraggableEntry): DraggableDimension =>
49
+ entry.getDimension(windowScroll),
50
+ );
51
+
52
+ const dimensions: DimensionMap = {
53
+ draggables: toDraggableMap(draggables),
54
+ droppables: toDroppableMap(droppables),
55
+ };
56
+
57
+ timings.finish(timingKey);
58
+
59
+ const result: StartPublishingResult = {
60
+ dimensions,
61
+ critical,
62
+ viewport,
63
+ };
64
+
65
+ return result;
66
+ };
@@ -0,0 +1,146 @@
1
+ // @flow
2
+ import type { Position } from 'css-box-model';
3
+ import type {
4
+ DraggableId,
5
+ DroppableId,
6
+ DraggableDescriptor,
7
+ Published,
8
+ DraggableDimension,
9
+ DroppablePublish,
10
+ DroppableIdMap,
11
+ DraggableIdMap,
12
+ } from '../../types';
13
+ import type {
14
+ DroppableEntry,
15
+ Registry,
16
+ DraggableEntry,
17
+ DraggableEntryMap,
18
+ } from '../registry/registry-types';
19
+ import * as timings from '../../debug/timings';
20
+ import { origin } from '../position';
21
+
22
+ export type WhileDraggingPublisher = {|
23
+ add: (entry: DraggableEntry) => void,
24
+ remove: (entry: DraggableEntry) => void,
25
+ stop: () => void,
26
+ |};
27
+
28
+ type Staging = {|
29
+ additions: DraggableEntryMap,
30
+ removals: DraggableIdMap,
31
+ modified: DroppableIdMap,
32
+ |};
33
+
34
+ type Callbacks = {|
35
+ publish: (args: Published) => mixed,
36
+ collectionStarting: () => mixed,
37
+ |};
38
+
39
+ type Args = {|
40
+ registry: Registry,
41
+ callbacks: Callbacks,
42
+ |};
43
+
44
+ const clean = (): Staging => ({
45
+ additions: {},
46
+ removals: {},
47
+ modified: {},
48
+ });
49
+
50
+ const timingKey: string = 'Publish collection from DOM';
51
+
52
+ export default function createPublisher({
53
+ registry,
54
+ callbacks,
55
+ }: Args): WhileDraggingPublisher {
56
+ let staging: Staging = clean();
57
+ let frameId: ?AnimationFrameID = null;
58
+
59
+ const collect = () => {
60
+ if (frameId) {
61
+ return;
62
+ }
63
+
64
+ callbacks.collectionStarting();
65
+ frameId = requestAnimationFrame(() => {
66
+ frameId = null;
67
+ timings.start(timingKey);
68
+
69
+ const { additions, removals, modified } = staging;
70
+
71
+ const added: DraggableDimension[] = Object.keys(additions)
72
+ .map(
73
+ // Using the origin as the window scroll. This will be adjusted when processing the published values
74
+ (id: DraggableId): DraggableDimension =>
75
+ registry.draggable.getById(id).getDimension(origin),
76
+ )
77
+ // Dimensions are not guarenteed to be ordered in the same order as keys
78
+ // So we need to sort them so they are in the correct order
79
+ .sort(
80
+ (a: DraggableDimension, b: DraggableDimension): number =>
81
+ a.descriptor.index - b.descriptor.index,
82
+ );
83
+
84
+ const updated: DroppablePublish[] = Object.keys(modified).map(
85
+ (id: DroppableId) => {
86
+ const entry: DroppableEntry = registry.droppable.getById(id);
87
+
88
+ const scroll: Position = entry.callbacks.getScrollWhileDragging();
89
+ return {
90
+ droppableId: id,
91
+ scroll,
92
+ };
93
+ },
94
+ );
95
+
96
+ const result: Published = {
97
+ additions: added,
98
+ removals: Object.keys(removals),
99
+ modified: updated,
100
+ };
101
+
102
+ staging = clean();
103
+
104
+ timings.finish(timingKey);
105
+ callbacks.publish(result);
106
+ });
107
+ };
108
+
109
+ const add = (entry: DraggableEntry) => {
110
+ const id: DraggableId = entry.descriptor.id;
111
+ staging.additions[id] = entry;
112
+ staging.modified[entry.descriptor.droppableId] = true;
113
+
114
+ if (staging.removals[id]) {
115
+ delete staging.removals[id];
116
+ }
117
+ collect();
118
+ };
119
+
120
+ const remove = (entry: DraggableEntry) => {
121
+ const descriptor: DraggableDescriptor = entry.descriptor;
122
+ staging.removals[descriptor.id] = true;
123
+ staging.modified[descriptor.droppableId] = true;
124
+
125
+ if (staging.additions[descriptor.id]) {
126
+ delete staging.additions[descriptor.id];
127
+ }
128
+ collect();
129
+ };
130
+
131
+ const stop = () => {
132
+ if (!frameId) {
133
+ return;
134
+ }
135
+
136
+ cancelAnimationFrame(frameId);
137
+ frameId = null;
138
+ staging = clean();
139
+ };
140
+
141
+ return {
142
+ add,
143
+ remove,
144
+ stop,
145
+ };
146
+ }
@@ -0,0 +1,35 @@
1
+ // @flow
2
+ import memoizeOne from 'memoize-one';
3
+ import { values } from '../native-with-fallback';
4
+ import type {
5
+ DroppableDimension,
6
+ DroppableDimensionMap,
7
+ DraggableDimension,
8
+ DraggableDimensionMap,
9
+ } from '../types';
10
+
11
+ export const toDroppableMap = memoizeOne(
12
+ (droppables: DroppableDimension[]): DroppableDimensionMap =>
13
+ droppables.reduce((previous, current) => {
14
+ previous[current.descriptor.id] = current;
15
+ return previous;
16
+ }, {}),
17
+ );
18
+
19
+ export const toDraggableMap = memoizeOne(
20
+ (draggables: DraggableDimension[]): DraggableDimensionMap =>
21
+ draggables.reduce((previous, current) => {
22
+ previous[current.descriptor.id] = current;
23
+ return previous;
24
+ }, {}),
25
+ );
26
+
27
+ export const toDroppableList = memoizeOne(
28
+ (droppables: DroppableDimensionMap): DroppableDimension[] =>
29
+ values(droppables),
30
+ );
31
+
32
+ export const toDraggableList = memoizeOne(
33
+ (draggables: DraggableDimensionMap): DraggableDimension[] =>
34
+ values(draggables),
35
+ );
@@ -0,0 +1,101 @@
1
+ // @flow
2
+ import { type BoxModel, type Position } from 'css-box-model';
3
+ import type {
4
+ Axis,
5
+ DroppableDimension,
6
+ DroppableDescriptor,
7
+ Scrollable,
8
+ DroppableSubject,
9
+ ScrollSize,
10
+ } from '../../types';
11
+ import { vertical, horizontal } from '../axis';
12
+ import { origin } from '../position';
13
+ import getMaxScroll from '../get-max-scroll';
14
+ import getSubject from './util/get-subject';
15
+
16
+ export type Closest = {|
17
+ client: BoxModel,
18
+ page: BoxModel,
19
+ scroll: Position,
20
+ scrollSize: ScrollSize,
21
+ shouldClipSubject: boolean,
22
+ |};
23
+
24
+ type Args = {|
25
+ descriptor: DroppableDescriptor,
26
+ isEnabled: boolean,
27
+ isCombineEnabled: boolean,
28
+ isFixedOnPage: boolean,
29
+ direction: 'vertical' | 'horizontal',
30
+ client: BoxModel,
31
+ // is null when in a fixed container
32
+ page: BoxModel,
33
+ closest?: ?Closest,
34
+ |};
35
+
36
+ export default ({
37
+ descriptor,
38
+ isEnabled,
39
+ isCombineEnabled,
40
+ isFixedOnPage,
41
+ direction,
42
+ client,
43
+ page,
44
+ closest,
45
+ }: Args): DroppableDimension => {
46
+ const frame: ?Scrollable = (() => {
47
+ if (!closest) {
48
+ return null;
49
+ }
50
+
51
+ const { scrollSize, client: frameClient } = closest;
52
+
53
+ // scrollHeight and scrollWidth are based on the padding box
54
+ // https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight
55
+ const maxScroll: Position = getMaxScroll({
56
+ scrollHeight: scrollSize.scrollHeight,
57
+ scrollWidth: scrollSize.scrollWidth,
58
+ height: frameClient.paddingBox.height,
59
+ width: frameClient.paddingBox.width,
60
+ });
61
+
62
+ return {
63
+ pageMarginBox: closest.page.marginBox,
64
+ frameClient,
65
+ scrollSize,
66
+ shouldClipSubject: closest.shouldClipSubject,
67
+ scroll: {
68
+ initial: closest.scroll,
69
+ current: closest.scroll,
70
+ max: maxScroll,
71
+ diff: {
72
+ value: origin,
73
+ displacement: origin,
74
+ },
75
+ },
76
+ };
77
+ })();
78
+
79
+ const axis: Axis = direction === 'vertical' ? vertical : horizontal;
80
+
81
+ const subject: DroppableSubject = getSubject({
82
+ page,
83
+ withPlaceholder: null,
84
+ axis,
85
+ frame,
86
+ });
87
+
88
+ const dimension: DroppableDimension = {
89
+ descriptor,
90
+ isCombineEnabled,
91
+ isFixedOnPage,
92
+ axis,
93
+ isEnabled,
94
+ client,
95
+ page,
96
+ frame,
97
+ subject,
98
+ };
99
+
100
+ return dimension;
101
+ };
@@ -0,0 +1,7 @@
1
+ // @flow
2
+ import type { DraggableDimension, DroppableDimension } from '../../types';
3
+
4
+ export default (
5
+ draggable: DraggableDimension,
6
+ destination: DroppableDimension,
7
+ ): boolean => draggable.descriptor.droppableId === destination.descriptor.id;
@@ -0,0 +1,53 @@
1
+ // @flow
2
+ import { type Position } from 'css-box-model';
3
+ import { invariant } from '../../invariant';
4
+ import type {
5
+ DroppableDimension,
6
+ Scrollable,
7
+ DroppableSubject,
8
+ } from '../../types';
9
+ import { negate, subtract } from '../position';
10
+ import getSubject from './util/get-subject';
11
+
12
+ export default (
13
+ droppable: DroppableDimension,
14
+ newScroll: Position,
15
+ ): DroppableDimension => {
16
+ invariant(droppable.frame);
17
+ const scrollable: Scrollable = droppable.frame;
18
+
19
+ const scrollDiff: Position = subtract(newScroll, scrollable.scroll.initial);
20
+ // a positive scroll difference leads to a negative displacement
21
+ // (scrolling down pulls an item upwards)
22
+ const scrollDisplacement: Position = negate(scrollDiff);
23
+
24
+ // Sometimes it is possible to scroll beyond the max point.
25
+ // This can occur when scrolling a foreign list that now has a placeholder.
26
+
27
+ const frame: Scrollable = {
28
+ ...scrollable,
29
+ scroll: {
30
+ initial: scrollable.scroll.initial,
31
+ current: newScroll,
32
+ diff: {
33
+ value: scrollDiff,
34
+ displacement: scrollDisplacement,
35
+ },
36
+ // TODO: rename 'softMax?'
37
+ max: scrollable.scroll.max,
38
+ },
39
+ };
40
+
41
+ const subject: DroppableSubject = getSubject({
42
+ page: droppable.subject.page,
43
+ withPlaceholder: droppable.subject.withPlaceholder,
44
+ axis: droppable.axis,
45
+ frame,
46
+ });
47
+ const result: DroppableDimension = {
48
+ ...droppable,
49
+ frame,
50
+ subject,
51
+ };
52
+ return result;
53
+ };
@@ -0,0 +1,7 @@
1
+ // @flow
2
+ import type { DraggableDescriptor, DragImpact } from '../../types';
3
+ import whatIsDraggedOver from './what-is-dragged-over';
4
+
5
+ // use placeholder if dragged over
6
+ export default (descriptor: DraggableDescriptor, impact: DragImpact): boolean =>
7
+ whatIsDraggedOver(impact) === descriptor.droppableId;
@@ -0,0 +1,17 @@
1
+ // @flow
2
+ import { getRect, type Rect, type Spacing } from 'css-box-model';
3
+
4
+ export default (frame: Spacing, subject: Spacing): ?Rect => {
5
+ const result: Rect = getRect({
6
+ top: Math.max(subject.top, frame.top),
7
+ right: Math.min(subject.right, frame.right),
8
+ bottom: Math.min(subject.bottom, frame.bottom),
9
+ left: Math.max(subject.left, frame.left),
10
+ });
11
+
12
+ if (result.width <= 0 || result.height <= 0) {
13
+ return null;
14
+ }
15
+
16
+ return result;
17
+ };