react-native-drax 0.11.0-alpha.2 → 1.0.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 (246) hide show
  1. package/LICENSE.md +1 -1
  2. package/README.md +385 -227
  3. package/lib/module/DebugOverlay.js +121 -0
  4. package/lib/module/DebugOverlay.js.map +1 -0
  5. package/lib/module/Drax.js +36 -0
  6. package/lib/module/Drax.js.map +1 -0
  7. package/lib/module/DraxContext.js +6 -0
  8. package/lib/module/DraxContext.js.map +1 -0
  9. package/lib/module/DraxHandle.js +47 -0
  10. package/lib/module/DraxHandle.js.map +1 -0
  11. package/lib/module/DraxHandleContext.js +11 -0
  12. package/lib/module/DraxHandleContext.js.map +1 -0
  13. package/lib/module/DraxList.js +108 -0
  14. package/lib/module/DraxList.js.map +1 -0
  15. package/lib/module/DraxProvider.js +203 -0
  16. package/lib/module/DraxProvider.js.map +1 -0
  17. package/lib/module/DraxScrollView.js +167 -0
  18. package/lib/module/DraxScrollView.js.map +1 -0
  19. package/lib/module/DraxSubprovider.js +21 -0
  20. package/lib/module/DraxSubprovider.js.map +1 -0
  21. package/lib/module/DraxView.js +348 -0
  22. package/lib/module/DraxView.js.map +1 -0
  23. package/lib/module/HoverLayer.js +152 -0
  24. package/lib/module/HoverLayer.js.map +1 -0
  25. package/lib/module/SortableBoardContainer.js +386 -0
  26. package/lib/module/SortableBoardContainer.js.map +1 -0
  27. package/lib/module/SortableBoardContext.js +6 -0
  28. package/lib/module/SortableBoardContext.js.map +1 -0
  29. package/lib/module/SortableContainer.js +561 -0
  30. package/lib/module/SortableContainer.js.map +1 -0
  31. package/lib/module/SortableItem.js +226 -0
  32. package/lib/module/SortableItem.js.map +1 -0
  33. package/lib/module/SortableItemContext.js +38 -0
  34. package/lib/module/SortableItemContext.js.map +1 -0
  35. package/lib/module/compat/detectVersion.js +19 -0
  36. package/lib/module/compat/detectVersion.js.map +1 -0
  37. package/lib/module/compat/index.js +5 -0
  38. package/lib/module/compat/index.js.map +1 -0
  39. package/lib/module/compat/types.js +4 -0
  40. package/lib/module/compat/types.js.map +1 -0
  41. package/lib/module/compat/useDraxPanGesture.js +94 -0
  42. package/lib/module/compat/useDraxPanGesture.js.map +1 -0
  43. package/lib/module/hooks/index.js +5 -0
  44. package/lib/module/hooks/index.js.map +1 -0
  45. package/lib/module/hooks/useCallbackDispatch.js +681 -0
  46. package/lib/module/hooks/useCallbackDispatch.js.map +1 -0
  47. package/lib/module/hooks/useDragGesture.js +240 -0
  48. package/lib/module/hooks/useDragGesture.js.map +1 -0
  49. package/lib/module/hooks/useDraxContext.js +12 -0
  50. package/lib/module/hooks/useDraxContext.js.map +1 -0
  51. package/lib/module/hooks/useDraxId.js +13 -0
  52. package/lib/module/hooks/useDraxId.js.map +1 -0
  53. package/lib/module/hooks/useDraxMethods.js +73 -0
  54. package/lib/module/hooks/useDraxMethods.js.map +1 -0
  55. package/lib/module/hooks/useDraxScrollHandler.js +97 -0
  56. package/lib/module/hooks/useDraxScrollHandler.js.map +1 -0
  57. package/lib/module/hooks/useSortableBoard.js +37 -0
  58. package/lib/module/hooks/useSortableBoard.js.map +1 -0
  59. package/lib/module/hooks/useSortableList.js +824 -0
  60. package/lib/module/hooks/useSortableList.js.map +1 -0
  61. package/lib/module/hooks/useSpatialIndex.js +283 -0
  62. package/lib/module/hooks/useSpatialIndex.js.map +1 -0
  63. package/lib/module/hooks/useViewStyles.js +158 -0
  64. package/lib/module/hooks/useViewStyles.js.map +1 -0
  65. package/lib/module/hooks/useWebScrollFreeze.js +52 -0
  66. package/lib/module/hooks/useWebScrollFreeze.js.map +1 -0
  67. package/lib/module/index.js +37 -0
  68. package/lib/module/index.js.map +1 -0
  69. package/lib/module/math.js +222 -0
  70. package/lib/module/math.js.map +1 -0
  71. package/lib/module/package.json +1 -0
  72. package/lib/module/params.js +88 -0
  73. package/lib/module/params.js.map +1 -0
  74. package/lib/module/types.js +213 -0
  75. package/lib/module/types.js.map +1 -0
  76. package/lib/typescript/package.json +1 -0
  77. package/lib/typescript/src/DebugOverlay.d.ts +17 -0
  78. package/lib/typescript/src/DebugOverlay.d.ts.map +1 -0
  79. package/lib/typescript/src/Drax.d.ts +28 -0
  80. package/lib/typescript/src/Drax.d.ts.map +1 -0
  81. package/lib/typescript/src/DraxContext.d.ts +3 -0
  82. package/lib/typescript/src/DraxContext.d.ts.map +1 -0
  83. package/lib/typescript/src/DraxHandle.d.ts +25 -0
  84. package/lib/typescript/src/DraxHandle.d.ts.map +1 -0
  85. package/lib/typescript/src/DraxHandleContext.d.ts +12 -0
  86. package/lib/typescript/src/DraxHandleContext.d.ts.map +1 -0
  87. package/lib/typescript/src/DraxList.d.ts +66 -0
  88. package/lib/typescript/src/DraxList.d.ts.map +1 -0
  89. package/lib/typescript/src/DraxProvider.d.ts +4 -0
  90. package/lib/typescript/src/DraxProvider.d.ts.map +1 -0
  91. package/lib/typescript/src/DraxScrollView.d.ts +7 -0
  92. package/lib/typescript/src/DraxScrollView.d.ts.map +1 -0
  93. package/lib/typescript/src/DraxSubprovider.d.ts +4 -0
  94. package/lib/typescript/src/DraxSubprovider.d.ts.map +1 -0
  95. package/lib/typescript/src/DraxView.d.ts +4 -0
  96. package/lib/typescript/src/DraxView.d.ts.map +1 -0
  97. package/lib/typescript/src/HoverLayer.d.ts +38 -0
  98. package/lib/typescript/src/HoverLayer.d.ts.map +1 -0
  99. package/lib/typescript/src/SortableBoardContainer.d.ts +11 -0
  100. package/lib/typescript/src/SortableBoardContainer.d.ts.map +1 -0
  101. package/lib/typescript/src/SortableBoardContext.d.ts +4 -0
  102. package/lib/typescript/src/SortableBoardContext.d.ts.map +1 -0
  103. package/lib/typescript/src/SortableContainer.d.ts +13 -0
  104. package/lib/typescript/src/SortableContainer.d.ts.map +1 -0
  105. package/lib/typescript/src/SortableItem.d.ts +14 -0
  106. package/lib/typescript/src/SortableItem.d.ts.map +1 -0
  107. package/lib/typescript/src/SortableItemContext.d.ts +37 -0
  108. package/lib/typescript/src/SortableItemContext.d.ts.map +1 -0
  109. package/lib/typescript/src/compat/detectVersion.d.ts +2 -0
  110. package/lib/typescript/src/compat/detectVersion.d.ts.map +1 -0
  111. package/lib/typescript/src/compat/index.d.ts +4 -0
  112. package/lib/typescript/src/compat/index.d.ts.map +1 -0
  113. package/lib/typescript/src/compat/types.d.ts +33 -0
  114. package/lib/typescript/src/compat/types.d.ts.map +1 -0
  115. package/lib/typescript/src/compat/useDraxPanGesture.d.ts +8 -0
  116. package/lib/typescript/src/compat/useDraxPanGesture.d.ts.map +1 -0
  117. package/lib/typescript/src/hooks/index.d.ts +3 -0
  118. package/lib/typescript/src/hooks/index.d.ts.map +1 -0
  119. package/lib/typescript/src/hooks/useCallbackDispatch.d.ts +40 -0
  120. package/lib/typescript/src/hooks/useCallbackDispatch.d.ts.map +1 -0
  121. package/lib/typescript/src/hooks/useDragGesture.d.ts +17 -0
  122. package/lib/typescript/src/hooks/useDragGesture.d.ts.map +1 -0
  123. package/lib/typescript/src/hooks/useDraxContext.d.ts +2 -0
  124. package/lib/typescript/src/hooks/useDraxContext.d.ts.map +1 -0
  125. package/{build → lib/typescript/src}/hooks/useDraxId.d.ts +1 -0
  126. package/lib/typescript/src/hooks/useDraxId.d.ts.map +1 -0
  127. package/lib/typescript/src/hooks/useDraxMethods.d.ts +13 -0
  128. package/lib/typescript/src/hooks/useDraxMethods.d.ts.map +1 -0
  129. package/lib/typescript/src/hooks/useDraxScrollHandler.d.ts +27 -0
  130. package/lib/typescript/src/hooks/useDraxScrollHandler.d.ts.map +1 -0
  131. package/lib/typescript/src/hooks/useSortableBoard.d.ts +10 -0
  132. package/lib/typescript/src/hooks/useSortableBoard.d.ts.map +1 -0
  133. package/lib/typescript/src/hooks/useSortableList.d.ts +11 -0
  134. package/lib/typescript/src/hooks/useSortableList.d.ts.map +1 -0
  135. package/lib/typescript/src/hooks/useSpatialIndex.d.ts +22 -0
  136. package/lib/typescript/src/hooks/useSpatialIndex.d.ts.map +1 -0
  137. package/lib/typescript/src/hooks/useViewStyles.d.ts +183 -0
  138. package/lib/typescript/src/hooks/useViewStyles.d.ts.map +1 -0
  139. package/lib/typescript/src/hooks/useWebScrollFreeze.d.ts +14 -0
  140. package/lib/typescript/src/hooks/useWebScrollFreeze.d.ts.map +1 -0
  141. package/lib/typescript/src/index.d.ts +25 -0
  142. package/lib/typescript/src/index.d.ts.map +1 -0
  143. package/lib/typescript/src/math.d.ts +52 -0
  144. package/lib/typescript/src/math.d.ts.map +1 -0
  145. package/{build → lib/typescript/src}/params.d.ts +13 -9
  146. package/lib/typescript/src/params.d.ts.map +1 -0
  147. package/lib/typescript/src/types.d.ts +743 -0
  148. package/lib/typescript/src/types.d.ts.map +1 -0
  149. package/package.json +164 -34
  150. package/src/DebugOverlay.tsx +140 -0
  151. package/src/Drax.ts +33 -0
  152. package/src/DraxContext.ts +8 -0
  153. package/src/DraxHandle.tsx +52 -0
  154. package/src/DraxHandleContext.ts +15 -0
  155. package/src/DraxList.tsx +181 -0
  156. package/src/DraxProvider.tsx +224 -0
  157. package/src/DraxScrollView.tsx +180 -0
  158. package/src/DraxSubprovider.tsx +22 -0
  159. package/src/DraxView.tsx +430 -0
  160. package/src/HoverLayer.tsx +167 -0
  161. package/src/SortableBoardContainer.tsx +439 -0
  162. package/src/SortableBoardContext.ts +6 -0
  163. package/src/SortableContainer.tsx +642 -0
  164. package/src/SortableItem.tsx +264 -0
  165. package/src/SortableItemContext.ts +46 -0
  166. package/src/compat/detectVersion.ts +17 -0
  167. package/src/compat/index.ts +7 -0
  168. package/src/compat/types.ts +35 -0
  169. package/src/compat/useDraxPanGesture.ts +112 -0
  170. package/src/hooks/index.ts +2 -0
  171. package/src/hooks/useCallbackDispatch.tsx +823 -0
  172. package/src/hooks/useDragGesture.ts +273 -0
  173. package/src/hooks/useDraxContext.ts +11 -0
  174. package/src/hooks/useDraxId.ts +11 -0
  175. package/src/hooks/useDraxMethods.ts +71 -0
  176. package/src/hooks/useDraxScrollHandler.ts +121 -0
  177. package/src/hooks/useSortableBoard.ts +44 -0
  178. package/src/hooks/useSortableList.ts +868 -0
  179. package/src/hooks/useSpatialIndex.ts +336 -0
  180. package/src/hooks/useViewStyles.ts +180 -0
  181. package/src/hooks/useWebScrollFreeze.ts +60 -0
  182. package/src/index.ts +110 -0
  183. package/src/math.ts +251 -0
  184. package/src/params.ts +74 -0
  185. package/src/types.ts +919 -0
  186. package/.editorconfig +0 -15
  187. package/.eslintrc.js +0 -4
  188. package/.prettierrc +0 -16
  189. package/CHANGELOG.md +0 -270
  190. package/CODE-OF-CONDUCT.md +0 -85
  191. package/CONTRIBUTING.md +0 -15
  192. package/FUNDING.yml +0 -4
  193. package/build/AllHoverViews.d.ts +0 -0
  194. package/build/AllHoverViews.js +0 -30
  195. package/build/DraxContext.d.ts +0 -2
  196. package/build/DraxContext.js +0 -6
  197. package/build/DraxList.d.ts +0 -8
  198. package/build/DraxList.js +0 -512
  199. package/build/DraxListItem.d.ts +0 -7
  200. package/build/DraxListItem.js +0 -121
  201. package/build/DraxProvider.d.ts +0 -2
  202. package/build/DraxProvider.js +0 -704
  203. package/build/DraxScrollView.d.ts +0 -6
  204. package/build/DraxScrollView.js +0 -136
  205. package/build/DraxSubprovider.d.ts +0 -3
  206. package/build/DraxSubprovider.js +0 -18
  207. package/build/DraxView.d.ts +0 -8
  208. package/build/DraxView.js +0 -93
  209. package/build/HoverView.d.ts +0 -8
  210. package/build/HoverView.js +0 -40
  211. package/build/PanGestureDetector.d.ts +0 -3
  212. package/build/PanGestureDetector.js +0 -49
  213. package/build/hooks/index.d.ts +0 -4
  214. package/build/hooks/index.js +0 -11
  215. package/build/hooks/useContent.d.ts +0 -23
  216. package/build/hooks/useContent.js +0 -212
  217. package/build/hooks/useDraxContext.d.ts +0 -1
  218. package/build/hooks/useDraxContext.js +0 -13
  219. package/build/hooks/useDraxId.js +0 -13
  220. package/build/hooks/useDraxProtocol.d.ts +0 -5
  221. package/build/hooks/useDraxProtocol.js +0 -32
  222. package/build/hooks/useDraxRegistry.d.ts +0 -78
  223. package/build/hooks/useDraxRegistry.js +0 -714
  224. package/build/hooks/useDraxScrollHandler.d.ts +0 -25
  225. package/build/hooks/useDraxScrollHandler.js +0 -89
  226. package/build/hooks/useDraxState.d.ts +0 -10
  227. package/build/hooks/useDraxState.js +0 -132
  228. package/build/hooks/useMeasurements.d.ts +0 -9
  229. package/build/hooks/useMeasurements.js +0 -119
  230. package/build/hooks/useStatus.d.ts +0 -11
  231. package/build/hooks/useStatus.js +0 -96
  232. package/build/index.d.ts +0 -9
  233. package/build/index.js +0 -33
  234. package/build/math.d.ts +0 -22
  235. package/build/math.js +0 -68
  236. package/build/params.js +0 -27
  237. package/build/transform.d.ts +0 -11
  238. package/build/transform.js +0 -59
  239. package/build/types.d.ts +0 -807
  240. package/build/types.js +0 -46
  241. package/docs/concept.md +0 -79
  242. package/docs/images/color-drag-drop.gif +0 -0
  243. package/docs/images/deck-cards.gif +0 -0
  244. package/docs/images/drag-drop-events.jpg +0 -0
  245. package/docs/images/knight-moves.gif +0 -0
  246. package/docs/images/reorderable-list.gif +0 -0
package/src/math.ts ADDED
@@ -0,0 +1,251 @@
1
+ import type {
2
+ DraxViewMeasurements,
3
+ HitTestResult,
4
+ Position,
5
+ SpatialEntry,
6
+ ViewDimensions,
7
+ } from './types';
8
+
9
+ export const getRelativePosition = (
10
+ { x, y }: Position,
11
+ { width, height, x: x0, y: y0 }: DraxViewMeasurements
12
+ ) => {
13
+ 'worklet';
14
+ const rx = x - x0;
15
+ const ry = y - y0;
16
+ return {
17
+ relativePosition: { x: rx, y: ry },
18
+ // Guard against division by zero for zero-dimension views
19
+ relativePositionRatio: { x: rx / (width || 1), y: ry / (height || 1) },
20
+ };
21
+ };
22
+
23
+ export const generateRandomId = () =>
24
+ `${Math.random().toString(36).substring(2)}${Math.random().toString(36).substring(2)}`;
25
+
26
+ /**
27
+ * Compute the absolute position of a spatial entry by walking the parent chain.
28
+ * Accounts for scroll offsets at each level.
29
+ */
30
+ export const computeAbsolutePositionWorklet = (
31
+ entryIndex: number,
32
+ entries: SpatialEntry[],
33
+ scrollOffsets: Position[]
34
+ ): Position => {
35
+ 'worklet';
36
+ const entry = entries[entryIndex];
37
+ if (!entry) return { x: 0, y: 0 };
38
+
39
+ let absX = entry.x;
40
+ let absY = entry.y;
41
+ let parentIdx = entry.parentIndex;
42
+
43
+ while (parentIdx >= 0) {
44
+ const parent = entries[parentIdx];
45
+ if (!parent) break;
46
+ const parentScroll = scrollOffsets[parentIdx] || { x: 0, y: 0 };
47
+ absX += parent.x - parentScroll.x;
48
+ absY += parent.y - parentScroll.y;
49
+ parentIdx = parent.parentIndex;
50
+ }
51
+
52
+ return { x: absX, y: absY };
53
+ };
54
+
55
+ /**
56
+ * Extra padding (in points) applied to monitoring views during hit-testing.
57
+ * During auto-scroll the hover center can drift outside the container's visible
58
+ * bounds. This padding prevents false monitor exits that would prematurely end
59
+ * the drag. Receptive views keep exact bounds for precise drop targeting.
60
+ */
61
+ const MONITOR_HIT_TEST_PADDING = 100;
62
+
63
+ /**
64
+ * Hit-test all views in the spatial index against a given absolute position.
65
+ * Runs entirely on the UI thread as a worklet.
66
+ * Returns the deepest receptive view and all monitoring views that contain the point.
67
+ *
68
+ * @param position - Center of the hover view (absolute)
69
+ * @param entries - Spatial index entries
70
+ * @param scrollOffsets - Scroll offsets per entry
71
+ * @param excludeId - ID of the dragged view (excluded from hit-testing)
72
+ * @param draggedDimensions - Optional dimensions of the dragged view (needed for intersect/contain)
73
+ */
74
+ export const hitTestWorklet = (
75
+ position: Position,
76
+ entries: SpatialEntry[],
77
+ scrollOffsets: Position[],
78
+ excludeId: string,
79
+ draggedDimensions?: ViewDimensions
80
+ ): HitTestResult => {
81
+ 'worklet';
82
+
83
+ let receiverId = '';
84
+ const monitorIds: string[] = [];
85
+
86
+ // Find the dragged item's parent index for rejectOwnChildren check
87
+ let draggedParentIndex = -1;
88
+ for (let i = 0; i < entries.length; i++) {
89
+ if (entries[i]?.id === excludeId) {
90
+ draggedParentIndex = entries[i]!.parentIndex;
91
+ break;
92
+ }
93
+ }
94
+
95
+ // Dragged view bounds (for intersect/contain algorithms)
96
+ const dw = draggedDimensions?.width ?? 0;
97
+ const dh = draggedDimensions?.height ?? 0;
98
+ // position is the center of the hover view; compute top-left
99
+ const dragLeft = position.x - dw / 2;
100
+ const dragTop = position.y - dh / 2;
101
+ const dragRight = dragLeft + dw;
102
+ const dragBottom = dragTop + dh;
103
+
104
+ for (let i = 0; i < entries.length; i++) {
105
+ const entry = entries[i];
106
+ if (!entry) continue;
107
+ if (entry.id === excludeId) continue;
108
+ if (!entry.receptive && !entry.monitoring) continue;
109
+
110
+ // Skip views with zero dimensions (not yet measured)
111
+ if (entry.width === 0 || entry.height === 0) continue;
112
+
113
+ // Compute absolute position by walking parent chain
114
+ const absPos = computeAbsolutePositionWorklet(i, entries, scrollOffsets);
115
+
116
+ const recLeft = absPos.x;
117
+ const recTop = absPos.y;
118
+ const recRight = recLeft + entry.width;
119
+ const recBottom = recTop + entry.height;
120
+
121
+ let isHit: boolean;
122
+ const algo = entry.collisionAlgorithm;
123
+
124
+ if (algo === 'intersect' && dw > 0 && dh > 0) {
125
+ // Any overlap between dragged view and receiver
126
+ isHit =
127
+ dragLeft < recRight &&
128
+ dragRight > recLeft &&
129
+ dragTop < recBottom &&
130
+ dragBottom > recTop;
131
+ } else if (algo === 'contain' && dw > 0 && dh > 0) {
132
+ // Dragged view is fully inside receiver
133
+ isHit =
134
+ dragLeft >= recLeft &&
135
+ dragRight <= recRight &&
136
+ dragTop >= recTop &&
137
+ dragBottom <= recBottom;
138
+ } else {
139
+ // Default 'center': hover center is inside receiver
140
+ isHit =
141
+ position.x >= recLeft &&
142
+ position.y >= recTop &&
143
+ position.x < recRight &&
144
+ position.y < recBottom;
145
+ }
146
+
147
+ if (isHit) {
148
+ if (entry.monitoring) monitorIds.push(entry.id);
149
+ // Take the last (deepest/most recently registered) receptive match
150
+ // Skip if this receiver rejects drags from its own children
151
+ if (entry.receptive) {
152
+ if (entry.rejectOwnChildren && i === draggedParentIndex) {
153
+ // This receiver is the parent of the dragged item — skip
154
+ } else {
155
+ receiverId = entry.id;
156
+ }
157
+ }
158
+ } else if (entry.monitoring) {
159
+ // Padded bounds check for monitoring views only (tolerates hover drift during auto-scroll)
160
+ const isPaddedHit =
161
+ position.x >= recLeft - MONITOR_HIT_TEST_PADDING &&
162
+ position.y >= recTop - MONITOR_HIT_TEST_PADDING &&
163
+ position.x < recRight + MONITOR_HIT_TEST_PADDING &&
164
+ position.y < recBottom + MONITOR_HIT_TEST_PADDING;
165
+ if (isPaddedHit) {
166
+ monitorIds.push(entry.id);
167
+ }
168
+ }
169
+ }
170
+
171
+ return { receiverId, monitorIds };
172
+ };
173
+
174
+ // ─── Snap Alignment Helper ──────────────────────────────────────────────
175
+
176
+ /** Named alignment positions for snap targets within a receiver */
177
+ export type SnapAlignment =
178
+ | 'center'
179
+ | 'top-left'
180
+ | 'top-center'
181
+ | 'top-right'
182
+ | 'center-left'
183
+ | 'center-right'
184
+ | 'bottom-left'
185
+ | 'bottom-center'
186
+ | 'bottom-right';
187
+
188
+ /**
189
+ * Compute a snap target position that aligns a dragged view within a receiver
190
+ * at the specified alignment point, with an optional pixel offset.
191
+ *
192
+ * Use as the return value from onDragDrop/onReceiveDragDrop/onMonitorDragDrop:
193
+ * ```
194
+ * onReceiveDragDrop={({ dragged, receiver }) =>
195
+ * snapToAlignment(receiver.measurements, dragged.measurements, 'top-left', { x: 8, y: 8 })
196
+ * }
197
+ * ```
198
+ */
199
+ export const snapToAlignment = (
200
+ receiver: { x: number; y: number; width: number; height: number },
201
+ dragged: { width: number; height: number } | undefined,
202
+ alignment: SnapAlignment = 'center',
203
+ offset: Position = { x: 0, y: 0 }
204
+ ): Position => {
205
+ const dw = dragged?.width ?? 0;
206
+ const dh = dragged?.height ?? 0;
207
+
208
+ let x: number;
209
+ let y: number;
210
+
211
+ switch (alignment) {
212
+ case 'top-left':
213
+ x = receiver.x;
214
+ y = receiver.y;
215
+ break;
216
+ case 'top-center':
217
+ x = receiver.x + (receiver.width - dw) / 2;
218
+ y = receiver.y;
219
+ break;
220
+ case 'top-right':
221
+ x = receiver.x + receiver.width - dw;
222
+ y = receiver.y;
223
+ break;
224
+ case 'center-left':
225
+ x = receiver.x;
226
+ y = receiver.y + (receiver.height - dh) / 2;
227
+ break;
228
+ case 'center':
229
+ x = receiver.x + (receiver.width - dw) / 2;
230
+ y = receiver.y + (receiver.height - dh) / 2;
231
+ break;
232
+ case 'center-right':
233
+ x = receiver.x + receiver.width - dw;
234
+ y = receiver.y + (receiver.height - dh) / 2;
235
+ break;
236
+ case 'bottom-left':
237
+ x = receiver.x;
238
+ y = receiver.y + receiver.height - dh;
239
+ break;
240
+ case 'bottom-center':
241
+ x = receiver.x + (receiver.width - dw) / 2;
242
+ y = receiver.y + receiver.height - dh;
243
+ break;
244
+ case 'bottom-right':
245
+ x = receiver.x + receiver.width - dw;
246
+ y = receiver.y + receiver.height - dh;
247
+ break;
248
+ }
249
+
250
+ return { x: x + offset.x, y: y + offset.y };
251
+ };
package/src/params.ts ADDED
@@ -0,0 +1,74 @@
1
+ /** Default snapback delay in milliseconds */
2
+ export const defaultSnapbackDelay = 100;
3
+
4
+ /** Default snapback duration in milliseconds */
5
+ export const defaultSnapbackDuration = 250;
6
+
7
+ /** Default pre-drag long press delay in milliseconds */
8
+ export const defaultLongPressDelay = 0;
9
+
10
+ /** Default pre-drag long press delay in milliseconds for DraxList items */
11
+ export const defaultListItemLongPressDelay = 250;
12
+
13
+ /** Default scroll event throttle (number of events per second) for DraxScrollView */
14
+ export const defaultScrollEventThrottle = 8;
15
+
16
+ /** Default interval length in milliseconds for auto-scrolling jumps */
17
+ export const defaultAutoScrollIntervalLength = 250;
18
+
19
+ /** Default auto-scroll jump distance, as a fraction relative to content width/length */
20
+ export const defaultAutoScrollJumpRatio = 0.2;
21
+
22
+ /** Default drag-over maximum position threshold for auto-scroll back, as a fraction relative to content width/length */
23
+ export const defaultAutoScrollBackThreshold = 0.1;
24
+
25
+ /** Default drag-over minimum position threshold for auto-scroll forward, as a fraction relative to content width/length */
26
+ export const defaultAutoScrollForwardThreshold = 0.9;
27
+
28
+ /** Duration in milliseconds for list item shift/reorder animations */
29
+ export const ITEM_SHIFT_ANIMATION_DURATION = 200;
30
+
31
+ /** Resolved animation configuration for sortable item shifts */
32
+ export interface ResolvedAnimationConfig {
33
+ useSpring: boolean;
34
+ shiftDuration: number;
35
+ springDamping: number;
36
+ springStiffness: number;
37
+ springMass: number;
38
+ }
39
+
40
+ // Frozen preset singletons — avoids object allocation on every call.
41
+ const PRESET_DEFAULT: ResolvedAnimationConfig = Object.freeze({
42
+ useSpring: false, shiftDuration: 200, springDamping: 15, springStiffness: 150, springMass: 1,
43
+ });
44
+ const PRESET_SPRING: ResolvedAnimationConfig = Object.freeze({
45
+ useSpring: true, shiftDuration: 200, springDamping: 15, springStiffness: 150, springMass: 1,
46
+ });
47
+ const PRESET_GENTLE: ResolvedAnimationConfig = Object.freeze({
48
+ useSpring: true, shiftDuration: 200, springDamping: 20, springStiffness: 100, springMass: 1.2,
49
+ });
50
+ const PRESET_SNAPPY: ResolvedAnimationConfig = Object.freeze({
51
+ useSpring: true, shiftDuration: 200, springDamping: 20, springStiffness: 300, springMass: 0.8,
52
+ });
53
+ const PRESET_NONE: ResolvedAnimationConfig = Object.freeze({
54
+ useSpring: false, shiftDuration: 0, springDamping: 15, springStiffness: 150, springMass: 1,
55
+ });
56
+
57
+ /** Resolve a SortableAnimationConfig (preset or custom) to concrete values */
58
+ export function resolveAnimationConfig(
59
+ config: import('./types').SortableAnimationConfig | undefined
60
+ ): ResolvedAnimationConfig {
61
+ if (!config || config === 'default') return PRESET_DEFAULT;
62
+ if (config === 'spring') return PRESET_SPRING;
63
+ if (config === 'gentle') return PRESET_GENTLE;
64
+ if (config === 'snappy') return PRESET_SNAPPY;
65
+ if (config === 'none') return PRESET_NONE;
66
+ // Custom config — only case that allocates
67
+ return {
68
+ useSpring: config.useSpring ?? false,
69
+ shiftDuration: config.shiftDuration ?? 200,
70
+ springDamping: config.springDamping ?? 15,
71
+ springStiffness: config.springStiffness ?? 150,
72
+ springMass: config.springMass ?? 1,
73
+ };
74
+ }