vscroll 1.5.3 → 1.5.4

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 (335) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +283 -273
  3. package/dist/bundles/vscroll.esm5.js +5553 -5525
  4. package/dist/bundles/vscroll.esm5.js.map +1 -1
  5. package/dist/bundles/vscroll.esm5.min.js +2 -2
  6. package/dist/bundles/vscroll.esm5.min.js.map +1 -1
  7. package/dist/bundles/vscroll.esm6.js +5040 -5015
  8. package/dist/bundles/vscroll.esm6.js.map +1 -1
  9. package/dist/bundles/vscroll.esm6.min.js +2 -2
  10. package/dist/bundles/vscroll.esm6.min.js.map +1 -1
  11. package/dist/bundles/vscroll.umd.js +5554 -5526
  12. package/dist/bundles/vscroll.umd.js.map +1 -1
  13. package/dist/bundles/vscroll.umd.min.js +2 -2
  14. package/dist/bundles/vscroll.umd.min.js.map +1 -1
  15. package/dist/esm2015/classes/adapter/context.js +43 -43
  16. package/dist/esm2015/classes/adapter/context.js.map +1 -1
  17. package/dist/esm2015/classes/adapter/props.js +268 -268
  18. package/dist/esm2015/classes/adapter/props.js.map +1 -1
  19. package/dist/esm2015/classes/adapter/wanted.js +28 -28
  20. package/dist/esm2015/classes/adapter/wanted.js.map +1 -1
  21. package/dist/esm2015/classes/adapter.js +455 -442
  22. package/dist/esm2015/classes/adapter.js.map +1 -1
  23. package/dist/esm2015/classes/buffer/cache.js +246 -246
  24. package/dist/esm2015/classes/buffer/cache.js.map +1 -1
  25. package/dist/esm2015/classes/buffer/checkCall.js +48 -48
  26. package/dist/esm2015/classes/buffer/checkCall.js.map +1 -1
  27. package/dist/esm2015/classes/buffer/defaultSize.js +127 -127
  28. package/dist/esm2015/classes/buffer/defaultSize.js.map +1 -1
  29. package/dist/esm2015/classes/buffer.js +342 -342
  30. package/dist/esm2015/classes/buffer.js.map +1 -1
  31. package/dist/esm2015/classes/datasource.js +28 -28
  32. package/dist/esm2015/classes/domRoutines.js +166 -166
  33. package/dist/esm2015/classes/domRoutines.js.map +1 -1
  34. package/dist/esm2015/classes/item.js +61 -61
  35. package/dist/esm2015/classes/item.js.map +1 -1
  36. package/dist/esm2015/classes/logger.js +186 -186
  37. package/dist/esm2015/classes/logger.js.map +1 -1
  38. package/dist/esm2015/classes/paddings.js +72 -72
  39. package/dist/esm2015/classes/reactive.js +54 -54
  40. package/dist/esm2015/classes/reactive.js.map +1 -1
  41. package/dist/esm2015/classes/settings.js +39 -39
  42. package/dist/esm2015/classes/settings.js.map +1 -1
  43. package/dist/esm2015/classes/state/clip.js +16 -16
  44. package/dist/esm2015/classes/state/clip.js.map +1 -1
  45. package/dist/esm2015/classes/state/cycle.js +60 -60
  46. package/dist/esm2015/classes/state/cycle.js.map +1 -1
  47. package/dist/esm2015/classes/state/fetch.js +122 -122
  48. package/dist/esm2015/classes/state/fetch.js.map +1 -1
  49. package/dist/esm2015/classes/state/render.js +14 -14
  50. package/dist/esm2015/classes/state/render.js.map +1 -1
  51. package/dist/esm2015/classes/state/scroll.js +30 -30
  52. package/dist/esm2015/classes/state/scroll.js.map +1 -1
  53. package/dist/esm2015/classes/state.js +59 -59
  54. package/dist/esm2015/classes/viewport.js +72 -72
  55. package/dist/esm2015/classes/viewport.js.map +1 -1
  56. package/dist/esm2015/index.js +8 -8
  57. package/dist/esm2015/index.js.map +1 -1
  58. package/dist/esm2015/inputs/adapter.js +230 -230
  59. package/dist/esm2015/inputs/adapter.js.map +1 -1
  60. package/dist/esm2015/inputs/common.js +11 -11
  61. package/dist/esm2015/inputs/common.js.map +1 -1
  62. package/dist/esm2015/inputs/datasource.js +20 -20
  63. package/dist/esm2015/inputs/datasource.js.map +1 -1
  64. package/dist/esm2015/inputs/index.js +6 -6
  65. package/dist/esm2015/inputs/index.js.map +1 -1
  66. package/dist/esm2015/inputs/settings.js +146 -146
  67. package/dist/esm2015/inputs/settings.js.map +1 -1
  68. package/dist/esm2015/inputs/validation.js +374 -374
  69. package/dist/esm2015/inputs/validation.js.map +1 -1
  70. package/dist/esm2015/interfaces/adapter.js +1 -1
  71. package/dist/esm2015/interfaces/datasource.js +1 -1
  72. package/dist/esm2015/interfaces/datasource.js.map +1 -1
  73. package/dist/esm2015/interfaces/index.js +1 -1
  74. package/dist/esm2015/interfaces/index.js.map +1 -1
  75. package/dist/esm2015/interfaces/item.js +1 -1
  76. package/dist/esm2015/interfaces/item.js.map +1 -1
  77. package/dist/esm2015/interfaces/process.js +1 -1
  78. package/dist/esm2015/interfaces/routines.js +1 -1
  79. package/dist/esm2015/interfaces/routines.js.map +1 -1
  80. package/dist/esm2015/interfaces/settings.js +1 -1
  81. package/dist/esm2015/interfaces/state.js +1 -1
  82. package/dist/esm2015/interfaces/validation.js +1 -1
  83. package/dist/esm2015/interfaces/validation.js.map +1 -1
  84. package/dist/esm2015/interfaces/workflow.js +1 -1
  85. package/dist/esm2015/interfaces/workflow.js.map +1 -1
  86. package/dist/esm2015/processes/adapter/append.js +35 -35
  87. package/dist/esm2015/processes/adapter/append.js.map +1 -1
  88. package/dist/esm2015/processes/adapter/check.js +32 -32
  89. package/dist/esm2015/processes/adapter/check.js.map +1 -1
  90. package/dist/esm2015/processes/adapter/clip.js +12 -12
  91. package/dist/esm2015/processes/adapter/clip.js.map +1 -1
  92. package/dist/esm2015/processes/adapter/fix.js +77 -77
  93. package/dist/esm2015/processes/adapter/fix.js.map +1 -1
  94. package/dist/esm2015/processes/adapter/insert.js +73 -73
  95. package/dist/esm2015/processes/adapter/insert.js.map +1 -1
  96. package/dist/esm2015/processes/adapter/reload.js +19 -20
  97. package/dist/esm2015/processes/adapter/reload.js.map +1 -1
  98. package/dist/esm2015/processes/adapter/remove.js +102 -102
  99. package/dist/esm2015/processes/adapter/remove.js.map +1 -1
  100. package/dist/esm2015/processes/adapter/replace.js +39 -39
  101. package/dist/esm2015/processes/adapter/replace.js.map +1 -1
  102. package/dist/esm2015/processes/adapter/reset.js +35 -35
  103. package/dist/esm2015/processes/adapter/reset.js.map +1 -1
  104. package/dist/esm2015/processes/adapter/update.js +43 -43
  105. package/dist/esm2015/processes/adapter/update.js.map +1 -1
  106. package/dist/esm2015/processes/adjust.js +141 -141
  107. package/dist/esm2015/processes/clip.js +49 -49
  108. package/dist/esm2015/processes/end.js +52 -52
  109. package/dist/esm2015/processes/end.js.map +1 -1
  110. package/dist/esm2015/processes/fetch.js +90 -90
  111. package/dist/esm2015/processes/fetch.js.map +1 -1
  112. package/dist/esm2015/processes/index.js +23 -23
  113. package/dist/esm2015/processes/init.js +14 -14
  114. package/dist/esm2015/processes/init.js.map +1 -1
  115. package/dist/esm2015/processes/misc/base.js +30 -30
  116. package/dist/esm2015/processes/misc/base.js.map +1 -1
  117. package/dist/esm2015/processes/misc/enums.js +35 -35
  118. package/dist/esm2015/processes/misc/enums.js.map +1 -1
  119. package/dist/esm2015/processes/misc/index.js +2 -2
  120. package/dist/esm2015/processes/misc/index.js.map +1 -1
  121. package/dist/esm2015/processes/postFetch.js +64 -64
  122. package/dist/esm2015/processes/postFetch.js.map +1 -1
  123. package/dist/esm2015/processes/preClip.js +85 -85
  124. package/dist/esm2015/processes/preClip.js.map +1 -1
  125. package/dist/esm2015/processes/preFetch.js +240 -240
  126. package/dist/esm2015/processes/preFetch.js.map +1 -1
  127. package/dist/esm2015/processes/render.js +54 -54
  128. package/dist/esm2015/processes/render.js.map +1 -1
  129. package/dist/esm2015/processes/scroll.js +97 -97
  130. package/dist/esm2015/processes/scroll.js.map +1 -1
  131. package/dist/esm2015/processes/start.js +11 -11
  132. package/dist/esm2015/processes/start.js.map +1 -1
  133. package/dist/esm2015/scroller.js +75 -69
  134. package/dist/esm2015/scroller.js.map +1 -1
  135. package/dist/esm2015/version.js +4 -4
  136. package/dist/esm2015/version.js.map +1 -1
  137. package/dist/esm2015/workflow-transducer.js +210 -210
  138. package/dist/esm2015/workflow-transducer.js.map +1 -1
  139. package/dist/esm2015/workflow.js +158 -151
  140. package/dist/esm2015/workflow.js.map +1 -1
  141. package/dist/esm5/classes/adapter/context.js +50 -50
  142. package/dist/esm5/classes/adapter/context.js.map +1 -1
  143. package/dist/esm5/classes/adapter/props.js +268 -268
  144. package/dist/esm5/classes/adapter/props.js.map +1 -1
  145. package/dist/esm5/classes/adapter/wanted.js +29 -29
  146. package/dist/esm5/classes/adapter/wanted.js.map +1 -1
  147. package/dist/esm5/classes/adapter.js +504 -490
  148. package/dist/esm5/classes/adapter.js.map +1 -1
  149. package/dist/esm5/classes/buffer/cache.js +260 -260
  150. package/dist/esm5/classes/buffer/cache.js.map +1 -1
  151. package/dist/esm5/classes/buffer/checkCall.js +56 -56
  152. package/dist/esm5/classes/buffer/checkCall.js.map +1 -1
  153. package/dist/esm5/classes/buffer/defaultSize.js +145 -145
  154. package/dist/esm5/classes/buffer/defaultSize.js.map +1 -1
  155. package/dist/esm5/classes/buffer.js +409 -409
  156. package/dist/esm5/classes/buffer.js.map +1 -1
  157. package/dist/esm5/classes/datasource.js +37 -37
  158. package/dist/esm5/classes/domRoutines.js +182 -182
  159. package/dist/esm5/classes/domRoutines.js.map +1 -1
  160. package/dist/esm5/classes/item.js +76 -76
  161. package/dist/esm5/classes/item.js.map +1 -1
  162. package/dist/esm5/classes/logger.js +210 -210
  163. package/dist/esm5/classes/logger.js.map +1 -1
  164. package/dist/esm5/classes/paddings.js +80 -80
  165. package/dist/esm5/classes/reactive.js +69 -69
  166. package/dist/esm5/classes/reactive.js.map +1 -1
  167. package/dist/esm5/classes/settings.js +47 -47
  168. package/dist/esm5/classes/settings.js.map +1 -1
  169. package/dist/esm5/classes/state/clip.js +22 -22
  170. package/dist/esm5/classes/state/clip.js.map +1 -1
  171. package/dist/esm5/classes/state/cycle.js +75 -75
  172. package/dist/esm5/classes/state/cycle.js.map +1 -1
  173. package/dist/esm5/classes/state/fetch.js +148 -148
  174. package/dist/esm5/classes/state/fetch.js.map +1 -1
  175. package/dist/esm5/classes/state/render.js +20 -20
  176. package/dist/esm5/classes/state/render.js.map +1 -1
  177. package/dist/esm5/classes/state/scroll.js +32 -32
  178. package/dist/esm5/classes/state/scroll.js.map +1 -1
  179. package/dist/esm5/classes/state.js +66 -66
  180. package/dist/esm5/classes/viewport.js +79 -79
  181. package/dist/esm5/classes/viewport.js.map +1 -1
  182. package/dist/esm5/index.js +8 -8
  183. package/dist/esm5/index.js.map +1 -1
  184. package/dist/esm5/inputs/adapter.js +231 -231
  185. package/dist/esm5/inputs/adapter.js.map +1 -1
  186. package/dist/esm5/inputs/common.js +11 -11
  187. package/dist/esm5/inputs/common.js.map +1 -1
  188. package/dist/esm5/inputs/datasource.js +21 -21
  189. package/dist/esm5/inputs/datasource.js.map +1 -1
  190. package/dist/esm5/inputs/index.js +6 -6
  191. package/dist/esm5/inputs/index.js.map +1 -1
  192. package/dist/esm5/inputs/settings.js +147 -147
  193. package/dist/esm5/inputs/settings.js.map +1 -1
  194. package/dist/esm5/inputs/validation.js +396 -396
  195. package/dist/esm5/inputs/validation.js.map +1 -1
  196. package/dist/esm5/interfaces/adapter.js +1 -1
  197. package/dist/esm5/interfaces/datasource.js +1 -1
  198. package/dist/esm5/interfaces/datasource.js.map +1 -1
  199. package/dist/esm5/interfaces/index.js +1 -1
  200. package/dist/esm5/interfaces/index.js.map +1 -1
  201. package/dist/esm5/interfaces/item.js +1 -1
  202. package/dist/esm5/interfaces/item.js.map +1 -1
  203. package/dist/esm5/interfaces/process.js +1 -1
  204. package/dist/esm5/interfaces/routines.js +1 -1
  205. package/dist/esm5/interfaces/routines.js.map +1 -1
  206. package/dist/esm5/interfaces/settings.js +1 -1
  207. package/dist/esm5/interfaces/state.js +1 -1
  208. package/dist/esm5/interfaces/validation.js +1 -1
  209. package/dist/esm5/interfaces/validation.js.map +1 -1
  210. package/dist/esm5/interfaces/workflow.js +1 -1
  211. package/dist/esm5/interfaces/workflow.js.map +1 -1
  212. package/dist/esm5/processes/adapter/append.js +43 -43
  213. package/dist/esm5/processes/adapter/append.js.map +1 -1
  214. package/dist/esm5/processes/adapter/check.js +39 -39
  215. package/dist/esm5/processes/adapter/check.js.map +1 -1
  216. package/dist/esm5/processes/adapter/clip.js +19 -19
  217. package/dist/esm5/processes/adapter/clip.js.map +1 -1
  218. package/dist/esm5/processes/adapter/fix.js +89 -89
  219. package/dist/esm5/processes/adapter/fix.js.map +1 -1
  220. package/dist/esm5/processes/adapter/insert.js +81 -81
  221. package/dist/esm5/processes/adapter/insert.js.map +1 -1
  222. package/dist/esm5/processes/adapter/reload.js +26 -27
  223. package/dist/esm5/processes/adapter/reload.js.map +1 -1
  224. package/dist/esm5/processes/adapter/remove.js +115 -115
  225. package/dist/esm5/processes/adapter/remove.js.map +1 -1
  226. package/dist/esm5/processes/adapter/replace.js +47 -47
  227. package/dist/esm5/processes/adapter/replace.js.map +1 -1
  228. package/dist/esm5/processes/adapter/reset.js +42 -42
  229. package/dist/esm5/processes/adapter/reset.js.map +1 -1
  230. package/dist/esm5/processes/adapter/update.js +59 -59
  231. package/dist/esm5/processes/adapter/update.js.map +1 -1
  232. package/dist/esm5/processes/adjust.js +152 -152
  233. package/dist/esm5/processes/clip.js +60 -60
  234. package/dist/esm5/processes/end.js +63 -63
  235. package/dist/esm5/processes/end.js.map +1 -1
  236. package/dist/esm5/processes/fetch.js +101 -101
  237. package/dist/esm5/processes/fetch.js.map +1 -1
  238. package/dist/esm5/processes/index.js +23 -23
  239. package/dist/esm5/processes/init.js +21 -21
  240. package/dist/esm5/processes/init.js.map +1 -1
  241. package/dist/esm5/processes/misc/base.js +44 -44
  242. package/dist/esm5/processes/misc/base.js.map +1 -1
  243. package/dist/esm5/processes/misc/enums.js +35 -35
  244. package/dist/esm5/processes/misc/enums.js.map +1 -1
  245. package/dist/esm5/processes/misc/index.js +2 -2
  246. package/dist/esm5/processes/misc/index.js.map +1 -1
  247. package/dist/esm5/processes/postFetch.js +73 -73
  248. package/dist/esm5/processes/postFetch.js.map +1 -1
  249. package/dist/esm5/processes/preClip.js +94 -94
  250. package/dist/esm5/processes/preClip.js.map +1 -1
  251. package/dist/esm5/processes/preFetch.js +247 -247
  252. package/dist/esm5/processes/preFetch.js.map +1 -1
  253. package/dist/esm5/processes/render.js +63 -63
  254. package/dist/esm5/processes/render.js.map +1 -1
  255. package/dist/esm5/processes/scroll.js +107 -107
  256. package/dist/esm5/processes/scroll.js.map +1 -1
  257. package/dist/esm5/processes/start.js +18 -18
  258. package/dist/esm5/processes/start.js.map +1 -1
  259. package/dist/esm5/scroller.js +81 -73
  260. package/dist/esm5/scroller.js.map +1 -1
  261. package/dist/esm5/version.js +4 -4
  262. package/dist/esm5/version.js.map +1 -1
  263. package/dist/esm5/workflow-transducer.js +212 -212
  264. package/dist/esm5/workflow-transducer.js.map +1 -1
  265. package/dist/esm5/workflow.js +183 -176
  266. package/dist/esm5/workflow.js.map +1 -1
  267. package/dist/typings/classes/adapter/context.d.ts +4 -4
  268. package/dist/typings/classes/adapter/props.d.ts +47 -47
  269. package/dist/typings/classes/adapter/wanted.d.ts +14 -14
  270. package/dist/typings/classes/adapter.d.ts +74 -64
  271. package/dist/typings/classes/buffer/cache.d.ts +95 -95
  272. package/dist/typings/classes/buffer/checkCall.d.ts +12 -12
  273. package/dist/typings/classes/buffer/defaultSize.d.ts +32 -32
  274. package/dist/typings/classes/buffer.d.ts +64 -64
  275. package/dist/typings/classes/datasource.d.ts +27 -27
  276. package/dist/typings/classes/domRoutines.d.ts +33 -33
  277. package/dist/typings/classes/item.d.ts +28 -28
  278. package/dist/typings/classes/logger.d.ts +28 -28
  279. package/dist/typings/classes/paddings.d.ts +22 -22
  280. package/dist/typings/classes/reactive.d.ts +21 -21
  281. package/dist/typings/classes/settings.d.ts +119 -119
  282. package/dist/typings/classes/state/clip.d.ts +9 -9
  283. package/dist/typings/classes/state/cycle.d.ts +29 -29
  284. package/dist/typings/classes/state/fetch.d.ts +62 -62
  285. package/dist/typings/classes/state/render.d.ts +9 -9
  286. package/dist/typings/classes/state/scroll.d.ts +16 -16
  287. package/dist/typings/classes/state.d.ts +27 -27
  288. package/dist/typings/classes/viewport.d.ts +32 -32
  289. package/dist/typings/index.d.ts +9 -9
  290. package/dist/typings/inputs/adapter.d.ts +5 -5
  291. package/dist/typings/inputs/common.d.ts +9 -9
  292. package/dist/typings/inputs/datasource.d.ts +7 -7
  293. package/dist/typings/inputs/index.d.ts +6 -6
  294. package/dist/typings/inputs/settings.d.ts +41 -41
  295. package/dist/typings/inputs/validation.d.ts +83 -83
  296. package/dist/typings/interfaces/adapter.d.ts +156 -156
  297. package/dist/typings/interfaces/datasource.d.ts +26 -26
  298. package/dist/typings/interfaces/index.d.ts +10 -10
  299. package/dist/typings/interfaces/item.d.ts +8 -8
  300. package/dist/typings/interfaces/process.d.ts +35 -35
  301. package/dist/typings/interfaces/routines.d.ts +157 -157
  302. package/dist/typings/interfaces/settings.d.ts +31 -31
  303. package/dist/typings/interfaces/state.d.ts +22 -22
  304. package/dist/typings/interfaces/validation.d.ts +33 -33
  305. package/dist/typings/interfaces/workflow.d.ts +53 -53
  306. package/dist/typings/processes/adapter/append.d.ts +14 -14
  307. package/dist/typings/processes/adapter/check.d.ts +6 -6
  308. package/dist/typings/processes/adapter/clip.d.ts +7 -7
  309. package/dist/typings/processes/adapter/fix.d.ts +13 -13
  310. package/dist/typings/processes/adapter/insert.d.ts +11 -11
  311. package/dist/typings/processes/adapter/reload.d.ts +6 -6
  312. package/dist/typings/processes/adapter/remove.d.ts +11 -11
  313. package/dist/typings/processes/adapter/replace.d.ts +8 -8
  314. package/dist/typings/processes/adapter/reset.d.ts +7 -7
  315. package/dist/typings/processes/adapter/update.d.ts +8 -8
  316. package/dist/typings/processes/adjust.d.ts +10 -10
  317. package/dist/typings/processes/clip.d.ts +7 -7
  318. package/dist/typings/processes/end.d.ts +10 -10
  319. package/dist/typings/processes/fetch.d.ts +18 -18
  320. package/dist/typings/processes/index.d.ts +23 -23
  321. package/dist/typings/processes/init.d.ts +7 -7
  322. package/dist/typings/processes/misc/base.d.ts +4 -4
  323. package/dist/typings/processes/misc/enums.d.ts +32 -32
  324. package/dist/typings/processes/misc/index.d.ts +2 -2
  325. package/dist/typings/processes/postFetch.d.ts +8 -8
  326. package/dist/typings/processes/preClip.d.ts +12 -12
  327. package/dist/typings/processes/preFetch.d.ts +17 -17
  328. package/dist/typings/processes/render.d.ts +9 -9
  329. package/dist/typings/processes/scroll.d.ts +13 -13
  330. package/dist/typings/processes/start.d.ts +6 -6
  331. package/dist/typings/scroller.d.ts +26 -26
  332. package/dist/typings/version.d.ts +5 -5
  333. package/dist/typings/workflow-transducer.d.ts +2 -2
  334. package/dist/typings/workflow.d.ts +28 -28
  335. package/package.json +68 -68
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2022 Denis Hilt (https://github.com/dhilt)
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2023 Denis Hilt (https://github.com/dhilt)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,273 +1,283 @@
1
- [![build status](https://github.com/dhilt/vscroll/actions/workflows/build.yml/badge.svg)](https://github.com/dhilt/vscroll/actions/workflows/build.yml)
2
- [![npm version](https://badge.fury.io/js/vscroll.svg)](https://www.npmjs.com/package/vscroll)
3
-
4
- # VScroll
5
-
6
- - [Overview](#overview)
7
- - [Getting started](#getting-started)
8
- - [Usage](#usage)
9
- - [Consumer](#1-consumer)
10
- - [Element](#2-element)
11
- - [Datasource](#3-datasource)
12
- - [Run](#4-run)
13
- - [Routines](#5-routines)
14
- - [Live](#live)
15
- - [Adapter API](#adapter-api)
16
- - [Thanks](#thanks)
17
-
18
- ## Overview
19
-
20
- VScroll is a JavaScript library providing virtual scroll engine. Can be seen as a core for platform-specific solutions designed to represent unlimited datasets using virtualization technique. Below is the diagram of how the VScroll engine is being distributed to the end user.
21
-
22
- <br>
23
- <p align="center">
24
- <img src="https://user-images.githubusercontent.com/4365660/104845671-ad1d4b80-58e7-11eb-9cc9-4a00ebcbc9e8.png">
25
- </p>
26
-
27
- Basically, the consumer layer can be omitted and the end Application developers can use VScroll directly. This repository has a [minimal demo page](https://dhilt.github.io/vscroll/) of direct use of the VScroll library in a non-specific environment. There are also several consumer implementations built on top of VScroll:
28
-
29
- - [ngx-ui-scroll](https://github.com/dhilt/ngx-ui-scroll), Angular virtual scroll directive
30
- - [vscroll-native](https://github.com/dhilt/vscroll-native), virtual scroll module for native JavaScript applications
31
- - [Vue integration sample](https://stackblitz.com/edit/vscroll-vue-integration?file=src%2Fcomponents%2FVScroll.vue), very rough implementation for Vue
32
-
33
- ## Getting started
34
-
35
- ### CDN
36
-
37
- ```html
38
- <script src="https://cdn.jsdelivr.net/npm/vscroll"></script>
39
- <script>
40
- const workflow = new VScroll.Workflow(...);
41
- </script>
42
- ```
43
-
44
- ### NPM
45
-
46
- ```
47
- npm install vscroll
48
- ```
49
-
50
- ```js
51
- import { Workflow } from 'vscroll';
52
-
53
- const workflow = new Workflow(...);
54
- ```
55
-
56
- ## Usage
57
-
58
- The main entity distributed via `vscroll` is the `Workflow` class. Its instantiating runs the virtual scroll engine.
59
-
60
- ```js
61
- new Workflow({ consumer, element, datasource, run });
62
- ```
63
-
64
- The constructor of the `Workflow` class requires an argument of the following type:
65
-
66
- ```typescript
67
- interface WorkflowParams<ItemData> {
68
- consumer: IPackage;
69
- element: HTMLElement;
70
- datasource: IDatasource<ItemData>;
71
- run: OnDataChanged<ItemData>;
72
- Routines?: CustomRoutinesClass;
73
- }
74
- ```
75
-
76
- This is a TypeScript definition, but speaking of JavaScript, an argument object must contain 4 fields described below.
77
-
78
- ### 1. Consumer
79
-
80
- A simple data object that provides information about a consumer. It is not critical to omit this, but if the result solution is going to be published as a separate 3d-party library ("consumer"), the name and the version of the result package should be passed as follows:
81
-
82
- ```js
83
- const consumer = {
84
- name: 'my-vscroll-consumer',
85
- version: 'v1.0.0-alpha.1'
86
- };
87
- ```
88
-
89
- ### 2. Element
90
-
91
- An HTML element the `Workflow` should use as a scrollable part of the viewport. It should be present in DOM before instantiating the `Workflow`.
92
-
93
- ```js
94
- const element = document.getElementById('vscroll');
95
- ```
96
-
97
- This element should be wrapped with another container with constrained height and overflow scroll/auto. And it also must have two special padding elements marked with special attributes for the virtualization purpose.
98
-
99
- ```html
100
- <div id="viewport">
101
- <div id="vscroll">
102
- <div data-padding-backward></div>
103
- <div data-padding-forward></div>
104
- </div>
105
- </div>
106
- ```
107
-
108
- ```css
109
- #viewport {
110
- height: 300px;
111
- overflow-y: scroll;
112
- }
113
- ```
114
-
115
- ### 3. Datasource
116
-
117
- This is a special object, providing dataset items in runtime. There is a separate wiki document describing the Datasource: [github.com/dhilt/vscroll/wiki/Datasource](https://github.com/dhilt/vscroll/wiki/Datasource). Below is a short version.
118
-
119
- The Datasource can be defined in two ways. First, as an object literal:
120
-
121
- ```js
122
- const datasource = {
123
- get: (index, count, success) => {
124
- const data = [];
125
- for (let i = index; i < index + count; i++) {
126
- data.push({ id: i, text: 'item #' + i });
127
- }
128
- success(data);
129
- }
130
- };
131
- ```
132
-
133
- Second, as an instance of Datasource class which can be obtained through a special factory method. Along with the `Workflow` class, VScroll exposes the `makeDatasource` method which can be used for creating Datasource class, so the end datasource object can be instantiated via operator `new`:
134
-
135
- ```js
136
- import { makeDatasource } from 'vscroll';
137
- const Datasource = makeDatasource();
138
-
139
- const datasource = new Datasource({
140
- get: (index, length, success) =>
141
- success(Array.from({ length }).map((_, i) =>
142
- ({ id: index + i, text: 'item #' + (index + i) })
143
- ))
144
- });
145
- ```
146
-
147
- The argument of the Datasource class is the same object literal as in the first case. It has one mandatory field which is the core of the App-Scroller integration: method `get`. The `Workflow` requests data via the `Datasource.get` method in runtime.
148
-
149
- For more solid understanding the concept of the Datasource with examples, please, refer to [the Datasource doc](https://github.com/dhilt/vscroll/wiki/Datasource).
150
-
151
- ### 4. Run
152
-
153
- A callback that is called every time the Workflow decides that the UI needs to be changed. Its argument is a list of items to be present in the UI. This is a consumer responsibility to detect changes and display them in the UI.
154
-
155
- ```js
156
- run: (newItems) => {
157
- // assume oldItems contains a list of items that are currently present in the UI
158
- if (!newItems.length && !oldItems.length) {
159
- return;
160
- }
161
- // make newItems to be present in the UI instead of oldItems
162
- processItems(newItems, oldItems);
163
- oldItems = newItems;
164
- };
165
- ```
166
-
167
- Each item (in both `newItems` and `oldItems` lists) is an instance of the [Item class](https://github.com/dhilt/vscroll/blob/v1.5.0/src/classes/item.ts) implementing the [Item interface](https://github.com/dhilt/vscroll/blob/v1.5.0/src/interfaces/item.ts), whose props can be used for proper implementation of the `run` callback:
168
-
169
- |Name|Type|Description|
170
- |:--|:--|:----|
171
- |element|_HTMLElement_|HTML element associated with the item|
172
- |$index|_number_|Integer index of the item in the Datasource. Correlates with the first argument of the Datasource.get method|
173
- |data|_Data_|Data (contents) of the item. This is what the Datasource.get passes to the Scroller via success-callback as an array of data-items typed as Data[]|
174
- |invisible|_boolean_|Flag that determines whether the item should be hidden (if _true_) or visible (if _false_) when the _run_ method is called|
175
- |get|_()&nbsp;=>&nbsp;ItemAdapter&lt;Data&gt;_|Shortcut method returning { element, $index, data } object|
176
-
177
- `Run` callback is the most complex and environment-specific part of the `vscroll` API, which is fully depends on the environment for which the consumer is being created. Framework specific consumer should rely on internal mechanism of the framework to provide runtime DOM modifications.
178
-
179
- There are some requirements on how the items should be processed by `run` call:
180
- - after the `run` callback is completed, there must be `newItems.length` elements in the DOM between backward and forward padding elements;
181
- - old items that are not in the new item list should be removed from DOM; use `oldItems[].element` references for this purpose;
182
- - old items that are in the list should not be removed and recreated, as it may lead to an unwanted shift of the scroll position; just don't touch them;
183
- - new items elements should be rendered in accordance with `newItems[].$index` comparable to `$index` of elements that remain: `$index` must increase continuously and the directions of increase must persist across the `run` calls; Scroller maintains `$index` internally, so you only need to properly inject a set of `newItems[].element` into the DOM;
184
- - new elements should be rendered but not visible, and this should be achieved by "fixed" positioning and "left"/"top" coordinates placing the item element out of view; the Workflow will take care of visibility after calculations; an additional attribute `newItems[].invisible` can be used to determine if a given element should be hidden; this requirement can be changed by the `Routines` class setting, see below;
185
- - new items elements should have "data-sid" attribute, which value should reflect `newItems[].$index`.
186
-
187
- ### 5. Routines
188
-
189
- A special class allowing to override the default behavior related to the DOM. All DOM-specific operations are implemented as the [DOM Routines class](https://github.com/dhilt/vscroll/blob/v1.5.0/src/classes/domRoutines.ts) methods inside core. When the `Routines` class setting is passed among the Workflow arguments, its methods override the base class methods. The Routines methods description can be taken from the [IRoutines interface](https://github.com/dhilt/vscroll/blob/v1.5.0/src/interfaces/routines.ts) sources. For example, there is a method that throws an error if its argument is not an HTML element:
190
-
191
- ```typescript
192
- checkElement(element: HTMLElement): void {
193
- if (!element) {
194
- throw new Error('HTML element is not defined');
195
- }
196
- }
197
- ```
198
-
199
- With the `Routines` class setting it can be overridden as follows:
200
-
201
- ```js
202
- new Workflow({
203
- consumer, element, datasource, run,
204
- Routines: class {
205
- checkElement(element) {
206
- if (!element || typeof element.querySelector !== 'function') {
207
- throw new Error('Fatal: expecting HTML element');
208
- }
209
- }
210
- }
211
- });
212
- ```
213
-
214
- Various DOM calculations, setting/getting the scroll position, render process and other logic can be adjusted, improved or completely replaced by custom methods of the `Routines` class setting.
215
-
216
- ## Live
217
-
218
- This repository has a minimal demonstration of the App-consumer implementation considering all of the requirements listed above: https://dhilt.github.io/vscroll/. This is all-in-one HTML demo with `vscroll` taken from CDN. The source code of the demo is [here](https://github.com/dhilt/vscroll/blob/main/demo/index.html). The approach is rough and non-optimized, if you are seeking for more general solution for native JavaScript applications, please have a look at [vscroll-native](https://github.com/dhilt/vscroll-native) project. It is relatively new and has no good documentation, but its [source code](https://github.com/dhilt/vscroll-native/tree/main/src) and its [demo](https://github.com/dhilt/vscroll-native/tree/main/demo) may shed light on `vscroll` usage in no-framework environment.
219
-
220
- Another example is [ngx-ui-scroll](https://github.com/dhilt/ngx-ui-scroll). Before 2021 `vscroll` was part of `ngx-ui-scroll`, and its [demo page](https://dhilt.github.io/ngx-ui-scroll/#/) contains well-documented samples that can be used to get an idea on the API and functionality offered by `vscroll`. The code of the [UiScrollComponent](https://github.com/dhilt/ngx-ui-scroll/blob/v2.3.1/src/ui-scroll.component.ts) clearly demonstrates the `Workflow` instantiation in the context of Angular. Also, since ngx-ui-scroll is the intermediate layer between `vscroll` and the end Application, the Datasource is being provided from the outside. Method `makeDatasource` is used to provide `Datasource` class to the end Application.
221
-
222
- ## Adapter API
223
-
224
- Adapter API is a powerful feature of the `vscroll` engine allowing to collect the statistics and provide runtime manipulations with the viewport: adding, removing, updating items. This API is very useful when building the real-time interactive applications when data can change over time by not only scrolling (like chats).
225
-
226
- Please refer to the ngx-ui-scroll [Adapter API doc](https://github.com/dhilt/ngx-ui-scroll#adapter-api) as it can be applied to `vscroll` case with only one important difference: vscroll does not have RxJs entities, it has [Reactive](https://github.com/dhilt/vscroll/blob/main/src/classes/reactive.ts) ones instead. It means, for example, `eof$` has no "subscribe" method, but "on":
227
-
228
- ```js
229
- // ngx-ui-scroll
230
- myDatasource.adapter.bof$.subscribe(value =>
231
- value && console.log('Begin of file is reached')
232
- );
233
- // vscroll
234
- myDatasource.adapter.bof$.on(value =>
235
- value && console.log('Begin of file is reached')
236
- );
237
- ```
238
-
239
- Adapter API becomes available as the `Datasource.adapter` property after the Datasource is instantiated via operator "new". In terms of "vscroll" you need to get a Datasource class by calling the `makeDatasource` method, then you can instantiate it. `makeDatasource` accepts 1 argument, which is an Adapter custom configuration. Currently this config can only be used to redefine the just mentioned Adapter reactive props. Here's an example of how simple Reactive props can be overridden with RxJs Subject and BehaviorSubject entities: [ui-scroll.datasource.ts](https://github.com/dhilt/ngx-ui-scroll/blob/v2.3.1/src/ui-scroll.datasource.ts).
240
-
241
- An important note is that the Adapter getting ready breaks onto 2 parts: instantiation (which is synchronous with the Datasource instantiation) and initialization (which occurs during the Workflow instantiating). Adapter gets all necessary props and methods during the first phase, but they start work only when the second phase is done. Practically this means
242
- - you may arrange any Adapter reactive subscriptions in your app/consumer right after the Datasource is instantiated,
243
- - some of the initial (default) values can be unusable, like `Adapter.bufferInfo.minIndex` = NaN (because Scroller's Buffer is empty before the very first `Datasource.get` call),
244
- - Adapter methods do nothing when called before phase 2, they immediately resolve some default "good" value (`{ immediate: true, success: true, ... }`).
245
-
246
- If there is some logic that could potentially run before the Adapter initialization and you don't want this to happen, the following approach can be applied:
247
-
248
- ```js
249
- myDatasource = new VScroll.makeDatasource()({...});
250
- myDatasource.adapter.init$.once(() => {
251
- console.log('The Adapter is initialized'); // 2nd output
252
- });
253
- workflow = new VScroll.Workflow({...});
254
- console.log('The Workflow runs'); // 1st output
255
- ```
256
-
257
- VScroll will receive its own Adapter API documentation later, but for now please refer to [ngx-ui-scroll](https://github.com/dhilt/ngx-ui-scroll#adapter-api).
258
-
259
- ## Thanks
260
-
261
- \- to [Mike Feingold](https://github.com/mfeingold) as he started all this story in far 2013,
262
-
263
- \- to [Joshua Toenyes](https://github.com/JoshuaToenyes) as he transferred ownership to the "vscroll" npm repository which he owned but did not use,
264
-
265
- \- to all contributors of related repositories ([link](https://github.com/angular-ui/ui-scroll/graphs/contributors), [link](https://github.com/dhilt/ngx-ui-scroll/graphs/contributors)),
266
-
267
- \- to all donators as their great support does increase motivation.
268
-
269
- <br>
270
-
271
- __________
272
-
273
- 2022 &copy; [Denis Hilt](https://github.com/dhilt)
1
+ [![build status](https://github.com/dhilt/vscroll/actions/workflows/build.yml/badge.svg)](https://github.com/dhilt/vscroll/actions/workflows/build.yml)
2
+ [![npm version](https://badge.fury.io/js/vscroll.svg)](https://www.npmjs.com/package/vscroll)
3
+
4
+ # VScroll
5
+
6
+ - [Overview](#overview)
7
+ - [Getting started](#getting-started)
8
+ - [Usage](#usage)
9
+ - [Consumer](#1-consumer)
10
+ - [Element](#2-element)
11
+ - [Datasource](#3-datasource)
12
+ - [Run](#4-run)
13
+ - [Routines](#5-routines)
14
+ - [Live](#live)
15
+ - [Adapter API](#adapter-api)
16
+ - [Thanks](#thanks)
17
+
18
+ ## Overview
19
+
20
+ VScroll is a JavaScript library providing virtual scroll engine. Can be seen as a core for platform-specific solutions designed to represent unlimited datasets using virtualization technique. Below is the diagram of how the VScroll engine is being distributed to the end user.
21
+
22
+ <br>
23
+ <p align="center">
24
+ <img src="https://user-images.githubusercontent.com/4365660/104845671-ad1d4b80-58e7-11eb-9cc9-4a00ebcbc9e8.png">
25
+ </p>
26
+
27
+ Basically, the consumer layer can be omitted and the end Application developers can use VScroll directly. This repository has a [minimal demo page](https://dhilt.github.io/vscroll/) of direct use of the VScroll library in a non-specific environment. There are also several consumer implementations built on top of VScroll:
28
+
29
+ - [ngx-ui-scroll](https://github.com/dhilt/ngx-ui-scroll), Angular virtual scroll directive
30
+ - [vscroll-native](https://github.com/dhilt/vscroll-native), virtual scroll module for native JavaScript applications
31
+ - [Vue integration sample](https://stackblitz.com/edit/vscroll-vue-integration?file=src%2Fcomponents%2FVScroll.vue), very rough implementation for Vue
32
+
33
+ ## Getting started
34
+
35
+ ### CDN
36
+
37
+ ```html
38
+ <script src="https://cdn.jsdelivr.net/npm/vscroll"></script>
39
+ <script>
40
+ const workflow = new VScroll.Workflow(...);
41
+ </script>
42
+ ```
43
+
44
+ ### NPM
45
+
46
+ ```
47
+ npm install vscroll
48
+ ```
49
+
50
+ ```js
51
+ import { Workflow } from 'vscroll';
52
+
53
+ const workflow = new Workflow(...);
54
+ ```
55
+
56
+ ## Usage
57
+
58
+ The main entity distributed via `vscroll` is the `Workflow` class. Its instantiating runs the virtual scroll engine.
59
+
60
+ ```js
61
+ new Workflow({ consumer, element, datasource, run });
62
+ ```
63
+
64
+ The constructor of the `Workflow` class requires an argument of the following type:
65
+
66
+ ```typescript
67
+ interface WorkflowParams<ItemData> {
68
+ consumer: IPackage;
69
+ element: HTMLElement;
70
+ datasource: IDatasource<ItemData>;
71
+ run: OnDataChanged<ItemData>;
72
+ Routines?: CustomRoutinesClass;
73
+ }
74
+ ```
75
+
76
+ This is a TypeScript definition, but speaking of JavaScript, an argument object must contain 4 fields described below.
77
+
78
+ ### 1. Consumer
79
+
80
+ A simple data object that provides information about a consumer. It is not critical to omit this, but if the result solution is going to be published as a separate 3d-party library ("consumer"), the name and the version of the result package should be passed as follows:
81
+
82
+ ```js
83
+ const consumer = {
84
+ name: 'my-vscroll-consumer',
85
+ version: 'v1.0.0-alpha.1'
86
+ };
87
+ ```
88
+
89
+ ### 2. Element
90
+
91
+ An HTML element the `Workflow` should use as a scrollable part of the viewport. It should be present in DOM before instantiating the `Workflow`.
92
+
93
+ ```js
94
+ const element = document.getElementById('vscroll');
95
+ ```
96
+
97
+ This element should be wrapped with another container with constrained height and overflow scroll/auto. And it also must have two special padding elements marked with special attributes for the virtualization purpose.
98
+
99
+ ```html
100
+ <div id="viewport">
101
+ <div id="vscroll">
102
+ <div data-padding-backward></div>
103
+ <div data-padding-forward></div>
104
+ </div>
105
+ </div>
106
+ ```
107
+
108
+ ```css
109
+ #viewport {
110
+ height: 300px;
111
+ overflow-y: scroll;
112
+ }
113
+ ```
114
+
115
+ ### 3. Datasource
116
+
117
+ This is a special object, providing dataset items in runtime. There is a separate wiki document describing the Datasource: [github.com/dhilt/vscroll/wiki/Datasource](https://github.com/dhilt/vscroll/wiki/Datasource). Below is a short version.
118
+
119
+ The Datasource can be defined in two ways. First, as an object literal:
120
+
121
+ ```js
122
+ const datasource = {
123
+ get: (index, count, success) => {
124
+ const data = [];
125
+ for (let i = index; i < index + count; i++) {
126
+ data.push({ id: i, text: 'item #' + i });
127
+ }
128
+ success(data);
129
+ }
130
+ };
131
+ ```
132
+
133
+ Second, as an instance of Datasource class which can be obtained through a special factory method. Along with the `Workflow` class, VScroll exposes the `makeDatasource` method which can be used for creating Datasource class, so the end datasource object can be instantiated via operator `new`:
134
+
135
+ ```js
136
+ import { makeDatasource } from 'vscroll';
137
+ const Datasource = makeDatasource();
138
+
139
+ const datasource = new Datasource({
140
+ get: (index, length, success) =>
141
+ success(Array.from({ length }).map((_, i) =>
142
+ ({ id: index + i, text: 'item #' + (index + i) })
143
+ ))
144
+ });
145
+ ```
146
+
147
+ The argument of the Datasource class is the same object literal as in the first case. It has one mandatory field which is the core of the App-Scroller integration: method `get`. The `Workflow` requests data via the `Datasource.get` method in runtime.
148
+
149
+ For more solid understanding the concept of the Datasource with examples, please, refer to [the Datasource doc](https://github.com/dhilt/vscroll/wiki/Datasource).
150
+
151
+ ### 4. Run
152
+
153
+ A callback that is called every time the Workflow decides that the UI needs to be changed. Its argument is a list of items to be present in the UI. This is a consumer responsibility to detect changes and display them in the UI.
154
+
155
+ ```js
156
+ run: (newItems) => {
157
+ // assume oldItems contains a list of items that are currently present in the UI
158
+ if (!newItems.length && !oldItems.length) {
159
+ return;
160
+ }
161
+ // make newItems to be present in the UI instead of oldItems
162
+ processItems(newItems, oldItems);
163
+ oldItems = newItems;
164
+ };
165
+ ```
166
+
167
+ Each item (in both `newItems` and `oldItems` lists) is an instance of the [Item class](https://github.com/dhilt/vscroll/blob/v1.5.0/src/classes/item.ts) implementing the [Item interface](https://github.com/dhilt/vscroll/blob/v1.5.0/src/interfaces/item.ts), whose props can be used for proper implementation of the `run` callback:
168
+
169
+ |Name|Type|Description|
170
+ |:--|:--|:----|
171
+ |element|_HTMLElement_|HTML element associated with the item|
172
+ |$index|_number_|Integer index of the item in the Datasource. Correlates with the first argument of the Datasource.get method|
173
+ |data|_Data_|Data (contents) of the item. This is what the Datasource.get passes to the Scroller via success-callback as an array of data-items typed as Data[]|
174
+ |invisible|_boolean_|Flag that determines whether the item should be hidden (if _true_) or visible (if _false_) when the _run_ method is called|
175
+ |get|_()&nbsp;=>&nbsp;ItemAdapter&lt;Data&gt;_|Shortcut method returning { element, $index, data } object|
176
+
177
+ `Run` callback is the most complex and environment-specific part of the `vscroll` API, which is fully depends on the environment for which the consumer is being created. Framework specific consumer should rely on internal mechanism of the framework to provide runtime DOM modifications.
178
+
179
+ There are some requirements on how the items should be processed by `run` call:
180
+ - after the `run` callback is completed, there must be `newItems.length` elements in the DOM between backward and forward padding elements;
181
+ - old items that are not in the new item list should be removed from DOM; use `oldItems[].element` references for this purpose;
182
+ - old items that are in the list should not be removed and recreated, as it may lead to an unwanted shift of the scroll position; just don't touch them;
183
+ - new items elements should be rendered in accordance with `newItems[].$index` comparable to `$index` of elements that remain: `$index` must increase continuously and the directions of increase must persist across the `run` calls; Scroller maintains `$index` internally, so you only need to properly inject a set of `newItems[].element` into the DOM;
184
+ - new elements should be rendered but not visible, and this should be achieved by "fixed" positioning and "left"/"top" coordinates placing the item element out of view; the Workflow will take care of visibility after calculations; an additional attribute `newItems[].invisible` can be used to determine if a given element should be hidden; this requirement can be changed by the `Routines` class setting, see below;
185
+ - new items elements should have "data-sid" attribute, which value should reflect `newItems[].$index`.
186
+
187
+ ### 5. Routines
188
+
189
+ A special class allowing to override the default behavior related to the DOM. All DOM-specific operations are implemented as the [DOM Routines class](https://github.com/dhilt/vscroll/blob/v1.5.0/src/classes/domRoutines.ts) methods inside core. When the `Routines` class setting is passed among the Workflow arguments, its methods override the base class methods. The Routines methods description can be taken from the [IRoutines interface](https://github.com/dhilt/vscroll/blob/v1.5.0/src/interfaces/routines.ts) sources. For example, there is a method that throws an error if its argument is not an HTML element:
190
+
191
+ ```typescript
192
+ checkElement(element: HTMLElement): void {
193
+ if (!element) {
194
+ throw new Error('HTML element is not defined');
195
+ }
196
+ }
197
+ ```
198
+
199
+ With the `Routines` class setting it can be overridden as follows:
200
+
201
+ ```js
202
+ new Workflow({
203
+ consumer, element, datasource, run,
204
+ Routines: class {
205
+ checkElement(element) {
206
+ if (!element || typeof element.querySelector !== 'function') {
207
+ throw new Error('Fatal: expecting HTML element');
208
+ }
209
+ }
210
+ }
211
+ });
212
+ ```
213
+
214
+ Another example is the table layout case where we need to specify the offset of the table header:
215
+
216
+ ```js
217
+ const Routines = class {
218
+ getOffset() {
219
+ return document.querySelector('#viewport thead')?.offsetHeight || 0;
220
+ }
221
+ }
222
+ ```
223
+
224
+ Various DOM calculations, setting/getting the scroll position, render process and other logic can be adjusted, improved or completely replaced by custom methods of the `Routines` class setting.
225
+
226
+ ## Live
227
+
228
+ This repository has a minimal demonstration of the App-consumer implementation considering all of the requirements listed above: https://dhilt.github.io/vscroll/. This is all-in-one HTML demo with `vscroll` taken from CDN. The source code of the demo is [here](https://github.com/dhilt/vscroll/blob/main/demo/index.html). The approach is rough and non-optimized, if you are seeking for more general solution for native JavaScript applications, please have a look at [vscroll-native](https://github.com/dhilt/vscroll-native) project. It is relatively new and has no good documentation, but its [source code](https://github.com/dhilt/vscroll-native/tree/main/src) and its [demo](https://github.com/dhilt/vscroll-native/tree/main/demo) may shed light on `vscroll` usage in no-framework environment.
229
+
230
+ Another example is [ngx-ui-scroll](https://github.com/dhilt/ngx-ui-scroll). Before 2021 `vscroll` was part of `ngx-ui-scroll`, and its [demo page](https://dhilt.github.io/ngx-ui-scroll/#/) contains well-documented samples that can be used to get an idea on the API and functionality offered by `vscroll`. The code of the [UiScrollComponent](https://github.com/dhilt/ngx-ui-scroll/blob/v2.3.1/src/ui-scroll.component.ts) clearly demonstrates the `Workflow` instantiation in the context of Angular. Also, since ngx-ui-scroll is the intermediate layer between `vscroll` and the end Application, the Datasource is being provided from the outside. Method `makeDatasource` is used to provide `Datasource` class to the end Application.
231
+
232
+ ## Adapter API
233
+
234
+ Adapter API is a powerful feature of the `vscroll` engine allowing to collect the statistics and provide runtime manipulations with the viewport: adding, removing, updating items. This API is very useful when building the real-time interactive applications when data can change over time by not only scrolling (like chats).
235
+
236
+ Please refer to the ngx-ui-scroll [Adapter API doc](https://github.com/dhilt/ngx-ui-scroll#adapter-api) as it can be applied to `vscroll` case with only one important difference: vscroll does not have RxJs entities, it has [Reactive](https://github.com/dhilt/vscroll/blob/main/src/classes/reactive.ts) ones instead. It means, for example, `eof$` has no "subscribe" method, but "on":
237
+
238
+ ```js
239
+ // ngx-ui-scroll
240
+ myDatasource.adapter.bof$.subscribe(value =>
241
+ value && console.log('Begin of file is reached')
242
+ );
243
+ // vscroll
244
+ myDatasource.adapter.bof$.on(value =>
245
+ value && console.log('Begin of file is reached')
246
+ );
247
+ ```
248
+
249
+ Adapter API becomes available as the `Datasource.adapter` property after the Datasource is instantiated via operator "new". In terms of "vscroll" you need to get a Datasource class by calling the `makeDatasource` method, then you can instantiate it. `makeDatasource` accepts 1 argument, which is an Adapter custom configuration. Currently this config can only be used to redefine the just mentioned Adapter reactive props. Here's an example of how simple Reactive props can be overridden with RxJs Subject and BehaviorSubject entities: [ui-scroll.datasource.ts](https://github.com/dhilt/ngx-ui-scroll/blob/v2.3.1/src/ui-scroll.datasource.ts).
250
+
251
+ An important note is that the Adapter getting ready breaks onto 2 parts: instantiation (which is synchronous with the Datasource instantiation) and initialization (which occurs during the Workflow instantiating). Adapter gets all necessary props and methods during the first phase, but they start work only when the second phase is done. Practically this means
252
+ - you may arrange any Adapter reactive subscriptions in your app/consumer right after the Datasource is instantiated,
253
+ - some of the initial (default) values can be unusable, like `Adapter.bufferInfo.minIndex` = NaN (because Scroller's Buffer is empty before the very first `Datasource.get` call),
254
+ - Adapter methods do nothing when called before phase 2, they immediately resolve some default "good" value (`{ immediate: true, success: true, ... }`).
255
+
256
+ If there is some logic that could potentially run before the Adapter initialization and you don't want this to happen, the following approach can be applied:
257
+
258
+ ```js
259
+ myDatasource = new VScroll.makeDatasource()({...});
260
+ myDatasource.adapter.init$.once(() => {
261
+ console.log('The Adapter is initialized'); // 2nd output
262
+ });
263
+ workflow = new VScroll.Workflow({...});
264
+ console.log('The Workflow runs'); // 1st output
265
+ ```
266
+
267
+ VScroll will receive its own Adapter API documentation later, but for now please refer to [ngx-ui-scroll](https://github.com/dhilt/ngx-ui-scroll#adapter-api).
268
+
269
+ ## Thanks
270
+
271
+ \- to [Mike Feingold](https://github.com/mfeingold) as he started all this story in far 2013,
272
+
273
+ \- to [Joshua Toenyes](https://github.com/JoshuaToenyes) as he transferred ownership to the "vscroll" npm repository which he owned but did not use,
274
+
275
+ \- to all contributors of related repositories ([link](https://github.com/angular-ui/ui-scroll/graphs/contributors), [link](https://github.com/dhilt/ngx-ui-scroll/graphs/contributors)),
276
+
277
+ \- to all donators as their great support does increase motivation.
278
+
279
+ <br>
280
+
281
+ __________
282
+
283
+ 2023 &copy; [Denis Hilt](https://github.com/dhilt)