@applicaster/zapp-react-native-utils 15.0.0-rc.12 → 15.0.0-rc.121

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 (159) hide show
  1. package/README.md +0 -6
  2. package/actionsExecutor/ActionExecutorContext.tsx +3 -6
  3. package/actionsExecutor/feedDecorator.ts +6 -6
  4. package/adsUtils/__tests__/createVMAP.test.ts +419 -0
  5. package/adsUtils/index.ts +2 -2
  6. package/analyticsUtils/README.md +1 -1
  7. package/analyticsUtils/analyticsMapper.ts +10 -2
  8. package/appDataUtils/__tests__/urlScheme.test.ts +678 -0
  9. package/appUtils/HooksManager/__tests__/__snapshots__/hooksManager.test.js.snap +0 -188
  10. package/appUtils/HooksManager/__tests__/hooksManager.test.js +16 -2
  11. package/appUtils/HooksManager/index.ts +10 -10
  12. package/appUtils/RiverFocusManager/{index.js → index.ts} +25 -18
  13. package/appUtils/accessibilityManager/__tests__/utils.test.ts +360 -0
  14. package/appUtils/accessibilityManager/const.ts +4 -0
  15. package/appUtils/accessibilityManager/hooks.ts +20 -13
  16. package/appUtils/accessibilityManager/index.ts +28 -1
  17. package/appUtils/accessibilityManager/utils.ts +59 -8
  18. package/appUtils/contextKeysManager/__tests__/getKeys/failure.test.ts +7 -2
  19. package/appUtils/contextKeysManager/__tests__/getKeys/success.test.ts +48 -0
  20. package/appUtils/contextKeysManager/contextResolver.ts +51 -22
  21. package/appUtils/contextKeysManager/index.ts +65 -10
  22. package/appUtils/focusManager/__tests__/__snapshots__/focusManager.test.js.snap +4 -0
  23. package/appUtils/focusManager/index.ios.ts +59 -3
  24. package/appUtils/focusManager/treeDataStructure/Tree/__tests__/Tree.test.js +46 -0
  25. package/appUtils/focusManager/treeDataStructure/Tree/index.js +18 -18
  26. package/appUtils/focusManagerAux/utils/index.ios.ts +122 -0
  27. package/appUtils/focusManagerAux/utils/index.ts +21 -5
  28. package/appUtils/focusManagerAux/utils/utils.ios.ts +234 -0
  29. package/appUtils/keyCodes/keys/keys.web.ts +1 -4
  30. package/appUtils/localizationsHelper.ts +4 -0
  31. package/appUtils/orientationHelper.ts +2 -4
  32. package/appUtils/platform/platformUtils.ts +117 -18
  33. package/appUtils/playerManager/OverlayObserver/OverlaysObserver.ts +94 -4
  34. package/appUtils/playerManager/OverlayObserver/utils.ts +32 -20
  35. package/appUtils/playerManager/player.ts +4 -0
  36. package/appUtils/playerManager/playerNative.ts +31 -17
  37. package/appUtils/playerManager/usePlayerState.tsx +14 -2
  38. package/arrayUtils/__tests__/allTruthy.test.ts +24 -0
  39. package/arrayUtils/__tests__/anyThruthy.test.ts +24 -0
  40. package/arrayUtils/index.ts +5 -0
  41. package/cellUtils/index.ts +32 -0
  42. package/cloudEventsUtils/__tests__/index.test.ts +529 -0
  43. package/cloudEventsUtils/index.ts +65 -1
  44. package/configurationUtils/__tests__/imageSrcFromMediaItem.test.ts +38 -0
  45. package/configurationUtils/__tests__/manifestKeyParser.test.ts +26 -26
  46. package/configurationUtils/index.ts +17 -11
  47. package/dateUtils/__tests__/dayjs.test.ts +330 -0
  48. package/enumUtils/__tests__/getEnumKeyByEnumValue.test.ts +207 -0
  49. package/errorUtils/__tests__/GeneralError.test.ts +97 -0
  50. package/errorUtils/__tests__/HttpStatusCode.test.ts +344 -0
  51. package/errorUtils/__tests__/MissingPluginError.test.ts +113 -0
  52. package/errorUtils/__tests__/NetworkError.test.ts +202 -0
  53. package/errorUtils/__tests__/getParsedResponse.test.ts +188 -0
  54. package/errorUtils/__tests__/invariant.test.ts +112 -0
  55. package/focusManager/aux/index.ts +1 -1
  56. package/headersUtils/__tests__/headersUtils.test.js +11 -1
  57. package/headersUtils/index.ts +2 -1
  58. package/manifestUtils/defaultManifestConfigurations/player.js +115 -11
  59. package/manifestUtils/keys.js +21 -0
  60. package/manifestUtils/platformIsTV.js +13 -0
  61. package/manifestUtils/sharedConfiguration/screenPicker/utils.js +1 -0
  62. package/manifestUtils/tvAction/container/index.js +1 -1
  63. package/navigationUtils/index.ts +15 -5
  64. package/numberUtils/__tests__/toNumber.test.ts +27 -0
  65. package/numberUtils/__tests__/toPositiveNumber.test.ts +193 -0
  66. package/numberUtils/index.ts +23 -1
  67. package/package.json +4 -4
  68. package/playerUtils/usePlayerTTS.ts +8 -3
  69. package/pluginUtils/index.ts +4 -0
  70. package/reactHooks/advertising/index.ts +2 -2
  71. package/reactHooks/analytics/__tests__/useSendAnalyticsOnPress.test.ts +537 -0
  72. package/reactHooks/app/__tests__/useAppState.test.ts +1 -1
  73. package/reactHooks/autoscrolling/__tests__/useTrackCurrentAutoScrollingElement.test.ts +1 -1
  74. package/reactHooks/autoscrolling/__tests__/useTrackedView.test.tsx +1 -2
  75. package/reactHooks/cell-click/__tests__/index.test.js +1 -3
  76. package/reactHooks/configuration/__tests__/index.test.tsx +1 -1
  77. package/reactHooks/connection/__tests__/index.test.js +1 -1
  78. package/reactHooks/debugging/__tests__/index.test.js +4 -4
  79. package/reactHooks/dev/__tests__/useReRenderLog.test.ts +188 -0
  80. package/reactHooks/device/useIsTablet.tsx +14 -19
  81. package/reactHooks/device/useMemoizedIsTablet.ts +3 -3
  82. package/reactHooks/events/index.ts +20 -0
  83. package/reactHooks/feed/__tests__/useBatchLoading.test.tsx +32 -23
  84. package/reactHooks/feed/__tests__/useBuildPipesUrl.test.tsx +19 -19
  85. package/reactHooks/feed/__tests__/useEntryScreenId.test.tsx +4 -1
  86. package/reactHooks/feed/__tests__/useFeedLoader.test.tsx +42 -30
  87. package/reactHooks/feed/__tests__/{useInflatedUrl.test.ts → useInflatedUrl.test.tsx} +62 -7
  88. package/reactHooks/feed/index.ts +0 -2
  89. package/reactHooks/feed/useBatchLoading.ts +7 -1
  90. package/reactHooks/feed/useEntryScreenId.ts +2 -2
  91. package/reactHooks/feed/useInflatedUrl.ts +44 -18
  92. package/reactHooks/feed/usePipesCacheReset.ts +3 -1
  93. package/reactHooks/flatList/useLoadNextPageIfNeeded.ts +13 -16
  94. package/reactHooks/hookModal/hooks/useHookModalScreenData.ts +12 -8
  95. package/reactHooks/index.ts +2 -0
  96. package/reactHooks/layout/__tests__/index.test.tsx +1 -1
  97. package/reactHooks/layout/__tests__/useLayoutVersion.test.tsx +1 -1
  98. package/reactHooks/layout/index.ts +1 -1
  99. package/reactHooks/layout/useDimensions/__tests__/{useDimensions.test.ts → useDimensions.test.tsx} +105 -25
  100. package/reactHooks/layout/useDimensions/useDimensions.ts +2 -2
  101. package/reactHooks/navigation/__tests__/index.test.tsx +40 -9
  102. package/reactHooks/navigation/index.ts +27 -11
  103. package/reactHooks/navigation/useRoute.ts +11 -7
  104. package/reactHooks/player/TVSeekControlller/TVSeekController.ts +27 -10
  105. package/reactHooks/player/__tests__/useAutoSeek._test.tsx +1 -1
  106. package/reactHooks/player/__tests__/useTapSeek._test.ts +1 -1
  107. package/reactHooks/resolvers/__tests__/useCellResolver.test.tsx +1 -1
  108. package/reactHooks/resolvers/__tests__/useComponentResolver.test.tsx +1 -1
  109. package/reactHooks/resolvers/useCellResolver.ts +6 -2
  110. package/reactHooks/resolvers/useComponentResolver.ts +19 -3
  111. package/reactHooks/screen/__tests__/useCurrentScreenData.test.tsx +2 -2
  112. package/reactHooks/screen/__tests__/useScreenBackgroundColor.test.tsx +1 -1
  113. package/reactHooks/screen/__tests__/useScreenData.test.tsx +1 -1
  114. package/reactHooks/screen/__tests__/useTargetScreenData.test.tsx +12 -4
  115. package/reactHooks/screen/useTargetScreenData.ts +4 -2
  116. package/reactHooks/state/__tests__/useComponentScreenState.test.ts +246 -0
  117. package/reactHooks/state/index.ts +2 -0
  118. package/reactHooks/state/useComponentScreenState.ts +45 -0
  119. package/reactHooks/state/useRefWithInitialValue.ts +10 -0
  120. package/reactHooks/state/useRivers.ts +1 -1
  121. package/reactHooks/ui/__tests__/useFadeOutWhenBlurred.test.ts +580 -0
  122. package/reactHooks/usePluginConfiguration.ts +2 -2
  123. package/reactHooks/utils/__tests__/index.test.js +1 -1
  124. package/rectUtils/__tests__/index.test.ts +549 -0
  125. package/rectUtils/index.ts +2 -2
  126. package/refreshUtils/RefreshCoordinator/__tests__/refreshCoordinator.test.ts +161 -0
  127. package/refreshUtils/RefreshCoordinator/index.ts +216 -0
  128. package/refreshUtils/RefreshCoordinator/utils/__tests__/getDataRefreshConfig.test.ts +104 -0
  129. package/refreshUtils/RefreshCoordinator/utils/index.ts +29 -0
  130. package/screenPickerUtils/__tests__/index.test.ts +333 -0
  131. package/screenPickerUtils/index.ts +5 -0
  132. package/screenState/__tests__/index.test.ts +1 -1
  133. package/screenUtils/index.ts +3 -0
  134. package/searchUtils/const.ts +7 -0
  135. package/searchUtils/index.ts +3 -0
  136. package/services/storageServiceSync.web.ts +1 -1
  137. package/stringUtils/index.ts +1 -1
  138. package/testUtils/index.tsx +30 -21
  139. package/time/__tests__/BackgroundTimer.test.ts +156 -0
  140. package/time/__tests__/Timer.test.ts +236 -0
  141. package/typeGuards/__tests__/isString.test.ts +21 -0
  142. package/typeGuards/index.ts +4 -0
  143. package/utils/__tests__/clone.test.ts +158 -0
  144. package/utils/__tests__/mapAccum.test.ts +73 -0
  145. package/utils/__tests__/mergeRight.test.ts +48 -0
  146. package/utils/__tests__/path.test.ts +7 -0
  147. package/utils/__tests__/selectors.test.ts +124 -0
  148. package/utils/clone.ts +7 -0
  149. package/utils/index.ts +22 -1
  150. package/utils/mapAccum.ts +23 -0
  151. package/utils/mergeRight.ts +5 -0
  152. package/utils/path.ts +6 -3
  153. package/utils/pathOr.ts +5 -1
  154. package/utils/selectors.ts +46 -0
  155. package/zappFrameworkUtils/HookCallback/callbackNavigationAction.ts +49 -12
  156. package/zappFrameworkUtils/HookCallback/hookCallbackManifestExtensions.config.js +1 -1
  157. package/reactHooks/componentsMap/index.ts +0 -55
  158. package/reactHooks/feed/__tests__/useFeedRefresh.test.tsx +0 -75
  159. package/reactHooks/feed/useFeedRefresh.tsx +0 -65
@@ -0,0 +1,549 @@
1
+ import {
2
+ measureDimensionalIntersection,
3
+ measureVerticalIntersection,
4
+ measureHorizontalIntersection,
5
+ measureDistance,
6
+ measureEuclidianDistanceToCenter,
7
+ isOnDirection,
8
+ } from "../index";
9
+
10
+ describe("rectUtils", () => {
11
+ describe("measureVerticalIntersection", () => {
12
+ it("should return 0 when rectangles don't overlap vertically", () => {
13
+ const current = { top: 0, bottom: 100, left: 0, right: 100 };
14
+ const target = { top: 150, bottom: 250, left: 0, right: 100 };
15
+
16
+ expect(measureVerticalIntersection(current, target)).toBe(0);
17
+ });
18
+
19
+ it("should return 0 when target is above current", () => {
20
+ const current = { top: 100, bottom: 200, left: 0, right: 100 };
21
+ const target = { top: 0, bottom: 50, left: 0, right: 100 };
22
+
23
+ expect(measureVerticalIntersection(current, target)).toBe(0);
24
+ });
25
+
26
+ it("should measure partial vertical overlap", () => {
27
+ const current = { top: 0, bottom: 100, left: 0, right: 100 };
28
+ const target = { top: 50, bottom: 150, left: 0, right: 100 };
29
+
30
+ expect(measureVerticalIntersection(current, target)).toBe(50);
31
+ });
32
+
33
+ it("should measure full vertical overlap when target inside current", () => {
34
+ const current = { top: 0, bottom: 200, left: 0, right: 100 };
35
+ const target = { top: 50, bottom: 150, left: 0, right: 100 };
36
+
37
+ expect(measureVerticalIntersection(current, target)).toBe(100);
38
+ });
39
+
40
+ it("should measure full vertical overlap when current inside target", () => {
41
+ const current = { top: 50, bottom: 150, left: 0, right: 100 };
42
+ const target = { top: 0, bottom: 200, left: 0, right: 100 };
43
+
44
+ expect(measureVerticalIntersection(current, target)).toBe(100);
45
+ });
46
+
47
+ it("should handle exact vertical alignment", () => {
48
+ const current = { top: 0, bottom: 100, left: 0, right: 100 };
49
+ const target = { top: 0, bottom: 100, left: 100, right: 200 };
50
+
51
+ expect(measureVerticalIntersection(current, target)).toBe(100);
52
+ });
53
+
54
+ it("should handle touching edges", () => {
55
+ const current = { top: 0, bottom: 100, left: 0, right: 100 };
56
+ const target = { top: 100, bottom: 200, left: 0, right: 100 };
57
+
58
+ expect(measureVerticalIntersection(current, target)).toBe(0);
59
+ });
60
+ });
61
+
62
+ describe("measureHorizontalIntersection", () => {
63
+ it("should return 0 when rectangles don't overlap horizontally", () => {
64
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
65
+ const target = { left: 150, right: 250, top: 0, bottom: 100 };
66
+
67
+ expect(measureHorizontalIntersection(current, target)).toBe(0);
68
+ });
69
+
70
+ it("should return 0 when target is to the left of current", () => {
71
+ const current = { left: 100, right: 200, top: 0, bottom: 100 };
72
+ const target = { left: 0, right: 50, top: 0, bottom: 100 };
73
+
74
+ expect(measureHorizontalIntersection(current, target)).toBe(0);
75
+ });
76
+
77
+ it("should measure partial horizontal overlap", () => {
78
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
79
+ const target = { left: 50, right: 150, top: 0, bottom: 100 };
80
+
81
+ expect(measureHorizontalIntersection(current, target)).toBe(50);
82
+ });
83
+
84
+ it("should measure full horizontal overlap when target inside current", () => {
85
+ const current = { left: 0, right: 200, top: 0, bottom: 100 };
86
+ const target = { left: 50, right: 150, top: 0, bottom: 100 };
87
+
88
+ expect(measureHorizontalIntersection(current, target)).toBe(100);
89
+ });
90
+
91
+ it("should measure full horizontal overlap when current inside target", () => {
92
+ const current = { left: 50, right: 150, top: 0, bottom: 100 };
93
+ const target = { left: 0, right: 200, top: 0, bottom: 100 };
94
+
95
+ expect(measureHorizontalIntersection(current, target)).toBe(100);
96
+ });
97
+
98
+ it("should handle exact horizontal alignment", () => {
99
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
100
+ const target = { left: 0, right: 100, top: 100, bottom: 200 };
101
+
102
+ expect(measureHorizontalIntersection(current, target)).toBe(100);
103
+ });
104
+
105
+ it("should handle touching edges", () => {
106
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
107
+ const target = { left: 100, right: 200, top: 0, bottom: 100 };
108
+
109
+ expect(measureHorizontalIntersection(current, target)).toBe(0);
110
+ });
111
+ });
112
+
113
+ describe("measureDimensionalIntersection", () => {
114
+ it("should call measureVerticalIntersection for horizontal direction", () => {
115
+ const current = { top: 0, bottom: 100, left: 0, right: 100 };
116
+ const target = { top: 50, bottom: 150, left: 0, right: 100 };
117
+ const direction = { isHorizontal: true };
118
+
119
+ const result = measureDimensionalIntersection(direction, current, target);
120
+
121
+ expect(result).toBe(50);
122
+ });
123
+
124
+ it("should call measureHorizontalIntersection for vertical direction", () => {
125
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
126
+ const target = { left: 50, right: 150, top: 0, bottom: 100 };
127
+ const direction = { isHorizontal: false };
128
+
129
+ const result = measureDimensionalIntersection(direction, current, target);
130
+
131
+ expect(result).toBe(50);
132
+ });
133
+
134
+ it("should handle no intersection for horizontal movement", () => {
135
+ const current = { top: 0, bottom: 100, left: 0, right: 100 };
136
+ const target = { top: 200, bottom: 300, left: 0, right: 100 };
137
+ const direction = { isHorizontal: true };
138
+
139
+ const result = measureDimensionalIntersection(direction, current, target);
140
+
141
+ expect(result).toBe(0);
142
+ });
143
+
144
+ it("should handle no intersection for vertical movement", () => {
145
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
146
+ const target = { left: 200, right: 300, top: 0, bottom: 100 };
147
+ const direction = { isHorizontal: false };
148
+
149
+ const result = measureDimensionalIntersection(direction, current, target);
150
+
151
+ expect(result).toBe(0);
152
+ });
153
+ });
154
+
155
+ describe("measureDistance", () => {
156
+ describe("right direction", () => {
157
+ it("should return positive distance when target is to the right", () => {
158
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
159
+ const target = { left: 150, right: 250, top: 0, bottom: 100 };
160
+ const direction = { value: "right" };
161
+
162
+ const result = measureDistance(direction, current, target);
163
+
164
+ expect(result).toBe(50);
165
+ });
166
+
167
+ it("should return negative distance when target is to the left", () => {
168
+ const current = { left: 100, right: 200, top: 0, bottom: 100 };
169
+ const target = { left: 0, right: 50, top: 0, bottom: 100 };
170
+ const direction = { value: "right" };
171
+
172
+ const result = measureDistance(direction, current, target);
173
+
174
+ // Formula: -1 * (current.right - target.left) = -1 * (200 - 0) = -200
175
+ expect(result).toBe(-200);
176
+ });
177
+
178
+ it("should return 0 when target touches current", () => {
179
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
180
+ const target = { left: 100, right: 200, top: 0, bottom: 100 };
181
+ const direction = { value: "right" };
182
+
183
+ const result = Number(measureDistance(direction, current, target));
184
+
185
+ // Formula: -1 * (100 - 100) = -0 (signed zero)
186
+ expect(Math.abs(result)).toBe(0);
187
+ });
188
+ });
189
+
190
+ describe("left direction", () => {
191
+ it("should return positive distance when target is to the left", () => {
192
+ const current = { left: 100, right: 200, top: 0, bottom: 100 };
193
+ const target = { left: 0, right: 50, top: 0, bottom: 100 };
194
+ const direction = { value: "left" };
195
+
196
+ const result = measureDistance(direction, current, target);
197
+
198
+ expect(result).toBe(50);
199
+ });
200
+
201
+ it("should return negative distance when target is to the right", () => {
202
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
203
+ const target = { left: 150, right: 250, top: 0, bottom: 100 };
204
+ const direction = { value: "left" };
205
+
206
+ const result = measureDistance(direction, current, target);
207
+
208
+ // Formula: current.left - target.right = 0 - 250 = -250
209
+ expect(result).toBe(-250);
210
+ });
211
+
212
+ it("should return 0 when target touches current", () => {
213
+ const current = { left: 100, right: 200, top: 0, bottom: 100 };
214
+ const target = { left: 0, right: 100, top: 0, bottom: 100 };
215
+ const direction = { value: "left" };
216
+
217
+ const result = measureDistance(direction, current, target);
218
+
219
+ expect(result).toBe(0);
220
+ });
221
+ });
222
+
223
+ describe("up direction", () => {
224
+ it("should return positive distance when target is above", () => {
225
+ const current = { left: 0, right: 100, top: 100, bottom: 200 };
226
+
227
+ const target = {
228
+ left: 0,
229
+ right: 100,
230
+ top: 0,
231
+ bottom: 50,
232
+ x: 0,
233
+ width: 100,
234
+ };
235
+
236
+ const direction = { value: "up" };
237
+
238
+ const result = measureDistance(direction, current, target);
239
+
240
+ expect(result).toBe(50);
241
+ });
242
+
243
+ it("should return negative distance when target is below", () => {
244
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
245
+
246
+ const target = {
247
+ left: 0,
248
+ right: 100,
249
+ top: 150,
250
+ bottom: 250,
251
+ x: 0,
252
+ width: 100,
253
+ };
254
+
255
+ const direction = { value: "up" };
256
+
257
+ const result = measureDistance(direction, current, target);
258
+
259
+ // Formula: current.top - target.bottom = 0 - 250 = -250
260
+ expect(result).toBe(-250);
261
+ });
262
+
263
+ it("should return -10000 when target is offscreen to the left", () => {
264
+ const current = { left: 0, right: 100, top: 100, bottom: 200 };
265
+
266
+ const target = {
267
+ left: -200,
268
+ right: -100,
269
+ top: 0,
270
+ bottom: 50,
271
+ x: -200,
272
+ width: 100,
273
+ };
274
+
275
+ const direction = { value: "up" };
276
+
277
+ const result = measureDistance(direction, current, target);
278
+
279
+ expect(result).toBe(-10000);
280
+ });
281
+
282
+ it("should handle target at x = 0", () => {
283
+ const current = { left: 0, right: 100, top: 100, bottom: 200 };
284
+
285
+ const target = {
286
+ left: 0,
287
+ right: 100,
288
+ top: 0,
289
+ bottom: 50,
290
+ x: 0,
291
+ width: 100,
292
+ };
293
+
294
+ const direction = { value: "up" };
295
+
296
+ const result = measureDistance(direction, current, target);
297
+
298
+ expect(result).toBe(50);
299
+ });
300
+ });
301
+
302
+ describe("down direction", () => {
303
+ it("should return positive distance when target is below", () => {
304
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
305
+ const target = { left: 0, right: 100, top: 150, bottom: 250, x: 0 };
306
+ const direction = { value: "down" };
307
+
308
+ const result = measureDistance(direction, current, target);
309
+
310
+ expect(result).toBe(50);
311
+ });
312
+
313
+ it("should return negative distance when target is above", () => {
314
+ const current = { left: 0, right: 100, top: 100, bottom: 200 };
315
+ const target = { left: 0, right: 100, top: 0, bottom: 50, x: 0 };
316
+ const direction = { value: "down" };
317
+
318
+ const result = measureDistance(direction, current, target);
319
+
320
+ // Formula: -1 * (current.bottom - target.top) = -1 * (200 - 0) = -200
321
+ expect(result).toBe(-200);
322
+ });
323
+
324
+ it("should return -10000 when target is offscreen to the right", () => {
325
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
326
+
327
+ const target = {
328
+ left: 2000,
329
+ right: 2100,
330
+ top: 150,
331
+ bottom: 250,
332
+ x: 2000,
333
+ };
334
+
335
+ const direction = { value: "down" };
336
+
337
+ const result = measureDistance(direction, current, target);
338
+
339
+ expect(result).toBe(-10000);
340
+ });
341
+
342
+ it("should handle target at x = 1920", () => {
343
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
344
+
345
+ const target = {
346
+ left: 1920,
347
+ right: 2020,
348
+ top: 150,
349
+ bottom: 250,
350
+ x: 1920,
351
+ };
352
+
353
+ const direction = { value: "down" };
354
+
355
+ const result = measureDistance(direction, current, target);
356
+
357
+ expect(result).toBe(50);
358
+ });
359
+ });
360
+ });
361
+
362
+ describe("measureEuclidianDistanceToCenter", () => {
363
+ it("should calculate distance between centers", () => {
364
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
365
+ const target = { left: 300, right: 400, top: 400, bottom: 500 };
366
+
367
+ const result = measureEuclidianDistanceToCenter(current, target);
368
+
369
+ // Current center: (50, 50)
370
+ // Target center: (350, 450)
371
+ // Distance: sqrt((350-50)^2 + (450-50)^2) = sqrt(90000 + 160000) = sqrt(250000) = 500
372
+ expect(result).toBe(500);
373
+ });
374
+
375
+ it("should return 0 for same rectangle", () => {
376
+ const rect = { left: 0, right: 100, top: 0, bottom: 100 };
377
+
378
+ const result = measureEuclidianDistanceToCenter(rect, rect);
379
+
380
+ expect(result).toBe(0);
381
+ });
382
+
383
+ it("should calculate distance for adjacent rectangles", () => {
384
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
385
+ const target = { left: 100, right: 200, top: 0, bottom: 100 };
386
+
387
+ const result = measureEuclidianDistanceToCenter(current, target);
388
+
389
+ // Current center: (50, 50)
390
+ // Target center: (150, 50)
391
+ // Distance: sqrt((150-50)^2 + (50-50)^2) = sqrt(10000) = 100
392
+ expect(result).toBe(100);
393
+ });
394
+
395
+ it("should calculate distance for vertical separation", () => {
396
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
397
+ const target = { left: 0, right: 100, top: 100, bottom: 200 };
398
+
399
+ const result = measureEuclidianDistanceToCenter(current, target);
400
+
401
+ // Current center: (50, 50)
402
+ // Target center: (50, 150)
403
+ // Distance: sqrt((50-50)^2 + (150-50)^2) = sqrt(10000) = 100
404
+ expect(result).toBe(100);
405
+ });
406
+
407
+ it("should calculate distance for diagonal separation", () => {
408
+ const current = { left: 0, right: 60, top: 0, bottom: 80 };
409
+ const target = { left: 60, right: 120, top: 80, bottom: 160 };
410
+
411
+ const result = measureEuclidianDistanceToCenter(current, target);
412
+
413
+ // Current center: (30, 40)
414
+ // Target center: (90, 120)
415
+ // Distance: sqrt((90-30)^2 + (120-40)^2) = sqrt(3600 + 6400) = sqrt(10000) = 100
416
+ expect(result).toBe(100);
417
+ });
418
+
419
+ it("should handle rectangles with different sizes", () => {
420
+ const current = { left: 0, right: 50, top: 0, bottom: 50 };
421
+ const target = { left: 100, right: 300, top: 100, bottom: 300 };
422
+
423
+ const result = measureEuclidianDistanceToCenter(current, target);
424
+
425
+ // Current center: (25, 25)
426
+ // Target center: (200, 200)
427
+ // Distance: sqrt((200-25)^2 + (200-25)^2) = sqrt(175^2 + 175^2) = sqrt(61250) ≈ 247.49
428
+ expect(result).toBeCloseTo(247.49, 1);
429
+ });
430
+ });
431
+
432
+ describe("isOnDirection", () => {
433
+ describe("horizontal directions", () => {
434
+ it("should return true when target is to the right", () => {
435
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
436
+ const target = { left: 150, right: 250, top: 0, bottom: 100 };
437
+ const direction = { value: "right", isHorizontal: true };
438
+
439
+ const result = isOnDirection(direction, current, target);
440
+
441
+ expect(result).toBe(true);
442
+ });
443
+
444
+ it("should return false when target is to the left but direction is right", () => {
445
+ const current = { left: 100, right: 200, top: 0, bottom: 100 };
446
+ const target = { left: 0, right: 50, top: 0, bottom: 100 };
447
+ const direction = { value: "right", isHorizontal: true };
448
+
449
+ const result = isOnDirection(direction, current, target);
450
+
451
+ expect(result).toBe(false);
452
+ });
453
+
454
+ it("should return true when target is to the left", () => {
455
+ const current = { left: 100, right: 200, top: 0, bottom: 100 };
456
+ const target = { left: 0, right: 50, top: 0, bottom: 100 };
457
+ const direction = { value: "left", isHorizontal: true };
458
+
459
+ const result = isOnDirection(direction, current, target);
460
+
461
+ expect(result).toBe(true);
462
+ });
463
+
464
+ it("should return false when target is to the right but direction is left", () => {
465
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
466
+ const target = { left: 150, right: 250, top: 0, bottom: 100 };
467
+ const direction = { value: "left", isHorizontal: true };
468
+
469
+ const result = isOnDirection(direction, current, target);
470
+
471
+ expect(result).toBe(false);
472
+ });
473
+ });
474
+
475
+ describe("vertical directions", () => {
476
+ it("should return true when target is above", () => {
477
+ const current = { left: 0, right: 100, top: 100, bottom: 200 };
478
+ const target = { left: 0, right: 100, top: 0, bottom: 50 };
479
+ const direction = { value: "up", isVertical: true };
480
+
481
+ const result = isOnDirection(direction, current, target);
482
+
483
+ expect(result).toBe(true);
484
+ });
485
+
486
+ it("should return false when target is below but direction is up", () => {
487
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
488
+ const target = { left: 0, right: 100, top: 150, bottom: 250 };
489
+ const direction = { value: "up", isVertical: true };
490
+
491
+ const result = isOnDirection(direction, current, target);
492
+
493
+ expect(result).toBe(false);
494
+ });
495
+
496
+ it("should return true when target is below", () => {
497
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
498
+ const target = { left: 0, right: 100, top: 150, bottom: 250 };
499
+ const direction = { value: "down", isVertical: true };
500
+
501
+ const result = isOnDirection(direction, current, target);
502
+
503
+ expect(result).toBe(true);
504
+ });
505
+
506
+ it("should return false when target is above but direction is down", () => {
507
+ const current = { left: 0, right: 100, top: 100, bottom: 200 };
508
+ const target = { left: 0, right: 100, top: 0, bottom: 50 };
509
+ const direction = { value: "down", isVertical: true };
510
+
511
+ const result = isOnDirection(direction, current, target);
512
+
513
+ expect(result).toBe(false);
514
+ });
515
+ });
516
+
517
+ describe("edge cases", () => {
518
+ it("should handle aligned centers", () => {
519
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
520
+ const target = { left: 100, right: 200, top: 0, bottom: 100 };
521
+ const direction = { value: "right", isHorizontal: true };
522
+
523
+ const result = isOnDirection(direction, current, target);
524
+
525
+ expect(result).toBe(true);
526
+ });
527
+
528
+ it("should handle overlapping rectangles", () => {
529
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
530
+ const target = { left: 50, right: 150, top: 50, bottom: 150 };
531
+ const direction = { value: "right", isHorizontal: true };
532
+
533
+ const result = isOnDirection(direction, current, target);
534
+
535
+ expect(result).toBe(true);
536
+ });
537
+
538
+ it("should return undefined for invalid direction", () => {
539
+ const current = { left: 0, right: 100, top: 0, bottom: 100 };
540
+ const target = { left: 150, right: 250, top: 0, bottom: 100 };
541
+ const direction = { value: "right" }; // No isHorizontal or isVertical
542
+
543
+ const result = isOnDirection(direction, current, target);
544
+
545
+ expect(result).toBeUndefined();
546
+ });
547
+ });
548
+ });
549
+ });
@@ -9,7 +9,7 @@
9
9
  */
10
10
  export function measureDimensionalIntersection(direction, current, target) {
11
11
  if (direction.isHorizontal) {
12
- return measureVerticalIntersectiont(current, target);
12
+ return measureVerticalIntersection(current, target);
13
13
  } else {
14
14
  return measureHorizontalIntersection(current, target);
15
15
  }
@@ -25,7 +25,7 @@ export function measureDimensionalIntersection(direction, current, target) {
25
25
  * @param {Object} target rect object {right, left, top, bottom, x, y, width. height}
26
26
  * @returns {Int} Returns vertical intersection of current and target object
27
27
  */
28
- export function measureVerticalIntersectiont(current, target) {
28
+ export function measureVerticalIntersection(current, target) {
29
29
  if (target.top >= current.bottom || target.bottom <= current.top) {
30
30
  return 0;
31
31
  }