@multiplatform.one/components 7.10.0 → 7.15.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 (452) hide show
  1. package/README.md +100 -2
  2. package/dist/cjs/Accordion/index.cjs +2 -6
  3. package/dist/cjs/Accordion/index.native.js +2 -6
  4. package/dist/cjs/Accordion/index.native.js.map +1 -1
  5. package/dist/cjs/AnimateHeight/index.cjs +1 -3
  6. package/dist/cjs/AnimateHeight/index.native.js +1 -3
  7. package/dist/cjs/AnimateHeight/index.native.js.map +1 -1
  8. package/dist/cjs/Chip/index.cjs +8 -1
  9. package/dist/cjs/Chip/index.native.js +8 -1
  10. package/dist/cjs/Chip/index.native.js.map +1 -1
  11. package/dist/cjs/SheetModal/index.cjs +22 -3
  12. package/dist/cjs/SheetModal/index.native.js +115 -27
  13. package/dist/cjs/SheetModal/index.native.js.map +1 -1
  14. package/dist/cjs/Tabs/index.cjs +35 -18
  15. package/dist/cjs/Tabs/index.native.js +39 -18
  16. package/dist/cjs/Tabs/index.native.js.map +1 -1
  17. package/dist/cjs/Text.cjs +2 -0
  18. package/dist/cjs/Text.native.js +2 -0
  19. package/dist/cjs/Text.native.js.map +1 -1
  20. package/dist/cjs/TreeSelect/index.cjs +55 -52
  21. package/dist/cjs/TreeSelect/index.native.js +55 -52
  22. package/dist/cjs/TreeSelect/index.native.js.map +1 -1
  23. package/dist/cjs/Video/PlayerChrome.cjs +3 -9
  24. package/dist/cjs/Video/PlayerChrome.native.js +3 -9
  25. package/dist/cjs/Video/PlayerChrome.native.js.map +1 -1
  26. package/dist/cjs/code/Code/index.cjs +6 -0
  27. package/dist/cjs/code/Code/index.native.js +7 -4
  28. package/dist/cjs/code/Code/index.native.js.map +1 -1
  29. package/dist/cjs/code/CodeBlock/index.cjs +4 -5
  30. package/dist/cjs/code/CodeBlock/index.native.js +4 -5
  31. package/dist/cjs/code/CodeBlock/index.native.js.map +1 -1
  32. package/dist/cjs/icons/themed.cjs +2 -1
  33. package/dist/cjs/icons/themed.native.js +2 -1
  34. package/dist/cjs/icons/themed.native.js.map +1 -1
  35. package/dist/cjs/knobImmuneExports.cjs +3 -3
  36. package/dist/cjs/knobImmuneExports.native.js +3 -3
  37. package/dist/cjs/layouts/PaneScaffold.cjs +70 -42
  38. package/dist/cjs/layouts/PaneScaffold.native.js +75 -48
  39. package/dist/cjs/layouts/PaneScaffold.native.js.map +1 -1
  40. package/dist/cjs/layouts/page.cjs +2 -1
  41. package/dist/cjs/layouts/page.native.js +2 -1
  42. package/dist/cjs/layouts/page.native.js.map +1 -1
  43. package/dist/cjs/layouts/sidebar.cjs +1 -3
  44. package/dist/cjs/layouts/sidebar.native.js +1 -3
  45. package/dist/cjs/layouts/sidebar.native.js.map +1 -1
  46. package/dist/cjs/layouts/tags.native.js.map +1 -1
  47. package/dist/cjs/surfaces.cjs +0 -32
  48. package/dist/cjs/surfaces.native.js +0 -32
  49. package/dist/cjs/surfaces.native.js.map +1 -1
  50. package/dist/cjs/views/List.cjs +1 -3
  51. package/dist/cjs/views/List.native.js +1 -3
  52. package/dist/cjs/views/List.native.js.map +1 -1
  53. package/dist/cjs/views/Matrix.cjs +568 -0
  54. package/dist/cjs/views/Matrix.native.js +612 -0
  55. package/dist/cjs/views/Matrix.native.js.map +1 -0
  56. package/dist/cjs/views/TreeView.cjs +175 -43
  57. package/dist/cjs/views/TreeView.native.js +181 -46
  58. package/dist/cjs/views/TreeView.native.js.map +1 -1
  59. package/dist/cjs/views/ganttMath.cjs +2 -0
  60. package/dist/cjs/views/ganttMath.native.js +2 -0
  61. package/dist/cjs/views/ganttMath.native.js.map +1 -1
  62. package/dist/cjs/views/index.cjs +16 -0
  63. package/dist/cjs/views/index.native.js +16 -0
  64. package/dist/cjs/views/index.native.js.map +1 -1
  65. package/dist/cjs/views/matrixMath.cjs +157 -0
  66. package/dist/cjs/views/matrixMath.native.js +229 -0
  67. package/dist/cjs/views/matrixMath.native.js.map +1 -0
  68. package/dist/esm/Accordion/index.mjs +3 -7
  69. package/dist/esm/Accordion/index.mjs.map +1 -1
  70. package/dist/esm/Accordion/index.native.js +3 -7
  71. package/dist/esm/Accordion/index.native.js.map +1 -1
  72. package/dist/esm/AnimateHeight/index.mjs +2 -4
  73. package/dist/esm/AnimateHeight/index.mjs.map +1 -1
  74. package/dist/esm/AnimateHeight/index.native.js +2 -4
  75. package/dist/esm/AnimateHeight/index.native.js.map +1 -1
  76. package/dist/esm/Avatar/getInitials.native.js.map +1 -1
  77. package/dist/esm/Avatar/index.native.js.map +1 -1
  78. package/dist/esm/Badge/index.native.js.map +1 -1
  79. package/dist/esm/Button.native.js.map +1 -1
  80. package/dist/esm/Carousel/index.native.js.map +1 -1
  81. package/dist/esm/Chip/index.mjs +9 -2
  82. package/dist/esm/Chip/index.mjs.map +1 -1
  83. package/dist/esm/Chip/index.native.js +9 -2
  84. package/dist/esm/Chip/index.native.js.map +1 -1
  85. package/dist/esm/Collapsible.native.js.map +1 -1
  86. package/dist/esm/ContextMenu/index.native.js.map +1 -1
  87. package/dist/esm/CopyField/index.native.js.map +1 -1
  88. package/dist/esm/DotIndicator/index.native.js.map +1 -1
  89. package/dist/esm/DropdownMenu/index.native.js.map +1 -1
  90. package/dist/esm/ErrorBoundary/index.native.js.map +1 -1
  91. package/dist/esm/Heading.native.js.map +1 -1
  92. package/dist/esm/Meter/index.native.js.map +1 -1
  93. package/dist/esm/Meter/meter.native.js.map +1 -1
  94. package/dist/esm/Pagination.native.js.map +1 -1
  95. package/dist/esm/ProgressSteps/index.native.js.map +1 -1
  96. package/dist/esm/Quote/index.native.js.map +1 -1
  97. package/dist/esm/Separator/index.native.js.map +1 -1
  98. package/dist/esm/SheetModal/detents.native.js.map +1 -1
  99. package/dist/esm/SheetModal/index.mjs +22 -3
  100. package/dist/esm/SheetModal/index.mjs.map +1 -1
  101. package/dist/esm/SheetModal/index.native.js +117 -29
  102. package/dist/esm/SheetModal/index.native.js.map +1 -1
  103. package/dist/esm/Skeleton/index.native.js.map +1 -1
  104. package/dist/esm/SkipLink/index.native.js.map +1 -1
  105. package/dist/esm/SortableList/SortableHandle.native.js.map +1 -1
  106. package/dist/esm/SortableList/index.native.js.map +1 -1
  107. package/dist/esm/SortableList/useSortableRows.native.js.map +1 -1
  108. package/dist/esm/Tabs/index.mjs +36 -19
  109. package/dist/esm/Tabs/index.mjs.map +1 -1
  110. package/dist/esm/Tabs/index.native.js +40 -19
  111. package/dist/esm/Tabs/index.native.js.map +1 -1
  112. package/dist/esm/Text.mjs +3 -1
  113. package/dist/esm/Text.mjs.map +1 -1
  114. package/dist/esm/Text.native.js +3 -1
  115. package/dist/esm/Text.native.js.map +1 -1
  116. package/dist/esm/Toast/index.native.js.map +1 -1
  117. package/dist/esm/Toast/store.native.js.map +1 -1
  118. package/dist/esm/Tooltip/nativePress.native.js.map +1 -1
  119. package/dist/esm/Tooltip/tooltipShared.native.js.map +1 -1
  120. package/dist/esm/TreeSelect/index.mjs +56 -53
  121. package/dist/esm/TreeSelect/index.mjs.map +1 -1
  122. package/dist/esm/TreeSelect/index.native.js +56 -53
  123. package/dist/esm/TreeSelect/index.native.js.map +1 -1
  124. package/dist/esm/TreeSelect/treeSelectModel.native.js.map +1 -1
  125. package/dist/esm/Video/PlayerChrome.mjs +4 -10
  126. package/dist/esm/Video/PlayerChrome.mjs.map +1 -1
  127. package/dist/esm/Video/PlayerChrome.native.js +4 -10
  128. package/dist/esm/Video/PlayerChrome.native.js.map +1 -1
  129. package/dist/esm/Video/VideoFrame.native.js.map +1 -1
  130. package/dist/esm/Video/types.native.js.map +1 -1
  131. package/dist/esm/Wheel/index.native.js.map +1 -1
  132. package/dist/esm/Wizard/index.native.js.map +1 -1
  133. package/dist/esm/actions/ActionBar.native.js.map +1 -1
  134. package/dist/esm/actions/DestructiveAction.native.js.map +1 -1
  135. package/dist/esm/actions/devWarn.native.js.map +1 -1
  136. package/dist/esm/actions/index.native.js.map +1 -1
  137. package/dist/esm/actions/severity.native.js.map +1 -1
  138. package/dist/esm/charts/Axis.native.js.map +1 -1
  139. package/dist/esm/charts/BarChart.native.js.map +1 -1
  140. package/dist/esm/charts/ChartDataView.native.js.map +1 -1
  141. package/dist/esm/charts/ChartSurface.native.js.map +1 -1
  142. package/dist/esm/charts/LineChart.native.js.map +1 -1
  143. package/dist/esm/charts/PieChart.native.js.map +1 -1
  144. package/dist/esm/charts/Sparkline.native.js.map +1 -1
  145. package/dist/esm/charts/accessibility.native.js.map +1 -1
  146. package/dist/esm/charts/composeChart.native.js.map +1 -1
  147. package/dist/esm/charts/index.native.js.map +1 -1
  148. package/dist/esm/charts/math.native.js.map +1 -1
  149. package/dist/esm/charts/series.native.js.map +1 -1
  150. package/dist/esm/charts/svg.native.js.map +1 -1
  151. package/dist/esm/charts/types.native.js.map +1 -1
  152. package/dist/esm/charts/useChartTheme.native.js.map +1 -1
  153. package/dist/esm/code/Code/index.mjs +6 -0
  154. package/dist/esm/code/Code/index.mjs.map +1 -1
  155. package/dist/esm/code/Code/index.native.js +10 -7
  156. package/dist/esm/code/Code/index.native.js.map +1 -1
  157. package/dist/esm/code/CodeBlock/index.mjs +5 -6
  158. package/dist/esm/code/CodeBlock/index.mjs.map +1 -1
  159. package/dist/esm/code/CodeBlock/index.native.js +5 -6
  160. package/dist/esm/code/CodeBlock/index.native.js.map +1 -1
  161. package/dist/esm/code/HighlightedCode/index.native.js.map +1 -1
  162. package/dist/esm/code/Highlighter/index.native.js.map +1 -1
  163. package/dist/esm/code/Pre/index.native.js.map +1 -1
  164. package/dist/esm/code/index.native.js.map +1 -1
  165. package/dist/esm/componentColors.native.js.map +1 -1
  166. package/dist/esm/feedback/ConfirmDialog.native.js.map +1 -1
  167. package/dist/esm/feedback/NotifyHost.native.js.map +1 -1
  168. package/dist/esm/feedback/copy.native.js.map +1 -1
  169. package/dist/esm/feedback/index.native.js.map +1 -1
  170. package/dist/esm/feedback/notify.native.js.map +1 -1
  171. package/dist/esm/feedback/route.native.js.map +1 -1
  172. package/dist/esm/feedback/store.native.js.map +1 -1
  173. package/dist/esm/hooks/index.native.js.map +1 -1
  174. package/dist/esm/hooks/useClipboard.native.js.map +1 -1
  175. package/dist/esm/hooks/useDocumentTitle.native.js.map +1 -1
  176. package/dist/esm/icons/CheckRegular.native.js.map +1 -1
  177. package/dist/esm/icons/MinusRegular.native.js.map +1 -1
  178. package/dist/esm/icons/index.native.js.map +1 -1
  179. package/dist/esm/icons/lucide.native.js.map +1 -1
  180. package/dist/esm/icons/themed.mjs +3 -2
  181. package/dist/esm/icons/themed.mjs.map +1 -1
  182. package/dist/esm/icons/themed.native.js +3 -2
  183. package/dist/esm/icons/themed.native.js.map +1 -1
  184. package/dist/esm/images/Image/ImageFrame.native.js.map +1 -1
  185. package/dist/esm/images/Image/shared.native.js.map +1 -1
  186. package/dist/esm/images/Image/types.native.js.map +1 -1
  187. package/dist/esm/images/index.native.js.map +1 -1
  188. package/dist/esm/index.native.js.map +1 -1
  189. package/dist/esm/knobImmuneExports.mjs +3 -3
  190. package/dist/esm/knobImmuneExports.native.js +3 -3
  191. package/dist/esm/knobImmuneExports.native.js.map +1 -1
  192. package/dist/esm/layouts/AsyncBoundary.native.js.map +1 -1
  193. package/dist/esm/layouts/Debug/index.native.js.map +1 -1
  194. package/dist/esm/layouts/EmptyState.native.js.map +1 -1
  195. package/dist/esm/layouts/KeyboardAvoidingWrapper/behavior.native.js.map +1 -1
  196. package/dist/esm/layouts/PageTemplates.native.js.map +1 -1
  197. package/dist/esm/layouts/PaneScaffold.mjs +70 -42
  198. package/dist/esm/layouts/PaneScaffold.mjs.map +1 -1
  199. package/dist/esm/layouts/PaneScaffold.native.js +75 -48
  200. package/dist/esm/layouts/PaneScaffold.native.js.map +1 -1
  201. package/dist/esm/layouts/SafeAreaWrapper/insets.native.js.map +1 -1
  202. package/dist/esm/layouts/ViewSwitcher.native.js.map +1 -1
  203. package/dist/esm/layouts/attachments.native.js.map +1 -1
  204. package/dist/esm/layouts/breadcrumbs.native.js.map +1 -1
  205. package/dist/esm/layouts/index.native.js.map +1 -1
  206. package/dist/esm/layouts/page.mjs +3 -2
  207. package/dist/esm/layouts/page.mjs.map +1 -1
  208. package/dist/esm/layouts/page.native.js +3 -2
  209. package/dist/esm/layouts/page.native.js.map +1 -1
  210. package/dist/esm/layouts/pageHeadingScope.native.js.map +1 -1
  211. package/dist/esm/layouts/sidebar.mjs +2 -4
  212. package/dist/esm/layouts/sidebar.mjs.map +1 -1
  213. package/dist/esm/layouts/sidebar.native.js +2 -4
  214. package/dist/esm/layouts/sidebar.native.js.map +1 -1
  215. package/dist/esm/layouts/tags.mjs.map +1 -1
  216. package/dist/esm/layouts/tags.native.js.map +1 -1
  217. package/dist/esm/layouts/timeline.native.js.map +1 -1
  218. package/dist/esm/layouts/toolbar.native.js.map +1 -1
  219. package/dist/esm/shared/actionScan.native.js.map +1 -1
  220. package/dist/esm/shared/i18n.native.js.map +1 -1
  221. package/dist/esm/shared/t.native.js.map +1 -1
  222. package/dist/esm/shared/textRidesText.native.js.map +1 -1
  223. package/dist/esm/shared/useReturnFocusOnClose.native.js.map +1 -1
  224. package/dist/esm/surfaces.mjs +1 -33
  225. package/dist/esm/surfaces.mjs.map +1 -1
  226. package/dist/esm/surfaces.native.js +1 -33
  227. package/dist/esm/surfaces.native.js.map +1 -1
  228. package/dist/esm/tamagui.native.js.map +1 -1
  229. package/dist/esm/testSetup.native.js.map +1 -1
  230. package/dist/esm/utils/setTinted.native.js.map +1 -1
  231. package/dist/esm/utils/unwrapText.native.js.map +1 -1
  232. package/dist/esm/views/Calendar.native.js.map +1 -1
  233. package/dist/esm/views/Dashboard.native.js.map +1 -1
  234. package/dist/esm/views/Gantt.native.js.map +1 -1
  235. package/dist/esm/views/ImageGrid.native.js.map +1 -1
  236. package/dist/esm/views/List.mjs +2 -4
  237. package/dist/esm/views/List.mjs.map +1 -1
  238. package/dist/esm/views/List.native.js +2 -4
  239. package/dist/esm/views/List.native.js.map +1 -1
  240. package/dist/esm/views/Matrix.mjs +543 -0
  241. package/dist/esm/views/Matrix.mjs.map +1 -0
  242. package/dist/esm/views/Matrix.native.js +573 -0
  243. package/dist/esm/views/Matrix.native.js.map +1 -0
  244. package/dist/esm/views/ReportBuilder.native.js.map +1 -1
  245. package/dist/esm/views/TreeView.mjs +175 -43
  246. package/dist/esm/views/TreeView.mjs.map +1 -1
  247. package/dist/esm/views/TreeView.native.js +181 -46
  248. package/dist/esm/views/TreeView.native.js.map +1 -1
  249. package/dist/esm/views/calendarMath.native.js.map +1 -1
  250. package/dist/esm/views/ganttMath.mjs +1 -1
  251. package/dist/esm/views/ganttMath.mjs.map +1 -1
  252. package/dist/esm/views/ganttMath.native.js +1 -1
  253. package/dist/esm/views/ganttMath.native.js.map +1 -1
  254. package/dist/esm/views/index.mjs +4 -2
  255. package/dist/esm/views/index.mjs.map +1 -1
  256. package/dist/esm/views/index.native.js +4 -2
  257. package/dist/esm/views/index.native.js.map +1 -1
  258. package/dist/esm/views/kanbanDnd.native.js.map +1 -1
  259. package/dist/esm/views/matrixMath.mjs +122 -0
  260. package/dist/esm/views/matrixMath.mjs.map +1 -0
  261. package/dist/esm/views/matrixMath.native.js +191 -0
  262. package/dist/esm/views/matrixMath.native.js.map +1 -0
  263. package/dist/esm/views/treeViewDnd.native.js.map +1 -1
  264. package/dist/esm/views/treeViewLayout.native.js.map +1 -1
  265. package/dist/esm/views/treeViewMotion.native.js.map +1 -1
  266. package/dist/esm/views/treeViewReveal.native.js.map +1 -1
  267. package/dist/jsx/Accordion/index.mjs +3 -7
  268. package/dist/jsx/Accordion/index.mjs.map +1 -1
  269. package/dist/jsx/Accordion/index.native.js +2 -6
  270. package/dist/jsx/Accordion/index.native.js.map +1 -1
  271. package/dist/jsx/AnimateHeight/index.mjs +2 -4
  272. package/dist/jsx/AnimateHeight/index.mjs.map +1 -1
  273. package/dist/jsx/AnimateHeight/index.native.js +1 -3
  274. package/dist/jsx/AnimateHeight/index.native.js.map +1 -1
  275. package/dist/jsx/Chip/index.mjs +9 -2
  276. package/dist/jsx/Chip/index.mjs.map +1 -1
  277. package/dist/jsx/Chip/index.native.js +8 -1
  278. package/dist/jsx/Chip/index.native.js.map +1 -1
  279. package/dist/jsx/SheetModal/index.mjs +22 -3
  280. package/dist/jsx/SheetModal/index.mjs.map +1 -1
  281. package/dist/jsx/SheetModal/index.native.js +115 -27
  282. package/dist/jsx/SheetModal/index.native.js.map +1 -1
  283. package/dist/jsx/Tabs/index.mjs +36 -19
  284. package/dist/jsx/Tabs/index.mjs.map +1 -1
  285. package/dist/jsx/Tabs/index.native.js +39 -18
  286. package/dist/jsx/Tabs/index.native.js.map +1 -1
  287. package/dist/jsx/Text.mjs +3 -1
  288. package/dist/jsx/Text.mjs.map +1 -1
  289. package/dist/jsx/Text.native.js +2 -0
  290. package/dist/jsx/Text.native.js.map +1 -1
  291. package/dist/jsx/TreeSelect/index.mjs +56 -53
  292. package/dist/jsx/TreeSelect/index.mjs.map +1 -1
  293. package/dist/jsx/TreeSelect/index.native.js +55 -52
  294. package/dist/jsx/TreeSelect/index.native.js.map +1 -1
  295. package/dist/jsx/Video/PlayerChrome.mjs +4 -10
  296. package/dist/jsx/Video/PlayerChrome.mjs.map +1 -1
  297. package/dist/jsx/Video/PlayerChrome.native.js +3 -9
  298. package/dist/jsx/Video/PlayerChrome.native.js.map +1 -1
  299. package/dist/jsx/code/Code/index.mjs +6 -0
  300. package/dist/jsx/code/Code/index.mjs.map +1 -1
  301. package/dist/jsx/code/Code/index.native.js +7 -4
  302. package/dist/jsx/code/Code/index.native.js.map +1 -1
  303. package/dist/jsx/code/CodeBlock/index.mjs +5 -6
  304. package/dist/jsx/code/CodeBlock/index.mjs.map +1 -1
  305. package/dist/jsx/code/CodeBlock/index.native.js +4 -5
  306. package/dist/jsx/code/CodeBlock/index.native.js.map +1 -1
  307. package/dist/jsx/icons/themed.mjs +3 -2
  308. package/dist/jsx/icons/themed.mjs.map +1 -1
  309. package/dist/jsx/icons/themed.native.js +2 -1
  310. package/dist/jsx/icons/themed.native.js.map +1 -1
  311. package/dist/jsx/knobImmuneExports.mjs +3 -3
  312. package/dist/jsx/knobImmuneExports.native.js +3 -3
  313. package/dist/jsx/layouts/PaneScaffold.mjs +70 -42
  314. package/dist/jsx/layouts/PaneScaffold.mjs.map +1 -1
  315. package/dist/jsx/layouts/PaneScaffold.native.js +75 -48
  316. package/dist/jsx/layouts/PaneScaffold.native.js.map +1 -1
  317. package/dist/jsx/layouts/page.mjs +3 -2
  318. package/dist/jsx/layouts/page.mjs.map +1 -1
  319. package/dist/jsx/layouts/page.native.js +2 -1
  320. package/dist/jsx/layouts/page.native.js.map +1 -1
  321. package/dist/jsx/layouts/sidebar.mjs +2 -4
  322. package/dist/jsx/layouts/sidebar.mjs.map +1 -1
  323. package/dist/jsx/layouts/sidebar.native.js +1 -3
  324. package/dist/jsx/layouts/sidebar.native.js.map +1 -1
  325. package/dist/jsx/layouts/tags.mjs.map +1 -1
  326. package/dist/jsx/layouts/tags.native.js.map +1 -1
  327. package/dist/jsx/surfaces.mjs +1 -33
  328. package/dist/jsx/surfaces.mjs.map +1 -1
  329. package/dist/jsx/surfaces.native.js +0 -32
  330. package/dist/jsx/surfaces.native.js.map +1 -1
  331. package/dist/jsx/views/List.mjs +2 -4
  332. package/dist/jsx/views/List.mjs.map +1 -1
  333. package/dist/jsx/views/List.native.js +1 -3
  334. package/dist/jsx/views/List.native.js.map +1 -1
  335. package/dist/jsx/views/Matrix.mjs +543 -0
  336. package/dist/jsx/views/Matrix.mjs.map +1 -0
  337. package/dist/jsx/views/Matrix.native.js +612 -0
  338. package/dist/jsx/views/Matrix.native.js.map +1 -0
  339. package/dist/jsx/views/TreeView.mjs +175 -43
  340. package/dist/jsx/views/TreeView.mjs.map +1 -1
  341. package/dist/jsx/views/TreeView.native.js +181 -46
  342. package/dist/jsx/views/TreeView.native.js.map +1 -1
  343. package/dist/jsx/views/ganttMath.mjs +1 -1
  344. package/dist/jsx/views/ganttMath.mjs.map +1 -1
  345. package/dist/jsx/views/ganttMath.native.js +2 -0
  346. package/dist/jsx/views/ganttMath.native.js.map +1 -1
  347. package/dist/jsx/views/index.mjs +4 -2
  348. package/dist/jsx/views/index.mjs.map +1 -1
  349. package/dist/jsx/views/index.native.js +16 -0
  350. package/dist/jsx/views/index.native.js.map +1 -1
  351. package/dist/jsx/views/matrixMath.mjs +122 -0
  352. package/dist/jsx/views/matrixMath.mjs.map +1 -0
  353. package/dist/jsx/views/matrixMath.native.js +229 -0
  354. package/dist/jsx/views/matrixMath.native.js.map +1 -0
  355. package/package.json +12 -12
  356. package/src/Accordion/Accordion.spec.tsx +20 -0
  357. package/src/Accordion/index.tsx +8 -4
  358. package/src/AnimateHeight/index.tsx +143 -142
  359. package/src/Chip/Chip.borderLadder.spec.tsx +54 -0
  360. package/src/Chip/Chip.pressSlop.spec.tsx +57 -0
  361. package/src/Chip/index.tsx +15 -1
  362. package/src/Heading.native.spec.tsx +1 -1
  363. package/src/Separator/index.tsx +3 -3
  364. package/src/SheetModal/SheetModal.detentLayout.spec.tsx +173 -0
  365. package/src/SheetModal/SheetModal.fill.spec.tsx +147 -0
  366. package/src/SheetModal/SheetModal.ownedBody.spec.tsx +200 -0
  367. package/src/SheetModal/SheetModal.stories.spec.tsx +23 -2
  368. package/src/SheetModal/SheetModal.stories.tsx +275 -2
  369. package/src/SheetModal/SheetModal.touch.spec.tsx +63 -0
  370. package/src/SheetModal/index.native.tsx +143 -21
  371. package/src/SheetModal/index.tsx +40 -3
  372. package/src/Tabs/Tabs.hydration.spec.tsx +123 -0
  373. package/src/Tabs/Tabs.lifecycle.spec.tsx +123 -0
  374. package/src/Tabs/Tabs.measurement.spec.tsx +186 -0
  375. package/src/Tabs/Tabs.stories.tsx +43 -0
  376. package/src/Tabs/index.tsx +45 -15
  377. package/src/Text.spec.tsx +32 -2
  378. package/src/Text.tsx +7 -6
  379. package/src/Toast/Toast.spec.tsx +50 -0
  380. package/src/Tooltip/Tooltip.spec.tsx +55 -2
  381. package/src/TreeSelect/TreeSelect.spec.tsx +15 -15
  382. package/src/TreeSelect/index.tsx +53 -50
  383. package/src/Video/PlayerChrome.tsx +4 -3
  384. package/src/Wheel/Wheel.spec.tsx +4 -4
  385. package/src/adjacency.l1.spec.tsx +175 -0
  386. package/src/code/Code/code.spec.tsx +2 -19
  387. package/src/code/Code/index.tsx +0 -6
  388. package/src/code/CodeBlock/index.tsx +5 -3
  389. package/src/code/highlightedCode.spec.tsx +2 -2
  390. package/src/code/hostProps.spec.tsx +55 -0
  391. package/src/icons/themed.hydration.spec.tsx +60 -0
  392. package/src/icons/themed.tsx +3 -6
  393. package/src/knobImmuneExports.ts +3 -3
  394. package/src/layouts/PaneScaffold.spec.tsx +148 -2
  395. package/src/layouts/PaneScaffold.stories.tsx +33 -1
  396. package/src/layouts/PaneScaffold.tsx +101 -48
  397. package/src/layouts/page.designLaw.spec.tsx +20 -0
  398. package/src/layouts/page.tsx +2 -0
  399. package/src/layouts/sidebar.tsx +2 -3
  400. package/src/layouts/tags.tsx +2 -1
  401. package/src/overlayElevation.spec.tsx +39 -51
  402. package/src/surfaces.spec.tsx +13 -10
  403. package/src/surfaces.tsx +4 -33
  404. package/src/tamagui.spec.ts +4 -3
  405. package/src/textAccentSecondary.spec.tsx +100 -2
  406. package/src/views/List.tsx +2 -1
  407. package/src/views/Matrix.spec.tsx +339 -0
  408. package/src/views/Matrix.stories.spec.tsx +68 -0
  409. package/src/views/Matrix.stories.tsx +153 -0
  410. package/src/views/Matrix.tsx +738 -0
  411. package/src/views/TreeView.reveal.spec.tsx +7 -0
  412. package/src/views/TreeView.reveal.stories.tsx +134 -0
  413. package/src/views/TreeView.scroll-index.spec.tsx +246 -0
  414. package/src/views/TreeView.scroll.spec.tsx +711 -50
  415. package/src/views/TreeView.tsx +230 -49
  416. package/src/views/ganttMath.ts +4 -2
  417. package/src/views/index.ts +30 -0
  418. package/src/views/matrixMath.spec.ts +237 -0
  419. package/src/views/matrixMath.ts +251 -0
  420. package/src/views/views.spec.tsx +3 -1
  421. package/types/Accordion/index.d.ts.map +1 -1
  422. package/types/AnimateHeight/index.d.ts.map +1 -1
  423. package/types/Chip/index.d.ts.map +1 -1
  424. package/types/Separator/index.d.ts +3 -3
  425. package/types/SheetModal/index.d.ts +8 -1
  426. package/types/SheetModal/index.d.ts.map +1 -1
  427. package/types/SheetModal/index.native.d.ts +1 -1
  428. package/types/SheetModal/index.native.d.ts.map +1 -1
  429. package/types/Tabs/index.d.ts.map +1 -1
  430. package/types/Text.d.ts.map +1 -1
  431. package/types/TreeSelect/index.d.ts.map +1 -1
  432. package/types/Video/PlayerChrome.d.ts.map +1 -1
  433. package/types/code/Code/index.d.ts.map +1 -1
  434. package/types/code/CodeBlock/index.d.ts.map +1 -1
  435. package/types/icons/themed.d.ts.map +1 -1
  436. package/types/layouts/PaneScaffold.d.ts +14 -1
  437. package/types/layouts/PaneScaffold.d.ts.map +1 -1
  438. package/types/layouts/page.d.ts.map +1 -1
  439. package/types/layouts/sidebar.d.ts.map +1 -1
  440. package/types/layouts/tags.d.ts.map +1 -1
  441. package/types/surfaces.d.ts.map +1 -1
  442. package/types/views/List.d.ts.map +1 -1
  443. package/types/views/Matrix.d.ts +102 -0
  444. package/types/views/Matrix.d.ts.map +1 -0
  445. package/types/views/TreeView.d.ts +10 -1
  446. package/types/views/TreeView.d.ts.map +1 -1
  447. package/types/views/ganttMath.d.ts +4 -0
  448. package/types/views/ganttMath.d.ts.map +1 -1
  449. package/types/views/index.d.ts +3 -1
  450. package/types/views/index.d.ts.map +1 -1
  451. package/types/views/matrixMath.d.ts +114 -0
  452. package/types/views/matrixMath.d.ts.map +1 -0
@@ -27,6 +27,13 @@ describe("TreeView public expansion contract", () => {
27
27
  expectTypeOf<TreeViewProps["revealRequest"]>().toEqualTypeOf<
28
28
  { id: string; requestId: number } | undefined
29
29
  >();
30
+ expectTypeOf<TreeViewProps["onRevealComplete"]>().toEqualTypeOf<
31
+ ((request: { id: string; requestId: number }) => void) | undefined
32
+ >();
33
+ expectTypeOf<TreeViewProps["initialScrollOffset"]>().toEqualTypeOf<number | undefined>();
34
+ expectTypeOf<TreeViewProps["onScrollOffsetChange"]>().toEqualTypeOf<
35
+ ((offset: number) => void) | undefined
36
+ >();
30
37
  expectTypeOf<TreeViewProps["expandedIds"]>().toEqualTypeOf<string[] | undefined>();
31
38
  expectTypeOf<TreeViewProps["onExpandedIdsChange"]>().toEqualTypeOf<
32
39
  ((ids: string[]) => void) | undefined
@@ -36,6 +36,10 @@ function RevealFixture(args: TreeViewProps) {
36
36
  const [expandedIds, setExpandedIds] = useState<string[]>(["other"]);
37
37
  const [selectedId, setSelectedId] = useState<string>();
38
38
  const [revealRequest, setRevealRequest] = useState<TreeViewProps["revealRequest"]>();
39
+ const [completion, setCompletion] = useState<{
40
+ request: NonNullable<TreeViewProps["revealRequest"]>;
41
+ count: number;
42
+ }>();
39
43
  const [deferExpansion, setDeferExpansion] = useState(false);
40
44
  const [pendingExpansion, setPendingExpansion] = useState<string[]>();
41
45
  const [hidden, setHidden] = useState(false);
@@ -77,6 +81,11 @@ function RevealFixture(args: TreeViewProps) {
77
81
  <Text>
78
82
  Target: {revealRequest?.id ?? "none"}. Expanded: {expandedIds.join(", ")}
79
83
  </Text>
84
+ <Text>
85
+ Measured completion:{" "}
86
+ {completion ? `${completion.request.id} (${completion.request.requestId})` : "none"}.
87
+ Callback count: {completion?.count ?? 0}
88
+ </Text>
80
89
  <YStack display={hidden ? "none" : "flex"}>
81
90
  <TreeView
82
91
  {...args}
@@ -88,6 +97,10 @@ function RevealFixture(args: TreeViewProps) {
88
97
  }}
89
98
  selectedId={selectedId}
90
99
  revealRequest={revealRequest}
100
+ onRevealComplete={(request) => {
101
+ setCompletion((previous) => ({ request, count: (previous?.count ?? 0) + 1 }));
102
+ args.onRevealComplete?.(request);
103
+ }}
91
104
  onNodeSelect={(node) => setSelectedId(node.id)}
92
105
  renderNode={(node) => {
93
106
  const index = Number(node.id.replace("item-", ""));
@@ -113,3 +126,124 @@ export const ControlledReveal: Story = {
113
126
  name: "Controlled reveal with 500 variable-height items",
114
127
  render: (args) => <RevealFixture {...args} />,
115
128
  };
129
+
130
+ function RetainedScrollFixture(args: TreeViewProps) {
131
+ const [mounted, setMounted] = useState(true);
132
+ const [generation, setGeneration] = useState(0);
133
+ const [nodes, setNodes] = useState(folders);
134
+ const [hidden, setHidden] = useState(false);
135
+ const [taller, setTaller] = useState(false);
136
+ const [savedOffset, setSavedOffset] = useState<number>();
137
+ const [observations, setObservations] = useState(0);
138
+ const [expandedIds, setExpandedIds] = useState(["folders", "archive", "other"]);
139
+ const [revealRequest, setRevealRequest] = useState<TreeViewProps["revealRequest"]>();
140
+ const [completion, setCompletion] = useState<string>();
141
+ const sequence = useRef(0);
142
+ const revealLast = () => setRevealRequest({ id: "item-499", requestId: ++sequence.current });
143
+ return (
144
+ <YStack gap="$3" width="100%" maxWidth={700}>
145
+ <Text>
146
+ Scroll manually, unmount, then mount. The observed offset and expansion survive outside the
147
+ tree. Remount with delayed data or a hidden host to check deferred restoration.
148
+ </Text>
149
+ <XStack gap="$2" flexWrap="wrap">
150
+ <Button onPress={() => setMounted((value) => !value)}>
151
+ {mounted ? "Unmount tree" : "Mount tree"}
152
+ </Button>
153
+ <Button
154
+ onPress={() => {
155
+ setNodes([]);
156
+ setMounted(true);
157
+ setGeneration((value) => value + 1);
158
+ }}
159
+ >
160
+ Remount without data
161
+ </Button>
162
+ <Button onPress={() => setNodes(folders)}>Deliver data</Button>
163
+ <Button
164
+ onPress={() => {
165
+ setHidden(true);
166
+ setMounted(true);
167
+ setGeneration((value) => value + 1);
168
+ }}
169
+ >
170
+ Remount hidden
171
+ </Button>
172
+ <Button onPress={() => setHidden((value) => !value)}>
173
+ {hidden ? "Show tree" : "Hide tree"}
174
+ </Button>
175
+ </XStack>
176
+ <XStack gap="$2" flexWrap="wrap">
177
+ <Button onPress={revealLast}>Reveal last item</Button>
178
+ <Button
179
+ onPress={() => {
180
+ revealLast();
181
+ setMounted(true);
182
+ setGeneration((value) => value + 1);
183
+ }}
184
+ >
185
+ Remount with reveal
186
+ </Button>
187
+ <Button onPress={() => setTaller((value) => !value)}>
188
+ {taller ? "Use configured height" : "Double viewport height"}
189
+ </Button>
190
+ </XStack>
191
+ <Text>
192
+ Retained observed offset: {savedOffset ?? "none"}. Observations: {observations}.
193
+ </Text>
194
+ <Text>
195
+ Initial fallback: {args.initialScrollOffset ?? "none"}. Mounted: {String(mounted)}.
196
+ </Text>
197
+ <Text>
198
+ Pending reveal: {revealRequest?.requestId ?? "none"}. Measured completion:{" "}
199
+ {completion ?? "none"}.
200
+ </Text>
201
+ <YStack display={hidden ? "none" : "flex"}>
202
+ {mounted && (
203
+ <TreeView
204
+ {...args}
205
+ key={generation}
206
+ nodes={nodes}
207
+ height={taller ? (args.height ?? 240) * 2 : args.height}
208
+ expandedIds={expandedIds}
209
+ onExpandedIdsChange={setExpandedIds}
210
+ initialScrollOffset={savedOffset ?? args.initialScrollOffset}
211
+ onScrollOffsetChange={(offset) => {
212
+ setSavedOffset(offset);
213
+ setObservations((value) => value + 1);
214
+ args.onScrollOffsetChange?.(offset);
215
+ }}
216
+ revealRequest={revealRequest}
217
+ onRevealComplete={(request) => {
218
+ setCompletion(`${request.id} (${request.requestId})`);
219
+ setRevealRequest((pending) =>
220
+ pending?.requestId === request.requestId ? undefined : pending,
221
+ );
222
+ args.onRevealComplete?.(request);
223
+ }}
224
+ renderNode={(node) => {
225
+ const index = Number(node.id.replace("item-", ""));
226
+ return (
227
+ <YStack
228
+ minHeight={Number.isFinite(index) && index % 2 ? 80 : 32}
229
+ justifyContent="center"
230
+ >
231
+ <Text>{node.label}</Text>
232
+ {Number.isFinite(index) && index % 2 === 1 && (
233
+ <Text fontSize="$2">Additional detail</Text>
234
+ )}
235
+ </YStack>
236
+ );
237
+ }}
238
+ />
239
+ )}
240
+ </YStack>
241
+ </YStack>
242
+ );
243
+ }
244
+
245
+ export const RetainedScroll: Story = {
246
+ name: "Retained scroll across unmount and delayed layout",
247
+ args: { initialScrollOffset: 640.5, ariaLabel: "Retained scroll fixture" },
248
+ render: (args) => <RetainedScrollFixture {...args} />,
249
+ };
@@ -0,0 +1,246 @@
1
+ import type { FlashListProps, FlashListRef } from "@shopify/flash-list";
2
+ import { act, cleanup, fireEvent, screen, waitFor } from "@testing-library/react";
3
+ import { renderWithProviders } from "@multiplatform.one/test-utils";
4
+ import { afterEach, expect, it, vi } from "vitest";
5
+ import { TreeView } from "./TreeView";
6
+
7
+ const observed = vi.hoisted(() => ({ list: null as FlashListRef<unknown> | null }));
8
+ vi.mock("@shopify/flash-list", async (importOriginal) => {
9
+ const actual = await importOriginal<typeof import("@shopify/flash-list")>();
10
+ const React = await import("react");
11
+ return {
12
+ ...actual,
13
+ FlashList: React.forwardRef<FlashListRef<unknown>, FlashListProps<unknown>>((props, ref) => {
14
+ const captureRef = React.useCallback(
15
+ (list: FlashListRef<unknown> | null) => {
16
+ observed.list = list;
17
+ if (typeof ref === "function") ref(list);
18
+ else if (ref) ref.current = list;
19
+ },
20
+ [ref],
21
+ );
22
+ return React.createElement(actual.FlashList, { ...props, ref: captureRef });
23
+ }),
24
+ };
25
+ });
26
+ afterEach(() => {
27
+ cleanup();
28
+ vi.restoreAllMocks();
29
+ });
30
+
31
+ it("reports no preparatory index offset while the actual scroll transport is deferred", async () => {
32
+ vi.spyOn(HTMLElement.prototype, "clientWidth", "get").mockReturnValue(320);
33
+ vi.spyOn(HTMLElement.prototype, "clientHeight", "get").mockReturnValue(240);
34
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockReturnValue({
35
+ x: 0,
36
+ y: 0,
37
+ top: 0,
38
+ left: 0,
39
+ right: 320,
40
+ bottom: 240,
41
+ width: 320,
42
+ height: 240,
43
+ toJSON: () => ({}),
44
+ });
45
+ const change = vi.fn();
46
+ renderWithProviders(
47
+ <TreeView
48
+ nodes={Array.from({ length: 100 }, (_, i) => ({ id: `row-${i}`, label: `Row ${i}` }))}
49
+ height={240}
50
+ onScrollOffsetChange={change}
51
+ />,
52
+ );
53
+ await waitFor(() => expect(observed.list?.getChildContainerDimensions().height).toBe(24000));
54
+ await waitFor(() => expect(change).toHaveBeenCalledWith(0));
55
+ expect(observed.list?.getWindowSize().height).toBe(240);
56
+ expect(observed.list?.getLayout(99)?.y).toBe(23760);
57
+ const native = observed.list!.getNativeScrollRef()!;
58
+ const transport = vi.spyOn(native, "scrollTo").mockImplementation(() => {});
59
+ const scroller = native.getScrollableNode();
60
+ const index = vi.spyOn(observed.list!, "scrollToIndex");
61
+ change.mockClear();
62
+ fireEvent.keyDown(screen.getByRole("tree"), { key: "End" });
63
+ expect(index).toHaveBeenCalledExactlyOnceWith({ index: 99, animated: true });
64
+ await act(async () => {
65
+ await new Promise((resolve) => setTimeout(resolve, 40));
66
+ });
67
+ expect(transport).toHaveBeenCalled();
68
+ expect(observed.list!.getAbsoluteLastScrollOffset()).toBeGreaterThan(0);
69
+ expect(scroller.scrollTop).toBe(0);
70
+ expect(change).not.toHaveBeenCalled();
71
+ await act(async () => {
72
+ await index.mock.results[0].value;
73
+ });
74
+ expect(change).not.toHaveBeenCalled();
75
+ fireEvent.scroll(scroller, { target: { scrollTop: 96.5 } });
76
+ await waitFor(() => expect(change).toHaveBeenCalledExactlyOnceWith(96.5));
77
+ change.mockClear();
78
+ fireEvent.keyDown(screen.getByRole("tree"), { key: "Home" });
79
+ expect(index).toHaveBeenLastCalledWith({ index: 0, animated: true });
80
+ await act(async () => {
81
+ await index.mock.results[1].value;
82
+ });
83
+ expect(change).not.toHaveBeenCalled();
84
+ fireEvent.scroll(scroller, { target: { scrollTop: 0 } });
85
+ await waitFor(() => expect(change).toHaveBeenCalledExactlyOnceWith(0));
86
+ });
87
+
88
+ it("positive control: actual scroll delivery reports the transported offset", async () => {
89
+ vi.spyOn(HTMLElement.prototype, "clientWidth", "get").mockReturnValue(320);
90
+ vi.spyOn(HTMLElement.prototype, "clientHeight", "get").mockReturnValue(240);
91
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockReturnValue({
92
+ x: 0,
93
+ y: 0,
94
+ top: 0,
95
+ left: 0,
96
+ right: 320,
97
+ bottom: 240,
98
+ width: 320,
99
+ height: 240,
100
+ toJSON: () => ({}),
101
+ });
102
+ const change = vi.fn();
103
+ renderWithProviders(
104
+ <TreeView
105
+ nodes={Array.from({ length: 100 }, (_, i) => ({ id: `row-${i}`, label: `Row ${i}` }))}
106
+ height={240}
107
+ onScrollOffsetChange={change}
108
+ />,
109
+ );
110
+ await waitFor(() => expect(observed.list?.getChildContainerDimensions().height).toBe(24000));
111
+ await waitFor(() => expect(change).toHaveBeenCalledWith(0));
112
+ change.mockClear();
113
+ const native = observed.list!.getNativeScrollRef()!;
114
+ const scroller = native.getScrollableNode();
115
+ fireEvent.scroll(scroller, { target: { scrollTop: 96.5 } });
116
+ await waitFor(() => expect(change).toHaveBeenCalledWith(96.5));
117
+ });
118
+
119
+ function dimensions() {
120
+ vi.spyOn(HTMLElement.prototype, "clientWidth", "get").mockReturnValue(320);
121
+ vi.spyOn(HTMLElement.prototype, "clientHeight", "get").mockReturnValue(240);
122
+ vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation(
123
+ function (this: HTMLElement) {
124
+ let y = 0;
125
+ for (let ancestor = this.parentElement; ancestor; ancestor = ancestor.parentElement) {
126
+ y -= ancestor.scrollTop;
127
+ }
128
+ return {
129
+ x: 0,
130
+ y,
131
+ top: y,
132
+ left: 0,
133
+ right: 320,
134
+ bottom: y + 240,
135
+ width: 320,
136
+ height: 240,
137
+ toJSON: () => ({}),
138
+ };
139
+ },
140
+ );
141
+ }
142
+
143
+ it.each([false, true])(
144
+ "acknowledges index-prepared reveal only after physical delivery (delivered: %s)",
145
+ async (delivered) => {
146
+ dimensions();
147
+ const nodes = Array.from({ length: 100 }, (_, i) => ({ id: `row-${i}`, label: `Row ${i}` }));
148
+ const change = vi.fn();
149
+ const complete = vi.fn();
150
+ const tree = renderWithProviders(
151
+ <TreeView
152
+ nodes={nodes}
153
+ height={240}
154
+ onScrollOffsetChange={change}
155
+ onRevealComplete={complete}
156
+ />,
157
+ );
158
+ await waitFor(() => expect(observed.list?.getChildContainerDimensions().height).toBe(24000));
159
+ await waitFor(() => expect(change).toHaveBeenCalledWith(0));
160
+ const native = observed.list!.getNativeScrollRef()!;
161
+ const transport = vi.spyOn(native, "scrollTo").mockImplementation(() => {});
162
+ const scroller = native.getScrollableNode();
163
+ const index = vi.spyOn(observed.list!, "scrollToIndex");
164
+ fireEvent.keyDown(screen.getByRole("tree"), { key: "End" });
165
+ await act(async () => {
166
+ await index.mock.results[0].value;
167
+ });
168
+ expect(transport).toHaveBeenCalled();
169
+ expect(scroller.scrollTop).toBe(0);
170
+ const offset = observed.list!.getAbsoluteLastScrollOffset();
171
+ const visible = observed.list!.computeVisibleIndices();
172
+ const id = `row-${visible.startIndex}`;
173
+ const layout = observed.list!.getLayout(visible.startIndex)!;
174
+ expect(offset).toBeGreaterThan(0);
175
+ expect(layout.isHeightMeasured).toBe(true);
176
+ expect(screen.queryByText(`Row ${visible.startIndex}`)).not.toBeNull();
177
+ if (delivered) {
178
+ fireEvent.scroll(scroller, { target: { scrollTop: offset } });
179
+ expect(scroller.scrollTop).toBe(offset);
180
+ await waitFor(() => expect(change).toHaveBeenCalledWith(offset));
181
+ }
182
+ transport.mockClear();
183
+ tree.rerender(
184
+ <TreeView
185
+ nodes={nodes}
186
+ height={240}
187
+ onScrollOffsetChange={change}
188
+ onRevealComplete={complete}
189
+ revealRequest={{ id, requestId: 71 }}
190
+ />,
191
+ );
192
+ await act(async () => {
193
+ await new Promise((resolve) => setTimeout(resolve, 60));
194
+ });
195
+ if (!delivered) {
196
+ expect(complete).not.toHaveBeenCalled();
197
+ expect(scroller.scrollTop).toBe(0);
198
+ expect(transport).toHaveBeenCalledWith({ x: 0, y: offset, animated: false });
199
+ } else {
200
+ expect(complete).toHaveBeenCalledExactlyOnceWith({ id, requestId: 71 });
201
+ }
202
+ fireEvent.scroll(scroller, { target: { scrollTop: offset } });
203
+ await waitFor(() => expect(complete).toHaveBeenCalledExactlyOnceWith({ id, requestId: 71 }));
204
+ },
205
+ );
206
+
207
+ it("reveals an observed keyboard destination without a retention callback", async () => {
208
+ dimensions();
209
+ const nodes = Array.from({ length: 100 }, (_, i) => ({ id: `row-${i}`, label: `Row ${i}` }));
210
+ const complete = vi.fn();
211
+ const tree = renderWithProviders(
212
+ <TreeView nodes={nodes} height={240} onRevealComplete={complete} />,
213
+ );
214
+ await waitFor(() => expect(observed.list?.getChildContainerDimensions().height).toBe(24000));
215
+ const list = observed.list!;
216
+ const native = list.getNativeScrollRef()!;
217
+ const transport = vi.spyOn(native, "scrollTo").mockImplementation(() => {});
218
+ const scroller = native.getScrollableNode();
219
+ const index = vi.spyOn(list, "scrollToIndex");
220
+ fireEvent.keyDown(screen.getByRole("tree"), { key: "End" });
221
+ await act(async () => {
222
+ await index.mock.results[0].value;
223
+ });
224
+ const target = list.computeVisibleIndices().endIndex;
225
+ const layout = list.getLayout(target)!;
226
+ const offset = layout.y + list.getFirstItemOffset();
227
+ expect(offset).toBeGreaterThan(list.getAbsoluteLastScrollOffset());
228
+ expect(layout.isHeightMeasured).toBe(true);
229
+ expect(screen.getByText(`Row ${target}`)).toBeTruthy();
230
+ fireEvent.scroll(scroller, { target: { scrollTop: offset } });
231
+ await waitFor(() => expect(list.getAbsoluteLastScrollOffset()).toBe(offset));
232
+ transport.mockClear();
233
+ const revealScroll = vi.spyOn(list, "scrollToOffset");
234
+ tree.rerender(
235
+ <TreeView
236
+ nodes={nodes}
237
+ height={240}
238
+ onRevealComplete={complete}
239
+ revealRequest={{ id: `row-${target}`, requestId: 72 }}
240
+ />,
241
+ );
242
+ await waitFor(() =>
243
+ expect(complete).toHaveBeenCalledExactlyOnceWith({ id: `row-${target}`, requestId: 72 }),
244
+ );
245
+ expect(revealScroll).not.toHaveBeenCalled();
246
+ });