@visulima/tui-kit 0.0.0 → 1.0.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 (371) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE.md +2095 -0
  3. package/README.md +115 -29
  4. package/dist/accordion.d.ts +59 -0
  5. package/dist/accordion.js +1 -0
  6. package/dist/alert.d.ts +26 -0
  7. package/dist/alert.js +1 -0
  8. package/dist/animate-presence.d.ts +18 -0
  9. package/dist/animate-presence.js +1 -0
  10. package/dist/approval-prompt.d.ts +65 -0
  11. package/dist/approval-prompt.js +1 -0
  12. package/dist/area-chart.d.ts +66 -0
  13. package/dist/area-chart.js +1 -0
  14. package/dist/badge.d.ts +22 -0
  15. package/dist/badge.js +1 -0
  16. package/dist/bar-chart.d.ts +67 -0
  17. package/dist/bar-chart.js +1 -0
  18. package/dist/big-text.d.ts +81 -0
  19. package/dist/big-text.js +1 -0
  20. package/dist/blink-dot.d.ts +36 -0
  21. package/dist/blink-dot.js +1 -0
  22. package/dist/breadcrumb.d.ts +33 -0
  23. package/dist/breadcrumb.js +1 -0
  24. package/dist/button.d.ts +45 -0
  25. package/dist/button.js +1 -0
  26. package/dist/calendar.d.ts +72 -0
  27. package/dist/calendar.js +1 -0
  28. package/dist/card.d.ts +57 -0
  29. package/dist/card.js +1 -0
  30. package/dist/checkbox-group.d.ts +59 -0
  31. package/dist/checkbox-group.js +1 -0
  32. package/dist/checkbox.d.ts +48 -0
  33. package/dist/checkbox.js +1 -0
  34. package/dist/code.d.ts +48 -0
  35. package/dist/code.js +2 -0
  36. package/dist/collapsible.d.ts +53 -0
  37. package/dist/collapsible.js +1 -0
  38. package/dist/color-picker.d.ts +71 -0
  39. package/dist/color-picker.js +1 -0
  40. package/dist/command-block.d.ts +47 -0
  41. package/dist/command-block.js +4 -0
  42. package/dist/command-palette.d.ts +82 -0
  43. package/dist/command-palette.js +1 -0
  44. package/dist/confirm-dialog.d.ts +75 -0
  45. package/dist/confirm-dialog.js +1 -0
  46. package/dist/confirm-input.d.ts +38 -0
  47. package/dist/confirm-input.js +1 -0
  48. package/dist/console-overlay.d.ts +54 -0
  49. package/dist/console-overlay.js +1 -0
  50. package/dist/content-switcher.d.ts +57 -0
  51. package/dist/content-switcher.js +1 -0
  52. package/dist/controlled-scroll-view.d.ts +3 -0
  53. package/dist/controlled-scroll-view.js +1 -0
  54. package/dist/data-grid.d.ts +49 -0
  55. package/dist/data-grid.js +1 -0
  56. package/dist/date-picker.d.ts +65 -0
  57. package/dist/date-picker.js +1 -0
  58. package/dist/definition-list.d.ts +44 -0
  59. package/dist/definition-list.js +1 -0
  60. package/dist/dialog.d.ts +110 -0
  61. package/dist/dialog.js +1 -0
  62. package/dist/diff-view.d.ts +85 -0
  63. package/dist/diff-view.js +1 -0
  64. package/dist/digits.d.ts +30 -0
  65. package/dist/digits.js +1 -0
  66. package/dist/directory-tree.d.ts +51 -0
  67. package/dist/directory-tree.js +1 -0
  68. package/dist/divider.d.ts +49 -0
  69. package/dist/divider.js +1 -0
  70. package/dist/drawer.d.ts +53 -0
  71. package/dist/drawer.js +1 -0
  72. package/dist/file-change.d.ts +40 -0
  73. package/dist/file-change.js +1 -0
  74. package/dist/file-picker-entry.d.ts +2 -0
  75. package/dist/file-picker-entry.js +1 -0
  76. package/dist/form.d.ts +81 -0
  77. package/dist/form.js +1 -0
  78. package/dist/gauge.d.ts +87 -0
  79. package/dist/gauge.js +1 -0
  80. package/dist/gradient.d.ts +42 -0
  81. package/dist/gradient.js +1 -0
  82. package/dist/grid.d.ts +40 -0
  83. package/dist/grid.js +1 -0
  84. package/dist/heading.d.ts +33 -0
  85. package/dist/heading.js +1 -0
  86. package/dist/heatmap.d.ts +62 -0
  87. package/dist/heatmap.js +1 -0
  88. package/dist/help.d.ts +52 -0
  89. package/dist/help.js +1 -0
  90. package/dist/histogram.d.ts +62 -0
  91. package/dist/histogram.js +1 -0
  92. package/dist/image.d.ts +26 -0
  93. package/dist/image.js +1 -0
  94. package/dist/index.d.ts +125 -0
  95. package/dist/index.js +1 -0
  96. package/dist/json.d.ts +58 -0
  97. package/dist/json.js +1 -0
  98. package/dist/kbd.d.ts +31 -0
  99. package/dist/kbd.js +1 -0
  100. package/dist/line-chart.d.ts +109 -0
  101. package/dist/line-chart.js +1 -0
  102. package/dist/link.d.ts +38 -0
  103. package/dist/link.js +1 -0
  104. package/dist/loading-indicator.d.ts +29 -0
  105. package/dist/loading-indicator.js +1 -0
  106. package/dist/log.d.ts +38 -0
  107. package/dist/log.js +1 -0
  108. package/dist/markdown.d.ts +40 -0
  109. package/dist/markdown.js +1 -0
  110. package/dist/masked-input.d.ts +50 -0
  111. package/dist/masked-input.js +1 -0
  112. package/dist/menu.d.ts +78 -0
  113. package/dist/menu.js +1 -0
  114. package/dist/message-bubble.d.ts +43 -0
  115. package/dist/message-bubble.js +1 -0
  116. package/dist/model-badge.d.ts +39 -0
  117. package/dist/model-badge.js +1 -0
  118. package/dist/model-selector.d.ts +52 -0
  119. package/dist/model-selector.js +1 -0
  120. package/dist/multi-progress.d.ts +55 -0
  121. package/dist/multi-progress.js +1 -0
  122. package/dist/multi-select.d.ts +65 -0
  123. package/dist/multi-select.js +1 -0
  124. package/dist/notification-badge.d.ts +47 -0
  125. package/dist/notification-badge.js +1 -0
  126. package/dist/number-input.d.ts +85 -0
  127. package/dist/number-input.js +1 -0
  128. package/dist/operation-tree.d.ts +49 -0
  129. package/dist/operation-tree.js +1 -0
  130. package/dist/option-list.d.ts +47 -0
  131. package/dist/option-list.js +1 -0
  132. package/dist/ordered-list.d.ts +24 -0
  133. package/dist/ordered-list.js +1 -0
  134. package/dist/packem_shared/ControlledScrollView-BzlbIUph.js +1 -0
  135. package/dist/packem_shared/FilePicker-V5H2fb-v.js +1 -0
  136. package/dist/packem_shared/ScrollBar-C9i3z3Ft.js +1 -0
  137. package/dist/packem_shared/ScrollBarBox-DZEC8YnV.js +1 -0
  138. package/dist/packem_shared/ScrollList-Djtb2vVy.js +1 -0
  139. package/dist/packem_shared/ScrollView-ESxpl6Hy.js +1 -0
  140. package/dist/packem_shared/TreeNodeMap-cJlYqckB.js +1 -0
  141. package/dist/packem_shared/TreeView-q0l446NV.js +1 -0
  142. package/dist/packem_shared/controlled-scroll-view-DerVKKv6.js +1 -0
  143. package/dist/packem_shared/controlled-scroll-view.d-vF4wevEJ.d.ts +54 -0
  144. package/dist/packem_shared/file-picker.d-Cie6aAMD.d.ts +104 -0
  145. package/dist/packem_shared/line-chart-BbhMhcZg.js +1 -0
  146. package/dist/packem_shared/scroll-bar-box.d-DSBbBsRc.d.ts +30 -0
  147. package/dist/packem_shared/scroll-bar.d-B4sD1hBR.d.ts +18 -0
  148. package/dist/packem_shared/scroll-list.d-BP0UZSY4.d.ts +12 -0
  149. package/dist/packem_shared/scroll-view.d-BqKpI-F-.d.ts +119 -0
  150. package/dist/packem_shared/treeViewTheme-Dq3ekRAC.js +1 -0
  151. package/dist/packem_shared/use-tree-view.d-dXTKoDPM.d.ts +350 -0
  152. package/dist/packem_shared/useTreeView-D0JEqT6W.js +1 -0
  153. package/dist/packem_shared/useTreeViewState-BiTJakkh.js +1 -0
  154. package/dist/packem_shared/variant-config-BJqpNo7H.js +1 -0
  155. package/dist/packem_shared/variant-config.d-D5NnrrQK.d.ts +2 -0
  156. package/dist/paginator.d.ts +69 -0
  157. package/dist/paginator.js +1 -0
  158. package/dist/paragraph.d.ts +38 -0
  159. package/dist/paragraph.js +1 -0
  160. package/dist/path-input.d.ts +67 -0
  161. package/dist/path-input.js +1 -0
  162. package/dist/pie-chart.d.ts +50 -0
  163. package/dist/pie-chart.js +1 -0
  164. package/dist/placeholder.d.ts +55 -0
  165. package/dist/placeholder.js +1 -0
  166. package/dist/popover.d.ts +46 -0
  167. package/dist/popover.js +1 -0
  168. package/dist/progress-bar.d.ts +51 -0
  169. package/dist/progress-bar.js +1 -0
  170. package/dist/progress-circle.d.ts +59 -0
  171. package/dist/progress-circle.js +1 -0
  172. package/dist/qr-code.d.ts +45 -0
  173. package/dist/qr-code.js +1 -0
  174. package/dist/r/accordion.json +24 -0
  175. package/dist/r/alert.json +24 -0
  176. package/dist/r/animate-presence.json +22 -0
  177. package/dist/r/approval-prompt.json +24 -0
  178. package/dist/r/area-chart.json +27 -0
  179. package/dist/r/badge.json +24 -0
  180. package/dist/r/bar-chart.json +24 -0
  181. package/dist/r/big-text.json +23 -0
  182. package/dist/r/blink-dot.json +24 -0
  183. package/dist/r/breadcrumb.json +24 -0
  184. package/dist/r/button.json +24 -0
  185. package/dist/r/calendar.json +24 -0
  186. package/dist/r/card.json +26 -0
  187. package/dist/r/chart-utils.json +24 -0
  188. package/dist/r/checkbox-group.json +24 -0
  189. package/dist/r/checkbox.json +24 -0
  190. package/dist/r/code.json +23 -0
  191. package/dist/r/collapsible.json +24 -0
  192. package/dist/r/color-picker.json +24 -0
  193. package/dist/r/command-block.json +26 -0
  194. package/dist/r/command-palette.json +24 -0
  195. package/dist/r/confirm-dialog.json +24 -0
  196. package/dist/r/confirm-input.json +22 -0
  197. package/dist/r/console-overlay.json +22 -0
  198. package/dist/r/content-switcher.json +24 -0
  199. package/dist/r/controlled-scroll-view.json +24 -0
  200. package/dist/r/data-grid.json +24 -0
  201. package/dist/r/date-picker.json +26 -0
  202. package/dist/r/definition-list.json +24 -0
  203. package/dist/r/dialog.json +24 -0
  204. package/dist/r/diff-view.json +24 -0
  205. package/dist/r/digits.json +24 -0
  206. package/dist/r/directory-tree.json +24 -0
  207. package/dist/r/divider.json +24 -0
  208. package/dist/r/drawer.json +24 -0
  209. package/dist/r/file-change.json +24 -0
  210. package/dist/r/file-picker.json +44 -0
  211. package/dist/r/form.json +24 -0
  212. package/dist/r/gauge.json +24 -0
  213. package/dist/r/gradient.json +24 -0
  214. package/dist/r/grid.json +22 -0
  215. package/dist/r/heading.json +24 -0
  216. package/dist/r/heatmap.json +24 -0
  217. package/dist/r/help.json +22 -0
  218. package/dist/r/histogram.json +26 -0
  219. package/dist/r/image.json +24 -0
  220. package/dist/r/json.json +24 -0
  221. package/dist/r/kbd.json +24 -0
  222. package/dist/r/line-chart.json +26 -0
  223. package/dist/r/link.json +23 -0
  224. package/dist/r/loading-indicator.json +27 -0
  225. package/dist/r/log.json +24 -0
  226. package/dist/r/markdown.json +29 -0
  227. package/dist/r/masked-input.json +22 -0
  228. package/dist/r/menu.json +24 -0
  229. package/dist/r/message-bubble.json +24 -0
  230. package/dist/r/model-badge.json +24 -0
  231. package/dist/r/model-selector.json +24 -0
  232. package/dist/r/multi-progress.json +24 -0
  233. package/dist/r/multi-select.json +24 -0
  234. package/dist/r/notification-badge.json +24 -0
  235. package/dist/r/number-input.json +24 -0
  236. package/dist/r/operation-tree.json +26 -0
  237. package/dist/r/option-list.json +24 -0
  238. package/dist/r/ordered-list.json +22 -0
  239. package/dist/r/paginator.json +22 -0
  240. package/dist/r/paragraph.json +24 -0
  241. package/dist/r/path-input.json +26 -0
  242. package/dist/r/pie-chart.json +24 -0
  243. package/dist/r/placeholder.json +24 -0
  244. package/dist/r/popover.json +24 -0
  245. package/dist/r/progress-bar.json +22 -0
  246. package/dist/r/progress-circle.json +24 -0
  247. package/dist/r/qr-code.json +24 -0
  248. package/dist/r/radio-group.json +24 -0
  249. package/dist/r/registry.json +1051 -0
  250. package/dist/r/scatter-plot.json +27 -0
  251. package/dist/r/scroll-bar-box.json +24 -0
  252. package/dist/r/scroll-bar.json +24 -0
  253. package/dist/r/scroll-list.json +24 -0
  254. package/dist/r/scroll-view.json +24 -0
  255. package/dist/r/scroll.json +58 -0
  256. package/dist/r/search-input.json +26 -0
  257. package/dist/r/select-input-indicator.json +24 -0
  258. package/dist/r/select-input-item.json +24 -0
  259. package/dist/r/select-input.json +28 -0
  260. package/dist/r/shimmer-text.json +24 -0
  261. package/dist/r/sidebar.json +24 -0
  262. package/dist/r/slider.json +24 -0
  263. package/dist/r/sparkline.json +24 -0
  264. package/dist/r/spinner.json +23 -0
  265. package/dist/r/status-line.json +24 -0
  266. package/dist/r/status-message.json +24 -0
  267. package/dist/r/stepper.json +24 -0
  268. package/dist/r/stopwatch.json +22 -0
  269. package/dist/r/streaming-text.json +24 -0
  270. package/dist/r/switch.json +24 -0
  271. package/dist/r/tab.json +22 -0
  272. package/dist/r/table.json +23 -0
  273. package/dist/r/tabs.json +26 -0
  274. package/dist/r/tag-input.json +24 -0
  275. package/dist/r/tag.json +24 -0
  276. package/dist/r/text-input.json +22 -0
  277. package/dist/r/textarea.json +22 -0
  278. package/dist/r/thinking-block.json +24 -0
  279. package/dist/r/time-picker.json +24 -0
  280. package/dist/r/timer.json +22 -0
  281. package/dist/r/toast.json +24 -0
  282. package/dist/r/token-usage.json +24 -0
  283. package/dist/r/tool-call.json +24 -0
  284. package/dist/r/tooltip.json +24 -0
  285. package/dist/r/transition.json +22 -0
  286. package/dist/r/tree-select.json +24 -0
  287. package/dist/r/tree-view.json +64 -0
  288. package/dist/r/unordered-list.json +22 -0
  289. package/dist/r/use-linked-scroll.json +24 -0
  290. package/dist/r/variant-config.json +22 -0
  291. package/dist/radio-group.d.ts +74 -0
  292. package/dist/radio-group.js +1 -0
  293. package/dist/scatter-plot.d.ts +35 -0
  294. package/dist/scatter-plot.js +1 -0
  295. package/dist/scroll-bar-box.d.ts +3 -0
  296. package/dist/scroll-bar-box.js +1 -0
  297. package/dist/scroll-bar.d.ts +3 -0
  298. package/dist/scroll-bar.js +1 -0
  299. package/dist/scroll-list.d.ts +4 -0
  300. package/dist/scroll-list.js +1 -0
  301. package/dist/scroll-view.d.ts +3 -0
  302. package/dist/scroll-view.js +1 -0
  303. package/dist/search-input.d.ts +55 -0
  304. package/dist/search-input.js +1 -0
  305. package/dist/select-input-indicator.d.ts +32 -0
  306. package/dist/select-input-indicator.js +1 -0
  307. package/dist/select-input-item.d.ts +41 -0
  308. package/dist/select-input-item.js +1 -0
  309. package/dist/select-input.d.ts +110 -0
  310. package/dist/select-input.js +1 -0
  311. package/dist/shimmer-text.d.ts +47 -0
  312. package/dist/shimmer-text.js +1 -0
  313. package/dist/sidebar.d.ts +47 -0
  314. package/dist/sidebar.js +1 -0
  315. package/dist/slider.d.ts +103 -0
  316. package/dist/slider.js +1 -0
  317. package/dist/sparkline.d.ts +42 -0
  318. package/dist/sparkline.js +1 -0
  319. package/dist/spinner.d.ts +17 -0
  320. package/dist/spinner.js +1 -0
  321. package/dist/status-line.d.ts +37 -0
  322. package/dist/status-line.js +1 -0
  323. package/dist/status-message.d.ts +21 -0
  324. package/dist/status-message.js +1 -0
  325. package/dist/stepper.d.ts +48 -0
  326. package/dist/stepper.js +1 -0
  327. package/dist/stopwatch.d.ts +49 -0
  328. package/dist/stopwatch.js +1 -0
  329. package/dist/streaming-text.d.ts +46 -0
  330. package/dist/streaming-text.js +1 -0
  331. package/dist/switch.d.ts +55 -0
  332. package/dist/switch.js +1 -0
  333. package/dist/tab.d.ts +19 -0
  334. package/dist/tab.js +1 -0
  335. package/dist/table.d.ts +119 -0
  336. package/dist/table.js +1 -0
  337. package/dist/tabs.d.ts +107 -0
  338. package/dist/tabs.js +1 -0
  339. package/dist/tag-input.d.ts +71 -0
  340. package/dist/tag-input.js +1 -0
  341. package/dist/tag.d.ts +35 -0
  342. package/dist/tag.js +1 -0
  343. package/dist/text-input.d.ts +48 -0
  344. package/dist/text-input.js +1 -0
  345. package/dist/textarea.d.ts +68 -0
  346. package/dist/textarea.js +2 -0
  347. package/dist/thinking-block.d.ts +57 -0
  348. package/dist/thinking-block.js +1 -0
  349. package/dist/time-picker.d.ts +67 -0
  350. package/dist/time-picker.js +1 -0
  351. package/dist/timer.d.ts +59 -0
  352. package/dist/timer.js +1 -0
  353. package/dist/toast.d.ts +49 -0
  354. package/dist/toast.js +1 -0
  355. package/dist/token-usage.d.ts +50 -0
  356. package/dist/token-usage.js +1 -0
  357. package/dist/tool-call.d.ts +33 -0
  358. package/dist/tool-call.js +1 -0
  359. package/dist/tooltip.d.ts +43 -0
  360. package/dist/tooltip.js +1 -0
  361. package/dist/transition.d.ts +74 -0
  362. package/dist/transition.js +1 -0
  363. package/dist/tree-select.d.ts +65 -0
  364. package/dist/tree-select.js +1 -0
  365. package/dist/tree-view-entry.d.ts +4 -0
  366. package/dist/tree-view-entry.js +1 -0
  367. package/dist/unordered-list.d.ts +30 -0
  368. package/dist/unordered-list.js +1 -0
  369. package/dist/use-linked-scroll.d.ts +42 -0
  370. package/dist/use-linked-scroll.js +1 -0
  371. package/package.json +553 -7
@@ -0,0 +1,68 @@
1
+ import { ReactElement } from 'react';
2
+ type Props = {
3
+ /** @default "" */
4
+ readonly defaultValue?: string;
5
+ /**
6
+ * When true, all input is ignored and text is dimmed.
7
+ * @default false
8
+ */
9
+ readonly isDisabled?: boolean;
10
+ /**
11
+ * When true, the component responds to keyboard input.
12
+ * @default true
13
+ */
14
+ readonly isFocused?: boolean;
15
+ /**
16
+ * Maximum visible rows before viewport scrolling kicks in.
17
+ * When set, the textarea will grow from `rows` to `maxRows` before scrolling.
18
+ */
19
+ readonly maxRows?: number;
20
+ /**
21
+ * Fires on every edit with the updated text.
22
+ */
23
+ readonly onChange?: (value: string) => void;
24
+ /**
25
+ * Fires when the user presses Meta+Enter or Ctrl+Enter.
26
+ */
27
+ readonly onSubmit?: (value: string) => void;
28
+ /**
29
+ * Greyed-out text shown when the textarea is empty.
30
+ */
31
+ readonly placeholder?: string;
32
+ /**
33
+ * Number of visible rows (viewport height).
34
+ * @default 5
35
+ */
36
+ readonly rows?: number;
37
+ /**
38
+ * Show line numbers in the left gutter.
39
+ * @default false
40
+ */
41
+ readonly showLineNumbers?: boolean;
42
+ /**
43
+ * Number of spaces inserted for a Tab key press.
44
+ * @default 2
45
+ */
46
+ readonly tabSize?: number;
47
+ };
48
+ /**
49
+ * A multi-line text input with cursor navigation, selection, clipboard, undo/redo,
50
+ * paste support, and viewport scrolling.
51
+ *
52
+ * ```tsx
53
+ * <Textarea defaultValue="Hello\nWorld" rows={10} onChange={setValue} onSubmit={handleSubmit} />
54
+ * ```
55
+ */
56
+ declare function Textarea({
57
+ defaultValue,
58
+ isDisabled,
59
+ isFocused,
60
+ maxRows,
61
+ onChange,
62
+ onSubmit,
63
+ placeholder,
64
+ rows,
65
+ showLineNumbers,
66
+ tabSize
67
+ }: Props): ReactElement;
68
+ export { Props, Textarea, type Props as TextareaProps, Textarea as default };
@@ -0,0 +1,2 @@
1
+ import{jsx as l,jsxs as m,Fragment as x}from"react/jsx-runtime";import C from"@visulima/tui/components/box";import o from"@visulima/tui/components/text";import I from"@visulima/tui/hooks/use-clipboard";import W from"@visulima/tui/hooks/use-input";import Z from"@visulima/tui/hooks/use-paste";import $ from"@visulima/tui/hooks/use-text-buffer";import{isInsertableInput as q}from"@visulima/tui/input";import{useRef as A,useState as H,useEffect as z,useMemo as N,useCallback as M}from"react";const O=(t,c)=>c.line<t.line||c.line===t.line&&c.col<t.col?{endCol:t.col,endLine:t.line,startCol:c.col,startLine:c.line}:{endCol:c.col,endLine:c.line,startCol:t.col,startLine:t.line};function rr({defaultValue:t="",isDisabled:c=!1,isFocused:g=!0,maxRows:d,onChange:v,onSubmit:h,placeholder:p,rows:a=5,showLineNumbers:f=!1,tabSize:L=2}){const n=$(t),S=A(n);S.current=n;const{copy:s}=I(),[u,T]=H(0),D=A(v);D.current=v;const E=A(h);E.current=h;const k=A(t);z(()=>{n.value!==k.current&&(k.current=n.value,D.current?.(n.value))},[n.value]);const w=N(()=>d?Math.min(Math.max(a,n.lines.length),d):a,[a,d,n.lines.length]);z(()=>{T(i=>n.cursor.line<i?n.cursor.line:n.cursor.line>=i+w?n.cursor.line-w+1:i)},[n.cursor.line,w]);const R=M((i,r)=>{const e=S.current;if(r.return&&(r.meta||r.ctrl)){E.current?.(e.value);return}if(r.return){e.newline();return}if(r.escape){e.clearSelection();return}if(r.tab){e.insert(" ".repeat(L));return}if(r.ctrl&&i==="z"){e.undo();return}if(r.ctrl&&(i==="y"||r.shift&&i==="Z")){e.redo();return}if(r.ctrl&&i==="c"&&e.hasSelection()){s(e.getSelectedText());return}if(r.ctrl&&(i==="A"||i==="a"&&r.shift)){e.selectAll();return}if(r.upArrow){e.moveCursor("up",r.shift);return}if(r.downArrow){e.moveCursor("down",r.shift);return}if(r.leftArrow){e.moveCursor("left",r.shift);return}if(r.rightArrow){e.moveCursor("right",r.shift);return}if(r.home){r.ctrl?e.moveToStart(r.shift):e.moveToLineStart(r.shift);return}if(r.end){r.ctrl?e.moveToEnd(r.shift):e.moveToLineEnd(r.shift);return}if(r.ctrl&&i==="a"){e.moveToLineStart(r.shift);return}if(r.ctrl&&i==="e"){e.moveToLineEnd(r.shift);return}if(r.backspace){e.deleteBack();return}if(r.delete){e.deleteForward();return}if(r.ctrl&&i==="u"){e.deleteToLineStart();return}if(r.ctrl&&i==="k"){e.deleteToLineEnd();return}if(r.ctrl&&i==="w"){e.deleteWord();return}q(i,r)&&(e.hasSelection()?e.replaceSelection(i):e.insert(i))},[s,L]);W(R,{isActive:g&&!c});const j=M(i=>{const r=S.current;r.hasSelection()?r.replaceSelection(i):r.insert(i)},[]);Z(j,{isActive:g&&!c});const F=n.lines.slice(u,u+w),b=f?String(n.lines.length).length+1:0,y=n.anchor?O(n.cursor,n.anchor):null;if(c)return l(C,{flexDirection:"column",children:F.map((i,r)=>{const e=u+r;return m(C,{children:[f?m(o,{dimColor:!0,children:[String(e+1).padStart(b)," "]}):void 0,l(o,{dimColor:!0,children:i||(e===0&&p?p:"")})]},e)})});if(n.value.length===0&&p){const i=p.split(`
2
+ `).slice(0,w);return l(C,{flexDirection:"column",children:i.map((r,e)=>m(C,{children:[f?m(o,{dimColor:!0,children:[String(e+1).padStart(b)," "]}):void 0,e===0?m(o,{children:[l(o,{dimColor:!0,inverse:!0,children:r[0]??" "}),l(o,{dimColor:!0,children:r.slice(1)})]}):l(o,{dimColor:!0,children:r})]},e))})}return l(C,{flexDirection:"column",children:F.map((i,r)=>{const e=u+r,B=e===n.cursor.line;return m(C,{children:[f?m(o,{dimColor:!B,children:[String(e+1).padStart(b)," "]}):void 0,l(o,{children:P(i,e,n.cursor,y)})]},e)})})}function P(t,c,g,d){const v=c===g.line,h=v?g.col:-1,p=d&&c>=d.startLine&&c<=d.endLine;if(!p&&!v)return l(x,{children:t});if(!p){const s=t.slice(0,h),u=t[h],T=t.slice(h+1);return m(x,{children:[s,l(o,{inverse:!0,children:u??" "}),T]})}const a=c===d.startLine?d.startCol:0,f=c===d.endLine?d.endCol:t.length,L=t.slice(0,a),n=t.slice(a,f),S=t.slice(f);if(v&&(h<a||h>=f)){const s=[];let u=0;return h<a?(s.push(l(o,{children:t.slice(0,h)},u++)),s.push(l(o,{inverse:!0,children:t[h]??" "},u++)),s.push(l(o,{children:t.slice(h+1,a)},u++)),s.push(l(o,{inverse:!0,children:n},u++)),s.push(l(o,{children:S},u++))):(s.push(l(o,{children:L},u++)),s.push(l(o,{inverse:!0,children:n},u++)),s.push(l(o,{children:t.slice(f,h)},u++)),s.push(l(o,{inverse:!0,children:t[h]??" "},u++)),s.push(l(o,{children:t.slice(h+1)},u++))),l(x,{children:s})}return m(x,{children:[L,l(o,{inverse:!0,children:n}),S]})}export{rr as Textarea,rr as default};
@@ -0,0 +1,57 @@
1
+ import { AnsiColors } from '@visulima/colorize';
2
+ import { ReactElement } from 'react';
3
+ import { LiteralUnion } from 'type-fest';
4
+ type Props = {
5
+ /**
6
+ * Accent color for the header and border.
7
+ * @default "magenta"
8
+ */
9
+ readonly accentColor?: LiteralUnion<AnsiColors, string>;
10
+ /**
11
+ * Auto-focus so Space/Enter can toggle the block.
12
+ */
13
+ readonly autoFocus?: boolean;
14
+ /**
15
+ * The reasoning text.
16
+ */
17
+ readonly children: string;
18
+ /**
19
+ * Start expanded when uncontrolled.
20
+ * @default true
21
+ */
22
+ readonly defaultExpanded?: boolean;
23
+ /**
24
+ * Controlled expanded state. When set, `defaultExpanded` is ignored.
25
+ */
26
+ readonly expanded?: boolean;
27
+ /**
28
+ * Header label.
29
+ * @default "Thinking"
30
+ */
31
+ readonly label?: string;
32
+ /**
33
+ * Fires when the expanded state toggles.
34
+ */
35
+ readonly onToggle?: (expanded: boolean) => void;
36
+ /**
37
+ * Show a pulsing indicator to signal in-progress reasoning.
38
+ * @default false
39
+ */
40
+ readonly streaming?: boolean;
41
+ };
42
+ /**
43
+ * A collapsible block for an assistant's reasoning. The dimmed body is hidden
44
+ * when collapsed; Space or Enter toggles it while focused. Set `streaming` to
45
+ * mark reasoning still in progress.
46
+ */
47
+ declare function ThinkingBlock({
48
+ accentColor,
49
+ autoFocus,
50
+ children,
51
+ defaultExpanded,
52
+ expanded: controlledExpanded,
53
+ label,
54
+ onToggle,
55
+ streaming
56
+ }: Props): ReactElement;
57
+ export { Props, ThinkingBlock, type Props as ThinkingBlockProps, ThinkingBlock as default };
@@ -0,0 +1 @@
1
+ import{jsxs as u,jsx as o}from"react/jsx-runtime";import n from"@visulima/tui/components/box";import e from"@visulima/tui/components/text";import b from"@visulima/tui/hooks/use-focus";import B from"@visulima/tui/hooks/use-input";import{useState as F,useCallback as m}from"react";function E({accentColor:i="magenta",autoFocus:p=!1,children:f,defaultExpanded:h=!0,expanded:c,label:g="Thinking",onToggle:t,streaming:x=!1}){const{isFocused:d}=b({autoFocus:p}),a=c!==void 0,[k,v]=F(h),r=c??k,s=m(()=>{const l=!r;a||v(l),t?.(l)},[r,a,t]),C=m((l,T)=>{(l===" "||T.return)&&s()},[s]);return B(C,{isActive:d}),u(n,{borderColor:i,borderStyle:"round",flexDirection:"column",paddingX:1,children:[u(n,{gap:1,children:[o(e,{color:i,children:r?"▾":"▸"}),o(e,{color:i,italic:!0,children:g}),x?o(e,{color:i,children:"…"}):void 0,d?o(e,{dimColor:!0,children:r?"(space to collapse)":"(space to expand)"}):void 0]}),r?o(n,{marginTop:1,children:o(e,{dimColor:!0,italic:!0,children:f})}):void 0]})}export{E as ThinkingBlock,E as default};
@@ -0,0 +1,67 @@
1
+ import { AnsiColors } from '@visulima/colorize';
2
+ import { ReactElement } from 'react';
3
+ import { LiteralUnion } from 'type-fest';
4
+ type TimeValue = {
5
+ readonly hours: number;
6
+ readonly minutes: number;
7
+ readonly seconds?: number;
8
+ };
9
+ type Props = {
10
+ /**
11
+ * Accent color for the focused segment.
12
+ * @default "blue"
13
+ */
14
+ readonly accentColor?: LiteralUnion<AnsiColors, string>;
15
+ /**
16
+ * Auto-focus on mount.
17
+ */
18
+ readonly autoFocus?: boolean;
19
+ /**
20
+ * Initial value when uncontrolled.
21
+ * @default { hours: 0, minutes: 0 }
22
+ */
23
+ readonly defaultValue?: TimeValue;
24
+ /**
25
+ * Use a 12-hour clock with an AM/PM segment instead of 24-hour.
26
+ * @default false
27
+ */
28
+ readonly hour12?: boolean;
29
+ /**
30
+ * Disable input and dim the display.
31
+ */
32
+ readonly isDisabled?: boolean;
33
+ /**
34
+ * Fires whenever any segment changes.
35
+ */
36
+ readonly onChange?: (value: TimeValue) => void;
37
+ /**
38
+ * Fires on Enter.
39
+ */
40
+ readonly onSubmit?: (value: TimeValue) => void;
41
+ /**
42
+ * Show a seconds segment.
43
+ * @default false
44
+ */
45
+ readonly showSeconds?: boolean;
46
+ /**
47
+ * Controlled value. When provided, `defaultValue` is ignored.
48
+ */
49
+ readonly value?: TimeValue;
50
+ };
51
+ /**
52
+ * A keyboard-driven time input with independent hour/minute (and optional
53
+ * second) segments. ←/→ move between segments, ↑/↓ adjust the focused segment
54
+ * (wrapping), digits type directly, and Enter submits.
55
+ */
56
+ declare function TimePicker({
57
+ accentColor,
58
+ autoFocus,
59
+ defaultValue,
60
+ hour12,
61
+ isDisabled,
62
+ onChange,
63
+ onSubmit,
64
+ showSeconds,
65
+ value: controlledValue
66
+ }: Props): ReactElement;
67
+ export { Props, TimePicker, type Props as TimePickerProps, TimeValue, TimePicker as default };
@@ -0,0 +1 @@
1
+ import{jsxs as R,jsx as c,Fragment as W}from"react/jsx-runtime";import T from"@visulima/tui/components/box";import f from"@visulima/tui/components/text";import _ from"@visulima/tui/hooks/use-focus";import z from"@visulima/tui/hooks/use-input";import{useState as V,useRef as X,useCallback as A}from"react";const I=/^\d$/,K={hours:0,minutes:0};function m(a,d){return d===0?0:(a%d+d)%d}const w=a=>String(a).padStart(2,"0");function oe({accentColor:a="blue",autoFocus:d=!1,defaultValue:q=K,hour12:n=!1,isDisabled:h=!1,onChange:k,onSubmit:x,showSeconds:F=!1,value:j}){const{isFocused:g}=_({autoFocus:d,isActive:!h}),M=j!==void 0,[y,B]=V(q),e=j??y,p=["hours","minutes",...F?["seconds"]:[],...n?["ampm"]:[]],[E,$]=V(0),i=p[Math.min(E,p.length-1)],D=X(k);D.current=k;const t=X(null),u=A(r=>{M||B(r),D.current?.(r)},[M]),S=A((r,o)=>{switch(r){case"hours":{u({...e,hours:m(e.hours+o,24)});break}case"minutes":{u({...e,minutes:m(e.minutes+o,60)});break}case"seconds":{u({...e,seconds:m((e.seconds??0)+o,60)});break}default:u({...e,hours:m(e.hours+12,24)})}},[e,u]),L=A((r,o)=>{const s=t.current,N=s!==null&&s.segment===r;if(r==="minutes"||r==="seconds"){let l=N?s.value*10+o:o;l>59&&(l=o),t.current={segment:r,value:l},u(r==="minutes"?{...e,minutes:l}:{...e,seconds:l});return}const Q=n?12:23;let v=N?s.value*10+o:o;if(v>Q&&(v=o),t.current={segment:r,value:v},n){const l=e.hours>=12;u({...e,hours:v%12+(l?12:0)})}else u({...e,hours:v})},[e,n,u]),G=A((r,o)=>{if(o.leftArrow){t.current=null,$(s=>m(s-1,p.length));return}if(o.rightArrow){t.current=null,$(s=>m(s+1,p.length));return}if(o.upArrow){t.current=null,S(i,1);return}if(o.downArrow){t.current=null,S(i,-1);return}if(o.return){x?.(e);return}if(I.test(r)){i!=="ampm"&&L(i,Number.parseInt(r,10));return}(r==="a"||r==="p")&&n&&(t.current=null,e.hours>=12!=(r==="p")&&u({...e,hours:m(e.hours+12,24)}))},[S,L,e,i,n,x,p.length,u]);z(G,{isActive:g&&!h});const H=e.hours%12===0?12:e.hours%12,J=n?H:e.hours,P=e.hours>=12?"PM":"AM";function b(r){return g&&i===r?a:void 0}function C(r){return g&&i===r}return R(T,{borderColor:g?a:void 0,borderStyle:"round",paddingX:1,children:[c(f,{color:b("hours"),dimColor:h,inverse:C("hours"),children:w(J)}),c(f,{dimColor:!0,children:":"}),c(f,{color:b("minutes"),dimColor:h,inverse:C("minutes"),children:w(e.minutes)}),F?R(W,{children:[c(f,{dimColor:!0,children:":"}),c(f,{color:b("seconds"),dimColor:h,inverse:C("seconds"),children:w(e.seconds??0)})]}):void 0,n?c(T,{marginLeft:1,children:c(f,{color:b("ampm"),dimColor:h,inverse:C("ampm"),children:P})}):void 0]})}export{oe as TimePicker,oe as default};
@@ -0,0 +1,59 @@
1
+ import { UseTimerResult } from '@visulima/tui/hooks/use-timer';
2
+ import { Ref, ReactElement } from 'react';
3
+ type TimerRef = Omit<UseTimerResult, "isFinished" | "isRunning" | "remaining">;
4
+ type Props = {
5
+ /**
6
+ * Whether to start the timer immediately.
7
+ * @default false
8
+ */
9
+ readonly autoStart?: boolean;
10
+ /**
11
+ * Make the rendered text bold.
12
+ */
13
+ readonly bold?: boolean;
14
+ /**
15
+ * Text color for the rendered time.
16
+ */
17
+ readonly color?: string;
18
+ /**
19
+ * Total countdown duration in milliseconds.
20
+ */
21
+ readonly duration: number;
22
+ /**
23
+ * Custom formatter for the remaining time.
24
+ * Receives remaining milliseconds, returns a display string.
25
+ * @default formatDuration (MM:SS or HH:MM:SS)
26
+ */
27
+ readonly format?: (remaining: number) => string;
28
+ /**
29
+ * Tick interval in milliseconds.
30
+ * @default 1000
31
+ */
32
+ readonly interval?: number;
33
+ /**
34
+ * Called once when the timer reaches zero.
35
+ */
36
+ readonly onTimeout?: () => void;
37
+ readonly ref?: Ref<TimerRef>;
38
+ };
39
+ /**
40
+ * A countdown timer component.
41
+ *
42
+ * Exposes `start`, `stop`, `toggle`, and `reset` methods via ref.
43
+ *
44
+ * ```tsx
45
+ * const ref = useRef&lt;TimerRef>(null);
46
+ * &lt;Timer ref={ref} duration={60_000} autoStart />
47
+ * ```
48
+ */
49
+ declare const Timer: ({
50
+ autoStart,
51
+ bold,
52
+ color,
53
+ duration,
54
+ format,
55
+ interval,
56
+ onTimeout,
57
+ ref
58
+ }: Props) => ReactElement;
59
+ export { Props, Timer, type Props as TimerProps, TimerRef, Timer as default };
package/dist/timer.js ADDED
@@ -0,0 +1 @@
1
+ import{jsx as l}from"react/jsx-runtime";import u from"@visulima/tui/components/text";import p from"@visulima/tui/hooks/use-timer";import{formatDuration as f}from"@visulima/tui/utils";import{useImperativeHandle as d}from"react";const x=({autoStart:o,bold:r,color:e,duration:a,format:i=f,interval:m,onTimeout:s,ref:n})=>{const t=p({autoStart:o,duration:a,interval:m,onTimeout:s});return d(n,()=>({reset:t.reset,start:t.start,stop:t.stop,toggle:t.toggle}),[t.reset,t.start,t.stop,t.toggle]),l(u,{bold:r,color:e,children:i(t.remaining)})};export{x as Timer,x as default};
@@ -0,0 +1,49 @@
1
+ import { ReactNode, ReactElement } from 'react';
2
+ import { V as Variant } from "./packem_shared/variant-config.d-D5NnrrQK.js";
3
+ type ToastVariant = Variant;
4
+ type Props = {
5
+ /**
6
+ * Toast body.
7
+ */
8
+ readonly children: ReactNode;
9
+ /**
10
+ * Milliseconds to display before auto-dismissing. Use `0` to disable.
11
+ * @default 4000
12
+ */
13
+ readonly duration?: number;
14
+ /**
15
+ * Called after the toast dismisses itself.
16
+ */
17
+ readonly onDismiss?: () => void;
18
+ /**
19
+ * Optional title rendered before the body.
20
+ */
21
+ readonly title?: string;
22
+ /**
23
+ * Visual variant determining the icon and border color.
24
+ * @default "info"
25
+ */
26
+ readonly variant?: ToastVariant;
27
+ /**
28
+ * Manually control visibility. When provided, `duration` is ignored.
29
+ */
30
+ readonly visible?: boolean;
31
+ /**
32
+ * Optional width override.
33
+ */
34
+ readonly width?: number;
35
+ };
36
+ /**
37
+ * Ephemeral notification. Disappears automatically after `duration` ms.
38
+ * @returns A bordered `ReactElement` while visible; `null` once dismissed.
39
+ */
40
+ declare function Toast({
41
+ children,
42
+ duration,
43
+ onDismiss,
44
+ title,
45
+ variant,
46
+ visible,
47
+ width
48
+ }: Props): ReactElement | null;
49
+ export { Props, Toast, type Props as ToastProps, ToastVariant, Toast as default };
package/dist/toast.js ADDED
@@ -0,0 +1 @@
1
+ import{jsxs as s,jsx as t}from"react/jsx-runtime";import u from"@visulima/tui/components/box";import i from"@visulima/tui/components/text";import{useState as v,useRef as T,useEffect as w}from"react";import{o as g}from"./packem_shared/variant-config-BJqpNo7H.js";function E({children:f,duration:r=4e3,onDismiss:n,title:l,variant:m="info",visible:o,width:a}){const[p,h]=v(!0),e=o??p,d=T(n);if(d.current=n,w(()=>{if(o!==void 0||r<=0||!e)return;const b=setTimeout(()=>{h(!1),d.current?.()},r);return()=>{clearTimeout(b)}},[r,o,e]),!e)return null;const{color:c,icon:x}=g[m];return s(u,{borderColor:c,borderStyle:"round",gap:1,paddingX:1,width:a,children:[t(i,{color:c,children:x}),s(u,{flexDirection:"column",flexGrow:1,children:[l===void 0?void 0:t(i,{bold:!0,children:l}),t(i,{children:f})]})]})}export{E as Toast,E as default};
@@ -0,0 +1,50 @@
1
+ import { AnsiColors } from '@visulima/colorize';
2
+ import { ReactElement } from 'react';
3
+ import { LiteralUnion } from 'type-fest';
4
+ type Color = LiteralUnion<AnsiColors, string>;
5
+ type Props = {
6
+ /**
7
+ * Width of the input/output ratio bar in cells.
8
+ * @default 20
9
+ */
10
+ readonly barWidth?: number;
11
+ /**
12
+ * Optional context-window size. When set, a `used / limit (pct%)` summary
13
+ * and a fill bar are shown instead of the input/output split.
14
+ */
15
+ readonly contextLimit?: number;
16
+ /**
17
+ * Number of input (prompt) tokens.
18
+ * @default 0
19
+ */
20
+ readonly input?: number;
21
+ /**
22
+ * Color for the input segment.
23
+ * @default "cyan"
24
+ */
25
+ readonly inputColor?: Color;
26
+ /**
27
+ * Number of output (completion) tokens.
28
+ * @default 0
29
+ */
30
+ readonly output?: number;
31
+ /**
32
+ * Color for the output segment.
33
+ * @default "magenta"
34
+ */
35
+ readonly outputColor?: Color;
36
+ };
37
+ /**
38
+ * A compact token-usage readout. By default it shows input vs output counts
39
+ * with a proportional two-color bar; when `contextLimit` is set, it instead
40
+ * shows how much of the context window is used.
41
+ */
42
+ declare function TokenUsage({
43
+ barWidth,
44
+ contextLimit,
45
+ input,
46
+ inputColor,
47
+ output,
48
+ outputColor
49
+ }: Props): ReactElement;
50
+ export { Props, TokenUsage, type Props as TokenUsageProps, TokenUsage as default };
@@ -0,0 +1 @@
1
+ import{jsxs as c,jsx as e}from"react/jsx-runtime";import l from"@visulima/tui/components/box";import t from"@visulima/tui/components/text";function f(r){return r>.9?"red":r>.7?"yellow":"green"}const o=r=>r>=1e6?`${(r/1e6).toFixed(1)}M`:r>=1e3?`${(r/1e3).toFixed(1)}k`:String(r);function $({barWidth:r=20,contextLimit:i,input:d=0,inputColor:h="cyan",output:u=0,outputColor:m="magenta"}){const n=d+u;if(i!==void 0&&i>0){const a=Math.min(1,n/i),s=Math.round(a*r),M=f(a);return c(l,{gap:1,children:[e(t,{color:M,children:"█".repeat(s)}),e(t,{dimColor:!0,children:"░".repeat(Math.max(0,r-s))}),c(t,{children:[o(n),"/",o(i)," ","(",Math.round(a*100),"%)"]})]})}const p=n===0?0:Math.round(d/n*r),x=Math.max(0,r-p);return c(l,{gap:1,children:[c(l,{children:[e(t,{color:h,children:"█".repeat(p)}),e(t,{color:m,children:"█".repeat(x)})]}),e(t,{color:h,children:`↑${o(d)}`}),e(t,{color:m,children:`↓${o(u)}`}),e(t,{dimColor:!0,children:`Σ${o(n)}`})]})}export{$ as TokenUsage,$ as default};
@@ -0,0 +1,33 @@
1
+ import { ReactNode, ReactElement } from 'react';
2
+ type ToolCallStatus = "error" | "pending" | "running" | "success";
3
+ type Props = {
4
+ /**
5
+ * The tool arguments. Objects are shown as compact `key=value` pairs;
6
+ * strings are shown verbatim.
7
+ */
8
+ readonly args?: Record<string, unknown> | string;
9
+ /**
10
+ * Rendered output/result of the call, shown indented beneath the header.
11
+ */
12
+ readonly children?: ReactNode;
13
+ /**
14
+ * The tool name.
15
+ */
16
+ readonly name: string;
17
+ /**
18
+ * Call status, driving the icon and color.
19
+ * @default "pending"
20
+ */
21
+ readonly status?: ToolCallStatus;
22
+ };
23
+ /**
24
+ * A single tool invocation: a status icon, the tool name, its arguments as
25
+ * compact `key=value` pairs, and any result rendered as indented children.
26
+ */
27
+ declare function ToolCall({
28
+ args,
29
+ children,
30
+ name,
31
+ status
32
+ }: Props): ReactElement;
33
+ export { Props, ToolCall, type Props as ToolCallProps, ToolCallStatus, ToolCall as default };
@@ -0,0 +1 @@
1
+ import{jsxs as d,jsx as i}from"react/jsx-runtime";import c from"@visulima/tui/components/box";import e from"@visulima/tui/components/text";const a={error:{color:"red",icon:"✖"},pending:{color:"gray",icon:"○"},running:{color:"yellow",icon:"◐"},success:{color:"green",icon:"✔"}},g=o=>o===void 0?"":typeof o=="string"?o:Object.entries(o).map(([n,r])=>`${n}=${typeof r=="string"?r:JSON.stringify(r)}`).join(" ");function u({args:o,children:n,name:r,status:s="pending"}){const l=a[s],t=g(o);return d(c,{flexDirection:"column",children:[d(c,{gap:1,children:[i(e,{color:l.color,children:l.icon}),i(e,{bold:!0,children:r}),t.length>0?i(e,{dimColor:!0,children:t}):void 0]}),n===void 0?void 0:i(c,{marginLeft:2,children:i(e,{dimColor:!0,children:n})})]})}export{u as ToolCall,u as default};
@@ -0,0 +1,43 @@
1
+ import { AnsiColors } from '@visulima/colorize';
2
+ import { ReactNode, ReactElement } from 'react';
3
+ import { LiteralUnion } from 'type-fest';
4
+ type TooltipPlacement = "bottom" | "left" | "right" | "top";
5
+ type Props = {
6
+ /**
7
+ * The element the tooltip is attached to.
8
+ */
9
+ readonly children: ReactNode;
10
+ /**
11
+ * Border color.
12
+ * @default "gray"
13
+ */
14
+ readonly color?: LiteralUnion<AnsiColors, string>;
15
+ /**
16
+ * Tooltip body content.
17
+ */
18
+ readonly content: ReactNode;
19
+ /**
20
+ * Controls whether the tooltip is rendered.
21
+ * @default true
22
+ */
23
+ readonly isVisible?: boolean;
24
+ /**
25
+ * Relative position. Terminal rendering does not support floating layers,
26
+ * so the tooltip is placed inline next to (or above / below) the anchor.
27
+ * @default "right"
28
+ */
29
+ readonly placement?: TooltipPlacement;
30
+ };
31
+ /**
32
+ * Renders supplementary text next to an anchor. Because terminals don't have
33
+ * a floating-layer concept, the tooltip lives inline in the layout. Hide it
34
+ * by toggling `isVisible`.
35
+ */
36
+ declare function Tooltip({
37
+ children,
38
+ color,
39
+ content,
40
+ isVisible,
41
+ placement
42
+ }: Props): ReactElement;
43
+ export { Props, Tooltip, TooltipPlacement, type Props as TooltipProps, Tooltip as default };
@@ -0,0 +1 @@
1
+ import{jsx as i,jsxs as s}from"react/jsx-runtime";import o from"@visulima/tui/components/box";import m from"@visulima/tui/components/text";const a={bottom:{flexDirection:"column",orderFirst:!1},left:{flexDirection:"row",orderFirst:!0},right:{flexDirection:"row",orderFirst:!1},top:{flexDirection:"column",orderFirst:!0}};function x({children:c,color:t="gray",content:r,isVisible:d=!0,placement:e="right"}){const{flexDirection:f,orderFirst:n}=a[e],l=d?i(o,{borderColor:t,borderStyle:"round",flexShrink:0,marginLeft:e==="right"?1:0,marginRight:e==="left"?1:0,paddingX:1,children:typeof r=="string"?i(m,{color:t,children:r}):r}):void 0;return s(o,{alignItems:"center",flexDirection:f,children:[n?l:void 0,i(o,{children:c}),n?void 0:l]})}export{x as Tooltip,x as default};
@@ -0,0 +1,74 @@
1
+ import { ReactNode, ReactElement } from 'react';
2
+ type TransitionPreset = "fade" | "reveal" | "slide-down" | "slide-left" | "slide-right" | "slide-up";
3
+ type TransitionPhase = "entered" | "entering" | "exited" | "exiting";
4
+ type Props = {
5
+ /**
6
+ * Content to animate.
7
+ */
8
+ readonly children: ReactNode;
9
+ /**
10
+ * For slide presets, how many characters of offset to animate across.
11
+ * For the `reveal` preset, the maximum row count to scale through.
12
+ * @default 4
13
+ */
14
+ readonly distance?: number;
15
+ /**
16
+ * Duration of both enter and exit transitions, in milliseconds.
17
+ * @default 240
18
+ */
19
+ readonly duration?: number;
20
+ /**
21
+ * Called once the exit animation finishes (i.e. the component has fully
22
+ * transitioned out). AnimatePresence uses this to unmount the wrapper.
23
+ */
24
+ readonly onExit?: () => void;
25
+ /**
26
+ * Animation preset controlling how the content appears/disappears.
27
+ * @default "fade"
28
+ */
29
+ readonly preset?: TransitionPreset;
30
+ /**
31
+ * Controls the target phase. `true` drives towards `entered`, `false`
32
+ * drives towards `exited`. Flip the value to trigger animation.
33
+ * @default true
34
+ */
35
+ readonly show?: boolean;
36
+ /**
37
+ * Tick interval in milliseconds. Lower values yield smoother animation
38
+ * at the cost of CPU.
39
+ * @default 30
40
+ */
41
+ readonly tickInterval?: number;
42
+ };
43
+ type TransitionComponent = ((props: Props) => ReactElement | null) & {
44
+ isAnimatable: true;
45
+ };
46
+ /**
47
+ * Animate a child's entry and exit using a TUI-friendly preset. Drive via
48
+ * `show`; the component toggles between enter and exit, fires `onExit` once
49
+ * the exit animation completes.
50
+ *
51
+ * **Fade preset note:** `dimColor` is only applied when the child is a plain
52
+ * string. Non-string children (Box trees, other components) pass through
53
+ * untouched during the transition — wrap them in `&lt;Text>` if you need the
54
+ * fade effect.
55
+ * @returns A `ReactElement` rendering the transitioning child, or `null`
56
+ * once a hidden transition has fully completed.
57
+ */
58
+ declare function Transition({
59
+ children,
60
+ distance,
61
+ duration,
62
+ onExit,
63
+ preset,
64
+ show,
65
+ tickInterval
66
+ }: Props): ReactElement | null;
67
+ /**
68
+ * Static marker used by `AnimatePresence` to recognize Transition children
69
+ * even when the consumer hasn't explicitly passed a `show` prop. Consumers
70
+ * can apply the same marker to their own wrappers (`MyWrapper.isAnimatable
71
+ * = true`) to opt them into animation orchestration.
72
+ */
73
+ declare const TransitionWithMarker: TransitionComponent;
74
+ export { Props, Transition, TransitionPhase, TransitionPreset, type Props as TransitionProps, TransitionWithMarker as default };
@@ -0,0 +1 @@
1
+ import{jsx as e}from"react/jsx-runtime";import c from"@visulima/tui/components/box";import y from"@visulima/tui/components/text";import{useState as w,useRef as a,useEffect as D}from"react";const A=(t,r)=>t>=1?e(c,{children:r}):t<=0?e(c,{}):e(c,{children:typeof r=="string"?e(y,{dimColor:t<.7,children:r}):r}),B=(t,r)=>Math.max(0,Math.min(r,Math.round((1-t)*r))),f=(t,r)=>(i,u,h)=>{const n=B(i,h);return i>=1?e(c,{children:u}):i<=0?e(c,{}):t==="x"?e(c,{paddingLeft:r===1?n:0,paddingRight:r===-1?n:0,children:u}):e(c,{flexDirection:"column",paddingBottom:r===-1?n:0,paddingTop:r===1?n:0,children:u})},C=(t,r,i)=>{if(t>=1)return e(c,{children:r});if(t<=0)return e(c,{});const u=Math.max(0,Math.min(i,Math.round(t*i)));return e(c,{flexDirection:"column",height:u,overflowY:"hidden",children:r})},O={fade:A,reveal:C,"slide-down":f("y",-1),"slide-left":f("x",-1),"slide-right":f("x",1),"slide-up":f("y",1)},T=(t,r)=>t?r>=1?"entered":"entering":r<=0?"exited":"exiting";function K({children:t,distance:r=4,duration:i=240,onExit:u,preset:h="fade",show:n=!0,tickInterval:g=30}){const[m,I]=w(n?1:0),p=a(n?1:0),M=a(Date.now()),l=a(n?1:0),d=a(!n),x=a(u);x.current=u;const[E,R]=w(0);if(D(()=>{const o=n?1:0;p.current!==o&&(p.current=o,M.current=Date.now(),l.current=m,d.current=!1,R(s=>s+1))},[n]),D(()=>{const o=p.current;if(l.current===o){o===0&&!d.current&&(d.current=!0,x.current?.());return}const s=setInterval(()=>{const j=Date.now()-M.current,v=i<=0?1:Math.min(1,j/i),k=l.current+(o-l.current)*v;I(k),v>=1&&(clearInterval(s),o===0&&!d.current&&(d.current=!0,x.current?.()))},g);return()=>{clearInterval(s)}},[E,i,g]),T(n,m)==="exited"&&!n)return null;const b=O[h];return b(m,t,r)}const Y=Object.assign(K,{isAnimatable:!0});export{K as Transition,Y as default};
@@ -0,0 +1,65 @@
1
+ import { AnsiColors } from '@visulima/colorize';
2
+ import { ReactElement } from 'react';
3
+ import { LiteralUnion } from 'type-fest';
4
+ type TreeSelectNode = {
5
+ readonly children?: ReadonlyArray<TreeSelectNode>;
6
+ readonly label: string;
7
+ readonly value: string;
8
+ };
9
+ type Props = {
10
+ /**
11
+ * Accent color for the focused row and selection marks.
12
+ * @default "blue"
13
+ */
14
+ readonly accentColor?: LiteralUnion<AnsiColors, string>;
15
+ /**
16
+ * Auto-focus on mount.
17
+ */
18
+ readonly autoFocus?: boolean;
19
+ /**
20
+ * Selected values when uncontrolled.
21
+ */
22
+ readonly defaultValue?: ReadonlyArray<string>;
23
+ /**
24
+ * Disable input and dim the tree.
25
+ */
26
+ readonly isDisabled?: boolean;
27
+ /**
28
+ * The tree to render.
29
+ */
30
+ readonly nodes: ReadonlyArray<TreeSelectNode>;
31
+ /**
32
+ * Fires whenever the selection changes.
33
+ */
34
+ readonly onChange?: (values: ReadonlyArray<string>) => void;
35
+ /**
36
+ * Fires on Enter with the current selection.
37
+ */
38
+ readonly onSubmit?: (values: ReadonlyArray<string>) => void;
39
+ /**
40
+ * `single` replaces the selection; `multiple` toggles values.
41
+ * @default "single"
42
+ */
43
+ readonly selectionMode?: "multiple" | "single";
44
+ /**
45
+ * Controlled selection. When provided, `defaultValue` is ignored.
46
+ */
47
+ readonly value?: ReadonlyArray<string>;
48
+ };
49
+ /**
50
+ * A keyboard-navigable tree with selectable leaves. ↑/↓ move the cursor, →/←
51
+ * expand/collapse a branch (or Space on a branch), Space selects a leaf, and
52
+ * Enter submits. Supports single or multiple selection.
53
+ */
54
+ declare function TreeSelect({
55
+ accentColor,
56
+ autoFocus,
57
+ defaultValue,
58
+ isDisabled,
59
+ nodes,
60
+ onChange,
61
+ onSubmit,
62
+ selectionMode,
63
+ value: controlledValue
64
+ }: Props): ReactElement;
65
+ export { Props, TreeSelect, TreeSelectNode, type Props as TreeSelectProps, TreeSelect as default };
@@ -0,0 +1 @@
1
+ import{jsx as p,jsxs as k}from"react/jsx-runtime";import B from"@visulima/tui/components/box";import w from"@visulima/tui/components/text";import V from"@visulima/tui/hooks/use-focus";import Y from"@visulima/tui/hooks/use-input";import{useState as C,useMemo as R,useRef as _,useCallback as g}from"react";const q=[];function T(i,t){return t===0?0:(i%t+t)%t}function z(i,t,s){return i?t?"▾":"▸":s?"◉":"◯"}const E=(i,t,s,u)=>{for(const l of i){const a=l.children!==void 0&&l.children.length>0;u.push({depth:s,hasChildren:a,node:l}),a&&t.has(l.value)&&E(l.children,t,s+1,u)}};function X({accentColor:i="blue",autoFocus:t=!1,defaultValue:s=q,isDisabled:u=!1,nodes:l,onChange:a,onSubmit:S,selectionMode:A="single",value:f}){const{isFocused:b}=V({autoFocus:t,isActive:!u}),x=f!==void 0,[D,H]=C(s),c=R(()=>new Set(f??D),[f,D]),[m,I]=C(()=>new Set),[v,F]=C(0),M=_(a);M.current=a;const d=R(()=>{const e=[];return E(l,m,0,e),e},[m,l]),j=g(e=>{const o=[...e];x||H(o),M.current?.(o)},[x]),h=g((e,o)=>{I(r=>{const n=new Set(r);return o??!n.has(e)?n.add(e):n.delete(e),n})},[]),J=g((e,o)=>{const r=d[v];if(o.upArrow){F(n=>T(n-1,d.length));return}if(o.downArrow){F(n=>T(n+1,d.length));return}if(r!==void 0){if(o.rightArrow&&r.hasChildren){h(r.node.value,!0);return}if(o.leftArrow&&r.hasChildren){h(r.node.value,!1);return}if(e===" "){if(r.hasChildren){h(r.node.value);return}const n=A==="single"?new Set:new Set(c);n.has(r.node.value)?n.delete(r.node.value):n.add(r.node.value),j(n);return}o.return&&S?.([...c])}},[v,j,S,d,c,A,h]);return Y(J,{isActive:b&&!u}),p(B,{flexDirection:"column",children:d.map((e,o)=>{const r=b&&o===v,n=c.has(e.node.value),K=" ".repeat(e.depth),N=z(e.hasChildren,m.has(e.node.value),n),U=!e.hasChildren&&n?i:void 0;return k(B,{children:[p(w,{color:r?i:void 0,children:r?"❯":" "}),p(w,{children:K}),k(w,{color:U,dimColor:u,children:[N," ",e.node.label]})]},o)})})}export{X as TreeSelect,X as default};
@@ -0,0 +1,4 @@
1
+ export { type A as AsyncChildrenFunction, type F as FlatNode, type S as SelectionMode, type T as TreeNode, a as TreeNodeMap, type b as TreeNodeRendererProps, type c as TreeNodeState, d as TreeView, type P as TreeViewProps, type e as TreeViewState, type f as TreeViewTheme, type U as UseTreeViewProps, type g as UseTreeViewStateProps, t as treeViewTheme, u as useTreeView, h as useTreeViewState } from "./packem_shared/use-tree-view.d-dXTKoDPM.js";
2
+ import '@visulima/tui/components/box';
3
+ import '@visulima/tui/components/text';
4
+ import 'react';
@@ -0,0 +1 @@
1
+ import{theme as o}from"./packem_shared/treeViewTheme-Dq3ekRAC.js";import{TreeNodeMap as m}from"./packem_shared/TreeNodeMap-cJlYqckB.js";import{TreeView as f}from"./packem_shared/TreeView-q0l446NV.js";import{useTreeView as T}from"./packem_shared/useTreeView-D0JEqT6W.js";import{useTreeViewState as w}from"./packem_shared/useTreeViewState-BiTJakkh.js";export{m as TreeNodeMap,f as TreeView,o as treeViewTheme,T as useTreeView,w as useTreeViewState};