@symbiote-native/angular 0.1.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 (372) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +147 -0
  3. package/build/angular/components/activity-indicator/index.android.d.ts +12 -0
  4. package/build/angular/components/activity-indicator/index.android.js +21 -0
  5. package/build/angular/components/activity-indicator/index.android.js.map +1 -0
  6. package/build/angular/components/activity-indicator/index.d.ts +1 -0
  7. package/build/angular/components/activity-indicator/index.ios.d.ts +8 -0
  8. package/build/angular/components/activity-indicator/index.ios.js +21 -0
  9. package/build/angular/components/activity-indicator/index.ios.js.map +1 -0
  10. package/build/angular/components/activity-indicator/index.js +4 -0
  11. package/build/angular/components/activity-indicator/index.js.map +1 -0
  12. package/build/angular/components/activity-indicator/shared.d.ts +67 -0
  13. package/build/angular/components/activity-indicator/shared.js +260 -0
  14. package/build/angular/components/activity-indicator/shared.js.map +1 -0
  15. package/build/angular/components/button.d.ts +63 -0
  16. package/build/angular/components/button.js +332 -0
  17. package/build/angular/components/button.js.map +1 -0
  18. package/build/angular/components/drawer-layout-android/index.android.d.ts +34 -0
  19. package/build/angular/components/drawer-layout-android/index.android.js +291 -0
  20. package/build/angular/components/drawer-layout-android/index.android.js.map +1 -0
  21. package/build/angular/components/drawer-layout-android/index.d.ts +11 -0
  22. package/build/angular/components/drawer-layout-android/index.js +109 -0
  23. package/build/angular/components/drawer-layout-android/index.js.map +1 -0
  24. package/build/angular/components/drawer-layout-android/shared.d.ts +74 -0
  25. package/build/angular/components/drawer-layout-android/shared.js +138 -0
  26. package/build/angular/components/drawer-layout-android/shared.js.map +1 -0
  27. package/build/angular/components/flat-list/index.d.ts +122 -0
  28. package/build/angular/components/flat-list/index.js +689 -0
  29. package/build/angular/components/flat-list/index.js.map +1 -0
  30. package/build/angular/components/image/index.android.d.ts +10 -0
  31. package/build/angular/components/image/index.android.js +59 -0
  32. package/build/angular/components/image/index.android.js.map +1 -0
  33. package/build/angular/components/image/index.d.ts +1 -0
  34. package/build/angular/components/image/index.ios.d.ts +10 -0
  35. package/build/angular/components/image/index.ios.js +59 -0
  36. package/build/angular/components/image/index.ios.js.map +1 -0
  37. package/build/angular/components/image/index.js +3 -0
  38. package/build/angular/components/image/index.js.map +1 -0
  39. package/build/angular/components/image/shared.d.ts +101 -0
  40. package/build/angular/components/image/shared.js +408 -0
  41. package/build/angular/components/image/shared.js.map +1 -0
  42. package/build/angular/components/image-background.d.ts +81 -0
  43. package/build/angular/components/image-background.js +418 -0
  44. package/build/angular/components/image-background.js.map +1 -0
  45. package/build/angular/components/input-accessory-view.d.ts +59 -0
  46. package/build/angular/components/input-accessory-view.js +266 -0
  47. package/build/angular/components/input-accessory-view.js.map +1 -0
  48. package/build/angular/components/keyboard-avoiding-view.d.ts +82 -0
  49. package/build/angular/components/keyboard-avoiding-view.js +363 -0
  50. package/build/angular/components/keyboard-avoiding-view.js.map +1 -0
  51. package/build/angular/components/modal.d.ts +92 -0
  52. package/build/angular/components/modal.js +365 -0
  53. package/build/angular/components/modal.js.map +1 -0
  54. package/build/angular/components/pressable/index.d.ts +123 -0
  55. package/build/angular/components/pressable/index.js +421 -0
  56. package/build/angular/components/pressable/index.js.map +1 -0
  57. package/build/angular/components/refresh-control.d.ts +86 -0
  58. package/build/angular/components/refresh-control.js +347 -0
  59. package/build/angular/components/refresh-control.js.map +1 -0
  60. package/build/angular/components/safe-area-view.d.ts +57 -0
  61. package/build/angular/components/safe-area-view.js +253 -0
  62. package/build/angular/components/safe-area-view.js.map +1 -0
  63. package/build/angular/components/scroll-view/index.android.d.ts +21 -0
  64. package/build/angular/components/scroll-view/index.android.js +235 -0
  65. package/build/angular/components/scroll-view/index.android.js.map +1 -0
  66. package/build/angular/components/scroll-view/index.d.ts +3 -0
  67. package/build/angular/components/scroll-view/index.ios.d.ts +9 -0
  68. package/build/angular/components/scroll-view/index.ios.js +86 -0
  69. package/build/angular/components/scroll-view/index.ios.js.map +1 -0
  70. package/build/angular/components/scroll-view/index.js +6 -0
  71. package/build/angular/components/scroll-view/index.js.map +1 -0
  72. package/build/angular/components/scroll-view/projection.d.ts +32 -0
  73. package/build/angular/components/scroll-view/projection.js +312 -0
  74. package/build/angular/components/scroll-view/projection.js.map +1 -0
  75. package/build/angular/components/scroll-view/shared.d.ts +230 -0
  76. package/build/angular/components/scroll-view/shared.js +679 -0
  77. package/build/angular/components/scroll-view/shared.js.map +1 -0
  78. package/build/angular/components/scroll-view/sticky-header.d.ts +41 -0
  79. package/build/angular/components/scroll-view/sticky-header.js +208 -0
  80. package/build/angular/components/scroll-view/sticky-header.js.map +1 -0
  81. package/build/angular/components/section-list/index.d.ts +116 -0
  82. package/build/angular/components/section-list/index.js +641 -0
  83. package/build/angular/components/section-list/index.js.map +1 -0
  84. package/build/angular/components/switch/index.android.d.ts +20 -0
  85. package/build/angular/components/switch/index.android.js +70 -0
  86. package/build/angular/components/switch/index.android.js.map +1 -0
  87. package/build/angular/components/switch/index.d.ts +1 -0
  88. package/build/angular/components/switch/index.ios.d.ts +19 -0
  89. package/build/angular/components/switch/index.ios.js +69 -0
  90. package/build/angular/components/switch/index.ios.js.map +1 -0
  91. package/build/angular/components/switch/index.js +4 -0
  92. package/build/angular/components/switch/index.js.map +1 -0
  93. package/build/angular/components/switch/shared.d.ts +40 -0
  94. package/build/angular/components/switch/shared.js +127 -0
  95. package/build/angular/components/switch/shared.js.map +1 -0
  96. package/build/angular/components/text-input.d.ts +153 -0
  97. package/build/angular/components/text-input.js +604 -0
  98. package/build/angular/components/text-input.js.map +1 -0
  99. package/build/angular/components/touchable-native-feedback.d.ts +83 -0
  100. package/build/angular/components/touchable-native-feedback.js +376 -0
  101. package/build/angular/components/touchable-native-feedback.js.map +1 -0
  102. package/build/angular/components/touchable.d.ts +248 -0
  103. package/build/angular/components/touchable.js +1206 -0
  104. package/build/angular/components/touchable.js.map +1 -0
  105. package/build/angular/components/virtualized-list/directives.d.ts +54 -0
  106. package/build/angular/components/virtualized-list/directives.js +154 -0
  107. package/build/angular/components/virtualized-list/directives.js.map +1 -0
  108. package/build/angular/components/virtualized-list/index.d.ts +268 -0
  109. package/build/angular/components/virtualized-list/index.js +1162 -0
  110. package/build/angular/components/virtualized-list/index.js.map +1 -0
  111. package/build/angular/components/virtualized-section-list/directives.d.ts +37 -0
  112. package/build/angular/components/virtualized-section-list/directives.js +77 -0
  113. package/build/angular/components/virtualized-section-list/directives.js.map +1 -0
  114. package/build/angular/components/virtualized-section-list/index.d.ts +178 -0
  115. package/build/angular/components/virtualized-section-list/index.js +722 -0
  116. package/build/angular/components/virtualized-section-list/index.js.map +1 -0
  117. package/build/angular/components.d.ts +39 -0
  118. package/build/angular/components.js +38 -0
  119. package/build/angular/components.js.map +1 -0
  120. package/build/angular/create-portal.d.ts +22 -0
  121. package/build/angular/create-portal.js +74 -0
  122. package/build/angular/create-portal.js.map +1 -0
  123. package/build/angular/create-tunnel.d.ts +34 -0
  124. package/build/angular/create-tunnel.js +126 -0
  125. package/build/angular/create-tunnel.js.map +1 -0
  126. package/build/angular/descriptor-to-angular/index.d.ts +22 -0
  127. package/build/angular/descriptor-to-angular/index.js +142 -0
  128. package/build/angular/descriptor-to-angular/index.js.map +1 -0
  129. package/build/angular/host-instance/index.d.ts +2 -0
  130. package/build/angular/host-instance/index.js +37 -0
  131. package/build/angular/host-instance/index.js.map +1 -0
  132. package/build/angular/index.d.ts +21 -0
  133. package/build/angular/index.js +42 -0
  134. package/build/angular/index.js.map +1 -0
  135. package/build/angular/modules/animated/create-animated-component.d.ts +68 -0
  136. package/build/angular/modules/animated/create-animated-component.js +429 -0
  137. package/build/angular/modules/animated/create-animated-component.js.map +1 -0
  138. package/build/angular/modules/animated/index.d.ts +51 -0
  139. package/build/angular/modules/animated/index.js +59 -0
  140. package/build/angular/modules/animated/index.js.map +1 -0
  141. package/build/angular/modules/app-registry/index.d.ts +7 -0
  142. package/build/angular/modules/app-registry/index.js +23 -0
  143. package/build/angular/modules/app-registry/index.js.map +1 -0
  144. package/build/angular/modules/status-bar.d.ts +20 -0
  145. package/build/angular/modules/status-bar.js +59 -0
  146. package/build/angular/modules/status-bar.js.map +1 -0
  147. package/build/angular/primitives/index.d.ts +63 -0
  148. package/build/angular/primitives/index.js +189 -0
  149. package/build/angular/primitives/index.js.map +1 -0
  150. package/build/angular/primitives/shared.d.ts +89 -0
  151. package/build/angular/primitives/shared.js +172 -0
  152. package/build/angular/primitives/shared.js.map +1 -0
  153. package/build/angular/render.d.ts +11 -0
  154. package/build/angular/render.js +161 -0
  155. package/build/angular/render.js.map +1 -0
  156. package/build/angular/renderer.d.ts +38 -0
  157. package/build/angular/renderer.js +360 -0
  158. package/build/angular/renderer.js.map +1 -0
  159. package/build/angular/services/color-scheme.service.d.ts +16 -0
  160. package/build/angular/services/color-scheme.service.js +31 -0
  161. package/build/angular/services/color-scheme.service.js.map +1 -0
  162. package/build/angular/services/index.d.ts +2 -0
  163. package/build/angular/services/index.js +3 -0
  164. package/build/angular/services/index.js.map +1 -0
  165. package/build/angular/services/window-dimensions.service.d.ts +16 -0
  166. package/build/angular/services/window-dimensions.service.js +42 -0
  167. package/build/angular/services/window-dimensions.service.js.map +1 -0
  168. package/build/components/activity-indicator/index.android.d.ts +9 -0
  169. package/build/components/activity-indicator/index.android.js +64 -0
  170. package/build/components/activity-indicator/index.d.ts +1 -0
  171. package/build/components/activity-indicator/index.ios.d.ts +5 -0
  172. package/build/components/activity-indicator/index.ios.js +64 -0
  173. package/build/components/activity-indicator/index.js +3 -0
  174. package/build/components/activity-indicator/shared.d.ts +64 -0
  175. package/build/components/activity-indicator/shared.js +424 -0
  176. package/build/components/button.d.ts +60 -0
  177. package/build/components/button.js +456 -0
  178. package/build/components/drawer-layout-android/index.android.d.ts +29 -0
  179. package/build/components/drawer-layout-android/index.android.js +326 -0
  180. package/build/components/drawer-layout-android/index.d.ts +8 -0
  181. package/build/components/drawer-layout-android/index.js +145 -0
  182. package/build/components/drawer-layout-android/shared.d.ts +71 -0
  183. package/build/components/drawer-layout-android/shared.js +205 -0
  184. package/build/components/flat-list/index.d.ts +119 -0
  185. package/build/components/flat-list/index.js +692 -0
  186. package/build/components/image/index.android.d.ts +7 -0
  187. package/build/components/image/index.android.js +88 -0
  188. package/build/components/image/index.d.ts +1 -0
  189. package/build/components/image/index.ios.d.ts +7 -0
  190. package/build/components/image/index.ios.js +88 -0
  191. package/build/components/image/index.js +2 -0
  192. package/build/components/image/shared.d.ts +101 -0
  193. package/build/components/image/shared.js +407 -0
  194. package/build/components/image-background.d.ts +78 -0
  195. package/build/components/image-background.js +583 -0
  196. package/build/components/input-accessory-view.d.ts +56 -0
  197. package/build/components/input-accessory-view.js +407 -0
  198. package/build/components/keyboard-avoiding-view.d.ts +79 -0
  199. package/build/components/keyboard-avoiding-view.js +509 -0
  200. package/build/components/modal.d.ts +89 -0
  201. package/build/components/modal.js +534 -0
  202. package/build/components/pressable/index.d.ts +120 -0
  203. package/build/components/pressable/index.js +640 -0
  204. package/build/components/refresh-control.d.ts +83 -0
  205. package/build/components/refresh-control.js +514 -0
  206. package/build/components/safe-area-view.d.ts +54 -0
  207. package/build/components/safe-area-view.js +393 -0
  208. package/build/components/scroll-view/index.android.d.ts +16 -0
  209. package/build/components/scroll-view/index.android.js +228 -0
  210. package/build/components/scroll-view/index.d.ts +3 -0
  211. package/build/components/scroll-view/index.ios.d.ts +6 -0
  212. package/build/components/scroll-view/index.ios.js +113 -0
  213. package/build/components/scroll-view/index.js +5 -0
  214. package/build/components/scroll-view/projection.d.ts +32 -0
  215. package/build/components/scroll-view/projection.js +311 -0
  216. package/build/components/scroll-view/shared.d.ts +225 -0
  217. package/build/components/scroll-view/shared.js +757 -0
  218. package/build/components/scroll-view/sticky-header.d.ts +38 -0
  219. package/build/components/scroll-view/sticky-header.js +257 -0
  220. package/build/components/section-list/index.d.ts +113 -0
  221. package/build/components/section-list/index.js +768 -0
  222. package/build/components/switch/index.android.d.ts +17 -0
  223. package/build/components/switch/index.android.js +107 -0
  224. package/build/components/switch/index.d.ts +1 -0
  225. package/build/components/switch/index.ios.d.ts +16 -0
  226. package/build/components/switch/index.ios.js +106 -0
  227. package/build/components/switch/index.js +3 -0
  228. package/build/components/switch/shared.d.ts +37 -0
  229. package/build/components/switch/shared.js +176 -0
  230. package/build/components/text-input.d.ts +150 -0
  231. package/build/components/text-input.js +826 -0
  232. package/build/components/touchable-native-feedback.d.ts +80 -0
  233. package/build/components/touchable-native-feedback.js +550 -0
  234. package/build/components/touchable.d.ts +241 -0
  235. package/build/components/touchable.js +1672 -0
  236. package/build/components/virtualized-list/directives.d.ts +41 -0
  237. package/build/components/virtualized-list/directives.js +250 -0
  238. package/build/components/virtualized-list/index.d.ts +265 -0
  239. package/build/components/virtualized-list/index.js +1344 -0
  240. package/build/components/virtualized-section-list/directives.d.ts +28 -0
  241. package/build/components/virtualized-section-list/directives.js +149 -0
  242. package/build/components/virtualized-section-list/index.d.ts +175 -0
  243. package/build/components/virtualized-section-list/index.js +854 -0
  244. package/build/components.d.ts +39 -0
  245. package/build/components.js +37 -0
  246. package/build/create-portal.d.ts +17 -0
  247. package/build/create-portal.js +128 -0
  248. package/build/create-tunnel.d.ts +29 -0
  249. package/build/create-tunnel.js +181 -0
  250. package/build/descriptor-to-angular/index.d.ts +19 -0
  251. package/build/descriptor-to-angular/index.js +186 -0
  252. package/build/host-instance/index.d.ts +2 -0
  253. package/build/host-instance/index.js +36 -0
  254. package/build/index.d.ts +21 -0
  255. package/build/index.js +41 -0
  256. package/build/modules/animated/create-animated-component.d.ts +57 -0
  257. package/build/modules/animated/create-animated-component.js +490 -0
  258. package/build/modules/animated/index.d.ts +51 -0
  259. package/build/modules/animated/index.js +58 -0
  260. package/build/modules/app-registry/index.d.ts +7 -0
  261. package/build/modules/app-registry/index.js +22 -0
  262. package/build/modules/status-bar.d.ts +17 -0
  263. package/build/modules/status-bar.js +121 -0
  264. package/build/primitives/index.d.ts +32 -0
  265. package/build/primitives/index.js +386 -0
  266. package/build/primitives/shared.d.ts +84 -0
  267. package/build/primitives/shared.js +231 -0
  268. package/build/render.d.ts +11 -0
  269. package/build/render.js +160 -0
  270. package/build/renderer.d.ts +38 -0
  271. package/build/renderer.js +359 -0
  272. package/build/services/color-scheme.service.d.ts +13 -0
  273. package/build/services/color-scheme.service.js +72 -0
  274. package/build/services/index.d.ts +2 -0
  275. package/build/services/index.js +2 -0
  276. package/build/services/window-dimensions.service.d.ts +13 -0
  277. package/build/services/window-dimensions.service.js +83 -0
  278. package/metro-css-parser.cjs +11 -0
  279. package/package.json +57 -0
  280. package/src/__tests__/responder-change-detection.test.ts +102 -0
  281. package/src/__tests__/responder-nested-cd.test.ts +113 -0
  282. package/src/angular-gaps.test.ts +142 -0
  283. package/src/angular-imports.test.ts +100 -0
  284. package/src/components/activity-indicator/activity-indicator-class-style.test.ts +44 -0
  285. package/src/components/activity-indicator/activity-indicator.test.ts +131 -0
  286. package/src/components/activity-indicator/index.android.ts +16 -0
  287. package/src/components/activity-indicator/index.ios.ts +17 -0
  288. package/src/components/activity-indicator/index.ts +4 -0
  289. package/src/components/activity-indicator/shared.ts +206 -0
  290. package/src/components/button.ts +193 -0
  291. package/src/components/flat-list/column-wrapper-style-class.test.ts +116 -0
  292. package/src/components/flat-list/flat-list-array-style.test.ts +131 -0
  293. package/src/components/flat-list/flat-list-class-style.test.ts +74 -0
  294. package/src/components/flat-list/flat-list-scroll-containment.test.ts +107 -0
  295. package/src/components/flat-list/flat-list.test.ts +99 -0
  296. package/src/components/flat-list/index.ts +575 -0
  297. package/src/components/image/image-class-style.test.ts +46 -0
  298. package/src/components/image/index.android.ts +48 -0
  299. package/src/components/image/index.ios.ts +48 -0
  300. package/src/components/image/index.ts +3 -0
  301. package/src/components/image/shared.ts +478 -0
  302. package/src/components/image-background-class-style.test.ts +48 -0
  303. package/src/components/image-background-style-class.test.ts +79 -0
  304. package/src/components/image-background.ts +270 -0
  305. package/src/components/input-accessory-view.test.ts +43 -0
  306. package/src/components/input-accessory-view.ts +191 -0
  307. package/src/components/keyboard-avoiding-view.test.ts +54 -0
  308. package/src/components/keyboard-avoiding-view.ts +308 -0
  309. package/src/components/modal.test.ts +43 -0
  310. package/src/components/modal.ts +304 -0
  311. package/src/components/pressable/index.ts +371 -0
  312. package/src/components/pressable/pressable.test.ts +85 -0
  313. package/src/components/refresh-control.test.ts +41 -0
  314. package/src/components/refresh-control.ts +288 -0
  315. package/src/components/safe-area-view.test.ts +43 -0
  316. package/src/components/safe-area-view.ts +178 -0
  317. package/src/components/scroll-view/android-scroll-view-axis-projection.test.ts +123 -0
  318. package/src/components/scroll-view/content-container-style-class.test.ts +75 -0
  319. package/src/components/scroll-view/index.android.ts +190 -0
  320. package/src/components/scroll-view/index.ios.ts +79 -0
  321. package/src/components/scroll-view/index.ts +7 -0
  322. package/src/components/scroll-view/projection.ts +384 -0
  323. package/src/components/scroll-view/scroll-view-class-style.test.ts +134 -0
  324. package/src/components/scroll-view/scroll-view-projection.test.ts +194 -0
  325. package/src/components/scroll-view/shared.ts +836 -0
  326. package/src/components/scroll-view/sticky-header.ts +230 -0
  327. package/src/components/section-list/index.ts +445 -0
  328. package/src/components/switch/android-switch-class.test.ts +42 -0
  329. package/src/components/switch/index.android.ts +61 -0
  330. package/src/components/switch/index.ios.ts +60 -0
  331. package/src/components/switch/index.ts +4 -0
  332. package/src/components/switch/shared.ts +197 -0
  333. package/src/components/switch/switch.test.ts +92 -0
  334. package/src/components/text-input-class-style.test.ts +54 -0
  335. package/src/components/text-input.ts +536 -0
  336. package/src/components/touchable-native-feedback.test.ts +49 -0
  337. package/src/components/touchable-native-feedback.ts +260 -0
  338. package/src/components/touchable.test.ts +102 -0
  339. package/src/components/touchable.ts +643 -0
  340. package/src/components/virtualized-list/directives.ts +169 -0
  341. package/src/components/virtualized-list/index.ts +1204 -0
  342. package/src/components/virtualized-list/virtualized-list-class-style.test.ts +76 -0
  343. package/src/components/virtualized-section-list/directives.ts +91 -0
  344. package/src/components/virtualized-section-list/index.ts +598 -0
  345. package/src/components/virtualized-section-list/virtualized-section-list-class-style.test.ts +60 -0
  346. package/src/components.ts +149 -0
  347. package/src/create-portal.test.ts +90 -0
  348. package/src/create-portal.ts +74 -0
  349. package/src/create-tunnel.test.ts +120 -0
  350. package/src/create-tunnel.ts +136 -0
  351. package/src/descriptor-to-angular/descriptor-outlet.test.ts +94 -0
  352. package/src/descriptor-to-angular/index.ts +190 -0
  353. package/src/host-instance/host-instance.test.ts +49 -0
  354. package/src/host-instance/index.ts +36 -0
  355. package/src/index.ts +257 -0
  356. package/src/modules/animated/animated-scroll-view.test.ts +85 -0
  357. package/src/modules/animated/create-animated-component.ts +435 -0
  358. package/src/modules/animated/index.ts +105 -0
  359. package/src/modules/app-registry/app-registry.test.ts +106 -0
  360. package/src/modules/app-registry/index.ts +60 -0
  361. package/src/modules/status-bar.test.ts +50 -0
  362. package/src/modules/status-bar.ts +57 -0
  363. package/src/primitives/index.ts +119 -0
  364. package/src/primitives/shared.ts +191 -0
  365. package/src/render.test.ts +147 -0
  366. package/src/render.ts +224 -0
  367. package/src/renderer.test.ts +179 -0
  368. package/src/renderer.ts +407 -0
  369. package/src/services/color-scheme.service.ts +27 -0
  370. package/src/services/index.ts +2 -0
  371. package/src/services/services.test.ts +163 -0
  372. package/src/services/window-dimensions.service.ts +41 -0
@@ -0,0 +1,1162 @@
1
+ // VirtualizedList, the Angular lifecycle half. The windowing engine (offset table, window
2
+ // compute, batch throttle, viewability, edge-reached, the child PLAN, the imperative-handle
3
+ // geometry) lives in @symbiote-native/components/state, shared verbatim with the React and Vue adapters
4
+ // (<adapters_reach_full_feature_parity>). Here Angular supplies only the lifecycle: plain fields
5
+ // for scroll offset / viewport / measurement bumps, a once-per-CD metrics + view recompute in
6
+ // ngDoCheck (the Angular twin of React render / Vue `computed` — it owns the controlled
7
+ // committedWindow throttle and assembles the windowed cells before the template bindings are read),
8
+ // and the after-commit work (batch fill, onEndReached/onStartReached, viewability, initialScroll, MVCP)
9
+ // in ngAfterViewChecked. OnPush + ChangeDetectorRef.markForCheck() drives re-render off the native
10
+ // scroll/layout/measure callbacks (they fire outside Angular's own event bindings, so they must
11
+ // mark the view dirty). This is the Angular twin of the React useReducer/useEffect and Vue
12
+ // ref/computed/watch over the same shared functions. It composes the Angular ScrollView, exactly
13
+ // as the React/Vue lists drive their ScrollView.
14
+ //
15
+ // Per-item rendering is TEMPLATES, not a callback: React/Vue `renderItem: (info) => element` does
16
+ // not translate to Angular. The app supplies the cell via `<ng-template vListItem>` (and the
17
+ // header/footer/empty/separator slots via vListHeader/vListFooter/vListEmpty/vListSeparator); the
18
+ // list captures them with @ContentChild and stamps the WINDOWED slice through VListOutletDirective
19
+ // (a core-only NgTemplateOutlet twin — @angular/common is not a dependency). See ./directives.ts.
20
+ // Every React/Vue behavior is present (windowing, onEndReached, viewability, headers/footers/empty/
21
+ // separators, refresh, imperative scroll, horizontal, inverted, MVCP); only the cell AUTHORING
22
+ // shape differs, per the per-adapter children/render split of
23
+ // <prop_types_split_agnostic_vs_per_adapter>.
24
+ //
25
+ // Lists have no Descriptor render fn (the cell content is the framework's own children); see
26
+ // core/components/.docs-note-lists.md. Cells/spacers are plain symbiote-view host elements.
27
+ import { CUSTOM_ELEMENTS_SCHEMA, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChild, ElementRef, EventEmitter, Input, Output, ViewChild, inject, } from '@angular/core';
28
+ import { DEFAULT_END_REACHED_THRESHOLD, DEFAULT_INITIAL_NUM_TO_RENDER, DEFAULT_MAX_TO_RENDER_PER_BATCH, DEFAULT_START_REACHED_THRESHOLD, DEFAULT_UPDATE_CELLS_BATCHING_PERIOD, DEFAULT_WINDOW_SIZE, EMPTY_OFFSET, FIRST_INDEX, INVERTED_X_STYLE, INVERTED_Y_STYLE, NO_CONTENT_LENGTH_SENT, averageMeasuredLength, buildListPlan, buildOffsets, buildViewabilityPairs, computeEndReached, computeStartReached, computeViewableSet, computeWindow, diffViewable, highestMeasuredIndex, maxMinimumViewTime, offsetForIndex, readLayoutLength, readScrollOffset, resolveAccessibilityProps, throttleWindow, } from '@symbiote-native/components';
29
+ import { dlog, flattenStyle, } from '@symbiote-native/engine';
30
+ import { ScrollView } from '../scroll-view';
31
+ import { RefreshControl } from '../refresh-control';
32
+ import { anchorHostStyle, ViewHost } from '../../primitives';
33
+ import { VListEmptyDirective, VListFooterDirective, VListHeaderDirective, VListItemDirective, VListOutletDirective, VListSeparatorDirective, } from './directives';
34
+ import * as i0 from "@angular/core";
35
+ export { VListEmptyDirective, VListFooterDirective, VListHeaderDirective, VListItemDirective, VListSeparatorDirective, } from './directives';
36
+ export class VirtualizedList {
37
+ // The list's edge/viewability/failure events as real Angular events: `(endReached)="…"`, not
38
+ // `[onEndReached]="…"`. See handleRefresh/accessibility*Tick below for how the still-callback-
39
+ // shaped ScrollView/RefreshControl @Input()s are fed from these.
40
+ endReached = new EventEmitter();
41
+ startReached = new EventEmitter();
42
+ refresh = new EventEmitter();
43
+ viewableItemsChanged = new EventEmitter();
44
+ scrollToIndexFailed = new EventEmitter();
45
+ accessibilityAction = new EventEmitter();
46
+ accessibilityTap = new EventEmitter();
47
+ magicTap = new EventEmitter();
48
+ accessibilityEscape = new EventEmitter();
49
+ data;
50
+ getItem;
51
+ getItemCount;
52
+ keyExtractor;
53
+ getItemLayout;
54
+ horizontal;
55
+ inverted;
56
+ extraData;
57
+ onEndReachedThreshold;
58
+ onStartReachedThreshold;
59
+ refreshing;
60
+ progressViewOffset;
61
+ // Set explicitly by a wrapper (FlatList/VirtualizedSectionList) that ALWAYS binds
62
+ // `(refresh)="refresh.emit()"` on this component to re-forward the event outward — that binding
63
+ // itself makes `this.refresh.observed` permanently true (Angular subscribes unconditionally the
64
+ // moment a template writes `(refresh)="…"`, regardless of what the handler does), so `.observed`
65
+ // can no longer tell "the app actually wants pull-to-refresh" from "a wrapper is just forwarding
66
+ // the event". A wrapper passes its OWN public `refresh.observed` here instead; direct usage
67
+ // (no wrapper) falls back to this component's own `.observed`, unchanged from before.
68
+ refreshRequested;
69
+ viewabilityConfig;
70
+ viewabilityConfigCallbackPairs;
71
+ initialNumToRender;
72
+ initialScrollIndex;
73
+ maxToRenderPerBatch;
74
+ updateCellsBatchingPeriod;
75
+ windowSize;
76
+ stickyHeaderIndices;
77
+ maintainVisibleContentPosition;
78
+ onScroll;
79
+ onScrollBeginDrag;
80
+ onScrollEndDrag;
81
+ onMomentumScrollBegin;
82
+ onMomentumScrollEnd;
83
+ scrollEventThrottle;
84
+ keyboardShouldPersistTaps;
85
+ keyboardDismissMode;
86
+ style;
87
+ contentContainerStyle;
88
+ testID;
89
+ nativeID;
90
+ accessible;
91
+ accessibilityLabel;
92
+ accessibilityHint;
93
+ accessibilityRole;
94
+ accessibilityState;
95
+ accessibilityValue;
96
+ accessibilityActions;
97
+ accessibilityLabelledBy;
98
+ importantForAccessibility;
99
+ accessibilityLiveRegion;
100
+ screenReaderFocusable;
101
+ accessibilityViewIsModal;
102
+ accessibilityElementsHidden;
103
+ accessibilityIgnoresInvertColors;
104
+ accessibilityLanguage;
105
+ accessibilityRespondsToUserInteraction;
106
+ accessibilityShowsLargeContentViewer;
107
+ accessibilityLargeContentTitle;
108
+ role;
109
+ ariaLabel;
110
+ ariaLabelledBy;
111
+ ariaLive;
112
+ ariaHidden;
113
+ ariaBusy;
114
+ ariaChecked;
115
+ ariaDisabled;
116
+ ariaExpanded;
117
+ ariaSelected;
118
+ ariaModal;
119
+ ariaValueMax;
120
+ ariaValueMin;
121
+ ariaValueNow;
122
+ ariaValueText;
123
+ // The cell + slot templates the app authors (the Angular twin of renderItem / ListHeaderComponent
124
+ // / ListFooterComponent / ListEmptyComponent / ItemSeparatorComponent), captured from projected
125
+ // <ng-template> content. Resolved by ngAfterContentInit, read each ngDoCheck (from the 2nd CD on).
126
+ itemDir;
127
+ headerDir;
128
+ footerDir;
129
+ emptyDir;
130
+ separatorDir;
131
+ // The composed inner scroll view. Its instance IS an IScrollViewHandle (scrollTo / scrollToEnd /
132
+ // flashScrollIndicators / getScrollNode), so the imperative handle delegates straight to it.
133
+ // Available from ngAfterViewInit on; the handle reads the node lazily and no-ops before commit.
134
+ scrollView;
135
+ // --- template-bound view state, assembled in ngDoCheck (recomputeView) ---
136
+ itemCount = EMPTY_OFFSET;
137
+ windowCells = [];
138
+ leadingSpacerStyle = null;
139
+ trailingSpacerStyle = null;
140
+ cellStyle = undefined;
141
+ renderedStickyIndices = undefined;
142
+ // Bound to the template's `[style]="resolvedStyle"`, which Angular compiles to the built-in
143
+ // ɵɵstyleMap instruction — it only understands a flat object, never an array (RN's own
144
+ // `style={[a, b]}` composition idiom crashes deep inside Angular's styling engine), so this
145
+ // is always pre-flattened via the engine's own flattenStyle, never left as an array.
146
+ resolvedStyle = undefined;
147
+ resolvedContentContainerStyle = undefined;
148
+ resolvedMaintainVisibleContentPosition = undefined;
149
+ // The offset we are imperatively driving native to before the scroll handle attaches (rides down
150
+ // as contentOffset). A fresh object identity each push so the commit re-applies a repeated value.
151
+ commandedOffset = undefined;
152
+ // --- reactive scalars (mutated by the native callbacks; markForCheck re-runs the CD) ---
153
+ scrollOffset = EMPTY_OFFSET;
154
+ viewportLength = EMPTY_OFFSET;
155
+ measureVersion = EMPTY_OFFSET;
156
+ // --- non-render state (the Angular twin of refs that never trigger a render) ---
157
+ metricsCore = {
158
+ count: EMPTY_OFFSET,
159
+ offsets: [],
160
+ lengths: [],
161
+ total: EMPTY_OFFSET,
162
+ first: FIRST_INDEX,
163
+ last: -1,
164
+ target: { first: FIRST_INDEX, last: -1 },
165
+ averageLength: EMPTY_OFFSET,
166
+ };
167
+ measured = new Map();
168
+ cellMeasures = new Map();
169
+ separatorOverrides = new Map();
170
+ // The previously committed window, grown by at most maxToRenderPerBatch per tick (no snap).
171
+ committedWindow = { first: FIRST_INDEX, last: -1 };
172
+ sentEndForContentLength = NO_CONTENT_LENGTH_SENT;
173
+ sentStartForContentLength = NO_CONTENT_LENGTH_SENT;
174
+ lastViewable = new Map();
175
+ viewableTimer = null;
176
+ batchTimer = null;
177
+ hasInteracted = false;
178
+ appliedInitialScroll = false;
179
+ firstVisibleKey = null;
180
+ // Dedupes the after-commit effects: they run only when the windowing signature changed.
181
+ lastEffectSignature = '';
182
+ // Dedupes ngDoCheck's own recompute. WITHOUT this, recomputeView() unconditionally rebuilds
183
+ // windowCells (and each cell's `separators` handle — fresh closures every call) on EVERY CD pass,
184
+ // including ones triggered by something else entirely in the app. A fresh context object flows
185
+ // into VListOutletDirective, which (correctly) sees its `context` @Input() change and calls
186
+ // `viewRef.markForCheck()` — which reschedules ANOTHER change-detection tick via the zoneless
187
+ // scheduler (adapters/angular/src/render.ts). Recomputing unconditionally therefore free-runs
188
+ // forever the moment a list actually has cells to stamp (a real, previously-dormant bug only
189
+ // exposed once flat-list.test.ts's projection fix let cells render for the first time — see that
190
+ // test's comment). Guarding recompute behind "did anything relevant actually change" breaks the
191
+ // cycle: unrelated CD passes reuse the same windowCells/context identities, so
192
+ // VListOutletDirective's ngOnChanges sees no change and never reschedules.
193
+ lastRecompute = undefined;
194
+ cdr = inject(ChangeDetectorRef);
195
+ // This component's OWN host — the non-painting anchor `class="..."` at the use site resolves
196
+ // onto (see anchorHostStyle's doc comment) — NOT `scrollView` above, which targets the real
197
+ // inner `<ScrollView>` one level down (itself its own separate anchor host).
198
+ elementRef = inject(ElementRef);
199
+ get foldedAccessibility() {
200
+ return resolveAccessibilityProps({
201
+ testID: this.testID,
202
+ nativeID: this.nativeID,
203
+ accessible: this.accessible,
204
+ accessibilityLabel: this.accessibilityLabel,
205
+ accessibilityHint: this.accessibilityHint,
206
+ accessibilityRole: this.accessibilityRole,
207
+ accessibilityState: this.accessibilityState,
208
+ accessibilityValue: this.accessibilityValue,
209
+ accessibilityActions: this.accessibilityActions,
210
+ accessibilityLabelledBy: this.accessibilityLabelledBy,
211
+ importantForAccessibility: this.importantForAccessibility,
212
+ accessibilityLiveRegion: this.accessibilityLiveRegion,
213
+ screenReaderFocusable: this.screenReaderFocusable,
214
+ accessibilityViewIsModal: this.accessibilityViewIsModal,
215
+ accessibilityElementsHidden: this.accessibilityElementsHidden,
216
+ accessibilityIgnoresInvertColors: this.accessibilityIgnoresInvertColors,
217
+ accessibilityLanguage: this.accessibilityLanguage,
218
+ accessibilityRespondsToUserInteraction: this.accessibilityRespondsToUserInteraction,
219
+ accessibilityShowsLargeContentViewer: this.accessibilityShowsLargeContentViewer,
220
+ accessibilityLargeContentTitle: this.accessibilityLargeContentTitle,
221
+ role: this.role,
222
+ 'aria-label': this.ariaLabel,
223
+ 'aria-labelledby': this.ariaLabelledBy,
224
+ 'aria-live': this.ariaLive,
225
+ 'aria-hidden': this.ariaHidden,
226
+ 'aria-busy': this.ariaBusy,
227
+ 'aria-checked': this.ariaChecked,
228
+ 'aria-disabled': this.ariaDisabled,
229
+ 'aria-expanded': this.ariaExpanded,
230
+ 'aria-selected': this.ariaSelected,
231
+ 'aria-modal': this.ariaModal,
232
+ 'aria-valuemax': this.ariaValueMax,
233
+ 'aria-valuemin': this.ariaValueMin,
234
+ 'aria-valuenow': this.ariaValueNow,
235
+ 'aria-valuetext': this.ariaValueText,
236
+ });
237
+ }
238
+ get shouldRenderRefreshControl() {
239
+ return this.refreshRequested ?? this.refresh.observed;
240
+ }
241
+ get isHorizontal() {
242
+ return this.horizontal === true;
243
+ }
244
+ get isInverted() {
245
+ return this.inverted === true;
246
+ }
247
+ get windowSizeValue() {
248
+ return this.windowSize ?? DEFAULT_WINDOW_SIZE;
249
+ }
250
+ get initialNumToRenderValue() {
251
+ return this.initialNumToRender ?? DEFAULT_INITIAL_NUM_TO_RENDER;
252
+ }
253
+ get maxToRenderPerBatchValue() {
254
+ return this.maxToRenderPerBatch ?? DEFAULT_MAX_TO_RENDER_PER_BATCH;
255
+ }
256
+ get updateCellsBatchingPeriodValue() {
257
+ return this.updateCellsBatchingPeriod ?? DEFAULT_UPDATE_CELLS_BATCHING_PERIOD;
258
+ }
259
+ get onEndReachedThresholdValue() {
260
+ return this.onEndReachedThreshold ?? DEFAULT_END_REACHED_THRESHOLD;
261
+ }
262
+ get onStartReachedThresholdValue() {
263
+ return this.onStartReachedThreshold ?? DEFAULT_START_REACHED_THRESHOLD;
264
+ }
265
+ // ScrollView's onScroll stays an @Input() callback (an Animated.event(...) target must be able to
266
+ // flow through it, which an @Output() can't carry), so this is a stable arrow field passed
267
+ // straight to [onScroll]. onLayout is a real @Output() now, bound via (layout)="onLayoutTick($event)".
268
+ onScrollTick = (event) => {
269
+ const offset = readScrollOffset(event, this.isHorizontal);
270
+ if (offset === undefined)
271
+ return;
272
+ dlog(`Angular VirtualizedList onScroll offset=${offset}`);
273
+ // First scroll is the interaction that ungates waitForInteraction configs.
274
+ this.hasInteracted = true;
275
+ this.scrollOffset = offset;
276
+ // A real native scroll supersedes any pending commanded offset.
277
+ this.commandedOffset = undefined;
278
+ // Compose, don't clobber: internal windowing ran first, now the user's onScroll.
279
+ this.onScroll?.(event);
280
+ this.cdr.markForCheck();
281
+ };
282
+ onLayoutTick = (event) => {
283
+ const length = readLayoutLength(event, this.isHorizontal);
284
+ if (length === undefined)
285
+ return;
286
+ dlog(`Angular VirtualizedList onLayout viewport=${length}`);
287
+ this.viewportLength = length;
288
+ this.cdr.markForCheck();
289
+ };
290
+ // RefreshControl's refresh and ScrollView's accessibility events are real @Output()s now, bound
291
+ // via (refresh)="handleRefresh()" / (accessibilityAction)="accessibilityActionTick($event)" etc.
292
+ // — these fields just adapt VirtualizedList's own @Output() into a plain re-emit callback.
293
+ handleRefresh = () => {
294
+ this.refresh.emit();
295
+ };
296
+ accessibilityActionTick = (event) => {
297
+ this.accessibilityAction.emit(event);
298
+ };
299
+ accessibilityTapTick = (event) => {
300
+ this.accessibilityTap.emit(event);
301
+ };
302
+ magicTapTick = (event) => {
303
+ this.magicTap.emit(event);
304
+ };
305
+ accessibilityEscapeTick = (event) => {
306
+ this.accessibilityEscape.emit(event);
307
+ };
308
+ keyFor = (index) => {
309
+ const item = this.getItem(this.data, index);
310
+ return this.keyExtractor ? this.keyExtractor(item, index) : String(index);
311
+ };
312
+ // Once-per-CD recompute, BEFORE the template bindings are read (so the freshly computed
313
+ // template-bound fields render this pass — computing them in ngAfterContentChecked instead would
314
+ // trip ExpressionChangedAfterItHasBeenChecked). recomputeMetrics owns the controlled committedWindow
315
+ // throttle (the side effect React runs during render); ngDoCheck is its single evaluation point, so
316
+ // the window grows exactly one step per CD. The projected templates (ContentChild) are resolved
317
+ // from the second CD on; the first paint (count/viewport still 0) corrects on the layout-driven CD.
318
+ ngDoCheck() {
319
+ const recomputeInputs = [
320
+ this.data,
321
+ this.extraData,
322
+ this.getItemLayout,
323
+ this.keyExtractor,
324
+ this.isHorizontal,
325
+ this.isInverted,
326
+ this.windowSizeValue,
327
+ this.initialNumToRenderValue,
328
+ this.maxToRenderPerBatchValue,
329
+ this.stickyHeaderIndices,
330
+ this.maintainVisibleContentPosition,
331
+ this.style,
332
+ this.contentContainerStyle,
333
+ this.scrollOffset,
334
+ this.viewportLength,
335
+ this.measureVersion,
336
+ this.headerDir !== undefined,
337
+ this.footerDir !== undefined,
338
+ this.emptyDir !== undefined,
339
+ this.separatorDir !== undefined,
340
+ ];
341
+ const previous = this.lastRecompute;
342
+ this.lastRecompute = recomputeInputs;
343
+ if (previous !== undefined &&
344
+ previous.length === recomputeInputs.length &&
345
+ previous.every((value, index) => value === recomputeInputs[index])) {
346
+ return;
347
+ }
348
+ this.recomputeMetrics();
349
+ this.recomputeView();
350
+ }
351
+ ngAfterViewChecked() {
352
+ const m = this.metricsCore;
353
+ const signature = `${this.scrollOffset}|${this.viewportLength}|${m.first}|${m.last}|${m.count}|${m.total}|${this.measureVersion}`;
354
+ if (signature === this.lastEffectSignature)
355
+ return;
356
+ this.lastEffectSignature = signature;
357
+ this.effectBatchFill();
358
+ this.effectEndReached();
359
+ this.effectStartReached();
360
+ this.effectViewability();
361
+ this.effectInitialScroll();
362
+ this.effectMaintainVisibleContentPosition();
363
+ }
364
+ ngOnDestroy() {
365
+ if (this.viewableTimer !== null)
366
+ clearTimeout(this.viewableTimer);
367
+ if (this.batchTimer !== null)
368
+ clearTimeout(this.batchTimer);
369
+ }
370
+ recomputeMetrics() {
371
+ const count = this.getItemCount(this.data);
372
+ const gil = this.getItemLayout;
373
+ const data = this.data;
374
+ const fixedLayout = gil !== undefined
375
+ ? (index) => {
376
+ const layout = gil(data, index);
377
+ return { length: layout.length, offset: layout.offset };
378
+ }
379
+ : undefined;
380
+ const averageLength = fixedLayout !== undefined
381
+ ? count > FIRST_INDEX
382
+ ? fixedLayout(FIRST_INDEX).length
383
+ : EMPTY_OFFSET
384
+ : averageMeasuredLength(this.measured);
385
+ const { offsets, lengths, total } = buildOffsets(count, this.measured, fixedLayout, averageLength);
386
+ const target = computeWindow(count, offsets, lengths, this.scrollOffset, this.viewportLength, this.windowSizeValue, this.initialNumToRenderValue);
387
+ const throttled = throttleWindow(target, this.committedWindow, this.maxToRenderPerBatchValue);
388
+ this.committedWindow = throttled;
389
+ this.metricsCore = {
390
+ count,
391
+ offsets,
392
+ lengths,
393
+ total,
394
+ first: throttled.first,
395
+ last: throttled.last,
396
+ target,
397
+ averageLength,
398
+ };
399
+ }
400
+ recomputeView() {
401
+ const m = this.metricsCore;
402
+ this.itemCount = m.count;
403
+ const hasHeader = this.headerDir !== undefined;
404
+ const hasSeparators = this.separatorDir !== undefined;
405
+ const stickySet = this.stickyHeaderIndices !== undefined ? new Set(this.stickyHeaderIndices) : undefined;
406
+ this.resolvedContentContainerStyle = this.isHorizontal
407
+ ? [this.contentContainerStyle, { width: m.total }]
408
+ : this.contentContainerStyle;
409
+ this.resolvedStyle = flattenStyle([
410
+ anchorHostStyle(this.elementRef),
411
+ this.isInverted
412
+ ? [this.style, this.isHorizontal ? INVERTED_X_STYLE : INVERTED_Y_STYLE]
413
+ : this.style,
414
+ ]);
415
+ this.cellStyle = this.isInverted
416
+ ? this.isHorizontal
417
+ ? INVERTED_X_STYLE
418
+ : INVERTED_Y_STYLE
419
+ : undefined;
420
+ this.resolvedMaintainVisibleContentPosition =
421
+ this.maintainVisibleContentPosition === undefined
422
+ ? undefined
423
+ : {
424
+ ...this.maintainVisibleContentPosition,
425
+ minIndexForVisible: this.maintainVisibleContentPosition.minIndexForVisible + (hasHeader ? 1 : 0),
426
+ };
427
+ if (m.count === FIRST_INDEX) {
428
+ this.windowCells = [];
429
+ this.leadingSpacerStyle = null;
430
+ this.trailingSpacerStyle = null;
431
+ this.renderedStickyIndices = undefined;
432
+ dlog(`Angular VirtualizedList empty (viewport=${this.viewportLength})`);
433
+ return;
434
+ }
435
+ const plan = buildListPlan({
436
+ count: m.count,
437
+ first: m.first,
438
+ last: m.last,
439
+ offsets: m.offsets,
440
+ lengths: m.lengths,
441
+ total: m.total,
442
+ keyFor: this.keyFor,
443
+ stickyIndices: stickySet,
444
+ hasHeader,
445
+ hasSeparators,
446
+ });
447
+ this.leadingSpacerStyle =
448
+ plan.leadingExtent > EMPTY_OFFSET ? this.spacerStyle(plan.leadingExtent) : null;
449
+ this.trailingSpacerStyle =
450
+ plan.trailingExtent > EMPTY_OFFSET ? this.spacerStyle(plan.trailingExtent) : null;
451
+ this.renderedStickyIndices =
452
+ stickySet !== undefined && plan.stickyChildPositions.length > 0
453
+ ? plan.stickyChildPositions
454
+ : undefined;
455
+ const cells = [];
456
+ for (const planned of plan.cells) {
457
+ const item = this.getItem(this.data, planned.index);
458
+ const context = {
459
+ $implicit: item,
460
+ index: planned.index,
461
+ separators: this.makeSeparators(planned.index),
462
+ };
463
+ let separatorContext;
464
+ if (hasSeparators && planned.index < m.last) {
465
+ separatorContext = this.buildSeparatorContext(planned.index, item);
466
+ }
467
+ cells.push({
468
+ key: planned.key,
469
+ index: planned.index,
470
+ context,
471
+ measure: this.cellMeasure(planned.index),
472
+ separatorContext,
473
+ });
474
+ }
475
+ this.windowCells = cells;
476
+ dlog(`Angular VirtualizedList window [${m.first}, ${m.last}] of ${m.count} ` +
477
+ `(offset=${this.scrollOffset}, viewport=${this.viewportLength}, rendered=${cells.length})`);
478
+ }
479
+ buildSeparatorContext(index, item) {
480
+ const overrides = this.separatorOverrides.get(index);
481
+ const highlighted = overrides?.highlighted ?? false;
482
+ const context = {
483
+ $implicit: highlighted,
484
+ highlighted,
485
+ leadingItem: item,
486
+ trailingItem: this.getItem(this.data, index + 1),
487
+ };
488
+ // Fold any custom updateProps keys through the context's index signature (RN lets a row drive
489
+ // arbitrary separator props); the typed fields above stay authoritative.
490
+ if (overrides !== undefined) {
491
+ for (const key of Object.keys(overrides)) {
492
+ if (key === 'highlighted' || key === 'leadingItem' || key === 'trailingItem')
493
+ continue;
494
+ context[key] = overrides[key];
495
+ }
496
+ }
497
+ return context;
498
+ }
499
+ spacerStyle(extent) {
500
+ return this.isHorizontal ? { width: extent } : { height: extent };
501
+ }
502
+ cellMeasure(index) {
503
+ const existing = this.cellMeasures.get(index);
504
+ if (existing !== undefined)
505
+ return existing;
506
+ const measure = (event) => {
507
+ if (this.getItemLayout !== undefined)
508
+ return;
509
+ const length = readLayoutLength(event, this.isHorizontal);
510
+ if (length === undefined)
511
+ return;
512
+ if (this.measured.get(index) === length)
513
+ return;
514
+ this.measured.set(index, length);
515
+ dlog(`Angular VirtualizedList cell ${index} measured length=${length}`);
516
+ this.measureVersion += 1;
517
+ this.cdr.markForCheck();
518
+ };
519
+ this.cellMeasures.set(index, measure);
520
+ return measure;
521
+ }
522
+ // Per-cell onLayout rides the engine's structural (layout) event channel — Angular forbids an
523
+ // [onLayout] property binding (NG8002). $event arrives untyped, narrowed before reaching measure.
524
+ handleCellLayout(measure, event) {
525
+ if (this.isSymbioteEvent(event))
526
+ measure(event);
527
+ }
528
+ isSymbioteEvent(value) {
529
+ return typeof value === 'object' && value !== null && 'nativeEvent' in value;
530
+ }
531
+ mergeSeparator(gapIndex, patch) {
532
+ const count = this.metricsCore.count;
533
+ if (gapIndex < FIRST_INDEX || gapIndex > count - 2)
534
+ return;
535
+ this.separatorOverrides.set(gapIndex, { ...this.separatorOverrides.get(gapIndex), ...patch });
536
+ this.cdr.markForCheck();
537
+ }
538
+ makeSeparators(index) {
539
+ return {
540
+ highlight: () => {
541
+ dlog(`Angular VirtualizedList separator highlight cell=${index}`);
542
+ this.mergeSeparator(index - 1, { highlighted: true });
543
+ this.mergeSeparator(index, { highlighted: true });
544
+ },
545
+ unhighlight: () => {
546
+ dlog(`Angular VirtualizedList separator unhighlight cell=${index}`);
547
+ this.mergeSeparator(index - 1, { highlighted: false });
548
+ this.mergeSeparator(index, { highlighted: false });
549
+ },
550
+ updateProps: (select, newProps) => {
551
+ this.mergeSeparator(select === 'leading' ? index - 1 : index, newProps);
552
+ },
553
+ };
554
+ }
555
+ // ---- imperative handle (the shared IVirtualizedListHandle surface) ----
556
+ scrollToOffset(params) {
557
+ this.scrollToPixel(params.offset, params.animated ?? true);
558
+ }
559
+ scrollToIndex(params) {
560
+ const m = this.metricsCore;
561
+ // No getItemLayout AND the target is past the last measured cell: report the failure instead of
562
+ // scrolling to a fabricated estimate (RN VirtualizedList.js).
563
+ if (this.getItemLayout === undefined && params.index > highestMeasuredIndex(this.measured)) {
564
+ dlog(`Angular VirtualizedList onScrollToIndexFailed index=${params.index} ` +
565
+ `highestMeasured=${highestMeasuredIndex(this.measured)} (no getItemLayout)`);
566
+ this.scrollToIndexFailed.emit({
567
+ index: params.index,
568
+ highestMeasuredFrameIndex: highestMeasuredIndex(this.measured),
569
+ averageItemLength: m.averageLength,
570
+ });
571
+ return;
572
+ }
573
+ this.scrollToPixel(this.offsetForIndexLocal(params.index, params.viewPosition ?? FIRST_INDEX, params.viewOffset ?? EMPTY_OFFSET), params.animated ?? true);
574
+ }
575
+ scrollToItem(params) {
576
+ const count = this.metricsCore.count;
577
+ for (let index = FIRST_INDEX; index < count; index += 1) {
578
+ if (this.getItem(this.data, index) === params.item) {
579
+ this.scrollToPixel(this.offsetForIndexLocal(index, params.viewPosition ?? FIRST_INDEX, EMPTY_OFFSET), params.animated ?? true);
580
+ return;
581
+ }
582
+ }
583
+ dlog('Angular VirtualizedList scrollToItem: item not found');
584
+ }
585
+ scrollToEnd(params) {
586
+ this.scrollToPixel(Math.max(EMPTY_OFFSET, this.metricsCore.total - this.viewportLength), params?.animated ?? true);
587
+ }
588
+ flashScrollIndicators() {
589
+ this.scrollView?.flashScrollIndicators();
590
+ }
591
+ getNativeScrollRef() {
592
+ return this.scrollView ?? null;
593
+ }
594
+ getScrollableNode() {
595
+ return this.scrollView ?? null;
596
+ }
597
+ getScrollResponder() {
598
+ return this.scrollView ?? null;
599
+ }
600
+ getScrollNode() {
601
+ return this.scrollView?.getScrollNode() ?? null;
602
+ }
603
+ recordInteraction() {
604
+ this.hasInteracted = true;
605
+ }
606
+ scrollToPixel(offset, animated) {
607
+ const clamped = Math.max(EMPTY_OFFSET, offset);
608
+ const target = this.isHorizontal
609
+ ? { x: clamped, y: EMPTY_OFFSET }
610
+ : { x: EMPTY_OFFSET, y: clamped };
611
+ if (this.scrollView !== undefined) {
612
+ dlog(`Angular VirtualizedList scrollTo offset=${clamped} animated=${animated} (horizontal=${this.isHorizontal})`);
613
+ this.scrollView.scrollTo({ x: target.x, y: target.y, animated });
614
+ return;
615
+ }
616
+ dlog(`Angular VirtualizedList scrollTo offset=${clamped} pending-ref`);
617
+ this.commandedOffset = target;
618
+ this.cdr.markForCheck();
619
+ }
620
+ offsetForIndexLocal(index, viewPosition, viewOffset) {
621
+ const m = this.metricsCore;
622
+ return offsetForIndex(index, viewPosition, viewOffset, m.count, m.offsets, m.lengths, this.viewportLength);
623
+ }
624
+ // ---- after-commit effects (run in ngAfterViewChecked, the post-render seam) ----
625
+ // Batch fill: when the throttled window has not reached the target, schedule a re-render so the
626
+ // window keeps filling toward target over successive ticks (RN's incremental fill).
627
+ effectBatchFill() {
628
+ const m = this.metricsCore;
629
+ if (this.batchTimer !== null) {
630
+ clearTimeout(this.batchTimer);
631
+ this.batchTimer = null;
632
+ }
633
+ if (m.first <= m.target.first && m.last >= m.target.last)
634
+ return;
635
+ this.batchTimer = setTimeout(() => {
636
+ this.batchTimer = null;
637
+ this.measureVersion += 1;
638
+ this.cdr.markForCheck();
639
+ }, this.updateCellsBatchingPeriodValue);
640
+ }
641
+ // onEndReached: fire only when the actual last cell is rendered AND within threshold; dedup by
642
+ // content length; re-arm on scroll away from the end (RN _maybeCallOnEdgeReached).
643
+ effectEndReached() {
644
+ if (!this.endReached.observed || this.viewportLength <= EMPTY_OFFSET)
645
+ return;
646
+ const m = this.metricsCore;
647
+ const { distanceFromEnd, withinThreshold } = computeEndReached(m.total, this.scrollOffset, this.viewportLength, this.onEndReachedThresholdValue);
648
+ const lastCellRendered = m.last === m.count - 1;
649
+ if (withinThreshold && lastCellRendered && this.sentEndForContentLength !== m.total) {
650
+ this.sentEndForContentLength = m.total;
651
+ dlog(`Angular VirtualizedList endReached distanceFromEnd=${distanceFromEnd} ` +
652
+ `(last=${m.last} of ${m.count}, contentLength=${m.total})`);
653
+ this.endReached.emit({ distanceFromEnd });
654
+ }
655
+ if (!withinThreshold)
656
+ this.sentEndForContentLength = NO_CONTENT_LENGTH_SENT;
657
+ }
658
+ // startReached: the top-edge twin of endReached.
659
+ effectStartReached() {
660
+ if (!this.startReached.observed || this.viewportLength <= EMPTY_OFFSET)
661
+ return;
662
+ const m = this.metricsCore;
663
+ const { distanceFromStart, withinThreshold } = computeStartReached(this.scrollOffset, this.viewportLength, this.onStartReachedThresholdValue);
664
+ const firstCellRendered = m.first === FIRST_INDEX;
665
+ if (withinThreshold && firstCellRendered && this.sentStartForContentLength !== m.total) {
666
+ this.sentStartForContentLength = m.total;
667
+ dlog(`Angular VirtualizedList startReached distanceFromStart=${distanceFromStart} ` +
668
+ `(first=${m.first}, contentLength=${m.total})`);
669
+ this.startReached.emit({ distanceFromStart });
670
+ }
671
+ if (!withinThreshold)
672
+ this.sentStartForContentLength = NO_CONTENT_LENGTH_SENT;
673
+ }
674
+ // Viewability: recompute which rendered cells clear the threshold and, if the viewable set
675
+ // changed, fire viewableItemsChanged + every config/callback pair, honoring minimumViewTime.
676
+ effectViewability() {
677
+ const m = this.metricsCore;
678
+ const pairs = buildViewabilityPairs(this.viewableItemsChanged.observed
679
+ ? (info) => this.viewableItemsChanged.emit(info)
680
+ : undefined, this.viewabilityConfig, this.viewabilityConfigCallbackPairs);
681
+ if (pairs.length === EMPTY_OFFSET || this.viewportLength <= EMPTY_OFFSET)
682
+ return;
683
+ if (m.count === FIRST_INDEX)
684
+ return;
685
+ const { tokens, map } = computeViewableSet({
686
+ first: m.first,
687
+ last: m.last,
688
+ count: m.count,
689
+ offsets: m.offsets,
690
+ lengths: m.lengths,
691
+ scrollOffset: this.scrollOffset,
692
+ viewportLength: this.viewportLength,
693
+ data: this.data,
694
+ getItem: this.getItem,
695
+ keyExtractor: this.keyExtractor,
696
+ pairs,
697
+ hasInteracted: this.hasInteracted,
698
+ });
699
+ const diff = diffViewable(this.lastViewable, map, tokens);
700
+ if (!diff.hasChanged)
701
+ return;
702
+ const commitAndFire = () => {
703
+ this.lastViewable = map;
704
+ dlog(`Angular VirtualizedList viewable=${tokens.length} changed=${diff.changed.length} ` +
705
+ `(window [${m.first}, ${m.last}])`);
706
+ const info = {
707
+ viewableItems: tokens,
708
+ changed: diff.changed,
709
+ };
710
+ for (const pair of pairs)
711
+ pair.onViewableItemsChanged(info);
712
+ };
713
+ const minimumViewTime = maxMinimumViewTime(pairs);
714
+ if (this.viewableTimer !== null) {
715
+ clearTimeout(this.viewableTimer);
716
+ this.viewableTimer = null;
717
+ }
718
+ if (minimumViewTime > EMPTY_OFFSET) {
719
+ dlog(`Angular VirtualizedList viewability debounce ${minimumViewTime}ms (window [${m.first}, ${m.last}])`);
720
+ this.viewableTimer = setTimeout(() => {
721
+ this.viewableTimer = null;
722
+ commitAndFire();
723
+ }, minimumViewTime);
724
+ return;
725
+ }
726
+ commitAndFire();
727
+ }
728
+ // initialScrollIndex: once the first viewport is known, jump to that index a single time.
729
+ effectInitialScroll() {
730
+ if (this.initialScrollIndex === undefined || this.appliedInitialScroll)
731
+ return;
732
+ if (this.viewportLength <= EMPTY_OFFSET || this.metricsCore.count === FIRST_INDEX)
733
+ return;
734
+ this.appliedInitialScroll = true;
735
+ // The initial jump is instant (RN does not animate initialScrollIndex).
736
+ this.scrollToPixel(this.offsetForIndexLocal(this.initialScrollIndex, FIRST_INDEX, EMPTY_OFFSET), false);
737
+ }
738
+ // maintainVisibleContentPosition JS anchor adjustment: track the key of the item at
739
+ // minIndexForVisible; when a prepend moves it down, add the inserted extent in the leading SPACER
740
+ // (the off-window items native MVCP cannot see) to scrollOffset so the anchored item does not jump
741
+ // (RN getDerivedStateFromProps).
742
+ effectMaintainVisibleContentPosition() {
743
+ const m = this.metricsCore;
744
+ if (this.maintainVisibleContentPosition === undefined || m.count === FIRST_INDEX) {
745
+ this.firstVisibleKey = null;
746
+ return;
747
+ }
748
+ const minIndexForVisible = this.maintainVisibleContentPosition.minIndexForVisible;
749
+ const newFirstVisibleKey = m.count > minIndexForVisible ? this.keyFor(minIndexForVisible) : null;
750
+ const prevKey = this.firstVisibleKey;
751
+ if (prevKey !== null && newFirstVisibleKey !== null && prevKey !== newFirstVisibleKey) {
752
+ let anchorIndex = -1;
753
+ for (let index = minIndexForVisible; index < m.count; index += 1) {
754
+ if (this.keyFor(index) === prevKey) {
755
+ anchorIndex = index;
756
+ break;
757
+ }
758
+ }
759
+ if (anchorIndex > minIndexForVisible) {
760
+ const spacerEnd = Math.min(anchorIndex, this.committedWindow.first);
761
+ const insertedExtent = spacerEnd > minIndexForVisible
762
+ ? m.offsets[spacerEnd] - m.offsets[minIndexForVisible]
763
+ : EMPTY_OFFSET;
764
+ if (insertedExtent > EMPTY_OFFSET) {
765
+ const autoThreshold = this.maintainVisibleContentPosition.autoscrollToTopThreshold;
766
+ const anchoredNearTop = autoThreshold !== undefined && this.scrollOffset <= autoThreshold;
767
+ if (anchoredNearTop) {
768
+ dlog(`Angular VirtualizedList MVCP autoscroll-to-top (offset=${this.scrollOffset} <= ${autoThreshold})`);
769
+ this.scrollToPixel(EMPTY_OFFSET, true);
770
+ }
771
+ else {
772
+ dlog(`Angular VirtualizedList MVCP adjust +${insertedExtent}px ` +
773
+ `(anchor "${prevKey}" moved ${minIndexForVisible}->${anchorIndex})`);
774
+ this.scrollToPixel(this.scrollOffset + insertedExtent, false);
775
+ }
776
+ }
777
+ }
778
+ }
779
+ this.firstVisibleKey = newFirstVisibleKey;
780
+ }
781
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: VirtualizedList, deps: [], target: i0.ɵɵFactoryTarget.Component });
782
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.4", type: VirtualizedList, isStandalone: true, selector: "VirtualizedList", inputs: { data: "data", getItem: "getItem", getItemCount: "getItemCount", keyExtractor: "keyExtractor", getItemLayout: "getItemLayout", horizontal: "horizontal", inverted: "inverted", extraData: "extraData", onEndReachedThreshold: "onEndReachedThreshold", onStartReachedThreshold: "onStartReachedThreshold", refreshing: "refreshing", progressViewOffset: "progressViewOffset", refreshRequested: "refreshRequested", viewabilityConfig: "viewabilityConfig", viewabilityConfigCallbackPairs: "viewabilityConfigCallbackPairs", initialNumToRender: "initialNumToRender", initialScrollIndex: "initialScrollIndex", maxToRenderPerBatch: "maxToRenderPerBatch", updateCellsBatchingPeriod: "updateCellsBatchingPeriod", windowSize: "windowSize", stickyHeaderIndices: "stickyHeaderIndices", maintainVisibleContentPosition: "maintainVisibleContentPosition", onScroll: "onScroll", onScrollBeginDrag: "onScrollBeginDrag", onScrollEndDrag: "onScrollEndDrag", onMomentumScrollBegin: "onMomentumScrollBegin", onMomentumScrollEnd: "onMomentumScrollEnd", scrollEventThrottle: "scrollEventThrottle", keyboardShouldPersistTaps: "keyboardShouldPersistTaps", keyboardDismissMode: "keyboardDismissMode", style: "style", contentContainerStyle: "contentContainerStyle", testID: "testID", nativeID: "nativeID", accessible: "accessible", accessibilityLabel: "accessibilityLabel", accessibilityHint: "accessibilityHint", accessibilityRole: "accessibilityRole", accessibilityState: "accessibilityState", accessibilityValue: "accessibilityValue", accessibilityActions: "accessibilityActions", accessibilityLabelledBy: "accessibilityLabelledBy", importantForAccessibility: "importantForAccessibility", accessibilityLiveRegion: "accessibilityLiveRegion", screenReaderFocusable: "screenReaderFocusable", accessibilityViewIsModal: "accessibilityViewIsModal", accessibilityElementsHidden: "accessibilityElementsHidden", accessibilityIgnoresInvertColors: "accessibilityIgnoresInvertColors", accessibilityLanguage: "accessibilityLanguage", accessibilityRespondsToUserInteraction: "accessibilityRespondsToUserInteraction", accessibilityShowsLargeContentViewer: "accessibilityShowsLargeContentViewer", accessibilityLargeContentTitle: "accessibilityLargeContentTitle", role: "role", ariaLabel: "ariaLabel", ariaLabelledBy: "ariaLabelledBy", ariaLive: "ariaLive", ariaHidden: "ariaHidden", ariaBusy: "ariaBusy", ariaChecked: "ariaChecked", ariaDisabled: "ariaDisabled", ariaExpanded: "ariaExpanded", ariaSelected: "ariaSelected", ariaModal: "ariaModal", ariaValueMax: "ariaValueMax", ariaValueMin: "ariaValueMin", ariaValueNow: "ariaValueNow", ariaValueText: "ariaValueText" }, outputs: { endReached: "endReached", startReached: "startReached", refresh: "refresh", viewableItemsChanged: "viewableItemsChanged", scrollToIndexFailed: "scrollToIndexFailed", accessibilityAction: "accessibilityAction", accessibilityTap: "accessibilityTap", magicTap: "magicTap", accessibilityEscape: "accessibilityEscape" }, queries: [{ propertyName: "itemDir", first: true, predicate: VListItemDirective, descendants: true }, { propertyName: "headerDir", first: true, predicate: VListHeaderDirective, descendants: true }, { propertyName: "footerDir", first: true, predicate: VListFooterDirective, descendants: true }, { propertyName: "emptyDir", first: true, predicate: VListEmptyDirective, descendants: true }, { propertyName: "separatorDir", first: true, predicate: VListSeparatorDirective, descendants: true }], viewQueries: [{ propertyName: "scrollView", first: true, predicate: ScrollView, descendants: true }], ngImport: i0, template: `
783
+ <ScrollView
784
+ [horizontal]="isHorizontal"
785
+ [style]="resolvedStyle"
786
+ [contentContainerStyle]="resolvedContentContainerStyle"
787
+ [testID]="foldedAccessibility.testID"
788
+ [nativeID]="foldedAccessibility.nativeID"
789
+ [accessible]="foldedAccessibility.accessible"
790
+ [accessibilityLabel]="foldedAccessibility.accessibilityLabel"
791
+ [accessibilityHint]="foldedAccessibility.accessibilityHint"
792
+ [accessibilityRole]="foldedAccessibility.accessibilityRole"
793
+ [accessibilityState]="foldedAccessibility.accessibilityState"
794
+ [accessibilityValue]="foldedAccessibility.accessibilityValue"
795
+ [accessibilityActions]="foldedAccessibility.accessibilityActions"
796
+ [accessibilityLabelledBy]="foldedAccessibility.accessibilityLabelledBy"
797
+ [importantForAccessibility]="foldedAccessibility.importantForAccessibility"
798
+ [accessibilityLiveRegion]="foldedAccessibility.accessibilityLiveRegion"
799
+ [screenReaderFocusable]="foldedAccessibility.screenReaderFocusable"
800
+ [accessibilityViewIsModal]="foldedAccessibility.accessibilityViewIsModal"
801
+ [accessibilityElementsHidden]="foldedAccessibility.accessibilityElementsHidden"
802
+ [accessibilityIgnoresInvertColors]="foldedAccessibility.accessibilityIgnoresInvertColors"
803
+ [accessibilityLanguage]="foldedAccessibility.accessibilityLanguage"
804
+ [accessibilityRespondsToUserInteraction]="
805
+ foldedAccessibility.accessibilityRespondsToUserInteraction
806
+ "
807
+ [accessibilityShowsLargeContentViewer]="
808
+ foldedAccessibility.accessibilityShowsLargeContentViewer
809
+ "
810
+ [accessibilityLargeContentTitle]="foldedAccessibility.accessibilityLargeContentTitle"
811
+ (accessibilityAction)="accessibilityActionTick($event)"
812
+ (accessibilityTap)="accessibilityTapTick($event)"
813
+ (magicTap)="magicTapTick($event)"
814
+ (accessibilityEscape)="accessibilityEscapeTick($event)"
815
+ [onScroll]="onScrollTick"
816
+ (layout)="onLayoutTick($event)"
817
+ [onScrollBeginDrag]="onScrollBeginDrag"
818
+ [onScrollEndDrag]="onScrollEndDrag"
819
+ [onMomentumScrollBegin]="onMomentumScrollBegin"
820
+ [onMomentumScrollEnd]="onMomentumScrollEnd"
821
+ [scrollEventThrottle]="scrollEventThrottle"
822
+ [keyboardShouldPersistTaps]="keyboardShouldPersistTaps"
823
+ [keyboardDismissMode]="keyboardDismissMode"
824
+ [contentOffset]="commandedOffset"
825
+ [stickyHeaderIndices]="renderedStickyIndices"
826
+ [maintainVisibleContentPosition]="resolvedMaintainVisibleContentPosition"
827
+ >
828
+ @if (shouldRenderRefreshControl) {
829
+ <RefreshControl
830
+ [refreshing]="refreshing ?? false"
831
+ (refresh)="handleRefresh()"
832
+ [progressViewOffset]="progressViewOffset"
833
+ />
834
+ }
835
+
836
+ @if (headerDir !== undefined) {
837
+ <symbiote-view>
838
+ <ng-container [vListOutlet]="headerDir.templateRef"></ng-container>
839
+ </symbiote-view>
840
+ }
841
+
842
+ @if (itemCount === 0) {
843
+ @if (emptyDir !== undefined) {
844
+ <symbiote-view>
845
+ <ng-container [vListOutlet]="emptyDir.templateRef"></ng-container>
846
+ </symbiote-view>
847
+ }
848
+ } @else {
849
+ @if (leadingSpacerStyle !== null) {
850
+ <symbiote-view [style]="leadingSpacerStyle"></symbiote-view>
851
+ }
852
+ @for (cell of windowCells; track cell.key) {
853
+ <symbiote-view (layout)="handleCellLayout(cell.measure, $event)" [style]="cellStyle">
854
+ <ng-container
855
+ [vListOutlet]="itemDir?.templateRef"
856
+ [vListOutletContext]="cell.context"
857
+ ></ng-container>
858
+ </symbiote-view>
859
+ @if (cell.separatorContext !== undefined) {
860
+ <symbiote-view>
861
+ <ng-container
862
+ [vListOutlet]="separatorDir?.templateRef"
863
+ [vListOutletContext]="cell.separatorContext"
864
+ ></ng-container>
865
+ </symbiote-view>
866
+ }
867
+ }
868
+ @if (trailingSpacerStyle !== null) {
869
+ <symbiote-view [style]="trailingSpacerStyle"></symbiote-view>
870
+ }
871
+ }
872
+
873
+ @if (footerDir !== undefined) {
874
+ <symbiote-view>
875
+ <ng-container [vListOutlet]="footerDir.templateRef"></ng-container>
876
+ </symbiote-view>
877
+ }
878
+ </ScrollView>
879
+ `, isInline: true, dependencies: [{ kind: "component", type: ScrollView, selector: "ScrollView", inputs: ["style", "contentContainerStyle", "horizontal", "scrollEnabled", "showsVerticalScrollIndicator", "showsHorizontalScrollIndicator", "pagingEnabled", "bounces", "decelerationRate", "scrollEventThrottle", "contentInset", "contentOffset", "removeClippedSubviews", "snapToInterval", "snapToOffsets", "snapToAlignment", "snapToStart", "snapToEnd", "disableIntervalMomentum", "stickyHeaderIndices", "invertStickyHeaders", "StickyHeaderComponent", "keyboardDismissMode", "keyboardShouldPersistTaps", "maintainVisibleContentPosition", "alwaysBounceHorizontal", "alwaysBounceVertical", "centerContent", "scrollIndicatorInsets", "indicatorStyle", "directionalLockEnabled", "automaticallyAdjustKeyboardInsets", "contentInsetAdjustmentBehavior", "minimumZoomScale", "maximumZoomScale", "zoomScale", "bouncesZoom", "pinchGestureEnabled", "nestedScrollEnabled", "overScrollMode", "fadingEdgeLength", "persistentScrollbar", "endFillColor", "onScroll", "onScrollBeginDrag", "onScrollEndDrag", "onMomentumScrollBegin", "onMomentumScrollEnd", "testID", "nativeID", "accessible", "accessibilityLabel", "accessibilityHint", "accessibilityRole", "accessibilityState", "accessibilityValue", "accessibilityActions", "accessibilityLabelledBy", "importantForAccessibility", "accessibilityLiveRegion", "screenReaderFocusable", "accessibilityViewIsModal", "accessibilityElementsHidden", "accessibilityIgnoresInvertColors", "accessibilityLanguage", "accessibilityRespondsToUserInteraction", "accessibilityShowsLargeContentViewer", "accessibilityLargeContentTitle", "role", "aria-label", "aria-labelledby", "aria-live", "aria-hidden", "aria-busy", "aria-checked", "aria-disabled", "aria-expanded", "aria-selected", "aria-modal", "aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-valuetext"] }, { kind: "component", type: RefreshControl, selector: "RefreshControl", inputs: ["refreshing", "tintColor", "title", "titleColor", "progressViewOffset", "colors", "progressBackgroundColor", "size", "enabled", "style", "testID", "nativeID", "accessible", "accessibilityLabel", "accessibilityHint", "accessibilityRole", "accessibilityState", "accessibilityValue", "accessibilityActions", "accessibilityLabelledBy", "importantForAccessibility", "accessibilityLiveRegion", "screenReaderFocusable", "accessibilityViewIsModal", "accessibilityElementsHidden", "accessibilityIgnoresInvertColors", "accessibilityLanguage", "accessibilityRespondsToUserInteraction", "accessibilityShowsLargeContentViewer", "accessibilityLargeContentTitle", "role", "aria-label", "aria-labelledby", "aria-live", "aria-hidden", "aria-busy", "aria-checked", "aria-disabled", "aria-expanded", "aria-selected", "aria-modal", "aria-valuemax", "aria-valuemin", "aria-valuenow", "aria-valuetext"], outputs: ["refresh", "accessibilityAction", "accessibilityTap", "magicTap", "accessibilityEscape"] }, { kind: "directive", type: VListOutletDirective, selector: "[vListOutlet]", inputs: ["vListOutlet", "vListOutletContext"] }, { kind: "component", type: ViewHost, selector: "symbiote-view, View" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
880
+ }
881
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.4", ngImport: i0, type: VirtualizedList, decorators: [{
882
+ type: Component,
883
+ args: [{
884
+ selector: 'VirtualizedList',
885
+ standalone: true,
886
+ schemas: [CUSTOM_ELEMENTS_SCHEMA],
887
+ imports: [ScrollView, RefreshControl, VListOutletDirective, ViewHost],
888
+ changeDetection: ChangeDetectionStrategy.OnPush,
889
+ template: `
890
+ <ScrollView
891
+ [horizontal]="isHorizontal"
892
+ [style]="resolvedStyle"
893
+ [contentContainerStyle]="resolvedContentContainerStyle"
894
+ [testID]="foldedAccessibility.testID"
895
+ [nativeID]="foldedAccessibility.nativeID"
896
+ [accessible]="foldedAccessibility.accessible"
897
+ [accessibilityLabel]="foldedAccessibility.accessibilityLabel"
898
+ [accessibilityHint]="foldedAccessibility.accessibilityHint"
899
+ [accessibilityRole]="foldedAccessibility.accessibilityRole"
900
+ [accessibilityState]="foldedAccessibility.accessibilityState"
901
+ [accessibilityValue]="foldedAccessibility.accessibilityValue"
902
+ [accessibilityActions]="foldedAccessibility.accessibilityActions"
903
+ [accessibilityLabelledBy]="foldedAccessibility.accessibilityLabelledBy"
904
+ [importantForAccessibility]="foldedAccessibility.importantForAccessibility"
905
+ [accessibilityLiveRegion]="foldedAccessibility.accessibilityLiveRegion"
906
+ [screenReaderFocusable]="foldedAccessibility.screenReaderFocusable"
907
+ [accessibilityViewIsModal]="foldedAccessibility.accessibilityViewIsModal"
908
+ [accessibilityElementsHidden]="foldedAccessibility.accessibilityElementsHidden"
909
+ [accessibilityIgnoresInvertColors]="foldedAccessibility.accessibilityIgnoresInvertColors"
910
+ [accessibilityLanguage]="foldedAccessibility.accessibilityLanguage"
911
+ [accessibilityRespondsToUserInteraction]="
912
+ foldedAccessibility.accessibilityRespondsToUserInteraction
913
+ "
914
+ [accessibilityShowsLargeContentViewer]="
915
+ foldedAccessibility.accessibilityShowsLargeContentViewer
916
+ "
917
+ [accessibilityLargeContentTitle]="foldedAccessibility.accessibilityLargeContentTitle"
918
+ (accessibilityAction)="accessibilityActionTick($event)"
919
+ (accessibilityTap)="accessibilityTapTick($event)"
920
+ (magicTap)="magicTapTick($event)"
921
+ (accessibilityEscape)="accessibilityEscapeTick($event)"
922
+ [onScroll]="onScrollTick"
923
+ (layout)="onLayoutTick($event)"
924
+ [onScrollBeginDrag]="onScrollBeginDrag"
925
+ [onScrollEndDrag]="onScrollEndDrag"
926
+ [onMomentumScrollBegin]="onMomentumScrollBegin"
927
+ [onMomentumScrollEnd]="onMomentumScrollEnd"
928
+ [scrollEventThrottle]="scrollEventThrottle"
929
+ [keyboardShouldPersistTaps]="keyboardShouldPersistTaps"
930
+ [keyboardDismissMode]="keyboardDismissMode"
931
+ [contentOffset]="commandedOffset"
932
+ [stickyHeaderIndices]="renderedStickyIndices"
933
+ [maintainVisibleContentPosition]="resolvedMaintainVisibleContentPosition"
934
+ >
935
+ @if (shouldRenderRefreshControl) {
936
+ <RefreshControl
937
+ [refreshing]="refreshing ?? false"
938
+ (refresh)="handleRefresh()"
939
+ [progressViewOffset]="progressViewOffset"
940
+ />
941
+ }
942
+
943
+ @if (headerDir !== undefined) {
944
+ <symbiote-view>
945
+ <ng-container [vListOutlet]="headerDir.templateRef"></ng-container>
946
+ </symbiote-view>
947
+ }
948
+
949
+ @if (itemCount === 0) {
950
+ @if (emptyDir !== undefined) {
951
+ <symbiote-view>
952
+ <ng-container [vListOutlet]="emptyDir.templateRef"></ng-container>
953
+ </symbiote-view>
954
+ }
955
+ } @else {
956
+ @if (leadingSpacerStyle !== null) {
957
+ <symbiote-view [style]="leadingSpacerStyle"></symbiote-view>
958
+ }
959
+ @for (cell of windowCells; track cell.key) {
960
+ <symbiote-view (layout)="handleCellLayout(cell.measure, $event)" [style]="cellStyle">
961
+ <ng-container
962
+ [vListOutlet]="itemDir?.templateRef"
963
+ [vListOutletContext]="cell.context"
964
+ ></ng-container>
965
+ </symbiote-view>
966
+ @if (cell.separatorContext !== undefined) {
967
+ <symbiote-view>
968
+ <ng-container
969
+ [vListOutlet]="separatorDir?.templateRef"
970
+ [vListOutletContext]="cell.separatorContext"
971
+ ></ng-container>
972
+ </symbiote-view>
973
+ }
974
+ }
975
+ @if (trailingSpacerStyle !== null) {
976
+ <symbiote-view [style]="trailingSpacerStyle"></symbiote-view>
977
+ }
978
+ }
979
+
980
+ @if (footerDir !== undefined) {
981
+ <symbiote-view>
982
+ <ng-container [vListOutlet]="footerDir.templateRef"></ng-container>
983
+ </symbiote-view>
984
+ }
985
+ </ScrollView>
986
+ `,
987
+ }]
988
+ }], propDecorators: { endReached: [{
989
+ type: Output
990
+ }], startReached: [{
991
+ type: Output
992
+ }], refresh: [{
993
+ type: Output
994
+ }], viewableItemsChanged: [{
995
+ type: Output
996
+ }], scrollToIndexFailed: [{
997
+ type: Output
998
+ }], accessibilityAction: [{
999
+ type: Output
1000
+ }], accessibilityTap: [{
1001
+ type: Output
1002
+ }], magicTap: [{
1003
+ type: Output
1004
+ }], accessibilityEscape: [{
1005
+ type: Output
1006
+ }], data: [{
1007
+ type: Input,
1008
+ args: [{ required: true }]
1009
+ }], getItem: [{
1010
+ type: Input,
1011
+ args: [{ required: true }]
1012
+ }], getItemCount: [{
1013
+ type: Input,
1014
+ args: [{ required: true }]
1015
+ }], keyExtractor: [{
1016
+ type: Input
1017
+ }], getItemLayout: [{
1018
+ type: Input
1019
+ }], horizontal: [{
1020
+ type: Input
1021
+ }], inverted: [{
1022
+ type: Input
1023
+ }], extraData: [{
1024
+ type: Input
1025
+ }], onEndReachedThreshold: [{
1026
+ type: Input
1027
+ }], onStartReachedThreshold: [{
1028
+ type: Input
1029
+ }], refreshing: [{
1030
+ type: Input
1031
+ }], progressViewOffset: [{
1032
+ type: Input
1033
+ }], refreshRequested: [{
1034
+ type: Input
1035
+ }], viewabilityConfig: [{
1036
+ type: Input
1037
+ }], viewabilityConfigCallbackPairs: [{
1038
+ type: Input
1039
+ }], initialNumToRender: [{
1040
+ type: Input
1041
+ }], initialScrollIndex: [{
1042
+ type: Input
1043
+ }], maxToRenderPerBatch: [{
1044
+ type: Input
1045
+ }], updateCellsBatchingPeriod: [{
1046
+ type: Input
1047
+ }], windowSize: [{
1048
+ type: Input
1049
+ }], stickyHeaderIndices: [{
1050
+ type: Input
1051
+ }], maintainVisibleContentPosition: [{
1052
+ type: Input
1053
+ }], onScroll: [{
1054
+ type: Input
1055
+ }], onScrollBeginDrag: [{
1056
+ type: Input
1057
+ }], onScrollEndDrag: [{
1058
+ type: Input
1059
+ }], onMomentumScrollBegin: [{
1060
+ type: Input
1061
+ }], onMomentumScrollEnd: [{
1062
+ type: Input
1063
+ }], scrollEventThrottle: [{
1064
+ type: Input
1065
+ }], keyboardShouldPersistTaps: [{
1066
+ type: Input
1067
+ }], keyboardDismissMode: [{
1068
+ type: Input
1069
+ }], style: [{
1070
+ type: Input
1071
+ }], contentContainerStyle: [{
1072
+ type: Input
1073
+ }], testID: [{
1074
+ type: Input
1075
+ }], nativeID: [{
1076
+ type: Input
1077
+ }], accessible: [{
1078
+ type: Input
1079
+ }], accessibilityLabel: [{
1080
+ type: Input
1081
+ }], accessibilityHint: [{
1082
+ type: Input
1083
+ }], accessibilityRole: [{
1084
+ type: Input
1085
+ }], accessibilityState: [{
1086
+ type: Input
1087
+ }], accessibilityValue: [{
1088
+ type: Input
1089
+ }], accessibilityActions: [{
1090
+ type: Input
1091
+ }], accessibilityLabelledBy: [{
1092
+ type: Input
1093
+ }], importantForAccessibility: [{
1094
+ type: Input
1095
+ }], accessibilityLiveRegion: [{
1096
+ type: Input
1097
+ }], screenReaderFocusable: [{
1098
+ type: Input
1099
+ }], accessibilityViewIsModal: [{
1100
+ type: Input
1101
+ }], accessibilityElementsHidden: [{
1102
+ type: Input
1103
+ }], accessibilityIgnoresInvertColors: [{
1104
+ type: Input
1105
+ }], accessibilityLanguage: [{
1106
+ type: Input
1107
+ }], accessibilityRespondsToUserInteraction: [{
1108
+ type: Input
1109
+ }], accessibilityShowsLargeContentViewer: [{
1110
+ type: Input
1111
+ }], accessibilityLargeContentTitle: [{
1112
+ type: Input
1113
+ }], role: [{
1114
+ type: Input
1115
+ }], ariaLabel: [{
1116
+ type: Input
1117
+ }], ariaLabelledBy: [{
1118
+ type: Input
1119
+ }], ariaLive: [{
1120
+ type: Input
1121
+ }], ariaHidden: [{
1122
+ type: Input
1123
+ }], ariaBusy: [{
1124
+ type: Input
1125
+ }], ariaChecked: [{
1126
+ type: Input
1127
+ }], ariaDisabled: [{
1128
+ type: Input
1129
+ }], ariaExpanded: [{
1130
+ type: Input
1131
+ }], ariaSelected: [{
1132
+ type: Input
1133
+ }], ariaModal: [{
1134
+ type: Input
1135
+ }], ariaValueMax: [{
1136
+ type: Input
1137
+ }], ariaValueMin: [{
1138
+ type: Input
1139
+ }], ariaValueNow: [{
1140
+ type: Input
1141
+ }], ariaValueText: [{
1142
+ type: Input
1143
+ }], itemDir: [{
1144
+ type: ContentChild,
1145
+ args: [VListItemDirective]
1146
+ }], headerDir: [{
1147
+ type: ContentChild,
1148
+ args: [VListHeaderDirective]
1149
+ }], footerDir: [{
1150
+ type: ContentChild,
1151
+ args: [VListFooterDirective]
1152
+ }], emptyDir: [{
1153
+ type: ContentChild,
1154
+ args: [VListEmptyDirective]
1155
+ }], separatorDir: [{
1156
+ type: ContentChild,
1157
+ args: [VListSeparatorDirective]
1158
+ }], scrollView: [{
1159
+ type: ViewChild,
1160
+ args: [ScrollView]
1161
+ }] } });
1162
+ //# sourceMappingURL=index.js.map