@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,20 @@
1
+ // @flow
2
+ import { useEffect } from 'react';
3
+ import { useMemo } from 'use-memo-one';
4
+ import type { Registry } from './registry-types';
5
+ import createRegistry from './create-registry';
6
+
7
+ export default function useRegistry(): Registry {
8
+ const registry: Registry = useMemo(createRegistry, []);
9
+
10
+ useEffect(() => {
11
+ return function unmount() {
12
+ // clean up the registry to avoid any leaks
13
+ // doing it after an animation frame so that other things unmounting
14
+ // can continue to interact with the registry
15
+ requestAnimationFrame(registry.clean);
16
+ };
17
+ }, [registry]);
18
+
19
+ return registry;
20
+ }
@@ -0,0 +1,13 @@
1
+ // @flow
2
+ import memoizeOne from 'memoize-one';
3
+ import type { DraggableDimension } from '../types';
4
+
5
+ export default memoizeOne(
6
+ (
7
+ remove: DraggableDimension,
8
+ list: DraggableDimension[],
9
+ ): DraggableDimension[] =>
10
+ list.filter(
11
+ (item: DraggableDimension) => item.descriptor.id !== remove.descriptor.id,
12
+ ),
13
+ );
@@ -0,0 +1,34 @@
1
+ // @flow
2
+ import { getRect, type Rect } from 'css-box-model';
3
+ import type { Position } from 'css-box-model';
4
+ import { subtract, negate } from './position';
5
+ import type { Viewport } from '../types';
6
+
7
+ export default (viewport: Viewport, newScroll: Position): Viewport => {
8
+ const diff: Position = subtract(newScroll, viewport.scroll.initial);
9
+ const displacement: Position = negate(diff);
10
+
11
+ // We need to update the frame so that it is always a live value
12
+ // The top / left of the frame should always match the newScroll position
13
+ const frame: Rect = getRect({
14
+ top: newScroll.y,
15
+ bottom: newScroll.y + viewport.frame.height,
16
+ left: newScroll.x,
17
+ right: newScroll.x + viewport.frame.width,
18
+ });
19
+
20
+ const updated: Viewport = {
21
+ frame,
22
+ scroll: {
23
+ initial: viewport.scroll.initial,
24
+ max: viewport.scroll.max,
25
+ current: newScroll,
26
+ diff: {
27
+ value: diff,
28
+ displacement,
29
+ },
30
+ },
31
+ };
32
+
33
+ return updated;
34
+ };
@@ -0,0 +1,45 @@
1
+ // @flow
2
+ import type { Spacing, Position } from 'css-box-model';
3
+
4
+ // TODO add test
5
+ export const isEqual = (first: Spacing, second: Spacing): boolean =>
6
+ first.top === second.top &&
7
+ first.right === second.right &&
8
+ first.bottom === second.bottom &&
9
+ first.left === second.left;
10
+
11
+ export const offsetByPosition = (
12
+ spacing: Spacing,
13
+ point: Position,
14
+ ): Spacing => ({
15
+ top: spacing.top + point.y,
16
+ left: spacing.left + point.x,
17
+ bottom: spacing.bottom + point.y,
18
+ right: spacing.right + point.x,
19
+ });
20
+
21
+ export const expandByPosition = (
22
+ spacing: Spacing,
23
+ position: Position,
24
+ ): Spacing => ({
25
+ // pulling back to increase size
26
+ top: spacing.top - position.y,
27
+ left: spacing.left - position.x,
28
+ // pushing forward to increase size
29
+ right: spacing.right + position.x,
30
+ bottom: spacing.bottom + position.y,
31
+ });
32
+
33
+ export const getCorners = (spacing: Spacing): Position[] => [
34
+ { x: spacing.left, y: spacing.top },
35
+ { x: spacing.right, y: spacing.top },
36
+ { x: spacing.left, y: spacing.bottom },
37
+ { x: spacing.right, y: spacing.bottom },
38
+ ];
39
+
40
+ export const noSpacing: Spacing = {
41
+ top: 0,
42
+ right: 0,
43
+ bottom: 0,
44
+ left: 0,
45
+ };
@@ -0,0 +1,16 @@
1
+ // @flow
2
+ // This file exists to avoid a circular dependency between types.js and action-creators.js
3
+ import type {
4
+ Store as ReduxStore,
5
+ Dispatch as ReduxDispatch,
6
+ Middleware as ReduxMiddleware,
7
+ MiddlewareAPI as ReduxMiddlewareAPI,
8
+ } from 'redux';
9
+ import type { Action as ActionCreators } from './action-creators';
10
+ import type { State } from '../types';
11
+
12
+ export type Action = ActionCreators;
13
+ export type Dispatch = ReduxDispatch<Action>;
14
+ export type Store = ReduxStore<State, Action, Dispatch>;
15
+ export type Middleware = ReduxMiddleware<State, Action, Dispatch>;
16
+ export type MiddlewareStore = ReduxMiddlewareAPI<State, Action, Dispatch>;
@@ -0,0 +1,54 @@
1
+ // @flow
2
+ import type {
3
+ DraggableDimension,
4
+ DroppableDimension,
5
+ DraggableDimensionMap,
6
+ DragImpact,
7
+ Viewport,
8
+ DraggableId,
9
+ DisplacementGroups,
10
+ } from '../../types';
11
+ import getDisplacementGroups from '../get-displacement-groups';
12
+
13
+ type RecomputeArgs = {|
14
+ impact: DragImpact,
15
+ draggables: DraggableDimensionMap,
16
+ destination: DroppableDimension,
17
+ viewport: Viewport,
18
+ forceShouldAnimate?: boolean,
19
+ |};
20
+
21
+ function getDraggables(
22
+ ids: DraggableId[],
23
+ draggables: DraggableDimensionMap,
24
+ ): DraggableDimension[] {
25
+ return ids.map((id: DraggableId): DraggableDimension => draggables[id]);
26
+ }
27
+
28
+ export default ({
29
+ impact,
30
+ viewport,
31
+ draggables,
32
+ destination,
33
+ forceShouldAnimate,
34
+ }: RecomputeArgs): DragImpact => {
35
+ const last: DisplacementGroups = impact.displaced;
36
+ const afterDragging: DraggableDimension[] = getDraggables(
37
+ last.all,
38
+ draggables,
39
+ );
40
+
41
+ const displaced: DisplacementGroups = getDisplacementGroups({
42
+ afterDragging,
43
+ destination,
44
+ displacedBy: impact.displacedBy,
45
+ viewport: viewport.frame,
46
+ forceShouldAnimate,
47
+ last,
48
+ });
49
+
50
+ return {
51
+ ...impact,
52
+ displaced,
53
+ };
54
+ };
@@ -0,0 +1,111 @@
1
+ // @flow
2
+ import type { Position } from 'css-box-model';
3
+ import type {
4
+ DraggableId,
5
+ DroppableDimension,
6
+ DraggableDimension,
7
+ DraggableDimensionMap,
8
+ DragImpact,
9
+ Displacement,
10
+ DisplacementGroups,
11
+ DraggableIdMap,
12
+ DisplacementMap,
13
+ Viewport,
14
+ } from '../../types';
15
+ import scrollViewport from '../scroll-viewport';
16
+ import scrollDroppable from '../droppable/scroll-droppable';
17
+ import { add } from '../position';
18
+ import getDisplacementGroups from '../get-displacement-groups';
19
+
20
+ type SpeculativeArgs = {|
21
+ impact: DragImpact,
22
+ destination: DroppableDimension,
23
+ viewport: Viewport,
24
+ draggables: DraggableDimensionMap,
25
+ maxScrollChange: Position,
26
+ |};
27
+
28
+ function getDraggables(
29
+ ids: DraggableId[],
30
+ draggables: DraggableDimensionMap,
31
+ ): DraggableDimension[] {
32
+ return ids.map((id: DraggableId): DraggableDimension => draggables[id]);
33
+ }
34
+
35
+ function tryGetVisible(
36
+ id: DraggableId,
37
+ groups: DisplacementGroups[],
38
+ ): ?Displacement {
39
+ for (let i = 0; i < groups.length; i++) {
40
+ const displacement: ?Displacement = groups[i].visible[id];
41
+ if (displacement) {
42
+ return displacement;
43
+ }
44
+ }
45
+ return null;
46
+ }
47
+
48
+ export default ({
49
+ impact,
50
+ viewport,
51
+ destination,
52
+ draggables,
53
+ maxScrollChange,
54
+ }: SpeculativeArgs): DragImpact => {
55
+ const scrolledViewport: Viewport = scrollViewport(
56
+ viewport,
57
+ add(viewport.scroll.current, maxScrollChange),
58
+ );
59
+ const scrolledDroppable: DroppableDimension = destination.frame
60
+ ? scrollDroppable(
61
+ destination,
62
+ add(destination.frame.scroll.current, maxScrollChange),
63
+ )
64
+ : destination;
65
+
66
+ const last: DisplacementGroups = impact.displaced;
67
+ const withViewportScroll: DisplacementGroups = getDisplacementGroups({
68
+ afterDragging: getDraggables(last.all, draggables),
69
+ destination,
70
+ displacedBy: impact.displacedBy,
71
+ viewport: scrolledViewport.frame,
72
+ last,
73
+ // we want the addition to be animated
74
+ forceShouldAnimate: false,
75
+ });
76
+ const withDroppableScroll: DisplacementGroups = getDisplacementGroups({
77
+ afterDragging: getDraggables(last.all, draggables),
78
+ destination: scrolledDroppable,
79
+ displacedBy: impact.displacedBy,
80
+ viewport: viewport.frame,
81
+ last,
82
+ // we want the addition to be animated
83
+ forceShouldAnimate: false,
84
+ });
85
+
86
+ const invisible: DraggableIdMap = {};
87
+ const visible: DisplacementMap = {};
88
+ const groups: DisplacementGroups[] = [
89
+ // this will populate the previous entries with the correct animation values
90
+ last,
91
+ withViewportScroll,
92
+ withDroppableScroll,
93
+ ];
94
+
95
+ last.all.forEach((id: DraggableId) => {
96
+ const displacement: ?Displacement = tryGetVisible(id, groups);
97
+
98
+ if (displacement) {
99
+ visible[id] = displacement;
100
+ return;
101
+ }
102
+ invisible[id] = true;
103
+ });
104
+
105
+ const newImpact: DragImpact = {
106
+ ...impact,
107
+ displaced: { all: last.all, invisible, visible },
108
+ };
109
+
110
+ return newImpact;
111
+ };
@@ -0,0 +1,60 @@
1
+ // @flow
2
+ import { type Spacing } from 'css-box-model';
3
+ import isWithin from '../is-within';
4
+
5
+ export default (frame: Spacing) => {
6
+ const isWithinVertical = isWithin(frame.top, frame.bottom);
7
+ const isWithinHorizontal = isWithin(frame.left, frame.right);
8
+
9
+ return (subject: Spacing) => {
10
+ // situations where target is visible:
11
+ // 1. is completely contained within frame
12
+ // 2. is partially visible on both axis within frame
13
+ // 3. is bigger than frame on both axis
14
+ // 4. is bigger than frame on one axis and is partially visible on the other
15
+
16
+ // completely contained
17
+ const isContained: boolean =
18
+ isWithinVertical(subject.top) &&
19
+ isWithinVertical(subject.bottom) &&
20
+ isWithinHorizontal(subject.left) &&
21
+ isWithinHorizontal(subject.right);
22
+
23
+ if (isContained) {
24
+ return true;
25
+ }
26
+
27
+ const isPartiallyVisibleVertically: boolean =
28
+ isWithinVertical(subject.top) || isWithinVertical(subject.bottom);
29
+ const isPartiallyVisibleHorizontally: boolean =
30
+ isWithinHorizontal(subject.left) || isWithinHorizontal(subject.right);
31
+
32
+ // partially visible on both axis
33
+ const isPartiallyContained: boolean =
34
+ isPartiallyVisibleVertically && isPartiallyVisibleHorizontally;
35
+
36
+ if (isPartiallyContained) {
37
+ return true;
38
+ }
39
+
40
+ const isBiggerVertically: boolean =
41
+ subject.top < frame.top && subject.bottom > frame.bottom;
42
+ const isBiggerHorizontally: boolean =
43
+ subject.left < frame.left && subject.right > frame.right;
44
+
45
+ // is bigger than frame on both axis
46
+ const isTargetBiggerThanFrame: boolean =
47
+ isBiggerVertically && isBiggerHorizontally;
48
+
49
+ if (isTargetBiggerThanFrame) {
50
+ return true;
51
+ }
52
+
53
+ // is bigger on one axis, and partially visible on another
54
+ const isTargetBiggerOnOneAxis: boolean =
55
+ (isBiggerVertically && isPartiallyVisibleHorizontally) ||
56
+ (isBiggerHorizontally && isPartiallyVisibleVertically);
57
+
58
+ return isTargetBiggerOnOneAxis;
59
+ };
60
+ };
@@ -0,0 +1,12 @@
1
+ // @flow
2
+ import { type Position, type Spacing } from 'css-box-model';
3
+ import isWithin from '../is-within';
4
+
5
+ export default function isPositionInFrame(frame: Spacing) {
6
+ const isWithinVertical = isWithin(frame.top, frame.bottom);
7
+ const isWithinHorizontal = isWithin(frame.left, frame.right);
8
+
9
+ return function run(point: Position) {
10
+ return isWithinVertical(point.y) && isWithinHorizontal(point.x);
11
+ };
12
+ }
@@ -0,0 +1,19 @@
1
+ // @flow
2
+ import { type Spacing } from 'css-box-model';
3
+ import type { Axis } from '../../types';
4
+ import isWithin from '../is-within';
5
+ import { vertical } from '../axis';
6
+
7
+ export default (axis: Axis) => (frame: Spacing) => {
8
+ const isWithinVertical = isWithin(frame.top, frame.bottom);
9
+ const isWithinHorizontal = isWithin(frame.left, frame.right);
10
+
11
+ return (subject: Spacing) => {
12
+ if (axis === vertical) {
13
+ return isWithinVertical(subject.top) && isWithinVertical(subject.bottom);
14
+ }
15
+ return (
16
+ isWithinHorizontal(subject.left) && isWithinHorizontal(subject.right)
17
+ );
18
+ };
19
+ };
@@ -0,0 +1,18 @@
1
+ // @flow
2
+ import { type Spacing } from 'css-box-model';
3
+ import isWithin from '../is-within';
4
+
5
+ export default (frame: Spacing) => {
6
+ const isWithinVertical = isWithin(frame.top, frame.bottom);
7
+ const isWithinHorizontal = isWithin(frame.left, frame.right);
8
+
9
+ return (subject: Spacing) => {
10
+ const isContained: boolean =
11
+ isWithinVertical(subject.top) &&
12
+ isWithinVertical(subject.bottom) &&
13
+ isWithinHorizontal(subject.left) &&
14
+ isWithinHorizontal(subject.right);
15
+
16
+ return isContained;
17
+ };
18
+ };
@@ -0,0 +1,102 @@
1
+ // @flow
2
+ import { type Position, type Spacing, type Rect } from 'css-box-model';
3
+ import type { DroppableDimension } from '../../types';
4
+ import isPartiallyVisibleThroughFrame from './is-partially-visible-through-frame';
5
+ import isTotallyVisibleThroughFrame from './is-totally-visible-through-frame';
6
+ import isTotallyVisibleThroughFrameOnAxis from './is-totally-visible-through-frame-on-axis';
7
+ import { offsetByPosition } from '../spacing';
8
+ import { origin } from '../position';
9
+
10
+ export type Args = {|
11
+ target: Spacing,
12
+ destination: DroppableDimension,
13
+ viewport: Rect,
14
+ withDroppableDisplacement: boolean,
15
+ shouldCheckDroppable?: boolean,
16
+ shouldCheckViewport?: boolean,
17
+ |};
18
+
19
+ type IsVisibleThroughFrameFn = (
20
+ frame: Spacing,
21
+ ) => (subject: Spacing) => boolean;
22
+
23
+ type InternalArgs = {|
24
+ ...Args,
25
+ isVisibleThroughFrameFn: IsVisibleThroughFrameFn,
26
+ |};
27
+
28
+ const getDroppableDisplaced = (
29
+ target: Spacing,
30
+ destination: DroppableDimension,
31
+ ): Spacing => {
32
+ const displacement: Position = destination.frame
33
+ ? destination.frame.scroll.diff.displacement
34
+ : origin;
35
+
36
+ return offsetByPosition(target, displacement);
37
+ };
38
+
39
+ const isVisibleInDroppable = (
40
+ target: Spacing,
41
+ destination: DroppableDimension,
42
+ isVisibleThroughFrameFn: IsVisibleThroughFrameFn,
43
+ ): boolean => {
44
+ // destination subject is totally hidden by frame
45
+ // this should never happen - but just guarding against it
46
+ if (!destination.subject.active) {
47
+ return false;
48
+ }
49
+
50
+ // When considering if the target is visible in the droppable we need
51
+ // to consider the change in scroll of the droppable. We need to
52
+ // adjust for the scroll as the clipped viewport takes into account
53
+ // the scroll of the droppable.
54
+
55
+ return isVisibleThroughFrameFn(destination.subject.active)(target);
56
+ };
57
+
58
+ const isVisibleInViewport = (
59
+ target: Spacing,
60
+ viewport: Rect,
61
+ isVisibleThroughFrameFn: IsVisibleThroughFrameFn,
62
+ ): boolean => isVisibleThroughFrameFn(viewport)(target);
63
+
64
+ const isVisible = ({
65
+ target: toBeDisplaced,
66
+ destination,
67
+ viewport,
68
+ withDroppableDisplacement,
69
+ isVisibleThroughFrameFn,
70
+ }: InternalArgs): boolean => {
71
+ const displacedTarget: Spacing = withDroppableDisplacement
72
+ ? getDroppableDisplaced(toBeDisplaced, destination)
73
+ : toBeDisplaced;
74
+
75
+ return (
76
+ isVisibleInDroppable(
77
+ displacedTarget,
78
+ destination,
79
+ isVisibleThroughFrameFn,
80
+ ) && isVisibleInViewport(displacedTarget, viewport, isVisibleThroughFrameFn)
81
+ );
82
+ };
83
+
84
+ export const isPartiallyVisible = (args: Args): boolean =>
85
+ isVisible({
86
+ ...args,
87
+ isVisibleThroughFrameFn: isPartiallyVisibleThroughFrame,
88
+ });
89
+
90
+ export const isTotallyVisible = (args: Args): boolean =>
91
+ isVisible({
92
+ ...args,
93
+ isVisibleThroughFrameFn: isTotallyVisibleThroughFrame,
94
+ });
95
+
96
+ export const isTotallyVisibleOnAxis = (args: Args): boolean =>
97
+ isVisible({
98
+ ...args,
99
+ isVisibleThroughFrameFn: isTotallyVisibleThroughFrameOnAxis(
100
+ args.destination.axis,
101
+ ),
102
+ });
@@ -0,0 +1,15 @@
1
+ // @flow
2
+ import type { Position } from 'css-box-model';
3
+ import type { DroppableDimension, Viewport } from '../../types';
4
+ import withDroppableDisplacement from './with-droppable-displacement';
5
+ import withViewportDisplacement from './with-viewport-displacement';
6
+
7
+ export default (
8
+ page: Position,
9
+ droppable: DroppableDimension,
10
+ viewport: Viewport,
11
+ ): Position =>
12
+ withDroppableDisplacement(
13
+ droppable,
14
+ withViewportDisplacement(viewport, page),
15
+ );
@@ -0,0 +1,13 @@
1
+ // @flow
2
+ import { type Position } from 'css-box-model';
3
+ import { add } from '../position';
4
+ import type { Scrollable, DroppableDimension } from '../../types';
5
+
6
+ export default (droppable: DroppableDimension, point: Position): Position => {
7
+ const frame: ?Scrollable = droppable.frame;
8
+ if (!frame) {
9
+ return point;
10
+ }
11
+
12
+ return add(point, frame.scroll.diff.displacement);
13
+ };
@@ -0,0 +1,13 @@
1
+ // @flow
2
+ import { type Rect } from 'css-box-model';
3
+ import type { Scrollable, DroppableDimension } from '../../types';
4
+ import { offsetRectByPosition } from '../rect';
5
+
6
+ export default (droppable: DroppableDimension, area: Rect): Rect => {
7
+ const frame: ?Scrollable = droppable.frame;
8
+ if (!frame) {
9
+ return area;
10
+ }
11
+
12
+ return offsetRectByPosition(area, frame.scroll.diff.value);
13
+ };
@@ -0,0 +1,7 @@
1
+ // @flow
2
+ import { type Position } from 'css-box-model';
3
+ import type { Viewport } from '../../types';
4
+ import { add } from '../position';
5
+
6
+ export default (viewport: Viewport, point: Position): Position =>
7
+ add(viewport.scroll.diff.displacement, point);