@jimka/typescript-ui 0.4.1 → 0.6.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 (292) hide show
  1. package/dist/lib/{AbstractInput-BxfrmD2W.js → AbstractInput-sRNPzWel.js} +2 -2
  2. package/dist/lib/{AbstractInput-BxfrmD2W.js.map → AbstractInput-sRNPzWel.js.map} +1 -1
  3. package/dist/lib/Anchor-CwRhdP2J.js +2 -0
  4. package/dist/lib/Anchor-CwRhdP2J.js.map +1 -0
  5. package/dist/lib/AnchorConstraints-Bfkt8019.js +2 -0
  6. package/dist/lib/AnchorConstraints-Bfkt8019.js.map +1 -0
  7. package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js +2 -0
  8. package/dist/lib/AnimatedDropdown-H3Rh-YMZ.js.map +1 -0
  9. package/dist/lib/Border-0DJFDiij.js +2 -0
  10. package/dist/lib/Border-0DJFDiij.js.map +1 -0
  11. package/dist/lib/Button-MpMIYBYJ.js +2 -0
  12. package/dist/lib/Button-MpMIYBYJ.js.map +1 -0
  13. package/dist/lib/{Card-a4dzYrbX.js → Card-QYo27r5b.js} +2 -2
  14. package/dist/lib/{Card-a4dzYrbX.js.map → Card-QYo27r5b.js.map} +1 -1
  15. package/dist/lib/Checkbox-D0JYK-wc.js +2 -0
  16. package/dist/lib/Checkbox-D0JYK-wc.js.map +1 -0
  17. package/dist/lib/CheckboxMenuRow-CesLhSnp.js +2 -0
  18. package/dist/lib/CheckboxMenuRow-CesLhSnp.js.map +1 -0
  19. package/dist/lib/CodeEditor-N1FQodcF.js +2 -0
  20. package/dist/lib/CodeEditor-N1FQodcF.js.map +1 -0
  21. package/dist/lib/ComboBox-Dx8Tk9yg.js +2 -0
  22. package/dist/lib/ComboBox-Dx8Tk9yg.js.map +1 -0
  23. package/dist/lib/Component-B0ShfPVi.js +2 -0
  24. package/dist/lib/Component-B0ShfPVi.js.map +1 -0
  25. package/dist/lib/Container-abY5Ww3W.js +2 -0
  26. package/dist/lib/{Container-0bsG2Q8Z.js.map → Container-abY5Ww3W.js.map} +1 -1
  27. package/dist/lib/DOM-C-Edb3tA.js +2 -0
  28. package/dist/lib/DOM-C-Edb3tA.js.map +1 -0
  29. package/dist/lib/Dialog-cbA9V17e.js +2 -0
  30. package/dist/lib/Dialog-cbA9V17e.js.map +1 -0
  31. package/dist/lib/{FieldDecorator-Bpx8J8n9.js → FieldDecorator-BlYMfZ9L.js} +2 -2
  32. package/dist/lib/{FieldDecorator-Bpx8J8n9.js.map → FieldDecorator-BlYMfZ9L.js.map} +1 -1
  33. package/dist/lib/{Fit-CL1m1nIZ.js → Fit-BhlB-HAo.js} +2 -2
  34. package/dist/lib/{Fit-CL1m1nIZ.js.map → Fit-BhlB-HAo.js.map} +1 -1
  35. package/dist/lib/FloatingPanel-DkJXsZ2D.js +2 -0
  36. package/dist/lib/FloatingPanel-DkJXsZ2D.js.map +1 -0
  37. package/dist/lib/{Glyph-wN7bk7mg.js → Glyph-_VeBacS2.js} +2 -2
  38. package/dist/lib/{Glyph-wN7bk7mg.js.map → Glyph-_VeBacS2.js.map} +1 -1
  39. package/dist/lib/{Grid-DHHmaB-Y.js → Grid-Daiz7F5d.js} +2 -2
  40. package/dist/lib/Grid-Daiz7F5d.js.map +1 -0
  41. package/dist/lib/GridConstraints-C58LuTqM.js +2 -0
  42. package/dist/lib/{GridConstraints-DVc1BmlP.js.map → GridConstraints-C58LuTqM.js.map} +1 -1
  43. package/dist/lib/{Header-2hKwQo_u.js → Header-Dql3Zxc6.js} +2 -2
  44. package/dist/lib/{Header-2hKwQo_u.js.map → Header-Dql3Zxc6.js.map} +1 -1
  45. package/dist/lib/{IconText-DC7Xe34b.js → IconText-PUjhTLlp.js} +2 -2
  46. package/dist/lib/{IconText-DC7Xe34b.js.map → IconText-PUjhTLlp.js.map} +1 -1
  47. package/dist/lib/LanguageRegistry-CcVnbKuh.js +2 -0
  48. package/dist/lib/LanguageRegistry-CcVnbKuh.js.map +1 -0
  49. package/dist/lib/LayoutSerialization-CMxunLfV.js +2 -0
  50. package/dist/lib/LayoutSerialization-CMxunLfV.js.map +1 -0
  51. package/dist/lib/List-nx8220Fi.js +2 -0
  52. package/dist/lib/{List-CG4NvwuV.js.map → List-nx8220Fi.js.map} +1 -1
  53. package/dist/lib/MemoryStore-DhPoU-7X.js +2 -0
  54. package/dist/lib/MemoryStore-DhPoU-7X.js.map +1 -0
  55. package/dist/lib/Menu-Q0bpXXze.js +2 -0
  56. package/dist/lib/Menu-Q0bpXXze.js.map +1 -0
  57. package/dist/lib/{MenuButton-wy_0RskC.js → MenuButton-DCXi0tsP.js} +2 -2
  58. package/dist/lib/{MenuButton-wy_0RskC.js.map → MenuButton-DCXi0tsP.js.map} +1 -1
  59. package/dist/lib/OverlayFade-3pof2AJH.js +2 -0
  60. package/dist/lib/OverlayFade-3pof2AJH.js.map +1 -0
  61. package/dist/lib/Panel-Cy1pdlWO.js +2 -0
  62. package/dist/lib/{Panel-Rd9zkNXx.js.map → Panel-Cy1pdlWO.js.map} +1 -1
  63. package/dist/lib/{Position-Ck_KD4cR.js → Position-BwtxouxK.js} +2 -2
  64. package/dist/lib/{Position-Ck_KD4cR.js.map → Position-BwtxouxK.js.map} +1 -1
  65. package/dist/lib/{ProgressSpinner-yt-VXyCb.js → ProgressSpinner-DK8xEQ9y.js} +2 -2
  66. package/dist/lib/{ProgressSpinner-yt-VXyCb.js.map → ProgressSpinner-DK8xEQ9y.js.map} +1 -1
  67. package/dist/lib/RadioButton-BEwpqg1k.js +2 -0
  68. package/dist/lib/RadioButton-BEwpqg1k.js.map +1 -0
  69. package/dist/lib/RadioMenuRow-DP5qPyFR.js +2 -0
  70. package/dist/lib/RadioMenuRow-DP5qPyFR.js.map +1 -0
  71. package/dist/lib/{RovingTabIndex-DFJyoveq.js → RovingTabIndex-pHEv5oLD.js} +2 -2
  72. package/dist/lib/{RovingTabIndex-DFJyoveq.js.map → RovingTabIndex-pHEv5oLD.js.map} +1 -1
  73. package/dist/lib/Scrollbar-t8fFrUVQ.js +2 -0
  74. package/dist/lib/Scrollbar-t8fFrUVQ.js.map +1 -0
  75. package/dist/lib/Slider-CTbwR6HR.js +2 -0
  76. package/dist/lib/Slider-CTbwR6HR.js.map +1 -0
  77. package/dist/lib/{Spacer-qalSEJ5i.js → Spacer-srdN2d2b.js} +2 -2
  78. package/dist/lib/{Spacer-qalSEJ5i.js.map → Spacer-srdN2d2b.js.map} +1 -1
  79. package/dist/lib/TabButton-DLoMQzky.js +2 -0
  80. package/dist/lib/TabButton-DLoMQzky.js.map +1 -0
  81. package/dist/lib/TabCloseButton-CY7BGitY.js +2 -0
  82. package/dist/lib/TabCloseButton-CY7BGitY.js.map +1 -0
  83. package/dist/lib/Text-CMKnK9uB.js +2 -0
  84. package/dist/lib/Text-CMKnK9uB.js.map +1 -0
  85. package/dist/lib/{Tooltip-Dro4DOZs.js → Tooltip-CUOJOqQi.js} +3 -3
  86. package/dist/lib/Tooltip-CUOJOqQi.js.map +1 -0
  87. package/dist/lib/Tree-C64JNPWJ.js +2 -0
  88. package/dist/lib/Tree-C64JNPWJ.js.map +1 -0
  89. package/dist/lib/VBox-DfJPWXqc.js +2 -0
  90. package/dist/lib/VBox-DfJPWXqc.js.map +1 -0
  91. package/dist/lib/{Validator-Du8PqS5i.js → Validator-Cjs1EU5Q.js} +2 -2
  92. package/dist/lib/{Validator-Du8PqS5i.js.map → Validator-Cjs1EU5Q.js.map} +1 -1
  93. package/dist/lib/VirtualScroller-DTIn19o1.js +2 -0
  94. package/dist/lib/VirtualScroller-DTIn19o1.js.map +1 -0
  95. package/dist/lib/assets/StoreWorker-B5NwRM2I.js +2 -0
  96. package/dist/lib/assets/StoreWorker-B5NwRM2I.js.map +1 -0
  97. package/dist/lib/component/button.es.js +1 -1
  98. package/dist/lib/component/button.es.js.map +1 -1
  99. package/dist/lib/component/chart.es.js +1 -1
  100. package/dist/lib/component/chart.es.js.map +1 -1
  101. package/dist/lib/component/container.es.js +1 -1
  102. package/dist/lib/component/container.es.js.map +1 -1
  103. package/dist/lib/component/diagram.es.js +1 -1
  104. package/dist/lib/component/diagram.es.js.map +1 -1
  105. package/dist/lib/component/display.es.js +1 -1
  106. package/dist/lib/component/display.es.js.map +1 -1
  107. package/dist/lib/component/editor.es.js +3 -3
  108. package/dist/lib/component/editor.es.js.map +1 -1
  109. package/dist/lib/component/input.es.js +1 -1
  110. package/dist/lib/component/input.es.js.map +1 -1
  111. package/dist/lib/component/list.es.js +1 -1
  112. package/dist/lib/component/list.es.js.map +1 -1
  113. package/dist/lib/component/menubar.es.js +1 -1
  114. package/dist/lib/component/menubar.es.js.map +1 -1
  115. package/dist/lib/component/table.es.js +6 -3
  116. package/dist/lib/component/table.es.js.map +1 -1
  117. package/dist/lib/component/tree.es.js +1 -1
  118. package/dist/lib/component/tree.es.js.map +1 -1
  119. package/dist/lib/core.es.js +1 -1
  120. package/dist/lib/core.es.js.map +1 -1
  121. package/dist/lib/data.es.js +1 -1
  122. package/dist/lib/glyphs/solid/index.es.js +1 -1
  123. package/dist/lib/languages-Dl8qdL8a.js +2 -0
  124. package/dist/lib/languages-Dl8qdL8a.js.map +1 -0
  125. package/dist/lib/layout.es.js +1 -1
  126. package/dist/lib/layout.es.js.map +1 -1
  127. package/dist/lib/overlay.es.js +1 -1
  128. package/dist/lib/overlay.es.js.map +1 -1
  129. package/dist/lib/primitive.es.js +1 -1
  130. package/dist/lib/router.es.js +1 -1
  131. package/dist/lib/router.es.js.map +1 -1
  132. package/dist/lib/selectionsEqual-gMG7gCVI.js +2 -0
  133. package/dist/lib/selectionsEqual-gMG7gCVI.js.map +1 -0
  134. package/dist/lib/types/component/button/Button.d.ts +13 -0
  135. package/dist/lib/types/component/button/MenuButton.d.ts +1 -0
  136. package/dist/lib/types/component/button/PopupButton.d.ts +22 -0
  137. package/dist/lib/types/component/button/TabButton.d.ts +5 -1
  138. package/dist/lib/types/component/button/ToggleButton.d.ts +1 -1
  139. package/dist/lib/types/component/button/index.d.ts +2 -0
  140. package/dist/lib/types/component/chart/ChartLegend.d.ts +1 -1
  141. package/dist/lib/types/component/container/CheckboxMenuRow.d.ts +33 -0
  142. package/dist/lib/types/component/container/CollapseButton.d.ts +11 -3
  143. package/dist/lib/types/component/container/FloatingPanel.d.ts +23 -0
  144. package/dist/lib/types/component/container/MenuItem.d.ts +15 -5
  145. package/dist/lib/types/component/container/MenuRow.d.ts +24 -0
  146. package/dist/lib/types/component/container/MenuSeparator.d.ts +4 -2
  147. package/dist/lib/types/component/container/RadioMenuRow.d.ts +33 -0
  148. package/dist/lib/types/component/container/ScrollStrip.d.ts +1 -1
  149. package/dist/lib/types/component/container/Scrollbar.d.ts +6 -3
  150. package/dist/lib/types/component/container/SplitGutter.d.ts +7 -2
  151. package/dist/lib/types/component/container/TabBar.d.ts +3 -1
  152. package/dist/lib/types/component/container/WindowBorder.d.ts +1 -1
  153. package/dist/lib/types/component/container/index.d.ts +8 -1
  154. package/dist/lib/types/component/diagram/DiagramGroupNode.d.ts +1 -1
  155. package/dist/lib/types/component/display/Markdown.d.ts +42 -1
  156. package/dist/lib/types/component/display/MarkdownMinimap.d.ts +38 -0
  157. package/dist/lib/types/component/display/MarkdownViewer.d.ts +60 -0
  158. package/dist/lib/types/component/display/WebGLCanvas.d.ts +1 -0
  159. package/dist/lib/types/component/display/index.d.ts +6 -0
  160. package/dist/lib/types/component/editor/CodeEditor.d.ts +13 -0
  161. package/dist/lib/types/component/editor/index.d.ts +1 -1
  162. package/dist/lib/types/component/input/AbstractCalendarDropdown.d.ts +2 -0
  163. package/dist/lib/types/component/input/AbstractPickerField.d.ts +3 -2
  164. package/dist/lib/types/component/input/Checkbox.d.ts +1 -1
  165. package/dist/lib/types/component/input/RadioButton.d.ts +1 -1
  166. package/dist/lib/types/component/input/Slider.d.ts +1 -1
  167. package/dist/lib/types/component/input/Text.d.ts +0 -2
  168. package/dist/lib/types/component/input/Toggle.d.ts +1 -1
  169. package/dist/lib/types/component/list/AbstractSelectableList.d.ts +1 -1
  170. package/dist/lib/types/component/list/MultiSelectList.d.ts +2 -1
  171. package/dist/lib/types/component/menubar/MenuBar.d.ts +1 -1
  172. package/dist/lib/types/component/menubar/ToolBar.d.ts +1 -0
  173. package/dist/lib/types/component/shared/VirtualRowView.d.ts +2 -0
  174. package/dist/lib/types/component/table/Body.d.ts +23 -1
  175. package/dist/lib/types/component/table/Column.d.ts +3 -1
  176. package/dist/lib/types/component/table/ColumnConfig.d.ts +2 -0
  177. package/dist/lib/types/component/table/ColumnFilter.d.ts +27 -0
  178. package/dist/lib/types/component/table/Header.d.ts +30 -3
  179. package/dist/lib/types/component/table/Row.d.ts +4 -0
  180. package/dist/lib/types/component/table/Table.d.ts +29 -0
  181. package/dist/lib/types/component/table/TableExporter.d.ts +4 -3
  182. package/dist/lib/types/component/table/TreeBody.d.ts +2 -1
  183. package/dist/lib/types/component/table/cell/CellText.d.ts +9 -0
  184. package/dist/lib/types/component/table/cell/Filter.d.ts +54 -0
  185. package/dist/lib/types/component/table/cell/FilterClauseBadge.d.ts +21 -0
  186. package/dist/lib/types/component/table/cell/GroupSeparator.d.ts +9 -0
  187. package/dist/lib/types/component/table/cell/Header.d.ts +1 -0
  188. package/dist/lib/types/component/table/cell/SortPriorityBadge.d.ts +1 -1
  189. package/dist/lib/types/component/table/cell/editor/CellEditor.d.ts +1 -0
  190. package/dist/lib/types/component/table/cell/editor/CellEditorPool.d.ts +1 -0
  191. package/dist/lib/types/component/table/cell/editor/Date.d.ts +1 -0
  192. package/dist/lib/types/component/table/cell/editor/DateTime.d.ts +1 -0
  193. package/dist/lib/types/component/table/cell/editor/Time.d.ts +1 -0
  194. package/dist/lib/types/component/table/cell/renderer/CellRenderer.d.ts +1 -0
  195. package/dist/lib/types/component/table/cell/renderer/Combo.d.ts +2 -0
  196. package/dist/lib/types/component/table/cell/renderer/Date.d.ts +2 -0
  197. package/dist/lib/types/component/table/cell/renderer/DateTime.d.ts +2 -0
  198. package/dist/lib/types/component/table/cell/renderer/Filter.d.ts +16 -0
  199. package/dist/lib/types/component/table/cell/renderer/Glyph.d.ts +1 -0
  200. package/dist/lib/types/component/table/cell/renderer/Link.d.ts +2 -0
  201. package/dist/lib/types/component/table/cell/renderer/Number.d.ts +3 -1
  202. package/dist/lib/types/component/table/cell/renderer/String.d.ts +2 -0
  203. package/dist/lib/types/component/table/cell/renderer/Time.d.ts +2 -0
  204. package/dist/lib/types/component/table/cell/renderer/TreeCell.d.ts +1 -0
  205. package/dist/lib/types/component/table/index.d.ts +6 -0
  206. package/dist/lib/types/component/tree/Tree.d.ts +26 -2
  207. package/dist/lib/types/component/tree/index.d.ts +1 -1
  208. package/dist/lib/types/component/tree/renderer/Label.d.ts +1 -1
  209. package/dist/lib/types/core/AnimatedDropdown.d.ts +0 -9
  210. package/dist/lib/types/core/Body.d.ts +4 -0
  211. package/dist/lib/types/core/ClassStyleRules.d.ts +1 -0
  212. package/dist/lib/types/core/Component.d.ts +5 -0
  213. package/dist/lib/types/core/DOM.d.ts +10 -0
  214. package/dist/lib/types/core/Event.d.ts +11 -2
  215. package/dist/lib/types/core/OverlayFade.d.ts +12 -0
  216. package/dist/lib/types/core/OverlayPosition.d.ts +6 -0
  217. package/dist/lib/types/core/Theme.d.ts +12 -2
  218. package/dist/lib/types/core/index.d.ts +5 -3
  219. package/dist/lib/types/data/AbstractStore.d.ts +3 -0
  220. package/dist/lib/types/data/FilterDescriptor.d.ts +13 -0
  221. package/dist/lib/types/data/index.d.ts +2 -1
  222. package/dist/lib/types/data/temporalText.d.ts +2 -0
  223. package/dist/lib/types/layout/BoxLayout.d.ts +6 -1
  224. package/dist/lib/types/layout/Grid.d.ts +1 -0
  225. package/dist/lib/types/layout/HFlow.d.ts +1 -1
  226. package/dist/lib/types/layout/LayoutManager.d.ts +8 -0
  227. package/dist/lib/types/layout/Split.d.ts +10 -1
  228. package/dist/lib/types/layout/Tab.d.ts +7 -1
  229. package/dist/lib/types/layout/VFlow.d.ts +1 -1
  230. package/dist/lib/types/layout/index.d.ts +1 -1
  231. package/dist/lib/types/overlay/Dock.d.ts +1 -0
  232. package/dist/lib/types/overlay/Menu.d.ts +1 -1
  233. package/dist/lib/types/overlay/Popover.d.ts +3 -0
  234. package/dist/lib/types/overlay/PopupPanel.d.ts +17 -0
  235. package/dist/lib/types/overlay/Window.d.ts +2 -0
  236. package/dist/lib/types/overlay/index.d.ts +2 -0
  237. package/dist/lib/types/router/RoutePattern.d.ts +7 -0
  238. package/dist/lib/types/router/Router.d.ts +6 -2
  239. package/dist/lib/types/router/index.d.ts +1 -1
  240. package/dist/lib/validation.es.js +1 -1
  241. package/llms.txt +7 -0
  242. package/package.json +15 -15
  243. package/dist/lib/AbstractBooleanInput-DE5NNJT0.js +0 -2
  244. package/dist/lib/AbstractBooleanInput-DE5NNJT0.js.map +0 -1
  245. package/dist/lib/AnchorConstraints-DdDYSDkf.js +0 -2
  246. package/dist/lib/AnchorConstraints-DdDYSDkf.js.map +0 -1
  247. package/dist/lib/AnimatedDropdown-QLNasu_Y.js +0 -2
  248. package/dist/lib/AnimatedDropdown-QLNasu_Y.js.map +0 -1
  249. package/dist/lib/Border-CKKUk5G9.js +0 -2
  250. package/dist/lib/Border-CKKUk5G9.js.map +0 -1
  251. package/dist/lib/Button-MZDYJOMC.js +0 -2
  252. package/dist/lib/Button-MZDYJOMC.js.map +0 -1
  253. package/dist/lib/ComboBox-C04SfXAR.js +0 -2
  254. package/dist/lib/ComboBox-C04SfXAR.js.map +0 -1
  255. package/dist/lib/Component-fRQvgaEY.js +0 -2
  256. package/dist/lib/Component-fRQvgaEY.js.map +0 -1
  257. package/dist/lib/Container-0bsG2Q8Z.js +0 -2
  258. package/dist/lib/DOM-67StIm5G.js +0 -2
  259. package/dist/lib/DOM-67StIm5G.js.map +0 -1
  260. package/dist/lib/DragManager-DRor_-1x.js +0 -2
  261. package/dist/lib/DragManager-DRor_-1x.js.map +0 -1
  262. package/dist/lib/Grid-DHHmaB-Y.js.map +0 -1
  263. package/dist/lib/GridConstraints-DVc1BmlP.js +0 -2
  264. package/dist/lib/LayoutSerialization-D5bBas4W.js +0 -2
  265. package/dist/lib/LayoutSerialization-D5bBas4W.js.map +0 -1
  266. package/dist/lib/LayoutSizes-qNaURyiw.js +0 -2
  267. package/dist/lib/LayoutSizes-qNaURyiw.js.map +0 -1
  268. package/dist/lib/List-CG4NvwuV.js +0 -2
  269. package/dist/lib/MemoryStore-DT6iWWco.js +0 -2
  270. package/dist/lib/MemoryStore-DT6iWWco.js.map +0 -1
  271. package/dist/lib/Menu-CrZy2u0g.js +0 -2
  272. package/dist/lib/Menu-CrZy2u0g.js.map +0 -1
  273. package/dist/lib/Panel-Rd9zkNXx.js +0 -2
  274. package/dist/lib/RadioButton-D23rId-V.js +0 -2
  275. package/dist/lib/RadioButton-D23rId-V.js.map +0 -1
  276. package/dist/lib/Scrollbar-SOj9psiP.js +0 -2
  277. package/dist/lib/Scrollbar-SOj9psiP.js.map +0 -1
  278. package/dist/lib/Slider-DBnAZ-F7.js +0 -2
  279. package/dist/lib/Slider-DBnAZ-F7.js.map +0 -1
  280. package/dist/lib/TabButton-DKECTTk1.js +0 -2
  281. package/dist/lib/TabButton-DKECTTk1.js.map +0 -1
  282. package/dist/lib/Text-KB5LksJl.js +0 -2
  283. package/dist/lib/Text-KB5LksJl.js.map +0 -1
  284. package/dist/lib/Tooltip-Dro4DOZs.js.map +0 -1
  285. package/dist/lib/VBox-P3WFGkPc.js +0 -2
  286. package/dist/lib/VBox-P3WFGkPc.js.map +0 -1
  287. package/dist/lib/VirtualScroller-Bv4KXGKW.js +0 -2
  288. package/dist/lib/VirtualScroller-Bv4KXGKW.js.map +0 -1
  289. package/dist/lib/assets/StoreWorker-CgOBYoai.js +0 -2
  290. package/dist/lib/assets/StoreWorker-CgOBYoai.js.map +0 -1
  291. package/dist/lib/selectionsEqual-Ci3_uflt.js +0 -2
  292. package/dist/lib/selectionsEqual-Ci3_uflt.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"VBox-P3WFGkPc.js","names":[],"sources":["../../src/typescript/lib/layout/BoxLayout.ts","../../src/typescript/lib/layout/HBox.ts","../../src/typescript/lib/layout/VBox.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { LayoutManager, LayoutManagerOptions } from \"~/layout/LayoutManager.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { AnchorType } from \"~/layout/AnchorType.js\";\nimport type { AxisPosition, AxisSpread } from \"~/primitive/Axis.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { Size, UNBOUNDED, isUnbounded } from \"~/primitive/Size.js\";\n\n/**\n * Sizing strategy along an {@link HBox} or {@link VBox}'s main axis.\n *\n * - `\"preferred\"` — each child gets its preferred width (height for VBox);\n * `weight`-constrained children split the remaining space; an overflow\n * shrinks non-weighted children proportionally toward their min sizes.\n * - `\"equal\"` — children split the container's inner extent equally; the\n * per-cell floor is `max(child.minSize.width)` (height for VBox);\n * `weight` constraints are ignored.\n *\n * @category Layouts\n */\nexport type BoxMode = \"preferred\" | \"equal\";\n\n/**\n * How an `\"equal\"`-mode {@link HBox}/{@link VBox} sizes its cells when the\n * row/column overflows the host's inner extent and the host has opted into\n * scrolling (`Panel.setAutoScroll`).\n *\n * - `\"preferred\"` (the default) — every cell takes the widest/tallest child's\n * preferred extent, so cells keep their preferred size and the host scrolls.\n * - `\"min\"` — every cell stays at the min floor (`max(child.minSize)`), so the\n * row/column scrolls at the minimum cell size instead of growing.\n *\n * Has no effect outside `\"equal\"` mode, nor when the cells fit (the equal share\n * clears the min floor), nor when the host does not scroll (cells always clamp\n * to the min floor and the host's `overflow: hidden` clips the surplus).\n *\n * @category Layouts\n */\nexport type BoxOverflowSizing = \"preferred\" | \"min\";\n\n/**\n * How a `\"preferred\"`-mode {@link HBox}/{@link VBox} distributes the leftover\n * main-axis space when its children are shorter than the inner main extent and\n * no `weight` cells consume the slack. Mirrors CSS `justify-content`.\n *\n * A single line makes exactly one main-axis slack decision, so the two shared\n * axis concepts fuse into this one field: the {@link AxisPosition} half\n * (`\"start\"`/`\"center\"`/`\"end\"`) positions the whole child block as a unit,\n * while the {@link AxisSpread} half (`\"between\"`/`\"around\"`) spreads the slack\n * into the inter-child gaps. `justifyOffsets` reflects the split — position\n * values yield a leading offset (`lead`, `gap: 0`) and spread values yield an\n * inter-child `gap`. `\"start\"` is the shared identity of both halves, so the\n * union collapses to these five distinct values.\n *\n * - `\"start\"` (the default) — children pack at the leading edge; the slack sits\n * at the trailing edge.\n * - `\"center\"` — the child block is centred; equal slack on both ends.\n * - `\"end\"` — children pack at the trailing edge; the slack sits at the leading\n * edge.\n * - `\"between\"` — the first child sits at the leading edge, the last at the\n * trailing edge, and the slack is split evenly into the gaps between them.\n * - `\"around\"` — every child gets equal space around it: a half-unit before the\n * first and after the last, a full unit between neighbours.\n *\n * Has no effect outside `\"preferred\"` mode, nor when `weight` cells absorb the\n * slack, nor when the content fills or overflows the inner extent (the row\n * clamps to `\"start\"` so the leading child is never pushed out of view).\n *\n * @category Layouts\n */\nexport type BoxJustify = AxisPosition | AxisSpread;\n\n/**\n * Construction-time options shared by {@link HBox} and {@link VBox}.\n *\n * @remarks `mode` selects the sizing strategy along the box's main axis.\n * `\"preferred\"` (the default) honours each child's preferred main-axis extent\n * and supports `weight` cells. `\"equal\"` divides the container's main axis\n * equally and ignores `weight`. `mode` is independent of `stretching`, which\n * governs the cross axis: `stretching` defaults to `false` in both modes, so\n * `\"equal\"` divides the main axis but leaves children at their preferred\n * cross-axis extent unless `stretching: true` is passed.\n *\n * @category Layouts\n */\nexport interface BoxLayoutOptions extends LayoutManagerOptions {\n spacing?: number;\n stretching?: boolean;\n mode?: BoxMode;\n overflowSizing?: BoxOverflowSizing;\n justify?: BoxJustify;\n}\n\n/**\n * Abstract base for the single-axis box layouts {@link HBox} and {@link VBox}.\n * Holds the axis-agnostic configuration plumbing — spacing, stretching, sizing\n * mode, and overflow sizing — and dispatches a {@link BoxLayoutOptions} bag.\n * The geometric algorithms (`getPreferredSize`, `getMinSize`, `getMaxSize`,\n * `computeTotalMinSize`, `doLayout`) are mirror-image per axis and stay\n * concrete on each subclass.\n *\n * @category Layouts\n */\nexport abstract class BoxLayout extends LayoutManager {\n\n // `protected`, not `private`: the subclasses' geometric methods\n // (getPreferredSize/getMinSize/getMaxSize/computeTotalMinSize/doLayout)\n // read these fields directly, so they must be visible to HBox/VBox.\n protected _spacing: number = 5;\n protected _stretching: boolean = false;\n protected _mode: BoxMode = \"preferred\";\n protected _overflowSizing: BoxOverflowSizing = \"preferred\";\n protected _justify: BoxJustify = \"start\";\n\n constructor(options?: BoxLayoutOptions) {\n // LayoutManager's constructor takes no options; applied via applyOptions below.\n // eslint-disable-next-line local/forward-super-options\n super();\n\n if (options) {\n this.applyOptions(options);\n }\n }\n\n /**\n * Applies a {@link BoxLayoutOptions} bag, dispatching mode, spacing, and\n * stretching after the inherited LayoutManager defaults.\n *\n * @param options - The options bag carrying the values to apply.\n *\n * @remarks `mode` and `stretching` are independent axes: `mode` governs the\n * main-axis sizing strategy, `stretching` governs whether children fill the\n * cross axis. Neither defaults from the other — `stretching` is `false`\n * unless the options bag passes it explicitly, in both `\"preferred\"` and\n * `\"equal\"` mode.\n */\n protected applyOptions(options: BoxLayoutOptions): void {\n super.applyOptions(options);\n\n if (options.mode !== undefined) {\n this.setMode(options.mode);\n }\n\n if (options.spacing !== undefined) {\n this.setComponentSpacing(options.spacing);\n }\n\n if (options.stretching !== undefined) {\n this.setStretching(options.stretching);\n }\n\n if (options.overflowSizing !== undefined) {\n this.setOverflowSizing(options.overflowSizing);\n }\n\n if (options.justify !== undefined) {\n this.setJustify(options.justify);\n }\n }\n\n /**\n * Returns the pixel spacing between child components.\n *\n * @returns The current spacing in pixels.\n */\n getComponentSpacing(): number {\n return this._spacing || 0;\n }\n\n /**\n * Sets the pixel spacing between child components.\n *\n * @param spacing - Spacing in pixels.\n *\n * @returns This layout manager, for method chaining.\n */\n setComponentSpacing(spacing: number): this {\n this._spacing = spacing || 0;\n\n return this;\n }\n\n /**\n * Returns whether children stretch to fill the container's cross axis.\n *\n * @returns `true` if stretching is enabled.\n */\n isStretching(): boolean {\n return this._stretching || false;\n }\n\n /**\n * Sets whether children stretch to fill the container's cross axis.\n *\n * @param stretching - Pass `true` to enable cross-axis stretching.\n *\n * @returns This layout manager, for method chaining.\n */\n setStretching(stretching: boolean): this {\n this._stretching = !!stretching;\n\n return this;\n }\n\n /**\n * Returns the current sizing mode along the main axis.\n *\n * @returns Either `\"preferred\"` or `\"equal\"`.\n */\n getMode(): BoxMode {\n return this._mode;\n }\n\n /**\n * Sets the sizing mode along the main axis.\n *\n * @param mode - `\"preferred\"` honours each child's preferred main-axis\n * extent; `\"equal\"` divides the container's main axis equally among\n * children.\n *\n * @returns This layout manager, for method chaining.\n */\n setMode(mode: BoxMode): this {\n this._mode = mode;\n\n return this;\n }\n\n /**\n * Returns the cell-sizing strategy used when an `\"equal\"`-mode row/column\n * overflows a scrolling host.\n *\n * @returns Either `\"preferred\"` or `\"min\"`.\n */\n getOverflowSizing(): BoxOverflowSizing {\n return this._overflowSizing;\n }\n\n /**\n * Sets the cell-sizing strategy used when an `\"equal\"`-mode row/column\n * overflows a scrolling host.\n *\n * @param overflowSizing - `\"preferred\"` grows every cell to the largest\n * child's preferred extent and scrolls; `\"min\"` keeps cells at the min\n * floor and scrolls at the minimum cell size. See {@link BoxOverflowSizing}.\n *\n * @returns This layout manager, for method chaining.\n */\n setOverflowSizing(overflowSizing: BoxOverflowSizing): this {\n this._overflowSizing = overflowSizing;\n\n return this;\n }\n\n /**\n * Returns how leftover main-axis space is distributed in `\"preferred\"` mode.\n *\n * @returns The current {@link BoxJustify} mode.\n */\n getJustify(): BoxJustify {\n return this._justify;\n }\n\n /**\n * Sets how leftover main-axis space is distributed in `\"preferred\"` mode.\n *\n * @param justify - `\"start\"` packs children at the leading edge (the\n * default), `\"center\"`/`\"end\"` shift the block, and `\"between\"`/`\"around\"`\n * spread the slack into the inter-child gaps. See {@link BoxJustify}.\n *\n * @returns This layout manager, for method chaining.\n */\n setJustify(justify: BoxJustify): this {\n this._justify = justify;\n\n return this;\n }\n\n /**\n * Aggregates the children's maximum sizes per the box contract: main axis =\n * sum of child maxima (+ spacing; in `\"equal\"` mode count * widest-child-max),\n * cross axis = max of child maxima, a null or unbounded child max making that\n * axis unbounded. Saturated to {@link UNBOUNDED}. Includes the container\n * perimeter.\n *\n * @param horizontal - `true` for {@link HBox} (main = width), `false` for\n * {@link VBox} (main = height).\n * @returns The aggregated maximum `{width, height}`, or `null` if no\n * container is attached.\n */\n protected aggregateMaxSize(horizontal: boolean): Size | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const perimeterSize = container.getPerimeterSize();\n const components = container.getLaidOutComponents();\n\n const mainStart = horizontal ? perimeterSize.left + perimeterSize.right : perimeterSize.top + perimeterSize.bottom;\n const crossExtra = horizontal ? perimeterSize.top + perimeterSize.bottom : perimeterSize.left + perimeterSize.right;\n\n let main = mainStart;\n let cross = 0;\n let mainUnbounded = false;\n let crossUnbounded = false;\n let maxChildMain = 0;\n\n for (const component of components) {\n const size = component.getMaxSize();\n\n if (!size) {\n mainUnbounded = true;\n crossUnbounded = true;\n continue;\n }\n\n const mainExtent = horizontal ? size.width : size.height;\n const crossExtent = horizontal ? size.height : size.width;\n\n if (isUnbounded(mainExtent)) {\n mainUnbounded = true;\n } else if (this._mode === \"equal\") {\n maxChildMain = Math.max(maxChildMain, mainExtent);\n } else {\n main += mainExtent;\n }\n\n if (isUnbounded(crossExtent)) {\n crossUnbounded = true;\n } else {\n cross = Math.max(cross, crossExtent);\n }\n }\n\n if (this._mode === \"equal\") {\n main += components.length * maxChildMain + this._spacing * Math.max(0, components.length - 1);\n } else {\n main += this._spacing * Math.max(0, components.length - 1);\n }\n\n cross += crossExtra;\n\n const mainValue = mainUnbounded ? UNBOUNDED : main;\n const crossValue = crossUnbounded ? UNBOUNDED : cross;\n\n return {\n width: horizontal ? mainValue : crossValue,\n height: horizontal ? crossValue : mainValue\n };\n }\n\n /**\n * Resolves how much main-axis space the weight cells share and how hard the\n * non-weighted children must shrink. When the non-weighted children's\n * preferred extents fit (or the host scrolls on this axis), nothing shrinks\n * and the leftover is the weight remainder. Otherwise the children shrink\n * proportionally toward their min extents so the last child's far edge lands\n * inside the container.\n *\n * @param fixedPreferred - Summed preferred main-axis extent of the\n * non-weighted children, including inter-child spacing.\n * @param fixedMin - Summed minimum main-axis extent of the same children,\n * including spacing.\n * @param available - The working container's inner extent on the main axis.\n * @param overflowing - Whether the host has opted into scrolling on this\n * axis; when `true` the shrink is skipped so the host's CSS overflow\n * engages instead.\n * @returns `remaining` — the main-axis space left for weight cells — and\n * `shrinkRatio` — `0` (no shrink) through `1` (shrink fully to min).\n */\n protected computeShrink(fixedPreferred: number, fixedMin: number, available: number, overflowing: boolean): { remaining: number; shrinkRatio: number } {\n if (fixedPreferred <= available || overflowing) {\n return { remaining: Math.max(0, available - fixedPreferred), shrinkRatio: 0 };\n }\n\n const excess = fixedPreferred - available;\n const shrinkable = fixedPreferred - fixedMin;\n\n return { remaining: 0, shrinkRatio: shrinkable > 0 ? Math.min(1, excess / shrinkable) : 1 };\n }\n\n /**\n * Distributes the trailing main-axis slack per {@link BoxJustify}, returning\n * a leading offset and an extra inter-child gap. The subclass adds `lead` to\n * the placement cursor's start and `gap` to the inter-child spacing. A row\n * that fills or overflows the inner extent (`residual === 0`) and the\n * `\"start\"` fast path both return `{ lead: 0, gap: 0 }`, leaving placement\n * byte-identical to the un-justified loop. Generalises\n * {@link FlowLayout.alignLead}, which only produces a leading offset, by also\n * spreading slack into the gaps for `\"between\"`/`\"around\"`.\n *\n * @param contentMain - Summed placed child main-extents plus inter-child\n * spacing — the block's total main extent.\n * @param innerMain - The container's inner extent along the main axis.\n * @param count - The number of children sharing the axis.\n * @returns `lead` — pixels added before the first child — and `gap` — pixels\n * added to the spacing after each child. Both are non-negative.\n */\n protected justifyOffsets(contentMain: number, innerMain: number, count: number): { lead: number; gap: number } {\n const residual = Math.max(0, innerMain - contentMain);\n\n if (residual === 0 || this._justify === \"start\") {\n return { lead: 0, gap: 0 };\n }\n\n if (this._justify === \"center\") {\n return { lead: residual / 2, gap: 0 };\n }\n\n if (this._justify === \"end\") {\n return { lead: residual, gap: 0 };\n }\n\n if (this._justify === \"between\") {\n return { lead: 0, gap: count > 1 ? residual / (count - 1) : 0 };\n }\n\n // \"around\"\n return { lead: count > 0 ? residual / (2 * count) : 0, gap: count > 0 ? residual / count : 0 };\n }\n\n /**\n * Resolves a child's cross-axis offset and extent within the full cross\n * band, honouring an explicit per-child cross `fill`/`anchor` (align-self).\n * A cross-axis `fill` (`VERTICAL`/`BOTH` in an {@link HBox}, `HORIZONTAL`/\n * `BOTH` in a {@link VBox}) stretches the child to the whole band; a\n * cross-axis `anchor` edge (NORTH/SOUTH for HBox, WEST/EAST for VBox, plus\n * the corners carrying that component) pins the child's natural cross extent\n * to the leading or trailing edge. The main-axis `anchor` component and\n * `CENTER` are deliberately inert — the box owns main-axis sequencing and\n * each box's default cross placement (HBox baseline, VBox WEST origin) is\n * more specific than geometric centring.\n *\n * @param component - The child whose constraints supply the cross intent.\n * @param crossLead - The band's leading edge (`insets.top` for HBox,\n * `insets.left` for VBox).\n * @param crossExtent - The full cross band extent.\n * @param naturalCross - The child's preferred cross extent, already capped to\n * the band and the child's maximum; the anchored child sits at this extent.\n * @param horizontal - `true` for {@link HBox} (cross axis is vertical),\n * `false` for {@link VBox} (cross axis is horizontal).\n * @returns `{ offset, extent }` when the child sets an explicit cross intent,\n * or `null` to signal the caller to keep its default cross placement.\n */\n protected crossPlacement(component: Component, crossLead: number, crossExtent: number, naturalCross: number, horizontal: boolean): { offset: number; extent: number } | null {\n const constraints = this.getLayoutConstraints(component);\n const fill = constraints?.fill ?? null;\n const anchor = constraints?.anchor ?? null;\n\n const crossFill = horizontal\n ? (fill === FillType.VERTICAL || fill === FillType.BOTH)\n : (fill === FillType.HORIZONTAL || fill === FillType.BOTH);\n\n if (crossFill) {\n return { offset: crossLead, extent: crossExtent };\n }\n\n const edge = this.crossAnchorEdge(anchor, horizontal);\n\n if (edge === null) {\n return null;\n }\n\n const extent = Math.min(naturalCross, crossExtent);\n const offset = edge === \"lead\"\n ? crossLead\n : crossLead + (crossExtent - extent);\n\n return { offset, extent };\n }\n\n /**\n * Projects a child's `anchor` onto the cross axis as a leading/trailing edge.\n * CENTER and pure main-axis anchors carry no cross component and return\n * `null`, leaving the caller on its default cross placement.\n *\n * @param anchor - The child's anchor constraint, or `null`.\n * @param horizontal - `true` for {@link HBox} (cross = vertical: NORTH=lead,\n * SOUTH=trail), `false` for {@link VBox} (cross = horizontal: WEST=lead,\n * EAST=trail).\n * @returns `\"lead\"`/`\"trail\"` for an anchor with a cross component, else `null`.\n */\n private crossAnchorEdge(anchor: AnchorType | null, horizontal: boolean): \"lead\" | \"trail\" | null {\n if (anchor === null) {\n return null;\n }\n\n if (horizontal) {\n if (anchor === AnchorType.NORTH || anchor === AnchorType.NORTHWEST || anchor === AnchorType.NORTHEAST) {\n return \"lead\";\n }\n\n if (anchor === AnchorType.SOUTH || anchor === AnchorType.SOUTHWEST || anchor === AnchorType.SOUTHEAST) {\n return \"trail\";\n }\n\n return null;\n }\n\n if (anchor === AnchorType.WEST || anchor === AnchorType.NORTHWEST || anchor === AnchorType.SOUTHWEST) {\n return \"lead\";\n }\n\n if (anchor === AnchorType.EAST || anchor === AnchorType.NORTHEAST || anchor === AnchorType.SOUTHEAST) {\n return \"trail\";\n }\n\n return null;\n }\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { BoxLayout, BoxLayoutOptions } from \"~/layout/BoxLayout.js\";\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Size } from \"~/primitive/Size.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link HBox}.\n *\n * @remarks `mode` selects the sizing strategy along the horizontal axis.\n * `\"preferred\"` (the default) honours each child's preferred width and\n * supports `weight` cells. `\"equal\"` divides the container width equally\n * and ignores `weight`. `mode` is independent of `stretching` (the cross-axis\n * fill): `stretching` defaults to `false` in both modes, so `\"equal\"` divides\n * the width but leaves children at their preferred height unless\n * `stretching: true` is passed.\n *\n * @category Layouts\n */\nexport interface HBoxOptions extends BoxLayoutOptions {}\n\n/**\n * A layout manager that places children in a single horizontal row. The\n * `mode` option selects between preferred-width sequencing (with weight-cell\n * support) and equal-width division of the container.\n *\n * @category Layouts\n */\nclass HBox extends BoxLayout {\n\n private _defaultComponentWidth: number = 100;\n\n /**\n * Returns the row's baseline (the maximum child text baseline) measured from\n * the container's content-top, so a baseline-aware parent aligns this HBox\n * container by the same baseline its own children align to — rather than\n * auto-centring the whole container.\n *\n * @returns The inner baseline offset in pixels, or `null` while stretching\n * (baseline alignment is disabled) or when no child reports a baseline.\n */\n getContentBaseline(): number | null {\n if (this.isStretching()) {\n return null;\n }\n\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n for (const component of container.getLaidOutComponents()) {\n const size = component.getPreferredSize();\n heights.push(size ? size.height : 0);\n baselines.push(component.getBaseline());\n }\n\n return this.computeRowMetrics(heights, baselines).rowAscent;\n }\n\n /**\n * Returns the preferred size. In `\"preferred\"` mode this is the sum\n * of child widths plus spacing. In `\"equal\"` mode it is\n * `count * (maxChildWidth + spacing) - spacing`. Row height in both\n * modes is the baseline-aware row height of the children.\n *\n * @returns The preferred `{width, height}`, or `null` if no container is attached.\n */\n getPreferredSize(): Size | null {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let perimeterSize = container.getPerimeterSize();\n let components = container.getLaidOutComponents();\n let width = perimeterSize.left + perimeterSize.right;\n\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n if (this._mode === \"equal\") {\n let maxChildWidth = 0;\n\n for (let idx in components) {\n let component = components[idx];\n let size = component.getPreferredSize();\n\n if (size) {\n maxChildWidth = Math.max(maxChildWidth, size.width);\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n\n width += components.length * (maxChildWidth + this._spacing) - this._spacing;\n } else {\n for (let idx in components) {\n let component = components[idx];\n let size = component.getPreferredSize();\n\n if (size) {\n width += size.width;\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n\n width += this._spacing * (components.length - 1);\n }\n\n let height = this.computeRowHeight(heights, baselines);\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the minimum size. In `\"preferred\"` mode this is the sum of\n * child min widths plus spacing. In `\"equal\"` mode it is\n * `count * (maxChildMinWidth + spacing) - spacing`. Row height in\n * both modes is the baseline-aware row height of the children's\n * minimums.\n *\n * @returns The minimum `{width, height}`, or `null` if no container is attached.\n */\n getMinSize(): Size | null {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let perimeterSize = container.getPerimeterSize();\n let components = container.getLaidOutComponents();\n let width = perimeterSize.left + perimeterSize.right;\n\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n if (this._mode === \"equal\") {\n let maxChildMinWidth = 0;\n\n for (let idx in components) {\n let component = components[idx];\n let size = component.getMinSize();\n\n if (size) {\n maxChildMinWidth = Math.max(maxChildMinWidth, size.width);\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n\n width += components.length * (maxChildMinWidth + this._spacing) - this._spacing;\n } else {\n for (let idx in components) {\n let component = components[idx];\n let size = component.getMinSize();\n\n if (size) {\n width += size.width;\n heights.push(size.height);\n baselines.push(component.getBaseline());\n }\n }\n\n width += this._spacing * (components.length - 1);\n }\n\n let height = this.computeRowHeight(heights, baselines);\n\n height += perimeterSize.top + perimeterSize.bottom;\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the maximum size the row can usefully occupy. Along the main axis\n * (width) it sums the children's *maximum* widths plus spacing; in `\"equal\"`\n * mode it is `count * maxChildMaxWidth` plus spacing, since every cell shares\n * the widest child's allowance. The cross axis (height) takes the *largest*\n * child maximum — the tallest a child permits the row to grow to. A child\n * whose maximum is `null` or at the unbounded sentinel makes that axis\n * unbounded.\n *\n * @returns The maximum `{width, height}`, or `null` if no container is attached.\n */\n getMaxSize(): Size | null {\n return this.aggregateMaxSize(true);\n }\n\n /**\n * Computes the children's combined minSize along this manager's geometry.\n * In `\"preferred\"` mode width is the sum of per-child `minSize.width`\n * plus spacing. In `\"equal\"` mode width is\n * `count * maxChildMinWidth + spacing*(n-1)` (HBox distributes width\n * equally so the per-cell floor is the max of every child's min width).\n * Height in both modes is the max per-child `minSize.height`. Used by\n * `doLayout` to inflate the working size when the host has opted into\n * `setOverflowing` on the corresponding axis.\n *\n * @returns The total min-size; `{ width: 0, height: 0 }` when the\n * container is absent or has no children.\n */\n protected computeTotalMinSize(): Size {\n const container = this.getContainer();\n if (!container) {\n return { width: 0, height: 0 };\n }\n\n const components = container.getLaidOutComponents();\n if (components.length === 0) {\n return { width: 0, height: 0 };\n }\n\n let height = 0;\n\n if (this._mode === \"equal\") {\n let maxWidth = 0;\n\n for (const component of components) {\n const min = component.getMinSize();\n if (min) {\n maxWidth = Math.max(maxWidth, min.width);\n height = Math.max(height, min.height);\n }\n }\n\n return {\n width: components.length * (maxWidth + this._spacing) - this._spacing,\n height,\n };\n }\n\n let width = this._spacing * (components.length - 1);\n\n for (const component of components) {\n const min = component.getMinSize();\n if (min) {\n width += min.width;\n height = Math.max(height, min.height);\n }\n }\n\n return { width, height };\n }\n\n /**\n * Lays out the children left-to-right, dispatching to `layoutEqualMode` or\n * `layoutPreferredMode` per the sizing mode after inflating the working\n * size for any scroll-enabled axis.\n */\n doLayout(): void {\n const container = this.getContainer();\n if (!container) {\n return;\n }\n\n const innerSize = container.getInnerSize();\n if (!innerSize) {\n return;\n }\n\n const components = container.getLaidOutComponents();\n const containerInsets = container.getContentInsets();\n const spacing = this.getComponentSpacing();\n\n // Universal scroll: when the host has opted into per-axis overflow, lay\n // out against the children's combined minSize so trailing children land\n // past the viewport and the host's CSS `overflow: auto` scrolls.\n // `innerSize` stays the real viewport for equal mode's overflow test.\n const containerSize = this.inflateForOverflow(innerSize);\n\n if (this._mode === \"equal\") {\n this.layoutEqualMode(components, innerSize, containerSize, containerInsets, spacing);\n } else {\n this.layoutPreferredMode(components, containerSize, containerInsets, spacing);\n }\n\n this.reserveContentFrame();\n }\n\n /**\n * Places children in equal-width cells. Every cell takes the same width\n * (see {@link HBox.computeEqualCellWidth}); when stretching, cells fill the\n * container height, otherwise children keep their preferred height and are\n * baseline-aligned within the row.\n *\n * @param components - The children to place, in order.\n * @param innerSize - The host's real inner size (pre-inflation), used to\n * measure the equal share against the true viewport.\n * @param containerSize - The working size, possibly inflated for overflow.\n * @param insets - The container's content insets.\n * @param spacing - Inter-child spacing in pixels.\n */\n private layoutEqualMode(components: Component[], innerSize: Size, containerSize: Size, insets: Insets, spacing: number): void {\n const cellWidth = this.computeEqualCellWidth(components, innerSize.width, spacing);\n\n if (this.isStretching()) {\n const y = insets.getTop();\n let x = insets.getLeft();\n\n for (const component of components) {\n this.placeComponent(component, x, y, cellWidth, containerSize.height, FillType.BOTH);\n\n x += cellWidth + spacing;\n }\n\n return;\n }\n\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n for (const component of components) {\n const size = component.getPreferredSize();\n\n heights.push(size ? size.height : 0);\n baselines.push(component.getBaseline());\n }\n\n const { rowAscent, rowDescent } = this.computeRowMetrics(heights, baselines);\n\n // Match the equal-stretch band exactly: the stretch branch fills\n // containerSize.height from insets.top with no bottom-inset subtraction,\n // so an EAST/fill align-self child reaches the same trailing edge.\n const crossLead = insets.getTop();\n const crossExtent = containerSize.height;\n\n let x = insets.getLeft();\n\n for (let idx = 0; idx < components.length; idx += 1) {\n const component = components[idx];\n\n const cross = this.crossPlacement(component, crossLead, crossExtent, heights[idx], true);\n\n if (cross) {\n this.placeComponent(component, x, cross.offset, cellWidth, cross.extent, FillType.BOTH);\n } else {\n const y = this.rowChildY(insets.getTop(), heights[idx], baselines[idx], rowAscent, rowDescent);\n\n this.placeComponent(component, x, y, cellWidth, heights[idx], FillType.BOTH);\n }\n\n x += cellWidth + spacing;\n }\n }\n\n /**\n * Computes the shared cell width for equal mode: the equal share of the\n * inner width, floored at the widest child's min width.\n *\n * @param components - The children sharing the row.\n * @param innerWidth - The host's real inner width (pre-inflation).\n * @param spacing - Inter-child spacing in pixels.\n * @returns The width every equal-mode cell receives.\n *\n * @remarks Three cases drive the floor: (1) the share clears the widest\n * child's min width → the row fits, divide equally; (2) the share is below\n * the min floor, the host scrolls on this axis, and `overflowSizing` is\n * `\"preferred\"` → every cell takes the widest child's preferred width so\n * cells regain preferred size instead of sticking at min while scrolling;\n * (3) otherwise → clamp to the min floor (a non-scrolling host's\n * `overflow: hidden` clips the surplus).\n */\n private computeEqualCellWidth(components: Component[], innerWidth: number, spacing: number): number {\n let maxChildMinWidth = 0;\n let maxChildPreferredWidth = 0;\n\n for (const component of components) {\n const min = component.getMinSize();\n if (min) {\n maxChildMinWidth = Math.max(maxChildMinWidth, min.width);\n }\n\n const pref = component.getPreferredSize();\n if (pref) {\n maxChildPreferredWidth = Math.max(maxChildPreferredWidth, pref.width);\n }\n }\n\n const equalShare = (innerWidth - spacing * (components.length - 1)) / components.length;\n\n if (equalShare >= maxChildMinWidth) {\n return equalShare;\n }\n\n if (this.isOverflowingX() && this._overflowSizing === \"preferred\") {\n return Math.max(maxChildMinWidth, maxChildPreferredWidth);\n }\n\n return maxChildMinWidth;\n }\n\n /**\n * Places children at their preferred widths. Weight cells split the space\n * left after the non-weighted children; when the row overflows, the\n * non-weighted children shrink proportionally toward their min widths.\n * Children keep their preferred height (or fill the row height when\n * stretching) and are baseline-aligned unless stretching.\n *\n * @param components - The children to place, in order.\n * @param containerSize - The working size, possibly inflated for overflow.\n * @param insets - The container's content insets.\n * @param spacing - Inter-child spacing in pixels.\n */\n private layoutPreferredMode(components: Component[], containerSize: Size, insets: Insets, spacing: number): void {\n const { totalWeight, fixedPreferred, fixedMin } = this.measureFixedWidths(components, spacing);\n\n const { remaining: remainingWidth, shrinkRatio } = this.computeShrink(\n fixedPreferred,\n fixedMin,\n containerSize.width,\n this.isOverflowingX()\n );\n\n const widths: number[] = [];\n const heights: number[] = [];\n const baselines: Array<number | null> = [];\n\n for (const component of components) {\n const weight = this.getLayoutConstraints(component)?.weight ?? 0;\n const size = component.getPreferredSize();\n const minSize = component.getMinSize();\n const maxSize = component.getMaxSize();\n\n widths.push(this.resolveChildWidth(size, minSize, maxSize, weight, totalWeight, remainingWidth, shrinkRatio));\n\n // Cross-axis (height): give the child the row's available height —\n // the full inner height when stretching or sizeless, otherwise its\n // preferred height capped to the row. Cap to the child's maximum, but\n // do NOT floor to its minimum: enforcing the minimum here would\n // dogmatically inflate a child back up to its content size even when\n // the row is shorter, defeating a scrolling/clipping child. The\n // child's own setHeight → clampHeight applies its minimum (its\n // content minimum for a general component, or nothing for a Panel,\n // which fits its allocation and scrolls). When the host opts into\n // vertical scroll, `containerSize` is already inflated to the content\n // extent upstream, so `min(pref, containerSize)` still yields the full\n // height without a floor here.\n let height: number;\n\n if (!size || this.isStretching()) {\n height = containerSize.height;\n } else {\n height = Math.min(size.height, containerSize.height);\n }\n\n if (maxSize) {\n height = Math.min(height, maxSize.height);\n }\n\n heights.push(height);\n\n baselines.push(component.getBaseline());\n }\n\n // Stretching forces every child to fill the row vertically, which makes\n // baseline alignment meaningless — fall back to top-alignment. rowAscent\n // is driven only by text-bearing children; tall null-baseline children\n // (a List, TextArea, etc.) must NOT drag the baseline down or every text\n // label in the row would be pushed off the top.\n const { rowAscent, rowDescent } = this.isStretching()\n ? { rowAscent: null, rowDescent: 0 }\n : this.computeRowMetrics(heights, baselines);\n\n // Sum the placed main extents to find the trailing slack, then ask the\n // shared helper how to distribute it. Weight cells already consume all\n // slack, so justify is a no-op when any are present.\n let lead = 0;\n let gap = 0;\n\n if (totalWeight === 0) {\n let contentWidth = spacing * (components.length - 1);\n\n for (const w of widths) {\n contentWidth += w;\n }\n\n const innerWidth = containerSize.width - (insets.getLeft() + insets.getRight());\n\n ({ lead, gap } = this.justifyOffsets(contentWidth, innerWidth, components.length));\n }\n\n // Cross band for per-child align-self: the same vertical band the\n // stretch path fills, trimmed by both insets.\n const crossLead = insets.getTop();\n const crossExtent = containerSize.height - (insets.getTop() + insets.getBottom());\n\n let x = insets.getLeft() + lead;\n\n for (let idx = 0; idx < components.length; idx += 1) {\n const component = components[idx];\n\n // Align-self sizes from the child's *preferred* height (capped to the\n // band + max), independent of the stretch-inflated heights[idx], so an\n // anchored child shrinks-and-anchors even under global stretching.\n const pref = component.getPreferredSize();\n const maxSize = component.getMaxSize();\n let naturalCross = pref ? Math.min(pref.height, crossExtent) : crossExtent;\n\n if (maxSize) {\n naturalCross = Math.min(naturalCross, maxSize.height);\n }\n\n const cross = this.crossPlacement(component, crossLead, crossExtent, naturalCross, true);\n\n if (cross) {\n this.placeComponent(component, x, cross.offset, widths[idx], cross.extent, FillType.BOTH);\n } else {\n const y = this.rowChildY(insets.getTop(), heights[idx], baselines[idx], rowAscent, rowDescent);\n\n this.placeComponent(component, x, y, widths[idx], heights[idx], FillType.BOTH);\n }\n\n // Advance by the resolved width, not getWidth(): the gap is measured\n // against the same extent contentWidth summed, so a placeComponent\n // clamp must not skew the trailing edge.\n x += widths[idx];\n x += spacing + gap;\n }\n }\n\n /**\n * Sums the non-weighted children's preferred and minimum widths (each\n * including inter-child spacing) and the total weight of the weight cells.\n *\n * @param components - The children sharing the row.\n * @param spacing - Inter-child spacing in pixels.\n * @returns `totalWeight` of the weight cells, plus the `fixedPreferred` and\n * `fixedMin` width totals of the non-weighted children.\n */\n private measureFixedWidths(components: Component[], spacing: number): { totalWeight: number; fixedPreferred: number; fixedMin: number } {\n let totalWeight = 0;\n let fixedPreferred = spacing * (components.length - 1);\n let fixedMin = spacing * (components.length - 1);\n\n for (const component of components) {\n const weight = this.getLayoutConstraints(component)?.weight ?? 0;\n\n if (weight > 0) {\n totalWeight += weight;\n } else {\n const size = component.getPreferredSize();\n const minSize = component.getMinSize();\n\n fixedPreferred += this.preferredChildWidth(size, minSize);\n fixedMin += minSize ? minSize.width : 0;\n }\n }\n\n return { totalWeight, fixedPreferred, fixedMin };\n }\n\n /**\n * Resolves a non-weighted child's preferred width, falling back through min\n * width to `_defaultComponentWidth`.\n *\n * @param size - The child's preferred size, or `null`.\n * @param minSize - The child's minimum size, or `null`.\n * @returns The width the child contributes before shrinking.\n *\n * @remarks Nullish-coalesce, not `||`: a component with an explicit\n * preferred width of 0 (e.g. an empty `Text` label) must contribute 0, not\n * fall through to `_defaultComponentWidth` and inflate the row's fixed total\n * past the container, which would force the shrink path to squeeze every\n * non-weighted child (including glyphs) toward its min size. The\n * `minSize.width > 0` guard prevents `LayoutManager._defaultMinSize =\n * {0,0}` from short-circuiting the chain into a 0 width (which would land a\n * layout-managed Table on width 0 even though no preferred size was set).\n *\n * The result is floored at the child's own min width: a child placed at\n * `max(preferred, min)` (see {@link HBox.resolveChildWidth}) must reserve\n * that same width in the fixed total, or a child reporting `preferred < min`\n * (a `min ≤ preferred` invariant violation) would be under-reserved and push\n * the weighted cells out, overflowing the row.\n */\n private preferredChildWidth(size: Size | null, minSize: Size | null): number {\n const preferred = (size ? size.width : undefined)\n ?? (minSize && minSize.width > 0 ? minSize.width : undefined)\n ?? this._defaultComponentWidth;\n\n return minSize ? Math.max(preferred, minSize.width) : preferred;\n }\n\n /**\n * Resolves a child's final width within the row, clamped to its min/max —\n * the minimum wins when the two conflict. Weight cells take a share of\n * `remainingWidth`; non-weighted children take their preferred width\n * reduced by the shrink ratio toward their min width.\n *\n * @param size - The child's preferred size, or `null`.\n * @param minSize - The child's minimum size, or `null`.\n * @param maxSize - The child's maximum size, or `null`.\n * @param weight - The child's weight constraint (0 when non-weighted).\n * @param totalWeight - The summed weight of all weight cells.\n * @param remainingWidth - The space available to weight cells.\n * @param shrinkRatio - How far (0–1) non-weighted children shrink to min.\n * @returns The child's width.\n */\n private resolveChildWidth(size: Size | null, minSize: Size | null, maxSize: Size | null, weight: number, totalWeight: number, remainingWidth: number, shrinkRatio: number): number {\n let width: number;\n\n if (weight > 0 && totalWeight > 0) {\n width = (weight / totalWeight) * remainingWidth;\n } else {\n const pref = this.preferredChildWidth(size, minSize);\n const min = minSize ? minSize.width : 0;\n\n width = pref - shrinkRatio * (pref - min);\n }\n\n if (maxSize) {\n width = Math.min(width, maxSize.width);\n }\n\n if (minSize) {\n width = Math.max(width, minSize.width);\n }\n\n return width;\n }\n\n /**\n * Computes a child's y within the row, aligning text-bearing children on the\n * shared baseline and centring null-baseline children in the text line.\n *\n * @param top - The row's content-top (inside the insets).\n * @param height - The child's height.\n * @param baseline - The child's baseline, or `null` for graphical/replaced children.\n * @param rowAscent - The row's text baseline, or `null` when no child reports one.\n * @param rowDescent - The row's text descent.\n * @returns The child's y position.\n */\n private rowChildY(top: number, height: number, baseline: number | null, rowAscent: number | null, rowDescent: number): number {\n if (rowAscent === null) {\n return top;\n }\n\n if (baseline !== null) {\n return top + (rowAscent - baseline);\n }\n\n return top + this.nullChildY(height, rowAscent, rowDescent);\n }\n}\n\nconst HBoxCallable = callable(HBox);\ntype HBoxCallable = HBox;\nexport {\n HBox as _HBox,\n HBoxCallable as HBox\n};\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { FillType } from \"~/layout/FillType.js\";\nimport { Size, UNBOUNDED, isUnbounded } from \"~/primitive/Size.js\";\nimport { Insets } from \"~/primitive/Insets.js\";\nimport { Component } from \"~/core/Component.js\";\nimport { BoxLayout, BoxLayoutOptions } from \"~/layout/BoxLayout.js\";\nimport { callable } from \"~/core/Callable.js\";\n\n/**\n * Construction-time options for {@link VBox}.\n *\n * @remarks `mode` selects the sizing strategy along the vertical axis.\n * `\"preferred\"` (the default) honours each child's preferred height and\n * supports `weight` cells. `\"equal\"` divides the container height equally\n * and ignores `weight`. `mode` is independent of `stretching` (the cross-axis\n * fill): `stretching` defaults to `false` in both modes, so `\"equal\"` divides\n * the height but leaves children at their preferred width unless\n * `stretching: true` is passed.\n *\n * @category Layouts\n */\nexport interface VBoxOptions extends BoxLayoutOptions {}\n\n/**\n * A layout manager that places children in a single vertical column. The\n * `mode` option selects between preferred-height sequencing (with weight-cell\n * support) and equal-height division of the container.\n *\n * @category Layouts\n */\nclass VBox extends BoxLayout {\n\n private _defaultComponentHeight: number = 100;\n\n /**\n * Returns the column's baseline — the first laid-out child's baseline,\n * measured from the container's content-top — so a baseline-aware parent\n * aligns this VBox container by its first row's text baseline rather than\n * auto-centring the whole container.\n *\n * @returns The first child's baseline offset in pixels, or `null` when there\n * is no container, no laid-out children, or the first child reports no\n * baseline of its own.\n *\n * @remarks Forwards the **first** child's baseline verbatim — unlike\n * {@link HBox}, which takes the maximum baseline across the row's children.\n * A column has a single well-defined first row, so forwarding it (including\n * a `null` when that first row is graphical) is the most predictable\n * contract. The first child stacks at the container's content-top in every\n * mode, so its own baseline is already content-relative — `Component`'s\n * `getBaseline` then adds the container's chrome. Unlike `HBox`, this is not\n * disabled while stretching: VBox `stretching` fills the cross (width) axis\n * and leaves each child's height and intrinsic baseline untouched.\n */\n getContentBaseline(): number | null {\n const container = this.getContainer();\n if (!container) {\n return null;\n }\n\n const components = container.getLaidOutComponents();\n if (components.length === 0) {\n return null;\n }\n\n return components[0].getBaseline();\n }\n\n /**\n * Returns the preferred size. In `\"preferred\"` mode this is the widest\n * child width and the sum of child heights plus spacing. In `\"equal\"`\n * mode height is `count * (maxChildHeight + spacing) - spacing`.\n *\n * @returns The preferred `{width, height}`, or `null` if no container is attached.\n */\n getPreferredSize(): Size | null {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let perimeterSize = container.getPerimeterSize();\n let components = container.getLaidOutComponents();\n\n if (this._mode === \"equal\") {\n let innerWidth = 0;\n let innerHeight = 0;\n\n for (let idx in components) {\n let component = components[idx];\n let size = component.getPreferredSize();\n\n if (size) {\n innerWidth = Math.max(innerWidth, size.width);\n innerHeight = Math.max(innerHeight, size.height);\n }\n }\n\n const width = innerWidth + perimeterSize.left + perimeterSize.right;\n const height = components.length * (innerHeight + this._spacing) - this._spacing\n + perimeterSize.top + perimeterSize.bottom;\n\n return { width, height };\n }\n\n let width = UNBOUNDED;\n let height = perimeterSize.top + perimeterSize.bottom;\n\n for (let idx in components) {\n let component = components[idx];\n let size = component.getPreferredSize();\n\n if (size) {\n width = isUnbounded(width) ? Math.min(width, size.width) : Math.max(width, size.width);\n height += size.height;\n }\n }\n\n width += perimeterSize.left + perimeterSize.right;\n height += this._spacing * (components.length - 1);\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the minimum size. In `\"preferred\"` mode this is the widest\n * child minimum width and the sum of child minimum heights plus\n * spacing. In `\"equal\"` mode height is\n * `count * (maxChildMinHeight + spacing) - spacing`.\n *\n * @returns The minimum `{width, height}`, or `null` if no container is attached.\n */\n getMinSize(): Size | null {\n let container = this.getContainer();\n if (!container) {\n return null;\n }\n\n let perimeterSize = container.getPerimeterSize();\n let components = container.getLaidOutComponents();\n\n if (this._mode === \"equal\") {\n let innerWidth = 0;\n let innerHeight = 0;\n\n for (let idx in components) {\n let component = components[idx];\n let size = component.getMinSize();\n\n if (size) {\n innerWidth = Math.max(innerWidth, size.width);\n innerHeight = Math.max(innerHeight, size.height);\n }\n }\n\n const width = innerWidth + perimeterSize.left + perimeterSize.right;\n const height = components.length * (innerHeight + this._spacing) - this._spacing\n + perimeterSize.top + perimeterSize.bottom;\n\n return { width, height };\n }\n\n let width = 0;\n let height = perimeterSize.top + perimeterSize.bottom;\n\n for (let idx in components) {\n let component = components[idx];\n let size = component.getMinSize();\n\n if (size) {\n width = Math.max(width, size.width);\n height += size.height;\n }\n }\n\n width += perimeterSize.left + perimeterSize.right;\n height += this._spacing * (components.length - 1);\n\n return {\n width: width,\n height: height\n };\n }\n\n /**\n * Returns the maximum size the column can usefully occupy. Along the main\n * axis (height) it sums the children's *maximum* heights plus spacing; in\n * `\"equal\"` mode it is `count * maxChildMaxHeight` plus spacing, since every\n * cell shares the tallest child's allowance. The cross axis (width) takes\n * the *largest* child maximum — the widest a child permits the column to\n * grow to. A child whose maximum is `null` or at the unbounded sentinel\n * makes that axis unbounded.\n *\n * @returns The maximum `{width, height}`, or `null` if no container is attached.\n */\n getMaxSize(): Size | null {\n return this.aggregateMaxSize(false);\n }\n\n /**\n * Computes the children's combined minSize along this manager's geometry.\n * In `\"preferred\"` mode height is the sum of per-child `minSize.height`\n * plus spacing. In `\"equal\"` mode height is\n * `count * maxChildMinHeight + spacing*(n-1)` (VBox distributes height\n * equally so the per-cell floor is the max of every child's min height).\n * Width in both modes is the max per-child `minSize.width`. Used by\n * `doLayout` to inflate the working size when the host has opted into\n * `setOverflowing` on the corresponding axis.\n *\n * @returns The total min-size; `{ width: 0, height: 0 }` when the\n * container is absent or has no children.\n */\n protected computeTotalMinSize(): Size {\n const container = this.getContainer();\n if (!container) {\n return { width: 0, height: 0 };\n }\n\n const components = container.getLaidOutComponents();\n if (components.length === 0) {\n return { width: 0, height: 0 };\n }\n\n let width = 0;\n\n if (this._mode === \"equal\") {\n let maxHeight = 0;\n\n for (const component of components) {\n const min = component.getMinSize();\n if (min) {\n width = Math.max(width, min.width);\n maxHeight = Math.max(maxHeight, min.height);\n }\n }\n\n return {\n width,\n height: components.length * (maxHeight + this._spacing) - this._spacing,\n };\n }\n\n let height = this._spacing * (components.length - 1);\n\n for (const component of components) {\n const min = component.getMinSize();\n if (min) {\n width = Math.max(width, min.width);\n height += min.height;\n }\n }\n\n return { width, height };\n }\n\n /**\n * Lays out the children top-to-bottom, dispatching to `layoutEqualMode` or\n * `layoutPreferredMode` per the sizing mode after inflating the working\n * size for any scroll-enabled axis.\n */\n doLayout(): void {\n const container = this.getContainer();\n if (!container) {\n return;\n }\n\n const innerSize = container.getInnerSize();\n if (!innerSize) {\n return;\n }\n\n const components = container.getLaidOutComponents();\n const containerInsets = container.getContentInsets();\n const spacing = this.getComponentSpacing();\n\n // Universal scroll: when the host has opted into per-axis overflow, lay\n // out against the children's combined minSize so trailing children land\n // past the viewport and the host's CSS `overflow: auto` scrolls.\n // `innerSize` stays the real viewport for equal mode's overflow test.\n const containerSize = this.inflateForOverflow(innerSize);\n\n if (this._mode === \"equal\") {\n this.layoutEqualMode(components, innerSize, containerSize, containerInsets, spacing);\n } else {\n this.layoutPreferredMode(components, containerSize, containerInsets, spacing);\n }\n\n this.reserveContentFrame();\n }\n\n /**\n * Places children in equal-height cells stacked top-to-bottom. Every cell\n * takes the same height (see {@link VBox.computeEqualCellHeight}); when\n * stretching, cells fill the container width, otherwise children keep their\n * preferred width and are left-aligned within the column.\n *\n * @param components - The children to place, in order.\n * @param innerSize - The host's real inner size (pre-inflation), used to\n * measure the equal share against the true viewport.\n * @param containerSize - The working size, possibly inflated for overflow.\n * @param insets - The container's content insets.\n * @param spacing - Inter-child spacing in pixels.\n */\n private layoutEqualMode(components: Component[], innerSize: Size, containerSize: Size, insets: Insets, spacing: number): void {\n const cellHeight = this.computeEqualCellHeight(components, innerSize.height, spacing);\n\n const x = insets.getLeft();\n let y = insets.getTop();\n\n if (this.isStretching()) {\n const cellWidth = containerSize.width;\n\n for (const component of components) {\n this.placeComponent(component, x, y, cellWidth, cellHeight, FillType.BOTH);\n\n y += cellHeight + spacing;\n }\n\n return;\n }\n\n // Match the equal-stretch band exactly: the stretch branch fills\n // containerSize.width from insets.left with no right-inset subtraction,\n // so an EAST/fill align-self child reaches the same trailing edge.\n const crossLead = insets.getLeft();\n const crossExtent = containerSize.width;\n\n for (const component of components) {\n const size = component.getPreferredSize();\n const width = size ? size.width : 0;\n\n const cross = this.crossPlacement(component, crossLead, crossExtent, width, false);\n\n if (cross) {\n this.placeComponent(component, cross.offset, y, cross.extent, cellHeight, FillType.BOTH);\n } else {\n this.placeComponent(component, x, y, width, cellHeight, FillType.BOTH);\n }\n\n y += cellHeight + spacing;\n }\n }\n\n /**\n * Computes the shared cell height for equal mode: the equal share of the\n * inner height, floored at the tallest child's min height.\n *\n * @param components - The children sharing the column.\n * @param innerHeight - The host's real inner height (pre-inflation).\n * @param spacing - Inter-child spacing in pixels.\n * @returns The height every equal-mode cell receives.\n *\n * @remarks Three cases drive the floor: (1) the share clears the tallest\n * child's min height → the column fits, divide equally; (2) the share is\n * below the min floor, the host scrolls on this axis, and `overflowSizing`\n * is `\"preferred\"` → every cell takes the tallest child's preferred height\n * so cells regain preferred size instead of sticking at min while\n * scrolling; (3) otherwise → clamp to the min floor (a non-scrolling host's\n * `overflow: hidden` clips the surplus).\n */\n private computeEqualCellHeight(components: Component[], innerHeight: number, spacing: number): number {\n let maxChildMinHeight = 0;\n let maxChildPreferredHeight = 0;\n\n for (const component of components) {\n const min = component.getMinSize();\n if (min) {\n maxChildMinHeight = Math.max(maxChildMinHeight, min.height);\n }\n\n const pref = component.getPreferredSize();\n if (pref) {\n maxChildPreferredHeight = Math.max(maxChildPreferredHeight, pref.height);\n }\n }\n\n const equalShare = (innerHeight - spacing * (components.length - 1)) / components.length;\n\n if (equalShare >= maxChildMinHeight) {\n return equalShare;\n }\n\n if (this.isOverflowingY() && this._overflowSizing === \"preferred\") {\n return Math.max(maxChildMinHeight, maxChildPreferredHeight);\n }\n\n return maxChildMinHeight;\n }\n\n /**\n * Places children at their preferred heights stacked top-to-bottom. Weight\n * cells split the space left after the non-weighted children; when the\n * column overflows, the non-weighted children shrink proportionally toward\n * their min heights. Children keep their preferred width, or fill the\n * container width when stretching.\n *\n * @param components - The children to place, in order.\n * @param containerSize - The working size, possibly inflated for overflow.\n * @param insets - The container's content insets.\n * @param spacing - Inter-child spacing in pixels.\n */\n private layoutPreferredMode(components: Component[], containerSize: Size, insets: Insets, spacing: number): void {\n const { totalWeight, fixedPreferred, fixedMin } = this.measureFixedHeights(components, spacing);\n\n const { remaining: remainingHeight, shrinkRatio } = this.computeShrink(\n fixedPreferred,\n fixedMin,\n containerSize.height,\n this.isOverflowingY()\n );\n\n // Pre-pass: resolve each child's height into an array so the trailing\n // slack can be measured before placement (mirrors HBox's widths[]).\n const heights: number[] = [];\n\n for (const component of components) {\n const weight = this.getLayoutConstraints(component)?.weight ?? 0;\n const size = component.getPreferredSize();\n const minSize = component.getMinSize();\n const maxSize = component.getMaxSize();\n\n heights.push(this.resolveChildHeight(size, minSize, maxSize, weight, totalWeight, remainingHeight, shrinkRatio));\n }\n\n // Sum the placed main extents to find the trailing slack, then ask the\n // shared helper how to distribute it. Weight cells already consume all\n // slack, so justify is a no-op when any are present.\n let lead = 0;\n let gap = 0;\n\n if (totalWeight === 0) {\n let contentHeight = spacing * (components.length - 1);\n\n for (const h of heights) {\n contentHeight += h;\n }\n\n const innerHeight = containerSize.height - (insets.getTop() + insets.getBottom());\n\n ({ lead, gap } = this.justifyOffsets(contentHeight, innerHeight, components.length));\n }\n\n // Cross band for per-child align-self: the horizontal band trimmed by\n // both insets. The default path keeps reading containerSize.width\n // (un-trimmed) to stay byte-identical with today's body.\n const crossLead = insets.getLeft();\n const crossExtent = containerSize.width - (insets.getLeft() + insets.getRight());\n\n const x = insets.getLeft();\n let y = insets.getTop() + lead;\n\n for (let idx = 0; idx < components.length; idx += 1) {\n const component = components[idx];\n const size = component.getPreferredSize();\n const maxSize = component.getMaxSize();\n\n // Cross-axis (width): give the child the column's available width —\n // the full inner width when stretching or sizeless, otherwise its\n // preferred width capped to the column. Cap to the child's maximum,\n // but do NOT floor to its minimum: enforcing the minimum here would\n // dogmatically inflate a child back up to its content size even when\n // the column is narrower, defeating a scrolling/clipping child. The\n // child's own setWidth → clampWidth applies its minimum (its content\n // minimum for a general component, or nothing for a Panel, which fits\n // its allocation and scrolls). When the host opts into horizontal\n // scroll, `containerSize` is already inflated to the content extent\n // upstream, so `min(pref, containerSize)` still yields the full width\n // without a floor here.\n let defaultWidth: number;\n\n if (!size || this.isStretching()) {\n defaultWidth = containerSize.width;\n } else {\n defaultWidth = Math.min(size.width, containerSize.width);\n }\n\n if (maxSize) {\n defaultWidth = Math.min(defaultWidth, maxSize.width);\n }\n\n // Align-self sizes from the child's *preferred* width (capped to the\n // band + max), independent of global stretching, so an anchored child\n // shrinks-and-anchors even when the column is stretching.\n let naturalWidth = size ? Math.min(size.width, crossExtent) : crossExtent;\n\n if (maxSize) {\n naturalWidth = Math.min(naturalWidth, maxSize.width);\n }\n\n const cross = this.crossPlacement(component, crossLead, crossExtent, naturalWidth, false);\n\n if (cross) {\n this.placeComponent(component, cross.offset, y, cross.extent, heights[idx], FillType.BOTH);\n } else {\n this.placeComponent(component, x, y, defaultWidth, heights[idx], FillType.BOTH);\n }\n\n // Advance by the resolved height, not getHeight(): the gap is\n // measured against the same extent contentHeight summed, so a\n // placeComponent clamp must not skew the trailing edge.\n y += heights[idx];\n y += spacing + gap;\n }\n }\n\n /**\n * Sums the non-weighted children's preferred and minimum heights (each\n * including inter-child spacing) and the total weight of the weight cells.\n *\n * @param components - The children sharing the column.\n * @param spacing - Inter-child spacing in pixels.\n * @returns `totalWeight` of the weight cells, plus the `fixedPreferred` and\n * `fixedMin` height totals of the non-weighted children.\n */\n private measureFixedHeights(components: Component[], spacing: number): { totalWeight: number; fixedPreferred: number; fixedMin: number } {\n let totalWeight = 0;\n let fixedPreferred = spacing * (components.length - 1);\n let fixedMin = spacing * (components.length - 1);\n\n for (const component of components) {\n const weight = this.getLayoutConstraints(component)?.weight ?? 0;\n\n if (weight > 0) {\n totalWeight += weight;\n } else {\n const size = component.getPreferredSize();\n const minSize = component.getMinSize();\n\n fixedPreferred += this.preferredChildHeight(size, minSize);\n fixedMin += minSize ? minSize.height : 0;\n }\n }\n\n return { totalWeight, fixedPreferred, fixedMin };\n }\n\n /**\n * Resolves a non-weighted child's preferred height, falling back through min\n * height to `_defaultComponentHeight`.\n *\n * @param size - The child's preferred size, or `null`.\n * @param minSize - The child's minimum size, or `null`.\n * @returns The height the child contributes before shrinking.\n *\n * @remarks Nullish-coalesce, not `||`: a component with an explicit\n * preferred height of 0 must contribute 0, not fall through to\n * `_defaultComponentHeight`. The `minSize.height > 0` guard prevents\n * `LayoutManager._defaultMinSize = {0,0}` from short-circuiting the chain\n * into a 0 height (which would land a layout-managed Table on a 0 height\n * even though no preferred size was set).\n *\n * The result is floored at the child's own min height: a child placed at\n * `max(preferred, min)` (see {@link VBox.resolveChildHeight}) must reserve\n * that same height in the fixed total, or a child reporting `preferred < min`\n * (a `min ≤ preferred` invariant violation) would be under-reserved and push\n * the weighted cells out, overflowing the column.\n */\n private preferredChildHeight(size: Size | null, minSize: Size | null): number {\n const preferred = (size ? size.height : undefined)\n ?? (minSize && minSize.height > 0 ? minSize.height : undefined)\n ?? this._defaultComponentHeight;\n\n return minSize ? Math.max(preferred, minSize.height) : preferred;\n }\n\n /**\n * Resolves a child's final height within the column, clamped to its\n * min/max — the minimum wins when the two conflict. Weight cells take a\n * share of `remainingHeight`; non-weighted children take their preferred\n * height reduced by the shrink ratio toward their min height.\n *\n * @param size - The child's preferred size, or `null`.\n * @param minSize - The child's minimum size, or `null`.\n * @param maxSize - The child's maximum size, or `null`.\n * @param weight - The child's weight constraint (0 when non-weighted).\n * @param totalWeight - The summed weight of all weight cells.\n * @param remainingHeight - The space available to weight cells.\n * @param shrinkRatio - How far (0–1) non-weighted children shrink to min.\n * @returns The child's height.\n */\n private resolveChildHeight(size: Size | null, minSize: Size | null, maxSize: Size | null, weight: number, totalWeight: number, remainingHeight: number, shrinkRatio: number): number {\n let height: number;\n\n if (weight > 0 && totalWeight > 0) {\n height = (weight / totalWeight) * remainingHeight;\n } else {\n const pref = this.preferredChildHeight(size, minSize);\n const min = minSize ? minSize.height : 0;\n\n height = pref - shrinkRatio * (pref - min);\n }\n\n if (maxSize) {\n height = Math.min(height, maxSize.height);\n }\n\n if (minSize) {\n height = Math.max(height, minSize.height);\n }\n\n return height;\n }\n}\n\nconst VBoxCallable = callable(VBox);\ntype VBoxCallable = VBox;\nexport {\n VBox as _VBox,\n VBoxCallable as VBox\n};\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{t as e}from"./DOM-67StIm5G.js";import{l as t}from"./Position-Ck_KD4cR.js";import{S as n,_ as r,g as i}from"./Component-fRQvgaEY.js";import{i as a,n as o,r as s,t as c}from"./Scrollbar-SOj9psiP.js";var VirtualScroller=class{_owner;_onScroll;_clipBox;_rowsContainer;_scrollbarV;_scrollbarH;_scrollX=0;_scrollY=0;_contentWidth=0;_contentHeight=0;_smooth;_shadowOverlay;_shadowEdges={top:0,bottom:0,left:0,right:0};constructor(t,r,a){this._owner=t,this._onScroll=a;let s=e.sink.createElement(`div`);e.sink.apply(s,{style:{position:`absolute`,top:`0`,left:`0`,width:`100%`,height:`100%`,overflow:`hidden`}}),e.sink.appendChild(r,s),this._clipBox=s;let l=e.sink.createElement(`div`);e.sink.apply(l,{style:{position:`absolute`,top:`0`,left:`0`,width:`100%`,transform:`translate3d(0, 0, 0)`,willChange:`transform`}}),e.sink.appendChild(s,l),this._rowsContainer=l;let u=e.sink.createElement(`div`);e.sink.apply(u,{style:{position:`absolute`,top:`0`,left:`0`,width:`100%`,height:`100%`,pointerEvents:`none`,boxShadow:o()}}),e.sink.appendChild(s,u),this._shadowOverlay=u,this._smooth=new i({read:e=>e===`x`?this._scrollX:this._scrollY,write:(e,t)=>e===`x`?this.setScrollX(t):this.setScrollY(t),clamp:(e,t)=>this.clampAxis(e,t)}),this._scrollbarV=new c(`vertical`),e.sink.appendChild(r,this._scrollbarV.getElement(!0)),this._scrollbarV.on(`scroll`,e=>{this._smooth.reset(),this.setScrollY(e)}),this._scrollbarH=new c(`horizontal`),e.sink.appendChild(r,this._scrollbarH.getElement(!0)),this._scrollbarH.on(`scroll`,e=>{this._smooth.reset(),this.setScrollX(e)}),this._owner.setTouchAction(`none`),n.addSubtreeListener(this._owner,`wheel`,e=>this.onWheel(e),{passive:!1}),this.attachTouchHandlers()}dispose(){this._scrollbarV.dispose(),this._scrollbarH.dispose()}ownedHandles(){return[this._clipBox,this._rowsContainer,this._shadowOverlay]}getRowsContainer(){return this._rowsContainer}getScrollY(){return this._scrollY}getScrollX(){return this._scrollX}setScrollY(e){let n=Math.max(0,this._contentHeight-this.effectiveViewportH()),r=t.clamp(e,0,n);return r===this._scrollY?this:(this._scrollY=r,this.updateTransform(),this._onScroll(),this)}setScrollX(e){let n=Math.max(0,this._contentWidth-this.effectiveViewportW()),r=t.clamp(e,0,n);return r===this._scrollX?this:(this._scrollX=r,this.updateTransform(),this._onScroll(),this)}clampAxis(e,n){let r=e===`x`?Math.max(0,this._contentWidth-this.effectiveViewportW()):Math.max(0,this._contentHeight-this.effectiveViewportH());return t.clamp(n,0,r)}resetWheelEase(){this._smooth.reset()}computeScrollbarVisibility(e,t){let n=this._owner.getContentBounds()??{x:0,y:0,width:this._owner.getWidth()||0,height:this._owner.getHeight()||0},r=n.height||0,i=n.width||0,a=this._scrollbarV.getTrackWidth(),o=!1,s=!1;for(let n=0;n<2;n++){let n=r-(s?a:0),c=i-(o?a:0);o=t>n,s=e>c}let c=r-(s?a:0),l=i-(o?a:0);return{vVisible:o,hVisible:s,effW:l,effH:c}}effectiveViewportH(){return this.computeScrollbarVisibility(this._contentWidth,this._contentHeight).effH}effectiveViewportW(){return this.computeScrollbarVisibility(this._contentWidth,this._contentHeight).effW}getViewportWidth(){return this.effectiveViewportW()}clampToContent(e,t){this._contentWidth=e,this._contentHeight=t;let n=Math.max(0,t-this.effectiveViewportH()),r=Math.max(0,e-this.effectiveViewportW()),i=!1;this._scrollY>n&&(this._scrollY=n,i=!0),this._scrollX>r&&(this._scrollX=r,i=!0),i&&this.updateTransform()}layoutScrollbars(t,n){this._contentWidth=t,this._contentHeight=n;let r=this._owner.getContentBounds()??{x:0,y:0,width:this._owner.getWidth()||0,height:this._owner.getHeight()||0},i=this._scrollbarV.getTrackWidth(),{effW:a,effH:o}=this.computeScrollbarVisibility(t,n),s=Math.max(0,n-o),c=Math.max(0,t-a);(this._scrollY>s||this._scrollX>c)&&(this._scrollY>s&&(this._scrollY=s),this._scrollX>c&&(this._scrollX=c),this.updateTransform()),this._scrollbarV.setX(r.x+Math.max(0,r.width-i)),this._scrollbarV.setY(r.y),this._scrollbarV.setHeight(o),this._scrollbarV.setMetrics(o,n,this._scrollY),this._scrollbarH.setX(r.x),this._scrollbarH.setY(r.y+Math.max(0,r.height-i)),this._scrollbarH.setWidth(a),this._scrollbarH.setMetrics(a,t,this._scrollX),e.sink.apply(this._clipBox,{style:{left:r.x+`px`,top:r.y+`px`,width:a+`px`,height:o+`px`}}),this.updateShadows()}updateTransform(){e.sink.apply(this._rowsContainer,{style:{transform:`translate3d(${-this._scrollX}px, ${-this._scrollY}px, 0)`}}),this.updateShadows()}updateShadows(){let{effW:e,effH:t}=this.computeScrollbarVisibility(this._contentWidth,this._contentHeight),n=Math.max(0,this._contentWidth-e),r=Math.max(0,this._contentHeight-t);this.setShadowEdge(`top`,`--ts-ss-top`,a(this._scrollY)),this.setShadowEdge(`bottom`,`--ts-ss-bottom`,a(r-this._scrollY)),this.setShadowEdge(`left`,`--ts-ss-left`,a(this._scrollX)),this.setShadowEdge(`right`,`--ts-ss-right`,a(n-this._scrollX))}setShadowEdge(t,n,r){let i=Math.round(r*100);this._shadowEdges[t]!==i&&(this._shadowEdges[t]=i,e.sink.apply(this._shadowOverlay,{style:{[n]:s(i)}}))}onWheel(e){if(r(e)){if(e.preventDefault(),e.shiftKey&&e.deltaY!==0&&e.deltaX===0){this._smooth.scrollBy(e.deltaY,0);return}this._smooth.scrollBy(e.deltaX,e.deltaY)}}attachTouchHandlers(){let t=!1,r=0,i=0,a=0,o=0,s=[],c=null,cancelMomentum=()=>{c!==null&&(e.sink.cancelAnimationFrame(c),c=null)};n.addSubtreeListener(this._owner,`touchstart`,e=>{e.touches.length===1&&(cancelMomentum(),this._smooth.reset(),t=!0,r=e.touches[0].clientY,i=e.touches[0].clientX,a=this._scrollY,o=this._scrollX,s=[{time:performance.now(),x:i,y:r}])}),n.addSubtreeListener(this._owner,`touchmove`,e=>{if(!t||e.touches.length!==1)return;let n=e.touches[0].clientY,c=e.touches[0].clientX,l=performance.now();for(s.push({time:l,x:c,y:n});s.length>1&&s[0].time<l-150;)s.shift();this.setScrollY(a+(r-n)),this.setScrollX(o+(i-c))});let startMomentum=()=>{if(s.length<2)return;let t=s[s.length-1];if(performance.now()-t.time>50)return;let n=t.time-80,r=s.length-1;for(;r>0&&s[r-1].time>=n;)r--;let i=s[r],a=t.time-i.time;if(a<=0)return;let o=(i.y-t.y)/a,l=(i.x-t.x)/a;if(Math.sqrt(l*l+o*o)<.1)return;let u=performance.now(),step=()=>{let t=performance.now(),n=t-u;u=t;let r=.95**(n/16.667);if(o*=r,l*=r,Math.sqrt(l*l+o*o)<.02){c=null;return}let i=this._scrollY,a=this._scrollX;if(this.setScrollY(this._scrollY+o*n),this.setScrollX(this._scrollX+l*n),this._scrollY===i&&(o=0),this._scrollX===a&&(l=0),o===0&&l===0){c=null;return}c=e.sink.requestAnimationFrame(step)};c=e.sink.requestAnimationFrame(step)};n.addSubtreeListener(this._owner,`touchend`,()=>{t&&(t=!1,startMomentum())}),n.addSubtreeListener(this._owner,`touchcancel`,()=>{t=!1,cancelMomentum()})}};export{VirtualScroller as t};
2
- //# sourceMappingURL=VirtualScroller-Bv4KXGKW.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"VirtualScroller-Bv4KXGKW.js","names":[],"sources":["../../src/typescript/lib/component/container/VirtualScroller.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component } from \"~/core/Component.js\";\nimport { Util } from \"~/core/Util.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { Event } from \"~/core/Event.js\";\nimport { SmoothScroller, consumeWheel } from \"~/core/SmoothScroller.js\";\nimport { Scrollbar } from \"~/component/container/Scrollbar.js\";\nimport { scrollShadowBoxShadow, scrollShadowEdgeValue, scrollShadowRamp } from \"~/core/ScrollShadow.js\";\n\n/** Per-edge scroll-shadow strength cache, quantised to a whole percent (0–100). */\ntype ScrollShadowEdges = { top: number; bottom: number; left: number; right: number };\n\n// VirtualScroller is a plain helper, not a Component: it owns and lays out raw\n// `clipBox` / `rowsContainer` `HTMLElement`s it creates directly, so the\n// Component style setters don't apply and direct `.style` writes are correct.\n\n/**\n * Callback fired by {@link VirtualScroller} whenever the scroll position\n * changes via user input (wheel, touch, momentum, scrollbar). The owner\n * should re-render its visible window in response.\n *\n * @category Components\n */\nexport type VirtualScrollerOnScroll = () => void;\n\n/**\n * Shared scroll machinery for transform-based virtual lists (e.g. table body,\n * tree). Owns the rows-container element, two custom {@link Scrollbar} overlays\n * (vertical + horizontal), and the wheel/touch handlers with 2-axis fling\n * momentum.\n *\n * The owner component:\n * 1. Constructs a VirtualScroller from its `init()` with the owner element and\n * a callback that re-renders the visible window.\n * 2. Appends pool rows into {@link getRowsContainer}.\n * 3. Reads {@link getScrollX} / {@link getScrollY} to determine the visible window.\n * 4. Calls {@link clampToContent} at the start of `renderWindow` (so scroll\n * positions are sane before being used).\n * 5. Calls {@link layoutScrollbars} at the end of `renderWindow` with the\n * current content sizes; the scroller applies the final clamp and positions\n * the scrollbars.\n *\n * @category Components\n */\nexport class VirtualScroller {\n\n private _owner : Component;\n private _onScroll : VirtualScrollerOnScroll;\n private _clipBox : Handle;\n private _rowsContainer : Handle;\n private _scrollbarV : Scrollbar;\n private _scrollbarH : Scrollbar;\n private _scrollX : number = 0;\n private _scrollY : number = 0;\n private _contentWidth : number = 0;\n private _contentHeight : number = 0;\n private _smooth : SmoothScroller;\n private _shadowOverlay : Handle;\n private _shadowEdges : ScrollShadowEdges = { top: 0, bottom: 0, left: 0, right: 0 };\n\n /**\n * Constructs a VirtualScroller and attaches it to the owner element.\n *\n * @param owner - The component being scrolled (used for `getContentBounds`).\n * @param element - The owner's root DOM element. Must already exist; call\n * this from the owner's `init()` after `super.init(element)`.\n * @param onScroll - Callback invoked when scroll position changes via\n * user input.\n */\n constructor(owner: Component, element: Handle, onScroll: VirtualScrollerOnScroll) {\n this._owner = owner;\n this._onScroll = onScroll;\n\n // Two-element wrapper: the outer `clipBox` carries `overflow:hidden`\n // sized to the effective viewport so the Scrollbar widgets — positioned\n // by `layoutScrollbars` at the far edge of the owner's content box —\n // sit in their own reserved band rather than overlaying the rightmost\n // column / bottom row. The inner `rowsContainer` carries the scroll\n // transform; the transform cannot sit on the same element as\n // `overflow:hidden` because CSS clipping happens in the element's own\n // LOCAL coordinate system before its transform applies — splitting\n // the two roles lets the transform shift the rows around inside a\n // stable clip.\n const clipBox = DOM.sink.createElement(\"div\");\n DOM.sink.apply(clipBox, { style: { position: \"absolute\", top: \"0\", left: \"0\", width: \"100%\", height: \"100%\", overflow: \"hidden\" } });\n DOM.sink.appendChild(element, clipBox);\n this._clipBox = clipBox;\n\n const container = DOM.sink.createElement(\"div\");\n DOM.sink.apply(container, { style: { position: \"absolute\", top: \"0\", left: \"0\", width: \"100%\", transform: \"translate3d(0, 0, 0)\", willChange: \"transform\" } });\n DOM.sink.appendChild(clipBox, container);\n this._rowsContainer = container;\n\n // Position-aware edge shadows, matching the native-scroll `Panel` cue.\n // The overlay is a sibling of `rowsContainer` inside the `clipBox`, so it\n // is clipped to the effective viewport and — being outside the scrolled\n // `rowsContainer` — is not shifted by the scroll transform; sizing it to\n // 100% tracks the clip box that `layoutScrollbars` resizes to the\n // effective viewport. It paints above the rows (appended last) and is\n // inert to the pointer. Each edge is a `box-shadow` layer gated by a\n // custom property; `updateShadows` flips the property per scroll/resize.\n const shadowOverlay = DOM.sink.createElement(\"div\");\n DOM.sink.apply(shadowOverlay, { style: {\n position: \"absolute\",\n top: \"0\",\n left: \"0\",\n width: \"100%\",\n height: \"100%\",\n pointerEvents: \"none\",\n boxShadow: scrollShadowBoxShadow(),\n } });\n DOM.sink.appendChild(clipBox, shadowOverlay);\n this._shadowOverlay = shadowOverlay;\n\n // Drives wheel-initiated scrolling through an eased RAF loop. The seam\n // delegates to the existing setScrollX/Y (which clamp, write the\n // transform, and fire onScroll, so the virtual window re-renders every\n // frame) and clamps targets against the same effective-viewport bounds.\n this._smooth = new SmoothScroller({\n read: (axis) => axis === \"x\" ? this._scrollX : this._scrollY,\n write: (axis, value) => axis === \"x\" ? this.setScrollX(value) : this.setScrollY(value),\n clamp: (axis, value) => this.clampAxis(axis, value),\n });\n\n this._scrollbarV = new Scrollbar(\"vertical\");\n DOM.sink.appendChild(element, this._scrollbarV.getElement(true)!);\n this._scrollbarV.on(\"scroll\", (p: number) => {\n this._smooth.reset();\n this.setScrollY(p);\n });\n\n this._scrollbarH = new Scrollbar(\"horizontal\");\n DOM.sink.appendChild(element, this._scrollbarH.getElement(true)!);\n this._scrollbarH.on(\"scroll\", (p: number) => {\n this._smooth.reset();\n this.setScrollX(p);\n });\n\n this._owner.setTouchAction(\"none\");\n\n // Subtree because wheel events fire on whichever descendant of the\n // owner the pointer is over (a row, a cell, …) — not the owner root.\n // passive: false so onWheel can preventDefault the native page scroll.\n Event.addSubtreeListener(\n this._owner,\n \"wheel\",\n (e: WheelEvent) => this.onWheel(e),\n { passive: false }\n );\n\n this.attachTouchHandlers();\n }\n\n /**\n * Disposes the two `Scrollbar` overlays this scroller owns. They are\n * appended straight onto the owner's element rather than registered as its\n * children, so the owner's `destructor()` recursion cannot reach them and\n * their per-instance stylesheet rules would otherwise survive teardown.\n * Called from `VirtualRowView.destructor()`.\n */\n dispose(): void {\n this._scrollbarV.dispose();\n this._scrollbarH.dispose();\n }\n\n /**\n * Returns the two created container handles (clip box and rows container).\n * The owning component tracks these via `trackHandle` so they are released\n * with the owner — on its destructor or, for a discarded owner, on GC — and\n * not left pinned in the registry. The scroller is not a `Component`, so it\n * cannot track its own handles.\n *\n * @returns The scroller's owned element handles.\n */\n ownedHandles(): readonly Handle[] {\n return [this._clipBox, this._rowsContainer, this._shadowOverlay];\n }\n\n /**\n * Returns the rows-container element. Owners append pool rows here so\n * they participate in the transform-based scroll.\n *\n * @returns The rows-container DOM element.\n */\n getRowsContainer(): Handle {\n return this._rowsContainer;\n }\n\n /**\n * Returns the current vertical scroll position in pixels.\n *\n * @returns The current `scrollY`.\n */\n getScrollY(): number {\n return this._scrollY;\n }\n\n /**\n * Returns the current horizontal scroll position in pixels.\n *\n * @returns The current `scrollX`.\n */\n getScrollX(): number {\n return this._scrollX;\n }\n\n /**\n * Sets the vertical scroll position. Clamped against the last-known\n * content height and the *effective* viewport height (the owner's\n * content-box height minus the horizontal scrollbar's reservation when\n * that bar is visible),\n * so the maximum reachable scroll position matches what the vertical\n * scrollbar's thumb tops out at. Triggers the owner's `onScroll` callback\n * if the position changed.\n *\n * @param y - The new scroll position in pixels.\n */\n setScrollY(y: number): this {\n const maxScroll = Math.max(0, this._contentHeight - this.effectiveViewportH());\n const next = Util.clamp(y, 0, maxScroll);\n\n if (next === this._scrollY) {\n return this;\n }\n\n this._scrollY = next;\n this.updateTransform();\n this._onScroll();\n\n return this;\n }\n\n /**\n * Sets the horizontal scroll position. Clamped against the last-known\n * content width and the *effective* viewport width (the owner's\n * content-box width minus the vertical scrollbar's reservation when that\n * bar is visible),\n * so the maximum reachable scroll position matches what the horizontal\n * scrollbar's thumb tops out at. Triggers the owner's `onScroll` callback\n * if the position changed.\n *\n * @param x - The new scroll position in pixels.\n */\n setScrollX(x: number): this {\n const maxScroll = Math.max(0, this._contentWidth - this.effectiveViewportW());\n const next = Util.clamp(x, 0, maxScroll);\n\n if (next === this._scrollX) {\n return this;\n }\n\n this._scrollX = next;\n this.updateTransform();\n this._onScroll();\n\n return this;\n }\n\n /**\n * Clamps a requested position for one axis to its `[0, max]` range, using\n * the same effective-viewport bounds as `setScrollX/Y` so the eased wheel\n * target converges exactly where the scrollbar thumb tops out.\n *\n * @param axis - The axis to clamp (`\"x\"` or `\"y\"`).\n * @param value - The requested position in pixels.\n *\n * @returns The clamped position in pixels.\n */\n private clampAxis(axis: \"x\" | \"y\", value: number): number {\n const max = axis === \"x\"\n ? Math.max(0, this._contentWidth - this.effectiveViewportW())\n : Math.max(0, this._contentHeight - this.effectiveViewportH());\n\n return Util.clamp(value, 0, max);\n }\n\n /**\n * Aborts any in-flight eased wheel animation and re-seeds it from the live\n * position. Call before a programmatic scroll jump (e.g. `scrollToRecord`)\n * so a lingering ease can't snap the position back afterward.\n */\n resetWheelEase(): void {\n this._smooth.reset();\n }\n\n /**\n * Decides whether each scrollbar should be visible given the current\n * content size, accounting for the mutual dependency between the two\n * axes — if one bar is visible, its track-width reservation shrinks\n * the cross-axis viewport, which can in turn force the other bar to\n * become visible. Two iterations are sufficient: each pass can only\n * promote one flag from false to true.\n *\n * The effective viewport is measured in the owner's content box, not its\n * outer box, so a bordered or padded owner reports the space actually\n * visible to rows.\n */\n private computeScrollbarVisibility(contentWidth: number, contentHeight: number): { vVisible: boolean, hVisible: boolean, effW: number, effH: number } {\n const box = this._owner.getContentBounds()\n ?? { x: 0, y: 0, width: this._owner.getWidth() || 0, height: this._owner.getHeight() || 0 };\n\n // `box.{width,height}` derive from the owner's committed `_width`/\n // `_height`, which are declared `NaN` and stay so until the owner is\n // first sized. The `?? …` fallback above covers the no-element case,\n // not that one — an element-bearing but unsized owner still yields a\n // non-null box whose extents are NaN — so `|| 0` stays, the same\n // coercion the outer-box reads it replaced already used.\n const outerH = box.height || 0;\n const outerW = box.width || 0;\n const trackW = this._scrollbarV.getTrackWidth();\n\n let vVisible = false;\n let hVisible = false;\n for (let i = 0; i < 2; i++) {\n const effH: number = outerH - (hVisible ? trackW : 0);\n const effW: number = outerW - (vVisible ? trackW : 0);\n\n vVisible = contentHeight > effH;\n hVisible = contentWidth > effW;\n }\n\n const effH = outerH - (hVisible ? trackW : 0);\n const effW = outerW - (vVisible ? trackW : 0);\n\n return { vVisible, hVisible, effW, effH };\n }\n\n /**\n * Effective vertical viewport — the owner's content-box height minus the\n * horizontal scrollbar's track-width reservation when that bar would be\n * visible.\n * Single source of truth so the clamps in `setScrollY` agree with what\n * the vertical scrollbar's `setMetrics` is fed.\n */\n private effectiveViewportH(): number {\n return this.computeScrollbarVisibility(this._contentWidth, this._contentHeight).effH;\n }\n\n /**\n * Effective horizontal viewport — see {@link effectiveViewportH}.\n */\n private effectiveViewportW(): number {\n return this.computeScrollbarVisibility(this._contentWidth, this._contentHeight).effW;\n }\n\n /**\n * Effective viewport width for the last-known content metrics — the owner's\n * content-box width minus the vertical scrollbar's track reservation when\n * that bar is visible. Owners that size fill-width rows (e.g. the\n * [`Tree`](/api/component/tree/classes/Tree)) base their row width on this so\n * content does not run under the vertical bar, which would otherwise force a\n * spurious horizontal bar for the reserved band. Reads the current\n * `_contentWidth` / `_contentHeight`; callers refresh those via\n * {@link clampToContent} at the top of their render pass before querying.\n * The public face of `effectiveViewportW` (same value; that stays the\n * internal clamp helper).\n *\n * @returns The effective viewport width in pixels.\n */\n getViewportWidth(): number {\n return this.effectiveViewportW();\n }\n\n /**\n * Clamps the current `scrollX` / `scrollY` against the new content size\n * and the *effective* viewport on each axis (which subtracts the\n * cross-axis scrollbar's track-width when that bar is visible). Call at\n * the start of `renderWindow` so scrollX/Y are within range before being\n * used for window calculations — important when content has shrunk since\n * the last frame. Uses the same effective-viewport reasoning as\n * `setScrollX/Y` so the clamps agree and scrollX/Y aren't pulled back to\n * a smaller bound than the scrollbar's own `setMetrics` expects (which\n * would leave the thumb stopping short of the end-arrow). Does not fire\n * `onScroll`.\n *\n * @param contentWidth - The total scrollable content width in pixels.\n * @param contentHeight - The total scrollable content height in pixels.\n */\n clampToContent(contentWidth: number, contentHeight: number): void {\n this._contentWidth = contentWidth;\n this._contentHeight = contentHeight;\n\n const maxY = Math.max(0, contentHeight - this.effectiveViewportH());\n const maxX = Math.max(0, contentWidth - this.effectiveViewportW());\n\n let changed = false;\n if (this._scrollY > maxY) {\n this._scrollY = maxY;\n changed = true;\n }\n if (this._scrollX > maxX) {\n this._scrollX = maxX;\n changed = true;\n }\n if (changed) {\n this.updateTransform();\n }\n }\n\n /**\n * Tight clamp using effective viewports (each axis subtracts the\n * cross-axis scrollbar's track width when it is visible), then positions\n * the scrollbars and pushes metrics. Call at end of `renderWindow`.\n *\n * Both bars and the clip box are placed in the owner's content box: a\n * child's containing block is already the owner's padding box, so\n * placing them against the outer box would run the far edge past where\n * `overflow: hidden` clips, by both border sides.\n *\n * @param contentWidth - The total scrollable content width in pixels.\n * @param contentHeight - The total scrollable content height in pixels.\n */\n layoutScrollbars(contentWidth: number, contentHeight: number): void {\n this._contentWidth = contentWidth;\n this._contentHeight = contentHeight;\n\n const box = this._owner.getContentBounds()\n ?? { x: 0, y: 0, width: this._owner.getWidth() || 0, height: this._owner.getHeight() || 0 };\n\n const trackW = this._scrollbarV.getTrackWidth();\n\n const { effW, effH } = this.computeScrollbarVisibility(contentWidth, contentHeight);\n\n const maxY = Math.max(0, contentHeight - effH);\n const maxX = Math.max(0, contentWidth - effW);\n if (this._scrollY > maxY || this._scrollX > maxX) {\n if (this._scrollY > maxY) this._scrollY = maxY;\n if (this._scrollX > maxX) this._scrollX = maxX;\n this.updateTransform();\n }\n\n this._scrollbarV.setX(box.x + Math.max(0, box.width - trackW));\n this._scrollbarV.setY(box.y);\n this._scrollbarV.setHeight(effH);\n this._scrollbarV.setMetrics(effH, contentHeight, this._scrollY);\n\n this._scrollbarH.setX(box.x);\n this._scrollbarH.setY(box.y + Math.max(0, box.height - trackW));\n this._scrollbarH.setWidth(effW);\n this._scrollbarH.setMetrics(effW, contentWidth, this._scrollX);\n\n // Resize the clip box to the effective viewport so cells translated\n // by the horizontal scroll can't bleed under the vertical scrollbar\n // (and rows beyond the bottom can't bleed under the horizontal\n // scrollbar). When neither bar is visible this collapses to the\n // full owner content box, matching the previous `width/height: 100%`\n // behaviour for a borderless, unpadded owner.\n DOM.sink.apply(this._clipBox, { style: { left: box.x + \"px\", top: box.y + \"px\", width: effW + \"px\", height: effH + \"px\" } });\n\n // Content size / viewport may have changed without the scroll position\n // moving (so `updateTransform` did not run above) — refresh the shadow\n // edges against the new extremes.\n this.updateShadows();\n }\n\n /**\n * Writes the current `scrollX` / `scrollY` into the rows-container\n * transform.\n */\n private updateTransform(): void {\n DOM.sink.apply(this._rowsContainer, { style: { transform: `translate3d(${-this._scrollX}px, ${-this._scrollY}px, 0)` } });\n this.updateShadows();\n }\n\n /**\n * Recomputes each scroll-shadow edge's strength from the current scroll\n * position, content size, and effective viewport, then lights only the\n * edges that have hidden content past them. Cheap on a no-op scroll: an\n * edge whose quantised strength is unchanged skips the DOM write (see\n * {@link setShadowEdge}). Called on every scroll ({@link updateTransform})\n * and whenever the content/viewport metrics change ({@link layoutScrollbars}).\n */\n private updateShadows(): void {\n const { effW, effH } = this.computeScrollbarVisibility(this._contentWidth, this._contentHeight);\n\n const maxX = Math.max(0, this._contentWidth - effW);\n const maxY = Math.max(0, this._contentHeight - effH);\n\n this.setShadowEdge(\"top\", \"--ts-ss-top\", scrollShadowRamp(this._scrollY));\n this.setShadowEdge(\"bottom\", \"--ts-ss-bottom\", scrollShadowRamp(maxY - this._scrollY));\n this.setShadowEdge(\"left\", \"--ts-ss-left\", scrollShadowRamp(this._scrollX));\n this.setShadowEdge(\"right\", \"--ts-ss-right\", scrollShadowRamp(maxX - this._scrollX));\n }\n\n /**\n * Sets a single edge's shadow strength by scaling the theme shadow colour\n * toward transparent. Strength is quantised to a whole percent so an\n * in-ramp scroll only repaints when the visible strength actually changes;\n * at zero the property is unset so the `box-shadow` layer falls back to\n * `transparent`.\n *\n * @param edge - The edge whose cached strength this updates.\n * @param property - The overlay custom property backing that edge's shadow.\n * @param strength - The target strength in the range 0–1.\n */\n private setShadowEdge(edge: keyof ScrollShadowEdges, property: string, strength: number): void {\n const percent = Math.round(strength * 100); // quantise: 0–1 → 0–100%\n\n if (this._shadowEdges[edge] === percent) {\n return;\n }\n\n this._shadowEdges[edge] = percent;\n DOM.sink.apply(this._shadowOverlay, { style: { [property]: scrollShadowEdgeValue(percent) } });\n }\n\n /**\n * Eases wheel input into the scroll position through the {@link SmoothScroller}.\n * Shift+wheel without an explicit deltaX is treated as horizontal scroll.\n * Claims the event so an ancestor scroll container doesn't also scroll it.\n *\n * @param e - The wheel event.\n */\n private onWheel(e: WheelEvent): void {\n if (!consumeWheel(e)) {\n return;\n }\n\n e.preventDefault();\n\n if (e.shiftKey && e.deltaY !== 0 && e.deltaX === 0) {\n this._smooth.scrollBy(e.deltaY, 0);\n\n return;\n }\n\n this._smooth.scrollBy(e.deltaX, e.deltaY);\n }\n\n /**\n * Installs the touch handlers: 1:1 finger drag scrolls both axes, and on\n * release a 2D fling momentum decays per frame until it falls below\n * threshold or hits a scroll boundary.\n */\n private attachTouchHandlers(): void {\n let touchActive = false;\n let touchStartY = 0;\n let touchStartX = 0;\n let touchStartScrollY = 0;\n let touchStartScrollX = 0;\n let touchSamples : Array<{ time: number, x: number, y: number }> = [];\n let momentumRaf : number | null = null;\n\n const cancelMomentum = (): void => {\n if (momentumRaf !== null) {\n DOM.sink.cancelAnimationFrame(momentumRaf);\n momentumRaf = null;\n }\n };\n\n // Subtree because touch events fire on descendants of the owner\n // (rows / cells) — not the owner root.\n Event.addSubtreeListener(this._owner, \"touchstart\", (e: TouchEvent) => {\n if (e.touches.length !== 1) {\n return;\n }\n cancelMomentum();\n this._smooth.reset();\n touchActive = true;\n touchStartY = e.touches[0].clientY;\n touchStartX = e.touches[0].clientX;\n touchStartScrollY = this._scrollY;\n touchStartScrollX = this._scrollX;\n touchSamples = [{ time: performance.now(), x: touchStartX, y: touchStartY }];\n });\n\n Event.addSubtreeListener(this._owner, \"touchmove\", (e: TouchEvent) => {\n if (!touchActive || e.touches.length !== 1) {\n return;\n }\n const y = e.touches[0].clientY;\n const x = e.touches[0].clientX;\n const now = performance.now();\n\n touchSamples.push({ time: now, x: x, y: y });\n while (touchSamples.length > 1 && touchSamples[0].time < now - 150) {\n touchSamples.shift();\n }\n\n this.setScrollY(touchStartScrollY + (touchStartY - y));\n this.setScrollX(touchStartScrollX + (touchStartX - x));\n });\n\n const startMomentum = (): void => {\n if (touchSamples.length < 2) {\n return;\n }\n\n const last = touchSamples[touchSamples.length - 1];\n\n const PAUSE_THRESHOLD = 50;\n if (performance.now() - last.time > PAUSE_THRESHOLD) {\n return;\n }\n\n const VELOCITY_WINDOW = 80;\n const cutoff = last.time - VELOCITY_WINDOW;\n let firstIdx = touchSamples.length - 1;\n while (firstIdx > 0 && touchSamples[firstIdx - 1].time >= cutoff) {\n firstIdx--;\n }\n const first = touchSamples[firstIdx];\n const dt = last.time - first.time;\n if (dt <= 0) {\n return;\n }\n\n let velocityY = (first.y - last.y) / dt;\n let velocityX = (first.x - last.x) / dt;\n\n const MIN_VELOCITY = 0.1;\n const FRICTION = 0.95;\n const STOP_VELOCITY = 0.02;\n\n const initialSpeed = Math.sqrt(velocityX * velocityX + velocityY * velocityY);\n if (initialSpeed < MIN_VELOCITY) {\n return;\n }\n\n let lastT = performance.now();\n const step = (): void => {\n const now = performance.now();\n const frame = now - lastT;\n lastT = now;\n\n const decay = Math.pow(FRICTION, frame / 16.667);\n velocityY *= decay;\n velocityX *= decay;\n\n const speed = Math.sqrt(velocityX * velocityX + velocityY * velocityY);\n if (speed < STOP_VELOCITY) {\n momentumRaf = null;\n return;\n }\n\n const beforeY = this._scrollY;\n const beforeX = this._scrollX;\n this.setScrollY(this._scrollY + velocityY * frame);\n this.setScrollX(this._scrollX + velocityX * frame);\n if (this._scrollY === beforeY) {\n velocityY = 0;\n }\n if (this._scrollX === beforeX) {\n velocityX = 0;\n }\n if (velocityY === 0 && velocityX === 0) {\n momentumRaf = null;\n return;\n }\n\n momentumRaf = DOM.sink.requestAnimationFrame(step);\n };\n\n momentumRaf = DOM.sink.requestAnimationFrame(step);\n };\n\n Event.addSubtreeListener(this._owner, \"touchend\", () => {\n if (!touchActive) {\n return;\n }\n touchActive = false;\n startMomentum();\n });\n\n Event.addSubtreeListener(this._owner, \"touchcancel\", () => {\n touchActive = false;\n cancelMomentum();\n });\n }\n}\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- (function(){function e(e,t){return e&&typeof e.get==`function`?e.get(t):e?e[t]:void 0}function t(n,r){switch(r.type){case`eq`:return e(n,r.field)===r.value;case`neq`:return e(n,r.field)!==r.value;case`contains`:{let t=e(n,r.field);if(t==null)return!1;let i=r.caseSensitive?String(t):String(t).toLowerCase(),a=r.caseSensitive?r.value:r.value.toLowerCase();return i.indexOf(a)!==-1}case`startsWith`:{let t=e(n,r.field);if(t==null)return!1;let i=r.caseSensitive?String(t):String(t).toLowerCase(),a=r.caseSensitive?r.value:r.value.toLowerCase();return i.indexOf(a)===0}case`gt`:return e(n,r.field)>r.value;case`gte`:return e(n,r.field)>=r.value;case`lt`:return e(n,r.field)<r.value;case`lte`:return e(n,r.field)<=r.value;case`in`:return r.values.indexOf(e(n,r.field))!==-1;case`and`:for(let e of r.filters)if(!t(n,e))return!1;return!0;case`or`:for(let e of r.filters)if(t(n,e))return!0;return!1;case`not`:return!t(n,r.filter)}}function n(e,t){return e<t?-1:+(e>t)}function r(e,t,r){return e==null&&t==null?0:e==null?1:t==null?-1:r===`string`||r===void 0&&typeof e==`string`&&typeof t==`string`?e.localeCompare(t):(r===`date`||r===`datetime`||r===`time`)&&e instanceof Date&&t instanceof Date?n(e.getTime(),t.getTime()):n(e,t)}let i=new Map;function a(e,t,n,i,a){t.sort((t,o)=>{let s=e[t]?e[t][n]:void 0,c=e[o]?e[o][n]:void 0,l=r(s,c,a);return s==null||c==null||i===`asc`?l:-l})}self.onmessage=e=>{let n=e.data;try{if(n.type===`snapshot`){i.set(n.storeId,n.records),self.postMessage({requestId:n.requestId});return}let e=i.get(n.storeId);if(!e){self.postMessage({requestId:n.requestId,error:`No snapshot for storeId `+n.storeId});return}let r=[];for(let t=0;t<e.length;t++)r.push(t);n.filter&&(r=r.filter(r=>t(e[r],n.filter))),n.sort&&a(e,r,n.sort.field,n.sort.direction,n.sort.fieldType),self.postMessage({requestId:n.requestId,indices:r})}catch(e){self.postMessage({requestId:n.requestId,error:String(e?.message??e)})}}})();
2
- //# sourceMappingURL=StoreWorker-CgOBYoai.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"StoreWorker-CgOBYoai.js","names":[],"sources":["../../src/typescript/lib/data/FilterDescriptor.ts","../../src/typescript/lib/data/compareValues.ts","../../src/typescript/lib/data/StoreWorker.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * Serializable filter algebra for {@link AbstractStore}. Descriptors are plain objects so\n * they can cross the worker boundary via structured clone (unlike arbitrary filter\n * functions, which can't). The same evaluator runs on either side.\n *\n * @category Data\n */\nexport type FilterDescriptor =\n | { type: 'eq'; field: string; value: any }\n | { type: 'neq'; field: string; value: any }\n | { type: 'contains'; field: string; value: string; caseSensitive?: boolean }\n | { type: 'startsWith'; field: string; value: string; caseSensitive?: boolean }\n | { type: 'gt'; field: string; value: number | string | Date }\n | { type: 'gte'; field: string; value: number | string | Date }\n | { type: 'lt'; field: string; value: number | string | Date }\n | { type: 'lte'; field: string; value: number | string | Date }\n | { type: 'in'; field: string; values: any[] }\n | { type: 'and'; filters: FilterDescriptor[] }\n | { type: 'or'; filters: FilterDescriptor[] }\n | { type: 'not'; filter: FilterDescriptor };\n\n/**\n * Looks up a field's value from either a plain data object or a ModelRecord-like\n * object that exposes a `get(field)` method. Lets the same matcher run on both\n * sides of the worker boundary.\n */\nfunction readField(record: any, field: string): any {\n if (record && typeof record.get === 'function') {\n return record.get(field);\n }\n return record ? record[field] : undefined;\n}\n\n/**\n * Evaluates a FilterDescriptor against a record. Returns true if the record\n * matches the filter. Works with both plain data objects (worker side) and\n * ModelRecord instances (main thread side).\n */\nexport function matchesFilter(record: any, descriptor: FilterDescriptor): boolean {\n switch (descriptor.type) {\n case 'eq':\n return readField(record, descriptor.field) === descriptor.value;\n\n case 'neq':\n return readField(record, descriptor.field) !== descriptor.value;\n\n case 'contains': {\n const raw = readField(record, descriptor.field);\n if (raw == null) return false;\n const haystack = descriptor.caseSensitive ? String(raw) : String(raw).toLowerCase();\n const needle = descriptor.caseSensitive ? descriptor.value : descriptor.value.toLowerCase();\n return haystack.indexOf(needle) !== -1;\n }\n\n case 'startsWith': {\n const raw = readField(record, descriptor.field);\n if (raw == null) return false;\n const haystack = descriptor.caseSensitive ? String(raw) : String(raw).toLowerCase();\n const needle = descriptor.caseSensitive ? descriptor.value : descriptor.value.toLowerCase();\n return haystack.indexOf(needle) === 0;\n }\n\n case 'gt':\n return readField(record, descriptor.field) > descriptor.value;\n\n case 'gte':\n return readField(record, descriptor.field) >= descriptor.value;\n\n case 'lt':\n return readField(record, descriptor.field) < descriptor.value;\n\n case 'lte':\n return readField(record, descriptor.field) <= descriptor.value;\n\n case 'in':\n return descriptor.values.indexOf(readField(record, descriptor.field)) !== -1;\n\n case 'and':\n for (const f of descriptor.filters) {\n if (!matchesFilter(record, f)) return false;\n }\n return true;\n\n case 'or':\n for (const f of descriptor.filters) {\n if (matchesFilter(record, f)) return true;\n }\n return false;\n\n case 'not':\n return !matchesFilter(record, descriptor.filter);\n }\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport type { FieldType } from '~/data/Field.js';\n\n/**\n * Native ordering of two non-null values via `<` / `>`, returning the\n * ascending-sense sign. Used for numeric (and any non-string, non-date) fields.\n *\n * @param av - The left operand.\n * @param bv - The right operand.\n *\n * @returns A negative, zero, or positive number in ascending sense.\n */\nfunction nativeCompare(av: any, bv: any): number {\n return av < bv ? -1 : av > bv ? 1 : 0;\n}\n\n/**\n * Type-aware, locale-aware comparison of two raw field values, returning a\n * negative / zero / positive number in **ascending** sense. This is the single\n * comparator shared by the main thread ({@link AbstractStore}) and the\n * `StoreWorker`, so the two sort paths can never drift.\n *\n * @param av - The left value.\n * @param bv - The right value.\n * @param type - Optional. The field's {@link FieldType}, which selects the\n * comparison strategy (string → locale, date/time → timestamp, else native).\n * When omitted, two string operands still use the locale path.\n *\n * @returns The ascending-sense comparison result.\n *\n * @remarks\n * `null`/`undefined` sort **last**: both null compare equal (`0`), and a single\n * null returns the sign that places it after a non-null value. Callers must\n * leave a null-involving result un-negated (apply sort direction only to a\n * non-null comparison) so nulls stay last regardless of `'asc'`/`'desc'`.\n *\n * String fields (or two string operands when `type` is unknown) use\n * `localeCompare`, so `'Ä'` orders between `'a'` and `'Z'` rather than after\n * `'Z'` by code point. Date/time fields compare by `getTime()` when both\n * operands are `Date`, falling through to native comparison otherwise.\n *\n * @category Data\n */\nexport function compareValues(av: any, bv: any, type?: FieldType): number {\n if (av == null && bv == null) {\n return 0;\n }\n\n if (av == null) {\n return 1;\n }\n\n if (bv == null) {\n return -1;\n }\n\n if (type === 'string' || (type === undefined && typeof av === 'string' && typeof bv === 'string')) {\n return av.localeCompare(bv);\n }\n\n if (type === 'date' || type === 'datetime' || type === 'time') {\n if (av instanceof Date && bv instanceof Date) {\n return nativeCompare(av.getTime(), bv.getTime());\n }\n }\n\n return nativeCompare(av, bv);\n}\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n/* eslint-disable local/no-raw-dom -- Web Worker entry: self/postMessage are worker-scope messaging, not DOM. */\n//\n// Worker entry point for AbstractStore sort/filter offload. Runs in a Web Worker\n// context (Vite imports it via `?worker` query). Owns a per-store snapshot of\n// plain record data so sort/filter can run without re-shipping the dataset on\n// every operation. Returns sorted indices into the snapshot — main thread maps\n// them back to ModelRecord instances itself.\n\nimport { FilterDescriptor, matchesFilter } from \"~/data/FilterDescriptor.js\";\nimport { compareValues } from \"~/data/compareValues.js\";\nimport type { FieldType } from \"~/data/Field.js\";\n\ntype Direction = \"asc\" | \"desc\";\n\ntype StoreSnapshot = Array<Record<string, any>>;\n\ntype Request =\n | { type: \"snapshot\"; storeId: string; records: StoreSnapshot; requestId: number }\n | { type: \"sortFilter\"; storeId: string; sort?: { field: string; direction: Direction; fieldType?: FieldType };\n filter?: FilterDescriptor; requestId: number };\n\ntype Response = { requestId: number; indices?: number[]; error?: string };\n\nconst snapshots: Map<string, StoreSnapshot> = new Map();\n\nfunction sortIndices(records: StoreSnapshot, indices: number[], field: string, direction: Direction, fieldType?: FieldType): void {\n indices.sort((ai, bi) => {\n const av = records[ai] ? records[ai][field] : undefined;\n const bv = records[bi] ? records[bi][field] : undefined;\n\n const cmp = compareValues(av, bv, fieldType);\n\n // Nulls sort last regardless of direction: leave a null-involving result\n // un-negated, applying direction only to a non-null comparison. This\n // mirrors the main-thread comparator in AbstractStore.applyView().\n if (av == null || bv == null) {\n return cmp;\n }\n\n return direction === \"asc\" ? cmp : -cmp;\n });\n}\n\nself.onmessage = (e: MessageEvent<Request>) => {\n const msg = e.data;\n\n try {\n if (msg.type === \"snapshot\") {\n snapshots.set(msg.storeId, msg.records);\n (self as any).postMessage({ requestId: msg.requestId } as Response);\n return;\n }\n\n const records = snapshots.get(msg.storeId);\n if (!records) {\n (self as any).postMessage({ requestId: msg.requestId, error: \"No snapshot for storeId \" + msg.storeId } as Response);\n return;\n }\n\n let indices: number[] = [];\n for (let i = 0; i < records.length; i++) {\n indices.push(i);\n }\n\n if (msg.filter) {\n indices = indices.filter(i => matchesFilter(records[i], msg.filter!));\n }\n\n if (msg.sort) {\n sortIndices(records, indices, msg.sort.field, msg.sort.direction, msg.sort.fieldType);\n }\n\n (self as any).postMessage({ requestId: msg.requestId, indices } as Response);\n } catch (err: any) {\n (self as any).postMessage({ requestId: msg.requestId, error: String(err?.message ?? err) } as Response);\n }\n};\n"],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- import{t as e}from"./DOM-67StIm5G.js";import{t,u as n}from"./Component-fRQvgaEY.js";import{t as r}from"./VirtualScroller-Bv4KXGKW.js";var i=2,VirtualRowView=class extends t{_rowPool=[];_boundIndices=[];_rowGeom=[];_rowDisplayed=[];_scroller=null;_renderDeferred=!1;_renderResumed=!1;_pendingScrollX=null;_pendingScrollY=null;_pendingScrollRow=null;initScroller(e){this._scroller=new r(this,e,()=>this.onScrollerTick());for(let e of this._scroller.ownedHandles())this.trackHandle(e)}onScrollerTick(){this.renderWindow()}destructor(){for(let e of this._rowPool)e.dispose();this._scroller?.dispose(),super.destructor()}setScrollX(e){return this._scroller?.resetWheelEase(),this.holdScrollWhileFirstLayoutHeld(`x`,e)||this._scroller?.setScrollX(e),this}setScrollY(e){return this._scroller?.resetWheelEase(),this.holdScrollWhileFirstLayoutHeld(`y`,e)||this._scroller?.setScrollY(e),this}holdScrollWhileFirstLayoutHeld(e,t){return n()?(e===`x`?this._pendingScrollX=t:(this._pendingScrollY=t,this._pendingScrollRow=null),!0):(e===`x`?this._pendingScrollX=null:(this._pendingScrollY=null,this._pendingScrollRow=null),!1)}applyPendingScroll(){let e=this._pendingScrollX,t=this._pendingScrollY,n=this._pendingScrollRow;this._pendingScrollX=null,this._pendingScrollY=null,this._pendingScrollRow=null,e!==null&&this.setScrollX(e),t!==null&&this.setScrollY(t),n!==null&&this.scrollRowIntoView(n)}computeVisibleWindow(e,t,n){let r=this.getRowHeight(),a=Math.max(0,Math.floor(e/r)-i),o=Math.min(n-1,Math.ceil((e+t)/r)+i);return{firstRow:a,lastRow:o,windowSize:o-a+1>0?o-a+1:0}}computePoolTarget(e,t,n){return Math.min(n,Math.max(e,Math.ceil(t/this.getRowHeight())+2*i+2))}computePageSize(){let e=this.getRowHeight();return Math.max(1,Math.floor((this.getHeight()||e)/e))}growRowPool(t){if(!this._scroller||this._rowPool.length>=t)return;let n=this._scroller.getRowsContainer(),r=e.sink.createDocumentFragment();for(;this._rowPool.length<t;){let t=this.createPoolRow(),n=t.getElement(!0);e.sink.appendChild(r,n),t.setY(0),t.setWillChange(`transform`),this._rowPool.push(t),this._boundIndices.push(-1),this._rowGeom.push(null),this._rowDisplayed.push(!1)}e.sink.appendChild(n,r),e.sink.release(r)}positionRow(e,t,n){let r=this._rowPool[e],i=this.getRowHeight(),a=this._rowGeom[e],o=!a||a.ty!==t||a.w!==n||a.h!==i;return o&&(r.setAutoCommitStyle(!1),r.setX(0),r.setTranslate(0,t),r.setWidth(n),r.setHeight(i),r.setAutoCommitStyle(!0),this._rowGeom[e]={ty:t,w:n,h:i}),this._rowDisplayed[e]||(r.setDisplayed(!0),this._rowDisplayed[e]=!0),o}hideExcessPoolRows(e){for(let t=e;t<this._rowPool.length;t++)this._rowDisplayed[t]&&(this._rowPool[t].setDisplayed(!1),this._rowDisplayed[t]=!1),this._boundIndices[t]=-1,this._rowGeom[t]=null}invalidateGeom(){for(let e=0;e<this._rowGeom.length;e++)this._rowGeom[e]=null}deferRenderWhileFirstLayoutHeld(){return n()?(this._renderDeferred=!0,this.scheduleLayout(),!0):(this._renderResumed=this._renderDeferred,this._renderDeferred=!1,!1)}wasRenderDeferred(){return this._renderDeferred}finishResumedRender(){let e=this._renderResumed;return this._renderResumed=!1,this.applyPendingScroll(),e}renderWindowIfDeferred(){return!this._renderDeferred||this.isLayoutPaused()?!1:(this.renderWindow(),!0)}onThemeReflow(){this._boundIndices.fill(-1),this.invalidateGeom(),this.renderWindow()}scrollRowIntoView(e){if(e<0||!this._scroller)return;if(n()){this._pendingScrollRow=e;return}let t=this.getRowHeight(),r=e*t,i=r+t,a=this._scroller.getScrollY(),o=this.getHeight(),s=a+o,c=a;r<a?c=r:i>s&&(c=i-o),c!==a&&this.setScrollY(c)}};function selectionsEqual(e,t){if(e.size!==t.size)return!1;for(let n of e)if(!t.has(n))return!1;return!0}export{VirtualRowView as n,selectionsEqual as t};
2
- //# sourceMappingURL=selectionsEqual-Ci3_uflt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"selectionsEqual-Ci3_uflt.js","names":[],"sources":["../../src/typescript/lib/component/shared/VirtualRowView.ts","../../src/typescript/lib/component/shared/selectionsEqual.ts"],"sourcesContent":["// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\nimport { Component, ComponentOptions } from \"~/core/Component.js\";\nimport { DOM } from \"~/core/DOM.js\";\nimport type { Handle } from \"~/core/DOM.js\";\nimport { VirtualScroller } from \"~/component/container/VirtualScroller.js\";\nimport { isFirstLayoutHeld } from \"~/core/FirstLayoutGate.js\";\n\n/** Number of off-screen rows to render above and below the visible viewport. */\nconst SCROLL_BUFFER = 2;\n\n/**\n * Shared transform-windowed virtual-scroll base for the data views —\n * `table/Body` and `tree/Tree` are its only two subclasses. It owns the\n * recycled row pool (`_rowPool` and the parallel `_boundIndices` / `_rowGeom` /\n * `_rowDisplayed` bookkeeping arrays), the {@link VirtualScroller} wiring, and\n * the window / pool-growth / geometry reconciliation primitives each subclass's\n * render pass composes.\n *\n * Only two things genuinely diverge between the two consumers, so only those\n * are hooks:\n *\n * - **Row height** — `Body` derives it live from the theme line box; `Tree`\n * uses a fixed constant. Read through {@link getRowHeight} on every call so a\n * live theme change is honoured.\n * - **Row construction** — the pool-row scaffolding (fragment batching, `setY(0)`\n * pin, `will-change` promotion, parallel-array bookkeeping) is identical; only\n * the row object each subclass builds differs. {@link createPoolRow} returns a\n * fully-constructed, un-appended row and the base owns the rest.\n *\n * The per-frame render pass itself ({@link renderWindow}) stays subclass-specific\n * because the content-width derivation genuinely diverges; the base exposes the\n * shared primitives it calls ({@link computeVisibleWindow},\n * {@link computePoolTarget}, {@link growRowPool}, {@link positionRow},\n * {@link hideExcessPoolRows}).\n *\n * @typeParam TRow - The concrete pooled row component type.\n * @typeParam TOptions - The subclass's options bag.\n *\n * @internal Not barrel-exported; the two subclasses are the only consumers.\n */\nabstract class VirtualRowView<\n TRow extends Component,\n TOptions extends ComponentOptions = ComponentOptions,\n> extends Component<TOptions> {\n\n protected _rowPool : TRow[] = [];\n protected _boundIndices : number[] = [];\n protected _rowGeom : Array<{ ty: number, w: number, h: number } | null> = [];\n protected _rowDisplayed : boolean[] = [];\n protected _scroller : VirtualScroller | null = null;\n\n /** Whether the startup font gate skipped a render pass that still owes a run. */\n private _renderDeferred: boolean = false;\n /** Whether the render now in flight is the one a skipped pass left pending. */\n private _renderResumed : boolean = false;\n /** Scroll offsets the gate held back, applied once a render pass has run. */\n private _pendingScrollX: number | null = null;\n private _pendingScrollY: number | null = null;\n /** A row reveal the gate held back, recomputed once a render pass has run. */\n private _pendingScrollRow: number | null = null;\n\n /**\n * Returns the height in pixels of a single row. Read on every window /\n * geometry calculation, so a subclass that recomputes it (e.g. on a theme\n * change) reflects the new value immediately.\n */\n protected abstract getRowHeight(): number;\n\n /**\n * Constructs one pool row, fully wired but not yet appended to the\n * rows container — the base's {@link growRowPool} owns the append, the\n * `setY(0)` pin, the `will-change` promotion, and the parallel-array\n * bookkeeping.\n */\n protected abstract createPoolRow(): TRow;\n\n /**\n * Recomputes and reconciles the visible row window against the current\n * scroll position and dataset. Subclass-specific because the content-width\n * derivation diverges; both implementations compose the shared primitives\n * on this base.\n */\n protected abstract renderWindow(): void;\n\n /**\n * Constructs the {@link VirtualScroller} for this view and tracks its\n * container handles so they are released with the component. The scroller's\n * onScroll hook is routed through {@link onScrollerTick}.\n *\n * @param element - This view's initialised element handle.\n */\n protected initScroller(element: Handle): void {\n this._scroller = new VirtualScroller(this, element, () => this.onScrollerTick());\n\n // Track the scroller's created container handles so they are released\n // with this view (on destructor or GC); the scroller is not a Component.\n for (const handle of this._scroller.ownedHandles()) {\n this.trackHandle(handle);\n }\n }\n\n /**\n * Invoked on every scroller tick. Default behaviour re-renders the window;\n * `Body` overrides it to additionally emit its scroll events.\n */\n protected onScrollerTick(): void {\n this.renderWindow();\n }\n\n /**\n * Destroys the pooled rows and the scroller's overlay scrollbars before the\n * inherited teardown runs.\n *\n * {@link growRowPool} appends each row's element straight to the rows\n * container and keeps the row only in `_rowPool`, so a pooled row is never\n * registered as a child component and the base destructor's recursion over\n * `_components` cannot reach it. Without this override neither the rows nor\n * their cells (which *are* registered on their row) release their\n * per-instance stylesheet rules, so the shared sheet grows by roughly the\n * view's whole cell count on every teardown. The scroller's two\n * `Scrollbar` overlays are raw-appended the same way, so they need the\n * same explicit disposal.\n */\n protected destructor(): void {\n for (const row of this._rowPool) {\n row.dispose();\n }\n\n this._scroller?.dispose();\n\n super.destructor();\n }\n\n /**\n * Sets the JS-controlled horizontal scroll position. Delegates to the\n * underlying {@link VirtualScroller}.\n *\n * @param x - The new scroll position in pixels.\n */\n setScrollX(x: number): this {\n // Ahead of the hold: a programmatic scroll cancels an in-flight wheel\n // ease whether or not the offset itself has to wait.\n this._scroller?.resetWheelEase();\n\n if (this.holdScrollWhileFirstLayoutHeld(\"x\", x)) {\n return this;\n }\n\n this._scroller?.setScrollX(x);\n\n return this;\n }\n\n /**\n * Sets the JS-controlled vertical scroll position. Delegates to the\n * underlying {@link VirtualScroller}.\n *\n * @param y - The new scroll position in pixels.\n */\n setScrollY(y: number): this {\n // Ahead of the hold: a programmatic scroll cancels an in-flight wheel\n // ease whether or not the offset itself has to wait.\n this._scroller?.resetWheelEase();\n\n if (this.holdScrollWhileFirstLayoutHeld(\"y\", y)) {\n return this;\n }\n\n this._scroller?.setScrollY(y);\n\n return this;\n }\n\n /**\n * Holds a scroll offset set while the startup font gate is holding this\n * view's render pass, for {@link applyPendingScroll} to apply once the pass\n * has run.\n *\n * @param axis - Which offset is being set.\n * @param offset - The requested offset in pixels.\n *\n * @returns `true` when the caller must return without scrolling.\n *\n * @remarks The scroller clamps every offset against a content extent that\n * only the render pass publishes, so an offset set while that pass is\n * deferred clamps to 0 and the request is lost — a row revealed during\n * startup would end up selected but off-screen. This guards the offsets\n * that are viewport-independent and so can be replayed verbatim: the\n * table's `scrollToRecord`, and a consumer restoring a saved offset.\n * `scrollRowIntoView` is held one level higher instead, by row index, since\n * its target depends on a height the gate is also holding. The table's\n * `scrollColumnIntoView` has that same width dependence but fires only from\n * a pooled cell's editor, which cannot exist while the pass is deferred.\n */\n private holdScrollWhileFirstLayoutHeld(axis: \"x\" | \"y\", offset: number): boolean {\n if (!isFirstLayoutHeld()) {\n // This offset is being applied for real, so it supersedes anything\n // held for the same axis — otherwise the held one would replay on\n // the next render and revert it. A held row reveal is a vertical\n // request too, so it goes with the Y offset.\n if (axis === \"x\") {\n this._pendingScrollX = null;\n } else {\n this._pendingScrollY = null;\n this._pendingScrollRow = null;\n }\n\n return false;\n }\n\n if (axis === \"x\") {\n this._pendingScrollX = offset;\n } else {\n this._pendingScrollY = offset;\n this._pendingScrollRow = null;\n }\n\n return true;\n }\n\n /**\n * Applies the scroll offsets {@link holdScrollWhileFirstLayoutHeld} held\n * back, now that a render pass has published the content extent they clamp\n * against. A no-op once they are applied.\n */\n private applyPendingScroll(): void {\n const x = this._pendingScrollX;\n const y = this._pendingScrollY;\n const row = this._pendingScrollRow;\n\n this._pendingScrollX = null;\n this._pendingScrollY = null;\n this._pendingScrollRow = null;\n\n if (x !== null) {\n this.setScrollX(x);\n }\n\n if (y !== null) {\n this.setScrollY(y);\n }\n\n // Applied after the offsets, which is what makes a reveal win over a\n // raw offset held before it. The reverse order is handled the other\n // way: a raw offset set later clears the reveal outright, so the two\n // vertical requests always resolve to whichever came last.\n if (row !== null) {\n this.scrollRowIntoView(row);\n }\n }\n\n /**\n * Computes the `[firstRow, lastRow]` data-index window visible in the\n * current viewport, padded by `SCROLL_BUFFER` on each side and clamped to\n * the dataset bounds.\n *\n * @param scrollY - The current scroll offset in pixels.\n * @param visibleHeight - The viewport height in pixels.\n * @param totalRows - The total number of rows in the dataset.\n * @returns The `firstRow` / `lastRow` data indices and the number of rows in the window.\n */\n protected computeVisibleWindow(scrollY: number, visibleHeight: number, totalRows: number): { firstRow: number, lastRow: number, windowSize: number } {\n const rowHeight = this.getRowHeight();\n const firstRow = Math.max(0, Math.floor(scrollY / rowHeight) - SCROLL_BUFFER);\n const lastRow = Math.min(\n totalRows - 1,\n Math.ceil((scrollY + visibleHeight) / rowHeight) + SCROLL_BUFFER\n );\n const windowSize = lastRow - firstRow + 1 > 0 ? lastRow - firstRow + 1 : 0;\n\n return { firstRow, lastRow, windowSize };\n }\n\n /**\n * Computes the row-pool target size: the max possible window for the\n * current viewport, not just the current windowSize. windowSize shrinks\n * near the top/bottom edges of the dataset because firstRow clamps to 0\n * (and lastRow to totalRows-1); growing only to windowSize would force\n * regrowth mid-scroll once the user passes a viewport-edge boundary. Pre-\n * growing pays the per-row first-layout cost once.\n *\n * @param windowSize - The current visible-window size.\n * @param visibleHeight - The viewport height in pixels.\n * @param totalRows - The total number of rows in the dataset.\n * @returns The pool target size.\n */\n protected computePoolTarget(windowSize: number, visibleHeight: number, totalRows: number): number {\n return Math.min(\n totalRows,\n Math.max(\n windowSize,\n Math.ceil(visibleHeight / this.getRowHeight()) + 2 * SCROLL_BUFFER + 2\n )\n );\n }\n\n /**\n * Computes the number of whole rows a page-nav keystroke should move by:\n * one viewport height, floored to at least one row.\n *\n * @returns The page size in rows.\n */\n protected computePageSize(): number {\n const rowHeight = this.getRowHeight();\n\n return Math.max(1, Math.floor((this.getHeight() || rowHeight) / rowHeight));\n }\n\n /**\n * Grows the row pool up to `poolTarget`, batching new row elements through\n * a {@link DocumentFragment} so the live rows container sees a single\n * append instead of N. Each new slot pins its static top to 0, promotes it\n * to its own compositor layer, and extends the parallel bookkeeping arrays\n * in lockstep.\n *\n * @param poolTarget - The target pool size.\n */\n protected growRowPool(poolTarget: number): void {\n if (!this._scroller || this._rowPool.length >= poolTarget) {\n return;\n }\n\n const rowsContainer = this._scroller.getRowsContainer();\n const growFragment = DOM.sink.createDocumentFragment();\n\n while (this._rowPool.length < poolTarget) {\n const row = this.createPoolRow();\n const rowEl = row.getElement(true)!;\n\n DOM.sink.appendChild(growFragment, rowEl);\n\n // Pin row's static top to 0 once. Per-frame Y offset comes from\n // translateY, which is composite-only (avoids layout/paint per\n // scroll tick).\n row.setY(0);\n\n // Pre-promote pooled rows to their own compositor layer so the first\n // scroll-driven translate doesn't pay a layer-creation cost.\n row.setWillChange(\"transform\");\n\n this._rowPool.push(row);\n this._boundIndices.push(-1);\n this._rowGeom.push(null);\n this._rowDisplayed.push(false);\n }\n\n DOM.sink.appendChild(rowsContainer, growFragment);\n DOM.sink.release(growFragment);\n }\n\n /**\n * Positions the pool slot at `slot` to `targetY` and sizes it to `rowWidth`,\n * writing the translate/size only when the cached geometry differs from the\n * target, and toggling the row displayed on the false→true edge.\n *\n * @param slot - The pool-slot index.\n * @param targetY - The row's translate-Y offset in pixels.\n * @param rowWidth - The row's width in pixels.\n * @returns `true` when the geometry changed (the subclass may need to re-lay\n * out the row's children), `false` when it was already at the target.\n */\n protected positionRow(slot: number, targetY: number, rowWidth: number): boolean {\n const row = this._rowPool[slot];\n const rowHeight = this.getRowHeight();\n const prev = this._rowGeom[slot];\n const geomChanged = !prev || prev.ty !== targetY || prev.w !== rowWidth || prev.h !== rowHeight;\n\n if (geomChanged) {\n row.setAutoCommitStyle(false);\n row.setX(0);\n row.setTranslate(0, targetY);\n row.setWidth(rowWidth);\n row.setHeight(rowHeight);\n row.setAutoCommitStyle(true);\n this._rowGeom[slot] = { ty: targetY, w: rowWidth, h: rowHeight };\n }\n\n if (!this._rowDisplayed[slot]) {\n row.setDisplayed(true);\n this._rowDisplayed[slot] = true;\n }\n\n return geomChanged;\n }\n\n /**\n * Hides pool slots whose index falls outside the visible window and\n * clears their cached binding so the next bind triggers a full rebuild.\n *\n * @param windowSize - The number of pool slots currently in use.\n */\n protected hideExcessPoolRows(windowSize: number): void {\n for (let i = windowSize; i < this._rowPool.length; i++) {\n if (this._rowDisplayed[i]) {\n this._rowPool[i].setDisplayed(false);\n this._rowDisplayed[i] = false;\n }\n this._boundIndices[i] = -1;\n this._rowGeom[i] = null;\n }\n }\n\n /**\n * Clears the cached row geometry so the next render re-applies positions and\n * sizes for every slot. `Body` overrides this to additionally clear its\n * per-cell geometry cache.\n */\n protected invalidateGeom(): void {\n for (let i = 0; i < this._rowGeom.length; i++) {\n this._rowGeom[i] = null;\n }\n }\n\n /**\n * Skips a render pass while the startup font gate is held, arranging for it\n * to run once the gate opens.\n *\n * @returns `true` when the caller must return without rendering.\n *\n * @remarks Both subclasses call {@link renderWindow} from many synchronous\n * entry points — `init`, a data change, a selection move — so a row's\n * geometry is routinely committed outside the coalesced layout queue, and\n * `init` in particular commits it the moment the element exists. Holding the\n * queue therefore does not hold these views; they have to check the gate\n * themselves. Deferring at this one choke point covers every entry point at\n * once, rather than guarding each caller.\n */\n protected deferRenderWhileFirstLayoutHeld(): boolean {\n if (!isFirstLayoutHeld()) {\n // This render is going ahead, which satisfies anything a held pass\n // left pending — clearing it keeps a later layout from replaying a\n // startup-era pass over the fresher state this one just committed.\n // Note that it also took over that pass's unfinished business, so\n // flag it for `finishResumedRender` to pick up once it has rendered.\n this._renderResumed = this._renderDeferred;\n this._renderDeferred = false;\n\n return false;\n }\n\n this._renderDeferred = true;\n this.scheduleLayout();\n\n return true;\n }\n\n /**\n * Whether the last render pass on this view was skipped by the startup font\n * gate and is still waiting to run.\n *\n * @returns `true` while a pass is pending.\n */\n protected wasRenderDeferred(): boolean {\n return this._renderDeferred;\n }\n\n /**\n * Reports, once, that the render now finishing is the one a held pass left\n * pending — so the caller can redo the post-render work that pass skipped.\n *\n * @returns `true` exactly once per resumed pass, at the end of the render\n * that resumed it.\n *\n * @remarks Called at the tail of {@link renderWindow} rather than from a\n * layout hook because a render resumes from whichever entry point reaches\n * it first, and for the table body that is the parent table layout calling\n * `renderWindow` directly rather than anything going through `doLayout`.\n */\n protected finishResumedRender(): boolean {\n // Read and clear before applying the scroll: applying it re-enters\n // `renderWindow` through the scroller's onScroll hook, and that nested\n // pass resets this flag. Reading it afterwards would lose the caller's\n // post-render work on exactly the passes that carry both.\n const resumed = this._renderResumed;\n\n this._renderResumed = false;\n\n // This pass has published the content extent, so any held offset can be\n // applied now — whether or not the pass is itself the deferred one.\n this.applyPendingScroll();\n\n return resumed;\n }\n\n /**\n * Runs the render pass the startup font gate deferred, if one is pending.\n * Each subclass calls this from its own `doLayout`, which is what picks the\n * pass back up once the gate opens.\n *\n * @returns `true` when a deferred pass ran, so the caller can skip a render\n * of its own and refresh whatever it keeps in step with the rendered rows.\n *\n * @remarks A paused view keeps its pass pending rather than running it: a\n * parent's layout recursion reaches `Body.doLayout` regardless of the\n * child's pause state, so rendering here would defeat a `pauseLayout` the\n * caller asked for. (`Tree.doLayout` already returns early when paused, so\n * the guard only binds for the body.) `resumeLayout` runs a layout of its\n * own, which picks the pass up.\n */\n protected renderWindowIfDeferred(): boolean {\n if (!this._renderDeferred || this.isLayoutPaused()) {\n return false;\n }\n\n // The pending flag is left for `renderWindow`'s own gate check to\n // consume: that is what marks this render as the resumed one, which\n // `finishResumedRender` reads at the end of the pass.\n this.renderWindow();\n\n return true;\n }\n\n /**\n * Re-binds and re-renders every pooled row after a text-metrics reflow —\n * a theme change, or the web font swapping in over the fallback face.\n *\n * @remarks Pooled rows do not ride `ThemeManager`'s reflow for free. Both\n * subclasses render through renderers whose `Text` runs with\n * `setAutoMeasure(false)`, so a bound row only re-measures inside the\n * renderer's `update()` — which {@link renderWindow} skips for a slot that\n * is already bound to its data index. Without the `_boundIndices` reset a\n * visible row therefore keeps the width it measured against whichever font\n * was active when it was bound, clipping the wider glyphs of the real face\n * once it arrives. Subclasses that cache metrics-derived state of their own\n * (row height, content width) override this to refresh it, then chain up.\n */\n protected onThemeReflow(): void {\n this._boundIndices.fill(-1);\n this.invalidateGeom();\n this.renderWindow();\n }\n\n /**\n * Scrolls the view so the row at `index` is fully visible, without moving\n * the viewport unless necessary. Delegates through {@link VirtualScroller}\n * so the header translate + scrollbar thumb stay in sync.\n *\n * @param index - The data index of the row to reveal. A negative index is a\n * no-op (the row is not in the current view).\n */\n protected scrollRowIntoView(index: number): void {\n if (index < 0 || !this._scroller) {\n return;\n }\n\n // Hold the row, not a target. The target depends on this view's height,\n // and at startup that height arrives from the very layout the gate is\n // holding — so computing it now would either read an unset height and\n // reveal nothing, or read 0 and scroll the row just out of view.\n if (isFirstLayoutHeld()) {\n this._pendingScrollRow = index;\n\n return;\n }\n\n const rowHeight = this.getRowHeight();\n const top = index * rowHeight;\n const bottom = top + rowHeight;\n const scrollTop = this._scroller.getScrollY();\n const viewportHeight = this.getHeight();\n const visibleBottom = scrollTop + viewportHeight;\n\n let target = scrollTop;\n if (top < scrollTop) {\n target = top;\n } else if (bottom > visibleBottom) {\n target = bottom - viewportHeight;\n }\n if (target !== scrollTop) {\n this.setScrollY(target);\n }\n }\n}\n\nexport { VirtualRowView };\n","// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0\n\n/**\n * Compares two selection sets by membership only — size and element\n * identity, regardless of insertion order.\n *\n * Pure; no DOM, no component state.\n *\n * @typeParam T - The selection identity type.\n * @param a - One selection set.\n * @param b - The other selection set.\n * @returns `true` when both sets have the same size and every member of\n * `a` is present in `b`.\n *\n * @internal Shared by `Tree` and `Body`; not barrel-exported.\n */\nexport function selectionsEqual<T>(a: ReadonlySet<T>, b: ReadonlySet<T>): boolean {\n if (a.size !== b.size) {\n return false;\n }\n\n for (const item of a) {\n if (!b.has(item)) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":"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"}