termcast 1.3.48 → 1.3.50

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 (255) hide show
  1. package/dist/build.d.ts.map +1 -1
  2. package/dist/build.js +12 -0
  3. package/dist/build.js.map +1 -1
  4. package/dist/cli.js +5 -40
  5. package/dist/cli.js.map +1 -1
  6. package/dist/colors.d.ts +7 -7
  7. package/dist/colors.js +7 -7
  8. package/dist/compile.d.ts +6 -1
  9. package/dist/compile.d.ts.map +1 -1
  10. package/dist/compile.js +45 -26
  11. package/dist/compile.js.map +1 -1
  12. package/dist/components/actions.js +1 -1
  13. package/dist/components/actions.js.map +1 -1
  14. package/dist/components/bar-chart.d.ts +38 -0
  15. package/dist/components/bar-chart.d.ts.map +1 -0
  16. package/dist/components/bar-chart.js +158 -0
  17. package/dist/components/bar-chart.js.map +1 -0
  18. package/dist/components/bar-graph.d.ts +41 -0
  19. package/dist/components/bar-graph.d.ts.map +1 -0
  20. package/dist/components/bar-graph.js +95 -0
  21. package/dist/components/bar-graph.js.map +1 -0
  22. package/dist/components/detail.d.ts.map +1 -1
  23. package/dist/components/detail.js +5 -7
  24. package/dist/components/detail.js.map +1 -1
  25. package/dist/components/footer.d.ts.map +1 -1
  26. package/dist/components/footer.js +8 -9
  27. package/dist/components/footer.js.map +1 -1
  28. package/dist/components/form/date-picker.d.ts.map +1 -1
  29. package/dist/components/form/date-picker.js +7 -1
  30. package/dist/components/form/date-picker.js.map +1 -1
  31. package/dist/components/form/dropdown.d.ts.map +1 -1
  32. package/dist/components/form/dropdown.js +10 -2
  33. package/dist/components/form/dropdown.js.map +1 -1
  34. package/dist/components/form/index.d.ts.map +1 -1
  35. package/dist/components/form/index.js +4 -5
  36. package/dist/components/form/index.js.map +1 -1
  37. package/dist/components/form/use-form-navigation.d.ts.map +1 -1
  38. package/dist/components/form/use-form-navigation.js +6 -0
  39. package/dist/components/form/use-form-navigation.js.map +1 -1
  40. package/dist/components/graph.d.ts +111 -0
  41. package/dist/components/graph.d.ts.map +1 -0
  42. package/dist/components/graph.js +392 -0
  43. package/dist/components/graph.js.map +1 -0
  44. package/dist/components/icon.js +5 -5
  45. package/dist/components/icon.js.map +1 -1
  46. package/dist/components/list.d.ts +53 -5
  47. package/dist/components/list.d.ts.map +1 -1
  48. package/dist/components/list.js +125 -71
  49. package/dist/components/list.js.map +1 -1
  50. package/dist/components/loading-bar.js +3 -3
  51. package/dist/components/loading-bar.js.map +1 -1
  52. package/dist/components/loading-text.d.ts +1 -1
  53. package/dist/components/loading-text.d.ts.map +1 -1
  54. package/dist/components/loading-text.js +3 -1
  55. package/dist/components/loading-text.js.map +1 -1
  56. package/dist/components/metadata.js +2 -2
  57. package/dist/components/metadata.js.map +1 -1
  58. package/dist/components/row.d.ts +10 -0
  59. package/dist/components/row.d.ts.map +1 -0
  60. package/dist/components/row.js +12 -0
  61. package/dist/components/row.js.map +1 -0
  62. package/dist/components/table.d.ts +57 -0
  63. package/dist/components/table.d.ts.map +1 -0
  64. package/dist/components/table.js +365 -0
  65. package/dist/components/table.js.map +1 -0
  66. package/dist/descendants.js +13 -13
  67. package/dist/descendants.js.map +1 -1
  68. package/dist/examples/bar-graph-weekly.d.ts +2 -0
  69. package/dist/examples/bar-graph-weekly.d.ts.map +1 -0
  70. package/dist/examples/bar-graph-weekly.js +95 -0
  71. package/dist/examples/bar-graph-weekly.js.map +1 -0
  72. package/dist/examples/components-weird-places.d.ts +2 -0
  73. package/dist/examples/components-weird-places.d.ts.map +1 -0
  74. package/dist/examples/components-weird-places.js +46 -0
  75. package/dist/examples/components-weird-places.js.map +1 -0
  76. package/dist/examples/graph-bar-chart.d.ts +2 -0
  77. package/dist/examples/graph-bar-chart.d.ts.map +1 -0
  78. package/dist/examples/graph-bar-chart.js +270 -0
  79. package/dist/examples/graph-bar-chart.js.map +1 -0
  80. package/dist/examples/graph-multi-series.d.ts +2 -0
  81. package/dist/examples/graph-multi-series.d.ts.map +1 -0
  82. package/dist/examples/graph-multi-series.js +23 -0
  83. package/dist/examples/graph-multi-series.js.map +1 -0
  84. package/dist/examples/graph-polymarket.d.ts +2 -0
  85. package/dist/examples/graph-polymarket.d.ts.map +1 -0
  86. package/dist/examples/graph-polymarket.js +109 -0
  87. package/dist/examples/graph-polymarket.js.map +1 -0
  88. package/dist/examples/graph-row.d.ts +2 -0
  89. package/dist/examples/graph-row.d.ts.map +1 -0
  90. package/dist/examples/graph-row.js +226 -0
  91. package/dist/examples/graph-row.js.map +1 -0
  92. package/dist/examples/graph-styles.d.ts +2 -0
  93. package/dist/examples/graph-styles.d.ts.map +1 -0
  94. package/dist/examples/graph-styles.js +316 -0
  95. package/dist/examples/graph-styles.js.map +1 -0
  96. package/dist/examples/list-accessory-table.d.ts +2 -0
  97. package/dist/examples/list-accessory-table.d.ts.map +1 -0
  98. package/dist/examples/list-accessory-table.js +46 -0
  99. package/dist/examples/list-accessory-table.js.map +1 -0
  100. package/dist/examples/list-item-accessories.d.ts +2 -0
  101. package/dist/examples/list-item-accessories.d.ts.map +1 -0
  102. package/dist/examples/list-item-accessories.js +27 -0
  103. package/dist/examples/list-item-accessories.js.map +1 -0
  104. package/dist/examples/list-no-actions.d.ts +2 -0
  105. package/dist/examples/list-no-actions.d.ts.map +1 -0
  106. package/dist/examples/list-no-actions.js +7 -0
  107. package/dist/examples/list-no-actions.js.map +1 -0
  108. package/dist/examples/simple-detail-table.d.ts +2 -0
  109. package/dist/examples/simple-detail-table.d.ts.map +1 -0
  110. package/dist/examples/simple-detail-table.js +45 -0
  111. package/dist/examples/simple-detail-table.js.map +1 -0
  112. package/dist/examples/simple-graph.d.ts +2 -0
  113. package/dist/examples/simple-graph.d.ts.map +1 -0
  114. package/dist/examples/simple-graph.js +32 -0
  115. package/dist/examples/simple-graph.js.map +1 -0
  116. package/dist/examples/simple-table-wrap.d.ts +2 -0
  117. package/dist/examples/simple-table-wrap.d.ts.map +1 -0
  118. package/dist/examples/simple-table-wrap.js +37 -0
  119. package/dist/examples/simple-table-wrap.js.map +1 -0
  120. package/dist/examples/table-edge-cases.d.ts +2 -0
  121. package/dist/examples/table-edge-cases.d.ts.map +1 -0
  122. package/dist/examples/table-edge-cases.js +70 -0
  123. package/dist/examples/table-edge-cases.js.map +1 -0
  124. package/dist/examples/table-flex-grow.d.ts +2 -0
  125. package/dist/examples/table-flex-grow.d.ts.map +1 -0
  126. package/dist/examples/table-flex-grow.js +18 -0
  127. package/dist/examples/table-flex-grow.js.map +1 -0
  128. package/dist/extensions/dev.d.ts.map +1 -1
  129. package/dist/extensions/dev.js +5 -1
  130. package/dist/extensions/dev.js.map +1 -1
  131. package/dist/globals.d.ts +1 -0
  132. package/dist/globals.d.ts.map +1 -1
  133. package/dist/globals.js +2 -0
  134. package/dist/globals.js.map +1 -1
  135. package/dist/index.d.ts +10 -0
  136. package/dist/index.d.ts.map +1 -1
  137. package/dist/index.js +10 -0
  138. package/dist/index.js.map +1 -1
  139. package/dist/internal/date-picker-widget.d.ts.map +1 -1
  140. package/dist/internal/date-picker-widget.js +4 -0
  141. package/dist/internal/date-picker-widget.js.map +1 -1
  142. package/dist/internal/providers.d.ts.map +1 -1
  143. package/dist/internal/providers.js +1 -3
  144. package/dist/internal/providers.js.map +1 -1
  145. package/dist/markdown-utils.d.ts +22 -1
  146. package/dist/markdown-utils.d.ts.map +1 -1
  147. package/dist/markdown-utils.js +66 -1
  148. package/dist/markdown-utils.js.map +1 -1
  149. package/dist/opentui.d.ts +4 -0
  150. package/dist/opentui.d.ts.map +1 -0
  151. package/dist/opentui.js +3 -0
  152. package/dist/opentui.js.map +1 -0
  153. package/dist/release.d.ts +2 -1
  154. package/dist/release.d.ts.map +1 -1
  155. package/dist/release.js +2 -1
  156. package/dist/release.js.map +1 -1
  157. package/dist/state.d.ts +1 -0
  158. package/dist/state.d.ts.map +1 -1
  159. package/dist/state.js +1 -1
  160. package/dist/state.js.map +1 -1
  161. package/dist/theme.d.ts +1 -0
  162. package/dist/theme.d.ts.map +1 -1
  163. package/dist/theme.js +13 -0
  164. package/dist/theme.js.map +1 -1
  165. package/dist/themes/nerv.json +227 -0
  166. package/dist/themes/termcast.json +72 -71
  167. package/dist/themes.d.ts +2 -1
  168. package/dist/themes.d.ts.map +1 -1
  169. package/dist/themes.js +7 -5
  170. package/dist/themes.js.map +1 -1
  171. package/dist/utils.d.ts.map +1 -1
  172. package/dist/utils.js +3 -0
  173. package/dist/utils.js.map +1 -1
  174. package/package.json +13 -5
  175. package/src/build.tsx +13 -0
  176. package/src/cli.tsx +5 -49
  177. package/src/colors.tsx +7 -7
  178. package/src/compile.tsx +52 -29
  179. package/src/components/actions.tsx +1 -1
  180. package/src/components/bar-chart.tsx +271 -0
  181. package/src/components/bar-graph.tsx +214 -0
  182. package/src/components/detail.tsx +7 -8
  183. package/src/components/footer.tsx +14 -15
  184. package/src/components/form/date-picker.tsx +9 -0
  185. package/src/components/form/dropdown.tsx +13 -3
  186. package/src/components/form/index.tsx +4 -6
  187. package/src/components/form/use-form-navigation.tsx +6 -0
  188. package/src/components/graph.tsx +506 -0
  189. package/src/components/icon.tsx +5 -5
  190. package/src/components/list.tsx +210 -102
  191. package/src/components/loading-bar.tsx +3 -3
  192. package/src/components/loading-text.tsx +4 -2
  193. package/src/components/metadata.tsx +2 -2
  194. package/src/components/row.tsx +31 -0
  195. package/src/components/table.tsx +511 -0
  196. package/src/descendants.tsx +13 -13
  197. package/src/examples/action-shortcut.vitest.tsx +1 -1
  198. package/src/examples/actions-context.vitest.tsx +1 -1
  199. package/src/examples/bar-graph-weekly.tsx +264 -0
  200. package/src/examples/bar-graph-weekly.vitest.tsx +275 -0
  201. package/src/examples/detail-metadata-showcase.vitest.tsx +8 -8
  202. package/src/examples/form-basic.vitest.tsx +239 -0
  203. package/src/examples/form-dropdown.vitest.tsx +29 -29
  204. package/src/examples/form-tagpicker.vitest.tsx +27 -27
  205. package/src/examples/github.vitest.tsx +4 -4
  206. package/src/examples/graph-bar-chart.tsx +408 -0
  207. package/src/examples/graph-bar-chart.vitest.tsx +283 -0
  208. package/src/examples/graph-multi-series.tsx +36 -0
  209. package/src/examples/graph-multi-series.vitest.tsx +89 -0
  210. package/src/examples/graph-polymarket.tsx +182 -0
  211. package/src/examples/graph-polymarket.vitest.tsx +130 -0
  212. package/src/examples/graph-row.tsx +347 -0
  213. package/src/examples/graph-row.vitest.tsx +295 -0
  214. package/src/examples/graph-styles.tsx +457 -0
  215. package/src/examples/graph-styles.vitest.tsx +322 -0
  216. package/src/examples/list-accessory-table.tsx +77 -0
  217. package/src/examples/list-detail-metadata.vitest.tsx +21 -21
  218. package/src/examples/list-dropdown-default.vitest.tsx +12 -12
  219. package/src/examples/list-item-accessories.tsx +106 -0
  220. package/src/examples/list-item-accessories.vitest.tsx +115 -0
  221. package/src/examples/list-no-actions.tsx +18 -0
  222. package/src/examples/list-no-actions.vitest.tsx +97 -0
  223. package/src/examples/list-spacing-mode.vitest.tsx +6 -6
  224. package/src/examples/list-with-detail.vitest.tsx +92 -92
  225. package/src/examples/list-with-dropdown.vitest.tsx +49 -6
  226. package/src/examples/list-with-sections.vitest.tsx +61 -56
  227. package/src/examples/simple-detail-markdown.vitest.tsx +21 -17
  228. package/src/examples/simple-detail-table.tsx +65 -0
  229. package/src/examples/simple-detail-table.vitest.tsx +200 -0
  230. package/src/examples/simple-graph.tsx +51 -0
  231. package/src/examples/simple-graph.vitest.tsx +124 -0
  232. package/src/examples/simple-grid.vitest.tsx +3 -3
  233. package/src/examples/simple-list-search.vitest.tsx +65 -0
  234. package/src/examples/simple-navigation.vitest.tsx +3 -3
  235. package/src/examples/simple-table-wrap.tsx +55 -0
  236. package/src/examples/simple-table-wrap.vitest.tsx +91 -0
  237. package/src/examples/store.vitest.tsx +1 -1
  238. package/src/examples/table-edge-cases.tsx +72 -0
  239. package/src/examples/table-edge-cases.vitest.tsx +307 -0
  240. package/src/examples/table-flex-grow.tsx +53 -0
  241. package/src/examples/table-flex-grow.vitest.tsx +124 -0
  242. package/src/extensions/dev.tsx +7 -1
  243. package/src/globals.ts +3 -0
  244. package/src/index.tsx +31 -0
  245. package/src/internal/date-picker-widget.tsx +4 -0
  246. package/src/internal/providers.tsx +1 -4
  247. package/src/markdown-utils.tsx +82 -1
  248. package/src/opentui.tsx +5 -0
  249. package/src/release.tsx +3 -0
  250. package/src/state.tsx +2 -1
  251. package/src/theme.tsx +14 -0
  252. package/src/themes/nerv.json +231 -0
  253. package/src/themes/termcast.json +75 -71
  254. package/src/themes.ts +8 -5
  255. package/src/utils.tsx +4 -0
@@ -0,0 +1,322 @@
1
+ import { test, expect, afterEach, beforeEach } from 'vitest'
2
+ import { launchTerminal, Session } from 'tuistory/src'
3
+
4
+ let session: Session
5
+
6
+ beforeEach(async () => {
7
+ session = await launchTerminal({
8
+ command: 'bun',
9
+ args: ['src/examples/graph-styles.tsx'],
10
+ cols: 80,
11
+ rows: 24,
12
+ })
13
+ })
14
+
15
+ afterEach(() => {
16
+ session?.close()
17
+ })
18
+
19
+ test('area style renders braille characters', async () => {
20
+ const text = await session.text({
21
+ waitFor: (text) => {
22
+ return text.includes('Area - Stock') && text.includes('│')
23
+ },
24
+ timeout: 10000,
25
+ })
26
+
27
+ expect(text).toMatchInlineSnapshot(`
28
+ "
29
+
30
+
31
+ Graph Styles ─────────────────────────────────────────────────────────────
32
+
33
+ > Search...
34
+
35
+ ›Area - Stock Price Orange braille do │ 211│ ⣠ ▲
36
+ Area - Multi Series CPU + Memory ove │ │ ⢀⣴⣦⣼⣿ █
37
+ Area - Waves Purple + Magenta sine/c │ │ ⢠⣦⣄⣴⣿⣿⣿⣿⣿ █
38
+ Area - Blue Revenue Single series, a │ 189│ ⢀⣴⣷⣦⣿⣿⣿⣿⣿⣿⣿⣿⣿ █
39
+ Filled - Red Revenue Solid block gro │ │ ⣠⣀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ▀
40
+ Filled - Green Temp Daily temperatur │ │ ⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
41
+ Filled - Yellow CPU High contrast on │ 167│ ⢀⣴⣿⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
42
+ Filled - Magenta Waves Smooth curve │ │ ⣰⣤⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
43
+ Striped - Purple/Orange Warm alterna │ │⢀⣴⡄⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
44
+ Striped - Blue/Red High contrast str │ 145│⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
45
+ Striped - Theme Default primary + ac │ 1 5 10 15 20
46
+ Striped - Green/Yellow Nature-inspir │
47
+ Striped - Red/Magenta Warm gradient │ ─────────────────────────────────
48
+
49
+ │ Variant: area
50
+ ↵ open detail ↑↓ navigate ^k act │ ▼
51
+
52
+ "
53
+ `)
54
+
55
+ expect(text).toMatch(/[\u2800-\u28FF]/)
56
+ expect(text).toContain('Stock Price')
57
+ }, 30000)
58
+
59
+ test('filled style renders block characters', async () => {
60
+ await session.text({
61
+ waitFor: (text) => {
62
+ return text.includes('Filled') && text.includes('│')
63
+ },
64
+ timeout: 10000,
65
+ })
66
+
67
+ // Navigate to 5th item: "Filled - Red Revenue"
68
+ for (let i = 0; i < 4; i++) {
69
+ await session.press('down')
70
+ }
71
+
72
+ const text = await session.text({
73
+ waitFor: (text) => {
74
+ return text.includes('›Filled - Red')
75
+ },
76
+ timeout: 5000,
77
+ })
78
+
79
+ expect(text).toMatchInlineSnapshot(`
80
+ "
81
+
82
+
83
+ Graph Styles ─────────────────────────────────────────────────────────────
84
+
85
+ > Search...
86
+
87
+ Area - Stock Price Orange braille do │ Revenue Growth ▲
88
+ Area - Multi Series CPU + Memory ove │ █
89
+ Area - Waves Purple + Magenta sine/c │ Quarterly revenue from $10k to
90
+ Area - Blue Revenue Single series, a │ $75k.
91
+ ›Filled - Red Revenue Solid block gro │
92
+ Filled - Green Temp Daily temperatur │ Q1: $10k → Q2: $25k (+150%)
93
+ Filled - Yellow CPU High contrast on │ Q2: $25k → Q3: $50k (+100%)
94
+ Filled - Magenta Waves Smooth curve │ Q3: $50k → Q4: $75k (+50%)
95
+ Striped - Purple/Orange Warm alterna │
96
+ Striped - Blue/Red High contrast str │ 78│ ▄
97
+ Striped - Theme Default primary + ac │ │ ▄▀▄▀▀
98
+ Striped - Green/Yellow Nature-inspir │ │ ▄▄▄▀▀▀▀▀▀
99
+ Striped - Red/Magenta Warm gradient │ 54│ ▄▀▀▀▀▀▀▀▀▀▀
100
+ │ │ ▄▄▄▀▀▀▀▀▀▀▀▀▀▀▀
101
+ │ │ ▄ ▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
102
+ ↵ open detail ↑↓ navigate ^k act │ 31│ ▄▀▀▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ ▼
103
+
104
+ "
105
+ `)
106
+
107
+ expect(text).toMatch(/[▄▀]/)
108
+ expect(text).toContain('›Filled - Red')
109
+ }, 30000)
110
+
111
+ test('striped style renders alternating columns', async () => {
112
+ await session.text({
113
+ waitFor: (text) => {
114
+ return text.includes('Striped') && text.includes('│')
115
+ },
116
+ timeout: 10000,
117
+ })
118
+
119
+ // Navigate to 9th item: "Striped - Purple/Orange"
120
+ for (let i = 0; i < 8; i++) {
121
+ await session.press('down')
122
+ }
123
+
124
+ const text = await session.text({
125
+ waitFor: (text) => {
126
+ return text.includes('›Striped - Purple')
127
+ },
128
+ timeout: 5000,
129
+ })
130
+
131
+ expect(text).toMatchInlineSnapshot(`
132
+ "
133
+
134
+
135
+ Graph Styles ─────────────────────────────────────────────────────────────
136
+
137
+ > Search...
138
+
139
+ Area - Stock Price Orange braille do │ 211│ ▄ ▲
140
+ Area - Multi Series CPU + Memory ove │ │ ▄▄▀▀ █
141
+ Area - Waves Purple + Magenta sine/c │ │ ▄▄▄▀▀▀▀▀ █
142
+ Area - Blue Revenue Single series, a │ 189│ ▄▄▀▄▀▀▀▀▀▀▀▀▀
143
+ Filled - Red Revenue Solid block gro │ │ ▄▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀
144
+ Filled - Green Temp Daily temperatur │ │ ▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
145
+ Filled - Yellow CPU High contrast on │ 167│ ▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
146
+ Filled - Magenta Waves Smooth curve │ │ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
147
+ ›Striped - Purple/Orange Warm alterna │ │▄▀▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
148
+ Striped - Blue/Red High contrast str │ 145│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
149
+ Striped - Theme Default primary + ac │ 1 5 10 15 20
150
+ Striped - Green/Yellow Nature-inspir │
151
+ Striped - Red/Magenta Warm gradient │ ─────────────────────────────────
152
+
153
+ │ Even cols: Purple
154
+ ↵ open detail ↑↓ navigate ^k act │ ▼
155
+
156
+ "
157
+ `)
158
+
159
+ expect(text).toMatch(/[▄▀]/)
160
+ expect(text).toContain('›Striped - Purple')
161
+ }, 30000)
162
+
163
+ test('markdown + metadata detail view in list', async () => {
164
+ await session.text({
165
+ waitFor: (text) => {
166
+ return text.includes('Area - Multi') && text.includes('│')
167
+ },
168
+ timeout: 10000,
169
+ })
170
+
171
+ // Navigate to 2nd item: "Area - Multi Series" (has markdown)
172
+ await session.press('down')
173
+
174
+ const text = await session.text({
175
+ waitFor: (text) => {
176
+ return text.includes('›Area - Multi') && text.includes('System Metrics')
177
+ },
178
+ timeout: 5000,
179
+ })
180
+
181
+ expect(text).toMatchInlineSnapshot(`
182
+ "
183
+
184
+
185
+ Graph Styles ─────────────────────────────────────────────────────────────
186
+
187
+ > Search...
188
+
189
+ Area - Stock Price Orange braille do │ System Metrics ▲
190
+ ›Area - Multi Series CPU + Memory ove │ ▀
191
+ Area - Waves Purple + Magenta sine/c │ CPU usage (blue) vs memory usage (
192
+ Area - Blue Revenue Single series, a │ green) over 24 hours.
193
+ Filled - Red Revenue Solid block gro │
194
+ Filled - Green Temp Daily temperatur │ - Peak CPU at 90% around 15h
195
+ Filled - Yellow CPU High contrast on │ - Memory steadily climbing to 86%
196
+ Filled - Magenta Waves Smooth curve │ - CPU has high variance, memory
197
+ Striped - Purple/Orange Warm alterna │ is monotonic
198
+ Striped - Blue/Red High contrast str │
199
+ Striped - Theme Default primary + ac │
200
+ Striped - Green/Yellow Nature-inspir │ 100│
201
+ Striped - Red/Magenta Warm gradient │ │ ⣠⣶⣧ ⣀⣠⣤⣶
202
+ │ 75│ ⢀⣴⣧ ⢀⣰⣿⣿⣿⣷⣾⣿⣿⣿⣿⣿
203
+ │ │ ⢀⣾⣿⣿⣧⢀⣀⣤⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
204
+ ↵ open detail ↑↓ navigate ^k act │ │ ⢀⣾⣶⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ▼
205
+
206
+ "
207
+ `)
208
+
209
+ expect(text).toContain('System Metrics')
210
+ expect(text).toMatch(/[\u2800-\u28FF]/)
211
+ }, 30000)
212
+
213
+ test('enter pushes full detail view with graph', async () => {
214
+ await session.text({
215
+ waitFor: (text) => {
216
+ return text.includes('Area - Stock') && text.includes('│')
217
+ },
218
+ timeout: 10000,
219
+ })
220
+
221
+ // Press enter to push the full Detail view for first item
222
+ await session.press('return')
223
+
224
+ const text = await session.text({
225
+ waitFor: (text) => {
226
+ return text.includes('Area - Stock Price') && text.includes('Orange braille dots')
227
+ },
228
+ timeout: 5000,
229
+ })
230
+
231
+ expect(text).toMatchInlineSnapshot(`
232
+ "
233
+
234
+
235
+
236
+
237
+ Area - Stock Price
238
+
239
+ Orange braille dots
240
+
241
+ Variant: area
242
+ Data points: 20
243
+
244
+ 211│ ⢀
245
+ │ ⢀⣴⣿
246
+ │ ⢀⣠⣴⣾⣷⣶⣦⣴⣿⣿⣿
247
+ │ ⣠⣄⣀ ⣠⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
248
+ 195│ ⢀⡀ ⣠⣾⣿⣿⣿⣿⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
249
+ │ ⣠⣴⣾⣿⣿⣿⣷⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
250
+ │ ⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
251
+ 178│ ⣀⣤⣶⣿⣶⣶⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
252
+
253
+
254
+ esc go back ^k actions ↵ Go Back powered by termcast.app
255
+
256
+ "
257
+ `)
258
+
259
+ // Full detail view shows markdown title and graph
260
+ expect(text).toContain('Stock Price')
261
+ expect(text).toContain('Orange braille')
262
+ expect(text).toMatch(/[\u2800-\u28FF]/)
263
+ }, 30000)
264
+
265
+ test('esc returns from detail to list', async () => {
266
+ await session.text({
267
+ waitFor: (text) => {
268
+ return text.includes('Area - Stock') && text.includes('│')
269
+ },
270
+ timeout: 10000,
271
+ })
272
+
273
+ // Push detail view
274
+ await session.press('return')
275
+ await session.text({
276
+ waitFor: (text) => {
277
+ return text.includes('Orange braille dots')
278
+ },
279
+ timeout: 5000,
280
+ })
281
+
282
+ // Go back
283
+ await session.press('escape')
284
+
285
+ const text = await session.text({
286
+ waitFor: (text) => {
287
+ return text.includes('›Area - Stock Price') && text.includes('Graph Styles')
288
+ },
289
+ timeout: 5000,
290
+ })
291
+
292
+ expect(text).toMatchInlineSnapshot(`
293
+ "
294
+
295
+
296
+ Graph Styles ─────────────────────────────────────────────────────────────
297
+
298
+ > Search...
299
+
300
+ ›Area - Stock Price Orange braille do │ 211│ ⣠ ▲
301
+ Area - Multi Series CPU + Memory ove │ │ ⢀⣴⣦⣼⣿ █
302
+ Area - Waves Purple + Magenta sine/c │ │ ⢠⣦⣄⣴⣿⣿⣿⣿⣿ █
303
+ Area - Blue Revenue Single series, a │ 189│ ⢀⣴⣷⣦⣿⣿⣿⣿⣿⣿⣿⣿⣿ █
304
+ Filled - Red Revenue Solid block gro │ │ ⣠⣀⢠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ▀
305
+ Filled - Green Temp Daily temperatur │ │ ⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
306
+ Filled - Yellow CPU High contrast on │ 167│ ⢀⣴⣿⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
307
+ Filled - Magenta Waves Smooth curve │ │ ⣰⣤⣰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
308
+ Striped - Purple/Orange Warm alterna │ │⢀⣴⡄⢰⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
309
+ Striped - Blue/Red High contrast str │ 145│⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿
310
+ Striped - Theme Default primary + ac │ 1 5 10 15 20
311
+ Striped - Green/Yellow Nature-inspir │
312
+ Striped - Red/Magenta Warm gradient │ ─────────────────────────────────
313
+
314
+ │ Variant: area
315
+ ↵ open detail ↑↓ navigate ^k act │ ▼
316
+
317
+ "
318
+ `)
319
+
320
+ expect(text).toContain('›Area - Stock')
321
+ expect(text).toContain('Graph Styles')
322
+ }, 30000)
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Example: List with accessoryTagsLayout for column-aligned accessories.
3
+ *
4
+ * Demonstrates table-like alignment where accessories at the same position
5
+ * (or with the same tag key/color) form fixed-width columns across all items.
6
+ * Missing accessories get empty space to preserve alignment.
7
+ *
8
+ * Shows: tag key grouping, color grouping, mixed accessory types, missing tags.
9
+ */
10
+ import { renderWithProviders, Color } from 'termcast'
11
+ import List from 'termcast'
12
+
13
+ function ListAccessoryTableExample() {
14
+ const now = new Date()
15
+ const hoursAgo = (h: number) => new Date(now.getTime() - h * 3600_000)
16
+ const daysAgo = (d: number) => new Date(now.getTime() - d * 86400_000)
17
+
18
+ // Column widths: [comments 11 "12 comments", status 11 "In Progress", priority 2 "P3"]
19
+ return (
20
+ <List navigationTitle="Accessory Table Layout" accessoryTagsLayout={[11, 11, 2]}>
21
+ <List.Section title="GitHub Issues">
22
+ <List.Item
23
+ id="issue-1"
24
+ title="Fix login timeout on slow networks"
25
+ accessories={[
26
+ { tag: { value: '3 comments', key: 'comments' } },
27
+ { tag: { value: 'Open', color: Color.Green, key: 'status' } },
28
+ { tag: { value: 'P1', color: Color.Red, key: 'priority' } },
29
+ { date: hoursAgo(2) },
30
+ ]}
31
+ />
32
+ <List.Item
33
+ id="issue-2"
34
+ title="Add dark mode support"
35
+ accessories={[
36
+ { tag: { value: '12 comments', key: 'comments' } },
37
+ { tag: { value: 'In Progress', color: Color.Orange, key: 'status' } },
38
+ { tag: { value: 'P2', color: Color.Yellow, key: 'priority' } },
39
+ { date: daysAgo(1) },
40
+ ]}
41
+ />
42
+ <List.Item
43
+ id="issue-3"
44
+ title="Update documentation for v3 API"
45
+ accessories={[
46
+ { tag: { value: '0 comments', key: 'comments' } },
47
+ { tag: { value: 'Open', color: Color.Green, key: 'status' } },
48
+ { tag: { value: 'P3', color: Color.Blue, key: 'priority' } },
49
+ { date: daysAgo(5) },
50
+ ]}
51
+ />
52
+ <List.Item
53
+ id="issue-4"
54
+ title="Refactor auth module"
55
+ accessories={[
56
+ { tag: { value: '7 comments', key: 'comments' } },
57
+ { tag: { value: 'Closed', color: Color.Purple, key: 'status' } },
58
+ { tag: null },
59
+ { date: daysAgo(14) },
60
+ ]}
61
+ />
62
+ <List.Item
63
+ id="issue-5"
64
+ title="Fix memory leak in worker pool"
65
+ accessories={[
66
+ { tag: { value: '1 comment', key: 'comments' } },
67
+ { tag: { value: 'Open', color: Color.Green, key: 'status' } },
68
+ { tag: { value: 'P1', color: Color.Red, key: 'priority' } },
69
+ { date: hoursAgo(6) },
70
+ ]}
71
+ />
72
+ </List.Section>
73
+ </List>
74
+ )
75
+ }
76
+
77
+ await renderWithProviders(<ListAccessoryTableExample />)
@@ -38,11 +38,9 @@ test('list detail metadata label renders short values in row layout (key: value)
38
38
 
39
39
  > Search...
40
40
 
41
- ›Short Values
42
- Long Values │ Details
43
- Colored & Tags │
44
-
45
- │ Name: John Doe
41
+ ›Short Values │ Details
42
+ Long Values │
43
+ Colored & Tags │ Name: John Doe
46
44
 
47
45
  │ Email: john@example.com
48
46
 
@@ -50,8 +48,10 @@ test('list detail metadata label renders short values in row layout (key: value)
50
48
 
51
49
  │ Status: Active
52
50
 
53
- │ Website: example.com
54
- ↑↓ navigate ^k actions │
51
+ ↑↓ navigate ^k actions │ Website: example.com
52
+
53
+
54
+
55
55
 
56
56
 
57
57
 
@@ -96,11 +96,9 @@ test('list detail metadata renders long values in column layout (key on one line
96
96
 
97
97
  > Search...
98
98
 
99
- Short Values
100
- ›Long Values │ Info with Long Values
101
- Colored & Tags │
102
-
103
- │ Description: This is a very long
99
+ Short Values │ Info with Long Values
100
+ ›Long Values │
101
+ Colored & Tags │ Description: This is a very long
104
102
  │ description that
105
103
  │ would be truncated
106
104
  │ if shown inline
@@ -115,8 +113,10 @@ test('list detail metadata renders long values in column layout (key on one line
115
113
  │ Short: OK
116
114
 
117
115
  │ URL: example.com/very/
118
- │ long/path
119
- ↑↓ navigate ^k actions │
116
+ ↑↓ navigate ^k actions │ long/path
117
+
118
+
119
+
120
120
 
121
121
 
122
122
 
@@ -156,13 +156,11 @@ test('list detail metadata renders colored values and tag lists', async () => {
156
156
 
157
157
  > Search...
158
158
 
159
- Short Values
160
- Long Values │ Project Status
161
- ›Colored & Tags │
162
- │ Overview of the current project
159
+ Short Values │ Project Status
160
+ Long Values │
161
+ ›Colored & Tags │ Overview of the current project
163
162
  │ state.
164
163
 
165
-
166
164
  │ Info
167
165
 
168
166
  │ Status: Active
@@ -179,8 +177,10 @@ test('list detail metadata renders colored values and tag lists', async () => {
179
177
 
180
178
  │ ──────────────────────────────────
181
179
 
182
- │ Repo: github.com/example
183
- ↑↓ navigate ^k actions │
180
+ ↑↓ navigate ^k actions │ Repo: github.com/example
181
+
182
+
183
+
184
184
 
185
185
 
186
186
 
@@ -33,7 +33,6 @@ test('dropdown defaults to first item when no value is provided', async () => {
33
33
 
34
34
  Dropdown Default Value Example ───────────────────────────────────────────
35
35
 
36
-
37
36
  > Search... Apple ▾
38
37
 
39
38
  ›First Item This list has a dropdown
@@ -44,7 +43,8 @@ test('dropdown defaults to first item when no value is provided', async () => {
44
43
 
45
44
 
46
45
 
47
- ↵ show selected fruit ↑↓ navigate ^p dropdown ^k powered by termcast
46
+ ↵ show selected fruit ↑↓ navigate ^p dropdown powered by termcast.app
47
+
48
48
 
49
49
 
50
50
 
@@ -77,7 +77,6 @@ test('dropdown opens and shows items', async () => {
77
77
 
78
78
 
79
79
  Dropdown Default Value Example ───────────────────────────────────────────
80
-
81
80
  ╭──────────────────────────────────────────────────────────────────────────╮
82
81
  │ │
83
82
  │ Filter by category esc │
@@ -90,7 +89,7 @@ test('dropdown opens and shows items', async () => {
90
89
  │ Grape │
91
90
  │ │
92
91
  │ │
93
- │ ↵ select ↑↓ navigate powered by termcast │
92
+ │ ↵ select ↑↓ navigate powered by termcast.app
94
93
  │ │
95
94
  ╰──────────────────────────────────────────────────────────────────────────╯
96
95
 
@@ -103,6 +102,7 @@ test('dropdown opens and shows items', async () => {
103
102
 
104
103
 
105
104
 
105
+
106
106
  "
107
107
  `)
108
108
 
@@ -114,7 +114,6 @@ test('dropdown opens and shows items', async () => {
114
114
 
115
115
 
116
116
  Dropdown Default Value Example ───────────────────────────────────────────
117
-
118
117
  ╭──────────────────────────────────────────────────────────────────────────╮
119
118
  │ │
120
119
  │ Filter by category esc │
@@ -127,7 +126,7 @@ test('dropdown opens and shows items', async () => {
127
126
  │ Grape │
128
127
  │ │
129
128
  │ │
130
- │ ↵ select ↑↓ navigate powered by termcast │
129
+ │ ↵ select ↑↓ navigate powered by termcast.app
131
130
  │ │
132
131
  ╰──────────────────────────────────────────────────────────────────────────╯
133
132
 
@@ -140,6 +139,7 @@ test('dropdown opens and shows items', async () => {
140
139
 
141
140
 
142
141
 
142
+
143
143
  "
144
144
  `)
145
145
 
@@ -152,7 +152,6 @@ test('dropdown opens and shows items', async () => {
152
152
 
153
153
  Dropdown Default Value Example ───────────────────────────────────────────
154
154
 
155
-
156
155
  > Search... Banana ▾
157
156
 
158
157
  ›First Item This list has a dropdown
@@ -163,7 +162,8 @@ test('dropdown opens and shows items', async () => {
163
162
 
164
163
 
165
164
 
166
- ↵ show selected fruit ↑↓ navigate ^p dropdown ^k powered by termcast
165
+ ↵ show selected fruit ↑↓ navigate ^p dropdown powered by termcast.app
166
+
167
167
 
168
168
 
169
169
 
@@ -196,7 +196,6 @@ test('clicking dropdown opens it', async () => {
196
196
 
197
197
 
198
198
  Dropdown Default Value Example ───────────────────────────────────────────
199
-
200
199
  ╭──────────────────────────────────────────────────────────────────────────╮
201
200
  │ │
202
201
  │ Filter by category esc │
@@ -209,7 +208,7 @@ test('clicking dropdown opens it', async () => {
209
208
  │ Grape │
210
209
  │ │
211
210
  │ │
212
- │ ↵ select ↑↓ navigate powered by termcast │
211
+ │ ↵ select ↑↓ navigate powered by termcast.app
213
212
  │ │
214
213
  ╰──────────────────────────────────────────────────────────────────────────╯
215
214
 
@@ -222,6 +221,7 @@ test('clicking dropdown opens it', async () => {
222
221
 
223
222
 
224
223
 
224
+
225
225
  "
226
226
  `)
227
227
 
@@ -234,7 +234,6 @@ test('clicking dropdown opens it', async () => {
234
234
 
235
235
  Dropdown Default Value Example ───────────────────────────────────────────
236
236
 
237
-
238
237
  > Search... Orange ▾
239
238
 
240
239
  ›First Item This list has a dropdown
@@ -245,7 +244,8 @@ test('clicking dropdown opens it', async () => {
245
244
 
246
245
 
247
246
 
248
- ↵ show selected fruit ↑↓ navigate ^p dropdown ^k powered by termcast
247
+ ↵ show selected fruit ↑↓ navigate ^p dropdown powered by termcast.app
248
+
249
249
 
250
250
 
251
251