@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,68 @@
1
+ // @flow
2
+ import type { Position, Rect, Spacing } from 'css-box-model';
3
+ import type {
4
+ Axis,
5
+ AxisScrollConditions,
6
+ ScrollDetails,
7
+ DistanceThresholds,
8
+ } from '../../../../../types';
9
+
10
+ type Args = {|
11
+ axis: Axis,
12
+ center: Position,
13
+ centerInitial: Position,
14
+ container: Rect,
15
+ containerScroll: ScrollDetails,
16
+ distanceToEdges: Spacing,
17
+ bufferMinScroll: number,
18
+ thresholds: DistanceThresholds,
19
+ windowScrollOffset: Position,
20
+ |};
21
+
22
+ export default ({
23
+ axis,
24
+ bufferMinScroll,
25
+ center,
26
+ centerInitial,
27
+ container,
28
+ containerScroll,
29
+ distanceToEdges,
30
+ thresholds,
31
+ windowScrollOffset,
32
+ }: Args): AxisScrollConditions => {
33
+ const distanceInsideThresholdEnd =
34
+ distanceToEdges[axis.end] < thresholds.startScrollingFrom;
35
+
36
+ const centerInsideThresholdEnd =
37
+ center[axis.line] >
38
+ container[axis.size] -
39
+ thresholds.startScrollingFrom +
40
+ windowScrollOffset[axis.line];
41
+
42
+ const inThresholdEnd = centerInsideThresholdEnd || distanceInsideThresholdEnd;
43
+
44
+ const inThresholdStart =
45
+ center[axis.line] <
46
+ thresholds.startScrollingFrom + windowScrollOffset[axis.line];
47
+
48
+ const draggedTowardsStart =
49
+ center[axis.line] < centerInitial[axis.line] - bufferMinScroll;
50
+
51
+ const draggedTowardsEnd =
52
+ center[axis.line] > centerInitial[axis.line] + bufferMinScroll;
53
+
54
+ const scrolledTowardsStart =
55
+ containerScroll.initial[axis.line] > containerScroll.current[axis.line];
56
+
57
+ const scrolledTowardsEnd =
58
+ containerScroll.initial[axis.line] < containerScroll.current[axis.line];
59
+
60
+ return {
61
+ inThresholdStart,
62
+ inThresholdEnd,
63
+ draggedTowardsStart,
64
+ draggedTowardsEnd,
65
+ scrolledTowardsStart,
66
+ scrolledTowardsEnd,
67
+ };
68
+ };
@@ -0,0 +1,56 @@
1
+ // @flow
2
+ import type { Position, Rect, Spacing } from 'css-box-model';
3
+ import type {
4
+ ScrollConditions,
5
+ ScrollDetails,
6
+ DistanceThresholds,
7
+ } from '../../../../../types';
8
+ import { horizontal, vertical } from '../../../../axis';
9
+ import calcAxisScrollConditions from './calc-axis-scroll-conditions';
10
+
11
+ type Args = {|
12
+ bufferMinScroll: number,
13
+ center: Position,
14
+ centerInitial: Position,
15
+ container: Rect,
16
+ containerScroll: ScrollDetails,
17
+ distanceToEdges: Spacing,
18
+ thresholdsHorizontal: DistanceThresholds,
19
+ thresholdsVertical: DistanceThresholds,
20
+ windowScrollOffset: Position,
21
+ |};
22
+
23
+ export default ({
24
+ bufferMinScroll,
25
+ center,
26
+ centerInitial,
27
+ container,
28
+ containerScroll,
29
+ distanceToEdges,
30
+ thresholdsHorizontal,
31
+ thresholdsVertical,
32
+ windowScrollOffset,
33
+ }: Args): ScrollConditions => ({
34
+ xAxis: calcAxisScrollConditions({
35
+ axis: horizontal,
36
+ bufferMinScroll,
37
+ center,
38
+ centerInitial,
39
+ container,
40
+ containerScroll,
41
+ distanceToEdges,
42
+ thresholds: thresholdsHorizontal,
43
+ windowScrollOffset,
44
+ }),
45
+ yAxis: calcAxisScrollConditions({
46
+ axis: vertical,
47
+ bufferMinScroll,
48
+ center,
49
+ centerInitial,
50
+ container,
51
+ containerScroll,
52
+ distanceToEdges,
53
+ thresholds: thresholdsVertical,
54
+ windowScrollOffset,
55
+ }),
56
+ });
@@ -0,0 +1,66 @@
1
+ // @flow
2
+ import type { Position, Rect, Spacing } from 'css-box-model';
3
+ import type { DistanceThresholds, ScrollDetails } from '../../../../../types';
4
+ import getScrollConditions from './get-scroll-conditions';
5
+
6
+ const BUFFER_MIN_SCROLL_DEFAULT = 24;
7
+
8
+ type Args = {|
9
+ center: Position,
10
+ centerInitial: Position,
11
+ container: Rect,
12
+ containerScroll: ScrollDetails,
13
+ distanceToEdges: Spacing,
14
+ bufferMinScroll?: number,
15
+ scroll: Position,
16
+ thresholdsHorizontal: DistanceThresholds,
17
+ thresholdsVertical: DistanceThresholds,
18
+ windowScrollOffset: Position,
19
+ |};
20
+
21
+ export default ({
22
+ bufferMinScroll = BUFFER_MIN_SCROLL_DEFAULT,
23
+ center,
24
+ centerInitial,
25
+ container,
26
+ containerScroll,
27
+ distanceToEdges,
28
+ scroll,
29
+ thresholdsHorizontal,
30
+ thresholdsVertical,
31
+ windowScrollOffset,
32
+ }: Args): Position => {
33
+ const { xAxis, yAxis } = getScrollConditions({
34
+ bufferMinScroll,
35
+ center,
36
+ centerInitial,
37
+ container,
38
+ containerScroll,
39
+ distanceToEdges,
40
+ thresholdsHorizontal,
41
+ thresholdsVertical,
42
+ windowScrollOffset,
43
+ });
44
+
45
+ if (xAxis.inThresholdStart) {
46
+ if (!xAxis.draggedTowardsStart && !xAxis.scrolledTowardsEnd) {
47
+ scroll.x = 0;
48
+ }
49
+ } else if (xAxis.inThresholdEnd) {
50
+ if (!xAxis.draggedTowardsEnd && !xAxis.scrolledTowardsStart) {
51
+ scroll.x = 0;
52
+ }
53
+ }
54
+
55
+ if (yAxis.inThresholdStart) {
56
+ if (!yAxis.draggedTowardsStart && !yAxis.scrolledTowardsEnd) {
57
+ scroll.y = 0;
58
+ }
59
+ } else if (yAxis.inThresholdEnd) {
60
+ if (!yAxis.draggedTowardsEnd && !yAxis.scrolledTowardsStart) {
61
+ scroll.y = 0;
62
+ }
63
+ }
64
+
65
+ return scroll;
66
+ };
@@ -0,0 +1,48 @@
1
+ // @flow
2
+ import getPercentage from '../../get-percentage';
3
+ import config from '../../config';
4
+ import minScroll from './min-scroll';
5
+ import type { FluidScrollerConfigOverride } from '../../../../../types';
6
+
7
+ const defaultAccelerateAt: number = config.durationDampening.accelerateAt;
8
+ const defaultStopAt: number = config.durationDampening.stopDampeningAt;
9
+
10
+ export default (
11
+ proposedScroll: number,
12
+ dragStartTime: number,
13
+ configOverride?: FluidScrollerConfigOverride,
14
+ ): number => {
15
+ const accelerateAt: number =
16
+ configOverride?.durationDampening?.accelerateAt || defaultAccelerateAt;
17
+ const stopAt: number =
18
+ configOverride?.durationDampening?.stopDampeningAt || defaultStopAt;
19
+ const ease: Function = configOverride?.ease || config.ease;
20
+
21
+ const startOfRange: number = dragStartTime;
22
+ const endOfRange: number = stopAt;
23
+ const now: number = Date.now();
24
+ const runTime: number = now - startOfRange;
25
+
26
+ // we have finished the time dampening period
27
+ if (runTime >= stopAt) {
28
+ return proposedScroll;
29
+ }
30
+
31
+ // Up to this point we know there is a proposed scroll
32
+ // but we have not reached our accelerate point
33
+ // Return the minimum amount of scroll
34
+ if (runTime < accelerateAt) {
35
+ return minScroll;
36
+ }
37
+
38
+ const betweenAccelerateAtAndStopAtPercentage: number = getPercentage({
39
+ startOfRange: accelerateAt,
40
+ endOfRange,
41
+ current: runTime,
42
+ });
43
+
44
+ const scroll: number =
45
+ proposedScroll * ease(betweenAccelerateAtAndStopAtPercentage);
46
+
47
+ return Math.ceil(scroll);
48
+ };
@@ -0,0 +1,31 @@
1
+ // @flow
2
+ import type { Rect } from 'css-box-model';
3
+ import config from '../../config';
4
+ import type {
5
+ Axis,
6
+ DistanceThresholds,
7
+ FluidScrollerConfigOverride,
8
+ } from '../../../../../types';
9
+
10
+ // converts the percentages in the config (or override) into actual pixel values
11
+ export default (
12
+ container: Rect,
13
+ axis: Axis,
14
+ configOverride?: FluidScrollerConfigOverride,
15
+ ): DistanceThresholds => {
16
+ const startFromPercentage =
17
+ configOverride?.startFromPercentage || config.startFromPercentage;
18
+
19
+ const maxScrollAtPercentage =
20
+ configOverride?.maxScrollAtPercentage || config.maxScrollAtPercentage;
21
+
22
+ const startScrollingFrom: number = container[axis.size] * startFromPercentage;
23
+ const maxScrollValueAt: number = container[axis.size] * maxScrollAtPercentage;
24
+
25
+ const thresholds: DistanceThresholds = {
26
+ startScrollingFrom,
27
+ maxScrollValueAt,
28
+ };
29
+
30
+ return thresholds;
31
+ };
@@ -0,0 +1,67 @@
1
+ // @flow
2
+ import type {
3
+ DistanceThresholds,
4
+ FluidScrollerConfigOverride,
5
+ } from '../../../../../types';
6
+ import getPercentage from '../../get-percentage';
7
+ import config from '../../config';
8
+ import minScroll from './min-scroll';
9
+
10
+ export default (
11
+ distanceToEdge: number,
12
+ thresholds: DistanceThresholds,
13
+ configOverride?: FluidScrollerConfigOverride,
14
+ ): number => {
15
+ /*
16
+ // This function only looks at the distance to one edge
17
+ // Example: looking at bottom edge
18
+ |----------------------------------|
19
+ | |
20
+ | |
21
+ | |
22
+ | |
23
+ | | => no scroll in this range
24
+ | |
25
+ | |
26
+ | startScrollingFrom (eg 100px) |
27
+ | |
28
+ | | => increased scroll value the closer to maxScrollValueAt
29
+ | maxScrollValueAt (eg 10px) |
30
+ | | => max scroll value in this range
31
+ |----------------------------------|
32
+ */
33
+
34
+ // too far away to auto scroll
35
+ if (distanceToEdge > thresholds.startScrollingFrom) {
36
+ return 0;
37
+ }
38
+
39
+ const maxSpeed = configOverride?.maxPixelScroll || config.maxPixelScroll;
40
+
41
+ // use max speed when on or over boundary
42
+ if (distanceToEdge <= thresholds.maxScrollValueAt) {
43
+ return maxSpeed;
44
+ }
45
+
46
+ // when just going on the boundary return the minimum integer
47
+ if (distanceToEdge === thresholds.startScrollingFrom) {
48
+ return minScroll;
49
+ }
50
+
51
+ // to get the % past startScrollingFrom we will calculate
52
+ // the % the value is from maxScrollValueAt and then invert it
53
+ const percentageFromMaxScrollValueAt: number = getPercentage({
54
+ startOfRange: thresholds.maxScrollValueAt,
55
+ endOfRange: thresholds.startScrollingFrom,
56
+ current: distanceToEdge,
57
+ });
58
+
59
+ const percentageFromStartScrollingFrom: number =
60
+ 1 - percentageFromMaxScrollValueAt;
61
+
62
+ const scroll: number =
63
+ maxSpeed * config.ease(percentageFromStartScrollingFrom);
64
+
65
+ // scroll will always be a positive integer
66
+ return Math.ceil(scroll);
67
+ };
@@ -0,0 +1,51 @@
1
+ // @flow
2
+ import type {
3
+ DistanceThresholds,
4
+ FluidScrollerConfigOverride,
5
+ } from '../../../../../types';
6
+ import getValueFromDistance from './get-value-from-distance';
7
+ import dampenValueByTime from './dampen-value-by-time';
8
+ import minScroll from './min-scroll';
9
+
10
+ type Args = {|
11
+ configOverride?: FluidScrollerConfigOverride,
12
+ distanceToEdge: number,
13
+ dragStartTime: number,
14
+ shouldUseTimeDampening: boolean,
15
+ thresholds: DistanceThresholds,
16
+ |};
17
+
18
+ export default ({
19
+ configOverride,
20
+ distanceToEdge,
21
+ dragStartTime,
22
+ shouldUseTimeDampening,
23
+ thresholds,
24
+ }: Args): number => {
25
+ const scroll: number = getValueFromDistance(
26
+ distanceToEdge,
27
+ thresholds,
28
+ configOverride,
29
+ );
30
+
31
+ // not enough distance to trigger a minimum scroll
32
+ // we can bail here
33
+ if (scroll === 0) {
34
+ return 0;
35
+ }
36
+
37
+ // Dampen an auto scroll speed based on duration of drag
38
+
39
+ if (!shouldUseTimeDampening) {
40
+ return scroll;
41
+ }
42
+
43
+ // Once we know an auto scroll should occur based on distance,
44
+ // we must let at least 1px through to trigger a scroll event an
45
+ // another auto scroll call
46
+
47
+ return Math.max(
48
+ dampenValueByTime(scroll, dragStartTime, configOverride),
49
+ minScroll,
50
+ );
51
+ };
@@ -0,0 +1,50 @@
1
+ // @flow
2
+ import type { Spacing } from 'css-box-model';
3
+ import type {
4
+ Axis,
5
+ DistanceThresholds,
6
+ FluidScrollerConfigOverride,
7
+ } from '../../../../../types';
8
+ import getValue from './get-value';
9
+
10
+ type GetOnAxisArgs = {|
11
+ axis: Axis,
12
+ configOverride?: FluidScrollerConfigOverride,
13
+ distanceToEdges: Spacing,
14
+ dragStartTime: number,
15
+ shouldUseTimeDampening: boolean,
16
+ thresholds: DistanceThresholds,
17
+ |};
18
+
19
+ export default ({
20
+ axis,
21
+ configOverride,
22
+ distanceToEdges,
23
+ dragStartTime,
24
+ shouldUseTimeDampening,
25
+ thresholds,
26
+ }: GetOnAxisArgs): number => {
27
+ const isCloserToEnd: boolean =
28
+ distanceToEdges[axis.end] < distanceToEdges[axis.start];
29
+
30
+ if (isCloserToEnd) {
31
+ return getValue({
32
+ configOverride,
33
+ distanceToEdge: distanceToEdges[axis.end],
34
+ dragStartTime,
35
+ shouldUseTimeDampening,
36
+ thresholds,
37
+ });
38
+ }
39
+
40
+ return (
41
+ -1 *
42
+ getValue({
43
+ configOverride,
44
+ distanceToEdge: distanceToEdges[axis.start],
45
+ dragStartTime,
46
+ shouldUseTimeDampening,
47
+ thresholds,
48
+ })
49
+ );
50
+ };
@@ -0,0 +1,4 @@
1
+ // @flow
2
+
3
+ // A scroll event will only be triggered when there is a value of at least 1px change
4
+ export default 1;
@@ -0,0 +1,139 @@
1
+ // @flow
2
+ import type { Position, Rect, Spacing } from 'css-box-model';
3
+ import { apply, isEqual, origin } from '../../../position';
4
+ import getScrollOnAxis from './get-scroll-on-axis';
5
+ import adjustForSizeLimits from './adjust-for-size-limits';
6
+ import { horizontal, vertical } from '../../../axis';
7
+ import bufferThresholds from './buffer-thresholds';
8
+ import getDistanceThresholds from './get-scroll-on-axis/get-distance-thresholds';
9
+ import type {
10
+ DistanceThresholds,
11
+ FluidScrollerOptions,
12
+ ScrollDetails,
13
+ } from '../../../../types';
14
+
15
+ // will replace -0 and replace with +0
16
+ const clean = apply((value: number) => (value === 0 ? 0 : value));
17
+
18
+ type Args = {|
19
+ dragStartTime: number,
20
+ container: Rect,
21
+ containerScroll: ScrollDetails,
22
+ subject: Rect,
23
+ center: Position,
24
+ centerInitial: Position,
25
+ shouldUseTimeDampening: boolean,
26
+ fluidScrollerOptions?: FluidScrollerOptions,
27
+ windowScrollOffset?: Position,
28
+ |};
29
+
30
+ export default ({
31
+ dragStartTime,
32
+ container,
33
+ containerScroll,
34
+ subject,
35
+ center,
36
+ centerInitial,
37
+ shouldUseTimeDampening,
38
+ fluidScrollerOptions,
39
+ windowScrollOffset = origin,
40
+ }: Args): ?Position => {
41
+ // get distance to each edge
42
+ const distanceToEdges: Spacing = {
43
+ top: center.y - container.top,
44
+ right: container.right - center.x,
45
+ bottom: container.bottom - center.y,
46
+ left: center.x - container.left,
47
+ };
48
+
49
+ const thresholdsVertical: DistanceThresholds = getDistanceThresholds(
50
+ container,
51
+ vertical,
52
+ fluidScrollerOptions?.configOverride,
53
+ );
54
+
55
+ const thresholdsHorizontal: DistanceThresholds = getDistanceThresholds(
56
+ container,
57
+ horizontal,
58
+ fluidScrollerOptions?.configOverride,
59
+ );
60
+
61
+ // 1. Figure out which x,y values are the best target
62
+ // 2. Can the container scroll in that direction at all?
63
+ // If no for both directions, then return null
64
+ // 3. Is the center close enough to a edge to start a drag?
65
+ // 4. Based on the distance, calculate the speed at which a scroll should occur
66
+ // The lower distance value the faster the scroll should be.
67
+ // Maximum speed value should be hit before the distance is 0
68
+ // Negative values to not continue to increase the speed
69
+ const y: number = getScrollOnAxis({
70
+ axis: vertical,
71
+ configOverride: fluidScrollerOptions?.configOverride,
72
+ distanceToEdges,
73
+ dragStartTime,
74
+ shouldUseTimeDampening,
75
+ thresholds: thresholdsVertical,
76
+ });
77
+ const x: number = getScrollOnAxis({
78
+ axis: horizontal,
79
+ configOverride: fluidScrollerOptions?.configOverride,
80
+ distanceToEdges,
81
+ dragStartTime,
82
+ shouldUseTimeDampening,
83
+ thresholds: thresholdsHorizontal,
84
+ });
85
+ const required: Position = clean({ x, y });
86
+
87
+ // nothing required
88
+ if (isEqual(required, origin)) {
89
+ return null;
90
+ }
91
+
92
+ // need to not scroll in a direction that we are too big to scroll in
93
+ const limited: ?Position = adjustForSizeLimits({
94
+ container,
95
+ subject,
96
+ proposedScroll: required,
97
+ });
98
+
99
+ if (!limited) {
100
+ return null;
101
+ }
102
+
103
+ let scroll: Position = limited;
104
+
105
+ if (fluidScrollerOptions) {
106
+ if (fluidScrollerOptions.bufferThresholds) {
107
+ // if the draggable originates inside a scroll threshold
108
+ // don't autoscroll in that threshold's direction until dragged in that direction
109
+ scroll = bufferThresholds({
110
+ bufferMinScroll: fluidScrollerOptions?.bufferMinScroll,
111
+ center,
112
+ centerInitial,
113
+ container,
114
+ containerScroll,
115
+ distanceToEdges,
116
+ scroll,
117
+ thresholdsHorizontal,
118
+ thresholdsVertical,
119
+ windowScrollOffset,
120
+ });
121
+ }
122
+ if (fluidScrollerOptions.thruGetScroll) {
123
+ // apply consumer injected scroll behavior
124
+ scroll = fluidScrollerOptions.thruGetScroll({
125
+ center,
126
+ centerInitial,
127
+ container,
128
+ containerScroll,
129
+ distanceToEdges,
130
+ scroll,
131
+ thresholdsHorizontal,
132
+ thresholdsVertical,
133
+ windowScrollOffset,
134
+ });
135
+ }
136
+ }
137
+
138
+ return isEqual(scroll, origin) ? null : scroll;
139
+ };
@@ -0,0 +1,43 @@
1
+ // @flow
2
+ import type { Position, Rect } from 'css-box-model';
3
+ import type { FluidScrollerOptions, Viewport } from '../../../types';
4
+ import getScroll from './get-scroll';
5
+ import { canScrollWindow } from '../can-scroll';
6
+
7
+ type Args = {|
8
+ viewport: Viewport,
9
+ subject: Rect,
10
+ center: Position,
11
+ centerInitial: Position,
12
+ dragStartTime: number,
13
+ shouldUseTimeDampening: boolean,
14
+ fluidScrollerOptions?: FluidScrollerOptions,
15
+ |};
16
+
17
+ export default ({
18
+ viewport,
19
+ subject,
20
+ center,
21
+ centerInitial,
22
+ dragStartTime,
23
+ shouldUseTimeDampening,
24
+ fluidScrollerOptions,
25
+ }: Args): ?Position => {
26
+ const windowScrollOffset: Position = {
27
+ x: viewport.scroll.current.x,
28
+ y: viewport.scroll.current.y,
29
+ };
30
+ const scroll: ?Position = getScroll({
31
+ dragStartTime,
32
+ container: viewport.frame,
33
+ containerScroll: viewport.scroll,
34
+ subject,
35
+ center,
36
+ centerInitial,
37
+ shouldUseTimeDampening,
38
+ fluidScrollerOptions,
39
+ windowScrollOffset,
40
+ });
41
+
42
+ return scroll && canScrollWindow(viewport, scroll) ? scroll : null;
43
+ };