litus 1.3.1 → 1.5.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 (385) hide show
  1. package/README.md +17 -17
  2. package/dist/index.cjs.js +1206 -0
  3. package/dist/index.cjs.js.map +1 -0
  4. package/dist/index.d.ts +779 -0
  5. package/dist/index.esm.js +1132 -0
  6. package/dist/index.esm.js.map +1 -0
  7. package/package.json +16 -8
  8. package/dist/cjs/arr/chunk.d.ts +0 -1
  9. package/dist/cjs/arr/chunk.js +0 -12
  10. package/dist/cjs/arr/chunk.js.map +0 -1
  11. package/dist/cjs/arr/fill.d.ts +0 -1
  12. package/dist/cjs/arr/fill.js +0 -9
  13. package/dist/cjs/arr/fill.js.map +0 -1
  14. package/dist/cjs/arr/find.d.ts +0 -2
  15. package/dist/cjs/arr/find.js +0 -9
  16. package/dist/cjs/arr/find.js.map +0 -1
  17. package/dist/cjs/arr/findAll.d.ts +0 -2
  18. package/dist/cjs/arr/findAll.js +0 -9
  19. package/dist/cjs/arr/findAll.js.map +0 -1
  20. package/dist/cjs/arr/findAllIdx.d.ts +0 -2
  21. package/dist/cjs/arr/findAllIdx.js +0 -17
  22. package/dist/cjs/arr/findAllIdx.js.map +0 -1
  23. package/dist/cjs/arr/findIdx.d.ts +0 -2
  24. package/dist/cjs/arr/findIdx.js +0 -13
  25. package/dist/cjs/arr/findIdx.js.map +0 -1
  26. package/dist/cjs/arr/from.d.ts +0 -1
  27. package/dist/cjs/arr/from.js +0 -13
  28. package/dist/cjs/arr/from.js.map +0 -1
  29. package/dist/cjs/arr/group.d.ts +0 -1
  30. package/dist/cjs/arr/group.js +0 -16
  31. package/dist/cjs/arr/group.js.map +0 -1
  32. package/dist/cjs/arr/groupBy.d.ts +0 -1
  33. package/dist/cjs/arr/groupBy.js +0 -9
  34. package/dist/cjs/arr/groupBy.js.map +0 -1
  35. package/dist/cjs/arr/index.d.ts +0 -17
  36. package/dist/cjs/arr/index.js +0 -34
  37. package/dist/cjs/arr/index.js.map +0 -1
  38. package/dist/cjs/arr/max.d.ts +0 -1
  39. package/dist/cjs/arr/max.js +0 -15
  40. package/dist/cjs/arr/max.js.map +0 -1
  41. package/dist/cjs/arr/min.d.ts +0 -1
  42. package/dist/cjs/arr/min.js +0 -9
  43. package/dist/cjs/arr/min.js.map +0 -1
  44. package/dist/cjs/arr/range.d.ts +0 -1
  45. package/dist/cjs/arr/range.js +0 -13
  46. package/dist/cjs/arr/range.js.map +0 -1
  47. package/dist/cjs/arr/sort.d.ts +0 -1
  48. package/dist/cjs/arr/sort.js +0 -21
  49. package/dist/cjs/arr/sort.js.map +0 -1
  50. package/dist/cjs/arr/transpose.d.ts +0 -2
  51. package/dist/cjs/arr/transpose.js +0 -12
  52. package/dist/cjs/arr/transpose.js.map +0 -1
  53. package/dist/cjs/arr/types.d.ts +0 -11
  54. package/dist/cjs/arr/types.js +0 -3
  55. package/dist/cjs/arr/types.js.map +0 -1
  56. package/dist/cjs/arr/union.d.ts +0 -1
  57. package/dist/cjs/arr/union.js +0 -8
  58. package/dist/cjs/arr/union.js.map +0 -1
  59. package/dist/cjs/arr/unique.d.ts +0 -2
  60. package/dist/cjs/arr/unique.js +0 -10
  61. package/dist/cjs/arr/unique.js.map +0 -1
  62. package/dist/cjs/arr/zip.d.ts +0 -1
  63. package/dist/cjs/arr/zip.js +0 -7
  64. package/dist/cjs/arr/zip.js.map +0 -1
  65. package/dist/cjs/func/apply.d.ts +0 -1
  66. package/dist/cjs/func/apply.js +0 -8
  67. package/dist/cjs/func/apply.js.map +0 -1
  68. package/dist/cjs/func/curry.d.ts +0 -2
  69. package/dist/cjs/func/curry.js +0 -17
  70. package/dist/cjs/func/curry.js.map +0 -1
  71. package/dist/cjs/func/debounce.d.ts +0 -1
  72. package/dist/cjs/func/debounce.js +0 -15
  73. package/dist/cjs/func/debounce.js.map +0 -1
  74. package/dist/cjs/func/index.d.ts +0 -6
  75. package/dist/cjs/func/index.js +0 -23
  76. package/dist/cjs/func/index.js.map +0 -1
  77. package/dist/cjs/func/memo.d.ts +0 -2
  78. package/dist/cjs/func/memo.js +0 -22
  79. package/dist/cjs/func/memo.js.map +0 -1
  80. package/dist/cjs/func/throttle.d.ts +0 -1
  81. package/dist/cjs/func/throttle.js +0 -19
  82. package/dist/cjs/func/throttle.js.map +0 -1
  83. package/dist/cjs/func/types.d.ts +0 -8
  84. package/dist/cjs/func/types.js +0 -3
  85. package/dist/cjs/func/types.js.map +0 -1
  86. package/dist/cjs/func/unapply.d.ts +0 -1
  87. package/dist/cjs/func/unapply.js +0 -8
  88. package/dist/cjs/func/unapply.js.map +0 -1
  89. package/dist/cjs/index.d.ts +0 -13
  90. package/dist/cjs/index.js +0 -43
  91. package/dist/cjs/index.js.map +0 -1
  92. package/dist/cjs/math/add.d.ts +0 -1
  93. package/dist/cjs/math/add.js +0 -8
  94. package/dist/cjs/math/add.js.map +0 -1
  95. package/dist/cjs/math/aprox.d.ts +0 -1
  96. package/dist/cjs/math/aprox.js +0 -9
  97. package/dist/cjs/math/aprox.js.map +0 -1
  98. package/dist/cjs/math/calc.d.ts +0 -5
  99. package/dist/cjs/math/calc.js +0 -23
  100. package/dist/cjs/math/calc.js.map +0 -1
  101. package/dist/cjs/math/cumsum.d.ts +0 -1
  102. package/dist/cjs/math/cumsum.js +0 -13
  103. package/dist/cjs/math/cumsum.js.map +0 -1
  104. package/dist/cjs/math/divide.d.ts +0 -1
  105. package/dist/cjs/math/divide.js +0 -6
  106. package/dist/cjs/math/divide.js.map +0 -1
  107. package/dist/cjs/math/inRange.d.ts +0 -1
  108. package/dist/cjs/math/inRange.js +0 -11
  109. package/dist/cjs/math/inRange.js.map +0 -1
  110. package/dist/cjs/math/index.d.ts +0 -16
  111. package/dist/cjs/math/index.js +0 -33
  112. package/dist/cjs/math/index.js.map +0 -1
  113. package/dist/cjs/math/interp.d.ts +0 -1
  114. package/dist/cjs/math/interp.js +0 -22
  115. package/dist/cjs/math/interp.js.map +0 -1
  116. package/dist/cjs/math/mean.d.ts +0 -1
  117. package/dist/cjs/math/mean.js +0 -16
  118. package/dist/cjs/math/mean.js.map +0 -1
  119. package/dist/cjs/math/median.d.ts +0 -1
  120. package/dist/cjs/math/median.js +0 -9
  121. package/dist/cjs/math/median.js.map +0 -1
  122. package/dist/cjs/math/mod.d.ts +0 -1
  123. package/dist/cjs/math/mod.js +0 -8
  124. package/dist/cjs/math/mod.js.map +0 -1
  125. package/dist/cjs/math/multiply.d.ts +0 -1
  126. package/dist/cjs/math/multiply.js +0 -7
  127. package/dist/cjs/math/multiply.js.map +0 -1
  128. package/dist/cjs/math/percentile.d.ts +0 -2
  129. package/dist/cjs/math/percentile.js +0 -49
  130. package/dist/cjs/math/percentile.js.map +0 -1
  131. package/dist/cjs/math/pow.d.ts +0 -1
  132. package/dist/cjs/math/pow.js +0 -8
  133. package/dist/cjs/math/pow.js.map +0 -1
  134. package/dist/cjs/math/round.d.ts +0 -2
  135. package/dist/cjs/math/round.js +0 -15
  136. package/dist/cjs/math/round.js.map +0 -1
  137. package/dist/cjs/math/subtract.d.ts +0 -1
  138. package/dist/cjs/math/subtract.js +0 -6
  139. package/dist/cjs/math/subtract.js.map +0 -1
  140. package/dist/cjs/math/sum.d.ts +0 -1
  141. package/dist/cjs/math/sum.js +0 -8
  142. package/dist/cjs/math/sum.js.map +0 -1
  143. package/dist/cjs/math/types.d.ts +0 -4
  144. package/dist/cjs/math/types.js +0 -3
  145. package/dist/cjs/math/types.js.map +0 -1
  146. package/dist/cjs/obj/copy.d.ts +0 -1
  147. package/dist/cjs/obj/copy.js +0 -16
  148. package/dist/cjs/obj/copy.js.map +0 -1
  149. package/dist/cjs/obj/entries.d.ts +0 -2
  150. package/dist/cjs/obj/entries.js +0 -5
  151. package/dist/cjs/obj/entries.js.map +0 -1
  152. package/dist/cjs/obj/equal.d.ts +0 -1
  153. package/dist/cjs/obj/equal.js +0 -30
  154. package/dist/cjs/obj/equal.js.map +0 -1
  155. package/dist/cjs/obj/get.d.ts +0 -1
  156. package/dist/cjs/obj/get.js +0 -19
  157. package/dist/cjs/obj/get.js.map +0 -1
  158. package/dist/cjs/obj/has.d.ts +0 -1
  159. package/dist/cjs/obj/has.js +0 -8
  160. package/dist/cjs/obj/has.js.map +0 -1
  161. package/dist/cjs/obj/index.d.ts +0 -11
  162. package/dist/cjs/obj/index.js +0 -28
  163. package/dist/cjs/obj/index.js.map +0 -1
  164. package/dist/cjs/obj/isObj.d.ts +0 -1
  165. package/dist/cjs/obj/isObj.js +0 -8
  166. package/dist/cjs/obj/isObj.js.map +0 -1
  167. package/dist/cjs/obj/keys.d.ts +0 -2
  168. package/dist/cjs/obj/keys.js +0 -5
  169. package/dist/cjs/obj/keys.js.map +0 -1
  170. package/dist/cjs/obj/merge.d.ts +0 -1
  171. package/dist/cjs/obj/merge.js +0 -9
  172. package/dist/cjs/obj/merge.js.map +0 -1
  173. package/dist/cjs/obj/omit.d.ts +0 -1
  174. package/dist/cjs/obj/omit.js +0 -13
  175. package/dist/cjs/obj/omit.js.map +0 -1
  176. package/dist/cjs/obj/pick.d.ts +0 -1
  177. package/dist/cjs/obj/pick.js +0 -13
  178. package/dist/cjs/obj/pick.js.map +0 -1
  179. package/dist/cjs/obj/types.d.ts +0 -4
  180. package/dist/cjs/obj/types.js +0 -3
  181. package/dist/cjs/obj/types.js.map +0 -1
  182. package/dist/cjs/obj/vals.d.ts +0 -2
  183. package/dist/cjs/obj/vals.js +0 -5
  184. package/dist/cjs/obj/vals.js.map +0 -1
  185. package/dist/cjs/time/index.d.ts +0 -16
  186. package/dist/cjs/time/index.js +0 -59
  187. package/dist/cjs/time/index.js.map +0 -1
  188. package/dist/cjs/time/types.d.ts +0 -4
  189. package/dist/cjs/time/types.js +0 -3
  190. package/dist/cjs/time/types.js.map +0 -1
  191. package/dist/cjs/types/index.d.ts +0 -1
  192. package/dist/cjs/types/index.js +0 -18
  193. package/dist/cjs/types/index.js.map +0 -1
  194. package/dist/cjs/types/primitives.d.ts +0 -4
  195. package/dist/cjs/types/primitives.js +0 -3
  196. package/dist/cjs/types/primitives.js.map +0 -1
  197. package/dist/esm/arr/chunk.d.ts +0 -1
  198. package/dist/esm/arr/chunk.js +0 -8
  199. package/dist/esm/arr/chunk.js.map +0 -1
  200. package/dist/esm/arr/fill.d.ts +0 -1
  201. package/dist/esm/arr/fill.js +0 -5
  202. package/dist/esm/arr/fill.js.map +0 -1
  203. package/dist/esm/arr/find.d.ts +0 -2
  204. package/dist/esm/arr/find.js +0 -5
  205. package/dist/esm/arr/find.js.map +0 -1
  206. package/dist/esm/arr/findAll.d.ts +0 -2
  207. package/dist/esm/arr/findAll.js +0 -5
  208. package/dist/esm/arr/findAll.js.map +0 -1
  209. package/dist/esm/arr/findAllIdx.d.ts +0 -2
  210. package/dist/esm/arr/findAllIdx.js +0 -13
  211. package/dist/esm/arr/findAllIdx.js.map +0 -1
  212. package/dist/esm/arr/findIdx.d.ts +0 -2
  213. package/dist/esm/arr/findIdx.js +0 -9
  214. package/dist/esm/arr/findIdx.js.map +0 -1
  215. package/dist/esm/arr/from.d.ts +0 -1
  216. package/dist/esm/arr/from.js +0 -9
  217. package/dist/esm/arr/from.js.map +0 -1
  218. package/dist/esm/arr/group.d.ts +0 -1
  219. package/dist/esm/arr/group.js +0 -12
  220. package/dist/esm/arr/group.js.map +0 -1
  221. package/dist/esm/arr/groupBy.d.ts +0 -1
  222. package/dist/esm/arr/groupBy.js +0 -5
  223. package/dist/esm/arr/groupBy.js.map +0 -1
  224. package/dist/esm/arr/index.d.ts +0 -17
  225. package/dist/esm/arr/index.js +0 -18
  226. package/dist/esm/arr/index.js.map +0 -1
  227. package/dist/esm/arr/max.d.ts +0 -1
  228. package/dist/esm/arr/max.js +0 -11
  229. package/dist/esm/arr/max.js.map +0 -1
  230. package/dist/esm/arr/min.d.ts +0 -1
  231. package/dist/esm/arr/min.js +0 -5
  232. package/dist/esm/arr/min.js.map +0 -1
  233. package/dist/esm/arr/range.d.ts +0 -1
  234. package/dist/esm/arr/range.js +0 -9
  235. package/dist/esm/arr/range.js.map +0 -1
  236. package/dist/esm/arr/sort.d.ts +0 -1
  237. package/dist/esm/arr/sort.js +0 -17
  238. package/dist/esm/arr/sort.js.map +0 -1
  239. package/dist/esm/arr/transpose.d.ts +0 -2
  240. package/dist/esm/arr/transpose.js +0 -8
  241. package/dist/esm/arr/transpose.js.map +0 -1
  242. package/dist/esm/arr/types.d.ts +0 -11
  243. package/dist/esm/arr/types.js +0 -2
  244. package/dist/esm/arr/types.js.map +0 -1
  245. package/dist/esm/arr/union.d.ts +0 -1
  246. package/dist/esm/arr/union.js +0 -5
  247. package/dist/esm/arr/union.js.map +0 -1
  248. package/dist/esm/arr/unique.d.ts +0 -2
  249. package/dist/esm/arr/unique.js +0 -6
  250. package/dist/esm/arr/unique.js.map +0 -1
  251. package/dist/esm/arr/zip.d.ts +0 -1
  252. package/dist/esm/arr/zip.js +0 -4
  253. package/dist/esm/arr/zip.js.map +0 -1
  254. package/dist/esm/func/apply.d.ts +0 -1
  255. package/dist/esm/func/apply.js +0 -4
  256. package/dist/esm/func/apply.js.map +0 -1
  257. package/dist/esm/func/curry.d.ts +0 -2
  258. package/dist/esm/func/curry.js +0 -13
  259. package/dist/esm/func/curry.js.map +0 -1
  260. package/dist/esm/func/debounce.d.ts +0 -1
  261. package/dist/esm/func/debounce.js +0 -11
  262. package/dist/esm/func/debounce.js.map +0 -1
  263. package/dist/esm/func/index.d.ts +0 -6
  264. package/dist/esm/func/index.js +0 -7
  265. package/dist/esm/func/index.js.map +0 -1
  266. package/dist/esm/func/memo.d.ts +0 -2
  267. package/dist/esm/func/memo.js +0 -18
  268. package/dist/esm/func/memo.js.map +0 -1
  269. package/dist/esm/func/throttle.d.ts +0 -1
  270. package/dist/esm/func/throttle.js +0 -15
  271. package/dist/esm/func/throttle.js.map +0 -1
  272. package/dist/esm/func/types.d.ts +0 -8
  273. package/dist/esm/func/types.js +0 -2
  274. package/dist/esm/func/types.js.map +0 -1
  275. package/dist/esm/func/unapply.d.ts +0 -1
  276. package/dist/esm/func/unapply.js +0 -4
  277. package/dist/esm/func/unapply.js.map +0 -1
  278. package/dist/esm/index.d.ts +0 -13
  279. package/dist/esm/index.js +0 -14
  280. package/dist/esm/index.js.map +0 -1
  281. package/dist/esm/math/add.d.ts +0 -1
  282. package/dist/esm/math/add.js +0 -5
  283. package/dist/esm/math/add.js.map +0 -1
  284. package/dist/esm/math/aprox.d.ts +0 -1
  285. package/dist/esm/math/aprox.js +0 -5
  286. package/dist/esm/math/aprox.js.map +0 -1
  287. package/dist/esm/math/calc.d.ts +0 -5
  288. package/dist/esm/math/calc.js +0 -19
  289. package/dist/esm/math/calc.js.map +0 -1
  290. package/dist/esm/math/cumsum.d.ts +0 -1
  291. package/dist/esm/math/cumsum.js +0 -9
  292. package/dist/esm/math/cumsum.js.map +0 -1
  293. package/dist/esm/math/divide.d.ts +0 -1
  294. package/dist/esm/math/divide.js +0 -3
  295. package/dist/esm/math/divide.js.map +0 -1
  296. package/dist/esm/math/inRange.d.ts +0 -1
  297. package/dist/esm/math/inRange.js +0 -7
  298. package/dist/esm/math/inRange.js.map +0 -1
  299. package/dist/esm/math/index.d.ts +0 -16
  300. package/dist/esm/math/index.js +0 -17
  301. package/dist/esm/math/index.js.map +0 -1
  302. package/dist/esm/math/interp.d.ts +0 -1
  303. package/dist/esm/math/interp.js +0 -18
  304. package/dist/esm/math/interp.js.map +0 -1
  305. package/dist/esm/math/mean.d.ts +0 -1
  306. package/dist/esm/math/mean.js +0 -12
  307. package/dist/esm/math/mean.js.map +0 -1
  308. package/dist/esm/math/median.d.ts +0 -1
  309. package/dist/esm/math/median.js +0 -5
  310. package/dist/esm/math/median.js.map +0 -1
  311. package/dist/esm/math/mod.d.ts +0 -1
  312. package/dist/esm/math/mod.js +0 -4
  313. package/dist/esm/math/mod.js.map +0 -1
  314. package/dist/esm/math/multiply.d.ts +0 -1
  315. package/dist/esm/math/multiply.js +0 -4
  316. package/dist/esm/math/multiply.js.map +0 -1
  317. package/dist/esm/math/percentile.d.ts +0 -2
  318. package/dist/esm/math/percentile.js +0 -45
  319. package/dist/esm/math/percentile.js.map +0 -1
  320. package/dist/esm/math/pow.d.ts +0 -1
  321. package/dist/esm/math/pow.js +0 -4
  322. package/dist/esm/math/pow.js.map +0 -1
  323. package/dist/esm/math/round.d.ts +0 -2
  324. package/dist/esm/math/round.js +0 -11
  325. package/dist/esm/math/round.js.map +0 -1
  326. package/dist/esm/math/subtract.d.ts +0 -1
  327. package/dist/esm/math/subtract.js +0 -3
  328. package/dist/esm/math/subtract.js.map +0 -1
  329. package/dist/esm/math/sum.d.ts +0 -1
  330. package/dist/esm/math/sum.js +0 -4
  331. package/dist/esm/math/sum.js.map +0 -1
  332. package/dist/esm/math/types.d.ts +0 -4
  333. package/dist/esm/math/types.js +0 -2
  334. package/dist/esm/math/types.js.map +0 -1
  335. package/dist/esm/obj/copy.d.ts +0 -1
  336. package/dist/esm/obj/copy.js +0 -12
  337. package/dist/esm/obj/copy.js.map +0 -1
  338. package/dist/esm/obj/entries.d.ts +0 -2
  339. package/dist/esm/obj/entries.js +0 -2
  340. package/dist/esm/obj/entries.js.map +0 -1
  341. package/dist/esm/obj/equal.d.ts +0 -1
  342. package/dist/esm/obj/equal.js +0 -27
  343. package/dist/esm/obj/equal.js.map +0 -1
  344. package/dist/esm/obj/get.d.ts +0 -1
  345. package/dist/esm/obj/get.js +0 -15
  346. package/dist/esm/obj/get.js.map +0 -1
  347. package/dist/esm/obj/has.d.ts +0 -1
  348. package/dist/esm/obj/has.js +0 -4
  349. package/dist/esm/obj/has.js.map +0 -1
  350. package/dist/esm/obj/index.d.ts +0 -11
  351. package/dist/esm/obj/index.js +0 -12
  352. package/dist/esm/obj/index.js.map +0 -1
  353. package/dist/esm/obj/isObj.d.ts +0 -1
  354. package/dist/esm/obj/isObj.js +0 -4
  355. package/dist/esm/obj/isObj.js.map +0 -1
  356. package/dist/esm/obj/keys.d.ts +0 -2
  357. package/dist/esm/obj/keys.js +0 -2
  358. package/dist/esm/obj/keys.js.map +0 -1
  359. package/dist/esm/obj/merge.d.ts +0 -1
  360. package/dist/esm/obj/merge.js +0 -5
  361. package/dist/esm/obj/merge.js.map +0 -1
  362. package/dist/esm/obj/omit.d.ts +0 -1
  363. package/dist/esm/obj/omit.js +0 -9
  364. package/dist/esm/obj/omit.js.map +0 -1
  365. package/dist/esm/obj/pick.d.ts +0 -1
  366. package/dist/esm/obj/pick.js +0 -9
  367. package/dist/esm/obj/pick.js.map +0 -1
  368. package/dist/esm/obj/types.d.ts +0 -4
  369. package/dist/esm/obj/types.js +0 -2
  370. package/dist/esm/obj/types.js.map +0 -1
  371. package/dist/esm/obj/vals.d.ts +0 -2
  372. package/dist/esm/obj/vals.js +0 -2
  373. package/dist/esm/obj/vals.js.map +0 -1
  374. package/dist/esm/time/index.d.ts +0 -16
  375. package/dist/esm/time/index.js +0 -55
  376. package/dist/esm/time/index.js.map +0 -1
  377. package/dist/esm/time/types.d.ts +0 -4
  378. package/dist/esm/time/types.js +0 -2
  379. package/dist/esm/time/types.js.map +0 -1
  380. package/dist/esm/types/index.d.ts +0 -1
  381. package/dist/esm/types/index.js +0 -2
  382. package/dist/esm/types/index.js.map +0 -1
  383. package/dist/esm/types/primitives.d.ts +0 -4
  384. package/dist/esm/types/primitives.js +0 -2
  385. package/dist/esm/types/primitives.js.map +0 -1
@@ -0,0 +1,1206 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Binary search for insertion index in a sorted array using a custom accessor
5
+ * @param arr Sorted array to search
6
+ * @param target Value to search for
7
+ * @param getVal Function to extract comparison value from each element
8
+ * @param start Start index (inclusive)
9
+ * @param end End index (exclusive)
10
+ * @returns Index to insert target to maintain order
11
+ */
12
+ const binSearch = (arr, target, getVal, start = 0, end = arr.length) => {
13
+ if (start < 0 || end > arr.length || start > end) {
14
+ throw new Error("Invalid start or end of search");
15
+ }
16
+ let a = start;
17
+ let b = end;
18
+ while (a < b) {
19
+ const mid = Math.floor((a + b) / 2);
20
+ const midVal = getVal(arr[mid]);
21
+ if (midVal < target) {
22
+ a = mid + 1;
23
+ }
24
+ else {
25
+ b = mid;
26
+ }
27
+ }
28
+ return a;
29
+ };
30
+
31
+ /**
32
+ * Creates an array of size `n`, filling each element using the map function
33
+ * @param n Size of the array to create
34
+ * @param mapFn Function that maps each index to an array element
35
+ * @returns Array of mapped values
36
+ */
37
+ const from = (n, mapFn) => {
38
+ const res = Array(n);
39
+ let i = n;
40
+ while (--i >= 0) {
41
+ res[i] = mapFn(i);
42
+ }
43
+ return res;
44
+ };
45
+
46
+ /**
47
+ * Creates an array of numbers from `a` up to `b` incremented by `step`
48
+ * @param a Start of the range (inclusive)
49
+ * @param b End of the range (exclusive)
50
+ * @param step Step between elements (default is 1)
51
+ * @returns Array of numbers in the specified range
52
+ */
53
+ const range = (a, b, step = 1) => {
54
+ if (step === 0) {
55
+ throw new Error("Step cannot be 0");
56
+ }
57
+ const n = Math.ceil((b - a) / step);
58
+ return from(n, (i) => a + step * i);
59
+ };
60
+
61
+ /**
62
+ * Splits an array into multiple chunks of a specified size
63
+ * @param arr Array to split
64
+ * @param size Size of each chunk
65
+ * @returns Array of chunks
66
+ */
67
+ const chunk = (arr, size) => {
68
+ if (!Number.isInteger(size)) {
69
+ throw new Error("Chunk size must be an integer");
70
+ }
71
+ return range(0, arr.length, size).map((i) => arr.slice(i, i + size));
72
+ };
73
+
74
+ /**
75
+ * Creates array of size `n` filled with the specified value
76
+ * @param n Array size
77
+ * @param val Value to fill the array with
78
+ * @returns Array containing `val` repeated `n` times
79
+ */
80
+ const fill = (n, val) => {
81
+ return from(n, () => val);
82
+ };
83
+
84
+ /**
85
+ * Finds the index of the first element that matches the given predicate
86
+ * @param arr Array to search
87
+ * @param predicate Function to test each element
88
+ * @param from Start index (inclusive). Default: 0
89
+ * @param to End index (exclusive). Default: arr.length
90
+ * @returns Index of the first matching element, or -1 if none found
91
+ */
92
+ const findIdx = (arr, predicate, from = 0, to = arr.length) => {
93
+ for (let i = from; i < to; i++) {
94
+ if (predicate(arr[i], i, arr)) {
95
+ return i;
96
+ }
97
+ }
98
+ return -1;
99
+ };
100
+
101
+ /**
102
+ * Finds the first element that matches the given predicate
103
+ * @param arr Array to search
104
+ * @param predicate Function to test each element
105
+ * @param from Start index (inclusive). Default: 0
106
+ * @param to End index (exclusive). Default: arr.length
107
+ * @returns First matching element, or undefined if none found
108
+ */
109
+ const find = (arr, predicate, from = 0, to = arr.length) => {
110
+ return arr[findIdx(arr, predicate, from, to)];
111
+ };
112
+
113
+ /**
114
+ * Finds indices of all elements that match the given predicate
115
+ * @param arr Array to search
116
+ * @param predicate Function to test each element
117
+ * @param from Start index (inclusive). Default: 0
118
+ * @param to End index (exclusive). Default: arr.length
119
+ * @param limit Maximum number of indices to return. Default: arr.length
120
+ * @returns Array of matching indices
121
+ */
122
+ const findAllIdx = (arr, predicate, from = 0, to = arr.length, limit = arr.length) => {
123
+ const res = [];
124
+ for (let i = from; i < to; i++) {
125
+ if (predicate(arr[i], i, arr)) {
126
+ res.push(i);
127
+ if (res.length >= limit) {
128
+ break;
129
+ }
130
+ }
131
+ }
132
+ return res;
133
+ };
134
+
135
+ /**
136
+ * Finds all elements that match the given predicate
137
+ * @param arr Array to search
138
+ * @param predicate Function to test each element
139
+ * @param from Start index (inclusive). Default: 0
140
+ * @param to End index (exclusive). Default: arr.length
141
+ * @param limit Maximum number of matches to return. Default: arr.length
142
+ * @returns Array of matching elements
143
+ */
144
+ const findAll = (arr, predicate, from = 0, to = arr.length, limit = arr.length) => {
145
+ return findAllIdx(arr, predicate, from, to, limit).map((i) => arr[i]);
146
+ };
147
+
148
+ /**
149
+ * Groups array items into an object by a key
150
+ * @param arr Array to group
151
+ * @param getKey Function to extract the group key from each item
152
+ * @returns Object with keys as group ids and values as arrays of grouped items
153
+ */
154
+ const group = (arr, getKey) => {
155
+ const res = {};
156
+ arr.forEach((el) => {
157
+ const val = getKey(el);
158
+ if (res[val] === undefined) {
159
+ res[val] = [];
160
+ }
161
+ res[val].push(el);
162
+ });
163
+ return res;
164
+ };
165
+
166
+ /**
167
+ * @deprecated Use `group` instead
168
+ */
169
+ const groupBy = (arr, key) => {
170
+ return group(arr, (obj) => obj[key]);
171
+ };
172
+
173
+ /**
174
+ * Returns the element with the maximum value based on the provided map function
175
+ * @param arr Array to search
176
+ * @param fn Function to extract the value for comparison
177
+ * @returns Element with the maximum value
178
+ */
179
+ const max = (arr, fn) => {
180
+ const scores = arr.map(fn);
181
+ let maxIdx = 0;
182
+ for (let i = 1; i < scores.length; i++) {
183
+ if (scores[i] > scores[maxIdx]) {
184
+ maxIdx = i;
185
+ }
186
+ }
187
+ return arr[maxIdx];
188
+ };
189
+
190
+ /**
191
+ * Returns the element with the minimum value based on the provided map function
192
+ * @param arr Array to search
193
+ * @param fn Function to extract the value for comparison
194
+ * @returns Element with the minimum value
195
+ */
196
+ const min = (arr, fn) => {
197
+ return max(arr, (val) => -fn(val));
198
+ };
199
+
200
+ /**
201
+ * Sorts an array in-place based on a mapping function
202
+ * @param arr Array to sort
203
+ * @param mapFn Function to map each element to a sortable value
204
+ * @returns Sorted array in-place
205
+ */
206
+ const sort = (arr, mapFn) => {
207
+ const mapped = arr.map((el) => [mapFn(el), el]);
208
+ mapped.sort(([a], [b]) => {
209
+ if (a < b) {
210
+ return -1;
211
+ }
212
+ if (a > b) {
213
+ return 1;
214
+ }
215
+ return 0;
216
+ });
217
+ mapped.forEach(([, el], i) => {
218
+ arr[i] = el;
219
+ });
220
+ return arr;
221
+ };
222
+
223
+ /**
224
+ * Transposes a 2D array (matrix), switching its rows and columns
225
+ * @param matrix The 2D array to transpose
226
+ * @returns Transposed matrix
227
+ */
228
+ const transpose = (matrix) => {
229
+ const rows = matrix.length;
230
+ const cols = matrix[0].length;
231
+ if (matrix.some((row) => row.length !== cols)) {
232
+ throw new Error("Invalid matrix. Rows have different size");
233
+ }
234
+ const res = from(cols, (i) => from(rows, (j) => matrix[j][i]));
235
+ return res;
236
+ };
237
+
238
+ /**
239
+ * Creates a set containing unique values from all provided arrays
240
+ * @param arrs Arrays to union
241
+ * @returns Set of unique values
242
+ */
243
+ const union = (...arrs) => {
244
+ return new Set(arrs.flat(1));
245
+ };
246
+
247
+ /**
248
+ * Creates array of unique values from the input array, preserving their order
249
+ * @param arr Array of primitive values
250
+ * @returns Array of unique values
251
+ */
252
+ const unique = (arr) => {
253
+ const set = Array.from(new Set(arr));
254
+ return sort(set, (el) => arr.indexOf(el));
255
+ };
256
+
257
+ /**
258
+ * Transforms a function with array argument into one with spread arguments
259
+ * @param fn Function accepting an array of arguments
260
+ * @returns Function accepting spread arguments
261
+ */
262
+ const unapply = (fn) => {
263
+ return (...args) => fn(args);
264
+ };
265
+
266
+ /**
267
+ * Creates an array of grouped elements, where each group contains the elements
268
+ * at the corresponding index from the input arrays
269
+ * @param arrays Arrays to process
270
+ * @returns Array of grouped elements
271
+ */
272
+ const zip = unapply(transpose);
273
+
274
+ const index$5 = /*#__PURE__*/Object.freeze({
275
+ __proto__: null,
276
+ binSearch: binSearch,
277
+ chunk: chunk,
278
+ fill: fill,
279
+ find: find,
280
+ findAll: findAll,
281
+ findAllIdx: findAllIdx,
282
+ findIdx: findIdx,
283
+ from: from,
284
+ group: group,
285
+ groupBy: groupBy,
286
+ max: max,
287
+ min: min,
288
+ range: range,
289
+ sort: sort,
290
+ transpose: transpose,
291
+ union: union,
292
+ unique: unique,
293
+ zip: zip
294
+ });
295
+
296
+ /**
297
+ * Transforms a function with spread arguments into one with array argument
298
+ * @param fn Function accepting spread arguments
299
+ * @returns Function accepting an array of arguments
300
+ */
301
+ const apply = (fn) => {
302
+ return (arg) => fn.apply(undefined, arg);
303
+ };
304
+
305
+ /**
306
+ * Creates a curried version of a function, allowing partial application of arguments
307
+ * @param fn Function to curry
308
+ * @param arity Number of arguments the function expects. Default: fn.length
309
+ * @returns Curried function
310
+ */
311
+ const curry = (fn, arity = fn.length) => {
312
+ return (...args) => {
313
+ const missing = arity - args.length;
314
+ if (missing <= 0) {
315
+ return fn.apply(undefined, args);
316
+ }
317
+ return curry((...rArgs) => {
318
+ return fn.apply(undefined, args.concat(rArgs));
319
+ }, missing);
320
+ };
321
+ };
322
+
323
+ /**
324
+ * Creates a debounced version of a function that delays invoking until after the specified delay.
325
+ * Only the last call within the delay period is executed
326
+ * @param fn Function to debounce
327
+ * @param delay Delay in milliseconds. Default: 100
328
+ * @returns Debounced function
329
+ */
330
+ const debounce = (fn, delay = 100) => {
331
+ let timer;
332
+ return (...args) => {
333
+ clearTimeout(timer);
334
+ timer = setTimeout(() => {
335
+ fn.apply(undefined, args);
336
+ }, delay);
337
+ };
338
+ };
339
+
340
+ /**
341
+ * Returns the input value unchanged
342
+ * @param value Value to return
343
+ * @returns Same value provided as input
344
+ */
345
+ const identity = (x) => x;
346
+
347
+ /**
348
+ * Creates a memoized version of a function, caching its output for faster repeated calls.
349
+ * Optionally accepts a custom cache key generator and a TTL (time-to-live) in milliseconds
350
+ * @param fn Function to memoize
351
+ * @param idFn Function to generate a cache key from arguments. Default: JSON.stringify
352
+ * @param ttl Optional cache expiration time in milliseconds. Default: 0 (no expiration)
353
+ * @returns Memoized function
354
+ */
355
+ const memo = (fn, idFn = JSON.stringify, ttl = 0) => {
356
+ const cache = new Map();
357
+ return (...args) => {
358
+ const key = idFn(args);
359
+ const cached = cache.get(key);
360
+ if (cached !== undefined) {
361
+ if (cached.exp === undefined || Date.now() < cached.exp) {
362
+ return cached.val;
363
+ }
364
+ }
365
+ const val = fn.apply(undefined, args);
366
+ const exp = ttl <= 0 ? undefined : Date.now() + ttl;
367
+ cache.set(key, { exp, val });
368
+ return val;
369
+ };
370
+ };
371
+
372
+ /**
373
+ * Ensures the provided function is executed only once
374
+ * Subsequent calls return the result of the first execution
375
+ * @param fn Function to execute only once
376
+ * @returns Function that invokes `fn` only once
377
+ */
378
+ const once = (fn) => {
379
+ let call = true;
380
+ let res;
381
+ return () => {
382
+ if (call) {
383
+ res = fn();
384
+ call = false;
385
+ }
386
+ return res;
387
+ };
388
+ };
389
+
390
+ /**
391
+ * Creates a function by composing multiple unary functions from left to right.
392
+ * The output of each function is passed as the input to the next
393
+ * @param fns Sequence of unary functions to compose
394
+ * @returns Composed function from left to right
395
+ */
396
+ const pipe = (...fns) => {
397
+ return ((input) => {
398
+ return fns.reduce((acc, fn) => fn(acc), input);
399
+ });
400
+ };
401
+
402
+ /**
403
+ * Creates a throttled version of the given function that only executes once per specified interval
404
+ * @param fn Function to throttle
405
+ * @param interval Minimum time (ms) between calls. Default: 100
406
+ * @returns Throttled function
407
+ */
408
+ const throttle = (fn, interval = 100) => {
409
+ let wait = false;
410
+ return (...args) => {
411
+ if (wait) {
412
+ return;
413
+ }
414
+ wait = true;
415
+ fn.apply(undefined, args);
416
+ setTimeout(() => {
417
+ wait = false;
418
+ }, interval);
419
+ };
420
+ };
421
+
422
+ const index$4 = /*#__PURE__*/Object.freeze({
423
+ __proto__: null,
424
+ apply: apply,
425
+ curry: curry,
426
+ debounce: debounce,
427
+ identity: identity,
428
+ memo: memo,
429
+ once: once,
430
+ pipe: pipe,
431
+ throttle: throttle,
432
+ unapply: unapply
433
+ });
434
+
435
+ /**
436
+ * Creates a function that applies the given operation to any combination of scalars and vectors
437
+ * @template T Tuple or array of numbers for the operation
438
+ * @param opFn Operation function to apply to the inputs
439
+ * @returns Function that takes quantities (scalars or vectors) and returns the calculated result
440
+ * @example
441
+ * const fn = calc((a, b, c) => a * b + c);
442
+ * fn([1, 2], 3, 4); // [7, 10]
443
+ */
444
+ const calc = (opFn) => {
445
+ return (...arr) => {
446
+ const vectors = arr.filter((el) => typeof el !== "number");
447
+ if (vectors.length === 0) {
448
+ return opFn.apply(undefined, arr);
449
+ }
450
+ const size = vectors[0].length;
451
+ if (vectors.some((v) => v.length !== size)) {
452
+ throw new Error("All vectors must have same length");
453
+ }
454
+ return from(size, (i) => {
455
+ const input = arr.map((el) => (typeof el === "number" ? el : el[i]));
456
+ return opFn.apply(undefined, input);
457
+ });
458
+ };
459
+ };
460
+
461
+ /**
462
+ * Calculates the sum of given quantities (vectors or scalars)
463
+ * @param q Quantities to add
464
+ * @returns Sum of the input quantities
465
+ * @example
466
+ * add([-4, 1, 0, 3], 5); // [1, 6, 5, 8]
467
+ * add([1, 2], [3, 4]); // [4, 6]
468
+ */
469
+ const add = calc((...arr) => arr.reduce((acc, el) => acc + el, 0));
470
+
471
+ const _round = (n, p) => {
472
+ const k = Math.pow(10, p);
473
+ return Math.round(n * k) / k;
474
+ };
475
+ /**
476
+ * Rounds a quantity (vector or scalar) to the specified number of decimal places
477
+ * @param q Quantity to round
478
+ * @param precision Number of decimal places to round to. Default: 0
479
+ * @returns Rounded quantity
480
+ */
481
+ const round = (q, precision = 0) => {
482
+ if (typeof q === "number") {
483
+ return _round(q, precision);
484
+ }
485
+ return q.map((el) => _round(el, precision));
486
+ };
487
+
488
+ /**
489
+ * Compares if two numbers are approximately equal using a custom precision
490
+ * @param a First number to compare
491
+ * @param b Second number to compare
492
+ * @param precision Number of decimal places to consider. Default: 4
493
+ * @returns True if numbers are approximately equal, false otherwise
494
+ */
495
+ const aprox = (a, b, precision = 4) => {
496
+ return round(a, precision) === round(b, precision);
497
+ };
498
+
499
+ /**
500
+ * Calculates the cumulative sum of an array of numbers
501
+ * @param arr Array of numbers to sum
502
+ * @returns Array of cumulative sums
503
+ */
504
+ const cumsum = (arr) => {
505
+ const res = Array(arr.length);
506
+ res[0] = arr[0];
507
+ for (let i = 1; i < arr.length; i++) {
508
+ res[i] = res[i - 1] + arr[i];
509
+ }
510
+ return res;
511
+ };
512
+
513
+ /**
514
+ * Calculates the division of two quantities (vectors or scalars)
515
+ * @param a Dividend(s)
516
+ * @param b Divisor(s)
517
+ * @returns Division of the input quantities
518
+ * @example
519
+ * divide([-4, 1, 0, 3], 2); // [-2, 0.5, 0, 1.5]
520
+ * divide([1, 2], [3, 4]); // [1 / 3, 0.5]
521
+ */
522
+ const divide = calc((a, b) => a / b);
523
+
524
+ /**
525
+ * Calculates the linear interpolation of monotonic increasing points (xp, fp) at given x values
526
+ * @param x Points to interpolate
527
+ * @param xp Known x-coordinates (must be increasing)
528
+ * @param fp Known y-coordinates (must be increasing, same length as xp)
529
+ * @returns Interpolated values at each x
530
+ */
531
+ const interp = (x, xp, fp) => {
532
+ if (xp.length !== fp.length) {
533
+ throw new Error("xp and fp must have the same length");
534
+ }
535
+ return x.map((xi) => {
536
+ if (xi >= xp[xp.length - 1]) {
537
+ return fp[fp.length - 1];
538
+ }
539
+ const i = binSearch(xp, xi, (el) => el);
540
+ if (i === 0) {
541
+ return fp[0];
542
+ }
543
+ const slope = (fp[i] - fp[i - 1]) / (xp[i] - xp[i - 1]);
544
+ return fp[i - 1] + slope * (xi - xp[i - 1]);
545
+ });
546
+ };
547
+
548
+ /**
549
+ * Checks if a number is within a half-open range [a, b)
550
+ * @param n The number to check
551
+ * @param a Start of the range
552
+ * @param b End of the range. Default: 0
553
+ * @returns True if n is in [a, b), false otherwise
554
+ */
555
+ const inRange = (n, a, b = 0) => {
556
+ if (a > b) {
557
+ return inRange(n, b, a);
558
+ }
559
+ return n >= a && n < b;
560
+ };
561
+
562
+ /**
563
+ * Calculates the multiplication of given quantities (vectors or scalars)
564
+ * @param q Quantities to multiply
565
+ * @returns Product of the input quantities
566
+ * @example
567
+ * multiply([-4, 1, 0, 3], 3); // => [-12, 3, 0, 9]
568
+ * multiply([1, 2], [3, 4]); // => [3, 8]
569
+ */
570
+ const multiply = calc((...arr) => arr.reduce((acc, el) => acc * el, 1));
571
+
572
+ /**
573
+ * Calculates the sum of an array of numbers
574
+ * @param arr Numbers to sum
575
+ * @returns Sum of all numbers in the array
576
+ */
577
+ const sum = (arr) => {
578
+ return arr.reduce((acc, el) => acc + el, 0);
579
+ };
580
+
581
+ /**
582
+ * Calculates the mean (average) of an array of numbers. Supports optional weighted mean
583
+ * @param arr Array of numbers
584
+ * @param weights Optional array of weights
585
+ * @returns Mean of the numbers
586
+ */
587
+ const mean = (arr, weights) => {
588
+ if (weights === undefined) {
589
+ return sum(arr) / arr.length;
590
+ }
591
+ if (arr.length !== weights.length) {
592
+ throw new Error("Nums and weights must have the same length");
593
+ }
594
+ return sum(multiply(arr, weights)) / sum(weights);
595
+ };
596
+
597
+ const _linear = (x, p) => {
598
+ const Pnorm = divide(p, 100);
599
+ const step = 1 / (x.length - 1);
600
+ const xp = range(0, 1 + step, step);
601
+ return interp(Pnorm, xp, x.sort());
602
+ };
603
+ const _weighted = (x, p, w) => {
604
+ if (w.length !== x.length) {
605
+ throw new Error("Weights must be the same length as the array");
606
+ }
607
+ else if (w.some((v) => v < 0)) {
608
+ throw new Error("Weights must be non-negative");
609
+ }
610
+ const X = sort(transpose([x, w]), (el) => el[0]);
611
+ const [Xsorted, Wsorted] = transpose(X);
612
+ const Wcum = cumsum(Wsorted);
613
+ const Wtotal = Wcum[Wcum.length - 1];
614
+ const Wnorm = divide(Wcum, Wtotal);
615
+ const Pnorm = divide(p, 100);
616
+ let i = 0;
617
+ return Pnorm.map((pi) => {
618
+ i = binSearch(Wnorm, pi, (el) => el, i);
619
+ return Xsorted[i];
620
+ });
621
+ };
622
+ /**
623
+ * Calculates the given percentile(s) of an array of numbers
624
+ * Supports both linear interpolation and weighted percentiles
625
+ * @param x Array of numbers
626
+ * @param p Percentile(s) to compute (number or array of numbers, 0–100)
627
+ * @param weights Optional array of weights (same length as x)
628
+ * @returns Computed percentile value(s)
629
+ */
630
+ const percentile = (x, p, weights) => {
631
+ if (typeof p === "number") {
632
+ return percentile(x, [p], weights)[0];
633
+ }
634
+ if (p.some((v) => v < 0 || v > 100)) {
635
+ throw new Error("Percentiles must be between 0 and 100");
636
+ }
637
+ if (weights === undefined) {
638
+ return _linear(x, p);
639
+ }
640
+ return _weighted(x, p, weights);
641
+ };
642
+
643
+ /**
644
+ * Calculates the median of an array of numbers
645
+ * @param arr Array of numbers
646
+ * @param weights Optional array of weights
647
+ * @returns Median value
648
+ */
649
+ const median = (arr, weights) => {
650
+ return percentile(arr, 50, weights);
651
+ };
652
+
653
+ /**
654
+ * Calculates the modulo of two quantities (vectors or scalars)
655
+ * @param x Dividend(s)
656
+ * @param modulo Divisor(s)
657
+ * @returns Modulo, matching the input shape
658
+ * @example
659
+ * mod(5, 3); // 2
660
+ * mod([2, 3, 4], 3); // [2, 0, 1]
661
+ * mod([4, 5], [2, 3]); // [0, 2]
662
+ */
663
+ const mod = calc((x, modulo) => {
664
+ const m = Math.abs(modulo);
665
+ return ((x % m) + m) % m;
666
+ });
667
+
668
+ /**
669
+ * Calculates the exponentiation of two quantities (vectors or scalars)
670
+ * @param base Base quantity
671
+ * @param exp Exponent quantity
672
+ * @returns base raised to the power of exp
673
+ */
674
+ const pow = calc((base, exp) => Math.pow(base, exp));
675
+
676
+ /**
677
+ * Calculates the subtraction of two quantities (vectors or scalars)
678
+ * @param a Minuend quantity
679
+ * @param b Subtrahend quantity
680
+ * @returns Subtraction of `b` from `a`
681
+ */
682
+ const subtract = calc((a, b) => a - b);
683
+
684
+ const index$3 = /*#__PURE__*/Object.freeze({
685
+ __proto__: null,
686
+ add: add,
687
+ aprox: aprox,
688
+ calc: calc,
689
+ cumsum: cumsum,
690
+ divide: divide,
691
+ inRange: inRange,
692
+ interp: interp,
693
+ mean: mean,
694
+ median: median,
695
+ mod: mod,
696
+ multiply: multiply,
697
+ percentile: percentile,
698
+ pow: pow,
699
+ round: round,
700
+ subtract: subtract,
701
+ sum: sum
702
+ });
703
+
704
+ /**
705
+ * Retrieves a strongly-typed array of the entries (key, value) of an object
706
+ * @param obj Object whose entries are to be retrieved
707
+ * @returns Array of key-value pairs from the object
708
+ */
709
+ const entries = Object.entries;
710
+
711
+ /**
712
+ * Checks if the provided value is a non-null object
713
+ * @param el Value to check
714
+ * @returns True if `el` is a non-null object, otherwise false
715
+ */
716
+ const isObj = (el) => {
717
+ return typeof el === "object" && el !== null;
718
+ };
719
+
720
+ /**
721
+ * Creates a deep copy of the provided object or array
722
+ * @param obj Object or array to copy
723
+ * @returns Deep copy of the input
724
+ */
725
+ const copy = (obj) => {
726
+ if (!isObj(obj)) {
727
+ return obj;
728
+ }
729
+ const res = (Array.isArray(obj) ? [] : {});
730
+ entries(obj).forEach(([key, val]) => {
731
+ res[key] = copy(val);
732
+ });
733
+ return res;
734
+ };
735
+
736
+ /**
737
+ * Retrieves a strongly-typed array of the keys of an object
738
+ * @param obj Object whose keys are to be retrieved
739
+ * @returns Array of the object's keys
740
+ */
741
+ const keys = Object.keys;
742
+
743
+ const deepEqual = (args) => {
744
+ if (args.every((arg) => arg === args[0])) {
745
+ return true;
746
+ }
747
+ if (!args.every(isObj)) {
748
+ return false;
749
+ }
750
+ const objs = args;
751
+ const objsKeys = objs.map(keys);
752
+ if (!deepEqual(objsKeys.map((key) => key.length))) {
753
+ return false;
754
+ }
755
+ const keysUnion = union.apply(undefined, objsKeys);
756
+ if (keysUnion.size !== objsKeys[0].length) {
757
+ return false;
758
+ }
759
+ return objsKeys[0].every((key) => {
760
+ const vals = objs.map((obj) => obj[key]);
761
+ return deepEqual(vals);
762
+ });
763
+ };
764
+ /**
765
+ * Performs a deep comparison between multiple objects to determine if they are equal
766
+ * @param objs Objects to compare
767
+ * @returns True if all objects are deeply equal, false otherwise
768
+ */
769
+ const equal = unapply(deepEqual);
770
+
771
+ /**
772
+ * Checks if an object has all specified properties
773
+ * @param obj Object to check
774
+ * @param keys Property keys to look for
775
+ * @returns True if all keys exist on the object, false otherwise
776
+ */
777
+ const has = (obj, ...keys) => {
778
+ return keys.every((key) => Object.prototype.hasOwnProperty.call(obj, key));
779
+ };
780
+
781
+ /**
782
+ * Gets a value at a nested path of an object or array
783
+ * @param obj Source object
784
+ * @param path Dot-separated path string
785
+ * @param fallback Value to return if the path is not found
786
+ * @returns Value at the specified path or the fallback
787
+ */
788
+ const get = (obj, path, fallback) => {
789
+ let val = obj;
790
+ for (const key of path.split(".")) {
791
+ if (isObj(val) && has(val, key)) {
792
+ val = val[key];
793
+ }
794
+ else {
795
+ return fallback;
796
+ }
797
+ }
798
+ return val;
799
+ };
800
+
801
+ /**
802
+ * Creates a strongly-typed object from the shallow merge of deep copies of two objects
803
+ * If both objects have the same property, the value from the second object overwrites the first
804
+ * @param a First object to merge
805
+ * @param b Second object to merge
806
+ * @returns The merged object with properties from both a and b
807
+ */
808
+ const merge = (a, b) => {
809
+ return Object.assign(copy(a), copy(b));
810
+ };
811
+
812
+ /**
813
+ * Creates a deep copy of an object without the specified keys
814
+ * @param obj Source object
815
+ * @param keys Array of keys to omit from the result
816
+ * @returns New object without the specified keys
817
+ */
818
+ const omit = (obj, keys) => {
819
+ const newObj = copy(obj);
820
+ for (const key of keys) {
821
+ delete newObj[key];
822
+ }
823
+ return newObj;
824
+ };
825
+
826
+ /**
827
+ * Creates a deep copy of an object with only the specified keys
828
+ * @param obj Source object
829
+ * @param keys Array of keys to pick from the object
830
+ * @returns New object with only the picked keys
831
+ */
832
+ const pick = (obj, keys) => {
833
+ const res = {};
834
+ for (const key of keys) {
835
+ res[key] = copy(obj[key]);
836
+ }
837
+ return res;
838
+ };
839
+
840
+ /**
841
+ * Sets a value at a nested path of an object, creating nested objects if needed
842
+ * @param obj Target object to modify
843
+ * @param path Dot-separated string path where the value should be set
844
+ * @param value Value to set at the specified path
845
+ * @returns Modified object with the value set at the given path
846
+ */
847
+ const set = (obj, path, value) => {
848
+ let val = obj;
849
+ const keys = path.split(".");
850
+ const end = keys.length - 1;
851
+ for (let i = 0; i < end; i++) {
852
+ const key = keys[i];
853
+ if (!isObj(val[key])) {
854
+ val[key] = {};
855
+ }
856
+ val = val[key];
857
+ }
858
+ val[keys[end]] = value;
859
+ return obj;
860
+ };
861
+
862
+ /**
863
+ * Retrieves a strongly-typed array of the values of an object
864
+ * @param obj Source object
865
+ * @returns Array of the object's values
866
+ */
867
+ const vals = Object.values;
868
+
869
+ const index$2 = /*#__PURE__*/Object.freeze({
870
+ __proto__: null,
871
+ copy: copy,
872
+ entries: entries,
873
+ equal: equal,
874
+ get: get,
875
+ has: has,
876
+ isObj: isObj,
877
+ keys: keys,
878
+ merge: merge,
879
+ omit: omit,
880
+ pick: pick,
881
+ set: set,
882
+ vals: vals
883
+ });
884
+
885
+ /**
886
+ * Returns a random integer between two numbers
887
+ * @param a Lower bound (inclusive)
888
+ * @param b Upper bound (exclusive). Default: 0
889
+ * @returns Random integer between a and b
890
+ */
891
+ const randInt = (a, b = 0) => {
892
+ if (!Number.isInteger(a) || !Number.isInteger(b)) {
893
+ throw Error("a and b must be integers");
894
+ }
895
+ return Math.floor(Math.random() * (b - a) + a);
896
+ };
897
+
898
+ /**
899
+ * Selects a random index based on the provided weights
900
+ * @param weights Array of non-negative weights
901
+ * @returns Selected index
902
+ */
903
+ const randWeight = (weights) => {
904
+ if (weights.length === 0) {
905
+ throw new Error("Weights array cannot be empty");
906
+ }
907
+ if (weights.some((w) => w < 0)) {
908
+ throw new Error("Weights array cannot contain negative values");
909
+ }
910
+ const wAccum = cumsum(weights);
911
+ const wTotal = wAccum[wAccum.length - 1];
912
+ if (wTotal === 0) {
913
+ throw new Error("Total weight must be greater than zero");
914
+ }
915
+ const r = Math.random() * wTotal;
916
+ return binSearch(wAccum, r, (el) => el);
917
+ };
918
+
919
+ const op = (arr, size, pick) => {
920
+ const n = Math.min(size, arr.length);
921
+ const res = arr.slice();
922
+ const end = res.length - n;
923
+ for (let i = res.length - 1; i > end; i--) {
924
+ const idx = pick(i + 1);
925
+ [res[i], res[idx]] = [res[idx], res[i]];
926
+ }
927
+ return n === arr.length ? res : res.slice(0, n);
928
+ };
929
+ const fisherYates = (data, size, weights) => {
930
+ if (size <= 0) {
931
+ return [];
932
+ }
933
+ if (weights === undefined) {
934
+ return op(data, size, (n) => Math.floor(Math.random() * n));
935
+ }
936
+ if (weights.length !== data.length) {
937
+ throw new Error("Weights must have the same length as the data array");
938
+ }
939
+ if (weights.some((w) => w < 0)) {
940
+ throw new Error("Weights cannot contain negative values.");
941
+ }
942
+ const w = weights.slice();
943
+ return op(data, size, () => {
944
+ const idx = randWeight(w);
945
+ w[idx] = 0;
946
+ return idx;
947
+ });
948
+ };
949
+
950
+ /**
951
+ * Samples elements from an array randomly, optionally using weights to influence selection
952
+ * @param data Array to sample from
953
+ * @param size Number of elements to sample
954
+ * @param weights Optional array of weights for weighted sampling
955
+ * @returns New array containing the sampled elements
956
+ */
957
+ const sample = fisherYates;
958
+
959
+ /**
960
+ * Shuffles an array randomly, optionally using weights to influence the
961
+ * likelihood of selecting elements first
962
+ * @param data Array to shuffle
963
+ * @param weights Optional array of weights for weighted shuffling
964
+ * @returns New array with the elements shuffled
965
+ */
966
+ const shuffle = (data, weights) => {
967
+ return fisherYates(data, data.length, weights);
968
+ };
969
+
970
+ const index$1 = /*#__PURE__*/Object.freeze({
971
+ __proto__: null,
972
+ randInt: randInt,
973
+ randWeight: randWeight,
974
+ sample: sample,
975
+ shuffle: shuffle
976
+ });
977
+
978
+ const words = (str) => {
979
+ return str
980
+ .replace(/([a-z])([A-Z])/g, "$1 $2") // Split camelCase and PascalCase
981
+ .replace(/([A-Z])([A-Z][a-z])/g, "$1 $2") // Split UPPERPascal > UPPER Pascal
982
+ .replace(/([0-9]+)/g, " $1 ")
983
+ .split(/[_-\s]+/)
984
+ .filter(Boolean);
985
+ };
986
+
987
+ /**
988
+ * Capitalizes the first letter of a string and converts the rest to lowercase
989
+ * @param str String to capitalize
990
+ * @returns Capitalized string
991
+ */
992
+ const capitalize = (str) => {
993
+ return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
994
+ };
995
+
996
+ /**
997
+ * Converts a string to camelCase
998
+ * @param str String to convert
999
+ * @returns camelCase version of the input string
1000
+ */
1001
+ const camel = (str) => {
1002
+ const w = words(str).map(capitalize);
1003
+ if (w.length === 0) {
1004
+ return "";
1005
+ }
1006
+ w[0] = w[0].toLowerCase();
1007
+ return w.join("");
1008
+ };
1009
+
1010
+ /**
1011
+ * Converts a string to kebab-case
1012
+ * @param str String to convert
1013
+ * @returns kebab-case version of the input string
1014
+ */
1015
+ const kebab = (str) => {
1016
+ return words(str)
1017
+ .map((str) => str.toLowerCase())
1018
+ .join("-");
1019
+ };
1020
+
1021
+ /**
1022
+ * Converts a string to PascalCase
1023
+ * @param str String to convert
1024
+ * @returns PascalCase version of the input string
1025
+ */
1026
+ const pascal = (str) => {
1027
+ return words(str).map(capitalize).join("");
1028
+ };
1029
+
1030
+ /**
1031
+ * Converts a string to snake_case
1032
+ * @param str String to convert
1033
+ * @returns snake_case version of the input string
1034
+ */
1035
+ const snake = (str) => {
1036
+ return words(str)
1037
+ .map((str) => str.toLowerCase())
1038
+ .join("_");
1039
+ };
1040
+
1041
+ /**
1042
+ * Replaces placeholders in the format `{{path.to.value}}` within a string
1043
+ * with corresponding values from the provided data object
1044
+ * @param str String containing placeholders to replace
1045
+ * @param data Object with values for the placeholders
1046
+ * @returns String with placeholders replaced by their values
1047
+ */
1048
+ const template = (str, data) => {
1049
+ return str.replace(/\{\{([a-zA-Z0-9._]+)\}\}/g, (_, path) => {
1050
+ return get(data, path, "");
1051
+ });
1052
+ };
1053
+
1054
+ /**
1055
+ * Removes leading and trailing whitespace or specified characters from a string
1056
+ * @param str String to trim
1057
+ * @param chars Optional characters to trim from the string. Default: whitespace
1058
+ * @returns Trimmed string
1059
+ */
1060
+ const trim = (str, chars = " ") => {
1061
+ const reg = new RegExp(`^[${chars}]+|[${chars}]+$`, "g");
1062
+ return str.replace(reg, "");
1063
+ };
1064
+
1065
+ const index = /*#__PURE__*/Object.freeze({
1066
+ __proto__: null,
1067
+ camel: camel,
1068
+ capitalize: capitalize,
1069
+ kebab: kebab,
1070
+ pascal: pascal,
1071
+ snake: snake,
1072
+ template: template,
1073
+ trim: trim
1074
+ });
1075
+
1076
+ /**
1077
+ * @deprecated Time module is deprecated and may be removed in future releases
1078
+ */
1079
+ class Time {
1080
+ constructor(val, unit = "ms") {
1081
+ this.date = new Date();
1082
+ if (val !== undefined) {
1083
+ this.set(val, unit);
1084
+ }
1085
+ }
1086
+ static convert(val, from, to = "ms") {
1087
+ const ms = Math.round(Time.UNITS[from] * val);
1088
+ return ms / Time.UNITS[to];
1089
+ }
1090
+ add(val, unit = "ms") {
1091
+ return this.set(this.get(unit) + val, unit);
1092
+ }
1093
+ format(mode = "full", local = Time.locales, opts = {}) {
1094
+ const options = merge(Time.formatOptions[mode], opts);
1095
+ return this.date.toLocaleString(local, options);
1096
+ }
1097
+ get(unit = "ms") {
1098
+ return Time.convert(this.date.getTime(), "ms", unit);
1099
+ }
1100
+ getDayTime(unit = "ms") {
1101
+ return Time.convert(this.get("d") % 1, "d", unit);
1102
+ }
1103
+ set(val, unit = "ms") {
1104
+ return this.date.setTime(Time.convert(val, unit));
1105
+ }
1106
+ setDayTime(val, unit = "ms") {
1107
+ return this.add(val - this.getDayTime(unit), unit);
1108
+ }
1109
+ toDate() {
1110
+ return new Date(this.date);
1111
+ }
1112
+ }
1113
+ Time.UNITS = {
1114
+ d: 864e5,
1115
+ h: 36e5,
1116
+ m: 6e4,
1117
+ ms: 1,
1118
+ s: 1e3
1119
+ };
1120
+ Time.formatOptions = {
1121
+ date: {
1122
+ dateStyle: "medium"
1123
+ },
1124
+ full: {
1125
+ dateStyle: "short",
1126
+ timeStyle: "short"
1127
+ },
1128
+ time: {
1129
+ timeStyle: "medium"
1130
+ }
1131
+ };
1132
+
1133
+ exports.Time = Time;
1134
+ exports.add = add;
1135
+ exports.apply = apply;
1136
+ exports.aprox = aprox;
1137
+ exports.arr = index$5;
1138
+ exports.binSearch = binSearch;
1139
+ exports.calc = calc;
1140
+ exports.camel = camel;
1141
+ exports.capitalize = capitalize;
1142
+ exports.chunk = chunk;
1143
+ exports.copy = copy;
1144
+ exports.cumsum = cumsum;
1145
+ exports.curry = curry;
1146
+ exports.debounce = debounce;
1147
+ exports.divide = divide;
1148
+ exports.entries = entries;
1149
+ exports.equal = equal;
1150
+ exports.fill = fill;
1151
+ exports.find = find;
1152
+ exports.findAll = findAll;
1153
+ exports.findAllIdx = findAllIdx;
1154
+ exports.findIdx = findIdx;
1155
+ exports.from = from;
1156
+ exports.func = index$4;
1157
+ exports.get = get;
1158
+ exports.group = group;
1159
+ exports.groupBy = groupBy;
1160
+ exports.has = has;
1161
+ exports.identity = identity;
1162
+ exports.inRange = inRange;
1163
+ exports.interp = interp;
1164
+ exports.isObj = isObj;
1165
+ exports.kebab = kebab;
1166
+ exports.keys = keys;
1167
+ exports.math = index$3;
1168
+ exports.max = max;
1169
+ exports.mean = mean;
1170
+ exports.median = median;
1171
+ exports.memo = memo;
1172
+ exports.merge = merge;
1173
+ exports.min = min;
1174
+ exports.mod = mod;
1175
+ exports.multiply = multiply;
1176
+ exports.obj = index$2;
1177
+ exports.omit = omit;
1178
+ exports.once = once;
1179
+ exports.pascal = pascal;
1180
+ exports.percentile = percentile;
1181
+ exports.pick = pick;
1182
+ exports.pipe = pipe;
1183
+ exports.pow = pow;
1184
+ exports.rand = index$1;
1185
+ exports.randInt = randInt;
1186
+ exports.randWeight = randWeight;
1187
+ exports.range = range;
1188
+ exports.round = round;
1189
+ exports.sample = sample;
1190
+ exports.set = set;
1191
+ exports.shuffle = shuffle;
1192
+ exports.snake = snake;
1193
+ exports.sort = sort;
1194
+ exports.str = index;
1195
+ exports.subtract = subtract;
1196
+ exports.sum = sum;
1197
+ exports.template = template;
1198
+ exports.throttle = throttle;
1199
+ exports.transpose = transpose;
1200
+ exports.trim = trim;
1201
+ exports.unapply = unapply;
1202
+ exports.union = union;
1203
+ exports.unique = unique;
1204
+ exports.vals = vals;
1205
+ exports.zip = zip;
1206
+ //# sourceMappingURL=index.cjs.js.map