@k2b/ui 0.20.0 → 0.22.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 (595) hide show
  1. package/dist/browser/actions/Button.js +20 -31
  2. package/dist/browser/actions/Button.js.map +1 -1
  3. package/dist/browser/actions/ContextMenu.js +10 -4
  4. package/dist/browser/actions/ContextMenu.js.map +1 -1
  5. package/dist/browser/actions/CopyButton.js +10 -8
  6. package/dist/browser/actions/CopyButton.js.map +1 -1
  7. package/dist/browser/actions/FilterChip.js +3 -1
  8. package/dist/browser/actions/FilterChip.js.map +1 -1
  9. package/dist/browser/actions/GestureMenu.js +4 -0
  10. package/dist/browser/actions/GestureMenu.js.map +1 -1
  11. package/dist/browser/actions/SpotlightSearch.js +3 -1
  12. package/dist/browser/actions/SpotlightSearch.js.map +1 -1
  13. package/dist/browser/actions/filter-messages.js +20 -0
  14. package/dist/browser/actions/filter-messages.js.map +1 -0
  15. package/dist/browser/actions/spotlight-messages.js +16 -0
  16. package/dist/browser/actions/spotlight-messages.js.map +1 -0
  17. package/dist/browser/chat/ChatComposer.js +47 -41
  18. package/dist/browser/chat/ChatComposer.js.map +1 -1
  19. package/dist/browser/chat/ChatPrimitives.js +25 -23
  20. package/dist/browser/chat/ChatPrimitives.js.map +1 -1
  21. package/dist/browser/chat/ChatRoot.js +3 -3
  22. package/dist/browser/chat/ChatRoot.js.map +1 -1
  23. package/dist/browser/chat/ChatTimeline.js +12 -12
  24. package/dist/browser/chat/ChatTimeline.js.map +1 -1
  25. package/dist/browser/chat/chat-messages.js +236 -0
  26. package/dist/browser/chat/chat-messages.js.map +1 -0
  27. package/dist/browser/content/Calendar.js +1960 -575
  28. package/dist/browser/content/Calendar.js.map +1 -1
  29. package/dist/browser/content/Chart.js +15 -8
  30. package/dist/browser/content/Chart.js.map +1 -1
  31. package/dist/browser/content/ChartExplorer.js +20 -12
  32. package/dist/browser/content/ChartExplorer.js.map +1 -1
  33. package/dist/browser/content/ChartExplorerControls.js +9 -7
  34. package/dist/browser/content/ChartExplorerControls.js.map +1 -1
  35. package/dist/browser/content/ChartFilterControls.js +4 -2
  36. package/dist/browser/content/ChartFilterControls.js.map +1 -1
  37. package/dist/browser/content/ChartSnapshotView.js +3 -3
  38. package/dist/browser/content/ChartSnapshotView.js.map +1 -1
  39. package/dist/browser/content/DataTable.js +68 -59
  40. package/dist/browser/content/DataTable.js.map +1 -1
  41. package/dist/browser/content/Docs.js +3 -1
  42. package/dist/browser/content/Docs.js.map +1 -1
  43. package/dist/browser/content/FileBrowser.js +30 -26
  44. package/dist/browser/content/FileBrowser.js.map +1 -1
  45. package/dist/browser/content/FileTree.js +9 -7
  46. package/dist/browser/content/FileTree.js.map +1 -1
  47. package/dist/browser/content/FileView.js +37 -28
  48. package/dist/browser/content/FileView.js.map +1 -1
  49. package/dist/browser/content/Lightbox.js +9 -7
  50. package/dist/browser/content/Lightbox.js.map +1 -1
  51. package/dist/browser/content/LogEntriesTable.js +3 -3
  52. package/dist/browser/content/LogEntriesTable.js.map +1 -1
  53. package/dist/browser/content/MessageRow.js +24 -22
  54. package/dist/browser/content/MessageRow.js.map +1 -1
  55. package/dist/browser/content/Pagination.js +7 -7
  56. package/dist/browser/content/Pagination.js.map +1 -1
  57. package/dist/browser/content/PdfPreview.js +15 -13
  58. package/dist/browser/content/PdfPreview.js.map +1 -1
  59. package/dist/browser/content/RangePicker.js +3 -1
  60. package/dist/browser/content/RangePicker.js.map +1 -1
  61. package/dist/browser/content/StructuredDataPreview.js +3 -1
  62. package/dist/browser/content/StructuredDataPreview.js.map +1 -1
  63. package/dist/browser/content/Timeline.js +13 -11
  64. package/dist/browser/content/Timeline.js.map +1 -1
  65. package/dist/browser/content/VideoPlayer.js +5 -5
  66. package/dist/browser/content/VideoPlayer.js.map +1 -1
  67. package/dist/browser/content/VirtualFeed.js +6 -4
  68. package/dist/browser/content/VirtualFeed.js.map +1 -1
  69. package/dist/browser/content/ZoomPanViewport.js +10 -7
  70. package/dist/browser/content/ZoomPanViewport.js.map +1 -1
  71. package/dist/browser/content/calendar-messages.js +121 -0
  72. package/dist/browser/content/calendar-messages.js.map +1 -0
  73. package/dist/browser/content/calendar-month-layout.js +108 -0
  74. package/dist/browser/content/calendar-month-layout.js.map +1 -0
  75. package/dist/browser/content/calendar-pointer.js +4 -3
  76. package/dist/browser/content/calendar-pointer.js.map +1 -1
  77. package/dist/browser/content/chart-messages.js +136 -0
  78. package/dist/browser/content/chart-messages.js.map +1 -0
  79. package/dist/browser/content/collection-selection.js +2 -0
  80. package/dist/browser/content/collection-selection.js.map +1 -1
  81. package/dist/browser/content/data-table-messages.js +24 -0
  82. package/dist/browser/content/data-table-messages.js.map +1 -0
  83. package/dist/browser/content/docs-messages.js +24 -0
  84. package/dist/browser/content/docs-messages.js.map +1 -0
  85. package/dist/browser/content/feed-messages.js +34 -0
  86. package/dist/browser/content/feed-messages.js.map +1 -0
  87. package/dist/browser/content/file-browser-messages.js +69 -0
  88. package/dist/browser/content/file-browser-messages.js.map +1 -0
  89. package/dist/browser/content/file-view-messages.js +64 -0
  90. package/dist/browser/content/file-view-messages.js.map +1 -0
  91. package/dist/browser/content/index.js.map +1 -1
  92. package/dist/browser/content/lightbox-messages.js +36 -0
  93. package/dist/browser/content/lightbox-messages.js.map +1 -0
  94. package/dist/browser/content/log-entries-messages.js +20 -0
  95. package/dist/browser/content/log-entries-messages.js.map +1 -0
  96. package/dist/browser/content/markdown-info-block-messages.js +24 -0
  97. package/dist/browser/content/markdown-info-block-messages.js.map +1 -0
  98. package/dist/browser/content/markdown-info-blocks.js +3 -3
  99. package/dist/browser/content/markdown-info-blocks.js.map +1 -1
  100. package/dist/browser/content/markdown-links.js +2 -2
  101. package/dist/browser/content/markdown-links.js.map +1 -1
  102. package/dist/browser/content/markdown-reference-messages.js +30 -0
  103. package/dist/browser/content/markdown-reference-messages.js.map +1 -0
  104. package/dist/browser/content/pagination-messages.js +38 -0
  105. package/dist/browser/content/pagination-messages.js.map +1 -0
  106. package/dist/browser/content/pdf-messages.js +43 -0
  107. package/dist/browser/content/pdf-messages.js.map +1 -0
  108. package/dist/browser/content/range-picker-messages.js +20 -0
  109. package/dist/browser/content/range-picker-messages.js.map +1 -0
  110. package/dist/browser/content/structured-data-messages.js +22 -0
  111. package/dist/browser/content/structured-data-messages.js.map +1 -0
  112. package/dist/browser/content/timeline-messages.js +62 -0
  113. package/dist/browser/content/timeline-messages.js.map +1 -0
  114. package/dist/browser/content/video-messages.js +24 -0
  115. package/dist/browser/content/video-messages.js.map +1 -0
  116. package/dist/browser/content/viewport-messages.js +28 -0
  117. package/dist/browser/content/viewport-messages.js.map +1 -0
  118. package/dist/browser/feedback/HoverPreview.js +34 -6
  119. package/dist/browser/feedback/HoverPreview.js.map +1 -1
  120. package/dist/browser/feedback/InstallGuide.js +18 -18
  121. package/dist/browser/feedback/InstallGuide.js.map +1 -1
  122. package/dist/browser/feedback/install-messages.js +104 -0
  123. package/dist/browser/feedback/install-messages.js.map +1 -0
  124. package/dist/browser/feedback/prompt-messages.js +65 -0
  125. package/dist/browser/feedback/prompt-messages.js.map +1 -0
  126. package/dist/browser/feedback/prompts.js +14 -11
  127. package/dist/browser/feedback/prompts.js.map +1 -1
  128. package/dist/browser/feedback/toast-messages.js +18 -0
  129. package/dist/browser/feedback/toast-messages.js.map +1 -0
  130. package/dist/browser/feedback/toast.js +4 -3
  131. package/dist/browser/feedback/toast.js.map +1 -1
  132. package/dist/browser/index.js +1 -1
  133. package/dist/browser/index.js.map +1 -1
  134. package/dist/browser/inputs/AutocompleteEditor.js +6 -4
  135. package/dist/browser/inputs/AutocompleteEditor.js.map +1 -1
  136. package/dist/browser/inputs/AutocompleteSelect.js +10 -8
  137. package/dist/browser/inputs/AutocompleteSelect.js.map +1 -1
  138. package/dist/browser/inputs/ChoiceGroups.js +4 -0
  139. package/dist/browser/inputs/ChoiceGroups.js.map +1 -1
  140. package/dist/browser/inputs/ChoiceInputs.js +5 -5
  141. package/dist/browser/inputs/ChoiceInputs.js.map +1 -1
  142. package/dist/browser/inputs/Combobox.js +3 -1
  143. package/dist/browser/inputs/Combobox.js.map +1 -1
  144. package/dist/browser/inputs/DatePicker.js +46 -10
  145. package/dist/browser/inputs/DatePicker.js.map +1 -1
  146. package/dist/browser/inputs/FileDropTarget.js +6 -6
  147. package/dist/browser/inputs/FileDropTarget.js.map +1 -1
  148. package/dist/browser/inputs/FileInputs.js +30 -21
  149. package/dist/browser/inputs/FileInputs.js.map +1 -1
  150. package/dist/browser/inputs/MultiSelectInput.js +7 -5
  151. package/dist/browser/inputs/MultiSelectInput.js.map +1 -1
  152. package/dist/browser/inputs/NumberInput.js +4 -2
  153. package/dist/browser/inputs/NumberInput.js.map +1 -1
  154. package/dist/browser/inputs/QrScanner.js +5 -5
  155. package/dist/browser/inputs/QrScanner.js.map +1 -1
  156. package/dist/browser/inputs/Select.js +7 -5
  157. package/dist/browser/inputs/Select.js.map +1 -1
  158. package/dist/browser/inputs/SelectChip.js +3 -3
  159. package/dist/browser/inputs/SelectChip.js.map +1 -1
  160. package/dist/browser/inputs/SignatureInput.js +9 -3
  161. package/dist/browser/inputs/SignatureInput.js.map +1 -1
  162. package/dist/browser/inputs/SpecialInputs.js +4 -2
  163. package/dist/browser/inputs/SpecialInputs.js.map +1 -1
  164. package/dist/browser/inputs/TagEditor.js +8 -6
  165. package/dist/browser/inputs/TagEditor.js.map +1 -1
  166. package/dist/browser/inputs/TagsInput.js +5 -5
  167. package/dist/browser/inputs/TagsInput.js.map +1 -1
  168. package/dist/browser/inputs/TemplateEditor.js +5 -5
  169. package/dist/browser/inputs/TemplateEditor.js.map +1 -1
  170. package/dist/browser/inputs/TextInput.js +3 -1
  171. package/dist/browser/inputs/TextInput.js.map +1 -1
  172. package/dist/browser/inputs/completion-messages.js +24 -0
  173. package/dist/browser/inputs/completion-messages.js.map +1 -0
  174. package/dist/browser/inputs/date-picker.js +24 -0
  175. package/dist/browser/inputs/date-picker.js.map +1 -1
  176. package/dist/browser/inputs/file-drop-messages.js +63 -0
  177. package/dist/browser/inputs/file-drop-messages.js.map +1 -0
  178. package/dist/browser/inputs/file-drop.js.map +1 -1
  179. package/dist/browser/inputs/file-input-messages.js +60 -0
  180. package/dist/browser/inputs/file-input-messages.js.map +1 -0
  181. package/dist/browser/inputs/icon-messages.js +22 -0
  182. package/dist/browser/inputs/icon-messages.js.map +1 -0
  183. package/dist/browser/inputs/input-messages.js +38 -0
  184. package/dist/browser/inputs/input-messages.js.map +1 -0
  185. package/dist/browser/inputs/markdown/MarkdownEditor.js +10 -6
  186. package/dist/browser/inputs/markdown/MarkdownEditor.js.map +1 -1
  187. package/dist/browser/inputs/markdown/Toolbar.js +13 -13
  188. package/dist/browser/inputs/markdown/Toolbar.js.map +1 -1
  189. package/dist/browser/inputs/markdown/editor-messages.js +43 -0
  190. package/dist/browser/inputs/markdown/editor-messages.js.map +1 -0
  191. package/dist/browser/inputs/markdown/toolbar-messages.js +40 -0
  192. package/dist/browser/inputs/markdown/toolbar-messages.js.map +1 -0
  193. package/dist/browser/inputs/qr-messages.js +26 -0
  194. package/dist/browser/inputs/qr-messages.js.map +1 -0
  195. package/dist/browser/inputs/select-messages.js +63 -0
  196. package/dist/browser/inputs/select-messages.js.map +1 -0
  197. package/dist/browser/inputs/tag-messages.js +44 -0
  198. package/dist/browser/inputs/tag-messages.js.map +1 -0
  199. package/dist/browser/inputs/template-messages.js +22 -0
  200. package/dist/browser/inputs/template-messages.js.map +1 -0
  201. package/dist/browser/internal/render-error-messages.js +20 -0
  202. package/dist/browser/internal/render-error-messages.js.map +1 -0
  203. package/dist/browser/internal/render-error.js +3 -1
  204. package/dist/browser/internal/render-error.js.map +1 -1
  205. package/dist/browser/internal/text-selection.js +101 -0
  206. package/dist/browser/internal/text-selection.js.map +1 -0
  207. package/dist/browser/intl/messages.js +12 -1155
  208. package/dist/browser/intl/messages.js.map +1 -1
  209. package/dist/browser/layout/AppWorkspace.js +561 -418
  210. package/dist/browser/layout/AppWorkspace.js.map +1 -1
  211. package/dist/browser/layout/BottomSheet.js +6 -1
  212. package/dist/browser/layout/BottomSheet.js.map +1 -1
  213. package/dist/browser/layout/Discussion.js +8 -5
  214. package/dist/browser/layout/Discussion.js.map +1 -1
  215. package/dist/browser/layout/FloatingWindow.js +8 -5
  216. package/dist/browser/layout/FloatingWindow.js.map +1 -1
  217. package/dist/browser/layout/Navigation.js +7 -6
  218. package/dist/browser/layout/Navigation.js.map +1 -1
  219. package/dist/browser/layout/PageTitle.js +370 -0
  220. package/dist/browser/layout/PageTitle.js.map +1 -0
  221. package/dist/browser/layout/PanelDialog.js +8 -6
  222. package/dist/browser/layout/PanelDialog.js.map +1 -1
  223. package/dist/browser/layout/Panes.js +23 -15
  224. package/dist/browser/layout/Panes.js.map +1 -1
  225. package/dist/browser/layout/PullToRefresh.js +13 -4
  226. package/dist/browser/layout/PullToRefresh.js.map +1 -1
  227. package/dist/browser/layout/Settings.js +14 -12
  228. package/dist/browser/layout/Settings.js.map +1 -1
  229. package/dist/browser/layout/SettingsCollection.js +6 -5
  230. package/dist/browser/layout/SettingsCollection.js.map +1 -1
  231. package/dist/browser/layout/SettingsModal.js +3 -1
  232. package/dist/browser/layout/SettingsModal.js.map +1 -1
  233. package/dist/browser/layout/app-workspace-controller.js +743 -12
  234. package/dist/browser/layout/app-workspace-controller.js.map +1 -1
  235. package/dist/browser/layout/app-workspace-state.js +3 -2
  236. package/dist/browser/layout/app-workspace-state.js.map +1 -1
  237. package/dist/browser/layout/floating-window-messages.js +28 -0
  238. package/dist/browser/layout/floating-window-messages.js.map +1 -0
  239. package/dist/browser/layout/index.js +2 -0
  240. package/dist/browser/layout/index.js.map +1 -1
  241. package/dist/browser/layout/navigation-model.js.map +1 -1
  242. package/dist/browser/layout/page-title-controller.js +169 -0
  243. package/dist/browser/layout/page-title-controller.js.map +1 -0
  244. package/dist/browser/layout/panel-dialog-messages.js +20 -0
  245. package/dist/browser/layout/panel-dialog-messages.js.map +1 -0
  246. package/dist/browser/layout/panes-messages.js +48 -0
  247. package/dist/browser/layout/panes-messages.js.map +1 -0
  248. package/dist/browser/layout/refresh-messages.js +20 -0
  249. package/dist/browser/layout/refresh-messages.js.map +1 -0
  250. package/dist/browser/layout/settings-messages.js +54 -0
  251. package/dist/browser/layout/settings-messages.js.map +1 -0
  252. package/dist/browser/layout/workspace-messages.js +56 -0
  253. package/dist/browser/layout/workspace-messages.js.map +1 -0
  254. package/dist/browser/surfaces/Avatar.js +5 -5
  255. package/dist/browser/surfaces/Avatar.js.map +1 -1
  256. package/dist/browser/surfaces/ResourceCard.js +4 -2
  257. package/dist/browser/surfaces/ResourceCard.js.map +1 -1
  258. package/dist/browser/surfaces/Tag.js +3 -3
  259. package/dist/browser/surfaces/Tag.js.map +1 -1
  260. package/dist/browser/surfaces/avatar-messages.js +26 -0
  261. package/dist/browser/surfaces/avatar-messages.js.map +1 -0
  262. package/dist/browser/surfaces/resource-messages.js +26 -0
  263. package/dist/browser/surfaces/resource-messages.js.map +1 -0
  264. package/dist/browser/widgets/Widget.js +6 -0
  265. package/dist/browser/widgets/Widget.js.map +1 -1
  266. package/dist/ssr/actions/Button.js +21 -32
  267. package/dist/ssr/actions/Button.js.map +1 -1
  268. package/dist/ssr/actions/ContextMenu.js +7 -3
  269. package/dist/ssr/actions/ContextMenu.js.map +1 -1
  270. package/dist/ssr/actions/CopyButton.js +9 -7
  271. package/dist/ssr/actions/CopyButton.js.map +1 -1
  272. package/dist/ssr/actions/FilterChip.js +3 -1
  273. package/dist/ssr/actions/FilterChip.js.map +1 -1
  274. package/dist/ssr/actions/GestureMenu.js +4 -0
  275. package/dist/ssr/actions/GestureMenu.js.map +1 -1
  276. package/dist/ssr/actions/SpotlightSearch.js +3 -1
  277. package/dist/ssr/actions/SpotlightSearch.js.map +1 -1
  278. package/dist/ssr/actions/filter-messages.js +20 -0
  279. package/dist/ssr/actions/filter-messages.js.map +1 -0
  280. package/dist/ssr/actions/spotlight-messages.js +16 -0
  281. package/dist/ssr/actions/spotlight-messages.js.map +1 -0
  282. package/dist/ssr/chat/ChatComposer.js +47 -41
  283. package/dist/ssr/chat/ChatComposer.js.map +1 -1
  284. package/dist/ssr/chat/ChatPrimitives.js +23 -21
  285. package/dist/ssr/chat/ChatPrimitives.js.map +1 -1
  286. package/dist/ssr/chat/ChatRoot.js +3 -3
  287. package/dist/ssr/chat/ChatRoot.js.map +1 -1
  288. package/dist/ssr/chat/ChatTimeline.js +11 -11
  289. package/dist/ssr/chat/ChatTimeline.js.map +1 -1
  290. package/dist/ssr/chat/chat-messages.js +236 -0
  291. package/dist/ssr/chat/chat-messages.js.map +1 -0
  292. package/dist/ssr/content/Calendar.js +1232 -115
  293. package/dist/ssr/content/Calendar.js.map +1 -1
  294. package/dist/ssr/content/Chart.js +12 -5
  295. package/dist/ssr/content/Chart.js.map +1 -1
  296. package/dist/ssr/content/ChartExplorer.js +10 -8
  297. package/dist/ssr/content/ChartExplorer.js.map +1 -1
  298. package/dist/ssr/content/ChartExplorerControls.js +9 -7
  299. package/dist/ssr/content/ChartExplorerControls.js.map +1 -1
  300. package/dist/ssr/content/ChartFilterControls.js +4 -2
  301. package/dist/ssr/content/ChartFilterControls.js.map +1 -1
  302. package/dist/ssr/content/ChartSnapshotView.js +3 -3
  303. package/dist/ssr/content/ChartSnapshotView.js.map +1 -1
  304. package/dist/ssr/content/DataTable.js +10 -4
  305. package/dist/ssr/content/DataTable.js.map +1 -1
  306. package/dist/ssr/content/Docs.js +3 -1
  307. package/dist/ssr/content/Docs.js.map +1 -1
  308. package/dist/ssr/content/FileBrowser.js +30 -26
  309. package/dist/ssr/content/FileBrowser.js.map +1 -1
  310. package/dist/ssr/content/FileTree.js +9 -7
  311. package/dist/ssr/content/FileTree.js.map +1 -1
  312. package/dist/ssr/content/FileView.js +37 -28
  313. package/dist/ssr/content/FileView.js.map +1 -1
  314. package/dist/ssr/content/Lightbox.js +8 -6
  315. package/dist/ssr/content/Lightbox.js.map +1 -1
  316. package/dist/ssr/content/LogEntriesTable.js +3 -3
  317. package/dist/ssr/content/LogEntriesTable.js.map +1 -1
  318. package/dist/ssr/content/MessageRow.js +24 -22
  319. package/dist/ssr/content/MessageRow.js.map +1 -1
  320. package/dist/ssr/content/Pagination.js +6 -6
  321. package/dist/ssr/content/Pagination.js.map +1 -1
  322. package/dist/ssr/content/PdfPreview.js +15 -13
  323. package/dist/ssr/content/PdfPreview.js.map +1 -1
  324. package/dist/ssr/content/RangePicker.js +3 -1
  325. package/dist/ssr/content/RangePicker.js.map +1 -1
  326. package/dist/ssr/content/StructuredDataPreview.js +3 -1
  327. package/dist/ssr/content/StructuredDataPreview.js.map +1 -1
  328. package/dist/ssr/content/Timeline.js +13 -11
  329. package/dist/ssr/content/Timeline.js.map +1 -1
  330. package/dist/ssr/content/VideoPlayer.js +5 -5
  331. package/dist/ssr/content/VideoPlayer.js.map +1 -1
  332. package/dist/ssr/content/VirtualFeed.js +6 -4
  333. package/dist/ssr/content/VirtualFeed.js.map +1 -1
  334. package/dist/ssr/content/ZoomPanViewport.js +7 -4
  335. package/dist/ssr/content/ZoomPanViewport.js.map +1 -1
  336. package/dist/ssr/content/calendar-messages.js +121 -0
  337. package/dist/ssr/content/calendar-messages.js.map +1 -0
  338. package/dist/ssr/content/calendar-month-layout.js +108 -0
  339. package/dist/ssr/content/calendar-month-layout.js.map +1 -0
  340. package/dist/ssr/content/calendar-pointer.js +4 -3
  341. package/dist/ssr/content/calendar-pointer.js.map +1 -1
  342. package/dist/ssr/content/chart-messages.js +136 -0
  343. package/dist/ssr/content/chart-messages.js.map +1 -0
  344. package/dist/ssr/content/collection-selection.js +2 -0
  345. package/dist/ssr/content/collection-selection.js.map +1 -1
  346. package/dist/ssr/content/data-table-messages.js +24 -0
  347. package/dist/ssr/content/data-table-messages.js.map +1 -0
  348. package/dist/ssr/content/docs-messages.js +24 -0
  349. package/dist/ssr/content/docs-messages.js.map +1 -0
  350. package/dist/ssr/content/feed-messages.js +34 -0
  351. package/dist/ssr/content/feed-messages.js.map +1 -0
  352. package/dist/ssr/content/file-browser-messages.js +69 -0
  353. package/dist/ssr/content/file-browser-messages.js.map +1 -0
  354. package/dist/ssr/content/file-view-messages.js +64 -0
  355. package/dist/ssr/content/file-view-messages.js.map +1 -0
  356. package/dist/ssr/content/index.js.map +1 -1
  357. package/dist/ssr/content/lightbox-messages.js +36 -0
  358. package/dist/ssr/content/lightbox-messages.js.map +1 -0
  359. package/dist/ssr/content/log-entries-messages.js +20 -0
  360. package/dist/ssr/content/log-entries-messages.js.map +1 -0
  361. package/dist/ssr/content/markdown-info-block-messages.js +24 -0
  362. package/dist/ssr/content/markdown-info-block-messages.js.map +1 -0
  363. package/dist/ssr/content/markdown-info-blocks.js +3 -3
  364. package/dist/ssr/content/markdown-info-blocks.js.map +1 -1
  365. package/dist/ssr/content/markdown-links.js +2 -2
  366. package/dist/ssr/content/markdown-links.js.map +1 -1
  367. package/dist/ssr/content/markdown-reference-messages.js +30 -0
  368. package/dist/ssr/content/markdown-reference-messages.js.map +1 -0
  369. package/dist/ssr/content/pagination-messages.js +38 -0
  370. package/dist/ssr/content/pagination-messages.js.map +1 -0
  371. package/dist/ssr/content/pdf-messages.js +43 -0
  372. package/dist/ssr/content/pdf-messages.js.map +1 -0
  373. package/dist/ssr/content/range-picker-messages.js +20 -0
  374. package/dist/ssr/content/range-picker-messages.js.map +1 -0
  375. package/dist/ssr/content/structured-data-messages.js +22 -0
  376. package/dist/ssr/content/structured-data-messages.js.map +1 -0
  377. package/dist/ssr/content/timeline-messages.js +62 -0
  378. package/dist/ssr/content/timeline-messages.js.map +1 -0
  379. package/dist/ssr/content/video-messages.js +24 -0
  380. package/dist/ssr/content/video-messages.js.map +1 -0
  381. package/dist/ssr/content/viewport-messages.js +28 -0
  382. package/dist/ssr/content/viewport-messages.js.map +1 -0
  383. package/dist/ssr/feedback/HoverPreview.js +34 -6
  384. package/dist/ssr/feedback/HoverPreview.js.map +1 -1
  385. package/dist/ssr/feedback/InstallGuide.js +18 -18
  386. package/dist/ssr/feedback/InstallGuide.js.map +1 -1
  387. package/dist/ssr/feedback/install-messages.js +104 -0
  388. package/dist/ssr/feedback/install-messages.js.map +1 -0
  389. package/dist/ssr/feedback/prompt-messages.js +65 -0
  390. package/dist/ssr/feedback/prompt-messages.js.map +1 -0
  391. package/dist/ssr/feedback/prompts.js +14 -11
  392. package/dist/ssr/feedback/prompts.js.map +1 -1
  393. package/dist/ssr/feedback/toast-messages.js +18 -0
  394. package/dist/ssr/feedback/toast-messages.js.map +1 -0
  395. package/dist/ssr/feedback/toast.js +4 -3
  396. package/dist/ssr/feedback/toast.js.map +1 -1
  397. package/dist/ssr/index.js +1 -1
  398. package/dist/ssr/index.js.map +1 -1
  399. package/dist/ssr/inputs/AutocompleteEditor.js +5 -3
  400. package/dist/ssr/inputs/AutocompleteEditor.js.map +1 -1
  401. package/dist/ssr/inputs/AutocompleteSelect.js +10 -8
  402. package/dist/ssr/inputs/AutocompleteSelect.js.map +1 -1
  403. package/dist/ssr/inputs/ChoiceGroups.js +4 -0
  404. package/dist/ssr/inputs/ChoiceGroups.js.map +1 -1
  405. package/dist/ssr/inputs/ChoiceInputs.js +5 -5
  406. package/dist/ssr/inputs/ChoiceInputs.js.map +1 -1
  407. package/dist/ssr/inputs/Combobox.js +3 -1
  408. package/dist/ssr/inputs/Combobox.js.map +1 -1
  409. package/dist/ssr/inputs/DatePicker.js +34 -4
  410. package/dist/ssr/inputs/DatePicker.js.map +1 -1
  411. package/dist/ssr/inputs/FileDropTarget.js +6 -6
  412. package/dist/ssr/inputs/FileDropTarget.js.map +1 -1
  413. package/dist/ssr/inputs/FileInputs.js +29 -20
  414. package/dist/ssr/inputs/FileInputs.js.map +1 -1
  415. package/dist/ssr/inputs/MultiSelectInput.js +7 -5
  416. package/dist/ssr/inputs/MultiSelectInput.js.map +1 -1
  417. package/dist/ssr/inputs/NumberInput.js +4 -2
  418. package/dist/ssr/inputs/NumberInput.js.map +1 -1
  419. package/dist/ssr/inputs/QrScanner.js +4 -4
  420. package/dist/ssr/inputs/QrScanner.js.map +1 -1
  421. package/dist/ssr/inputs/Select.js +7 -5
  422. package/dist/ssr/inputs/Select.js.map +1 -1
  423. package/dist/ssr/inputs/SelectChip.js +3 -3
  424. package/dist/ssr/inputs/SelectChip.js.map +1 -1
  425. package/dist/ssr/inputs/SignatureInput.js +9 -3
  426. package/dist/ssr/inputs/SignatureInput.js.map +1 -1
  427. package/dist/ssr/inputs/SpecialInputs.js +4 -2
  428. package/dist/ssr/inputs/SpecialInputs.js.map +1 -1
  429. package/dist/ssr/inputs/TagEditor.js +8 -6
  430. package/dist/ssr/inputs/TagEditor.js.map +1 -1
  431. package/dist/ssr/inputs/TagsInput.js +5 -5
  432. package/dist/ssr/inputs/TagsInput.js.map +1 -1
  433. package/dist/ssr/inputs/TemplateEditor.js +5 -5
  434. package/dist/ssr/inputs/TemplateEditor.js.map +1 -1
  435. package/dist/ssr/inputs/TextInput.js +3 -1
  436. package/dist/ssr/inputs/TextInput.js.map +1 -1
  437. package/dist/ssr/inputs/completion-messages.js +24 -0
  438. package/dist/ssr/inputs/completion-messages.js.map +1 -0
  439. package/dist/ssr/inputs/date-picker.js +24 -0
  440. package/dist/ssr/inputs/date-picker.js.map +1 -1
  441. package/dist/ssr/inputs/file-drop-messages.js +63 -0
  442. package/dist/ssr/inputs/file-drop-messages.js.map +1 -0
  443. package/dist/ssr/inputs/file-drop.js.map +1 -1
  444. package/dist/ssr/inputs/file-input-messages.js +60 -0
  445. package/dist/ssr/inputs/file-input-messages.js.map +1 -0
  446. package/dist/ssr/inputs/icon-messages.js +22 -0
  447. package/dist/ssr/inputs/icon-messages.js.map +1 -0
  448. package/dist/ssr/inputs/input-messages.js +38 -0
  449. package/dist/ssr/inputs/input-messages.js.map +1 -0
  450. package/dist/ssr/inputs/markdown/MarkdownEditor.js +9 -5
  451. package/dist/ssr/inputs/markdown/MarkdownEditor.js.map +1 -1
  452. package/dist/ssr/inputs/markdown/Toolbar.js +13 -13
  453. package/dist/ssr/inputs/markdown/Toolbar.js.map +1 -1
  454. package/dist/ssr/inputs/markdown/editor-messages.js +43 -0
  455. package/dist/ssr/inputs/markdown/editor-messages.js.map +1 -0
  456. package/dist/ssr/inputs/markdown/toolbar-messages.js +40 -0
  457. package/dist/ssr/inputs/markdown/toolbar-messages.js.map +1 -0
  458. package/dist/ssr/inputs/qr-messages.js +26 -0
  459. package/dist/ssr/inputs/qr-messages.js.map +1 -0
  460. package/dist/ssr/inputs/select-messages.js +63 -0
  461. package/dist/ssr/inputs/select-messages.js.map +1 -0
  462. package/dist/ssr/inputs/tag-messages.js +44 -0
  463. package/dist/ssr/inputs/tag-messages.js.map +1 -0
  464. package/dist/ssr/inputs/template-messages.js +22 -0
  465. package/dist/ssr/inputs/template-messages.js.map +1 -0
  466. package/dist/ssr/internal/render-error-messages.js +20 -0
  467. package/dist/ssr/internal/render-error-messages.js.map +1 -0
  468. package/dist/ssr/internal/render-error.js +3 -1
  469. package/dist/ssr/internal/render-error.js.map +1 -1
  470. package/dist/ssr/internal/text-selection.js +101 -0
  471. package/dist/ssr/internal/text-selection.js.map +1 -0
  472. package/dist/ssr/intl/messages.js +12 -1155
  473. package/dist/ssr/intl/messages.js.map +1 -1
  474. package/dist/ssr/layout/AppWorkspace.js +203 -96
  475. package/dist/ssr/layout/AppWorkspace.js.map +1 -1
  476. package/dist/ssr/layout/BottomSheet.js +1 -0
  477. package/dist/ssr/layout/BottomSheet.js.map +1 -1
  478. package/dist/ssr/layout/Discussion.js +8 -5
  479. package/dist/ssr/layout/Discussion.js.map +1 -1
  480. package/dist/ssr/layout/FloatingWindow.js +8 -5
  481. package/dist/ssr/layout/FloatingWindow.js.map +1 -1
  482. package/dist/ssr/layout/Navigation.js +6 -5
  483. package/dist/ssr/layout/Navigation.js.map +1 -1
  484. package/dist/ssr/layout/PageTitle.js +253 -0
  485. package/dist/ssr/layout/PageTitle.js.map +1 -0
  486. package/dist/ssr/layout/PanelDialog.js +8 -6
  487. package/dist/ssr/layout/PanelDialog.js.map +1 -1
  488. package/dist/ssr/layout/Panes.js +22 -14
  489. package/dist/ssr/layout/Panes.js.map +1 -1
  490. package/dist/ssr/layout/PullToRefresh.js +13 -4
  491. package/dist/ssr/layout/PullToRefresh.js.map +1 -1
  492. package/dist/ssr/layout/Settings.js +14 -12
  493. package/dist/ssr/layout/Settings.js.map +1 -1
  494. package/dist/ssr/layout/SettingsCollection.js +6 -5
  495. package/dist/ssr/layout/SettingsCollection.js.map +1 -1
  496. package/dist/ssr/layout/SettingsModal.js +3 -1
  497. package/dist/ssr/layout/SettingsModal.js.map +1 -1
  498. package/dist/ssr/layout/app-workspace-controller.js +743 -12
  499. package/dist/ssr/layout/app-workspace-controller.js.map +1 -1
  500. package/dist/ssr/layout/app-workspace-state.js +3 -2
  501. package/dist/ssr/layout/app-workspace-state.js.map +1 -1
  502. package/dist/ssr/layout/floating-window-messages.js +28 -0
  503. package/dist/ssr/layout/floating-window-messages.js.map +1 -0
  504. package/dist/ssr/layout/index.js +2 -0
  505. package/dist/ssr/layout/index.js.map +1 -1
  506. package/dist/ssr/layout/navigation-model.js.map +1 -1
  507. package/dist/ssr/layout/page-title-controller.js +169 -0
  508. package/dist/ssr/layout/page-title-controller.js.map +1 -0
  509. package/dist/ssr/layout/panel-dialog-messages.js +20 -0
  510. package/dist/ssr/layout/panel-dialog-messages.js.map +1 -0
  511. package/dist/ssr/layout/panes-messages.js +48 -0
  512. package/dist/ssr/layout/panes-messages.js.map +1 -0
  513. package/dist/ssr/layout/refresh-messages.js +20 -0
  514. package/dist/ssr/layout/refresh-messages.js.map +1 -0
  515. package/dist/ssr/layout/settings-messages.js +54 -0
  516. package/dist/ssr/layout/settings-messages.js.map +1 -0
  517. package/dist/ssr/layout/workspace-messages.js +56 -0
  518. package/dist/ssr/layout/workspace-messages.js.map +1 -0
  519. package/dist/ssr/surfaces/Avatar.js +5 -5
  520. package/dist/ssr/surfaces/Avatar.js.map +1 -1
  521. package/dist/ssr/surfaces/ResourceCard.js +4 -2
  522. package/dist/ssr/surfaces/ResourceCard.js.map +1 -1
  523. package/dist/ssr/surfaces/Tag.js +3 -3
  524. package/dist/ssr/surfaces/Tag.js.map +1 -1
  525. package/dist/ssr/surfaces/avatar-messages.js +26 -0
  526. package/dist/ssr/surfaces/avatar-messages.js.map +1 -0
  527. package/dist/ssr/surfaces/resource-messages.js +26 -0
  528. package/dist/ssr/surfaces/resource-messages.js.map +1 -0
  529. package/dist/ssr/widgets/Widget.js +6 -0
  530. package/dist/ssr/widgets/Widget.js.map +1 -1
  531. package/dist/styles.css +1 -1
  532. package/dist/types/actions/GestureMenu.d.ts +2 -0
  533. package/dist/types/actions/filter-messages.d.ts +8 -0
  534. package/dist/types/actions/spotlight-messages.d.ts +8 -0
  535. package/dist/types/chat/chat-messages.d.ts +116 -0
  536. package/dist/types/content/Calendar.d.ts +32 -0
  537. package/dist/types/content/DataTable.d.ts +2 -0
  538. package/dist/types/content/FileView.d.ts +0 -10
  539. package/dist/types/content/calendar-messages.d.ts +60 -0
  540. package/dist/types/content/calendar-month-layout.d.ts +52 -0
  541. package/dist/types/content/chart-messages.d.ts +32 -0
  542. package/dist/types/content/data-table-messages.d.ts +10 -0
  543. package/dist/types/content/docs-messages.d.ts +10 -0
  544. package/dist/types/content/feed-messages.d.ts +15 -0
  545. package/dist/types/content/file-browser-messages.d.ts +33 -0
  546. package/dist/types/content/file-view-messages.d.ts +30 -0
  547. package/dist/types/content/index.d.ts +1 -1
  548. package/dist/types/content/lightbox-messages.d.ts +16 -0
  549. package/dist/types/content/log-entries-messages.d.ts +8 -0
  550. package/dist/types/content/markdown-info-block-messages.d.ts +12 -0
  551. package/dist/types/content/markdown-reference-messages.d.ts +15 -0
  552. package/dist/types/content/pagination-messages.d.ts +17 -0
  553. package/dist/types/content/pdf-messages.d.ts +20 -0
  554. package/dist/types/content/range-picker-messages.d.ts +8 -0
  555. package/dist/types/content/structured-data-messages.d.ts +9 -0
  556. package/dist/types/content/timeline-messages.d.ts +29 -0
  557. package/dist/types/content/video-messages.d.ts +10 -0
  558. package/dist/types/content/viewport-messages.d.ts +12 -0
  559. package/dist/types/feedback/install-messages.d.ts +50 -0
  560. package/dist/types/feedback/prompt-messages.d.ts +31 -0
  561. package/dist/types/feedback/toast-messages.d.ts +9 -0
  562. package/dist/types/index.d.ts +1 -0
  563. package/dist/types/inputs/completion-messages.d.ts +10 -0
  564. package/dist/types/inputs/date-picker.d.ts +7 -0
  565. package/dist/types/inputs/file-drop-messages.d.ts +30 -0
  566. package/dist/types/inputs/file-drop.d.ts +3 -3
  567. package/dist/types/inputs/file-input-messages.d.ts +28 -0
  568. package/dist/types/inputs/icon-messages.d.ts +9 -0
  569. package/dist/types/inputs/input-messages.d.ts +17 -0
  570. package/dist/types/inputs/markdown/editor-messages.d.ts +20 -0
  571. package/dist/types/inputs/markdown/toolbar-messages.d.ts +18 -0
  572. package/dist/types/inputs/qr-messages.d.ts +11 -0
  573. package/dist/types/inputs/select-messages.d.ts +30 -0
  574. package/dist/types/inputs/tag-messages.d.ts +20 -0
  575. package/dist/types/inputs/template-messages.d.ts +9 -0
  576. package/dist/types/internal/render-error-messages.d.ts +8 -0
  577. package/dist/types/internal/text-selection.d.ts +18 -0
  578. package/dist/types/intl/messages.d.ts +6 -544
  579. package/dist/types/layout/AppWorkspace.d.ts +19 -4
  580. package/dist/types/layout/PageTitle.d.ts +64 -0
  581. package/dist/types/layout/app-workspace-controller.d.ts +4 -0
  582. package/dist/types/layout/app-workspace-state.d.ts +3 -2
  583. package/dist/types/layout/floating-window-messages.d.ts +12 -0
  584. package/dist/types/layout/index.d.ts +3 -0
  585. package/dist/types/layout/navigation-model.d.ts +7 -0
  586. package/dist/types/layout/page-title-controller.d.ts +13 -0
  587. package/dist/types/layout/panel-dialog-messages.d.ts +8 -0
  588. package/dist/types/layout/panes-messages.d.ts +22 -0
  589. package/dist/types/layout/refresh-messages.d.ts +8 -0
  590. package/dist/types/layout/settings-messages.d.ts +25 -0
  591. package/dist/types/layout/workspace-messages.d.ts +26 -0
  592. package/dist/types/surfaces/avatar-messages.d.ts +11 -0
  593. package/dist/types/surfaces/resource-messages.d.ts +11 -0
  594. package/dist/types/widgets/Widget.d.ts +5 -1
  595. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["content/VirtualFeed.tsx"],"sourcesContent":["import { type Accessor, createEffect, createRoot, createSignal, getOwner, type JSX, on, onCleanup, onMount, Show, untrack } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\n\n/**\n * The tallest loaded window in px. Firefox renders an element taller than about 17.9 M px with a height of 0, so the\n * feed lays out at most this much and drops far items while it keeps the reading position.\n */\nconst MAX_WINDOW = 8_000_000;\n/** How much the loaded window grows at once when the reader nears one of its edges. */\nconst WINDOW_STEP = 2_000_000;\n/** Rows rendered above and below the visible part, in px. */\nconst OVERSCAN = 600;\n/** Distance from the end, in px, that still counts as being at the end. */\nconst END_TOLERANCE = 2;\n/**\n * Rows mounted during one correction reach the ResizeObserver a frame late; measure up to this many passes at once.\n * A last pass places the rows; the observer measures what that pass mounted.\n */\nconst MEASURE_PASSES = 4;\nconst ANNOUNCE_MS = 1_000;\nconst HIGHLIGHT_MS = 1_600;\n/** In engines without `scrollend`, the reader's scroll has ended after this long without moving. */\nconst QUIET_MS = 300;\n/** The longest wait for the `scrollend` of the reader's scroll after it last moved, or of a write of the feed. */\nconst END_WAIT_MS = 1_000;\n\nexport type VirtualFeedScrollOptions = {\n /** Where the item lands in the visible area. Defaults to `\"center\"`. */\n align?: \"start\" | \"center\";\n /** Tints the item briefly so the reader finds it. */\n highlight?: boolean;\n};\n\nexport type VirtualFeedController = {\n /**\n * Scrolls to a loaded item, also when the reader's scroll still coasts. Returns false when no loaded item has this\n * key, so the caller can load around it first.\n */\n scrollToKey: (key: string, options?: VirtualFeedScrollOptions) => boolean;\n /**\n * Follows the end again, also when the reader's scroll still coasts. When newer items exist but are not loaded, it\n * asks `onLoadNewest` for them first.\n */\n scrollToEnd: () => void;\n /** Whether the reader is at the end and new items keep the feed there. */\n isAtEnd: () => boolean;\n};\n\nexport type VirtualFeedProps<T> = {\n /** Loaded items, oldest first. Replace the array to add, remove, or change items. */\n items: readonly T[];\n /** Stable, unique identity of an item across updates. */\n getKey: (item: T) => string;\n /** Height in px before the item was measured. Close estimates mean fewer corrections while scrolling. */\n estimateSize: (item: T) => number;\n /** Content of one item, created once per item object as with Solid's `For`. `index` is its position in `items`. */\n children: (item: T, index: Accessor<number>) => JSX.Element;\n /** Accessible name of the feed. */\n label: string;\n /** Accessible name of one item, for example its author and time. */\n itemLabel?: (item: T) => string | undefined;\n /**\n * Label shown above an item, for example when the day changes. Return nothing for no separator. While `hasOlder` is\n * set, the first loaded item has no known predecessor and gets none.\n */\n separator?: (item: T, previous: T | undefined) => JSX.Element;\n /** Key of the first item the reader has not seen; a marker appears above it. */\n markerKey?: string | null;\n /** Text of that marker. Defaults to \"New\". */\n markerLabel?: string;\n /** Older items exist that `items` does not contain yet. */\n hasOlder?: boolean;\n /** Newer items exist that `items` does not contain yet. */\n hasNewer?: boolean;\n /** Called near the start of the loaded items while `hasOlder` is true. Prepend the next older page to `items`. */\n onLoadOlder?: () => unknown;\n /** Called near the end of the loaded items while `hasNewer` is true. Append the next newer page to `items`. */\n onLoadNewer?: () => unknown;\n /** Called by \"Jump to latest\" while `hasNewer` is true. Replace `items` with the newest page. */\n onLoadNewest?: () => unknown;\n /** Marks the feed as busy for assistive technology, for example during the first load. */\n busy?: boolean;\n /** Number of items in the whole feed when known. */\n totalCount?: number;\n /** One-based position of `items[0]` in the whole feed when known. */\n firstPosition?: number;\n /**\n * Count shown on \"Jump to latest\". Defaults to the new items added while the reader was away from the end, which\n * excludes pages of older history loaded toward the end.\n */\n newCount?: number;\n /** Text announced for new items added at the end, bundled per second. Return nothing to stay silent. */\n announce?: (added: readonly T[]) => string | undefined;\n /** Called when the reader reaches or leaves the end. */\n onEndChange?: (atEnd: boolean) => void;\n /** Receives the controller once the feed is mounted. */\n controller?: (controller: VirtualFeedController) => void;\n /** Shown while `items` is empty. */\n empty?: JSX.Element;\n class?: string;\n};\n\n/**\n * One mounted row. Rows are created and removed but never moved, so focus, media, and frames inside them survive.\n * `lead` is the measured height of the separator and marker above the content.\n */\ntype Row<T> = { item: T; node: HTMLElement; index: number; lead?: number; setIndex: (index: number) => void; dispose: () => void };\n\nconst runsMatch = (before: readonly string[], after: readonly string[], shift: number) => {\n for (let index = 0; index < before.length; index++) if (before[index] !== after[index + shift]) return false;\n return true;\n};\n\n/** Height of the separator and marker that a row shows above its content. */\nconst leadOf = (node: HTMLElement) => {\n let height = 0;\n for (const child of node.children) {\n if (!child.classList.contains(\"k2b-virtual-feed__separator\") && !child.classList.contains(\"k2b-virtual-feed__marker\")) break;\n height += child.getBoundingClientRect().height;\n }\n return height;\n};\n\n/**\n * A virtualized feed of items with variable heights that grows at both ends and keeps the reading position: it stays\n * at the end while the reader is there, and otherwise keeps the item in view where it is, whatever loads, grows, or\n * resizes around it.\n */\nexport function VirtualFeed<T>(props: VirtualFeedProps<T>): JSX.Element {\n const messages = useUiMessages();\n let viewport!: HTMLDivElement;\n let feed!: HTMLDivElement;\n let log!: HTMLDivElement;\n\n // Layout: one size per item and prefix sums over the loaded window [lo, hi).\n let list: readonly T[] = [];\n let keys: string[] = [];\n let sizes = new Float64Array(0);\n let lo = 0;\n let hi = 0;\n let offsets = new Float64Array(1);\n let dirtyFrom = 0;\n\n // Reading position: follow the end, or keep one item (index) at a pixel distance (delta) below the visible top.\n let stick = true;\n let anchor = { index: 0, delta: 0 };\n /** Key of the last item while no newer items existed; items appended after it are new. */\n let endKey: string | undefined;\n /** The last scrollTop the feed wrote or accounted for; any other value comes from the reader. */\n let lastTop = 0;\n /** The viewport height the reading position was last applied to. */\n let lastHeight = 0;\n /**\n * While the reader scrolls, the feed does not write scrollTop, which would fight a finger, momentum, or a scroll\n * animation. It moves the rows by this much instead: the logical position minus the physical scrollTop.\n */\n let deferred = 0;\n /** Touches that began in the feed and have not ended. */\n const fingers = new Set<number>();\n /** Where those touches began. Their touchend still goes there after the feed removed the row. */\n const touched = new Set<EventTarget>();\n /** The reader's scroll runs, from its first move until its scrollend, or a quiet time where the engine has none. */\n let scrolling = false;\n /** A jump by the application ended the reader's scroll; what is left of its momentum is put back. */\n let overriding = false;\n let lastMove = 0;\n let endedAt = Number.NEGATIVE_INFINITY;\n /**\n * Until then, the next `scrollend` belongs to the feed's last write that moved the position. iOS delivers it late\n * enough to land in a later scroll of the reader, also in a pause of a slow momentum tail.\n */\n let owedUntil = 0;\n let endTimer: ReturnType<typeof setTimeout> | undefined;\n let hasScrollEnd = false;\n /** First item appended while the reader scrolls away from the end; reaching the end is judged before it. */\n let appendedFrom = -1;\n let focusIndex = -1;\n let fresh: HTMLElement[] = [];\n let restoring = false;\n let restoreAgain = false;\n let pendingAnnouncement: T[] = [];\n let announceTimer: ReturnType<typeof setTimeout> | undefined;\n let highlightTimer: ReturnType<typeof setTimeout> | undefined;\n /** \"Jump to latest\" asked for the newest page; it waits for running loads and stops new paging until it settles. */\n let newest: \"waiting\" | \"loading\" | undefined;\n let disposed = false;\n let observeRow: (row: HTMLElement) => void = () => {};\n /** Set while the ResizeObserver callback runs. */\n let observing = false;\n let unobserveRow: (row: HTMLElement) => void = () => {};\n const owner = getOwner();\n const rows = new Map<string, Row<T>>();\n const rowOf = new WeakMap<Element, Row<T>>();\n\n const [version, setVersion] = createSignal(0);\n /** Changes with every new `items` array, so separators see a replaced predecessor. */\n const [listVersion, setListVersion] = createSignal(0);\n const [tabStop, setTabStop] = createSignal(-1);\n // Known on the server too, so the empty slot never flashes for a feed that has items.\n const [count, setCount] = createSignal(untrack(() => props.items.length));\n const [atEnd, setAtEnd] = createSignal(true);\n const [unseen, setUnseen] = createSignal(0);\n const [highlighted, setHighlighted] = createSignal<string>();\n const [loadingOlder, setLoadingOlder] = createSignal(false);\n const [loadingNewer, setLoadingNewer] = createSignal(false);\n\n const estimate = (item: T) => {\n const size = props.estimateSize(item);\n return size > 0 ? size : 1;\n };\n\n const recompute = () => {\n const length = hi - lo;\n if (offsets.length !== length + 1) {\n offsets = new Float64Array(length + 1);\n dirtyFrom = 0;\n }\n for (let j = dirtyFrom; j < length; j++) offsets[j + 1] = offsets[j]! + sizes[lo + j]!;\n dirtyFrom = length;\n };\n const total = () => offsets[hi - lo]!;\n const offsetOf = (index: number) => offsets[Math.min(hi - lo, Math.max(0, index - lo))]!;\n /** The loaded item whose bottom edge lies below `y`. */\n const indexAt = (y: number) => {\n let low = 0;\n let high = hi - lo - 1;\n while (low < high) {\n const middle = (low + high) >> 1;\n if (offsets[middle + 1]! <= y) low = middle + 1;\n else high = middle;\n }\n return lo + Math.max(0, low);\n };\n\n const anchorAt = (top: number) => {\n const index = indexAt(top);\n return { index, delta: offsetOf(index) - top };\n };\n const logicalTop = () => viewport.scrollTop + deferred;\n const setStick = (value: boolean) => {\n // The anchor is not maintained while following the end; leaving the end keeps what is visible now.\n if (stick && !value && hi > lo) anchor = anchorAt(logicalTop());\n stick = value;\n if (value) setUnseen(0);\n if (atEnd() === value) return;\n setAtEnd(value);\n props.onEndChange?.(value);\n };\n /**\n * Whether `top` shows the end. It is judged in the geometry the position was last applied to: a viewport resize\n * not yet handled, and items appended while the reader scrolls away from the end, do not count yet.\n */\n const reachesEnd = (top: number) =>\n hi === list.length && !props.hasNewer && (appendedFrom >= 0 ? offsetOf(appendedFrom) : total()) - (top + lastHeight) <= END_TOLERANCE;\n\n const deferring = () => fingers.size > 0 || scrolling;\n /**\n * Whether the rows may stand in for the logical position `top` while the reader scrolls. Near the start they may\n * not: rows moved down would show empty space above the first item, and rows moved up would put the first items\n * out of the scroll range's reach. The margin is the overscan, so the write lands before the engine draws there.\n */\n const mayDefer = (top: number) => deferring() && Math.min(viewport.scrollTop, top) > OVERSCAN;\n /** Scrolls to `target`, within what the layout can reach, and returns the position the reader gets. */\n const writeTop = (target: number, immediate: boolean) => {\n const next = Math.min(Math.max(0, total() - viewport.clientHeight), Math.max(0, target));\n if (!immediate && mayDefer(next)) {\n // The rows move instead; the scroll range stays the same, so the engine clamps nothing.\n lastTop = viewport.scrollTop;\n deferred = next - lastTop;\n feed.style.height = `${total() - deferred}px`;\n return next;\n }\n deferred = 0;\n feed.style.height = `${total()}px`;\n const from = viewport.scrollTop;\n if (Math.abs(from - next) > 0.5) viewport.scrollTop = next;\n lastTop = viewport.scrollTop;\n if (Math.abs(lastTop - from) > 0.5) owedUntil = performance.now() + END_WAIT_MS;\n return next;\n };\n\n const updateRange = () => {\n const top = logicalTop();\n const height = viewport.clientHeight;\n const indices: number[] = [];\n if (hi > lo) {\n const start = indexAt(top - OVERSCAN);\n const end = indexAt(top + height + OVERSCAN);\n // The focused row stays mounted wherever it is, so focus never falls back to the document.\n const focused = focusIndex >= lo && focusIndex < hi;\n if (focused && focusIndex < start) indices.push(focusIndex);\n for (let index = start; index <= end; index++) indices.push(index);\n if (focused && focusIndex > end) indices.push(focusIndex);\n }\n renderRows(indices);\n setTabStop(focusIndex >= lo && focusIndex < hi ? focusIndex : hi > lo ? indexAt(top + height - 1) : -1);\n };\n\n const measure = (measured: ReadonlyArray<readonly [HTMLElement, number]>) => {\n let changed = false;\n for (const [node, size] of measured) {\n const row = rowOf.get(node);\n if (!row || row.index < lo || row.index >= hi) continue;\n const index = row.index;\n // The anchor keeps the content of its row in place: a separator or marker that appears or goes away above it\n // moves the row's top instead.\n const lead = leadOf(node);\n if (!stick && index === anchor.index && row.lead !== undefined) anchor = { index, delta: anchor.delta + row.lead - lead };\n row.lead = lead;\n if (Math.abs(sizes[index]! - size) > 0.1) {\n sizes[index] = size;\n dirtyFrom = Math.min(dirtyFrom, index - lo);\n changed = true;\n }\n }\n return changed;\n };\n\n const position = (index: number) =>\n props.firstPosition !== undefined ? props.firstPosition + index : props.hasOlder ? undefined : index + 1;\n const setSize = () => props.totalCount ?? (props.hasOlder || props.hasNewer ? -1 : count());\n\n const createRow = (item: T, key: string, at: number): Row<T> =>\n createRoot((dispose) => {\n const [index, setIndex] = createSignal(at);\n // While older items may come, the first loaded item's predecessor is unknown, so it gets no separator yet.\n const separator = () => (listVersion(), index() === 0 && props.hasOlder ? undefined : props.separator?.(item, list[index() - 1]));\n // Created once, as Solid's For does, so signals that the content reads while rendering never rebuild it.\n const content = untrack(() => props.children(item, index));\n const node = (\n <div\n class=\"k2b-virtual-feed__item\"\n role=\"article\"\n data-index={index()}\n data-key={key}\n data-highlighted={highlighted() === key ? \"\" : undefined}\n tabindex={index() === tabStop() ? 0 : -1}\n aria-label={props.itemLabel?.(item)}\n aria-posinset={position(index())}\n aria-setsize={setSize()}\n style={{ transform: `translateY(${(version(), offsetOf(index()) - deferred)}px)` }}\n >\n <Show when={separator()}>\n {(content) => (\n <div class=\"k2b-virtual-feed__separator\">\n <span>{content()}</span>\n </div>\n )}\n </Show>\n <Show when={props.markerKey === key}>\n <div class=\"k2b-virtual-feed__marker\">\n <span>{props.markerLabel ?? messages().feedNewMarker}</span>\n </div>\n </Show>\n {content}\n </div>\n ) as HTMLElement;\n const row: Row<T> = {\n item,\n node,\n index: at,\n setIndex: (next) => {\n row.index = next;\n setIndex(next);\n },\n dispose,\n };\n return row;\n }, owner);\n\n /** Mounts exactly these items in this order; rows that stay keep their node in place. */\n const renderRows = (indices: readonly number[]) => {\n const wanted = new Map<string, number>();\n for (const index of indices) wanted.set(keys[index]!, index);\n const active = feed.contains(document.activeElement) ? (document.activeElement as HTMLElement) : undefined;\n let focusedKey: string | undefined;\n for (const [key, row] of rows) {\n const index = wanted.get(key);\n if (index !== undefined && list[index] === row.item) continue;\n if (active && row.node.contains(active)) focusedKey = key;\n unobserveRow(row.node);\n row.node.remove();\n row.dispose();\n rows.delete(key);\n }\n let cursor = feed.firstChild;\n for (const index of indices) {\n const key = keys[index]!;\n let row = rows.get(key);\n if (row) row.setIndex(index);\n else {\n row = createRow(list[index]!, key, index);\n rows.set(key, row);\n rowOf.set(row.node, row);\n observeRow(row.node);\n fresh.push(row.node);\n }\n if (row.node === cursor) cursor = cursor.nextSibling;\n else feed.insertBefore(row.node, cursor);\n }\n // A reordered item moves its node, which blurs it, and a replaced item gets a new row: focus stays on the item.\n // Only when the item is gone does it fall back to the scroll area.\n if (active && document.activeElement !== active) {\n const replaced = focusedKey === undefined ? undefined : rows.get(focusedKey)?.node;\n (active.isConnected ? active : (replaced ?? viewport)).focus({ preventScroll: true });\n }\n };\n\n /**\n * Puts the reading position back after sizes, items, or the viewport changed: the end while following it, the\n * anchor otherwise. While the reader scrolls, it moves the rows instead of the scroll position, except for\n * `immediate` corrections, which follow structural changes and jumps.\n */\n const restore = (immediate = false) => {\n if (!viewport) return;\n if (restoring) {\n restoreAgain = true;\n return;\n }\n restoring = true;\n let target = 0;\n let top = 0;\n // Following the end shows the end of all items from now on, so later moves are judged against it.\n if (stick) appendedFrom = -1;\n try {\n for (let pass = 0; ; pass++) {\n restoreAgain = false;\n recompute();\n target = stick ? total() : offsetOf(anchor.index) - anchor.delta;\n top = writeTop(target, immediate);\n updateRange();\n setVersion((value) => value + 1);\n if (pass === MEASURE_PASSES) break;\n // Rows mounted here reach the ResizeObserver only next frame (its loop limit), so measure them now.\n const mounted = fresh.filter((node) => node.isConnected);\n fresh = [];\n if (measure(mounted.map((node) => [node, node.getBoundingClientRect().height] as const))) restoreAgain = true;\n if (!restoreAgain) break;\n }\n // A position the layout cannot reach, above its start or past its end, becomes the one the reader sees, so a\n // page that loads there later keeps it instead of moving to it.\n if (!stick && Math.abs(top - target) > 0.5) anchor = { index: anchor.index, delta: offsetOf(anchor.index) - top };\n } finally {\n restoring = false;\n }\n checkEdges();\n };\n\n /**\n * Keeps the reader's new position, reached from `from`. A row that the move reveals at the top can change size in the\n * same frame, before the feed measured it, and the reader never saw it. So the row at the top of `from` keeps its\n * place while it is still in view, and the rows the reader saw move by the reader's step alone.\n */\n const captureAnchor = (from: number) => {\n const top = logicalTop();\n setStick(reachesEnd(top));\n const seen = indexAt(from);\n anchor =\n offsetOf(seen + 1) > top && offsetOf(seen) < top + viewport.clientHeight\n ? { index: seen, delta: offsetOf(seen) - top }\n : anchorAt(top);\n };\n\n /**\n * Whether scrollTop moved since the feed last wrote or accounted for it. When a size change shortens the scroll\n * range, the engine clamps the position onto the new end; that move is the size change, not the reader.\n */\n const readerMoved = () => {\n const top = viewport.scrollTop;\n if (Math.abs(top - lastTop) <= 0.5) return false;\n const end = viewport.scrollHeight - viewport.clientHeight;\n return !(lastTop > end + 1 && Math.abs(top - end) <= 1);\n };\n\n /**\n * Takes a scroll position the feed did not make as the reader's, whatever moved it: touch, momentum, wheel, keys,\n * the scrollbar, focus, scrollIntoView, find in page, or assistive technology. Returns whether there was one.\n */\n const noteReader = () => {\n if (!readerMoved()) return false;\n lastMove = performance.now();\n if (overriding) {\n // Momentum left from before a jump of the application does not take the reader away again.\n armEnd(QUIET_MS);\n restore(true);\n return false;\n }\n armEnd();\n const from = lastTop + deferred;\n lastTop = viewport.scrollTop;\n scrolling = true;\n captureAnchor(from);\n return true;\n };\n\n const armEnd = (ms = hasScrollEnd ? END_WAIT_MS : QUIET_MS) => {\n clearTimeout(endTimer);\n endTimer = setTimeout(() => {\n endTimer = undefined;\n // A finger holds the scroll until it lifts; a move without its scroll event yet continues it.\n if (fingers.size > 0) return;\n if (readerMoved()) noteReader();\n else endScroll();\n }, ms);\n };\n\n /** The reader's scroll ended: what it held back is written in one step that moves nothing the reader sees. */\n const endScroll = () => {\n clearTimeout(endTimer);\n endTimer = undefined;\n scrolling = false;\n overriding = false;\n appendedFrom = -1;\n restore();\n };\n\n /**\n * A jump of the application ends the reader's scroll in progress: the jump lands at once, and what is left of the\n * momentum is put back until it has been still for a quiet time, or the reader touches, wheels, clicks, or presses\n * a key. A scrollend does not end this: a momentum stopped by the engine can still deliver a step in flight.\n */\n const takeOver = () => {\n appendedFrom = -1;\n if (!scrolling || fingers.size > 0) return;\n scrolling = false;\n overriding = true;\n lastMove = performance.now();\n armEnd(QUIET_MS);\n // A scroller that cannot scroll drops its momentum where the engine allows that. It scrolls again after a frame\n // in which nothing was left to put back.\n viewport.style.overflowY = \"hidden\";\n let seen = Number.NaN;\n const check = () => {\n if (disposed) return;\n if (overriding && lastMove !== seen) {\n seen = lastMove;\n requestAnimationFrame(check);\n } else viewport.style.removeProperty(\"overflow-y\");\n };\n requestAnimationFrame(check);\n };\n\n /** Lays out a window of about half the maximum around `center`. */\n const windowAround = (center: number) => {\n lo = center;\n hi = center + 1;\n let height = sizes[center]!;\n while (height < MAX_WINDOW / 2 && (lo > 0 || hi < list.length)) {\n if (lo > 0 && (center - lo <= hi - 1 - center || hi >= list.length)) height += sizes[--lo]!;\n else height += sizes[hi++]!;\n }\n dirtyFrom = 0;\n };\n\n const dropFocus = () => {\n if (focusIndex >= lo && focusIndex < hi) return;\n const focused = rows.get(keys[focusIndex] ?? \"\")?.node;\n focusIndex = -1;\n if (focused?.contains(document.activeElement)) viewport.focus({ preventScroll: true });\n };\n\n /**\n * Drops items from one side of the window, never those around the reading position, until it fits again. Returns\n * whether it dropped any.\n */\n const trimWindow = (side: \"start\" | \"end\") => {\n recompute();\n let excess = total() - MAX_WINDOW;\n if (excess <= 0) return false;\n const [from, to] = [lo, hi];\n const height = viewport.clientHeight;\n const top = stick ? total() - height : offsetOf(anchor.index) - anchor.delta;\n // While following the end the anchor is not maintained; only the visible end counts.\n const first = Math.min(indexAt(top - height - OVERSCAN), stick ? hi : anchor.index);\n const last = Math.max(indexAt(top + 2 * height + OVERSCAN), stick ? lo : anchor.index);\n if (side === \"start\") while (excess > 0 && lo < first) excess -= sizes[lo++]!;\n else while (excess > 0 && hi - 1 > last) excess -= sizes[--hi]!;\n dirtyFrom = 0;\n dropFocus();\n return lo !== from || hi !== to;\n };\n\n const loadNewest = () => {\n if (loadingOlder() || loadingNewer()) {\n newest = \"waiting\";\n return;\n }\n newest = \"loading\";\n load(\"newest\");\n };\n\n const load = (direction: \"older\" | \"newer\" | \"newest\") => {\n const setLoading = direction === \"older\" ? setLoadingOlder : setLoadingNewer;\n const callback = direction === \"older\" ? props.onLoadOlder : direction === \"newer\" ? props.onLoadNewer : props.onLoadNewest;\n if (!callback) return;\n // A load succeeded when its edge moved; other changes to `items` meanwhile do not count.\n const edge = () => (direction === \"older\" ? keys[0] : keys[keys.length - 1]);\n const before = edge();\n setLoading(true);\n let result: unknown;\n try {\n result = callback();\n } catch {\n result = undefined;\n }\n void Promise.resolve(result)\n .catch(() => undefined)\n .then(() => {\n setLoading(false);\n if (disposed) return;\n if (direction === \"newest\") newest = undefined;\n if (newest === \"waiting\") {\n if (!loadingOlder() && !loadingNewer()) loadNewest();\n return;\n }\n const arrived = edge() !== before;\n // A failed or empty load toward the end shows \"Jump to latest\" again instead of following an end that never came.\n if (direction !== \"older\" && !arrived && stick && props.hasNewer) setStick(false);\n // Keep loading while the reader still sits at the edge and the last page arrived.\n if (arrived) checkEdges();\n });\n };\n\n /** Grows the window or asks for more items when the reader nears an edge. */\n const checkEdges = () => {\n if (hi <= lo || restoring) return;\n const top = logicalTop();\n const height = viewport.clientHeight;\n // Rows measured taller than estimated can grow the window past the cap without any edge moving.\n if (total() > MAX_WINDOW && trimWindow(top + height / 2 > total() / 2 ? \"start\" : \"end\")) {\n restore(true);\n return;\n }\n const margin = Math.max(2_000, 3 * height);\n if (top < margin) {\n if (lo > 0) {\n let added = 0;\n while (lo > 0 && added < WINDOW_STEP) added += sizes[--lo]!;\n dirtyFrom = 0;\n trimWindow(\"end\");\n restore(true);\n return;\n }\n if (props.hasOlder && !loadingOlder() && !newest) load(\"older\");\n }\n if (total() - top - height < margin) {\n if (hi < list.length) {\n let added = 0;\n while (hi < list.length && added < WINDOW_STEP) added += sizes[hi++]!;\n dirtyFrom = 0;\n trimWindow(\"start\");\n restore(true);\n return;\n }\n if (props.hasNewer && !loadingNewer() && !newest) load(\"newer\");\n }\n };\n\n const queueAnnouncement = (added: readonly T[]) => {\n pendingAnnouncement = pendingAnnouncement.concat(added);\n if (announceTimer !== undefined) return;\n announceTimer = setTimeout(() => {\n announceTimer = undefined;\n const batch = pendingAnnouncement;\n pendingAnnouncement = [];\n const text = props.announce ? props.announce(batch) : messages().feedNewItems({ count: batch.length });\n if (!text) return;\n const line = document.createElement(\"p\");\n line.textContent = text;\n log.append(line);\n while (log.childElementCount > 3) log.firstElementChild?.remove();\n }, ANNOUNCE_MS);\n };\n\n /** Applies a new `items` array: appends follow the end, prepends and other changes keep the anchor by key. */\n const sync = (next: readonly T[]) => {\n // The reader may have scrolled in this frame before its scroll event ran; take that position first.\n if (keys.length > 0) noteReader();\n const length = next.length;\n const nextKeys = next.map(props.getKey);\n const previous = keys.length;\n const focusKey = focusIndex >= 0 ? keys[focusIndex] : undefined;\n let added: readonly T[] = [];\n let appended = false;\n /** A new feed, or one that shares no item with the last: start at its end. */\n const reset = () => {\n sizes = Float64Array.from(next, estimate);\n focusIndex = -1;\n appendedFrom = -1;\n setStick(!props.hasNewer);\n anchor = { index: 0, delta: 0 };\n setUnseen(0);\n // Pending announcements describe the items that are gone.\n clearTimeout(announceTimer);\n announceTimer = undefined;\n pendingAnnouncement = [];\n list = next;\n if (sizes.reduce((sum, size) => sum + size, 0) <= MAX_WINDOW) {\n lo = 0;\n hi = length;\n } else windowAround(length - 1);\n };\n if (previous === 0 || length === 0) reset();\n else if (length >= previous && runsMatch(keys, nextKeys, 0)) {\n const grown = new Float64Array(length);\n grown.set(sizes);\n for (let index = previous; index < length; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n if (hi === previous) hi = length;\n appended = true;\n // Away from the end, the reader's scroll in progress still reaches the end it was heading for.\n if (!stick && deferring() && appendedFrom < 0) appendedFrom = previous;\n // Only items after the newest one the feed has known are new; older pages toward the end are history.\n const known = endKey === undefined ? -1 : nextKeys.lastIndexOf(endKey);\n if (known >= 0) added = next.slice(Math.max(previous, known + 1));\n } else if (length >= previous && runsMatch(keys, nextKeys, length - previous)) {\n const shift = length - previous;\n const grown = new Float64Array(length);\n grown.set(sizes, shift);\n for (let index = 0; index < shift; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n anchor = { index: anchor.index + shift, delta: anchor.delta };\n if (focusIndex >= 0) focusIndex += shift;\n if (appendedFrom >= 0) appendedFrom += shift;\n if (lo > 0) lo += shift;\n hi += shift;\n } else {\n const known = new Map<string, number>();\n for (let index = 0; index < previous; index++) known.set(keys[index]!, sizes[index]!);\n const position = new Map<string, number>();\n for (let index = 0; index < length; index++) position.set(nextKeys[index]!, index);\n if (!nextKeys.some((key) => known.has(key))) reset();\n else {\n sizes = new Float64Array(length);\n for (let index = 0; index < length; index++) sizes[index] = known.get(nextKeys[index]!) ?? estimate(next[index]!);\n // An item that is gone hands its role to the nearest surviving neighbor.\n const survivor = (from: number) => {\n for (let distance = 0; distance < previous; distance++) {\n const below = position.get(keys[from + distance] ?? \"\");\n if (below !== undefined) return below;\n const above = position.get(keys[from - distance] ?? \"\");\n if (above !== undefined) return above;\n }\n return length - 1;\n };\n const wasAtStart = lo === 0;\n const wasAtEnd = hi === previous;\n appendedFrom = -1;\n anchor = { index: survivor(anchor.index), delta: anchor.delta };\n focusIndex = focusKey === undefined ? -1 : (position.get(focusKey) ?? -1);\n lo = wasAtStart ? 0 : survivor(lo);\n hi = wasAtEnd ? length : survivor(hi - 1) + 1;\n if (anchor.index < lo || anchor.index >= hi) {\n list = next;\n windowAround(anchor.index);\n }\n }\n }\n list = next;\n keys = nextKeys;\n dirtyFrom = 0;\n setCount(length);\n setListVersion((value) => value + 1);\n if (!props.hasNewer) endKey = nextKeys[length - 1];\n recompute();\n const center = stick ? hi - 1 : anchor.index;\n const trimmed = total() > MAX_WINDOW && trimWindow(center - lo > hi - 1 - center ? \"start\" : \"end\");\n // Appended items wait for the reader's scroll to end like other size changes; the rows show them meanwhile.\n restore(!appended || trimmed);\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n if (added.length > 0) {\n if (!stick) setUnseen((value) => value + added.length);\n queueAnnouncement(added);\n }\n };\n\n /**\n * Follows the end. With newer items not loaded, `onLoadNewest` replaces the items, after any running load; without\n * it, following the end keeps `onLoadNewer` paging until the newest item arrives or the reader scrolls away.\n */\n const scrollToEnd = () => {\n takeOver();\n setStick(!props.hasNewer || Boolean(props.onLoadNewer || props.onLoadNewest));\n if (props.hasNewer && props.onLoadNewest) loadNewest();\n if (hi < list.length) windowAround(list.length - 1);\n restore(true);\n };\n\n const scrollToKey = (key: string, options: VirtualFeedScrollOptions = {}) => {\n const index = keys.indexOf(key);\n if (index < 0) return false;\n takeOver();\n if (index < lo || index >= hi) windowAround(index);\n recompute();\n const delta = () => (options.align === \"start\" ? 0 : Math.max(0, (viewport.clientHeight - sizes[index]!) / 2));\n setStick(false);\n anchor = { index, delta: delta() };\n restore(true);\n // The row was measured while mounting, before this frame paints; center it on its real height.\n if (anchor.index === index && anchor.delta !== delta()) {\n anchor = { index, delta: delta() };\n restore(true);\n }\n if (reachesEnd(logicalTop())) setStick(true);\n if (options.highlight) {\n clearTimeout(highlightTimer);\n setHighlighted(key);\n highlightTimer = setTimeout(() => setHighlighted(undefined), HIGHLIGHT_MS);\n }\n return true;\n };\n\n const focusRow = (target: number) => {\n if (list.length === 0) return;\n const index = Math.min(list.length - 1, Math.max(0, target));\n // An edge load during the restore may add items synchronously and shift indices; the key keeps the target.\n const key = keys[index]!;\n const outside = index < lo || index >= hi;\n if (outside) windowAround(index);\n recompute();\n focusIndex = index;\n const top = logicalTop();\n const height = viewport.clientHeight;\n const start = offsetOf(index);\n const size = sizes[index]!;\n if (index === list.length - 1 && hi === list.length && !props.hasNewer) setStick(true);\n else if (outside) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start < top) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start + size > top + height) {\n setStick(false);\n anchor = { index, delta: Math.max(0, height - size) };\n restore(true);\n // The row was measured while mounting; align its real bottom before this frame paints.\n if (anchor.index === focusIndex) anchor = { index: focusIndex, delta: Math.max(0, height - sizes[focusIndex]!) };\n }\n restore(true);\n rows.get(key)?.node.focus({ preventScroll: true });\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const row = rowOf.get(event.target as Element);\n if (!row) return;\n const index = row.index;\n if (event.key === \"ArrowUp\" || event.key === \"PageUp\") focusRow(index - 1);\n else if (event.key === \"ArrowDown\" || event.key === \"PageDown\") focusRow(index + 1);\n else if (event.key === \"Home\" && event.ctrlKey) focusRow(0);\n else if (event.key === \"End\" && event.ctrlKey) {\n scrollToEnd();\n focusRow(list.length - 1);\n } else return;\n event.preventDefault();\n };\n\n const onScroll = () => {\n // The feed checked its edges when it wrote scrollTop. Its own scroll event arrives a frame later, and checking again\n // then would retry a load that failed in between.\n const reader = noteReader();\n // Near the start, the rows no longer stand in for a held-back correction; it is written now.\n if (deferred !== 0 && !mayDefer(logicalTop())) restore(true);\n else {\n updateRange();\n if (reader) checkEdges();\n }\n };\n\n /**\n * Ends the reader's scroll if the feed stands still for the next two frames. A `scrollend` not counted as a write's\n * can still be the late one of an earlier write; movement after it means the scroll goes on.\n */\n const confirmEnd = () => {\n const seen = lastMove;\n requestAnimationFrame(() =>\n requestAnimationFrame(() => {\n if (disposed || fingers.size > 0 || !scrolling || lastMove !== seen || readerMoved()) return;\n endScroll();\n }),\n );\n };\n\n const onScrollEnd = () => {\n // The scrollend of the feed's own write, not the end of the reader's scroll.\n if (performance.now() < owedUntil) {\n owedUntil = 0;\n return;\n }\n endedAt = performance.now();\n if (fingers.size > 0 || !scrolling) return;\n confirmEnd();\n };\n\n const controller: VirtualFeedController = {\n scrollToKey,\n scrollToEnd,\n isAtEnd: () => stick,\n };\n\n // Created before the first sync below, so items that an edge load adds synchronously during it are not lost.\n createEffect(on(() => props.items, sync, { defer: true }));\n // More items can appear at an edge without new items, for example when a live update reports newer ones.\n createEffect(\n on(\n [() => props.hasOlder, () => props.hasNewer],\n () => {\n if (!props.hasNewer) endKey = keys[keys.length - 1];\n if (hi <= lo) return;\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n // Only newer pages can be followed; with just `onLoadNewest`, \"Jump to latest\" has to show.\n else if (stick && props.hasNewer && !props.onLoadNewer) setStick(false);\n checkEdges();\n },\n { defer: true },\n ),\n );\n\n onMount(() => {\n hasScrollEnd = \"onscrollend\" in window;\n lastHeight = viewport.clientHeight;\n const observer = new ResizeObserver((entries) => {\n observing = true;\n try {\n // A scroll of the reader in this frame counts first, in the geometry from before these changes.\n noteReader();\n fresh = [];\n let resized = false;\n const measured: Array<readonly [HTMLElement, number]> = [];\n for (const entry of entries) {\n if (entry.target === viewport) {\n // A shorter viewport (a growing footer or keyboard) keeps what is at its bottom in place.\n const height = viewport.clientHeight;\n if (!stick) anchor = { index: anchor.index, delta: anchor.delta + height - lastHeight };\n lastHeight = height;\n resized = true;\n } else if (entry.target.isConnected) {\n const row = entry.target as HTMLElement;\n measured.push([row, entry.borderBoxSize?.[0]?.blockSize ?? row.getBoundingClientRect().height]);\n }\n }\n if (measure(measured) || resized) restore();\n } finally {\n observing = false;\n }\n });\n observer.observe(viewport);\n // Rows observed inside the observer's own callback miss its first notification, which raises a window error.\n // They were measured while mounting, so they are observed from the next frame on.\n let later: HTMLElement[] = [];\n let laterFrame = 0;\n observeRow = (row) => {\n if (!observing) return observer.observe(row);\n later.push(row);\n laterFrame ||= requestAnimationFrame(() => {\n laterFrame = 0;\n for (const node of later) if (node.isConnected) observer.observe(node);\n later = [];\n });\n };\n unobserveRow = (row) => observer.unobserve(row);\n const release = () => {\n for (const target of touched) {\n target.removeEventListener(\"touchend\", touchEnd);\n target.removeEventListener(\"touchcancel\", touchEnd);\n }\n touched.clear();\n };\n // Input of the reader ends a takeover by the application at once, and lets the feed scroll for that input.\n const act = () => {\n overriding = false;\n viewport.style.removeProperty(\"overflow-y\");\n };\n const touchStart = (event: TouchEvent) => {\n // A touch whose end the feed missed has left the screen by now.\n const down = new Set(Array.from(event.touches, (touch) => touch.identifier));\n for (const id of fingers) if (!down.has(id)) fingers.delete(id);\n for (const touch of Array.from(event.changedTouches)) fingers.add(touch.identifier);\n act();\n // Touch events stay with the element the touch began on, also when the feed removes its row meanwhile.\n const target = event.target;\n if (target && !touched.has(target)) {\n touched.add(target);\n target.addEventListener(\"touchend\", touchEnd, { passive: true });\n target.addEventListener(\"touchcancel\", touchEnd, { passive: true });\n }\n };\n function touchEnd(event: Event) {\n for (const touch of Array.from((event as TouchEvent).changedTouches)) fingers.delete(touch.identifier);\n if (fingers.size > 0) return;\n release();\n // The last step of a short flick can have moved scrollTop before its scroll event; it counts before anything ends.\n if (!scrolling && !noteReader()) return endScroll();\n armEnd();\n // A scroll that ended under the finger ends now, unless the release starts a momentum.\n if (endedAt >= lastMove) confirmEnd();\n }\n viewport.addEventListener(\"touchstart\", touchStart, { passive: true });\n viewport.addEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.addEventListener(type, act, { passive: true });\n onCleanup(() => {\n disposed = true;\n observer.disconnect();\n cancelAnimationFrame(laterFrame);\n viewport.removeEventListener(\"touchstart\", touchStart);\n viewport.removeEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.removeEventListener(type, act);\n release();\n clearTimeout(endTimer);\n clearTimeout(announceTimer);\n clearTimeout(highlightTimer);\n for (const row of rows.values()) row.dispose();\n rows.clear();\n });\n sync(props.items);\n props.controller?.(controller);\n });\n\n const shownCount = () => props.newCount ?? unseen();\n\n return (\n <div class={props.class ? `k2b-virtual-feed ${props.class}` : \"k2b-virtual-feed\"}>\n <div ref={viewport} class=\"k2b-virtual-feed__viewport\" tabindex=\"-1\" onScroll={onScroll}>\n <div\n ref={feed}\n class=\"k2b-virtual-feed__feed\"\n role=\"feed\"\n aria-label={props.label}\n aria-busy={props.busy || loadingOlder() || loadingNewer() ? \"true\" : \"false\"}\n onKeyDown={onKeyDown}\n onFocusIn={(event) => {\n const node = (event.target as HTMLElement).closest(\".k2b-virtual-feed__item\");\n const row = node ? rowOf.get(node) : undefined;\n if (row) {\n focusIndex = row.index;\n setTabStop(focusIndex);\n }\n }}\n onFocusOut={(event) => {\n const next = event.relatedTarget as Node | null;\n if (next && !feed.contains(next)) focusIndex = -1;\n }}\n />\n </div>\n <Show when={count() === 0 && props.empty}>\n <div class=\"k2b-virtual-feed__empty\">{props.empty}</div>\n </Show>\n <Show when={loadingOlder()}>\n <div class=\"k2b-virtual-feed__status\" aria-hidden=\"true\">\n <i class=\"ti ti-loader-2 k2b-spin\" />\n {messages().loading}\n </div>\n </Show>\n <Show when={!atEnd() && count() > 0}>\n <button\n type=\"button\"\n class=\"k2b-virtual-feed__end\"\n aria-label={shownCount() > 0 ? messages().feedJumpToLatestCount({ count: shownCount() }) : undefined}\n onClick={() => {\n scrollToEnd();\n // The button disappears at the end; keep focus in the feed instead of the document.\n if (props.hasNewer) viewport.focus({ preventScroll: true });\n else focusRow(list.length - 1);\n }}\n >\n <i class={loadingNewer() ? \"ti ti-loader-2 k2b-spin\" : \"ti ti-arrow-down\"} aria-hidden=\"true\" />\n {messages().feedJumpToLatest}\n <Show when={shownCount() > 0}>\n <span class=\"k2b-virtual-feed__count\" aria-hidden=\"true\">\n {shownCount()}\n </span>\n </Show>\n </button>\n </Show>\n <div ref={log} class=\"k2b-sr-only\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\" />\n </div>\n );\n}\n\nexport default VirtualFeed;\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["content/VirtualFeed.tsx"],"sourcesContent":["import { type Accessor, createEffect, createRoot, createSignal, getOwner, type JSX, on, onCleanup, onMount, Show, untrack } from \"solid-js\";\nimport { useUiMessages } from \"../intl/messages\";\nimport { useFeedMessages } from \"./feed-messages\";\n\n/**\n * The tallest loaded window in px. Firefox renders an element taller than about 17.9 M px with a height of 0, so the\n * feed lays out at most this much and drops far items while it keeps the reading position.\n */\nconst MAX_WINDOW = 8_000_000;\n/** How much the loaded window grows at once when the reader nears one of its edges. */\nconst WINDOW_STEP = 2_000_000;\n/** Rows rendered above and below the visible part, in px. */\nconst OVERSCAN = 600;\n/** Distance from the end, in px, that still counts as being at the end. */\nconst END_TOLERANCE = 2;\n/**\n * Rows mounted during one correction reach the ResizeObserver a frame late; measure up to this many passes at once.\n * A last pass places the rows; the observer measures what that pass mounted.\n */\nconst MEASURE_PASSES = 4;\nconst ANNOUNCE_MS = 1_000;\nconst HIGHLIGHT_MS = 1_600;\n/** In engines without `scrollend`, the reader's scroll has ended after this long without moving. */\nconst QUIET_MS = 300;\n/** The longest wait for the `scrollend` of the reader's scroll after it last moved, or of a write of the feed. */\nconst END_WAIT_MS = 1_000;\n\nexport type VirtualFeedScrollOptions = {\n /** Where the item lands in the visible area. Defaults to `\"center\"`. */\n align?: \"start\" | \"center\";\n /** Tints the item briefly so the reader finds it. */\n highlight?: boolean;\n};\n\nexport type VirtualFeedController = {\n /**\n * Scrolls to a loaded item, also when the reader's scroll still coasts. Returns false when no loaded item has this\n * key, so the caller can load around it first.\n */\n scrollToKey: (key: string, options?: VirtualFeedScrollOptions) => boolean;\n /**\n * Follows the end again, also when the reader's scroll still coasts. When newer items exist but are not loaded, it\n * asks `onLoadNewest` for them first.\n */\n scrollToEnd: () => void;\n /** Whether the reader is at the end and new items keep the feed there. */\n isAtEnd: () => boolean;\n};\n\nexport type VirtualFeedProps<T> = {\n /** Loaded items, oldest first. Replace the array to add, remove, or change items. */\n items: readonly T[];\n /** Stable, unique identity of an item across updates. */\n getKey: (item: T) => string;\n /** Height in px before the item was measured. Close estimates mean fewer corrections while scrolling. */\n estimateSize: (item: T) => number;\n /** Content of one item, created once per item object as with Solid's `For`. `index` is its position in `items`. */\n children: (item: T, index: Accessor<number>) => JSX.Element;\n /** Accessible name of the feed. */\n label: string;\n /** Accessible name of one item, for example its author and time. */\n itemLabel?: (item: T) => string | undefined;\n /**\n * Label shown above an item, for example when the day changes. Return nothing for no separator. While `hasOlder` is\n * set, the first loaded item has no known predecessor and gets none.\n */\n separator?: (item: T, previous: T | undefined) => JSX.Element;\n /** Key of the first item the reader has not seen; a marker appears above it. */\n markerKey?: string | null;\n /** Text of that marker. Defaults to \"New\". */\n markerLabel?: string;\n /** Older items exist that `items` does not contain yet. */\n hasOlder?: boolean;\n /** Newer items exist that `items` does not contain yet. */\n hasNewer?: boolean;\n /** Called near the start of the loaded items while `hasOlder` is true. Prepend the next older page to `items`. */\n onLoadOlder?: () => unknown;\n /** Called near the end of the loaded items while `hasNewer` is true. Append the next newer page to `items`. */\n onLoadNewer?: () => unknown;\n /** Called by \"Jump to latest\" while `hasNewer` is true. Replace `items` with the newest page. */\n onLoadNewest?: () => unknown;\n /** Marks the feed as busy for assistive technology, for example during the first load. */\n busy?: boolean;\n /** Number of items in the whole feed when known. */\n totalCount?: number;\n /** One-based position of `items[0]` in the whole feed when known. */\n firstPosition?: number;\n /**\n * Count shown on \"Jump to latest\". Defaults to the new items added while the reader was away from the end, which\n * excludes pages of older history loaded toward the end.\n */\n newCount?: number;\n /** Text announced for new items added at the end, bundled per second. Return nothing to stay silent. */\n announce?: (added: readonly T[]) => string | undefined;\n /** Called when the reader reaches or leaves the end. */\n onEndChange?: (atEnd: boolean) => void;\n /** Receives the controller once the feed is mounted. */\n controller?: (controller: VirtualFeedController) => void;\n /** Shown while `items` is empty. */\n empty?: JSX.Element;\n class?: string;\n};\n\n/**\n * One mounted row. Rows are created and removed but never moved, so focus, media, and frames inside them survive.\n * `lead` is the measured height of the separator and marker above the content.\n */\ntype Row<T> = { item: T; node: HTMLElement; index: number; lead?: number; setIndex: (index: number) => void; dispose: () => void };\n\nconst runsMatch = (before: readonly string[], after: readonly string[], shift: number) => {\n for (let index = 0; index < before.length; index++) if (before[index] !== after[index + shift]) return false;\n return true;\n};\n\n/** Height of the separator and marker that a row shows above its content. */\nconst leadOf = (node: HTMLElement) => {\n let height = 0;\n for (const child of node.children) {\n if (!child.classList.contains(\"k2b-virtual-feed__separator\") && !child.classList.contains(\"k2b-virtual-feed__marker\")) break;\n height += child.getBoundingClientRect().height;\n }\n return height;\n};\n\n/**\n * A virtualized feed of items with variable heights that grows at both ends and keeps the reading position: it stays\n * at the end while the reader is there, and otherwise keeps the item in view where it is, whatever loads, grows, or\n * resizes around it.\n */\nexport function VirtualFeed<T>(props: VirtualFeedProps<T>): JSX.Element {\n const messages = useUiMessages();\n const feedMessages = useFeedMessages();\n let viewport!: HTMLDivElement;\n let feed!: HTMLDivElement;\n let log!: HTMLDivElement;\n\n // Layout: one size per item and prefix sums over the loaded window [lo, hi).\n let list: readonly T[] = [];\n let keys: string[] = [];\n let sizes = new Float64Array(0);\n let lo = 0;\n let hi = 0;\n let offsets = new Float64Array(1);\n let dirtyFrom = 0;\n\n // Reading position: follow the end, or keep one item (index) at a pixel distance (delta) below the visible top.\n let stick = true;\n let anchor = { index: 0, delta: 0 };\n /** Key of the last item while no newer items existed; items appended after it are new. */\n let endKey: string | undefined;\n /** The last scrollTop the feed wrote or accounted for; any other value comes from the reader. */\n let lastTop = 0;\n /** The viewport height the reading position was last applied to. */\n let lastHeight = 0;\n /**\n * While the reader scrolls, the feed does not write scrollTop, which would fight a finger, momentum, or a scroll\n * animation. It moves the rows by this much instead: the logical position minus the physical scrollTop.\n */\n let deferred = 0;\n /** Touches that began in the feed and have not ended. */\n const fingers = new Set<number>();\n /** Where those touches began. Their touchend still goes there after the feed removed the row. */\n const touched = new Set<EventTarget>();\n /** The reader's scroll runs, from its first move until its scrollend, or a quiet time where the engine has none. */\n let scrolling = false;\n /** A jump by the application ended the reader's scroll; what is left of its momentum is put back. */\n let overriding = false;\n let lastMove = 0;\n let endedAt = Number.NEGATIVE_INFINITY;\n /**\n * Until then, the next `scrollend` belongs to the feed's last write that moved the position. iOS delivers it late\n * enough to land in a later scroll of the reader, also in a pause of a slow momentum tail.\n */\n let owedUntil = 0;\n let endTimer: ReturnType<typeof setTimeout> | undefined;\n let hasScrollEnd = false;\n /** First item appended while the reader scrolls away from the end; reaching the end is judged before it. */\n let appendedFrom = -1;\n let focusIndex = -1;\n let fresh: HTMLElement[] = [];\n let restoring = false;\n let restoreAgain = false;\n let pendingAnnouncement: T[] = [];\n let announceTimer: ReturnType<typeof setTimeout> | undefined;\n let highlightTimer: ReturnType<typeof setTimeout> | undefined;\n /** \"Jump to latest\" asked for the newest page; it waits for running loads and stops new paging until it settles. */\n let newest: \"waiting\" | \"loading\" | undefined;\n let disposed = false;\n let observeRow: (row: HTMLElement) => void = () => {};\n /** Set while the ResizeObserver callback runs. */\n let observing = false;\n let unobserveRow: (row: HTMLElement) => void = () => {};\n const owner = getOwner();\n const rows = new Map<string, Row<T>>();\n const rowOf = new WeakMap<Element, Row<T>>();\n\n const [version, setVersion] = createSignal(0);\n /** Changes with every new `items` array, so separators see a replaced predecessor. */\n const [listVersion, setListVersion] = createSignal(0);\n const [tabStop, setTabStop] = createSignal(-1);\n // Known on the server too, so the empty slot never flashes for a feed that has items.\n const [count, setCount] = createSignal(untrack(() => props.items.length));\n const [atEnd, setAtEnd] = createSignal(true);\n const [unseen, setUnseen] = createSignal(0);\n const [highlighted, setHighlighted] = createSignal<string>();\n const [loadingOlder, setLoadingOlder] = createSignal(false);\n const [loadingNewer, setLoadingNewer] = createSignal(false);\n\n const estimate = (item: T) => {\n const size = props.estimateSize(item);\n return size > 0 ? size : 1;\n };\n\n const recompute = () => {\n const length = hi - lo;\n if (offsets.length !== length + 1) {\n offsets = new Float64Array(length + 1);\n dirtyFrom = 0;\n }\n for (let j = dirtyFrom; j < length; j++) offsets[j + 1] = offsets[j]! + sizes[lo + j]!;\n dirtyFrom = length;\n };\n const total = () => offsets[hi - lo]!;\n const offsetOf = (index: number) => offsets[Math.min(hi - lo, Math.max(0, index - lo))]!;\n /** The loaded item whose bottom edge lies below `y`. */\n const indexAt = (y: number) => {\n let low = 0;\n let high = hi - lo - 1;\n while (low < high) {\n const middle = (low + high) >> 1;\n if (offsets[middle + 1]! <= y) low = middle + 1;\n else high = middle;\n }\n return lo + Math.max(0, low);\n };\n\n const anchorAt = (top: number) => {\n const index = indexAt(top);\n return { index, delta: offsetOf(index) - top };\n };\n const logicalTop = () => viewport.scrollTop + deferred;\n const setStick = (value: boolean) => {\n // The anchor is not maintained while following the end; leaving the end keeps what is visible now.\n if (stick && !value && hi > lo) anchor = anchorAt(logicalTop());\n stick = value;\n if (value) setUnseen(0);\n if (atEnd() === value) return;\n setAtEnd(value);\n props.onEndChange?.(value);\n };\n /**\n * Whether `top` shows the end. It is judged in the geometry the position was last applied to: a viewport resize\n * not yet handled, and items appended while the reader scrolls away from the end, do not count yet.\n */\n const reachesEnd = (top: number) =>\n hi === list.length && !props.hasNewer && (appendedFrom >= 0 ? offsetOf(appendedFrom) : total()) - (top + lastHeight) <= END_TOLERANCE;\n\n const deferring = () => fingers.size > 0 || scrolling;\n /**\n * Whether the rows may stand in for the logical position `top` while the reader scrolls. Near the start they may\n * not: rows moved down would show empty space above the first item, and rows moved up would put the first items\n * out of the scroll range's reach. The margin is the overscan, so the write lands before the engine draws there.\n */\n const mayDefer = (top: number) => deferring() && Math.min(viewport.scrollTop, top) > OVERSCAN;\n /** Scrolls to `target`, within what the layout can reach, and returns the position the reader gets. */\n const writeTop = (target: number, immediate: boolean) => {\n const next = Math.min(Math.max(0, total() - viewport.clientHeight), Math.max(0, target));\n if (!immediate && mayDefer(next)) {\n // The rows move instead; the scroll range stays the same, so the engine clamps nothing.\n lastTop = viewport.scrollTop;\n deferred = next - lastTop;\n feed.style.height = `${total() - deferred}px`;\n return next;\n }\n deferred = 0;\n feed.style.height = `${total()}px`;\n const from = viewport.scrollTop;\n if (Math.abs(from - next) > 0.5) viewport.scrollTop = next;\n lastTop = viewport.scrollTop;\n if (Math.abs(lastTop - from) > 0.5) owedUntil = performance.now() + END_WAIT_MS;\n return next;\n };\n\n const updateRange = () => {\n const top = logicalTop();\n const height = viewport.clientHeight;\n const indices: number[] = [];\n if (hi > lo) {\n const start = indexAt(top - OVERSCAN);\n const end = indexAt(top + height + OVERSCAN);\n // The focused row stays mounted wherever it is, so focus never falls back to the document.\n const focused = focusIndex >= lo && focusIndex < hi;\n if (focused && focusIndex < start) indices.push(focusIndex);\n for (let index = start; index <= end; index++) indices.push(index);\n if (focused && focusIndex > end) indices.push(focusIndex);\n }\n renderRows(indices);\n setTabStop(focusIndex >= lo && focusIndex < hi ? focusIndex : hi > lo ? indexAt(top + height - 1) : -1);\n };\n\n const measure = (measured: ReadonlyArray<readonly [HTMLElement, number]>) => {\n let changed = false;\n for (const [node, size] of measured) {\n const row = rowOf.get(node);\n if (!row || row.index < lo || row.index >= hi) continue;\n const index = row.index;\n // The anchor keeps the content of its row in place: a separator or marker that appears or goes away above it\n // moves the row's top instead.\n const lead = leadOf(node);\n if (!stick && index === anchor.index && row.lead !== undefined) anchor = { index, delta: anchor.delta + row.lead - lead };\n row.lead = lead;\n if (Math.abs(sizes[index]! - size) > 0.1) {\n sizes[index] = size;\n dirtyFrom = Math.min(dirtyFrom, index - lo);\n changed = true;\n }\n }\n return changed;\n };\n\n const position = (index: number) =>\n props.firstPosition !== undefined ? props.firstPosition + index : props.hasOlder ? undefined : index + 1;\n const setSize = () => props.totalCount ?? (props.hasOlder || props.hasNewer ? -1 : count());\n\n const createRow = (item: T, key: string, at: number): Row<T> =>\n createRoot((dispose) => {\n const [index, setIndex] = createSignal(at);\n // While older items may come, the first loaded item's predecessor is unknown, so it gets no separator yet.\n const separator = () => (listVersion(), index() === 0 && props.hasOlder ? undefined : props.separator?.(item, list[index() - 1]));\n // Created once, as Solid's For does, so signals that the content reads while rendering never rebuild it.\n const content = untrack(() => props.children(item, index));\n const node = (\n <div\n class=\"k2b-virtual-feed__item\"\n role=\"article\"\n data-index={index()}\n data-key={key}\n data-highlighted={highlighted() === key ? \"\" : undefined}\n tabindex={index() === tabStop() ? 0 : -1}\n aria-label={props.itemLabel?.(item)}\n aria-posinset={position(index())}\n aria-setsize={setSize()}\n style={{ transform: `translateY(${(version(), offsetOf(index()) - deferred)}px)` }}\n >\n <Show when={separator()}>\n {(content) => (\n <div class=\"k2b-virtual-feed__separator\">\n <span>{content()}</span>\n </div>\n )}\n </Show>\n <Show when={props.markerKey === key}>\n <div class=\"k2b-virtual-feed__marker\">\n <span>{props.markerLabel ?? feedMessages().feedNewMarker}</span>\n </div>\n </Show>\n {content}\n </div>\n ) as HTMLElement;\n const row: Row<T> = {\n item,\n node,\n index: at,\n setIndex: (next) => {\n row.index = next;\n setIndex(next);\n },\n dispose,\n };\n return row;\n }, owner);\n\n /** Mounts exactly these items in this order; rows that stay keep their node in place. */\n const renderRows = (indices: readonly number[]) => {\n const wanted = new Map<string, number>();\n for (const index of indices) wanted.set(keys[index]!, index);\n const active = feed.contains(document.activeElement) ? (document.activeElement as HTMLElement) : undefined;\n let focusedKey: string | undefined;\n for (const [key, row] of rows) {\n const index = wanted.get(key);\n if (index !== undefined && list[index] === row.item) continue;\n if (active && row.node.contains(active)) focusedKey = key;\n unobserveRow(row.node);\n row.node.remove();\n row.dispose();\n rows.delete(key);\n }\n let cursor = feed.firstChild;\n for (const index of indices) {\n const key = keys[index]!;\n let row = rows.get(key);\n if (row) row.setIndex(index);\n else {\n row = createRow(list[index]!, key, index);\n rows.set(key, row);\n rowOf.set(row.node, row);\n observeRow(row.node);\n fresh.push(row.node);\n }\n if (row.node === cursor) cursor = cursor.nextSibling;\n else feed.insertBefore(row.node, cursor);\n }\n // A reordered item moves its node, which blurs it, and a replaced item gets a new row: focus stays on the item.\n // Only when the item is gone does it fall back to the scroll area.\n if (active && document.activeElement !== active) {\n const replaced = focusedKey === undefined ? undefined : rows.get(focusedKey)?.node;\n (active.isConnected ? active : (replaced ?? viewport)).focus({ preventScroll: true });\n }\n };\n\n /**\n * Puts the reading position back after sizes, items, or the viewport changed: the end while following it, the\n * anchor otherwise. While the reader scrolls, it moves the rows instead of the scroll position, except for\n * `immediate` corrections, which follow structural changes and jumps.\n */\n const restore = (immediate = false) => {\n if (!viewport) return;\n if (restoring) {\n restoreAgain = true;\n return;\n }\n restoring = true;\n let target = 0;\n let top = 0;\n // Following the end shows the end of all items from now on, so later moves are judged against it.\n if (stick) appendedFrom = -1;\n try {\n for (let pass = 0; ; pass++) {\n restoreAgain = false;\n recompute();\n target = stick ? total() : offsetOf(anchor.index) - anchor.delta;\n top = writeTop(target, immediate);\n updateRange();\n setVersion((value) => value + 1);\n if (pass === MEASURE_PASSES) break;\n // Rows mounted here reach the ResizeObserver only next frame (its loop limit), so measure them now.\n const mounted = fresh.filter((node) => node.isConnected);\n fresh = [];\n if (measure(mounted.map((node) => [node, node.getBoundingClientRect().height] as const))) restoreAgain = true;\n if (!restoreAgain) break;\n }\n // A position the layout cannot reach, above its start or past its end, becomes the one the reader sees, so a\n // page that loads there later keeps it instead of moving to it.\n if (!stick && Math.abs(top - target) > 0.5) anchor = { index: anchor.index, delta: offsetOf(anchor.index) - top };\n } finally {\n restoring = false;\n }\n checkEdges();\n };\n\n /**\n * Keeps the reader's new position, reached from `from`. A row that the move reveals at the top can change size in the\n * same frame, before the feed measured it, and the reader never saw it. So the row at the top of `from` keeps its\n * place while it is still in view, and the rows the reader saw move by the reader's step alone.\n */\n const captureAnchor = (from: number) => {\n const top = logicalTop();\n setStick(reachesEnd(top));\n const seen = indexAt(from);\n anchor =\n offsetOf(seen + 1) > top && offsetOf(seen) < top + viewport.clientHeight\n ? { index: seen, delta: offsetOf(seen) - top }\n : anchorAt(top);\n };\n\n /**\n * Whether scrollTop moved since the feed last wrote or accounted for it. When a size change shortens the scroll\n * range, the engine clamps the position onto the new end; that move is the size change, not the reader.\n */\n const readerMoved = () => {\n const top = viewport.scrollTop;\n if (Math.abs(top - lastTop) <= 0.5) return false;\n const end = viewport.scrollHeight - viewport.clientHeight;\n return !(lastTop > end + 1 && Math.abs(top - end) <= 1);\n };\n\n /**\n * Takes a scroll position the feed did not make as the reader's, whatever moved it: touch, momentum, wheel, keys,\n * the scrollbar, focus, scrollIntoView, find in page, or assistive technology. Returns whether there was one.\n */\n const noteReader = () => {\n if (!readerMoved()) return false;\n lastMove = performance.now();\n if (overriding) {\n // Momentum left from before a jump of the application does not take the reader away again.\n armEnd(QUIET_MS);\n restore(true);\n return false;\n }\n armEnd();\n const from = lastTop + deferred;\n lastTop = viewport.scrollTop;\n scrolling = true;\n captureAnchor(from);\n return true;\n };\n\n const armEnd = (ms = hasScrollEnd ? END_WAIT_MS : QUIET_MS) => {\n clearTimeout(endTimer);\n endTimer = setTimeout(() => {\n endTimer = undefined;\n // A finger holds the scroll until it lifts; a move without its scroll event yet continues it.\n if (fingers.size > 0) return;\n if (readerMoved()) noteReader();\n else endScroll();\n }, ms);\n };\n\n /** The reader's scroll ended: what it held back is written in one step that moves nothing the reader sees. */\n const endScroll = () => {\n clearTimeout(endTimer);\n endTimer = undefined;\n scrolling = false;\n overriding = false;\n appendedFrom = -1;\n restore();\n };\n\n /**\n * A jump of the application ends the reader's scroll in progress: the jump lands at once, and what is left of the\n * momentum is put back until it has been still for a quiet time, or the reader touches, wheels, clicks, or presses\n * a key. A scrollend does not end this: a momentum stopped by the engine can still deliver a step in flight.\n */\n const takeOver = () => {\n appendedFrom = -1;\n if (!scrolling || fingers.size > 0) return;\n scrolling = false;\n overriding = true;\n lastMove = performance.now();\n armEnd(QUIET_MS);\n // A scroller that cannot scroll drops its momentum where the engine allows that. It scrolls again after a frame\n // in which nothing was left to put back.\n viewport.style.overflowY = \"hidden\";\n let seen = Number.NaN;\n const check = () => {\n if (disposed) return;\n if (overriding && lastMove !== seen) {\n seen = lastMove;\n requestAnimationFrame(check);\n } else viewport.style.removeProperty(\"overflow-y\");\n };\n requestAnimationFrame(check);\n };\n\n /** Lays out a window of about half the maximum around `center`. */\n const windowAround = (center: number) => {\n lo = center;\n hi = center + 1;\n let height = sizes[center]!;\n while (height < MAX_WINDOW / 2 && (lo > 0 || hi < list.length)) {\n if (lo > 0 && (center - lo <= hi - 1 - center || hi >= list.length)) height += sizes[--lo]!;\n else height += sizes[hi++]!;\n }\n dirtyFrom = 0;\n };\n\n const dropFocus = () => {\n if (focusIndex >= lo && focusIndex < hi) return;\n const focused = rows.get(keys[focusIndex] ?? \"\")?.node;\n focusIndex = -1;\n if (focused?.contains(document.activeElement)) viewport.focus({ preventScroll: true });\n };\n\n /**\n * Drops items from one side of the window, never those around the reading position, until it fits again. Returns\n * whether it dropped any.\n */\n const trimWindow = (side: \"start\" | \"end\") => {\n recompute();\n let excess = total() - MAX_WINDOW;\n if (excess <= 0) return false;\n const [from, to] = [lo, hi];\n const height = viewport.clientHeight;\n const top = stick ? total() - height : offsetOf(anchor.index) - anchor.delta;\n // While following the end the anchor is not maintained; only the visible end counts.\n const first = Math.min(indexAt(top - height - OVERSCAN), stick ? hi : anchor.index);\n const last = Math.max(indexAt(top + 2 * height + OVERSCAN), stick ? lo : anchor.index);\n if (side === \"start\") while (excess > 0 && lo < first) excess -= sizes[lo++]!;\n else while (excess > 0 && hi - 1 > last) excess -= sizes[--hi]!;\n dirtyFrom = 0;\n dropFocus();\n return lo !== from || hi !== to;\n };\n\n const loadNewest = () => {\n if (loadingOlder() || loadingNewer()) {\n newest = \"waiting\";\n return;\n }\n newest = \"loading\";\n load(\"newest\");\n };\n\n const load = (direction: \"older\" | \"newer\" | \"newest\") => {\n const setLoading = direction === \"older\" ? setLoadingOlder : setLoadingNewer;\n const callback = direction === \"older\" ? props.onLoadOlder : direction === \"newer\" ? props.onLoadNewer : props.onLoadNewest;\n if (!callback) return;\n // A load succeeded when its edge moved; other changes to `items` meanwhile do not count.\n const edge = () => (direction === \"older\" ? keys[0] : keys[keys.length - 1]);\n const before = edge();\n setLoading(true);\n let result: unknown;\n try {\n result = callback();\n } catch {\n result = undefined;\n }\n void Promise.resolve(result)\n .catch(() => undefined)\n .then(() => {\n setLoading(false);\n if (disposed) return;\n if (direction === \"newest\") newest = undefined;\n if (newest === \"waiting\") {\n if (!loadingOlder() && !loadingNewer()) loadNewest();\n return;\n }\n const arrived = edge() !== before;\n // A failed or empty load toward the end shows \"Jump to latest\" again instead of following an end that never came.\n if (direction !== \"older\" && !arrived && stick && props.hasNewer) setStick(false);\n // Keep loading while the reader still sits at the edge and the last page arrived.\n if (arrived) checkEdges();\n });\n };\n\n /** Grows the window or asks for more items when the reader nears an edge. */\n const checkEdges = () => {\n if (hi <= lo || restoring) return;\n const top = logicalTop();\n const height = viewport.clientHeight;\n // Rows measured taller than estimated can grow the window past the cap without any edge moving.\n if (total() > MAX_WINDOW && trimWindow(top + height / 2 > total() / 2 ? \"start\" : \"end\")) {\n restore(true);\n return;\n }\n const margin = Math.max(2_000, 3 * height);\n if (top < margin) {\n if (lo > 0) {\n let added = 0;\n while (lo > 0 && added < WINDOW_STEP) added += sizes[--lo]!;\n dirtyFrom = 0;\n trimWindow(\"end\");\n restore(true);\n return;\n }\n if (props.hasOlder && !loadingOlder() && !newest) load(\"older\");\n }\n if (total() - top - height < margin) {\n if (hi < list.length) {\n let added = 0;\n while (hi < list.length && added < WINDOW_STEP) added += sizes[hi++]!;\n dirtyFrom = 0;\n trimWindow(\"start\");\n restore(true);\n return;\n }\n if (props.hasNewer && !loadingNewer() && !newest) load(\"newer\");\n }\n };\n\n const queueAnnouncement = (added: readonly T[]) => {\n pendingAnnouncement = pendingAnnouncement.concat(added);\n if (announceTimer !== undefined) return;\n announceTimer = setTimeout(() => {\n announceTimer = undefined;\n const batch = pendingAnnouncement;\n pendingAnnouncement = [];\n const text = props.announce ? props.announce(batch) : feedMessages().feedNewItems({ count: batch.length });\n if (!text) return;\n const line = document.createElement(\"p\");\n line.textContent = text;\n log.append(line);\n while (log.childElementCount > 3) log.firstElementChild?.remove();\n }, ANNOUNCE_MS);\n };\n\n /** Applies a new `items` array: appends follow the end, prepends and other changes keep the anchor by key. */\n const sync = (next: readonly T[]) => {\n // The reader may have scrolled in this frame before its scroll event ran; take that position first.\n if (keys.length > 0) noteReader();\n const length = next.length;\n const nextKeys = next.map(props.getKey);\n const previous = keys.length;\n const focusKey = focusIndex >= 0 ? keys[focusIndex] : undefined;\n let added: readonly T[] = [];\n let appended = false;\n /** A new feed, or one that shares no item with the last: start at its end. */\n const reset = () => {\n sizes = Float64Array.from(next, estimate);\n focusIndex = -1;\n appendedFrom = -1;\n setStick(!props.hasNewer);\n anchor = { index: 0, delta: 0 };\n setUnseen(0);\n // Pending announcements describe the items that are gone.\n clearTimeout(announceTimer);\n announceTimer = undefined;\n pendingAnnouncement = [];\n list = next;\n if (sizes.reduce((sum, size) => sum + size, 0) <= MAX_WINDOW) {\n lo = 0;\n hi = length;\n } else windowAround(length - 1);\n };\n if (previous === 0 || length === 0) reset();\n else if (length >= previous && runsMatch(keys, nextKeys, 0)) {\n const grown = new Float64Array(length);\n grown.set(sizes);\n for (let index = previous; index < length; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n if (hi === previous) hi = length;\n appended = true;\n // Away from the end, the reader's scroll in progress still reaches the end it was heading for.\n if (!stick && deferring() && appendedFrom < 0) appendedFrom = previous;\n // Only items after the newest one the feed has known are new; older pages toward the end are history.\n const known = endKey === undefined ? -1 : nextKeys.lastIndexOf(endKey);\n if (known >= 0) added = next.slice(Math.max(previous, known + 1));\n } else if (length >= previous && runsMatch(keys, nextKeys, length - previous)) {\n const shift = length - previous;\n const grown = new Float64Array(length);\n grown.set(sizes, shift);\n for (let index = 0; index < shift; index++) grown[index] = estimate(next[index]!);\n sizes = grown;\n anchor = { index: anchor.index + shift, delta: anchor.delta };\n if (focusIndex >= 0) focusIndex += shift;\n if (appendedFrom >= 0) appendedFrom += shift;\n if (lo > 0) lo += shift;\n hi += shift;\n } else {\n const known = new Map<string, number>();\n for (let index = 0; index < previous; index++) known.set(keys[index]!, sizes[index]!);\n const position = new Map<string, number>();\n for (let index = 0; index < length; index++) position.set(nextKeys[index]!, index);\n if (!nextKeys.some((key) => known.has(key))) reset();\n else {\n sizes = new Float64Array(length);\n for (let index = 0; index < length; index++) sizes[index] = known.get(nextKeys[index]!) ?? estimate(next[index]!);\n // An item that is gone hands its role to the nearest surviving neighbor.\n const survivor = (from: number) => {\n for (let distance = 0; distance < previous; distance++) {\n const below = position.get(keys[from + distance] ?? \"\");\n if (below !== undefined) return below;\n const above = position.get(keys[from - distance] ?? \"\");\n if (above !== undefined) return above;\n }\n return length - 1;\n };\n const wasAtStart = lo === 0;\n const wasAtEnd = hi === previous;\n appendedFrom = -1;\n anchor = { index: survivor(anchor.index), delta: anchor.delta };\n focusIndex = focusKey === undefined ? -1 : (position.get(focusKey) ?? -1);\n lo = wasAtStart ? 0 : survivor(lo);\n hi = wasAtEnd ? length : survivor(hi - 1) + 1;\n if (anchor.index < lo || anchor.index >= hi) {\n list = next;\n windowAround(anchor.index);\n }\n }\n }\n list = next;\n keys = nextKeys;\n dirtyFrom = 0;\n setCount(length);\n setListVersion((value) => value + 1);\n if (!props.hasNewer) endKey = nextKeys[length - 1];\n recompute();\n const center = stick ? hi - 1 : anchor.index;\n const trimmed = total() > MAX_WINDOW && trimWindow(center - lo > hi - 1 - center ? \"start\" : \"end\");\n // Appended items wait for the reader's scroll to end like other size changes; the rows show them meanwhile.\n restore(!appended || trimmed);\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n if (added.length > 0) {\n if (!stick) setUnseen((value) => value + added.length);\n queueAnnouncement(added);\n }\n };\n\n /**\n * Follows the end. With newer items not loaded, `onLoadNewest` replaces the items, after any running load; without\n * it, following the end keeps `onLoadNewer` paging until the newest item arrives or the reader scrolls away.\n */\n const scrollToEnd = () => {\n takeOver();\n setStick(!props.hasNewer || Boolean(props.onLoadNewer || props.onLoadNewest));\n if (props.hasNewer && props.onLoadNewest) loadNewest();\n if (hi < list.length) windowAround(list.length - 1);\n restore(true);\n };\n\n const scrollToKey = (key: string, options: VirtualFeedScrollOptions = {}) => {\n const index = keys.indexOf(key);\n if (index < 0) return false;\n takeOver();\n if (index < lo || index >= hi) windowAround(index);\n recompute();\n const delta = () => (options.align === \"start\" ? 0 : Math.max(0, (viewport.clientHeight - sizes[index]!) / 2));\n setStick(false);\n anchor = { index, delta: delta() };\n restore(true);\n // The row was measured while mounting, before this frame paints; center it on its real height.\n if (anchor.index === index && anchor.delta !== delta()) {\n anchor = { index, delta: delta() };\n restore(true);\n }\n if (reachesEnd(logicalTop())) setStick(true);\n if (options.highlight) {\n clearTimeout(highlightTimer);\n setHighlighted(key);\n highlightTimer = setTimeout(() => setHighlighted(undefined), HIGHLIGHT_MS);\n }\n return true;\n };\n\n const focusRow = (target: number) => {\n if (list.length === 0) return;\n const index = Math.min(list.length - 1, Math.max(0, target));\n // An edge load during the restore may add items synchronously and shift indices; the key keeps the target.\n const key = keys[index]!;\n const outside = index < lo || index >= hi;\n if (outside) windowAround(index);\n recompute();\n focusIndex = index;\n const top = logicalTop();\n const height = viewport.clientHeight;\n const start = offsetOf(index);\n const size = sizes[index]!;\n if (index === list.length - 1 && hi === list.length && !props.hasNewer) setStick(true);\n else if (outside) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start < top) {\n setStick(false);\n anchor = { index, delta: 0 };\n } else if (start + size > top + height) {\n setStick(false);\n anchor = { index, delta: Math.max(0, height - size) };\n restore(true);\n // The row was measured while mounting; align its real bottom before this frame paints.\n if (anchor.index === focusIndex) anchor = { index: focusIndex, delta: Math.max(0, height - sizes[focusIndex]!) };\n }\n restore(true);\n rows.get(key)?.node.focus({ preventScroll: true });\n };\n\n const onKeyDown = (event: KeyboardEvent) => {\n const row = rowOf.get(event.target as Element);\n if (!row) return;\n const index = row.index;\n if (event.key === \"ArrowUp\" || event.key === \"PageUp\") focusRow(index - 1);\n else if (event.key === \"ArrowDown\" || event.key === \"PageDown\") focusRow(index + 1);\n else if (event.key === \"Home\" && event.ctrlKey) focusRow(0);\n else if (event.key === \"End\" && event.ctrlKey) {\n scrollToEnd();\n focusRow(list.length - 1);\n } else return;\n event.preventDefault();\n };\n\n const onScroll = () => {\n // The feed checked its edges when it wrote scrollTop. Its own scroll event arrives a frame later, and checking again\n // then would retry a load that failed in between.\n const reader = noteReader();\n // Near the start, the rows no longer stand in for a held-back correction; it is written now.\n if (deferred !== 0 && !mayDefer(logicalTop())) restore(true);\n else {\n updateRange();\n if (reader) checkEdges();\n }\n };\n\n /**\n * Ends the reader's scroll if the feed stands still for the next two frames. A `scrollend` not counted as a write's\n * can still be the late one of an earlier write; movement after it means the scroll goes on.\n */\n const confirmEnd = () => {\n const seen = lastMove;\n requestAnimationFrame(() =>\n requestAnimationFrame(() => {\n if (disposed || fingers.size > 0 || !scrolling || lastMove !== seen || readerMoved()) return;\n endScroll();\n }),\n );\n };\n\n const onScrollEnd = () => {\n // The scrollend of the feed's own write, not the end of the reader's scroll.\n if (performance.now() < owedUntil) {\n owedUntil = 0;\n return;\n }\n endedAt = performance.now();\n if (fingers.size > 0 || !scrolling) return;\n confirmEnd();\n };\n\n const controller: VirtualFeedController = {\n scrollToKey,\n scrollToEnd,\n isAtEnd: () => stick,\n };\n\n // Created before the first sync below, so items that an edge load adds synchronously during it are not lost.\n createEffect(on(() => props.items, sync, { defer: true }));\n // More items can appear at an edge without new items, for example when a live update reports newer ones.\n createEffect(\n on(\n [() => props.hasOlder, () => props.hasNewer],\n () => {\n if (!props.hasNewer) endKey = keys[keys.length - 1];\n if (hi <= lo) return;\n if (!stick && reachesEnd(logicalTop())) setStick(true);\n // Only newer pages can be followed; with just `onLoadNewest`, \"Jump to latest\" has to show.\n else if (stick && props.hasNewer && !props.onLoadNewer) setStick(false);\n checkEdges();\n },\n { defer: true },\n ),\n );\n\n onMount(() => {\n hasScrollEnd = \"onscrollend\" in window;\n lastHeight = viewport.clientHeight;\n const observer = new ResizeObserver((entries) => {\n observing = true;\n try {\n // A scroll of the reader in this frame counts first, in the geometry from before these changes.\n noteReader();\n fresh = [];\n let resized = false;\n const measured: Array<readonly [HTMLElement, number]> = [];\n for (const entry of entries) {\n if (entry.target === viewport) {\n // A shorter viewport (a growing footer or keyboard) keeps what is at its bottom in place.\n const height = viewport.clientHeight;\n if (!stick) anchor = { index: anchor.index, delta: anchor.delta + height - lastHeight };\n lastHeight = height;\n resized = true;\n } else if (entry.target.isConnected) {\n const row = entry.target as HTMLElement;\n measured.push([row, entry.borderBoxSize?.[0]?.blockSize ?? row.getBoundingClientRect().height]);\n }\n }\n if (measure(measured) || resized) restore();\n } finally {\n observing = false;\n }\n });\n observer.observe(viewport);\n // Rows observed inside the observer's own callback miss its first notification, which raises a window error.\n // They were measured while mounting, so they are observed from the next frame on.\n let later: HTMLElement[] = [];\n let laterFrame = 0;\n observeRow = (row) => {\n if (!observing) return observer.observe(row);\n later.push(row);\n laterFrame ||= requestAnimationFrame(() => {\n laterFrame = 0;\n for (const node of later) if (node.isConnected) observer.observe(node);\n later = [];\n });\n };\n unobserveRow = (row) => observer.unobserve(row);\n const release = () => {\n for (const target of touched) {\n target.removeEventListener(\"touchend\", touchEnd);\n target.removeEventListener(\"touchcancel\", touchEnd);\n }\n touched.clear();\n };\n // Input of the reader ends a takeover by the application at once, and lets the feed scroll for that input.\n const act = () => {\n overriding = false;\n viewport.style.removeProperty(\"overflow-y\");\n };\n const touchStart = (event: TouchEvent) => {\n // A touch whose end the feed missed has left the screen by now.\n const down = new Set(Array.from(event.touches, (touch) => touch.identifier));\n for (const id of fingers) if (!down.has(id)) fingers.delete(id);\n for (const touch of Array.from(event.changedTouches)) fingers.add(touch.identifier);\n act();\n // Touch events stay with the element the touch began on, also when the feed removes its row meanwhile.\n const target = event.target;\n if (target && !touched.has(target)) {\n touched.add(target);\n target.addEventListener(\"touchend\", touchEnd, { passive: true });\n target.addEventListener(\"touchcancel\", touchEnd, { passive: true });\n }\n };\n function touchEnd(event: Event) {\n for (const touch of Array.from((event as TouchEvent).changedTouches)) fingers.delete(touch.identifier);\n if (fingers.size > 0) return;\n release();\n // The last step of a short flick can have moved scrollTop before its scroll event; it counts before anything ends.\n if (!scrolling && !noteReader()) return endScroll();\n armEnd();\n // A scroll that ended under the finger ends now, unless the release starts a momentum.\n if (endedAt >= lastMove) confirmEnd();\n }\n viewport.addEventListener(\"touchstart\", touchStart, { passive: true });\n viewport.addEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.addEventListener(type, act, { passive: true });\n onCleanup(() => {\n disposed = true;\n observer.disconnect();\n cancelAnimationFrame(laterFrame);\n viewport.removeEventListener(\"touchstart\", touchStart);\n viewport.removeEventListener(\"scrollend\", onScrollEnd);\n for (const type of [\"wheel\", \"keydown\", \"pointerdown\"]) viewport.removeEventListener(type, act);\n release();\n clearTimeout(endTimer);\n clearTimeout(announceTimer);\n clearTimeout(highlightTimer);\n for (const row of rows.values()) row.dispose();\n rows.clear();\n });\n sync(props.items);\n props.controller?.(controller);\n });\n\n const shownCount = () => props.newCount ?? unseen();\n\n return (\n <div class={props.class ? `k2b-virtual-feed ${props.class}` : \"k2b-virtual-feed\"}>\n <div ref={viewport} class=\"k2b-virtual-feed__viewport\" tabindex=\"-1\" onScroll={onScroll}>\n <div\n ref={feed}\n class=\"k2b-virtual-feed__feed\"\n role=\"feed\"\n aria-label={props.label}\n aria-busy={props.busy || loadingOlder() || loadingNewer() ? \"true\" : \"false\"}\n onKeyDown={onKeyDown}\n onFocusIn={(event) => {\n const node = (event.target as HTMLElement).closest(\".k2b-virtual-feed__item\");\n const row = node ? rowOf.get(node) : undefined;\n if (row) {\n focusIndex = row.index;\n setTabStop(focusIndex);\n }\n }}\n onFocusOut={(event) => {\n const next = event.relatedTarget as Node | null;\n if (next && !feed.contains(next)) focusIndex = -1;\n }}\n />\n </div>\n <Show when={count() === 0 && props.empty}>\n <div class=\"k2b-virtual-feed__empty\">{props.empty}</div>\n </Show>\n <Show when={loadingOlder()}>\n <div class=\"k2b-virtual-feed__status\" aria-hidden=\"true\">\n <i class=\"ti ti-loader-2 k2b-spin\" />\n {messages().loading}\n </div>\n </Show>\n <Show when={!atEnd() && count() > 0}>\n <button\n type=\"button\"\n class=\"k2b-virtual-feed__end\"\n aria-label={shownCount() > 0 ? feedMessages().feedJumpToLatestCount({ count: shownCount() }) : undefined}\n onClick={() => {\n scrollToEnd();\n // The button disappears at the end; keep focus in the feed instead of the document.\n if (props.hasNewer) viewport.focus({ preventScroll: true });\n else focusRow(list.length - 1);\n }}\n >\n <i class={loadingNewer() ? \"ti ti-loader-2 k2b-spin\" : \"ti ti-arrow-down\"} aria-hidden=\"true\" />\n {feedMessages().feedJumpToLatest}\n <Show when={shownCount() > 0}>\n <span class=\"k2b-virtual-feed__count\" aria-hidden=\"true\">\n {shownCount()}\n </span>\n </Show>\n </button>\n </Show>\n <div ref={log} class=\"k2b-sr-only\" role=\"log\" aria-live=\"polite\" aria-relevant=\"additions\" />\n </div>\n );\n}\n\nexport default VirtualFeed;\n"],"mappings":"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","ignoreList":[]}
@@ -13,8 +13,9 @@ import { createSignal, For, onCleanup, onMount, Show } from "solid-js";
13
13
  import { Button, IconButton } from "../actions/Button";
14
14
  import { dialogCore } from "../feedback/dialog-core";
15
15
  import { DialogHeader } from "../feedback/prompts";
16
+ import { suppressTextSelection } from "../internal/text-selection";
16
17
  import { LocaleProvider, useLocale } from "../intl/locale";
17
- import { useUiMessages } from "../intl/messages";
18
+ import { useViewportMessages } from "./viewport-messages";
18
19
  import { clampZoomPan, panZoomPan, ZOOM_PAN_FIT, ZOOM_PAN_STEP, zoomZoomPanAt } from "./zoom-pan";
19
20
  const PAN_KEY_STEP = 48;
20
21
  const DRAG_THRESHOLD = 4;
@@ -72,7 +73,7 @@ const ActionButton = props => {
72
73
  * stays crisp and is never re-rendered. The view always starts at fit.
73
74
  */
74
75
  export function ZoomPanViewport(props) {
75
- const messages = useUiMessages();
76
+ const viewportMessages = useViewportMessages();
76
77
  const locale = useLocale();
77
78
  const [transform, setTransform] = createSignal(ZOOM_PAN_FIT);
78
79
  const [smooth, setSmooth] = createSignal(false);
@@ -243,6 +244,8 @@ export function ZoomPanViewport(props) {
243
244
  const dx = event.clientX - drag.x;
244
245
  const dy = event.clientY - drag.y;
245
246
  if (!drag.moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;
247
+ // The pointer's own pointerup or pointercancel ends the hold.
248
+ if (!drag.moved) suppressTextSelection(event.pointerId);
246
249
  drag.moved = true;
247
250
  setDragging(true);
248
251
  apply(panZoomPan(drag.origin, dx, dy, geometry()), false);
@@ -296,12 +299,12 @@ export function ZoomPanViewport(props) {
296
299
  return _$ssr(_tmpl$4, `ti ${_$escape(icon, true)}`);
297
300
  }
298
301
  });
299
- return _$ssr(_tmpl$5, `k2b-zoom-pan ${_$escape(props.class ?? "", true)}`, _$ssrStyle(props.style), _$ssrAttribute("aria-label", _$escape(props.label, true), false) + _$ssrAttribute("aria-description", _$escape(messages().zoomPanKeys, true), false), _$ssrAttribute("data-controls", _$escape(props.controls ?? "visible", true), false) + _$ssrAttribute("data-zoomed", zoomed() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-dragging", dragging() ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-smooth", smooth() ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("transform:", `translate(${_$escape(transform().x, true)}px, ${_$escape(transform().y, true)}px) scale(${_$escape(transform().scale, true)})`), _$escape(props.children), _$escape(control(messages().zoomIn, "+", "ti-plus", () => zoomBy(ZOOM_PAN_STEP))), _$escape(control(messages().zoomOut, "-", "ti-minus", () => zoomBy(1 / ZOOM_PAN_STEP))), _$escape(control(messages().resetZoom, "0", "ti-focus-centered", reset)), _$escape(_$createComponent(Show, {
302
+ return _$ssr(_tmpl$5, `k2b-zoom-pan ${_$escape(props.class ?? "", true)}`, _$ssrStyle(props.style), _$ssrAttribute("aria-label", _$escape(props.label, true), false) + _$ssrAttribute("aria-description", _$escape(viewportMessages().zoomPanKeys, true), false), _$ssrAttribute("data-controls", _$escape(props.controls ?? "visible", true), false) + _$ssrAttribute("data-zoomed", zoomed() ? "true" : _$escape(undefined, true), false) + _$ssrAttribute("data-dragging", dragging() ? "true" : _$escape(undefined, true), false), _$ssrAttribute("data-smooth", smooth() ? "true" : _$escape(undefined, true), false), _$ssrStyleProperty("transform:", `translate(${_$escape(transform().x, true)}px, ${_$escape(transform().y, true)}px) scale(${_$escape(transform().scale, true)})`), _$escape(props.children), _$escape(control(viewportMessages().zoomIn, "+", "ti-plus", () => zoomBy(ZOOM_PAN_STEP))), _$escape(control(viewportMessages().zoomOut, "-", "ti-minus", () => zoomBy(1 / ZOOM_PAN_STEP))), _$escape(control(viewportMessages().resetZoom, "0", "ti-focus-centered", reset)), _$escape(_$createComponent(Show, {
300
303
  get when() {
301
304
  return props.fullscreen;
302
305
  },
303
306
  get children() {
304
- return control(messages().openFullscreen, "F", "ti-maximize", openFullscreen);
307
+ return control(viewportMessages().openFullscreen, "F", "ti-maximize", openFullscreen);
305
308
  }
306
309
  })));
307
310
  }
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["content/ZoomPanViewport.tsx"],"sourcesContent":["import { createSignal, For, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Button, IconButton } from \"../actions/Button\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { DialogHeader } from \"../feedback/prompts\";\nimport { LocaleProvider, useLocale } from \"../intl/locale\";\nimport { useUiMessages } from \"../intl/messages\";\nimport {\n clampZoomPan,\n panZoomPan,\n ZOOM_PAN_FIT,\n ZOOM_PAN_STEP,\n type ZoomPanGeometry,\n type ZoomPanTransform,\n zoomZoomPanAt,\n} from \"./zoom-pan\";\n\nexport type ZoomPanAction = {\n label: string;\n icon?: string;\n /** Runs the action; the button shows a pending state until a returned promise settles. Handle failures here. */\n onSelect: () => void | Promise<void>;\n};\n\nexport type ZoomPanFullscreen = {\n /** Heading and accessible name of the fullscreen dialog. */\n title: string;\n /** Renders a fresh copy of the content for the dialog. Called once per opening. */\n content: () => JSX.Element;\n /** Actions shown in the fullscreen dialog, for example exports. */\n actions?: readonly ZoomPanAction[];\n};\n\nexport type ZoomPanViewportProps = {\n /** Accessible name of the focusable viewport. */\n label: string;\n /** The zoomable content. Its first element is measured to keep it on screen. */\n children: JSX.Element;\n /** Enables the fullscreen control and the `F` shortcut. */\n fullscreen?: ZoomPanFullscreen;\n /** `hover` reveals the controls on hover, on focus, and while zoomed in. Touch screens always show them. */\n controls?: \"visible\" | \"hover\";\n class?: string;\n style?: JSX.CSSProperties;\n};\n\nconst PAN_KEY_STEP = 48;\nconst DRAG_THRESHOLD = 4;\nconst PAN_KEYS: Record<string, readonly [number, number]> = {\n ArrowLeft: [PAN_KEY_STEP, 0],\n ArrowRight: [-PAN_KEY_STEP, 0],\n ArrowUp: [0, PAN_KEY_STEP],\n ArrowDown: [0, -PAN_KEY_STEP],\n};\n\n/** Current screen transform of the stage, including a running CSS transition. */\nconst renderedTransform = (stage: HTMLElement, fallback: ZoomPanTransform): ZoomPanTransform => {\n const match = /^matrix\\(([^)]+)\\)$/.exec(getComputedStyle(stage).transform ?? \"\");\n const values = match?.[1]?.split(\",\").map(Number);\n if (!values || values.length !== 6 || values.some((value) => !Number.isFinite(value)) || !values[0]) return fallback;\n return { scale: values[0], x: values[4] ?? 0, y: values[5] ?? 0 };\n};\n\nconst ActionButton = (props: { action: ZoomPanAction }): JSX.Element => {\n const [pending, setPending] = createSignal(false);\n const run = async () => {\n if (pending()) return;\n setPending(true);\n try {\n await props.action.onSelect();\n } catch (error) {\n console.error(\"Zoom-pan action failed\", error);\n } finally {\n setPending(false);\n }\n };\n return (\n <Button variant=\"secondary\" loading={pending()} onClick={() => void run()}>\n <Show when={props.action.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>\n {props.action.label}\n </Button>\n );\n};\n\n/**\n * Makes any content zoomable (fit to 8×) and pannable with buttons, Ctrl/Cmd +\n * wheel, pinch, drag, and keys. It applies a CSS transform, so vector content\n * stays crisp and is never re-rendered. The view always starts at fit.\n */\nexport function ZoomPanViewport(props: ZoomPanViewportProps): JSX.Element {\n const messages = useUiMessages();\n const locale = useLocale();\n const [transform, setTransform] = createSignal<ZoomPanTransform>(ZOOM_PAN_FIT);\n const [smooth, setSmooth] = createSignal(false);\n const [dragging, setDragging] = createSignal(false);\n let root: HTMLDivElement | undefined;\n let stage: HTMLDivElement | undefined;\n const pointers = new Map<number, { x: number; y: number }>();\n let drag: { id: number; x: number; y: number; origin: ZoomPanTransform; moved: boolean } | undefined;\n let pinch: { distance: number; center: { x: number; y: number }; origin: ZoomPanTransform } | undefined;\n let suppressClick = false;\n\n const zoomed = () => transform().scale > 1;\n\n const geometry = (): ZoomPanGeometry => {\n const rect = root?.getBoundingClientRect();\n const width = rect?.width ?? 0;\n const height = rect?.height ?? 0;\n const content = stage?.firstElementChild?.getBoundingClientRect();\n if (!rect || !stage || !content || content.width <= 0 || content.height <= 0) {\n return { width, height, content: { left: 0, top: 0, width, height } };\n }\n const current = renderedTransform(stage, transform());\n return {\n width,\n height,\n content: {\n left: (content.left - rect.left - current.x) / current.scale,\n top: (content.top - rect.top - current.y) / current.scale,\n width: content.width / current.scale,\n height: content.height / current.scale,\n },\n };\n };\n\n const apply = (next: ZoomPanTransform, animate: boolean) => {\n setSmooth(animate);\n setTransform(next);\n };\n\n const local = (event: { clientX: number; clientY: number }) => {\n const rect = root?.getBoundingClientRect();\n return { x: event.clientX - (rect?.left ?? 0), y: event.clientY - (rect?.top ?? 0) };\n };\n\n const zoomBy = (factor: number, point?: { x: number; y: number }, animate = true) => {\n const box = geometry();\n const current = transform();\n apply(zoomZoomPanAt(current, current.scale * factor, point ?? { x: box.width / 2, y: box.height / 2 }, box), animate);\n };\n\n const reset = () => apply(ZOOM_PAN_FIT, true);\n\n const openFullscreen = () => {\n const fullscreen = props.fullscreen;\n if (!fullscreen) return;\n const currentLocale = locale();\n void dialogCore.open<void>(\n (close) => (\n <LocaleProvider locale={currentLocale}>\n <div class=\"k2b-dialog__panel k2b-dialog__stack\">\n <DialogHeader title={fullscreen.title} close={() => close()} />\n <div class=\"k2b-zoom-pan-dialog\">\n <ZoomPanViewport label={props.label}>{fullscreen.content()}</ZoomPanViewport>\n <Show when={fullscreen.actions?.length}>\n <footer class=\"k2b-dialog__actions\">\n <For each={fullscreen.actions}>{(action) => <ActionButton action={action} />}</For>\n </footer>\n </Show>\n </div>\n </div>\n </LocaleProvider>\n ),\n {\n panelClassName: \"k2b-dialog k2b-dialog--full\",\n ariaLabel: fullscreen.title,\n initialFocus: (dialog) => dialog.querySelector<HTMLElement>(\".k2b-zoom-pan\"),\n },\n );\n };\n\n const handleKeyDown: JSX.EventHandler<HTMLDivElement, KeyboardEvent> = (event) => {\n if (event.target !== root || event.ctrlKey || event.metaKey || event.altKey) return;\n const key = event.key;\n if (key === \"+\" || key === \"=\") zoomBy(ZOOM_PAN_STEP);\n else if (key === \"-\" || key === \"_\") zoomBy(1 / ZOOM_PAN_STEP);\n else if (key === \"0\") reset();\n else if ((key === \"f\" || key === \"F\") && props.fullscreen) openFullscreen();\n else {\n const delta = PAN_KEYS[key];\n // At fit the arrow keys keep scrolling the page.\n if (!delta || !zoomed()) return;\n apply(panZoomPan(transform(), delta[0], delta[1], geometry()), true);\n }\n event.preventDefault();\n };\n\n // Plain wheel keeps scrolling the page; Ctrl/Cmd + wheel (and trackpad pinch) zooms toward the pointer.\n const handleWheel: JSX.EventHandler<HTMLDivElement, WheelEvent> = (event) => {\n if (!event.ctrlKey && !event.metaKey) return;\n event.preventDefault();\n const lines = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? 400 : 1;\n const delta = Math.max(-50, Math.min(50, event.deltaY * lines));\n zoomBy(Math.exp(-delta / 100), local(event), false);\n };\n\n const handlePointerDown: JSX.EventHandler<HTMLDivElement, PointerEvent> = (event) => {\n if (event.button !== 0 || (event.target as Element).closest(\"button, a, input, select, textarea\")) return;\n pointers.set(event.pointerId, local(event));\n if (pointers.size === 2) {\n const [first, second] = [...pointers.values()] as [{ x: number; y: number }, { x: number; y: number }];\n pinch = {\n distance: Math.max(1, Math.hypot(second.x - first.x, second.y - first.y)),\n center: { x: (first.x + second.x) / 2, y: (first.y + second.y) / 2 },\n origin: transform(),\n };\n drag = undefined;\n } else if (pointers.size === 1 && zoomed()) {\n // Panning starts only above fit, so clicks and text selection keep working at fit.\n drag = { id: event.pointerId, x: event.clientX, y: event.clientY, origin: transform(), moved: false };\n } else return;\n try {\n event.currentTarget.setPointerCapture(event.pointerId);\n } catch {\n // A synthetic or already released pointer cannot be captured; moves still arrive while inside.\n }\n };\n\n const handlePointerMove: JSX.EventHandler<HTMLDivElement, PointerEvent> = (event) => {\n if (!pointers.has(event.pointerId)) return;\n pointers.set(event.pointerId, local(event));\n if (pinch && pointers.size >= 2) {\n const [first, second] = [...pointers.values()] as [{ x: number; y: number }, { x: number; y: number }];\n const distance = Math.hypot(second.x - first.x, second.y - first.y);\n const center = { x: (first.x + second.x) / 2, y: (first.y + second.y) / 2 };\n const box = geometry();\n const scaled = zoomZoomPanAt(pinch.origin, pinch.origin.scale * (distance / pinch.distance), pinch.center, box);\n apply(panZoomPan(scaled, center.x - pinch.center.x, center.y - pinch.center.y, box), false);\n return;\n }\n if (drag?.id !== event.pointerId) return;\n const dx = event.clientX - drag.x;\n const dy = event.clientY - drag.y;\n if (!drag.moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;\n drag.moved = true;\n setDragging(true);\n apply(panZoomPan(drag.origin, dx, dy, geometry()), false);\n };\n\n const handlePointerEnd: JSX.EventHandler<HTMLDivElement, PointerEvent> = (event) => {\n pointers.delete(event.pointerId);\n if (pointers.size < 2) pinch = undefined;\n if (drag?.id !== event.pointerId) return;\n if (drag.moved) {\n // The click that follows this pointerup (if the browser sends one) comes in the same task.\n suppressClick = true;\n setTimeout(() => {\n suppressClick = false;\n });\n }\n drag = undefined;\n setDragging(false);\n };\n\n onMount(() => {\n const element = root;\n if (!element) return;\n // A drag must not also count as a click on the content or its owner.\n const click = (event: MouseEvent) => {\n if (!suppressClick) return;\n suppressClick = false;\n event.preventDefault();\n event.stopPropagation();\n };\n // Keep a two-finger gesture for pinch zoom instead of page panning.\n const touchMove = (event: TouchEvent) => {\n if (event.touches.length > 1) event.preventDefault();\n };\n element.addEventListener(\"click\", click, true);\n element.addEventListener(\"touchmove\", touchMove, { passive: false });\n const observer =\n typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(() => apply(clampZoomPan(transform(), geometry()), false));\n observer?.observe(element);\n onCleanup(() => {\n element.removeEventListener(\"click\", click, true);\n element.removeEventListener(\"touchmove\", touchMove);\n observer?.disconnect();\n });\n });\n\n const control = (label: string, shortcut: string, icon: string, action: () => void) => (\n <IconButton variant=\"secondary\" label={label} tooltip={`${label} (${shortcut})`} onClick={action}>\n <i class={`ti ${icon}`} aria-hidden=\"true\" />\n </IconButton>\n );\n\n return (\n <div\n ref={root}\n class={`k2b-zoom-pan ${props.class ?? \"\"}`}\n style={props.style}\n role=\"group\"\n aria-label={props.label}\n aria-description={messages().zoomPanKeys}\n tabIndex={0}\n data-controls={props.controls ?? \"visible\"}\n data-zoomed={zoomed() ? \"true\" : undefined}\n data-dragging={dragging() ? \"true\" : undefined}\n onKeyDown={handleKeyDown}\n onWheel={handleWheel}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerEnd}\n onPointerCancel={handlePointerEnd}\n >\n <div\n ref={stage}\n class=\"k2b-zoom-pan__stage\"\n data-smooth={smooth() ? \"true\" : undefined}\n style={{ transform: `translate(${transform().x}px, ${transform().y}px) scale(${transform().scale})` }}\n >\n {props.children}\n </div>\n <div class=\"k2b-zoom-pan__controls\">\n {control(messages().zoomIn, \"+\", \"ti-plus\", () => zoomBy(ZOOM_PAN_STEP))}\n {control(messages().zoomOut, \"-\", \"ti-minus\", () => zoomBy(1 / ZOOM_PAN_STEP))}\n {control(messages().resetZoom, \"0\", \"ti-focus-centered\", reset)}\n <Show when={props.fullscreen}>{control(messages().openFullscreen, \"F\", \"ti-maximize\", openFullscreen)}</Show>\n </div>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["content/ZoomPanViewport.tsx"],"sourcesContent":["import { createSignal, For, type JSX, onCleanup, onMount, Show } from \"solid-js\";\nimport { Button, IconButton } from \"../actions/Button\";\nimport { dialogCore } from \"../feedback/dialog-core\";\nimport { DialogHeader } from \"../feedback/prompts\";\nimport { suppressTextSelection } from \"../internal/text-selection\";\nimport { LocaleProvider, useLocale } from \"../intl/locale\";\nimport { useViewportMessages } from \"./viewport-messages\";\n\nimport {\n clampZoomPan,\n panZoomPan,\n ZOOM_PAN_FIT,\n ZOOM_PAN_STEP,\n type ZoomPanGeometry,\n type ZoomPanTransform,\n zoomZoomPanAt,\n} from \"./zoom-pan\";\n\nexport type ZoomPanAction = {\n label: string;\n icon?: string;\n /** Runs the action; the button shows a pending state until a returned promise settles. Handle failures here. */\n onSelect: () => void | Promise<void>;\n};\n\nexport type ZoomPanFullscreen = {\n /** Heading and accessible name of the fullscreen dialog. */\n title: string;\n /** Renders a fresh copy of the content for the dialog. Called once per opening. */\n content: () => JSX.Element;\n /** Actions shown in the fullscreen dialog, for example exports. */\n actions?: readonly ZoomPanAction[];\n};\n\nexport type ZoomPanViewportProps = {\n /** Accessible name of the focusable viewport. */\n label: string;\n /** The zoomable content. Its first element is measured to keep it on screen. */\n children: JSX.Element;\n /** Enables the fullscreen control and the `F` shortcut. */\n fullscreen?: ZoomPanFullscreen;\n /** `hover` reveals the controls on hover, on focus, and while zoomed in. Touch screens always show them. */\n controls?: \"visible\" | \"hover\";\n class?: string;\n style?: JSX.CSSProperties;\n};\n\nconst PAN_KEY_STEP = 48;\nconst DRAG_THRESHOLD = 4;\nconst PAN_KEYS: Record<string, readonly [number, number]> = {\n ArrowLeft: [PAN_KEY_STEP, 0],\n ArrowRight: [-PAN_KEY_STEP, 0],\n ArrowUp: [0, PAN_KEY_STEP],\n ArrowDown: [0, -PAN_KEY_STEP],\n};\n\n/** Current screen transform of the stage, including a running CSS transition. */\nconst renderedTransform = (stage: HTMLElement, fallback: ZoomPanTransform): ZoomPanTransform => {\n const match = /^matrix\\(([^)]+)\\)$/.exec(getComputedStyle(stage).transform ?? \"\");\n const values = match?.[1]?.split(\",\").map(Number);\n if (!values || values.length !== 6 || values.some((value) => !Number.isFinite(value)) || !values[0]) return fallback;\n return { scale: values[0], x: values[4] ?? 0, y: values[5] ?? 0 };\n};\n\nconst ActionButton = (props: { action: ZoomPanAction }): JSX.Element => {\n const [pending, setPending] = createSignal(false);\n const run = async () => {\n if (pending()) return;\n setPending(true);\n try {\n await props.action.onSelect();\n } catch (error) {\n console.error(\"Zoom-pan action failed\", error);\n } finally {\n setPending(false);\n }\n };\n return (\n <Button variant=\"secondary\" loading={pending()} onClick={() => void run()}>\n <Show when={props.action.icon}>{(icon) => <i class={icon()} aria-hidden=\"true\" />}</Show>\n {props.action.label}\n </Button>\n );\n};\n\n/**\n * Makes any content zoomable (fit to 8×) and pannable with buttons, Ctrl/Cmd +\n * wheel, pinch, drag, and keys. It applies a CSS transform, so vector content\n * stays crisp and is never re-rendered. The view always starts at fit.\n */\nexport function ZoomPanViewport(props: ZoomPanViewportProps): JSX.Element {\n const viewportMessages = useViewportMessages();\n const locale = useLocale();\n const [transform, setTransform] = createSignal<ZoomPanTransform>(ZOOM_PAN_FIT);\n const [smooth, setSmooth] = createSignal(false);\n const [dragging, setDragging] = createSignal(false);\n let root: HTMLDivElement | undefined;\n let stage: HTMLDivElement | undefined;\n const pointers = new Map<number, { x: number; y: number }>();\n let drag: { id: number; x: number; y: number; origin: ZoomPanTransform; moved: boolean } | undefined;\n let pinch: { distance: number; center: { x: number; y: number }; origin: ZoomPanTransform } | undefined;\n let suppressClick = false;\n\n const zoomed = () => transform().scale > 1;\n\n const geometry = (): ZoomPanGeometry => {\n const rect = root?.getBoundingClientRect();\n const width = rect?.width ?? 0;\n const height = rect?.height ?? 0;\n const content = stage?.firstElementChild?.getBoundingClientRect();\n if (!rect || !stage || !content || content.width <= 0 || content.height <= 0) {\n return { width, height, content: { left: 0, top: 0, width, height } };\n }\n const current = renderedTransform(stage, transform());\n return {\n width,\n height,\n content: {\n left: (content.left - rect.left - current.x) / current.scale,\n top: (content.top - rect.top - current.y) / current.scale,\n width: content.width / current.scale,\n height: content.height / current.scale,\n },\n };\n };\n\n const apply = (next: ZoomPanTransform, animate: boolean) => {\n setSmooth(animate);\n setTransform(next);\n };\n\n const local = (event: { clientX: number; clientY: number }) => {\n const rect = root?.getBoundingClientRect();\n return { x: event.clientX - (rect?.left ?? 0), y: event.clientY - (rect?.top ?? 0) };\n };\n\n const zoomBy = (factor: number, point?: { x: number; y: number }, animate = true) => {\n const box = geometry();\n const current = transform();\n apply(zoomZoomPanAt(current, current.scale * factor, point ?? { x: box.width / 2, y: box.height / 2 }, box), animate);\n };\n\n const reset = () => apply(ZOOM_PAN_FIT, true);\n\n const openFullscreen = () => {\n const fullscreen = props.fullscreen;\n if (!fullscreen) return;\n const currentLocale = locale();\n void dialogCore.open<void>(\n (close) => (\n <LocaleProvider locale={currentLocale}>\n <div class=\"k2b-dialog__panel k2b-dialog__stack\">\n <DialogHeader title={fullscreen.title} close={() => close()} />\n <div class=\"k2b-zoom-pan-dialog\">\n <ZoomPanViewport label={props.label}>{fullscreen.content()}</ZoomPanViewport>\n <Show when={fullscreen.actions?.length}>\n <footer class=\"k2b-dialog__actions\">\n <For each={fullscreen.actions}>{(action) => <ActionButton action={action} />}</For>\n </footer>\n </Show>\n </div>\n </div>\n </LocaleProvider>\n ),\n {\n panelClassName: \"k2b-dialog k2b-dialog--full\",\n ariaLabel: fullscreen.title,\n initialFocus: (dialog) => dialog.querySelector<HTMLElement>(\".k2b-zoom-pan\"),\n },\n );\n };\n\n const handleKeyDown: JSX.EventHandler<HTMLDivElement, KeyboardEvent> = (event) => {\n if (event.target !== root || event.ctrlKey || event.metaKey || event.altKey) return;\n const key = event.key;\n if (key === \"+\" || key === \"=\") zoomBy(ZOOM_PAN_STEP);\n else if (key === \"-\" || key === \"_\") zoomBy(1 / ZOOM_PAN_STEP);\n else if (key === \"0\") reset();\n else if ((key === \"f\" || key === \"F\") && props.fullscreen) openFullscreen();\n else {\n const delta = PAN_KEYS[key];\n // At fit the arrow keys keep scrolling the page.\n if (!delta || !zoomed()) return;\n apply(panZoomPan(transform(), delta[0], delta[1], geometry()), true);\n }\n event.preventDefault();\n };\n\n // Plain wheel keeps scrolling the page; Ctrl/Cmd + wheel (and trackpad pinch) zooms toward the pointer.\n const handleWheel: JSX.EventHandler<HTMLDivElement, WheelEvent> = (event) => {\n if (!event.ctrlKey && !event.metaKey) return;\n event.preventDefault();\n const lines = event.deltaMode === 1 ? 16 : event.deltaMode === 2 ? 400 : 1;\n const delta = Math.max(-50, Math.min(50, event.deltaY * lines));\n zoomBy(Math.exp(-delta / 100), local(event), false);\n };\n\n const handlePointerDown: JSX.EventHandler<HTMLDivElement, PointerEvent> = (event) => {\n if (event.button !== 0 || (event.target as Element).closest(\"button, a, input, select, textarea\")) return;\n pointers.set(event.pointerId, local(event));\n if (pointers.size === 2) {\n const [first, second] = [...pointers.values()] as [{ x: number; y: number }, { x: number; y: number }];\n pinch = {\n distance: Math.max(1, Math.hypot(second.x - first.x, second.y - first.y)),\n center: { x: (first.x + second.x) / 2, y: (first.y + second.y) / 2 },\n origin: transform(),\n };\n drag = undefined;\n } else if (pointers.size === 1 && zoomed()) {\n // Panning starts only above fit, so clicks and text selection keep working at fit.\n drag = { id: event.pointerId, x: event.clientX, y: event.clientY, origin: transform(), moved: false };\n } else return;\n try {\n event.currentTarget.setPointerCapture(event.pointerId);\n } catch {\n // A synthetic or already released pointer cannot be captured; moves still arrive while inside.\n }\n };\n\n const handlePointerMove: JSX.EventHandler<HTMLDivElement, PointerEvent> = (event) => {\n if (!pointers.has(event.pointerId)) return;\n pointers.set(event.pointerId, local(event));\n if (pinch && pointers.size >= 2) {\n const [first, second] = [...pointers.values()] as [{ x: number; y: number }, { x: number; y: number }];\n const distance = Math.hypot(second.x - first.x, second.y - first.y);\n const center = { x: (first.x + second.x) / 2, y: (first.y + second.y) / 2 };\n const box = geometry();\n const scaled = zoomZoomPanAt(pinch.origin, pinch.origin.scale * (distance / pinch.distance), pinch.center, box);\n apply(panZoomPan(scaled, center.x - pinch.center.x, center.y - pinch.center.y, box), false);\n return;\n }\n if (drag?.id !== event.pointerId) return;\n const dx = event.clientX - drag.x;\n const dy = event.clientY - drag.y;\n if (!drag.moved && Math.hypot(dx, dy) < DRAG_THRESHOLD) return;\n // The pointer's own pointerup or pointercancel ends the hold.\n if (!drag.moved) suppressTextSelection(event.pointerId);\n drag.moved = true;\n setDragging(true);\n apply(panZoomPan(drag.origin, dx, dy, geometry()), false);\n };\n\n const handlePointerEnd: JSX.EventHandler<HTMLDivElement, PointerEvent> = (event) => {\n pointers.delete(event.pointerId);\n if (pointers.size < 2) pinch = undefined;\n if (drag?.id !== event.pointerId) return;\n if (drag.moved) {\n // The click that follows this pointerup (if the browser sends one) comes in the same task.\n suppressClick = true;\n setTimeout(() => {\n suppressClick = false;\n });\n }\n drag = undefined;\n setDragging(false);\n };\n\n onMount(() => {\n const element = root;\n if (!element) return;\n // A drag must not also count as a click on the content or its owner.\n const click = (event: MouseEvent) => {\n if (!suppressClick) return;\n suppressClick = false;\n event.preventDefault();\n event.stopPropagation();\n };\n // Keep a two-finger gesture for pinch zoom instead of page panning.\n const touchMove = (event: TouchEvent) => {\n if (event.touches.length > 1) event.preventDefault();\n };\n element.addEventListener(\"click\", click, true);\n element.addEventListener(\"touchmove\", touchMove, { passive: false });\n const observer =\n typeof ResizeObserver === \"undefined\" ? undefined : new ResizeObserver(() => apply(clampZoomPan(transform(), geometry()), false));\n observer?.observe(element);\n onCleanup(() => {\n element.removeEventListener(\"click\", click, true);\n element.removeEventListener(\"touchmove\", touchMove);\n observer?.disconnect();\n });\n });\n\n const control = (label: string, shortcut: string, icon: string, action: () => void) => (\n <IconButton variant=\"secondary\" label={label} tooltip={`${label} (${shortcut})`} onClick={action}>\n <i class={`ti ${icon}`} aria-hidden=\"true\" />\n </IconButton>\n );\n\n return (\n <div\n ref={root}\n class={`k2b-zoom-pan ${props.class ?? \"\"}`}\n style={props.style}\n role=\"group\"\n aria-label={props.label}\n aria-description={viewportMessages().zoomPanKeys}\n tabIndex={0}\n data-controls={props.controls ?? \"visible\"}\n data-zoomed={zoomed() ? \"true\" : undefined}\n data-dragging={dragging() ? \"true\" : undefined}\n onKeyDown={handleKeyDown}\n onWheel={handleWheel}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerEnd}\n onPointerCancel={handlePointerEnd}\n >\n <div\n ref={stage}\n class=\"k2b-zoom-pan__stage\"\n data-smooth={smooth() ? \"true\" : undefined}\n style={{ transform: `translate(${transform().x}px, ${transform().y}px) scale(${transform().scale})` }}\n >\n {props.children}\n </div>\n <div class=\"k2b-zoom-pan__controls\">\n {control(viewportMessages().zoomIn, \"+\", \"ti-plus\", () => zoomBy(ZOOM_PAN_STEP))}\n {control(viewportMessages().zoomOut, \"-\", \"ti-minus\", () => zoomBy(1 / ZOOM_PAN_STEP))}\n {control(viewportMessages().resetZoom, \"0\", \"ti-focus-centered\", reset)}\n <Show when={props.fullscreen}>{control(viewportMessages().openFullscreen, \"F\", \"ti-maximize\", openFullscreen)}</Show>\n </div>\n </div>\n );\n}\n"],"mappings":"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","ignoreList":[]}