@multiplatform.one/components 7.81.1 → 7.81.2

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 (367) hide show
  1. package/dist/cjs/Accordion/index.native.js +1 -1
  2. package/dist/cjs/Accordion/index.native.js.map +1 -1
  3. package/dist/cjs/Alert/index.native.js.map +1 -1
  4. package/dist/cjs/AnimateHeight/index.native.js.map +1 -1
  5. package/dist/cjs/Avatar/getInitials.native.js.map +1 -1
  6. package/dist/cjs/Avatar/index.native.js.map +1 -1
  7. package/dist/cjs/Badge/index.native.js.map +1 -1
  8. package/dist/cjs/Button.native.js.map +1 -1
  9. package/dist/cjs/Card.native.js.map +1 -1
  10. package/dist/cjs/CardFooter.native.js.map +1 -1
  11. package/dist/cjs/CardHeader.native.js.map +1 -1
  12. package/dist/cjs/Carousel/index.native.js +3 -3
  13. package/dist/cjs/Carousel/index.native.js.map +1 -1
  14. package/dist/cjs/CheckGlyph/MenuCheckColumn.native.js.map +1 -1
  15. package/dist/cjs/CheckGlyph/index.native.js.map +1 -1
  16. package/dist/cjs/Chip/index.native.js.map +1 -1
  17. package/dist/cjs/Collapsible.native.js.map +1 -1
  18. package/dist/cjs/ContextMenu/index.native.js.map +1 -1
  19. package/dist/cjs/CopyField/CopyMenuButton.native.js +1 -1
  20. package/dist/cjs/CopyField/CopyMenuButton.native.js.map +1 -1
  21. package/dist/cjs/CopyField/index.native.js.map +1 -1
  22. package/dist/cjs/Dialog.native.js.map +1 -1
  23. package/dist/cjs/Diff/diff.native.js.map +1 -1
  24. package/dist/cjs/Diff/index.native.js.map +1 -1
  25. package/dist/cjs/DotIndicator/index.native.js.map +1 -1
  26. package/dist/cjs/DropdownMenu/index.native.js.map +1 -1
  27. package/dist/cjs/DropdownMenu/menuSettle.native.js.map +1 -1
  28. package/dist/cjs/ElapsedProgress/index.native.js.map +1 -1
  29. package/dist/cjs/ErrorBoundary/index.native.js.map +1 -1
  30. package/dist/cjs/Heading.native.js.map +1 -1
  31. package/dist/cjs/Kbd/index.native.js.map +1 -1
  32. package/dist/cjs/Kbd/keys.native.js.map +1 -1
  33. package/dist/cjs/Lightbox/MediaControl.native.js.map +1 -1
  34. package/dist/cjs/Lightbox/index.gnome.native.js.map +1 -1
  35. package/dist/cjs/Lightbox/index.native.js +1 -1
  36. package/dist/cjs/Lightbox/shared.native.js.map +1 -1
  37. package/dist/cjs/Lightbox/useLightbox.native.js.map +1 -1
  38. package/dist/cjs/MachineLiteral/index.native.js.map +1 -1
  39. package/dist/cjs/Material/index.native.js.map +1 -1
  40. package/dist/cjs/Meter/index.native.js +1 -1
  41. package/dist/cjs/Meter/index.native.js.map +1 -1
  42. package/dist/cjs/Meter/meter.native.js.map +1 -1
  43. package/dist/cjs/OverflowRow/index.native.js +1 -1
  44. package/dist/cjs/OverflowRow/index.native.js.map +1 -1
  45. package/dist/cjs/Pagination.native.js +1 -1
  46. package/dist/cjs/Pagination.native.js.map +1 -1
  47. package/dist/cjs/Popover.native.js +1 -1
  48. package/dist/cjs/Popover.native.js.map +1 -1
  49. package/dist/cjs/ProgressSteps/index.native.js.map +1 -1
  50. package/dist/cjs/Quote/index.native.js.map +1 -1
  51. package/dist/cjs/SchemeToggle/index.native.js +1 -1
  52. package/dist/cjs/SchemeToggle/index.native.js.map +1 -1
  53. package/dist/cjs/ScrollView/revealFocusedField.native.js.map +1 -1
  54. package/dist/cjs/Separator/index.native.js.map +1 -1
  55. package/dist/cjs/Sheet.native.js.map +1 -1
  56. package/dist/cjs/SheetModal/SheetHeader.native.js.map +1 -1
  57. package/dist/cjs/SheetModal/SheetNavigation.native.js.map +1 -1
  58. package/dist/cjs/SheetModal/detents.native.js.map +1 -1
  59. package/dist/cjs/SheetModal/useSheetFrameFocus.native.js.map +1 -1
  60. package/dist/cjs/Skeleton/index.native.js.map +1 -1
  61. package/dist/cjs/SkipLink/index.native.js.map +1 -1
  62. package/dist/cjs/SortableList/SortableHandle.native.js.map +1 -1
  63. package/dist/cjs/SortableList/index.native.js.map +1 -1
  64. package/dist/cjs/SortableList/useSortableRows.native.js.map +1 -1
  65. package/dist/cjs/SortableList/useUserOrder.native.js.map +1 -1
  66. package/dist/cjs/Tabs/index.native.js +1 -1
  67. package/dist/cjs/Tabs/index.native.js.map +1 -1
  68. package/dist/cjs/Text.native.js.map +1 -1
  69. package/dist/cjs/ThemePresetPicker/index.native.js +2 -2
  70. package/dist/cjs/ThemePresetPicker/index.native.js.map +1 -1
  71. package/dist/cjs/Toast/index.native.js.map +1 -1
  72. package/dist/cjs/Toast/store.native.js.map +1 -1
  73. package/dist/cjs/Tooltip/nativePress.native.js.map +1 -1
  74. package/dist/cjs/Tooltip/tooltipShared.native.js.map +1 -1
  75. package/dist/cjs/TreeSelect/index.native.js +2 -2
  76. package/dist/cjs/TreeSelect/index.native.js.map +1 -1
  77. package/dist/cjs/TreeSelect/treeSelectModel.native.js.map +1 -1
  78. package/dist/cjs/Video/PlayerChrome.native.js.map +1 -1
  79. package/dist/cjs/Video/VideoFrame.native.js.map +1 -1
  80. package/dist/cjs/Video/types.native.js.map +1 -1
  81. package/dist/cjs/Wheel/index.native.js.map +1 -1
  82. package/dist/cjs/Wizard/index.native.js +2 -2
  83. package/dist/cjs/Wizard/index.native.js.map +1 -1
  84. package/dist/cjs/actions/ActionBar.native.js.map +1 -1
  85. package/dist/cjs/actions/DangerSection.native.js.map +1 -1
  86. package/dist/cjs/actions/DestructiveAction.native.js.map +1 -1
  87. package/dist/cjs/actions/HeaderActions.native.js +2 -2
  88. package/dist/cjs/actions/HeaderActions.native.js.map +1 -1
  89. package/dist/cjs/actions/StandardAction.native.js +1 -1
  90. package/dist/cjs/actions/StandardAction.native.js.map +1 -1
  91. package/dist/cjs/actions/devWarn.native.js.map +1 -1
  92. package/dist/cjs/actions/index.native.js.map +1 -1
  93. package/dist/cjs/actions/severity.native.js.map +1 -1
  94. package/dist/cjs/appShell/AppShell.native.js +1 -1
  95. package/dist/cjs/appShell/AppShell.native.js.map +1 -1
  96. package/dist/cjs/appShell/Dock.native.js.map +1 -1
  97. package/dist/cjs/appShell/MpoTabHost.native.js.map +1 -1
  98. package/dist/cjs/appShell/ScopeMenu.native.js +1 -1
  99. package/dist/cjs/appShell/ScopeMenu.native.js.map +1 -1
  100. package/dist/cjs/appShell/SettingsSplit.native.js +1 -1
  101. package/dist/cjs/appShell/SettingsSplit.native.js.map +1 -1
  102. package/dist/cjs/appShell/Springboard.native.js +1 -1
  103. package/dist/cjs/appShell/Springboard.native.js.map +1 -1
  104. package/dist/cjs/appShell/SystemBar.native.js.map +1 -1
  105. package/dist/cjs/appShell/TabBar.native.js +1 -1
  106. package/dist/cjs/appShell/TabBar.native.js.map +1 -1
  107. package/dist/cjs/appShell/appTile.native.js +1 -1
  108. package/dist/cjs/appShell/appTile.native.js.map +1 -1
  109. package/dist/cjs/appShell/bottomChrome.native.js.map +1 -1
  110. package/dist/cjs/appShell/index.native.js.map +1 -1
  111. package/dist/cjs/charts/Axis.native.js.map +1 -1
  112. package/dist/cjs/charts/BarChart.cjs +1 -0
  113. package/dist/cjs/charts/BarChart.native.js +1 -0
  114. package/dist/cjs/charts/BarChart.native.js.map +1 -1
  115. package/dist/cjs/charts/ChartDataView.cjs +89 -9
  116. package/dist/cjs/charts/ChartDataView.native.js +95 -10
  117. package/dist/cjs/charts/ChartDataView.native.js.map +1 -1
  118. package/dist/cjs/charts/ChartSurface.cjs +26 -8
  119. package/dist/cjs/charts/ChartSurface.native.js +27 -9
  120. package/dist/cjs/charts/ChartSurface.native.js.map +1 -1
  121. package/dist/cjs/charts/LineChart.native.js.map +1 -1
  122. package/dist/cjs/charts/PieChart.native.js.map +1 -1
  123. package/dist/cjs/charts/Sparkline.native.js.map +1 -1
  124. package/dist/cjs/charts/accessibility.native.js.map +1 -1
  125. package/dist/cjs/charts/chartHeight.cjs +1 -1
  126. package/dist/cjs/charts/chartHeight.native.js +1 -1
  127. package/dist/cjs/charts/chartHeight.native.js.map +1 -1
  128. package/dist/cjs/charts/composeChart.cjs +1 -1
  129. package/dist/cjs/charts/composeChart.native.js +1 -1
  130. package/dist/cjs/charts/composeChart.native.js.map +1 -1
  131. package/dist/cjs/charts/index.native.js.map +1 -1
  132. package/dist/cjs/charts/math.native.js.map +1 -1
  133. package/dist/cjs/charts/series.native.js.map +1 -1
  134. package/dist/cjs/charts/svg.native.js.map +1 -1
  135. package/dist/cjs/charts/types.native.js.map +1 -1
  136. package/dist/cjs/charts/useChartTheme.native.js.map +1 -1
  137. package/dist/cjs/code/Code/index.native.js.map +1 -1
  138. package/dist/cjs/code/CodeBlock/index.native.js +7 -7
  139. package/dist/cjs/code/CodeBlock/index.native.js.map +1 -1
  140. package/dist/cjs/code/HighlightedCode/index.native.js.map +1 -1
  141. package/dist/cjs/code/Highlighter/houseSyntaxTheme.native.js.map +1 -1
  142. package/dist/cjs/code/Highlighter/index.native.js.map +1 -1
  143. package/dist/cjs/code/Highlighter/namedGroupMatchAll.native.js.map +1 -1
  144. package/dist/cjs/code/LogView.cjs +142 -0
  145. package/dist/cjs/code/LogView.native.js +151 -0
  146. package/dist/cjs/code/LogView.native.js.map +1 -0
  147. package/dist/cjs/code/Pre/index.native.js.map +1 -1
  148. package/dist/cjs/code/index.cjs +2 -1
  149. package/dist/cjs/code/index.native.js +6 -5
  150. package/dist/cjs/code/index.native.js.map +1 -1
  151. package/dist/cjs/componentColors.native.js.map +1 -1
  152. package/dist/cjs/feedback/ConfirmDialog.native.js.map +1 -1
  153. package/dist/cjs/feedback/NotifyHost.native.js +2 -2
  154. package/dist/cjs/feedback/NotifyHost.native.js.map +1 -1
  155. package/dist/cjs/feedback/copy.native.js.map +1 -1
  156. package/dist/cjs/feedback/index.native.js.map +1 -1
  157. package/dist/cjs/feedback/notify.native.js.map +1 -1
  158. package/dist/cjs/feedback/route.native.js.map +1 -1
  159. package/dist/cjs/feedback/store.native.js.map +1 -1
  160. package/dist/cjs/formLayouts/FormLayouts.native.js +1 -1
  161. package/dist/cjs/formLayouts/FormLayouts.native.js.map +1 -1
  162. package/dist/cjs/formLayouts/PreferencePanel.native.js +2 -2
  163. package/dist/cjs/formLayouts/PreferencePanel.native.js.map +1 -1
  164. package/dist/cjs/formLayouts/index.native.js.map +1 -1
  165. package/dist/cjs/hooks/index.native.js +1 -1
  166. package/dist/cjs/hooks/index.native.js.map +1 -1
  167. package/dist/cjs/hooks/useClipboard.native.js.map +1 -1
  168. package/dist/cjs/hooks/useDocumentTitle.native.js.map +1 -1
  169. package/dist/cjs/hooks/useHoldCue.native.js.map +1 -1
  170. package/dist/cjs/icons/CheckRegular.native.js.map +1 -1
  171. package/dist/cjs/icons/MinusRegular.native.js.map +1 -1
  172. package/dist/cjs/icons/index.native.js.map +1 -1
  173. package/dist/cjs/icons/lucide.native.js.map +1 -1
  174. package/dist/cjs/icons/themed.native.js.map +1 -1
  175. package/dist/cjs/images/Image/ImageFrame.native.js +1 -1
  176. package/dist/cjs/images/Image/ImageFrame.native.js.map +1 -1
  177. package/dist/cjs/images/Image/framing.native.js.map +1 -1
  178. package/dist/cjs/images/Image/index.native.js +1 -1
  179. package/dist/cjs/images/Image/mediaRadius.native.js.map +1 -1
  180. package/dist/cjs/images/Image/shared.native.js +1 -1
  181. package/dist/cjs/images/Image/shared.native.js.map +1 -1
  182. package/dist/cjs/images/Image/types.native.js.map +1 -1
  183. package/dist/cjs/images/index.native.js.map +1 -1
  184. package/dist/cjs/index.native.js +39 -39
  185. package/dist/cjs/index.native.js.map +1 -1
  186. package/dist/cjs/knobImmuneExports.native.js.map +1 -1
  187. package/dist/cjs/layouts/AsyncBoundary.native.js +2 -2
  188. package/dist/cjs/layouts/AsyncBoundary.native.js.map +1 -1
  189. package/dist/cjs/layouts/Debug/index.native.js.map +1 -1
  190. package/dist/cjs/layouts/EmptyState.native.js.map +1 -1
  191. package/dist/cjs/layouts/IdentityPlate.native.js.map +1 -1
  192. package/dist/cjs/layouts/KeyboardAvoidingWrapper/behavior.native.js.map +1 -1
  193. package/dist/cjs/layouts/PageTemplates.cjs +61 -0
  194. package/dist/cjs/layouts/PageTemplates.native.js +62 -0
  195. package/dist/cjs/layouts/PageTemplates.native.js.map +1 -1
  196. package/dist/cjs/layouts/PaneScaffold.native.js.map +1 -1
  197. package/dist/cjs/layouts/SafeAreaWrapper/insets.native.js.map +1 -1
  198. package/dist/cjs/layouts/StatusDot.native.js.map +1 -1
  199. package/dist/cjs/layouts/StatusGlyphStrip.native.js +1 -1
  200. package/dist/cjs/layouts/StatusGlyphStrip.native.js.map +1 -1
  201. package/dist/cjs/layouts/ViewSwitcher.native.js.map +1 -1
  202. package/dist/cjs/layouts/attachments.native.js +1 -1
  203. package/dist/cjs/layouts/attachments.native.js.map +1 -1
  204. package/dist/cjs/layouts/bottomAccessory.native.js.map +1 -1
  205. package/dist/cjs/layouts/breadcrumbs.native.js.map +1 -1
  206. package/dist/cjs/layouts/index.native.js +3 -3
  207. package/dist/cjs/layouts/index.native.js.map +1 -1
  208. package/dist/cjs/layouts/page.native.js +2 -2
  209. package/dist/cjs/layouts/page.native.js.map +1 -1
  210. package/dist/cjs/layouts/pageHeadingScope.native.js.map +1 -1
  211. package/dist/cjs/layouts/screenScroll.native.js.map +1 -1
  212. package/dist/cjs/layouts/shellSidebarSlot.native.js.map +1 -1
  213. package/dist/cjs/layouts/sidebar.native.js +1 -1
  214. package/dist/cjs/layouts/sidebar.native.js.map +1 -1
  215. package/dist/cjs/layouts/tags.native.js +2 -2
  216. package/dist/cjs/layouts/tags.native.js.map +1 -1
  217. package/dist/cjs/layouts/timeline.native.js +2 -2
  218. package/dist/cjs/layouts/timeline.native.js.map +1 -1
  219. package/dist/cjs/layouts/toolbar.native.js +1 -1
  220. package/dist/cjs/layouts/toolbar.native.js.map +1 -1
  221. package/dist/cjs/shared/actionScan.native.js.map +1 -1
  222. package/dist/cjs/shared/i18n.native.js.map +1 -1
  223. package/dist/cjs/shared/restoreRetries.native.js.map +1 -1
  224. package/dist/cjs/shared/t.native.js.map +1 -1
  225. package/dist/cjs/shared/textRidesText.native.js.map +1 -1
  226. package/dist/cjs/shared/useReturnFocusOnClose.native.js.map +1 -1
  227. package/dist/cjs/surfaces.native.js +1 -1
  228. package/dist/cjs/surfaces.native.js.map +1 -1
  229. package/dist/cjs/tamagui.native.js +1 -1
  230. package/dist/cjs/tamagui.native.js.map +1 -1
  231. package/dist/cjs/testSetup.native.js.map +1 -1
  232. package/dist/cjs/utils/setTinted.native.js.map +1 -1
  233. package/dist/cjs/utils/unwrapText.native.js.map +1 -1
  234. package/dist/cjs/views/Calendar.native.js +1 -1
  235. package/dist/cjs/views/Calendar.native.js.map +1 -1
  236. package/dist/cjs/views/Dashboard.native.js +2 -2
  237. package/dist/cjs/views/Dashboard.native.js.map +1 -1
  238. package/dist/cjs/views/Gantt.native.js +2 -2
  239. package/dist/cjs/views/Gantt.native.js.map +1 -1
  240. package/dist/cjs/views/GanttDateGrip.native.js.map +1 -1
  241. package/dist/cjs/views/ImageGrid.cjs +9 -0
  242. package/dist/cjs/views/ImageGrid.native.js +14 -3
  243. package/dist/cjs/views/ImageGrid.native.js.map +1 -1
  244. package/dist/cjs/views/Kanban.native.js +1 -1
  245. package/dist/cjs/views/List.native.js.map +1 -1
  246. package/dist/cjs/views/ListGroup.native.js.map +1 -1
  247. package/dist/cjs/views/ListRow.native.js.map +1 -1
  248. package/dist/cjs/views/Matrix.native.js +2 -2
  249. package/dist/cjs/views/Matrix.native.js.map +1 -1
  250. package/dist/cjs/views/ReportBuilder.native.js +2 -2
  251. package/dist/cjs/views/ReportBuilder.native.js.map +1 -1
  252. package/dist/cjs/views/ShortcutCard.native.js.map +1 -1
  253. package/dist/cjs/views/TreeView.native.js.map +1 -1
  254. package/dist/cjs/views/calendarMath.native.js.map +1 -1
  255. package/dist/cjs/views/ganttIntervals.native.js.map +1 -1
  256. package/dist/cjs/views/ganttMath.native.js.map +1 -1
  257. package/dist/cjs/views/index.native.js +1 -1
  258. package/dist/cjs/views/index.native.js.map +1 -1
  259. package/dist/cjs/views/kanbanDnd.native.js.map +1 -1
  260. package/dist/cjs/views/matrixMath.native.js.map +1 -1
  261. package/dist/cjs/views/sameNameScope.native.js.map +1 -1
  262. package/dist/cjs/views/treeViewDnd.native.js.map +1 -1
  263. package/dist/cjs/views/treeViewLayout.native.js.map +1 -1
  264. package/dist/cjs/views/treeViewMotion.native.js.map +1 -1
  265. package/dist/cjs/views/treeViewReveal.native.js.map +1 -1
  266. package/dist/cjs/views/usePageFlowLoadMore.native.js.map +1 -1
  267. package/dist/cjs/views/widgetChrome.native.js.map +1 -1
  268. package/dist/esm/charts/BarChart.mjs +1 -0
  269. package/dist/esm/charts/BarChart.mjs.map +1 -1
  270. package/dist/esm/charts/BarChart.native.js +1 -0
  271. package/dist/esm/charts/BarChart.native.js.map +1 -1
  272. package/dist/esm/charts/ChartDataView.mjs +83 -3
  273. package/dist/esm/charts/ChartDataView.mjs.map +1 -1
  274. package/dist/esm/charts/ChartDataView.native.js +88 -3
  275. package/dist/esm/charts/ChartDataView.native.js.map +1 -1
  276. package/dist/esm/charts/ChartSurface.mjs +26 -8
  277. package/dist/esm/charts/ChartSurface.mjs.map +1 -1
  278. package/dist/esm/charts/ChartSurface.native.js +27 -9
  279. package/dist/esm/charts/ChartSurface.native.js.map +1 -1
  280. package/dist/esm/charts/chartHeight.mjs +1 -1
  281. package/dist/esm/charts/chartHeight.mjs.map +1 -1
  282. package/dist/esm/charts/chartHeight.native.js +1 -1
  283. package/dist/esm/charts/chartHeight.native.js.map +1 -1
  284. package/dist/esm/charts/composeChart.mjs +1 -1
  285. package/dist/esm/charts/composeChart.mjs.map +1 -1
  286. package/dist/esm/charts/composeChart.native.js +1 -1
  287. package/dist/esm/charts/composeChart.native.js.map +1 -1
  288. package/dist/esm/code/LogView.mjs +117 -0
  289. package/dist/esm/code/LogView.mjs.map +1 -0
  290. package/dist/esm/code/LogView.native.js +123 -0
  291. package/dist/esm/code/LogView.native.js.map +1 -0
  292. package/dist/esm/code/index.mjs +1 -0
  293. package/dist/esm/code/index.mjs.map +1 -1
  294. package/dist/esm/code/index.native.js +1 -0
  295. package/dist/esm/code/index.native.js.map +1 -1
  296. package/dist/esm/layouts/PageTemplates.mjs +61 -1
  297. package/dist/esm/layouts/PageTemplates.mjs.map +1 -1
  298. package/dist/esm/layouts/PageTemplates.native.js +62 -1
  299. package/dist/esm/layouts/PageTemplates.native.js.map +1 -1
  300. package/dist/esm/views/ImageGrid.mjs +10 -1
  301. package/dist/esm/views/ImageGrid.mjs.map +1 -1
  302. package/dist/esm/views/ImageGrid.native.js +13 -2
  303. package/dist/esm/views/ImageGrid.native.js.map +1 -1
  304. package/dist/jsx/charts/BarChart.mjs +1 -0
  305. package/dist/jsx/charts/BarChart.mjs.map +1 -1
  306. package/dist/jsx/charts/BarChart.native.js +1 -0
  307. package/dist/jsx/charts/BarChart.native.js.map +1 -1
  308. package/dist/jsx/charts/ChartDataView.mjs +83 -3
  309. package/dist/jsx/charts/ChartDataView.mjs.map +1 -1
  310. package/dist/jsx/charts/ChartDataView.native.js +94 -9
  311. package/dist/jsx/charts/ChartDataView.native.js.map +1 -1
  312. package/dist/jsx/charts/ChartSurface.mjs +26 -8
  313. package/dist/jsx/charts/ChartSurface.mjs.map +1 -1
  314. package/dist/jsx/charts/ChartSurface.native.js +27 -9
  315. package/dist/jsx/charts/ChartSurface.native.js.map +1 -1
  316. package/dist/jsx/charts/chartHeight.mjs +1 -1
  317. package/dist/jsx/charts/chartHeight.mjs.map +1 -1
  318. package/dist/jsx/charts/chartHeight.native.js +1 -1
  319. package/dist/jsx/charts/chartHeight.native.js.map +1 -1
  320. package/dist/jsx/charts/composeChart.mjs +1 -1
  321. package/dist/jsx/charts/composeChart.mjs.map +1 -1
  322. package/dist/jsx/charts/composeChart.native.js +1 -1
  323. package/dist/jsx/charts/composeChart.native.js.map +1 -1
  324. package/dist/jsx/code/LogView.mjs +117 -0
  325. package/dist/jsx/code/LogView.mjs.map +1 -0
  326. package/dist/jsx/code/LogView.native.js +151 -0
  327. package/dist/jsx/code/LogView.native.js.map +1 -0
  328. package/dist/jsx/code/index.mjs +1 -0
  329. package/dist/jsx/code/index.mjs.map +1 -1
  330. package/dist/jsx/code/index.native.js +1 -0
  331. package/dist/jsx/code/index.native.js.map +1 -1
  332. package/dist/jsx/layouts/PageTemplates.mjs +61 -1
  333. package/dist/jsx/layouts/PageTemplates.mjs.map +1 -1
  334. package/dist/jsx/layouts/PageTemplates.native.js +62 -0
  335. package/dist/jsx/layouts/PageTemplates.native.js.map +1 -1
  336. package/dist/jsx/views/ImageGrid.mjs +10 -1
  337. package/dist/jsx/views/ImageGrid.mjs.map +1 -1
  338. package/dist/jsx/views/ImageGrid.native.js +12 -1
  339. package/dist/jsx/views/ImageGrid.native.js.map +1 -1
  340. package/package.json +9 -9
  341. package/src/charts/BarChart.tsx +8 -2
  342. package/src/charts/ChartDataView.spec.tsx +23 -2
  343. package/src/charts/ChartDataView.tsx +87 -6
  344. package/src/charts/ChartSurface.tsx +17 -8
  345. package/src/charts/chartHeight.ts +8 -2
  346. package/src/charts/composeChart.ts +3 -2
  347. package/src/code/LogView.tsx +127 -0
  348. package/src/code/index.ts +1 -0
  349. package/src/layouts/DenseContent.stories.tsx +93 -0
  350. package/src/layouts/PageTemplates.tsx +90 -0
  351. package/src/views/ImageGrid.tsx +19 -2
  352. package/types/charts/BarChart.d.ts +1 -1
  353. package/types/charts/BarChart.d.ts.map +1 -1
  354. package/types/charts/ChartDataView.d.ts +3 -1
  355. package/types/charts/ChartDataView.d.ts.map +1 -1
  356. package/types/charts/ChartSurface.d.ts.map +1 -1
  357. package/types/charts/chartHeight.d.ts +2 -1
  358. package/types/charts/chartHeight.d.ts.map +1 -1
  359. package/types/charts/composeChart.d.ts +2 -1
  360. package/types/charts/composeChart.d.ts.map +1 -1
  361. package/types/code/LogView.d.ts +31 -0
  362. package/types/code/LogView.d.ts.map +1 -0
  363. package/types/code/index.d.ts +1 -0
  364. package/types/code/index.d.ts.map +1 -1
  365. package/types/layouts/PageTemplates.d.ts +26 -0
  366. package/types/layouts/PageTemplates.d.ts.map +1 -1
  367. package/types/views/ImageGrid.d.ts.map +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multiplatform.one/components",
3
- "version": "7.81.1",
3
+ "version": "7.81.2",
4
4
  "description": "multiplatform.one ui components",
5
5
  "keywords": [
6
6
  "components",
@@ -58,11 +58,11 @@
58
58
  },
59
59
  "dependencies": {
60
60
  "@floating-ui/react": "^0.27.20",
61
- "@multiplatform.one/forms": "^7.81.1",
62
- "@multiplatform.one/i18n": "^7.81.1",
63
- "@multiplatform.one/platform": "^7.81.1",
64
- "@multiplatform.one/router": "^7.81.1",
65
- "@multiplatform.one/theme": "^7.81.1",
61
+ "@multiplatform.one/forms": "^7.81.2",
62
+ "@multiplatform.one/i18n": "^7.81.2",
63
+ "@multiplatform.one/platform": "^7.81.2",
64
+ "@multiplatform.one/router": "^7.81.2",
65
+ "@multiplatform.one/theme": "^7.81.2",
66
66
  "@phosphor-icons/react": "^2.1.10",
67
67
  "@shopify/flash-list": "^2.3.1",
68
68
  "@tamagui/colors": "2.7.6",
@@ -89,9 +89,9 @@
89
89
  "tamagui": "2.7.6"
90
90
  },
91
91
  "devDependencies": {
92
- "@multiplatform.one/config": "7.81.1",
93
- "@multiplatform.one/storybook": "7.81.1",
94
- "@multiplatform.one/test-utils": "7.81.1",
92
+ "@multiplatform.one/config": "7.81.2",
93
+ "@multiplatform.one/storybook": "7.81.2",
94
+ "@multiplatform.one/test-utils": "7.81.2",
95
95
  "@tamagui/build": "2.7.6",
96
96
  "@testing-library/jest-dom": "^7.0.1",
97
97
  "@testing-library/react": "^16.3.3",
@@ -20,7 +20,7 @@ import { useChartTheme } from "./useChartTheme";
20
20
  export interface BarChartProps
21
21
  extends ChartDatumEvents, Omit<YStackProps, "children" | "width" | "height"> {
22
22
  data: ChartDatum[];
23
- /** Drawing height as a theme size token or pixels (default 200). */
23
+ /** Drawing height as a theme size token, pixels, or "fill" (default 200). */
24
24
  height?: ChartHeight;
25
25
  /** Explicit width bypasses responsive measurement. */
26
26
  width?: number;
@@ -85,7 +85,13 @@ export function BarChart({
85
85
  const interactive = Boolean(onDatumPress || onDatumHoverIn || onDatumHoverOut);
86
86
 
87
87
  return (
88
- <ChartDataFrame data={data} title={title} valueFormatter={valueFormatter} width={width}>
88
+ <ChartDataFrame
89
+ data={data}
90
+ title={title}
91
+ valueFormatter={valueFormatter}
92
+ width={width}
93
+ fill={height === "fill"}
94
+ >
89
95
  <ChartSurface
90
96
  label={ariaLabel}
91
97
  proof={{
@@ -2,6 +2,7 @@ import { renderWithProviders } from "@multiplatform.one/test-utils";
2
2
  import { cleanup, fireEvent, screen, waitFor } from "@testing-library/react";
3
3
  import { afterEach, expect, it, vi } from "vitest";
4
4
  import { XStack, YStack } from "tamagui";
5
+ import { BarChart } from "./BarChart";
5
6
  import { ChartDataView } from "./ChartDataView";
6
7
  import { Sparkline } from "./Sparkline";
7
8
  import { PieChart } from "./PieChart";
@@ -29,7 +30,7 @@ it("opens the complete formatted dataset without expanding the concise chart nam
29
30
  )}
30
31
  </ChartDataView>,
31
32
  );
32
- const image = document.querySelector("svg")!;
33
+ const image = document.querySelector("svg[data-mpo-chart]")!;
33
34
  expect(image.getAttribute("aria-label")).toBe("Revenue trend");
34
35
  expect(image.getAttribute("height")).toBe("36");
35
36
  expect(image.querySelector("button")).toBeNull();
@@ -71,7 +72,9 @@ it("keeps a visible pie legend complete without a dangling data-action associati
71
72
  );
72
73
  expect(screen.getByText("Region 13")).toBeInTheDocument();
73
74
  expect(screen.queryByRole("button", { name: "View data for Revenue" })).toBeNull();
74
- expect(document.querySelector("svg")!.getAttribute("aria-describedby")).toBeNull();
75
+ expect(
76
+ document.querySelector("svg[data-mpo-chart]")!.getAttribute("aria-describedby"),
77
+ ).toBeNull();
75
78
  });
76
79
 
77
80
  it("keeps a consumer metric press override separate from the data action", async () => {
@@ -102,3 +105,21 @@ it("keeps a consumer metric press override separate from the data action", async
102
105
  expect(consumer).toHaveBeenCalledTimes(2);
103
106
  expect(configured).not.toHaveBeenCalled();
104
107
  });
108
+
109
+ it("gives a filled chart's remaining height to its values instead of a data action (LC-215, LC-173)", () => {
110
+ renderWithProviders(
111
+ <YStack height={800}>
112
+ <BarChart
113
+ data={data}
114
+ height="fill"
115
+ title="Revenue"
116
+ valueFormatter={(value) => `USD ${value}`}
117
+ />
118
+ </YStack>,
119
+ );
120
+ const inline = document.querySelector("[data-mpo-chart-data-inline]");
121
+ expect(inline).not.toBeNull();
122
+ expect(inline!.querySelectorAll("[data-mpo-chart-data-row]")).toHaveLength(13);
123
+ expect(screen.getByText("USD 13")).toBeInTheDocument();
124
+ expect(document.querySelector("[data-mpo-chart-data-trigger]")).toBeNull();
125
+ });
@@ -1,4 +1,5 @@
1
1
  import { Button } from "@multiplatform.one/forms";
2
+ import { TableIcon } from "@phosphor-icons/react";
2
3
  import { isWeb } from "@multiplatform.one/platform";
3
4
  import { useResolvedKnobs } from "@multiplatform.one/theme";
4
5
  import { createContext, useContext, useId, useState, type ReactNode } from "react";
@@ -6,6 +7,8 @@ import { Paragraph, XStack, YStack } from "tamagui";
6
7
  import { OverlayHeader } from "../actions/StandardAction";
7
8
  import { Dialog } from "../Dialog";
8
9
  import { ScrollView } from "../ScrollView";
10
+ import { Separator } from "../Separator";
11
+ import { Text } from "../Text";
9
12
  import { sectionHeading } from "../componentColors";
10
13
  import { useTranslation } from "../shared/i18n";
11
14
  import { DialogContent, DialogOverlay } from "../surfaces";
@@ -44,13 +47,13 @@ export function ChartDataView({ data, title, valueFormatter, children }: ChartDa
44
47
  const action = (
45
48
  <Dialog.Trigger asChild>
46
49
  <Button
47
- size="$3"
50
+ circular
51
+ chromeless
52
+ icon={TableIcon}
48
53
  id={triggerId}
49
54
  {...(isWeb ? { "aria-label": actionLabel } : { accessibilityLabel: actionLabel })}
50
55
  {...chartWebProps({ "data-mpo-chart-data-trigger": id })}
51
- >
52
- {t("View data")}
53
- </Button>
56
+ />
54
57
  </Dialog.Trigger>
55
58
  );
56
59
  return (
@@ -128,15 +131,41 @@ export function ChartDataFrame({
128
131
  title,
129
132
  valueFormatter,
130
133
  width,
134
+ fill,
131
135
  children,
132
- }: Omit<ChartDataViewProps, "children"> & { children: ReactNode; width?: number }) {
136
+ }: Omit<ChartDataViewProps, "children"> & {
137
+ children: ReactNode;
138
+ width?: number;
139
+ /** The chart flexes to its region's height (LC-215). */
140
+ fill?: boolean;
141
+ }) {
133
142
  const inherited = useContext(ChartDataContext);
134
143
  const { knobProps } = useResolvedKnobs();
135
144
  if (inherited) return children;
145
+ if (fill)
146
+ return (
147
+ <YStack
148
+ minWidth={0}
149
+ width={width ?? "100%"}
150
+ maxWidth="100%"
151
+ flex={1}
152
+ minHeight={0}
153
+ {...knobProps.gap}
154
+ >
155
+ {children}
156
+ <ChartDataList data={data} title={title} valueFormatter={valueFormatter} />
157
+ </YStack>
158
+ );
136
159
  return (
137
160
  <ChartDataView data={data} title={title} valueFormatter={valueFormatter}>
138
161
  {({ action }) => (
139
- <YStack minWidth={0} width={width ?? "100%"} maxWidth="100%" {...knobProps.gap}>
162
+ <YStack
163
+ minWidth={0}
164
+ width={width ?? "100%"}
165
+ maxWidth="100%"
166
+ {...(fill ? { flex: 1, minHeight: 0 } : null)}
167
+ {...knobProps.gap}
168
+ >
140
169
  {children}
141
170
  <XStack justifyContent="flex-end">{action}</XStack>
142
171
  </YStack>
@@ -145,6 +174,58 @@ export function ChartDataFrame({
145
174
  );
146
175
  }
147
176
 
177
+ /**
178
+ * LC-215: a chart that fills its region stops at its aspect and gives the
179
+ * rest of the height to its own values, one row per datum, so the page never
180
+ * ends in an empty band (LC-173) and the data needs no separate action.
181
+ */
182
+ function ChartDataList({
183
+ data,
184
+ title,
185
+ valueFormatter,
186
+ }: Pick<ChartDataViewProps, "data" | "title" | "valueFormatter">) {
187
+ const { t } = useTranslation();
188
+ const { knobProps } = useResolvedKnobs();
189
+ const format = valueFormatter ?? formatChartValue;
190
+ const rows = data.map((datum, index) =>
191
+ typeof datum === "number" ? { label: String(index + 1), value: datum } : datum,
192
+ );
193
+ const label = title ? `${title}: ${t("data")}` : t("Chart data");
194
+ return (
195
+ <ScrollView
196
+ flex={1}
197
+ minHeight={0}
198
+ {...(isWeb ? { "aria-label": label } : { accessibilityLabel: label })}
199
+ {...chartWebProps({ "data-mpo-chart-data-inline": "true" })}
200
+ >
201
+ {rows.map((datum, index) => (
202
+ <YStack key={index}>
203
+ {index > 0 ? <Separator /> : null}
204
+ <XStack
205
+ minHeight={44}
206
+ alignItems="center"
207
+ {...knobProps.gap}
208
+ {...chartWebProps({ "data-mpo-chart-data-row": String(index) })}
209
+ {...(!isWeb
210
+ ? {
211
+ accessible: true,
212
+ accessibilityLabel: describeDatum({ datum, formatValue: format }),
213
+ }
214
+ : {})}
215
+ >
216
+ <Text flex={1} minWidth={0} {...knobProps.body}>
217
+ {datum.label}
218
+ </Text>
219
+ <Text tabular {...knobProps.body} color={knobProps.textRole.meta.color}>
220
+ {format(datum.value)}
221
+ </Text>
222
+ </XStack>
223
+ </YStack>
224
+ ))}
225
+ </ScrollView>
226
+ );
227
+ }
228
+
148
229
  export function useChartDataViewProps(): Record<string, unknown> {
149
230
  const context = useContext(ChartDataContext);
150
231
  if (!context) return {};
@@ -47,28 +47,37 @@ export function ChartSurface({
47
47
  children,
48
48
  ...stackProps
49
49
  }: ChartSurfaceProps) {
50
- const height = useChartHeight(heightProp, 200);
50
+ const fill = heightProp === "fill";
51
+ const fixedHeight = useChartHeight(heightProp, 200);
51
52
  const dataViewProps = useChartDataViewProps();
52
53
  const { motion, animationEnabled } = useChartTheme();
53
- const [measuredWidth, setMeasuredWidth] = useState(0);
54
- const width = widthProp ?? measuredWidth;
54
+ const [measured, setMeasured] = useState({ width: 0, height: 0 });
55
+ const width = widthProp ?? measured.width;
56
+ const height = fill ? measured.height : fixedHeight;
57
+ // LC-215: a filled chart takes its region's height only up to its aspect,
58
+ // so a dozen bars never stand a phone screen tall or a desktop wide.
59
+ const fillCap = width > 0 ? Math.round(width * (width < 600 ? 0.9 : 0.5)) : undefined;
55
60
 
56
61
  const handleLayout = useCallback((event: LayoutChangeEvent) => {
57
- const next = event.nativeEvent.layout.width;
58
- setMeasuredWidth((prev) => (Math.abs(prev - next) >= 0.5 ? next : prev));
62
+ const { width: nextWidth, height: nextHeight } = event.nativeEvent.layout;
63
+ setMeasured((prev) =>
64
+ Math.abs(prev.width - nextWidth) >= 0.5 || Math.abs(prev.height - nextHeight) >= 0.5
65
+ ? { width: nextWidth, height: nextHeight }
66
+ : prev,
67
+ );
59
68
  }, []);
60
69
 
61
70
  return (
62
71
  <YStack
63
72
  width="100%"
64
- height={height}
73
+ {...(fill ? { flex: 1, minHeight: 0, maxHeight: fillCap } : { height })}
65
74
  overflow="hidden"
66
- onLayout={widthProp === undefined ? handleLayout : undefined}
75
+ onLayout={widthProp === undefined || fill ? handleLayout : undefined}
67
76
  {...transitionProps(motion)}
68
77
  {...(animationEnabled ? { enterStyle: { opacity: 0, y: 6 } } : {})}
69
78
  {...stackProps}
70
79
  >
71
- {width > 0 ? (
80
+ {width > 0 && height > 0 ? (
72
81
  <Svg width={width} height={height} {...chartRootA11yProps(label, proof)} {...dataViewProps}>
73
82
  {children({ width, height })}
74
83
  </Svg>
@@ -1,9 +1,15 @@
1
1
  import { getActiveScaleTokens, usePresetContext, type SizeKey } from "@multiplatform.one/theme";
2
2
 
3
- export type ChartHeight = number | SizeKey;
3
+ /** `"fill"` flexes the chart to the height its region hands it (LC-215). */
4
+ export type ChartHeight = number | SizeKey | "fill";
4
5
 
5
6
  export function useChartHeight(height: ChartHeight | undefined, fallback: number): number {
6
7
  usePresetContext();
7
- const value = typeof height === "string" ? getActiveScaleTokens().size[height] : height;
8
+ const value =
9
+ height === "fill"
10
+ ? undefined
11
+ : typeof height === "string"
12
+ ? getActiveScaleTokens().size[height]
13
+ : height;
8
14
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? value : fallback;
9
15
  }
@@ -76,7 +76,8 @@ const X_LABEL_SLOT_GAP = 8;
76
76
  /**
77
77
  * Pick an evenly-strided subset of category labels that fits the plot width
78
78
  * without overlap (LC-10 at phone widths): every label gets a slot sized by
79
- * the widest label (capped), and the stride skips the rest.
79
+ * the widest label (capped), and the stride counts back from the last label
80
+ * so the latest category always keeps its label.
80
81
  */
81
82
  export function thinCategories(labels: string[], plotWidth: number, fontSize: number): string[] {
82
83
  if (labels.length <= 1 || plotWidth <= 0) return labels;
@@ -85,5 +86,5 @@ export function thinCategories(labels: string[], plotWidth: number, fontSize: nu
85
86
  const capacity = Math.max(1, Math.floor(plotWidth / slot));
86
87
  if (labels.length <= capacity) return labels;
87
88
  const stride = Math.ceil(labels.length / capacity);
88
- return labels.filter((_, index) => index % stride === 0);
89
+ return labels.filter((_, index) => (labels.length - 1 - index) % stride === 0);
89
90
  }
@@ -0,0 +1,127 @@
1
+ import { useLayoutSizeClass, useResolvedKnobs } from "@multiplatform.one/theme";
2
+ import { useEffect, useRef } from "react";
3
+ import { ScrollView, Text, View, XStack, YStack, useTheme, type YStackProps } from "tamagui";
4
+ import { WarningIcon, XCircleIcon } from "@phosphor-icons/react";
5
+
6
+ export type LogLevel = "debug" | "info" | "warn" | "error";
7
+
8
+ export interface LogEntry {
9
+ /** Stable key; defaults to the entry's index. */
10
+ id?: string;
11
+ /** When it happened: an ISO string or a Date. Shown as HH:MM:SS. */
12
+ time: string | Date;
13
+ level?: LogLevel;
14
+ /** Who wrote it ("worker-2"), a short muted column. */
15
+ source?: string;
16
+ message: string;
17
+ }
18
+
19
+ export interface LogViewProps extends Omit<YStackProps, "children"> {
20
+ entries: readonly LogEntry[];
21
+ /** Names the log for assistive tech ("Sync worker log"). */
22
+ label: string;
23
+ /** Keep the newest entry in view as entries arrive. Default: true. */
24
+ follow?: boolean;
25
+ }
26
+
27
+ const levelInk = { warn: "yellow11", error: "red11" } as const;
28
+ const levelGlyph = { warn: WarningIcon, error: XCircleIcon } as const;
29
+
30
+ function clockTime(time: string | Date): string {
31
+ const iso = typeof time === "string" ? time : time.toISOString();
32
+ return iso.match(/T(\d{2}:\d{2}:\d{2})/)?.[1] ?? iso;
33
+ }
34
+
35
+ /**
36
+ * A log or terminal stream (LC-215): one row per entry, the time and source
37
+ * in fixed muted columns and the message wrapping under itself, so the
38
+ * columns stay aligned at any width. At compact width the time, level and
39
+ * source sit on a line above the message, which then takes the full width.
40
+ * Only a warning or an error carries a mark: a glyph leading its message in
41
+ * the level's ink, never a word and never a dot between two values (LC-261).
42
+ * The log sits on the page ground and fills whatever
43
+ * region it is given; its first glyph sits on the page line.
44
+ */
45
+ export function LogView({ entries, label, follow = true, ...rest }: LogViewProps) {
46
+ const { knobProps } = useResolvedKnobs({ component: "Screen" });
47
+ const compact = useLayoutSizeClass() === "compact";
48
+ const theme = useTheme();
49
+ const scroller = useRef<{ scrollToEnd?: (options?: { animated?: boolean }) => void } | null>(
50
+ null,
51
+ );
52
+ useEffect(() => {
53
+ if (follow) scroller.current?.scrollToEnd?.({ animated: false });
54
+ }, [entries, follow]);
55
+
56
+ return (
57
+ <YStack flex={1} minHeight={0} data-log-view="" role="log" aria-label={label} {...rest}>
58
+ <ScrollView ref={scroller as never} flex={1} keyboardShouldPersistTaps="handled">
59
+ <YStack
60
+ {...knobProps.panelPadding}
61
+ {...(compact ? null : { paddingHorizontal: 0 })}
62
+ gap={compact ? "$3" : "$1"}
63
+ >
64
+ {entries.map((entry, index) => {
65
+ const level = entry.level === "warn" || entry.level === "error" ? entry.level : null;
66
+ const ink = level ? (`$${levelInk[level]}` as const) : "$color12";
67
+ const Glyph = level ? levelGlyph[level] : null;
68
+ const meta = (
69
+ <>
70
+ <Text fontFamily="$mono" fontSize="$3" color="$color10" flexShrink={0}>
71
+ {clockTime(entry.time)}
72
+ </Text>
73
+ {entry.source ? (
74
+ <Text
75
+ fontFamily="$mono"
76
+ fontSize="$3"
77
+ color="$color10"
78
+ flexShrink={0}
79
+ numberOfLines={1}
80
+ >
81
+ {entry.source}
82
+ </Text>
83
+ ) : null}
84
+ </>
85
+ );
86
+ const message = (
87
+ <XStack
88
+ gap="$1.5"
89
+ alignItems="flex-start"
90
+ flex={compact ? undefined : 1}
91
+ minWidth={0}
92
+ >
93
+ {Glyph ? (
94
+ <View height="$1" justifyContent="center" flexShrink={0} aria-hidden>
95
+ <Glyph
96
+ size={14}
97
+ weight="bold"
98
+ color={
99
+ level ? (theme[levelInk[level]]?.get() as string | undefined) : undefined
100
+ }
101
+ />
102
+ </View>
103
+ ) : null}
104
+ <Text fontFamily="$mono" fontSize="$3" color={ink} flex={1} minWidth={0}>
105
+ {entry.message}
106
+ </Text>
107
+ </XStack>
108
+ );
109
+ return compact ? (
110
+ <YStack key={entry.id ?? index} data-log-entry="">
111
+ <XStack gap="$2" alignItems="center">
112
+ {meta}
113
+ </XStack>
114
+ {message}
115
+ </YStack>
116
+ ) : (
117
+ <XStack key={entry.id ?? index} gap="$3" alignItems="flex-start" data-log-entry="">
118
+ {meta}
119
+ {message}
120
+ </XStack>
121
+ );
122
+ })}
123
+ </YStack>
124
+ </ScrollView>
125
+ </YStack>
126
+ );
127
+ }
package/src/code/index.ts CHANGED
@@ -3,3 +3,4 @@ export * from "./CodeBlock";
3
3
  export * from "./HighlightedCode";
4
4
  export * from "./Highlighter";
5
5
  export * from "./Pre";
6
+ export * from "./LogView";
@@ -0,0 +1,93 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-native-web-vite";
2
+ import { DownloadSimpleIcon, PauseIcon, type IconProps } from "@phosphor-icons/react";
3
+ import { Button } from "@multiplatform.one/forms";
4
+ import { BarChart } from "../charts/BarChart";
5
+ import { LogView, type LogEntry } from "../code/LogView";
6
+ import { DensePageLayout } from "./PageTemplates";
7
+ import { StatusDot } from "./StatusDot";
8
+
9
+ const PauseFillIcon = (props: IconProps) => <PauseIcon weight="fill" {...props} />;
10
+
11
+ const tables = ["customers", "orders", "invoices", "payments", "shipments", "returns"];
12
+
13
+ const logEntries: LogEntry[] = Array.from({ length: 64 }, (_, index) => {
14
+ const second = 7 + index * 13;
15
+ const time = `2026-10-29T14:${String(Math.floor(second / 60) % 60).padStart(2, "0")}:${String(second % 60).padStart(2, "0")}Z`;
16
+ const table = tables[index % tables.length];
17
+ if (index % 17 === 11)
18
+ return {
19
+ time,
20
+ level: "error",
21
+ source: `worker-${index % 4}`,
22
+ message: `push ${table} failed: 409 conflict on row ${1200 + index}, retrying in 4s`,
23
+ };
24
+ if (index % 9 === 4)
25
+ return {
26
+ time,
27
+ level: "warn",
28
+ source: `worker-${index % 4}`,
29
+ message: `${table} lagging 38s behind the primary`,
30
+ };
31
+ return {
32
+ time,
33
+ level: "info",
34
+ source: `worker-${index % 4}`,
35
+ message: `synced ${table}: ${(index * 37) % 400} rows in ${120 + ((index * 53) % 900)} ms`,
36
+ };
37
+ });
38
+
39
+ const weeks = [42, 57, 49, 63, 71, 66, 80, 74, 88, 92, 85, 97];
40
+ const deploys = weeks.map((value, index) => ({ label: `W${index + 31}`, value }));
41
+
42
+ const meta: Meta<typeof DensePageLayout> = {
43
+ title: "Components/DenseContent",
44
+ component: DensePageLayout,
45
+ parameters: {
46
+ status: { type: "beta" },
47
+ layout: "fullscreen",
48
+ docs: {
49
+ description: {
50
+ component:
51
+ "LC-215 DENSE-CONTENT-BLEEDS: a page whose content is a log, terminal or chart keeps its head (title, live status, icon actions) and gives the rest of the height to the surface. On a phone the surface bleeds to both screen edges; from `medium` up it stays in the page column at the measure its content reads at: the page column for a log, the readable `expanded` measure for a chart.",
52
+ },
53
+ },
54
+ },
55
+ };
56
+ export default meta;
57
+
58
+ type Story = StoryObj<typeof DensePageLayout>;
59
+
60
+ export const Log: Story = {
61
+ render: () => (
62
+ <DensePageLayout
63
+ kind="log"
64
+ title="Sync worker"
65
+ status={<StatusDot tone="positive">Running</StatusDot>}
66
+ actions={
67
+ <>
68
+ <Button circular chromeless icon={PauseFillIcon} aria-label="Pause the stream" />
69
+ <Button circular chromeless icon={DownloadSimpleIcon} aria-label="Download the log" />
70
+ </>
71
+ }
72
+ >
73
+ <LogView label="Sync worker log" entries={logEntries} />
74
+ </DensePageLayout>
75
+ ),
76
+ };
77
+
78
+ export const Chart: Story = {
79
+ render: () => (
80
+ <DensePageLayout
81
+ kind="chart"
82
+ measure="readable"
83
+ gutter
84
+ title="Deploys"
85
+ subtitle="Last 12 weeks"
86
+ actions={
87
+ <Button circular chromeless icon={DownloadSimpleIcon} aria-label="Download the data" />
88
+ }
89
+ >
90
+ <BarChart data={deploys} height="fill" title="Deploys per week" />
91
+ </DensePageLayout>
92
+ ),
93
+ };
@@ -315,3 +315,93 @@ export function SettingsPageLayout({
315
315
  </Screen>
316
316
  );
317
317
  }
318
+
319
+ // ── DensePageLayout ────────────────────────────────────────────────────────
320
+
321
+ export interface DensePageLayoutProps
322
+ extends Omit<ScreenProps, "scroll" | "bleed" | "noPadding">, TemplateHeaderProps {
323
+ /** The live state beside the title (a `StatusDot`). */
324
+ status?: ReactNode;
325
+ /**
326
+ * The column the dense region keeps at regular width: `"wide"` (a log or
327
+ * terminal, the page column) or `"readable"` (a chart, the `expanded`
328
+ * measure, so a dozen bars never stretch across a desktop).
329
+ */
330
+ measure?: "wide" | "readable";
331
+ /** Names the dense region (`data-dense-surface`), e.g. "log" or "chart". */
332
+ kind?: string;
333
+ /**
334
+ * Keep the page gutter inside the region on a phone. A chart takes it so its
335
+ * axis labels sit on the page line; a `LogView` pads its own text.
336
+ */
337
+ gutter?: boolean;
338
+ children: ReactNode;
339
+ }
340
+
341
+ /**
342
+ * A page whose content is one dense surface: a log, a terminal or a chart
343
+ * (LC-215). The page keeps its head (title, live status, icon actions) and
344
+ * the surface takes the rest of the height. On a phone the surface bleeds to
345
+ * both screen edges; from `medium` up it stays in the page column, rounded
346
+ * as the page's one surface, at the measure its content reads at.
347
+ */
348
+ export function DensePageLayout({
349
+ title,
350
+ subtitle,
351
+ status,
352
+ actions,
353
+ header,
354
+ nav,
355
+ measure = "wide",
356
+ kind,
357
+ gutter = false,
358
+ maxWidth,
359
+ children,
360
+ ...rest
361
+ }: DensePageLayoutProps) {
362
+ const compact = useLayoutSizeClass() === "compact";
363
+ const { knobProps } = useResolvedKnobs({ component: "Screen" });
364
+ const head =
365
+ header !== undefined ? (
366
+ header
367
+ ) : title || subtitle || actions || nav || status ? (
368
+ <PageHeader title={title} subtitle={subtitle} status={status} actions={actions} nav={nav} />
369
+ ) : null;
370
+ const region = (
371
+ <YStack
372
+ flex={1}
373
+ minHeight={0}
374
+ minWidth={0}
375
+ data-dense-surface={kind}
376
+ {...(compact
377
+ ? gutter
378
+ ? { paddingHorizontal: knobProps.panelPadding.padding as "$4" }
379
+ : null
380
+ : { ...knobProps.containerRadius, overflow: "hidden" })}
381
+ >
382
+ {children}
383
+ </YStack>
384
+ );
385
+ if (compact)
386
+ return (
387
+ <Screen data-canonical="dense-page" scroll={false} bleed noPadding {...rest}>
388
+ {head ? (
389
+ <YStack {...knobProps.panelPadding} paddingBottom={0}>
390
+ {head}
391
+ </YStack>
392
+ ) : null}
393
+ {region}
394
+ </Screen>
395
+ );
396
+ return (
397
+ <Screen
398
+ data-canonical="dense-page"
399
+ scroll={false}
400
+ maxWidth={maxWidth ?? (measure === "readable" ? layoutBreakpoints.expanded : undefined)}
401
+ {...rest}
402
+ >
403
+ {head}
404
+ {region}
405
+ </Screen>
406
+ );
407
+ }