@textui/widgets 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (423) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +69 -0
  3. package/dist/chart/area-chart.d.ts +4 -0
  4. package/dist/chart/area-chart.d.ts.map +1 -0
  5. package/dist/chart/area-chart.js +3 -0
  6. package/dist/chart/bar-chart.d.ts +32 -0
  7. package/dist/chart/bar-chart.d.ts.map +1 -0
  8. package/dist/chart/bar-chart.js +32 -0
  9. package/dist/chart/gauge.d.ts +26 -0
  10. package/dist/chart/gauge.d.ts.map +1 -0
  11. package/dist/chart/gauge.js +26 -0
  12. package/dist/chart/heatmap.d.ts +13 -0
  13. package/dist/chart/heatmap.d.ts.map +1 -0
  14. package/dist/chart/heatmap.js +27 -0
  15. package/dist/chart/histogram.d.ts +12 -0
  16. package/dist/chart/histogram.d.ts.map +1 -0
  17. package/dist/chart/histogram.js +22 -0
  18. package/dist/chart/index.d.ts +20 -0
  19. package/dist/chart/index.d.ts.map +1 -0
  20. package/dist/chart/index.js +32 -0
  21. package/dist/chart/line-chart.d.ts +7 -0
  22. package/dist/chart/line-chart.d.ts.map +1 -0
  23. package/dist/chart/line-chart.js +75 -0
  24. package/dist/chart/shared.d.ts +34 -0
  25. package/dist/chart/shared.d.ts.map +1 -0
  26. package/dist/chart/shared.js +78 -0
  27. package/dist/chart/sparkline.d.ts +15 -0
  28. package/dist/chart/sparkline.d.ts.map +1 -0
  29. package/dist/chart/sparkline.js +22 -0
  30. package/dist/control/button.d.ts +27 -0
  31. package/dist/control/button.d.ts.map +1 -0
  32. package/dist/control/button.js +130 -0
  33. package/dist/control/checkbox.d.ts +10 -0
  34. package/dist/control/checkbox.d.ts.map +1 -0
  35. package/dist/control/checkbox.js +31 -0
  36. package/dist/control/index.d.ts +20 -0
  37. package/dist/control/index.d.ts.map +1 -0
  38. package/dist/control/index.js +36 -0
  39. package/dist/control/radio-group.d.ts +17 -0
  40. package/dist/control/radio-group.d.ts.map +1 -0
  41. package/dist/control/radio-group.js +32 -0
  42. package/dist/control/search-box.d.ts +7 -0
  43. package/dist/control/search-box.d.ts.map +1 -0
  44. package/dist/control/search-box.js +3 -0
  45. package/dist/control/select.d.ts +42 -0
  46. package/dist/control/select.d.ts.map +1 -0
  47. package/dist/control/select.js +166 -0
  48. package/dist/control/shared.d.ts +41 -0
  49. package/dist/control/shared.d.ts.map +1 -0
  50. package/dist/control/shared.js +1 -0
  51. package/dist/control/slider.d.ts +14 -0
  52. package/dist/control/slider.d.ts.map +1 -0
  53. package/dist/control/slider.js +45 -0
  54. package/dist/control/switch.d.ts +10 -0
  55. package/dist/control/switch.d.ts.map +1 -0
  56. package/dist/control/switch.js +32 -0
  57. package/dist/control/text-area.d.ts +87 -0
  58. package/dist/control/text-area.d.ts.map +1 -0
  59. package/dist/control/text-area.js +299 -0
  60. package/dist/control/text-input.d.ts +10 -0
  61. package/dist/control/text-input.d.ts.map +1 -0
  62. package/dist/control/text-input.js +129 -0
  63. package/dist/data/code-viewer.d.ts +71 -0
  64. package/dist/data/code-viewer.d.ts.map +1 -0
  65. package/dist/data/code-viewer.js +232 -0
  66. package/dist/data/feed.d.ts +43 -0
  67. package/dist/data/feed.d.ts.map +1 -0
  68. package/dist/data/feed.js +178 -0
  69. package/dist/data/index.d.ts +54 -0
  70. package/dist/data/index.d.ts.map +1 -0
  71. package/dist/data/index.js +187 -0
  72. package/dist/data/list.d.ts +31 -0
  73. package/dist/data/list.d.ts.map +1 -0
  74. package/dist/data/list.js +104 -0
  75. package/dist/data/log-viewer.d.ts +26 -0
  76. package/dist/data/log-viewer.d.ts.map +1 -0
  77. package/dist/data/log-viewer.js +69 -0
  78. package/dist/data/markdown-view.d.ts +31 -0
  79. package/dist/data/markdown-view.d.ts.map +1 -0
  80. package/dist/data/markdown-view.js +139 -0
  81. package/dist/data/pagination.d.ts +9 -0
  82. package/dist/data/pagination.d.ts.map +1 -0
  83. package/dist/data/pagination.js +18 -0
  84. package/dist/data/scroll-thumb.d.ts +15 -0
  85. package/dist/data/scroll-thumb.d.ts.map +1 -0
  86. package/dist/data/scroll-thumb.js +32 -0
  87. package/dist/data/shared.d.ts +12 -0
  88. package/dist/data/shared.d.ts.map +1 -0
  89. package/dist/data/shared.js +17 -0
  90. package/dist/data/tree.d.ts +35 -0
  91. package/dist/data/tree.d.ts.map +1 -0
  92. package/dist/data/tree.js +158 -0
  93. package/dist/decorations.d.ts +88 -0
  94. package/dist/decorations.d.ts.map +1 -0
  95. package/dist/decorations.js +135 -0
  96. package/dist/display/alert.d.ts +8 -0
  97. package/dist/display/alert.d.ts.map +1 -0
  98. package/dist/display/alert.js +12 -0
  99. package/dist/display/badge.d.ts +10 -0
  100. package/dist/display/badge.d.ts.map +1 -0
  101. package/dist/display/badge.js +21 -0
  102. package/dist/display/card.d.ts +8 -0
  103. package/dist/display/card.d.ts.map +1 -0
  104. package/dist/display/card.js +12 -0
  105. package/dist/display/empty-state.d.ts +10 -0
  106. package/dist/display/empty-state.d.ts.map +1 -0
  107. package/dist/display/empty-state.js +5 -0
  108. package/dist/display/error-state.d.ts +9 -0
  109. package/dist/display/error-state.d.ts.map +1 -0
  110. package/dist/display/error-state.js +7 -0
  111. package/dist/display/heading.d.ts +6 -0
  112. package/dist/display/heading.d.ts.map +1 -0
  113. package/dist/display/heading.js +8 -0
  114. package/dist/display/index.d.ts +25 -0
  115. package/dist/display/index.d.ts.map +1 -0
  116. package/dist/display/index.js +52 -0
  117. package/dist/display/key-value.d.ts +14 -0
  118. package/dist/display/key-value.d.ts.map +1 -0
  119. package/dist/display/key-value.js +11 -0
  120. package/dist/display/label.d.ts +6 -0
  121. package/dist/display/label.d.ts.map +1 -0
  122. package/dist/display/label.js +3 -0
  123. package/dist/display/marquee.d.ts +36 -0
  124. package/dist/display/marquee.d.ts.map +1 -0
  125. package/dist/display/marquee.js +55 -0
  126. package/dist/display/progress.d.ts +39 -0
  127. package/dist/display/progress.d.ts.map +1 -0
  128. package/dist/display/progress.js +46 -0
  129. package/dist/display/skeleton.d.ts +20 -0
  130. package/dist/display/skeleton.d.ts.map +1 -0
  131. package/dist/display/skeleton.js +20 -0
  132. package/dist/display/spinner.d.ts +7 -0
  133. package/dist/display/spinner.d.ts.map +1 -0
  134. package/dist/display/spinner.js +9 -0
  135. package/dist/display/status-dot.d.ts +8 -0
  136. package/dist/display/status-dot.d.ts.map +1 -0
  137. package/dist/display/status-dot.js +13 -0
  138. package/dist/display/timeline.d.ts +12 -0
  139. package/dist/display/timeline.d.ts.map +1 -0
  140. package/dist/display/timeline.js +22 -0
  141. package/dist/find.d.ts +74 -0
  142. package/dist/find.d.ts.map +1 -0
  143. package/dist/find.js +102 -0
  144. package/dist/form/danger-zone.d.ts +11 -0
  145. package/dist/form/danger-zone.d.ts.map +1 -0
  146. package/dist/form/danger-zone.js +15 -0
  147. package/dist/form/field.d.ts +19 -0
  148. package/dist/form/field.d.ts.map +1 -0
  149. package/dist/form/field.js +35 -0
  150. package/dist/form/form-actions.d.ts +11 -0
  151. package/dist/form/form-actions.d.ts.map +1 -0
  152. package/dist/form/form-actions.js +16 -0
  153. package/dist/form/form-section.d.ts +7 -0
  154. package/dist/form/form-section.d.ts.map +1 -0
  155. package/dist/form/form-section.js +5 -0
  156. package/dist/form/form.d.ts +7 -0
  157. package/dist/form/form.d.ts.map +1 -0
  158. package/dist/form/form.js +3 -0
  159. package/dist/form/index.d.ts +42 -0
  160. package/dist/form/index.d.ts.map +1 -0
  161. package/dist/form/index.js +140 -0
  162. package/dist/form/shared.d.ts +25 -0
  163. package/dist/form/shared.d.ts.map +1 -0
  164. package/dist/form/shared.js +9 -0
  165. package/dist/index.d.ts +26 -0
  166. package/dist/index.d.ts.map +1 -0
  167. package/dist/index.js +62 -0
  168. package/dist/layout/center.d.ts +7 -0
  169. package/dist/layout/center.d.ts.map +1 -0
  170. package/dist/layout/center.js +8 -0
  171. package/dist/layout/column.d.ts +3 -0
  172. package/dist/layout/column.d.ts.map +1 -0
  173. package/dist/layout/column.js +2 -0
  174. package/dist/layout/divider.d.ts +11 -0
  175. package/dist/layout/divider.d.ts.map +1 -0
  176. package/dist/layout/divider.js +13 -0
  177. package/dist/layout/grid.d.ts +10 -0
  178. package/dist/layout/grid.d.ts.map +1 -0
  179. package/dist/layout/grid.js +22 -0
  180. package/dist/layout/index.d.ts +19 -0
  181. package/dist/layout/index.d.ts.map +1 -0
  182. package/dist/layout/index.js +36 -0
  183. package/dist/layout/panel.d.ts +37 -0
  184. package/dist/layout/panel.d.ts.map +1 -0
  185. package/dist/layout/panel.js +71 -0
  186. package/dist/layout/row.d.ts +7 -0
  187. package/dist/layout/row.d.ts.map +1 -0
  188. package/dist/layout/row.js +2 -0
  189. package/dist/layout/scroll-view.d.ts +27 -0
  190. package/dist/layout/scroll-view.d.ts.map +1 -0
  191. package/dist/layout/scroll-view.js +93 -0
  192. package/dist/layout/splitter.d.ts +10 -0
  193. package/dist/layout/splitter.d.ts.map +1 -0
  194. package/dist/layout/splitter.js +9 -0
  195. package/dist/layout/stack.d.ts +7 -0
  196. package/dist/layout/stack.d.ts.map +1 -0
  197. package/dist/layout/stack.js +5 -0
  198. package/dist/navigation/breadcrumb.d.ts +14 -0
  199. package/dist/navigation/breadcrumb.d.ts.map +1 -0
  200. package/dist/navigation/breadcrumb.js +24 -0
  201. package/dist/navigation/index.d.ts +17 -0
  202. package/dist/navigation/index.d.ts.map +1 -0
  203. package/dist/navigation/index.js +30 -0
  204. package/dist/navigation/key-hints.d.ts +11 -0
  205. package/dist/navigation/key-hints.d.ts.map +1 -0
  206. package/dist/navigation/key-hints.js +13 -0
  207. package/dist/navigation/menu.d.ts +35 -0
  208. package/dist/navigation/menu.d.ts.map +1 -0
  209. package/dist/navigation/menu.js +88 -0
  210. package/dist/navigation/status-bar.d.ts +18 -0
  211. package/dist/navigation/status-bar.d.ts.map +1 -0
  212. package/dist/navigation/status-bar.js +12 -0
  213. package/dist/navigation/tabs.d.ts +20 -0
  214. package/dist/navigation/tabs.d.ts.map +1 -0
  215. package/dist/navigation/tabs.js +41 -0
  216. package/dist/navigation/toolbar.d.ts +14 -0
  217. package/dist/navigation/toolbar.d.ts.map +1 -0
  218. package/dist/navigation/toolbar.js +10 -0
  219. package/dist/navigation/wizard.d.ts +15 -0
  220. package/dist/navigation/wizard.d.ts.map +1 -0
  221. package/dist/navigation/wizard.js +17 -0
  222. package/dist/overlay/command-palette.d.ts +63 -0
  223. package/dist/overlay/command-palette.d.ts.map +1 -0
  224. package/dist/overlay/command-palette.js +415 -0
  225. package/dist/overlay/dialog.d.ts +16 -0
  226. package/dist/overlay/dialog.d.ts.map +1 -0
  227. package/dist/overlay/dialog.js +44 -0
  228. package/dist/overlay/index.d.ts +84 -0
  229. package/dist/overlay/index.d.ts.map +1 -0
  230. package/dist/overlay/index.js +157 -0
  231. package/dist/overlay/layer-scope.d.ts +21 -0
  232. package/dist/overlay/layer-scope.d.ts.map +1 -0
  233. package/dist/overlay/layer-scope.js +5 -0
  234. package/dist/overlay/path-picker.d.ts +14 -0
  235. package/dist/overlay/path-picker.d.ts.map +1 -0
  236. package/dist/overlay/path-picker.js +200 -0
  237. package/dist/overlay/prompt-dialog.d.ts +12 -0
  238. package/dist/overlay/prompt-dialog.d.ts.map +1 -0
  239. package/dist/overlay/prompt-dialog.js +29 -0
  240. package/dist/overlay/shared.d.ts +17 -0
  241. package/dist/overlay/shared.d.ts.map +1 -0
  242. package/dist/overlay/shared.js +17 -0
  243. package/dist/overlay/toast-host.d.ts +8 -0
  244. package/dist/overlay/toast-host.d.ts.map +1 -0
  245. package/dist/overlay/toast-host.js +19 -0
  246. package/dist/overlay/toast.d.ts +9 -0
  247. package/dist/overlay/toast.d.ts.map +1 -0
  248. package/dist/overlay/toast.js +20 -0
  249. package/dist/overlay/tooltip.d.ts +6 -0
  250. package/dist/overlay/tooltip.d.ts.map +1 -0
  251. package/dist/overlay/tooltip.js +11 -0
  252. package/dist/panel/index.d.ts +79 -0
  253. package/dist/panel/index.d.ts.map +1 -0
  254. package/dist/panel/index.js +256 -0
  255. package/dist/panel/resource-panel.d.ts +93 -0
  256. package/dist/panel/resource-panel.d.ts.map +1 -0
  257. package/dist/panel/resource-panel.js +213 -0
  258. package/dist/panel/shared.d.ts +6 -0
  259. package/dist/panel/shared.d.ts.map +1 -0
  260. package/dist/panel/shared.js +4 -0
  261. package/dist/shells/console-shell.d.ts +8 -0
  262. package/dist/shells/console-shell.d.ts.map +1 -0
  263. package/dist/shells/console-shell.js +30 -0
  264. package/dist/shells/index.d.ts +20 -0
  265. package/dist/shells/index.d.ts.map +1 -0
  266. package/dist/shells/index.js +61 -0
  267. package/dist/shells/paper-shell.d.ts +9 -0
  268. package/dist/shells/paper-shell.d.ts.map +1 -0
  269. package/dist/shells/paper-shell.js +23 -0
  270. package/dist/shells/plain-shell.d.ts +3 -0
  271. package/dist/shells/plain-shell.d.ts.map +1 -0
  272. package/dist/shells/plain-shell.js +11 -0
  273. package/dist/shells/shared.d.ts +12 -0
  274. package/dist/shells/shared.d.ts.map +1 -0
  275. package/dist/shells/shared.js +21 -0
  276. package/dist/shells/workbench-shell.d.ts +9 -0
  277. package/dist/shells/workbench-shell.d.ts.map +1 -0
  278. package/dist/shells/workbench-shell.js +43 -0
  279. package/dist/surface/bar-layout.d.ts +4 -0
  280. package/dist/surface/bar-layout.d.ts.map +1 -0
  281. package/dist/surface/bar-layout.js +7 -0
  282. package/dist/surface/index.d.ts +58 -0
  283. package/dist/surface/index.d.ts.map +1 -0
  284. package/dist/surface/index.js +48 -0
  285. package/dist/surface/inline-layout.d.ts +4 -0
  286. package/dist/surface/inline-layout.d.ts.map +1 -0
  287. package/dist/surface/inline-layout.js +7 -0
  288. package/dist/surface/mount-view.d.ts +7 -0
  289. package/dist/surface/mount-view.d.ts.map +1 -0
  290. package/dist/surface/mount-view.js +19 -0
  291. package/dist/surface/rail-layout.d.ts +4 -0
  292. package/dist/surface/rail-layout.d.ts.map +1 -0
  293. package/dist/surface/rail-layout.js +19 -0
  294. package/dist/surface/shared.d.ts +7 -0
  295. package/dist/surface/shared.d.ts.map +1 -0
  296. package/dist/surface/shared.js +1 -0
  297. package/dist/surface/single-layout.d.ts +4 -0
  298. package/dist/surface/single-layout.d.ts.map +1 -0
  299. package/dist/surface/single-layout.js +18 -0
  300. package/dist/surface/split-layout.d.ts +4 -0
  301. package/dist/surface/split-layout.d.ts.map +1 -0
  302. package/dist/surface/split-layout.js +7 -0
  303. package/dist/surface/stack-layout.d.ts +4 -0
  304. package/dist/surface/stack-layout.d.ts.map +1 -0
  305. package/dist/surface/stack-layout.js +22 -0
  306. package/dist/surface/surface-area.d.ts +16 -0
  307. package/dist/surface/surface-area.d.ts.map +1 -0
  308. package/dist/surface/surface-area.js +32 -0
  309. package/dist/surface/tabs-layout.d.ts +4 -0
  310. package/dist/surface/tabs-layout.d.ts.map +1 -0
  311. package/dist/surface/tabs-layout.js +24 -0
  312. package/dist/tone.d.ts +16 -0
  313. package/dist/tone.d.ts.map +1 -0
  314. package/dist/tone.js +45 -0
  315. package/dist/viewport.d.ts +30 -0
  316. package/dist/viewport.d.ts.map +1 -0
  317. package/dist/viewport.js +17 -0
  318. package/package.json +54 -0
  319. package/src/chart/area-chart.ts +9 -0
  320. package/src/chart/bar-chart.ts +74 -0
  321. package/src/chart/gauge.ts +60 -0
  322. package/src/chart/heatmap.ts +49 -0
  323. package/src/chart/histogram.ts +36 -0
  324. package/src/chart/index.ts +36 -0
  325. package/src/chart/line-chart.ts +100 -0
  326. package/src/chart/shared.ts +112 -0
  327. package/src/chart/sparkline.ts +46 -0
  328. package/src/control/button.ts +184 -0
  329. package/src/control/checkbox.ts +48 -0
  330. package/src/control/index.ts +40 -0
  331. package/src/control/radio-group.ts +60 -0
  332. package/src/control/search-box.ts +15 -0
  333. package/src/control/select.ts +230 -0
  334. package/src/control/shared.ts +41 -0
  335. package/src/control/slider.ts +63 -0
  336. package/src/control/switch.ts +39 -0
  337. package/src/control/text-area.ts +390 -0
  338. package/src/control/text-input.ts +150 -0
  339. package/src/data/code-viewer.ts +337 -0
  340. package/src/data/feed.ts +204 -0
  341. package/src/data/index.ts +243 -0
  342. package/src/data/list.ts +149 -0
  343. package/src/data/log-viewer.ts +105 -0
  344. package/src/data/markdown-view.ts +182 -0
  345. package/src/data/pagination.ts +31 -0
  346. package/src/data/scroll-thumb.ts +40 -0
  347. package/src/data/shared.ts +23 -0
  348. package/src/data/tree.ts +215 -0
  349. package/src/decorations.ts +176 -0
  350. package/src/display/alert.ts +28 -0
  351. package/src/display/badge.ts +40 -0
  352. package/src/display/card.ts +23 -0
  353. package/src/display/empty-state.ts +21 -0
  354. package/src/display/error-state.ts +23 -0
  355. package/src/display/heading.ts +17 -0
  356. package/src/display/index.ts +55 -0
  357. package/src/display/key-value.ts +32 -0
  358. package/src/display/label.ts +11 -0
  359. package/src/display/marquee.ts +88 -0
  360. package/src/display/progress.ts +92 -0
  361. package/src/display/skeleton.ts +34 -0
  362. package/src/display/spinner.ts +20 -0
  363. package/src/display/status-dot.ts +24 -0
  364. package/src/display/timeline.ts +47 -0
  365. package/src/find.ts +138 -0
  366. package/src/form/danger-zone.ts +34 -0
  367. package/src/form/field.ts +61 -0
  368. package/src/form/form-actions.ts +35 -0
  369. package/src/form/form-section.ts +16 -0
  370. package/src/form/form.ts +13 -0
  371. package/src/form/index.ts +191 -0
  372. package/src/form/shared.ts +36 -0
  373. package/src/index.ts +63 -0
  374. package/src/layout/center.ts +17 -0
  375. package/src/layout/column.ts +6 -0
  376. package/src/layout/divider.ts +31 -0
  377. package/src/layout/grid.ts +34 -0
  378. package/src/layout/index.ts +39 -0
  379. package/src/layout/panel.ts +114 -0
  380. package/src/layout/row.ts +11 -0
  381. package/src/layout/scroll-view.ts +115 -0
  382. package/src/layout/splitter.ts +24 -0
  383. package/src/layout/stack.ts +12 -0
  384. package/src/navigation/breadcrumb.ts +43 -0
  385. package/src/navigation/index.ts +33 -0
  386. package/src/navigation/key-hints.ts +25 -0
  387. package/src/navigation/menu.ts +134 -0
  388. package/src/navigation/status-bar.ts +43 -0
  389. package/src/navigation/tabs.ts +73 -0
  390. package/src/navigation/toolbar.ts +25 -0
  391. package/src/navigation/wizard.ts +43 -0
  392. package/src/overlay/command-palette.ts +485 -0
  393. package/src/overlay/dialog.ts +65 -0
  394. package/src/overlay/index.ts +232 -0
  395. package/src/overlay/layer-scope.ts +26 -0
  396. package/src/overlay/path-picker.ts +215 -0
  397. package/src/overlay/prompt-dialog.ts +45 -0
  398. package/src/overlay/shared.ts +19 -0
  399. package/src/overlay/toast-host.ts +30 -0
  400. package/src/overlay/toast.ts +35 -0
  401. package/src/overlay/tooltip.ts +17 -0
  402. package/src/panel/index.ts +317 -0
  403. package/src/panel/resource-panel.ts +304 -0
  404. package/src/panel/shared.ts +8 -0
  405. package/src/shells/console-shell.ts +47 -0
  406. package/src/shells/index.ts +66 -0
  407. package/src/shells/paper-shell.ts +31 -0
  408. package/src/shells/plain-shell.ts +19 -0
  409. package/src/shells/shared.ts +24 -0
  410. package/src/shells/workbench-shell.ts +62 -0
  411. package/src/surface/bar-layout.ts +11 -0
  412. package/src/surface/index.ts +53 -0
  413. package/src/surface/inline-layout.ts +11 -0
  414. package/src/surface/mount-view.ts +30 -0
  415. package/src/surface/rail-layout.ts +27 -0
  416. package/src/surface/shared.ts +7 -0
  417. package/src/surface/single-layout.ts +25 -0
  418. package/src/surface/split-layout.ts +11 -0
  419. package/src/surface/stack-layout.ts +32 -0
  420. package/src/surface/surface-area.ts +46 -0
  421. package/src/surface/tabs-layout.ts +30 -0
  422. package/src/tone.ts +48 -0
  423. package/src/viewport.ts +45 -0
@@ -0,0 +1,71 @@
1
+ import type { BoxProps, RenderOutput, SyntaxToken } from '@textui/core';
2
+ export interface CodeViewerProps extends BoxProps {
3
+ content: string;
4
+ /** Show line numbers in a gutter. */
5
+ lineNumbers?: boolean;
6
+ startLine?: number;
7
+ /**
8
+ * Fix the number of rows. Left off, the viewer renders exactly as many rows
9
+ * as it was laid out into - which is what stops a long file from resizing
10
+ * the pane it is shown in.
11
+ */
12
+ visibleRows?: number;
13
+ /** Rows to mark, 1-based. */
14
+ highlight?: number[];
15
+ /** Pre-tokenised content, when the caller has already highlighted it. */
16
+ tokens?: SyntaxToken[][];
17
+ /** Ask the registry for a highlighter by id... */
18
+ language?: string;
19
+ /** ...or by resource kind... */
20
+ kind?: string;
21
+ /** ...or by filename. */
22
+ uri?: string;
23
+ /** Caret line, 1-based. Controlled when passed. */
24
+ line?: number;
25
+ onLineChange?(line: number): void;
26
+ /** Called whenever the caret or the viewport moves. */
27
+ onPosition?(position: CodeViewerPosition): void;
28
+ /** Draw a scrollbar when the content is taller than the view. */
29
+ scrollbar?: boolean;
30
+ /** Mark the caret line. Off for a plain excerpt. */
31
+ showCaret?: boolean;
32
+ tabWidth?: number;
33
+ /**
34
+ * Take the keyboard on mount.
35
+ *
36
+ * Wanted by a viewer that is the only thing in a dialog: a modal traps focus
37
+ * but does not hand it to anything, so a scrollable body nobody focused is a
38
+ * body nobody can scroll.
39
+ */
40
+ autoFocus?: boolean;
41
+ }
42
+ export interface CodeViewerPosition {
43
+ /** Caret line, 1-based. */
44
+ line: number;
45
+ /** Leftmost visible column, 0-based. */
46
+ column: number;
47
+ /** First visible line, 1-based. */
48
+ top: number;
49
+ rows: number;
50
+ lines: number;
51
+ /** Longest line, in cells. */
52
+ width: number;
53
+ }
54
+ /**
55
+ * How far one press of `left` or `right` pans a viewer that cannot fit its
56
+ * widest line. Exported because every viewer that scrolls sideways has to
57
+ * agree - a diff that panned by one column beside a code view that panned by
58
+ * four would be two different keys wearing the same arrow.
59
+ */
60
+ export declare const HORIZONTAL_STEP = 4;
61
+ /**
62
+ * A file viewer.
63
+ *
64
+ * Two things make this different from a column of `text` nodes. It renders
65
+ * only the rows it was given room for, so opening a ten-thousand-line file
66
+ * costs the same as opening a ten-line one and neither of them moves the panes
67
+ * around it. And it colours by asking the registry for a highlighter, so a new
68
+ * file type arrives coloured without this component learning what it is.
69
+ */
70
+ export declare const CodeViewer: (props: CodeViewerProps) => RenderOutput;
71
+ //# sourceMappingURL=code-viewer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-viewer.d.ts","sourceRoot":"","sources":["../../src/data/code-viewer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAiB,WAAW,EAAE,MAAM,cAAc,CAAC;AAuBvF,MAAM,WAAW,eAAgB,SAAQ,QAAQ;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,qCAAqC;IACrC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,yEAAyE;IACzE,MAAM,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC;IACzB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,yBAAyB;IACzB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,YAAY,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,uDAAuD;IACvD,UAAU,CAAC,CAAC,QAAQ,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChD,iEAAiE;IACjE,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oDAAoD;IACpD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;GAKG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC;;;;;;;;GAQG;AACH,eAAO,MAAM,UAAU,0CAmMrB,CAAC"}
@@ -0,0 +1,232 @@
1
+ import { chorded, defineComponent, expandTabs, h, nameOf, sliceColumns, stringWidth, useEffect, useFocus, useHighlight, useInput, useMeasure, useMemo, useTheme, } from '@textui/core';
2
+ import { MARK_GLYPH, MARK_TONE, useLineMarks } from '../decorations.js';
3
+ import { usePanelState, usePanelStatus } from '../panel/index.js';
4
+ import { viewportRows } from '../viewport.js';
5
+ import { ScrollThumb } from './scroll-thumb.js';
6
+ /**
7
+ * How far one press of `left` or `right` pans a viewer that cannot fit its
8
+ * widest line. Exported because every viewer that scrolls sideways has to
9
+ * agree - a diff that panned by one column beside a code view that panned by
10
+ * four would be two different keys wearing the same arrow.
11
+ */
12
+ export const HORIZONTAL_STEP = 4;
13
+ /**
14
+ * A file viewer.
15
+ *
16
+ * Two things make this different from a column of `text` nodes. It renders
17
+ * only the rows it was given room for, so opening a ten-thousand-line file
18
+ * costs the same as opening a ten-line one and neither of them moves the panes
19
+ * around it. And it colours by asking the registry for a highlighter, so a new
20
+ * file type arrives coloured without this component learning what it is.
21
+ */
22
+ export const CodeViewer = defineComponent('CodeViewer', (props) => {
23
+ const { content, lineNumbers = true, startLine = 1, visibleRows, highlight = [], tokens, language, kind, uri, line, onLineChange, onPosition, scrollbar = true, showCaret = true, tabWidth = 4, disabled, autoFocus, ...rest } = props;
24
+ const theme = useTheme();
25
+ const focus = useFocus({ disabled, ...(autoFocus ? { autoFocus } : {}) });
26
+ const measured = useMeasure();
27
+ const text = useMemo(() => expandTabs(content, tabWidth), [content, tabWidth]);
28
+ const lines = useMemo(() => text.split('\n'), [text]);
29
+ const auto = useHighlight(tokens ? '' : text, { language, kind, uri });
30
+ const lineTokens = tokens ?? auto;
31
+ /*
32
+ * Where this viewer is looking belongs to the panel, not to this component.
33
+ *
34
+ * Switching tabs and coming back, or swapping this viewer for an editor on
35
+ * the same file, both unmount it - and both are the moments a reader most
36
+ * expects to land where they left. `line`, `column`, `top` and `left` are
37
+ * the shared vocabulary for a renderer that measures in source lines, so an
38
+ * editor picks up the caret this viewer left behind. Outside a panel the
39
+ * hook is ordinary component state, which is what a viewer in a dialog gets.
40
+ */
41
+ const [view, setView] = usePanelState({ top: 0, left: 0, line: 0 });
42
+ const top = view.top;
43
+ const setTop = (next) => setView({ top: next });
44
+ const left = view.left;
45
+ const setLeft = (next) => setView({ left: next });
46
+ // The record counts from zero, like an index; this component's `line` prop
47
+ // counts from one, like a gutter. The conversion lives here, once.
48
+ const internalLine = view.line + 1;
49
+ const setInternalLine = (next) => setView({ line: next - 1 });
50
+ const rows = viewportRows(props, measured, lines.length, { requested: visibleRows });
51
+ /*
52
+ * The same marks the editor draws, for the same reason.
53
+ *
54
+ * "This line changed" is true of the file, not of whether you happen to be
55
+ * editing it - and it lived only in the editor, so turning the setting on
56
+ * while reading did nothing at all and said nothing about why.
57
+ *
58
+ * The column costs a cell only when somebody has actually marked something,
59
+ * so a viewer nobody has decorated is the width it always was.
60
+ */
61
+ const marks = useLineMarks(uri ?? null);
62
+ const markWidth = Object.keys(marks).length > 0 ? 1 : 0;
63
+ const gutter = lineNumbers ? String(startLine + lines.length - 1).length : 0;
64
+ const bars = scrollbar && lines.length > rows ? 1 : 0;
65
+ const textWidth = Math.max(1, (measured.width > 0 ? measured.width : 80) - (lineNumbers ? gutter + 1 : 0) - markWidth - bars);
66
+ const longest = useMemo(() => lines.reduce((max, l) => Math.max(max, stringWidth(l)), 0), [lines]);
67
+ const maxTop = Math.max(0, lines.length - rows);
68
+ const maxLeft = Math.max(0, longest - textWidth);
69
+ const caret = clampLine(line ?? internalLine, lines.length);
70
+ // The caret leads and the viewport follows, so arrowing past the last row
71
+ // scrolls rather than parking the caret out of sight.
72
+ const firstVisible = Math.min(Math.max(0, Math.min(top, maxTop)), Math.max(0, Math.min(caret - 1, maxTop)));
73
+ const offset = Math.max(firstVisible, Math.min(caret - rows, maxTop));
74
+ const leftColumn = Math.max(0, Math.min(left, maxLeft));
75
+ const moveTo = (next) => {
76
+ const clamped = clampLine(next, lines.length);
77
+ if (line === undefined)
78
+ setInternalLine(clamped);
79
+ onLineChange?.(clamped);
80
+ if (clamped - 1 < offset)
81
+ setTop(clamped - 1);
82
+ else if (clamped > offset + rows)
83
+ setTop(clamped - rows);
84
+ };
85
+ const scrollBy = (delta) => {
86
+ const next = Math.max(0, Math.min(maxTop, offset + delta));
87
+ setTop(next);
88
+ // Keep the caret inside the view, the way a pager does.
89
+ const clamped = clampLine(Math.min(Math.max(caret, next + 1), next + rows), lines.length);
90
+ if (line === undefined)
91
+ setInternalLine(clamped);
92
+ else
93
+ onLineChange?.(clamped);
94
+ };
95
+ useInput((event) => {
96
+ if (disabled || chorded(event))
97
+ return false;
98
+ switch (event.name) {
99
+ case 'up':
100
+ moveTo(caret - 1);
101
+ return true;
102
+ case 'down':
103
+ moveTo(caret + 1);
104
+ return true;
105
+ case 'pageup':
106
+ moveTo(caret - rows);
107
+ return true;
108
+ case 'pagedown':
109
+ moveTo(caret + rows);
110
+ return true;
111
+ case 'home':
112
+ moveTo(1);
113
+ return true;
114
+ case 'end':
115
+ moveTo(lines.length);
116
+ return true;
117
+ case 'left':
118
+ setLeft(Math.max(0, leftColumn - HORIZONTAL_STEP));
119
+ return true;
120
+ case 'right':
121
+ setLeft(Math.min(maxLeft, leftColumn + HORIZONTAL_STEP));
122
+ return true;
123
+ default: return false;
124
+ }
125
+ }, { focusId: focus.id });
126
+ useEffect(() => {
127
+ onPosition?.({
128
+ line: caret,
129
+ column: leftColumn,
130
+ top: offset + 1,
131
+ rows,
132
+ lines: lines.length,
133
+ width: longest,
134
+ });
135
+ }, [caret, leftColumn, offset, rows, lines.length, longest]);
136
+ /*
137
+ * What this pane says about itself: which file it is showing.
138
+ *
139
+ * A viewer is not an editor and should not pretend to be one - `Ln 12,
140
+ * Col 4` is what the *editor* says, because a caret is a thing you put
141
+ * somewhere and a reader has not put one anywhere. The name is what a
142
+ * reader wants confirmed, particularly in a split where two panes are
143
+ * showing two files and only one of them is focused.
144
+ */
145
+ usePanelStatus(uri !== null && uri !== undefined ? nameOf(uri) : null);
146
+ const body = [];
147
+ for (let i = 0; i < rows; i++) {
148
+ const index = offset + i;
149
+ if (index >= lines.length)
150
+ break;
151
+ const number = startLine + index;
152
+ const marked = highlight.includes(number);
153
+ const onCaret = showCaret && focus.focused && number === caret + startLine - 1;
154
+ // No `gap` on this row: the gap would land between every token, not only
155
+ // between the gutter and the code, and space out the source by a cell per
156
+ // token. The gutter carries its own trailing space instead.
157
+ body.push(h('box', {
158
+ key: number,
159
+ direction: 'row',
160
+ height: 1,
161
+ bg: marked ? 'active' : onCaret ? 'hover' : undefined,
162
+ }, lineNumbers
163
+ ? h('text', {
164
+ content: `${String(number).padStart(gutter)} `,
165
+ fg: onCaret || marked ? 'text' : 'subtle',
166
+ width: gutter + 1,
167
+ })
168
+ : null,
169
+ // Between the number and the code, which is where the editor puts it
170
+ // too - so swapping a viewer for an editor on the same file does not
171
+ // move the text sideways.
172
+ markWidth > 0
173
+ ? h('text', {
174
+ content: MARK_GLYPH[marks[index]] ?? ' ',
175
+ fg: MARK_TONE[marks[index]] ?? 'border',
176
+ width: 1,
177
+ })
178
+ : null, ...spansFor(lineTokens[index] ?? [{ text: lines[index] ?? '', scope: 'plain' }], leftColumn, textWidth, theme)));
179
+ }
180
+ return h('box', {
181
+ id: focus.id,
182
+ role: 'document',
183
+ direction: 'row',
184
+ onMouse: (event) => {
185
+ if (event.action !== 'wheel')
186
+ return false;
187
+ scrollBy((event.wheel ?? 0) * 3);
188
+ return true;
189
+ },
190
+ ...rest,
191
+ }, h('box', { direction: 'column', flex: 1 }, ...body), bars
192
+ ? h(ScrollThumb, { total: lines.length, rows, offset, focused: focus.focused })
193
+ : null);
194
+ });
195
+ function clampLine(line, total) {
196
+ return Math.max(1, Math.min(total === 0 ? 1 : total, Math.round(line)));
197
+ }
198
+ /**
199
+ * One `text` node per token, sliced to the visible columns.
200
+ *
201
+ * Slicing here rather than truncating in the layout is what keeps the viewer
202
+ * from claiming the width of its longest line - which is the horizontal half
203
+ * of the same bug that makes a pane resize when a file is opened.
204
+ */
205
+ function spansFor(tokens, left, width, theme) {
206
+ const out = [];
207
+ let column = 0;
208
+ let drawn = 0;
209
+ for (let i = 0; i < tokens.length && drawn < width; i++) {
210
+ const token = tokens[i];
211
+ const tokenWidth = stringWidth(token.text);
212
+ const end = column + tokenWidth;
213
+ if (end > left) {
214
+ const from = Math.max(0, left - column);
215
+ const slice = sliceColumns(token.text, from, width - drawn);
216
+ if (slice !== '') {
217
+ out.push(h('text', {
218
+ key: i,
219
+ content: slice,
220
+ fg: token.scope === 'plain' ? undefined : theme.syntax[token.scope],
221
+ }));
222
+ drawn += stringWidth(slice);
223
+ }
224
+ }
225
+ column = end;
226
+ }
227
+ // The row must still fill its width, or the caret background stops short of
228
+ // the right edge and the highlight looks ragged.
229
+ if (drawn < width)
230
+ out.push(h('box', { flex: 1 }));
231
+ return out;
232
+ }
@@ -0,0 +1,43 @@
1
+ import type { BoxProps } from '@textui/core';
2
+ export interface FeedProps extends BoxProps {
3
+ /** The entries. Any height each - that is the whole point of this one. */
4
+ children?: unknown;
5
+ /**
6
+ * Stick to the newest entry. Turned off when the reader scrolls up, and back
7
+ * on at the bottom - a feed that yanks itself away is one you cannot read.
8
+ */
9
+ follow?: boolean;
10
+ onFollowChange?(follow: boolean): void;
11
+ /**
12
+ * The cursor, by index. Passed, the caller owns it; omitted, the arrows
13
+ * scroll by line instead, which is what a feed with nothing to activate
14
+ * wants.
15
+ */
16
+ selectedIndex?: number;
17
+ onSelect?(index: number): void;
18
+ onActivate?(index: number): void;
19
+ scrollbar?: boolean;
20
+ focusable?: boolean;
21
+ autoFocus?: boolean;
22
+ /** So a command can send the reader here by name. */
23
+ focusId?: string;
24
+ }
25
+ /**
26
+ * A viewport over entries of any height.
27
+ *
28
+ * The one between `List` and `ScrollView`, and it is not either of them:
29
+ * `List` is fixed-height rows with a selection, `ScrollView` is a dumb
30
+ * viewport, and a feed is entries whose height is whatever their text wrapped
31
+ * to, with a cursor that moves between them and a tail it follows.
32
+ *
33
+ * Heights are **measured, not computed**. What a paragraph wraps to is decided
34
+ * by the layout, so each entry reports its height after it is laid out and the
35
+ * feed scrolls by summing them. That is one frame behind, which is invisible,
36
+ * and it is the only answer that is not a guess.
37
+ *
38
+ * A transcript, an activity stream, search results with snippets, a diff whose
39
+ * files expand - all the same component, because all of them are "an ordered
40
+ * list of things that are not one line tall".
41
+ */
42
+ export declare const Feed: (props: FeedProps) => import("@textui/core").RenderOutput;
43
+ //# sourceMappingURL=feed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feed.d.ts","sourceRoot":"","sources":["../../src/data/feed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAiB7C,MAAM,WAAW,SAAU,SAAQ,QAAQ;IACzC,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,cAAc,CAAC,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACvC;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,UAAU,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,qDAAqD;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,IAAI,2DAiJf,CAAC"}
@@ -0,0 +1,178 @@
1
+ import { chorded, defineComponent, h, useFocus, useInput, useMeasure, useRef, useScrollExtent, useState, } from '@textui/core';
2
+ import { sizedByLayout } from '../viewport.js';
3
+ import { FeedEntry, FeedScrollbar } from './shared.js';
4
+ /**
5
+ * A viewport over entries of any height.
6
+ *
7
+ * The one between `List` and `ScrollView`, and it is not either of them:
8
+ * `List` is fixed-height rows with a selection, `ScrollView` is a dumb
9
+ * viewport, and a feed is entries whose height is whatever their text wrapped
10
+ * to, with a cursor that moves between them and a tail it follows.
11
+ *
12
+ * Heights are **measured, not computed**. What a paragraph wraps to is decided
13
+ * by the layout, so each entry reports its height after it is laid out and the
14
+ * feed scrolls by summing them. That is one frame behind, which is invisible,
15
+ * and it is the only answer that is not a guess.
16
+ *
17
+ * A transcript, an activity stream, search results with snippets, a diff whose
18
+ * files expand - all the same component, because all of them are "an ordered
19
+ * list of things that are not one line tall".
20
+ */
21
+ export const Feed = defineComponent('Feed', (props) => {
22
+ const { children, follow: followProp, onFollowChange, selectedIndex, onSelect, onActivate, scrollbar = true, focusable = true, autoFocus, focusId, id, ...rest } = props;
23
+ const focus = useFocus({
24
+ ...(focusId ? { id: focusId } : {}),
25
+ disabled: !focusable,
26
+ ...(autoFocus ? { autoFocus } : {}),
27
+ });
28
+ const measured = useMeasure();
29
+ const extent = useScrollExtent();
30
+ const heights = useRef([]);
31
+ // The catalog's rule, and this has to follow it like every other viewport:
32
+ // given `flex`, a `height`, a `maxHeight` or a `basis`, the layout decided
33
+ // the size and the feed fills it and scrolls; given none of those, the
34
+ // content decides and it draws everything. Clamping to a measurement in the
35
+ // second case is clamping to how tall it happened to be last frame, which
36
+ // for a box that is sized *by* this content is nothing at all - the entries
37
+ // vanish and the panel is empty.
38
+ const fills = sizedByLayout(props) && measured.height > 0;
39
+ // Null is "at the tail", rather than a boolean beside a number: the two can
40
+ // disagree, and a follow flag that says yes while the offset says otherwise
41
+ // is how a log ends up frozen three lines from the bottom.
42
+ const [internalTop, setInternalTop] = useState(null);
43
+ const [internalIndex, setInternalIndex] = useState(0);
44
+ const entries = (Array.isArray(children) ? children : [children]).filter((c) => c != null);
45
+ const count = entries.length;
46
+ const selects = onSelect !== undefined || selectedIndex !== undefined;
47
+ const index = Math.max(0, Math.min(count - 1, selectedIndex ?? internalIndex));
48
+ const total = extent?.height ?? 0;
49
+ const limit = Math.max(0, total - measured.height);
50
+ const following = followProp ?? (internalTop === null);
51
+ const top = following ? limit : Math.min(internalTop ?? 0, limit);
52
+ const scrollTo = (next) => {
53
+ if (next === null) {
54
+ setInternalTop(null);
55
+ onFollowChange?.(true);
56
+ return;
57
+ }
58
+ const clamped = Math.max(0, Math.min(next, limit));
59
+ setInternalTop(clamped);
60
+ // Scrolled back to the bottom is following again, without a second key.
61
+ onFollowChange?.(clamped >= limit);
62
+ };
63
+ /** Where an entry starts, from what the layout measured last frame. */
64
+ const startOf = (target) => {
65
+ let y = 0;
66
+ for (let i = 0; i < target && i < heights.current.length; i++)
67
+ y += (heights.current[i] ?? 1);
68
+ return y;
69
+ };
70
+ const reveal = (target) => {
71
+ const start = startOf(target);
72
+ const height = heights.current[target] ?? 1;
73
+ const view = Math.max(1, measured.height);
74
+ if (start < top)
75
+ scrollTo(start);
76
+ else if (start + height > top + view)
77
+ scrollTo(start + height - view);
78
+ else
79
+ scrollTo(top);
80
+ };
81
+ const move = (delta) => {
82
+ if (count === 0)
83
+ return;
84
+ const next = Math.max(0, Math.min(count - 1, index + delta));
85
+ if (selectedIndex === undefined)
86
+ setInternalIndex(next);
87
+ onSelect?.(next);
88
+ reveal(next);
89
+ };
90
+ useInput((event) => {
91
+ const page = Math.max(1, measured.height - 2);
92
+ if (chorded(event))
93
+ return false;
94
+ switch (event.name) {
95
+ case 'up':
96
+ case 'k':
97
+ if (selects)
98
+ move(-1);
99
+ else
100
+ scrollTo(top - 1);
101
+ return true;
102
+ case 'down':
103
+ case 'j':
104
+ if (selects)
105
+ move(1);
106
+ else
107
+ scrollTo(top + 1);
108
+ return true;
109
+ case 'pageup':
110
+ scrollTo(top - page);
111
+ return true;
112
+ case 'pagedown':
113
+ scrollTo(top + page);
114
+ return true;
115
+ case 'home':
116
+ case 'g':
117
+ scrollTo(0);
118
+ if (selects) {
119
+ if (selectedIndex === undefined)
120
+ setInternalIndex(0);
121
+ onSelect?.(0);
122
+ }
123
+ return true;
124
+ case 'end':
125
+ case 'G':
126
+ scrollTo(null);
127
+ if (selects && count > 0) {
128
+ if (selectedIndex === undefined)
129
+ setInternalIndex(count - 1);
130
+ onSelect?.(count - 1);
131
+ }
132
+ return true;
133
+ case 'f':
134
+ scrollTo(following ? top : null);
135
+ return true;
136
+ case 'enter':
137
+ case 'space':
138
+ if (onActivate && count > 0) {
139
+ onActivate(index);
140
+ return true;
141
+ }
142
+ return false;
143
+ default: return false;
144
+ }
145
+ }, { focusId: focus.id, enabled: focusable });
146
+ const drawn = entries.map((entry, i) => h(FeedEntry, {
147
+ key: i,
148
+ onHeight: (height) => { heights.current[i] = height; },
149
+ }, entry));
150
+ // Content-sized: draw everything and let the box grow. Clamping to a
151
+ // measurement here would clamp to how tall this happened to be last frame,
152
+ // which for a box sized *by* its own content is nothing at all - the entries
153
+ // vanish and the panel is empty.
154
+ if (!fills) {
155
+ return h('box', {
156
+ id: id ?? focus.id,
157
+ role: 'list',
158
+ ...rest,
159
+ direction: 'column',
160
+ }, ...drawn);
161
+ }
162
+ return h('box', {
163
+ id: id ?? focus.id,
164
+ role: 'list',
165
+ ...rest,
166
+ direction: 'row',
167
+ overflow: 'hidden',
168
+ onMouse: (event) => {
169
+ if (event.action !== 'wheel')
170
+ return false;
171
+ scrollTo(top + (event.wheel ?? 0) * 3);
172
+ return true;
173
+ },
174
+ }, h('box', { flex: 1, direction: 'column', scrollTop: top, overflow: 'scroll' }, ...drawn),
175
+ // Only when there is somewhere to scroll. A track down the side of a feed
176
+ // that fits is chrome that states something untrue.
177
+ scrollbar && limit > 0 ? h(FeedScrollbar, {}) : null);
178
+ });
@@ -0,0 +1,54 @@
1
+ import type { BoxProps, ComponentDefinition, RenderOutput, SemanticVariant } from '@textui/core';
2
+ /**
3
+ * Lists, tables and trees.
4
+ *
5
+ * These are the components that own real interaction state - selection,
6
+ * keyboard navigation, scrolling - so they are the ones where a controlled and
7
+ * an uncontrolled mode both have to work. The rule throughout: if the caller
8
+ * passes the value, the caller owns it; otherwise the component keeps it.
9
+ */
10
+ export * from './code-viewer.js';
11
+ export * from './feed.js';
12
+ export * from './list.js';
13
+ export * from './log-viewer.js';
14
+ export * from './markdown-view.js';
15
+ export * from './pagination.js';
16
+ export * from './scroll-thumb.js';
17
+ export * from './tree.js';
18
+ export interface TableColumn<T extends object = Record<string, unknown>> {
19
+ key: string;
20
+ header: string;
21
+ /** Fixed cell width. Omit to size from the content. */
22
+ width?: number;
23
+ align?: 'left' | 'center' | 'right';
24
+ /** Lower priority columns are dropped first as the table narrows. */
25
+ priority?: number;
26
+ /** Render a cell to a string. Defaults to `String(row[key])`. */
27
+ format?(value: unknown, row: T): string;
28
+ tone?(value: unknown, row: T): SemanticVariant | undefined;
29
+ /** Take the whole remaining width. At most one column should. */
30
+ flex?: boolean;
31
+ }
32
+ export interface TableProps<T extends object = Record<string, unknown>> extends BoxProps {
33
+ columns: TableColumn<T>[];
34
+ rows: T[];
35
+ /** Field used as the row key. Defaults to `id`. */
36
+ rowKey?: string;
37
+ selectedKey?: string;
38
+ onSelect?(key: string, row: T): void;
39
+ onActivate?(key: string, row: T): void;
40
+ visibleRows?: number;
41
+ showHeader?: boolean;
42
+ emptyMessage?: string;
43
+ focusable?: boolean;
44
+ /** Width below which low-priority columns start being dropped. */
45
+ responsive?: boolean;
46
+ }
47
+ /**
48
+ * Exported with its own generic signature so a caller's row type flows into
49
+ * `format` and `tone` - the alternative is every table taking
50
+ * `Record<string, unknown>` and every cell function starting with a cast.
51
+ */
52
+ export declare const Table: <T extends object>(props: TableProps<T>) => RenderOutput;
53
+ export declare const DATA_COMPONENTS: ComponentDefinition[];
54
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/data/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,mBAAmB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAwBjG;;;;;;;GAOG;AACH,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC;AAC1B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAClC,cAAc,WAAW,CAAC;AAE1B,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACrE,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC;IACxC,IAAI,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,GAAG,eAAe,GAAG,SAAS,CAAC;IAC3D,iEAAiE;IACjE,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,MAAM,WAAW,UAAU,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAE,SAAQ,QAAQ;IACtF,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1B,IAAI,EAAE,CAAC,EAAE,CAAC;IACV,mDAAmD;IACnD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;IACrC,UAAU,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AA4JD;;;;GAIG;AACH,eAAO,MAAM,KAAK,EAAgB,CAAC,CAAC,SAAS,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC;AAE3F,eAAO,MAAM,eAAe,EAAE,mBAAmB,EAShD,CAAC"}