senaev-utils 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 (166) hide show
  1. package/README.md +11 -0
  2. package/package.json +66 -0
  3. package/src/reactHooks/setDeepEqualState.ts +19 -0
  4. package/src/reactHooks/useLocationParameter.ts +46 -0
  5. package/src/reactHooks/useObjectDeepChangesCounter.ts +22 -0
  6. package/src/reactHooks/useObservableMap/useObservableMap.ts +21 -0
  7. package/src/reactHooks/useRecentChangeTimer.ts +42 -0
  8. package/src/reactHooks/useReload.ts +17 -0
  9. package/src/reactHooks/useVisualizedProcessesTree.ts +202 -0
  10. package/src/types/Boolean.ts +9 -0
  11. package/src/types/DeepPartial.ts +1 -0
  12. package/src/types/GlobalContext.ts +8 -0
  13. package/src/types/HexColorString.ts +9 -0
  14. package/src/types/ISOLang.ts +5 -0
  15. package/src/types/IsEqualUnion.ts +1 -0
  16. package/src/types/IterableWithIndexAccess.ts +4 -0
  17. package/src/types/Kilobits.ts +4 -0
  18. package/src/types/Network/Bits.ts +4 -0
  19. package/src/types/Network/Bps.ts +4 -0
  20. package/src/types/Network/Kbps.ts +4 -0
  21. package/src/types/Network/Mbps.ts +4 -0
  22. package/src/types/Number/AngleInDegrees.ts +3 -0
  23. package/src/types/Number/FiniteNumber.ts +11 -0
  24. package/src/types/Number/Integer.ts +14 -0
  25. package/src/types/Number/IntegerInString.ts +13 -0
  26. package/src/types/Number/Number.ts +15 -0
  27. package/src/types/Number/Portion.ts +4 -0
  28. package/src/types/Number/PositiveInteger.ts +30 -0
  29. package/src/types/Number/PositiveNumber.ts +4 -0
  30. package/src/types/Number/StringUnsignedInteger.ts +4 -0
  31. package/src/types/Number/UnsignedFiniteNumber.ts +13 -0
  32. package/src/types/Number/UnsignedInteger.ts +28 -0
  33. package/src/types/Object/Object.ts +20 -0
  34. package/src/types/Percent.ts +4 -0
  35. package/src/types/PixelPosition.ts +9 -0
  36. package/src/types/PixelSize.ts +9 -0
  37. package/src/types/Pixels.ts +4 -0
  38. package/src/types/RangeTuple.ts +1 -0
  39. package/src/types/Size.ts +8 -0
  40. package/src/types/Time/DaysCount.ts +6 -0
  41. package/src/types/Time/Hours.ts +4 -0
  42. package/src/types/Time/ISODateString/ISODateString.ts +16 -0
  43. package/src/types/Time/Milliseconds.ts +4 -0
  44. package/src/types/Time/Minutes.ts +4 -0
  45. package/src/types/Time/Seconds.ts +5 -0
  46. package/src/types/Time/Time.ts +13 -0
  47. package/src/types/Time/Timestamp.ts +6 -0
  48. package/src/types/Time/UnixTimeMs.ts +6 -0
  49. package/src/types/Time/UnixTimeSec.ts +11 -0
  50. package/src/types/Time/const.ts +24 -0
  51. package/src/types/any/AnyAsyncFunction.ts +2 -0
  52. package/src/types/any/AnyFunction.ts +2 -0
  53. package/src/types/assertions/ANY_VALUE.ts +2 -0
  54. package/src/types/assertions/isNever/isNever.ts +34 -0
  55. package/src/types/assertions/isTrue/isTrue.ts +13 -0
  56. package/src/utils/AbortableProcess.ts +160 -0
  57. package/src/utils/Array/createArray/createArray.ts +8 -0
  58. package/src/utils/Array/createIntegerSequenceArray/createIntegerSequenceArray.ts +3 -0
  59. package/src/utils/Array/getUniqueValues/getUniqueValues.ts +3 -0
  60. package/src/utils/Array/separateToArrays/separateToArrays.ts +24 -0
  61. package/src/utils/Array/shuffleArray/shuffleArray.ts +18 -0
  62. package/src/utils/CircularBuffer/CircularBuffer.ts +117 -0
  63. package/src/utils/DOM/blurDocument.ts +3 -0
  64. package/src/utils/DOM/unfocusDocument.ts +3 -0
  65. package/src/utils/Date/dateToUnixTimeSec/dateToUnixTimeSec.ts +6 -0
  66. package/src/utils/Date/isoDateStringToUnixTimeMs/isoDateStringToUnixTimeMs.ts +6 -0
  67. package/src/utils/Date/isoDateStringToUnixTimeSec/isoDateStringToUnixTimeSec.ts +7 -0
  68. package/src/utils/Date/unixTimeSecToIsoDateString/unixTimeSecToIsoDateString.ts +6 -0
  69. package/src/utils/Deque/Deque.ts +530 -0
  70. package/src/utils/DeviceDetection/isTouchScreenDevice/isTouchScreenDevice.ts +16 -0
  71. package/src/utils/Error/rethrowError/rethrowError.ts +8 -0
  72. package/src/utils/Error/wrapError.ts +32 -0
  73. package/src/utils/Function/callFirstThenOther/callFirstThenOther.ts +24 -0
  74. package/src/utils/Function/callFunctions/callFunctions.ts +11 -0
  75. package/src/utils/Function/callTimes/callTimes.ts +5 -0
  76. package/src/utils/Function/isFunction.ts +3 -0
  77. package/src/utils/Function/noop/index.ts +4 -0
  78. package/src/utils/Function/once/once.ts +32 -0
  79. package/src/utils/Function/subscribeUpdatesWithTimeout/index.ts +44 -0
  80. package/src/utils/Function/throttleFunction/throttleFunction.ts +18 -0
  81. package/src/utils/Function/throttleWithPromiseFunction/throttleWithPromiseFunction.ts +19 -0
  82. package/src/utils/Function/tryCatch/tryCatch.ts +13 -0
  83. package/src/utils/Latch/Latch.ts +63 -0
  84. package/src/utils/Map/ObservableMap/ObservableMap.ts +55 -0
  85. package/src/utils/Map/findMapsDifferences/findMapsDifferences.ts +35 -0
  86. package/src/utils/Map/mapGetOrSet/mapGetOrSet.ts +7 -0
  87. package/src/utils/Map/mapMapToArray/mapMapToArray.ts +6 -0
  88. package/src/utils/Map/mapMapValues/mapMapValues.ts +9 -0
  89. package/src/utils/Math/createSimpleMovingAverageSeries/createSimpleMovingAverageSeries.ts +22 -0
  90. package/src/utils/Math/mean/mean.ts +14 -0
  91. package/src/utils/Math/simpleMovingAverageUsingAccFabric/simpleMovingAverageUsingAccFabric.ts +29 -0
  92. package/src/utils/Math/sum/sum.ts +45 -0
  93. package/src/utils/MinHeap/MinHeap.ts +88 -0
  94. package/src/utils/MinHeapUniqueNumber/MinHeapUniqueNumber.ts +105 -0
  95. package/src/utils/MinMaxHeap/MinMaxHeap.ts +91 -0
  96. package/src/utils/Number/collectIntegerSequences/collectIntegerSequences.ts +36 -0
  97. package/src/utils/Number/numberToFixedPrecision/numberToFixedPrecision.ts +13 -0
  98. package/src/utils/Object/cloneObject/cloneObject.ts +3 -0
  99. package/src/utils/Object/deepEqual/deepEqual.ts +45 -0
  100. package/src/utils/Object/deleteUndefinedProperties/index.ts +13 -0
  101. package/src/utils/Object/entriesToObject/entriesToObject.ts +12 -0
  102. package/src/utils/Object/filterObject/filterObject.ts +18 -0
  103. package/src/utils/Object/forOwn/forOwn.ts +12 -0
  104. package/src/utils/Object/getObjectEntries/getObjectEntries.ts +3 -0
  105. package/src/utils/Object/getObjectKeys/getObjectKeys.ts +3 -0
  106. package/src/utils/Object/getObjectValues/index.ts +3 -0
  107. package/src/utils/Object/hasOwnProperty/hasOwnProperty.ts +3 -0
  108. package/src/utils/Object/invertObject/InvertedObject.ts +3 -0
  109. package/src/utils/Object/invertObject/invertObject.ts +15 -0
  110. package/src/utils/Object/isEmptyObject/index.ts +5 -0
  111. package/src/utils/Object/isObject/index.ts +8 -0
  112. package/src/utils/Object/mapObjectKeys/mapObjectKeys.ts +25 -0
  113. package/src/utils/Object/mapObjectValues/mapObjectValues.ts +16 -0
  114. package/src/utils/Object/mirrorObject/ObjectKeysMirror.ts +1 -0
  115. package/src/utils/Object/mirrorObject/mirrorObject.ts +7 -0
  116. package/src/utils/Pagination/DEFAULT_PAGE.ts +1 -0
  117. package/src/utils/Pagination/calculatePaginationParameters.ts +29 -0
  118. package/src/utils/Promise/promiseAll/promiseAll.ts +6 -0
  119. package/src/utils/Promise/restrictParallelCalls/restrictParallelCalls.ts +18 -0
  120. package/src/utils/Ranges/checkRangesAdjacent/checkRangesAdjacent.ts +23 -0
  121. package/src/utils/Ranges/checkRangesIntersection/checkRangesIntersection.ts +8 -0
  122. package/src/utils/Ranges/excludeRanges/excludeRanges.ts +42 -0
  123. package/src/utils/Ranges/getDistanceToRange/getDistanceToRange.ts +14 -0
  124. package/src/utils/Ranges/isRangeWithinRanges.ts +14 -0
  125. package/src/utils/Ranges/mapDateRangeToISODateStringRange/mapDateRangeToISODateStringRange.ts +7 -0
  126. package/src/utils/Ranges/mapISODateStringRangeToUnixTimeMsRange/mapISODateStringRangeToUnixTimeMsRange.ts +8 -0
  127. package/src/utils/Ranges/mapRange/mapRange.ts +13 -0
  128. package/src/utils/Ranges/mapUnixTimeMsRangeToISODateStringRange/mapUnixTimeMsRangeToISODateStringRange.ts +8 -0
  129. package/src/utils/Ranges/mergeRanges/mergeRanges.ts +34 -0
  130. package/src/utils/Signal/Signal.ts +47 -0
  131. package/src/utils/Signal/SignalCallback.ts +1 -0
  132. package/src/utils/Signal/combineSignalsIntoNewOne/combineSignalsIntoNewOne.ts +75 -0
  133. package/src/utils/Signal/subscribeSignalAndCallWithCurrentValue/subscribeSignalAndCallWithCurrentValue.ts +7 -0
  134. package/src/utils/Signal/useSignal.ts +10 -0
  135. package/src/utils/String/HexString/HEX_SYMBOLS.ts +1 -0
  136. package/src/utils/String/HexString/HexString.ts +2 -0
  137. package/src/utils/String/HexString/isHexString.ts +16 -0
  138. package/src/utils/String/NonEmptyString/NonEmptyString.ts +22 -0
  139. package/src/utils/String/endsWith/index.ts +6 -0
  140. package/src/utils/String/isString.ts +3 -0
  141. package/src/utils/binarySearch/binarySearch.ts +20 -0
  142. package/src/utils/binarySearchClosest/binarySearchClosest.ts +43 -0
  143. package/src/utils/createIncrementalIntegerGenerator.ts +7 -0
  144. package/src/utils/createRemoteDataProcessingWindow/createRemoteDataProcessingWindow.ts +157 -0
  145. package/src/utils/createSimultaneousOperationsHandler/createSimultaneousOperationsHandler.ts +65 -0
  146. package/src/utils/encryptDecryptString/encryptDecryptString.ts +34 -0
  147. package/src/utils/getPrimeNumbersWithEratosthenesSieve/getPrimeNumbersWithEratosthenesSieve.ts +21 -0
  148. package/src/utils/isPromise/isPromise.ts +30 -0
  149. package/src/utils/makeAsyncFunctionCallsSimultaneous/makeAsyncFunctionCallsSimultaneous.ts +64 -0
  150. package/src/utils/parallelsLimitPromise/index.ts +28 -0
  151. package/src/utils/parallelsLimitQueue/parallelsLimitQueue.ts +69 -0
  152. package/src/utils/prettyStringify/index.ts +3 -0
  153. package/src/utils/random/fnv1a/fnv1a.ts +87 -0
  154. package/src/utils/random/generateHashedFloats/generateHashedFloats.ts +28 -0
  155. package/src/utils/random/getRandomIntegerInARange/getRandomIntegerInARange.ts +3 -0
  156. package/src/utils/random/getSampleIndexByStringHash/getSampleIndexByStringHash.ts +10 -0
  157. package/src/utils/random/randomBoolean/randomBoolean.ts +3 -0
  158. package/src/utils/random/randomHexString/randomHexString.ts +12 -0
  159. package/src/utils/requestAnimationFrame/requestAnimationFramePromise/requestAnimationFramePromise.ts +7 -0
  160. package/src/utils/requestAnimationFrame/requestAnimationFrameThrottle/requestAnimationFrameThrottle.ts +6 -0
  161. package/src/utils/retryFunctionWrapper/retryFunctionWrapper.ts +40 -0
  162. package/src/utils/runParallelTimescalesProcessing/runParallelTimescalesProcessing.ts +113 -0
  163. package/src/utils/stringifyError.ts +3 -0
  164. package/src/utils/timers/promiseTimeout/promiseTimeout.ts +26 -0
  165. package/src/utils/timers/subscribeSyntheticInterval/subscribeSyntheticInterval.ts +47 -0
  166. package/src/utils/waitForFunction/waitForFunction.ts +50 -0
@@ -0,0 +1,530 @@
1
+ import { IterableWithIndexAccess } from '../../types/IterableWithIndexAccess';
2
+
3
+ function _nextPowerOf2(num: number): number {
4
+ const log2 = Math.log(num) / Math.log(2);
5
+ const nextPow2 = 1 << (log2 + 1);
6
+
7
+ return Math.max(nextPow2, 4);
8
+ }
9
+
10
+ const DEFAULT_CAPACITY = 4;
11
+
12
+ /**
13
+ * Stolen from here
14
+ * https://github.com/invertase/denque/blob/539105bb57854e997dd469221cdc52a0ad80e0a2/index.js#L6
15
+ */
16
+ export class Deque<T> implements IterableWithIndexAccess<T> {
17
+ public readonly _capacity: number | undefined;
18
+ public _head: number;
19
+ public _tail: number;
20
+ public _capacityMask: number;
21
+ public _list: (T | undefined)[];
22
+
23
+ public constructor(array?: T[], options: {
24
+ /**
25
+ * The capacity (maximum amount of elements) of the deque
26
+ */
27
+ capacity?: number;
28
+ } = {}) {
29
+ this._capacity = options.capacity;
30
+
31
+ this._head = 0;
32
+ this._tail = 0;
33
+
34
+ if (Array.isArray(array)) {
35
+ const { length } = array;
36
+ const capacity = _nextPowerOf2(length);
37
+
38
+ this._list = new Array(capacity);
39
+ this._capacityMask = capacity - 1;
40
+ this._tail = length;
41
+
42
+ for (let i = 0; i < length; i++) {
43
+ this._list[i] = array[i];
44
+ }
45
+ } else {
46
+ this._list = new Array(DEFAULT_CAPACITY);
47
+ this._capacityMask = DEFAULT_CAPACITY - 1;
48
+ }
49
+ }
50
+
51
+ public get length(): number {
52
+ if (this._head === this._tail) {
53
+ return 0;
54
+ }
55
+
56
+ if (this._head < this._tail) {
57
+ return this._tail - this._head;
58
+ }
59
+
60
+ return this._capacityMask + 1 - (this._head - this._tail);
61
+ }
62
+
63
+ public *[Symbol.iterator](): Iterator<T> {
64
+ const { length } = this;
65
+
66
+ for (let i = 0; i < length; i++) {
67
+ const item = this.at(i);
68
+
69
+ if (item !== undefined) {
70
+ yield item;
71
+ }
72
+ }
73
+ }
74
+
75
+ /**
76
+ * Returns the item at the specified index from the list.
77
+ * 0 is the first element, 1 is the second, and so on...
78
+ * Elements at negative values are that many from the end: -1 is one before the end
79
+ * (the last element), -2 is two before the end (one before last), etc.
80
+ */
81
+ public at(index: number): T | undefined {
82
+ let i = index;
83
+
84
+ if ((i !== (i | 0))) {
85
+ return undefined;
86
+ }
87
+
88
+ const len = this.length;
89
+
90
+ if (i >= len || i < -len) {
91
+ return undefined;
92
+ }
93
+
94
+ if (i < 0) {
95
+ i += len;
96
+ }
97
+
98
+ i = (this._head + i) & this._capacityMask;
99
+
100
+ return this._list[i];
101
+ }
102
+
103
+ public peek(): T | undefined {
104
+ if (this._head === this._tail) {
105
+ return undefined;
106
+ }
107
+
108
+ return this._list[this._head];
109
+ }
110
+
111
+ public peekBack(): T | undefined {
112
+ return this.at(-1);
113
+ }
114
+
115
+ /**
116
+ * Add an item at the beginning of the list
117
+ * Returns new length of the list
118
+ */
119
+ public unshift(item?: T): number {
120
+ if (arguments.length === 0) {
121
+ return this.length;
122
+ }
123
+
124
+ const len = this._list.length;
125
+
126
+ this._head = (this._head - 1 + len) & this._capacityMask;
127
+ this._list[this._head] = item;
128
+
129
+ if (this._tail === this._head) {
130
+ this._growArray();
131
+ }
132
+
133
+ if (this._capacity && this.length > this._capacity) {
134
+ this.pop();
135
+ }
136
+
137
+ if (this._head < this._tail) {
138
+ return this._tail - this._head;
139
+ }
140
+
141
+ return this._capacityMask + 1 - (this._head - this._tail);
142
+ }
143
+
144
+ public pop(): T | undefined {
145
+ const tail = this._tail;
146
+
147
+ if (tail === this._head) {
148
+ return undefined;
149
+ }
150
+
151
+ const len = this._list.length;
152
+
153
+ this._tail = (tail - 1 + len) & this._capacityMask;
154
+ const item = this._list[this._tail];
155
+
156
+ this._list[this._tail] = undefined;
157
+ if (this._head < 2 && tail > 10000 && tail <= len >>> 2) {
158
+ this._shrinkArray();
159
+ }
160
+
161
+ return item;
162
+ }
163
+
164
+ public shift() {
165
+ const head = this._head;
166
+
167
+ if (head === this._tail) {
168
+ return undefined;
169
+ }
170
+
171
+ const item = this._list[head];
172
+
173
+ this._list[head] = undefined;
174
+ this._head = (head + 1) & this._capacityMask;
175
+ if (head < 2 && this._tail > 10000 && this._tail <= this._list.length >>> 2) {
176
+ this._shrinkArray();
177
+ }
178
+
179
+ return item;
180
+ }
181
+
182
+ /**
183
+ * Add an item to the end of the list
184
+ * Returns new length of the list
185
+ */
186
+ public push(...items: T[]): number {
187
+ if (arguments.length === 0) {
188
+ return this.length;
189
+ }
190
+
191
+ const tail = this._tail;
192
+
193
+ this._list[tail] = items[0];
194
+ this._tail = (tail + 1) & this._capacityMask;
195
+
196
+ if (this._tail === this._head) {
197
+ this._growArray();
198
+ }
199
+
200
+ if (this._capacity && this.length > this._capacity) {
201
+ this.shift();
202
+ }
203
+
204
+ if (this._head < this._tail) {
205
+ return this._tail - this._head;
206
+ }
207
+
208
+ return this._capacityMask + 1 - (this._head - this._tail);
209
+ }
210
+
211
+ public removeOne(index: number): T | undefined {
212
+ let i = index;
213
+
214
+ // expect a number or return undefined
215
+ if ((i !== (i | 0))) {
216
+ return undefined;
217
+ }
218
+
219
+ if (this._head === this._tail) {
220
+ return undefined;
221
+ }
222
+
223
+ const { length } = this;
224
+ const len = this._list.length;
225
+
226
+ if (i >= length || i < -length) {
227
+ return undefined;
228
+ }
229
+
230
+ if (i < 0) {
231
+ i += length;
232
+ }
233
+
234
+ i = (this._head + i) & this._capacityMask;
235
+ const item = this._list[i];
236
+ let k;
237
+
238
+ if (index < length / 2) {
239
+ for (k = index; k > 0; k--) {
240
+ this._list[i] = this._list[i = (i - 1 + len) & this._capacityMask];
241
+ }
242
+
243
+ this._list[i] = undefined;
244
+ this._head = (this._head + 1 + len) & this._capacityMask;
245
+ } else {
246
+ for (k = length - 1 - index; k > 0; k--) {
247
+ this._list[i] = this._list[i = (i + 1 + len) & this._capacityMask];
248
+ }
249
+
250
+ this._list[i] = undefined;
251
+ this._tail = (this._tail - 1 + len) & this._capacityMask;
252
+ }
253
+
254
+ return item;
255
+ }
256
+
257
+ public isEmpty(): boolean {
258
+ return this._head === this._tail;
259
+ }
260
+
261
+ public clear(): void {
262
+ this._list = new Array(this._list.length);
263
+ this._head = 0;
264
+ this._tail = 0;
265
+ }
266
+
267
+ public remove(index: number, count: number): T[] | undefined {
268
+ let i = index;
269
+ let removed;
270
+ let del_count = count;
271
+
272
+ // expect a number or return undefined
273
+ if ((i !== (i | 0))) {
274
+ return undefined;
275
+ }
276
+
277
+ if (this._head === this._tail) {
278
+ return undefined;
279
+ }
280
+
281
+ const { length } = this;
282
+ const len = this._list.length;
283
+
284
+ if (i >= length || i < -length || count < 1) {
285
+ return undefined;
286
+ }
287
+
288
+ if (i < 0) {
289
+ i += length;
290
+ }
291
+
292
+ if (count === 1 || !count) {
293
+ removed = new Array(1);
294
+ removed[0] = this.removeOne(i);
295
+
296
+ return removed;
297
+ }
298
+
299
+ if (i === 0 && i + count >= length) {
300
+ removed = this.toArray();
301
+ this.clear();
302
+
303
+ return removed;
304
+ }
305
+
306
+ if (i + count > length) {
307
+ count = length - i;
308
+ }
309
+
310
+ let k;
311
+
312
+ removed = new Array(count);
313
+ for (k = 0; k < count; k++) {
314
+ removed[k] = this._list[(this._head + i + k) & this._capacityMask];
315
+ }
316
+
317
+ i = (this._head + i) & this._capacityMask;
318
+ if (index + count === length) {
319
+ this._tail = (this._tail - count + len) & this._capacityMask;
320
+ for (k = count; k > 0; k--) {
321
+ this._list[i = (i + 1 + len) & this._capacityMask] = undefined;
322
+ }
323
+
324
+ return removed;
325
+ }
326
+
327
+ if (index === 0) {
328
+ this._head = (this._head + count + len) & this._capacityMask;
329
+ for (k = count - 1; k > 0; k--) {
330
+ this._list[i = (i + 1 + len) & this._capacityMask] = undefined;
331
+ }
332
+
333
+ return removed;
334
+ }
335
+
336
+ if (i < length / 2) {
337
+ this._head = (this._head + index + count + len) & this._capacityMask;
338
+ for (k = index; k > 0; k--) {
339
+ this.unshift(this._list[i = (i - 1 + len) & this._capacityMask]!);
340
+ }
341
+
342
+ i = (this._head - 1 + len) & this._capacityMask;
343
+ while (del_count > 0) {
344
+ this._list[i = (i - 1 + len) & this._capacityMask] = undefined;
345
+ del_count--;
346
+ }
347
+
348
+ if (index < 0) {
349
+ this._tail = i;
350
+ }
351
+ } else {
352
+ this._tail = i;
353
+ i = (i + count + len) & this._capacityMask;
354
+ for (k = length - (count + index); k > 0; k--) {
355
+ this.push(this._list[i++]!);
356
+ }
357
+
358
+ i = this._tail;
359
+ while (del_count > 0) {
360
+ this._list[i = (i + 1 + len) & this._capacityMask] = undefined;
361
+ del_count--;
362
+ }
363
+ }
364
+
365
+ if (this._head < 2 && this._tail > 10000 && this._tail <= len >>> 2) {
366
+ this._shrinkArray();
367
+ }
368
+
369
+ return removed;
370
+ }
371
+
372
+ public toArray() {
373
+ return this._copyArray(false);
374
+ }
375
+
376
+ /**
377
+ * Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
378
+ */
379
+ public splice(
380
+ /**
381
+ * The zero-based location in the array from which to start removing elements.
382
+ */
383
+ start: number,
384
+ /**
385
+ * The number of elements to remove.
386
+ */
387
+ deleteCount: number,
388
+ /**
389
+ * Elements to insert into the array in place of the deleted elements.
390
+ */
391
+ ...items: T[]
392
+ ): T[] | undefined {
393
+ let i = start;
394
+
395
+ // expect a number or return undefined
396
+ if ((i !== (i | 0))) {
397
+ return undefined;
398
+ }
399
+
400
+ const { length } = this;
401
+
402
+ if (i < 0) {
403
+ i += length;
404
+ }
405
+
406
+ if (i > length) {
407
+ return undefined;
408
+ }
409
+
410
+ let itemsLength = items.length;
411
+
412
+ if (itemsLength > 0) {
413
+ let k;
414
+ let temp;
415
+ let removed;
416
+ const len = this._list.length;
417
+ let itemIndex = 0;
418
+
419
+ if (!length || i < length / 2) {
420
+ temp = new Array(i);
421
+ for (k = 0; k < i; k++) {
422
+ temp[k] = this._list[(this._head + k) & this._capacityMask];
423
+ }
424
+
425
+ if (deleteCount === 0) {
426
+ removed = [];
427
+ if (i > 0) {
428
+ this._head = (this._head + i + len) & this._capacityMask;
429
+ }
430
+ } else {
431
+ removed = this.remove(i, deleteCount);
432
+ this._head = (this._head + i + len) & this._capacityMask;
433
+ }
434
+
435
+ while (itemsLength > itemIndex) {
436
+ this.unshift(items[--itemsLength]);
437
+ }
438
+
439
+ for (k = i; k > 0; k--) {
440
+ this.unshift(temp[k - 1]);
441
+ }
442
+ } else {
443
+ temp = new Array(length - (i + deleteCount));
444
+ const leng = temp.length;
445
+
446
+ for (k = 0; k < leng; k++) {
447
+ temp[k] = this._list[(this._head + i + deleteCount + k) & this._capacityMask];
448
+ }
449
+
450
+ if (deleteCount === 0) {
451
+ removed = [];
452
+ if (i !== length) {
453
+ this._tail = (this._head + i + len) & this._capacityMask;
454
+ }
455
+ } else {
456
+ removed = this.remove(i, deleteCount);
457
+ this._tail = (this._tail - leng + len) & this._capacityMask;
458
+ }
459
+
460
+ while (itemIndex < itemsLength) {
461
+ this.push(items[itemIndex++]);
462
+ }
463
+
464
+ for (k = 0; k < leng; k++) {
465
+ this.push(temp[k]);
466
+ }
467
+ }
468
+
469
+ return removed;
470
+ } else {
471
+ return this.remove(i, deleteCount);
472
+ }
473
+ }
474
+
475
+ private _growArray() {
476
+ if (this._head !== 0) {
477
+ // double array size and copy existing data, head to end, then beginning to tail.
478
+ const newList = this._copyArray(true, this._list.length << 1);
479
+
480
+ this._tail = this._list.length;
481
+ this._head = 0;
482
+
483
+ this._list = newList;
484
+ } else {
485
+ this._tail = this._list.length;
486
+ this._list.length <<= 1;
487
+ }
488
+
489
+ this._capacityMask = (this._capacityMask << 1) | 1;
490
+ }
491
+
492
+ private _copyArray(fullCopy: boolean, sizeToCopy?: number) {
493
+ const src = this._list;
494
+ const capacity = src.length;
495
+ const { length } = this;
496
+ const size = (sizeToCopy ?? 0) | length;
497
+
498
+ // No prealloc requested and the buffer is contiguous
499
+ if (size === length && this._head < this._tail) {
500
+ // Simply do a fast slice copy
501
+ return this._list.slice(this._head, this._tail);
502
+ }
503
+
504
+ const dest = new Array(size);
505
+
506
+ let k = 0;
507
+ let i;
508
+
509
+ if (fullCopy || this._head > this._tail) {
510
+ for (i = this._head; i < capacity; i++) {
511
+ dest[k++] = src[i];
512
+ }
513
+
514
+ for (i = 0; i < this._tail; i++) {
515
+ dest[k++] = src[i];
516
+ }
517
+ } else {
518
+ for (i = this._head; i < this._tail; i++) {
519
+ dest[k++] = src[i];
520
+ }
521
+ }
522
+
523
+ return dest;
524
+ }
525
+
526
+ private _shrinkArray(): void {
527
+ this._list.length >>>= 1;
528
+ this._capacityMask >>>= 1;
529
+ }
530
+ }
@@ -0,0 +1,16 @@
1
+ import { GlobalContext } from '../../../types/GlobalContext';
2
+
3
+ /**
4
+ * The check returns true for devices
5
+ * where the PRIMARY mechanism of interaction with the user is a touchscreen
6
+ *
7
+ * This is the easiest way, primitive, but effective way to separate mobile and desktop devices
8
+ *
9
+ * For example, on a laptop with a touchscreen, this utility should return false
10
+ * (since there is a touchscreen, but it's not the primary way of interaction,
11
+ * the user most likely uses a touchpad),
12
+ * while on a tablet with a keyboard - true
13
+ */
14
+ export function isTouchScreenDevice(win: Pick<GlobalContext, 'ontouchstart'>): boolean {
15
+ return 'ontouchstart' in win;
16
+ }
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Метод организует всплытие ошибки до глобального скоупа без прерывания текущего коллстека
3
+ */
4
+ export function rethrowError(error: Error): void {
5
+ setTimeout(() => {
6
+ throw error;
7
+ }, 0);
8
+ }
@@ -0,0 +1,32 @@
1
+ import { isObject } from '../../types/Object/Object';
2
+ import { isFunction } from '../Function/isFunction';
3
+ import { isString } from '../String/isString';
4
+
5
+ export function wrapError(error: unknown, {
6
+ messageModifier,
7
+ }: Partial<{
8
+ messageModifier: (oldMessage: string) => string;
9
+ }> = {}): Error {
10
+ let resultError: Error;
11
+
12
+ if (error instanceof Error) {
13
+ resultError = error;
14
+ } else {
15
+ resultError = new Error('DEFAULT_ERROR_MESSAGE');
16
+ if (isObject(error)) {
17
+ if (isString(error.message)) {
18
+ resultError.message = error.message;
19
+ }
20
+
21
+ if (isString(error.stack)) {
22
+ resultError.stack = error.stack;
23
+ }
24
+ }
25
+ }
26
+
27
+ if (isFunction(messageModifier)) {
28
+ resultError.message = messageModifier(resultError.message);
29
+ }
30
+
31
+ return resultError;
32
+ }
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Wrapper for a function that will be called first time with first function, and then with other function
3
+ */
4
+
5
+ export function callFirstThenOther<T extends (
6
+ this: unknown, ...args: unknown[]) => unknown>(
7
+ this: unknown,
8
+ first: T,
9
+ other: T
10
+ ): T {
11
+ let called = false;
12
+
13
+ const wrapper = function (this: unknown, ...args: unknown[]) {
14
+ const fn = called ? other : first;
15
+
16
+ called = true;
17
+
18
+ return fn.apply(this, args);
19
+ };
20
+
21
+ return function (this: unknown, ...args: unknown[]) {
22
+ return wrapper.apply(this, args);
23
+ } as T;
24
+ }
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Функция вызывает массив функций с аргументами
3
+ */
4
+ export function callFunctions<T extends unknown[]>(
5
+ functions: Iterable<((...callArgs: T) => unknown)>,
6
+ ...args: T
7
+ ): void {
8
+ for (const func of functions) {
9
+ func(...args);
10
+ }
11
+ }
@@ -0,0 +1,5 @@
1
+ export function callTimes(times: number, fn: (index: number) => void): void {
2
+ for (let index = 0; index < times; index++) {
3
+ fn(index);
4
+ }
5
+ }
@@ -0,0 +1,3 @@
1
+ export function isFunction<T extends (...args: unknown[]) => unknown>(value: unknown): value is T {
2
+ return typeof value === 'function';
3
+ }
@@ -0,0 +1,4 @@
1
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2
+ export function noop(...args: unknown[]): void {
3
+ //
4
+ }
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Wrapper for a function that will be called no more than once
3
+ *
4
+ * Call context is preserved
5
+ *
6
+ * Subsequent calls return the result of the first call
7
+ *
8
+ * Subsequent recursive calls will not be executed either
9
+ */
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
11
+ export function once<T extends (this: any, ...args: any[]) => any>(this: any, fn: T): T {
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ let onceFn = function (this: any) {
14
+ // Create variable in advance to avoid errors when accessing non-existent constant during call
15
+ // eslint-disable-next-line prefer-const, @typescript-eslint/no-explicit-any
16
+ let result: any;
17
+
18
+ // Overwrite function in advance to avoid recursive call inside once
19
+ onceFn = () => result;
20
+
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, prefer-rest-params
22
+ result = fn.apply(this, arguments as any);
23
+
24
+ return result;
25
+ };
26
+
27
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
28
+ return function (this: any) {
29
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, prefer-rest-params
30
+ return onceFn.apply(this, arguments as any);
31
+ } as T;
32
+ }