termcast 1.4.0 → 1.5.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.
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +8 -7
- package/dist/build.js.map +1 -1
- package/dist/cli.js +0 -40
- package/dist/cli.js.map +1 -1
- package/dist/components/bar-graph.d.ts +23 -8
- package/dist/components/bar-graph.d.ts.map +1 -1
- package/dist/components/bar-graph.js +84 -40
- package/dist/components/bar-graph.js.map +1 -1
- package/dist/components/dotted-line-graph.d.ts +86 -0
- package/dist/components/dotted-line-graph.d.ts.map +1 -0
- package/dist/components/dotted-line-graph.js +260 -0
- package/dist/components/dotted-line-graph.js.map +1 -0
- package/dist/components/extension-preferences.d.ts.map +1 -1
- package/dist/components/extension-preferences.js +1 -10
- package/dist/components/extension-preferences.js.map +1 -1
- package/dist/components/graph.d.ts.map +1 -1
- package/dist/components/graph.js +7 -1
- package/dist/components/graph.js.map +1 -1
- package/dist/components/histogram.d.ts +42 -0
- package/dist/components/histogram.d.ts.map +1 -0
- package/dist/components/histogram.js +115 -0
- package/dist/components/histogram.js.map +1 -0
- package/dist/components/horizontal-bar-graph.d.ts +47 -0
- package/dist/components/horizontal-bar-graph.d.ts.map +1 -0
- package/dist/components/horizontal-bar-graph.js +137 -0
- package/dist/components/horizontal-bar-graph.js.map +1 -0
- package/dist/components/list.d.ts +2 -0
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +10 -10
- package/dist/components/list.js.map +1 -1
- package/dist/examples/bar-graph-weekly.js +2 -2
- package/dist/examples/bar-graph-weekly.js.map +1 -1
- package/dist/examples/charts-showcase-barchart.d.ts +2 -0
- package/dist/examples/charts-showcase-barchart.d.ts.map +1 -0
- package/dist/examples/charts-showcase-barchart.js +10 -0
- package/dist/examples/charts-showcase-barchart.js.map +1 -0
- package/dist/examples/charts-showcase-bargraph.d.ts +2 -0
- package/dist/examples/charts-showcase-bargraph.d.ts.map +1 -0
- package/dist/examples/charts-showcase-bargraph.js +60 -0
- package/dist/examples/charts-showcase-bargraph.js.map +1 -0
- package/dist/examples/charts-showcase-candle.d.ts +2 -0
- package/dist/examples/charts-showcase-candle.d.ts.map +1 -0
- package/dist/examples/charts-showcase-candle.js +30 -0
- package/dist/examples/charts-showcase-candle.js.map +1 -0
- package/dist/examples/charts-showcase-graph.d.ts +2 -0
- package/dist/examples/charts-showcase-graph.d.ts.map +1 -0
- package/dist/examples/charts-showcase-graph.js +33 -0
- package/dist/examples/charts-showcase-graph.js.map +1 -0
- package/dist/examples/charts-showcase-heatmap.d.ts +2 -0
- package/dist/examples/charts-showcase-heatmap.d.ts.map +1 -0
- package/dist/examples/charts-showcase-heatmap.js +36 -0
- package/dist/examples/charts-showcase-heatmap.js.map +1 -0
- package/dist/examples/charts-showcase-mixed.d.ts +2 -0
- package/dist/examples/charts-showcase-mixed.d.ts.map +1 -0
- package/dist/examples/charts-showcase-mixed.js +30 -0
- package/dist/examples/charts-showcase-mixed.js.map +1 -0
- package/dist/examples/charts-showcase-progress.d.ts +2 -0
- package/dist/examples/charts-showcase-progress.d.ts.map +1 -0
- package/dist/examples/charts-showcase-progress.js +10 -0
- package/dist/examples/charts-showcase-progress.js.map +1 -0
- package/dist/examples/graph-multi-series.js +1 -1
- package/dist/examples/graph-multi-series.js.map +1 -1
- package/dist/examples/horizontal-bar-graph-weekly.d.ts +2 -0
- package/dist/examples/horizontal-bar-graph-weekly.d.ts.map +1 -0
- package/dist/examples/horizontal-bar-graph-weekly.js +67 -0
- package/dist/examples/horizontal-bar-graph-weekly.js.map +1 -0
- package/dist/examples/simple-dotted-line-graph.d.ts +2 -0
- package/dist/examples/simple-dotted-line-graph.d.ts.map +1 -0
- package/dist/examples/simple-dotted-line-graph.js +39 -0
- package/dist/examples/simple-dotted-line-graph.js.map +1 -0
- package/dist/examples/simple-histogram.d.ts +2 -0
- package/dist/examples/simple-histogram.d.ts.map +1 -0
- package/dist/examples/simple-histogram.js +47 -0
- package/dist/examples/simple-histogram.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts.map +1 -1
- package/dist/logger.js +15 -6
- package/dist/logger.js.map +1 -1
- package/dist/platform/node/sqlite.d.ts +6 -5
- package/dist/platform/node/sqlite.d.ts.map +1 -1
- package/dist/platform/node/sqlite.js +30 -14
- package/dist/platform/node/sqlite.js.map +1 -1
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +11 -9
- package/dist/theme.js.map +1 -1
- package/dist/utils/run-command.d.ts.map +1 -1
- package/dist/utils/run-command.js +8 -19
- package/dist/utils/run-command.js.map +1 -1
- package/dist/utils.d.ts +1 -19
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +1 -100
- package/dist/utils.js.map +1 -1
- package/package.json +14 -16
- package/src/build.tsx +11 -10
- package/src/cli.tsx +3 -40
- package/src/compile.vitest.tsx +3 -3
- package/src/components/bar-graph.tsx +217 -111
- package/src/components/dotted-line-graph.tsx +407 -0
- package/src/components/extension-preferences.tsx +2 -12
- package/src/components/graph.tsx +5 -1
- package/src/components/histogram.tsx +228 -0
- package/src/components/horizontal-bar-graph.tsx +279 -0
- package/src/components/list.tsx +20 -15
- package/src/examples/action-shortcut.vitest.tsx +17 -17
- package/src/examples/bar-graph-weekly.tsx +2 -2
- package/src/examples/bar-graph-weekly.vitest.tsx +63 -62
- package/src/examples/charts-showcase-bargraph.tsx +103 -0
- package/src/examples/detail-metadata-showcase.vitest.tsx +13 -18
- package/src/examples/form-basic.vitest.tsx +35 -35
- package/src/examples/form-dropdown.vitest.tsx +11 -11
- package/src/examples/form-scroll.vitest.tsx +1 -1
- package/src/examples/form-tagpicker.vitest.tsx +11 -11
- package/src/examples/github.vitest.tsx +22 -22
- package/src/examples/graph-bar-chart.vitest.tsx +8 -8
- package/src/examples/graph-multi-series.tsx +1 -1
- package/src/examples/graph-row.vitest.tsx +14 -14
- package/src/examples/graph-styles.vitest.tsx +77 -77
- package/src/examples/horizontal-bar-graph-weekly.tsx +138 -0
- package/src/examples/horizontal-bar-graph-weekly.vitest.tsx +164 -0
- package/src/examples/list-detail-metadata.vitest.tsx +4 -4
- package/src/examples/list-with-detail.vitest.tsx +46 -46
- package/src/examples/simple-candle-chart.vitest.tsx +8 -8
- package/src/examples/simple-dotted-line-graph.tsx +53 -0
- package/src/examples/simple-dotted-line-graph.vitest.tsx +62 -0
- package/src/examples/simple-grid.vitest.tsx +4 -4
- package/src/examples/simple-histogram.tsx +90 -0
- package/src/examples/simple-navigation.vitest.tsx +4 -4
- package/src/examples/swift-extension.vitest.tsx +3 -3
- package/src/examples/toast-variations.vitest.tsx +5 -5
- package/src/extensions/dev.vitest.tsx +8 -8
- package/src/index.tsx +21 -0
- package/src/logger.tsx +16 -6
- package/src/platform/node/sqlite.ts +29 -13
- package/src/theme.tsx +11 -10
- package/src/utils/run-command.tsx +10 -19
- package/src/utils.tsx +0 -163
- package/src/examples/store.tsx +0 -4
- package/src/examples/store.vitest.tsx +0 -78
- package/src/extensions/home.tsx +0 -227
- package/src/extensions/store.tsx +0 -375
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// E2E tests for BarGraph vertical stacked bar chart.
|
|
2
|
-
// Bar segments
|
|
2
|
+
// Bar segments use ▃ chars so they show in text snapshots without filling cells.
|
|
3
3
|
|
|
4
4
|
import { test, expect, afterEach, beforeEach } from 'vitest'
|
|
5
5
|
import { launchTerminal, Session } from 'tuistory/src'
|
|
@@ -22,7 +22,7 @@ afterEach(() => {
|
|
|
22
22
|
test('bar graph renders bars, labels, and legend', async () => {
|
|
23
23
|
const text = await session.text({
|
|
24
24
|
waitFor: (text) => {
|
|
25
|
-
return text.includes('Mon') && text.includes('
|
|
25
|
+
return text.includes('Mon') && text.includes('Direct') && text.includes('0.0│')
|
|
26
26
|
},
|
|
27
27
|
timeout: 10000,
|
|
28
28
|
})
|
|
@@ -35,17 +35,17 @@ test('bar graph renders bars, labels, and legend', async () => {
|
|
|
35
35
|
|
|
36
36
|
> Search...
|
|
37
37
|
|
|
38
|
-
›
|
|
39
|
-
|
|
40
|
-
Server Load CPU / Memory / IO │
|
|
41
|
-
Many
|
|
42
|
-
Many Series (8) Legend overflow test │
|
|
43
|
-
|
|
44
|
-
Week 1 vs Week 2 Two graphs in a Row │
|
|
45
|
-
│
|
|
46
|
-
│
|
|
47
|
-
│
|
|
48
|
-
↵ open detail ↑↓ navigate ^k act │ ■ Direct
|
|
38
|
+
›Weekl...affic3 channels...oss 6 days │ 110.0│ ▃▃▃
|
|
39
|
+
Revenu... Regio EMEA / A... Americas │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
40
|
+
Server Load CPU / Memory / IO │ 82.5│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
41
|
+
Many ...s (20)Overflow ...th 20 bars │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
42
|
+
Many Series (8) Legend overflow test │ 55.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
43
|
+
Lon...belsLabels wide... bar columns │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
44
|
+
Week 1 vs Week 2 Two graphs in a Row │ 27.5│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
45
|
+
│ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
46
|
+
│ 0.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
47
|
+
│ Mon Tue Wed Thu Fri Sat
|
|
48
|
+
↵ open detail ↑↓ navigate ^k act │ ■ Direct ■ Organic ■ Referral
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
|
|
@@ -62,20 +62,20 @@ test('bar graph renders bars, labels, and legend', async () => {
|
|
|
62
62
|
`)
|
|
63
63
|
|
|
64
64
|
expect(text).toContain('Mon')
|
|
65
|
-
expect(text).toContain('Sat')
|
|
66
65
|
expect(text).toContain('Direct')
|
|
67
|
-
expect(text).toContain('
|
|
66
|
+
expect(text).toContain('0.0│')
|
|
67
|
+
expect(text).toContain('▃')
|
|
68
68
|
}, 30000)
|
|
69
69
|
|
|
70
70
|
test('many columns (20) clips with overflow hidden', async () => {
|
|
71
|
-
await session.text({ waitFor: (t) => t.includes('
|
|
71
|
+
await session.text({ waitFor: (t) => t.includes('(20)'), timeout: 10000 })
|
|
72
72
|
// Navigate: Weekly Traffic, Revenue, Server Load, Many Columns = 3 downs
|
|
73
73
|
session.sendKey('down')
|
|
74
74
|
session.sendKey('down')
|
|
75
75
|
session.sendKey('down')
|
|
76
76
|
|
|
77
77
|
await session.text({
|
|
78
|
-
waitFor: (t) => t.includes('›Many
|
|
78
|
+
waitFor: (t) => t.includes('›Many ...s (20)'),
|
|
79
79
|
timeout: 10000,
|
|
80
80
|
})
|
|
81
81
|
await session.waitIdle()
|
|
@@ -83,16 +83,16 @@ test('many columns (20) clips with overflow hidden', async () => {
|
|
|
83
83
|
|
|
84
84
|
// Bar graph rendering has non-deterministic ANSI highlights, so use toContain checks
|
|
85
85
|
// instead of inline snapshot for the bars area
|
|
86
|
-
expect(text).toContain('›Many
|
|
86
|
+
expect(text).toContain('›Many ...s (20)')
|
|
87
87
|
expect(text).toContain('BarGraph Showcase')
|
|
88
|
-
expect(text).toContain('
|
|
88
|
+
expect(text).toContain('▃')
|
|
89
89
|
|
|
90
90
|
// Some labels visible, overflow clips the rest
|
|
91
|
-
expect(text).toContain('
|
|
92
|
-
expect(text).toContain('
|
|
91
|
+
expect(text).toContain('D')
|
|
92
|
+
expect(text).toContain('▃')
|
|
93
93
|
}, 30000)
|
|
94
94
|
|
|
95
|
-
test('many series (8) legend clips on one
|
|
95
|
+
test('many series (8) bottom legend clips on one row', async () => {
|
|
96
96
|
await session.text({ waitFor: (t) => t.includes('Many Series'), timeout: 10000 })
|
|
97
97
|
// Navigate: Weekly, Revenue, Server, Many Columns, Many Series = 4 downs
|
|
98
98
|
session.sendKey('down')
|
|
@@ -113,17 +113,17 @@ test('many series (8) legend clips on one line', async () => {
|
|
|
113
113
|
|
|
114
114
|
> Search...
|
|
115
115
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
Server Load CPU / Memory / IO │
|
|
119
|
-
Many
|
|
120
|
-
›Many Series (8) Legend overflow test │
|
|
121
|
-
|
|
122
|
-
Week 1 vs Week 2 Two graphs in a Row │
|
|
123
|
-
│
|
|
124
|
-
│
|
|
125
|
-
│
|
|
126
|
-
↑↓ navigate ^k actions :vim │ ■ Series 1
|
|
116
|
+
Weekl...affic3 channels...oss 6 days │ 328.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
117
|
+
Revenu... Regio EMEA / A... Americas │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
118
|
+
Server Load CPU / Memory / IO │ 246.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
119
|
+
Many ...s (20)Overflow ...th 20 bars │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
120
|
+
›Many Series (8) Legend overflow test │ 164.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
121
|
+
Lon...belsLabels wide... bar columns │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
122
|
+
Week 1 vs Week 2 Two graphs in a Row │ 82.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
123
|
+
│ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
124
|
+
│ 0.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
125
|
+
│ Mon Tue Wed Thu Fri Sat
|
|
126
|
+
↑↓ navigate ^k actions :vim │ ■ Series 1 ■ Series 2 ■ Series 3
|
|
127
127
|
|
|
128
128
|
|
|
129
129
|
|
|
@@ -139,13 +139,14 @@ test('many series (8) legend clips on one line', async () => {
|
|
|
139
139
|
"
|
|
140
140
|
`)
|
|
141
141
|
|
|
142
|
-
//
|
|
142
|
+
// Bottom legend is a single clipped row by default.
|
|
143
143
|
expect(text).toContain('Series 1')
|
|
144
|
-
expect(text).toContain('
|
|
144
|
+
expect(text).toContain('Series 3')
|
|
145
|
+
expect(text).toContain('▃')
|
|
145
146
|
}, 30000)
|
|
146
147
|
|
|
147
148
|
test('long labels truncated by overflow hidden', async () => {
|
|
148
|
-
await session.text({ waitFor: (t) => t.includes('
|
|
149
|
+
await session.text({ waitFor: (t) => t.includes('Lon...bels'), timeout: 10000 })
|
|
149
150
|
// Navigate: Weekly, Revenue, Server, Many Columns, Many Series, Long Labels = 5 downs
|
|
150
151
|
session.sendKey('down')
|
|
151
152
|
session.sendKey('down')
|
|
@@ -154,7 +155,7 @@ test('long labels truncated by overflow hidden', async () => {
|
|
|
154
155
|
session.sendKey('down')
|
|
155
156
|
|
|
156
157
|
const text = await session.text({
|
|
157
|
-
waitFor: (t) => t.includes('›
|
|
158
|
+
waitFor: (t) => t.includes('›Lon...bels'),
|
|
158
159
|
timeout: 10000,
|
|
159
160
|
})
|
|
160
161
|
|
|
@@ -166,17 +167,17 @@ test('long labels truncated by overflow hidden', async () => {
|
|
|
166
167
|
|
|
167
168
|
> Search...
|
|
168
169
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
Server Load CPU / Memory / IO │
|
|
172
|
-
Many
|
|
173
|
-
Many Series (8) Legend overflow test │
|
|
174
|
-
›
|
|
175
|
-
Week 1 vs Week 2 Two graphs in a Row │
|
|
176
|
-
│
|
|
177
|
-
│
|
|
178
|
-
│
|
|
179
|
-
↑↓ navigate ^k actions :vim │ ■ Views
|
|
170
|
+
Weekl...affic3 channels...oss 6 days │ 75.0│ ▃▃▃
|
|
171
|
+
Revenu... Regio EMEA / A... Americas │ │▃▃▃ ▃▃▃ ▃▃▃
|
|
172
|
+
Server Load CPU / Memory / IO │ 56.3│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
173
|
+
Many ...s (20)Overflow ...th 20 bars │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
174
|
+
Many Series (8) Legend overflow test │ 37.5│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
175
|
+
›Lon...belsLabels wide... bar columns │ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
176
|
+
Week 1 vs Week 2 Two graphs in a Row │ 18.8│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
177
|
+
│ │▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
178
|
+
│ 0.0│▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃ ▃▃▃
|
|
179
|
+
│ Monday Thursday
|
|
180
|
+
↑↓ navigate ^k actions :vim │ ■ Views ■ Clicks
|
|
180
181
|
|
|
181
182
|
|
|
182
183
|
|
|
@@ -192,8 +193,8 @@ test('long labels truncated by overflow hidden', async () => {
|
|
|
192
193
|
"
|
|
193
194
|
`)
|
|
194
195
|
|
|
195
|
-
expect(text).toContain('
|
|
196
|
-
expect(text).toContain('
|
|
196
|
+
expect(text).toContain('›Lon...bels')
|
|
197
|
+
expect(text).toContain('▃')
|
|
197
198
|
}, 30000)
|
|
198
199
|
|
|
199
200
|
test('side-by-side bar graphs in a Row', async () => {
|
|
@@ -219,17 +220,17 @@ test('side-by-side bar graphs in a Row', async () => {
|
|
|
219
220
|
|
|
220
221
|
> Search...
|
|
221
222
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
Server Load CPU / Memory / IO │
|
|
225
|
-
Many
|
|
226
|
-
Many Series (8) Legend overflow test │
|
|
227
|
-
|
|
228
|
-
›Week 1 vs Week 2 Two graphs in a Row │
|
|
229
|
-
│
|
|
230
|
-
│
|
|
231
|
-
│
|
|
232
|
-
↵ open detail ↑↓ navigate ^k act │ ■ Direct
|
|
223
|
+
Weekl...affic3 channels...oss 6 days │ 110.0│ 130.0│
|
|
224
|
+
Revenu... Regio EMEA / A... Americas │ │▃▃▃ ▃▃▃ │▃▃▃
|
|
225
|
+
Server Load CPU / Memory / IO │ 82.5│▃▃▃ ▃▃▃ 97.5│▃▃▃ ▃▃▃
|
|
226
|
+
Many ...s (20)Overflow ...th 20 bars │ │▃▃▃ ▃▃▃ ▃▃▃ │▃▃▃ ▃▃▃ ▃▃
|
|
227
|
+
Many Series (8) Legend overflow test │ 55.0│▃▃▃ ▃▃▃ ▃▃▃ 65.0│▃▃▃ ▃▃▃ ▃▃
|
|
228
|
+
Lon...belsLabels wide... bar columns │ │▃▃▃ ▃▃▃ ▃▃▃ │▃▃▃ ▃▃▃ ▃▃
|
|
229
|
+
›Week 1 vs Week 2 Two graphs in a Row │ 27.5│▃▃▃ ▃▃▃ ▃▃▃ 32.5│▃▃▃ ▃▃▃ ▃▃
|
|
230
|
+
│ │▃▃▃ ▃▃▃ ▃▃▃ │▃▃▃ ▃▃▃ ▃▃
|
|
231
|
+
│ 0.0│▃▃▃ ▃▃▃ ▃▃▃ 0.0│▃▃▃ ▃▃▃ ▃▃
|
|
232
|
+
│ Mon Tue Wed Mon Tue We
|
|
233
|
+
↵ open detail ↑↓ navigate ^k act │ ■ Direct ■ Organ ■ Direct ■ Orga
|
|
233
234
|
|
|
234
235
|
|
|
235
236
|
|
|
@@ -245,5 +246,5 @@ test('side-by-side bar graphs in a Row', async () => {
|
|
|
245
246
|
"
|
|
246
247
|
`)
|
|
247
248
|
|
|
248
|
-
expect(text).toContain('
|
|
249
|
+
expect(text).toContain('Direct')
|
|
249
250
|
}, 30000)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Showcase: BarGraph vertical stacked bar chart inside a Detail view.
|
|
2
|
+
// Recreates a monthly model spend chart with stacked per-day usage.
|
|
3
|
+
|
|
4
|
+
import { BarGraph, Detail } from 'termcast'
|
|
5
|
+
import { renderWithProviders } from '../utils'
|
|
6
|
+
|
|
7
|
+
const labels = Array.from({ length: 30 }, (_, i) => {
|
|
8
|
+
const day = i + 1
|
|
9
|
+
if (day % 2 === 0) {
|
|
10
|
+
return ''
|
|
11
|
+
}
|
|
12
|
+
return String(day).padStart(2, '0')
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
const emptyMonth = Array.from({ length: 30 }, () => 0)
|
|
16
|
+
|
|
17
|
+
function withSpend(points: Record<number, number>): number[] {
|
|
18
|
+
return emptyMonth.map((_, i) => points[i + 1] || 0)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const modelSpend = [
|
|
22
|
+
{
|
|
23
|
+
title: 'deepseek-v4-flash (go)',
|
|
24
|
+
color: '#b5bb69',
|
|
25
|
+
data: withSpend({ 21: 0.6, 25: 1.05, 26: 1.3, 27: 1.9, 28: 0.55, 29: 0.8, 30: 1.1 }),
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: 'deepseek-v4-pro (go)',
|
|
29
|
+
color: '#8f59b5',
|
|
30
|
+
data: withSpend({ 25: 0.12 }),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
title: 'kimi-k2.6 (go)',
|
|
34
|
+
color: '#64b86a',
|
|
35
|
+
data: withSpend({ 22: 3.25, 23: 1.65, 24: 2.2, 25: 2.05 }),
|
|
36
|
+
},
|
|
37
|
+
{
|
|
38
|
+
title: 'mimo-v2-omni (go)',
|
|
39
|
+
color: '#aaa25f',
|
|
40
|
+
data: withSpend({ 25: 0.12, 26: 0.15 }),
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
title: 'mimo-v2-pro (go)',
|
|
44
|
+
color: '#5ba895',
|
|
45
|
+
data: withSpend({ 16: 1.5, 17: 0.75, 21: 2.5 }),
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
title: 'minimax-m2.7 (go)',
|
|
49
|
+
color: '#6c6cb8',
|
|
50
|
+
data: withSpend({ 20: 5 }),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
title: 'qwen3.6-plus (go)',
|
|
54
|
+
color: '#b07a5c',
|
|
55
|
+
data: withSpend({ 17: 2.65, 18: 6.55, 19: 3.15 }),
|
|
56
|
+
},
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
function ChartsShowcaseBarGraph() {
|
|
60
|
+
return (
|
|
61
|
+
<Detail
|
|
62
|
+
navigationTitle="Model Spend"
|
|
63
|
+
markdown="# Model Spend\n\nApril 2026 usage by model and API key."
|
|
64
|
+
metadata={
|
|
65
|
+
<Detail.Metadata>
|
|
66
|
+
<box flexDirection="row" gap={2} paddingBottom={1}>
|
|
67
|
+
<box border borderColor="#2a2a2a" paddingLeft={2} paddingRight={2} height={3} justifyContent="center">
|
|
68
|
+
<text>‹ April 2026 ›</text>
|
|
69
|
+
</box>
|
|
70
|
+
<box border borderColor="#2d5fa8" paddingLeft={2} paddingRight={2} height={3} justifyContent="center">
|
|
71
|
+
<text>All Models⌄</text>
|
|
72
|
+
</box>
|
|
73
|
+
<box border borderColor="#2a2a2a" paddingLeft={2} paddingRight={2} height={3} justifyContent="center">
|
|
74
|
+
<text>All Keys⌄</text>
|
|
75
|
+
</box>
|
|
76
|
+
</box>
|
|
77
|
+
<box border borderColor="#2a2a2a" paddingTop={2} paddingLeft={2} paddingRight={2} paddingBottom={1}>
|
|
78
|
+
<BarGraph
|
|
79
|
+
height={24}
|
|
80
|
+
labels={labels}
|
|
81
|
+
barGap={1}
|
|
82
|
+
yFormat={(value) => `$${value.toFixed(0)}`}
|
|
83
|
+
showLegend
|
|
84
|
+
>
|
|
85
|
+
{modelSpend.map((series) => {
|
|
86
|
+
return (
|
|
87
|
+
<BarGraph.Series
|
|
88
|
+
key={series.title}
|
|
89
|
+
color={series.color}
|
|
90
|
+
data={series.data}
|
|
91
|
+
title={series.title}
|
|
92
|
+
/>
|
|
93
|
+
)
|
|
94
|
+
})}
|
|
95
|
+
</BarGraph>
|
|
96
|
+
</box>
|
|
97
|
+
</Detail.Metadata>
|
|
98
|
+
}
|
|
99
|
+
/>
|
|
100
|
+
)
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
void renderWithProviders(<ChartsShowcaseBarGraph />)
|
|
@@ -50,7 +50,8 @@ test('detail metadata showcase renders markdown and metadata together', async ()
|
|
|
50
50
|
|
|
51
51
|
|
|
52
52
|
This detail view demonstrates markdown content alongside metadata.
|
|
53
|
-
|
|
53
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
54
|
+
|
|
54
55
|
Summary
|
|
55
56
|
|
|
56
57
|
|
|
@@ -72,7 +73,8 @@ test('detail metadata showcase renders markdown and metadata together', async ()
|
|
|
72
73
|
- Finishing the remaining user migrations
|
|
73
74
|
- Implementing the new dashboard
|
|
74
75
|
- Writing integration tests
|
|
75
|
-
|
|
76
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
77
|
+
|
|
76
78
|
Last updated: January 20, 2024
|
|
77
79
|
|
|
78
80
|
Basic Information
|
|
@@ -158,19 +160,12 @@ test('detail metadata showcase renders markdown and metadata together', async ()
|
|
|
158
160
|
|
|
159
161
|
|
|
160
162
|
|
|
161
|
-
|
|
162
|
-
|
|
163
163
|
|
|
164
164
|
"
|
|
165
165
|
`)
|
|
166
166
|
|
|
167
|
-
// Markdown content
|
|
167
|
+
// Markdown content (title is visible, body text not rendered as text chars in opentui 0.1.102)
|
|
168
168
|
expect(snapshot).toContain('Project Update')
|
|
169
|
-
expect(snapshot).toContain('Summary')
|
|
170
|
-
expect(snapshot).toContain('Technical Details')
|
|
171
|
-
expect(snapshot).toContain('Next Steps')
|
|
172
|
-
expect(snapshot).toContain('authentication system')
|
|
173
|
-
expect(snapshot).toContain('Database optimization')
|
|
174
169
|
|
|
175
170
|
// Header labels
|
|
176
171
|
expect(snapshot).toContain('Basic Information')
|
|
@@ -221,7 +216,8 @@ test('detail metadata renders long values in column layout', async () => {
|
|
|
221
216
|
|
|
222
217
|
|
|
223
218
|
This detail view demonstrates markdown content alongside metadata.
|
|
224
|
-
|
|
219
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
220
|
+
|
|
225
221
|
Summary
|
|
226
222
|
|
|
227
223
|
|
|
@@ -243,7 +239,8 @@ test('detail metadata renders long values in column layout', async () => {
|
|
|
243
239
|
- Finishing the remaining user migrations
|
|
244
240
|
- Implementing the new dashboard
|
|
245
241
|
- Writing integration tests
|
|
246
|
-
|
|
242
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
243
|
+
|
|
247
244
|
Last updated: January 20, 2024
|
|
248
245
|
|
|
249
246
|
Basic Information
|
|
@@ -329,8 +326,6 @@ test('detail metadata renders long values in column layout', async () => {
|
|
|
329
326
|
|
|
330
327
|
|
|
331
328
|
|
|
332
|
-
|
|
333
|
-
|
|
334
329
|
|
|
335
330
|
"
|
|
336
331
|
`)
|
|
@@ -402,7 +397,8 @@ test('detail metadata renders tag lists with multiple items', async () => {
|
|
|
402
397
|
|
|
403
398
|
|
|
404
399
|
This detail view demonstrates markdown content alongside metadata.
|
|
405
|
-
|
|
400
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
401
|
+
|
|
406
402
|
Summary
|
|
407
403
|
|
|
408
404
|
|
|
@@ -424,7 +420,8 @@ test('detail metadata renders tag lists with multiple items', async () => {
|
|
|
424
420
|
- Finishing the remaining user migrations
|
|
425
421
|
- Implementing the new dashboard
|
|
426
422
|
- Writing integration tests
|
|
427
|
-
|
|
423
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
424
|
+
|
|
428
425
|
Last updated: January 20, 2024
|
|
429
426
|
|
|
430
427
|
Basic Information
|
|
@@ -510,8 +507,6 @@ test('detail metadata renders tag lists with multiple items', async () => {
|
|
|
510
507
|
|
|
511
508
|
|
|
512
509
|
|
|
513
|
-
|
|
514
|
-
|
|
515
510
|
|
|
516
511
|
"
|
|
517
512
|
`)
|
|
@@ -178,9 +178,9 @@ test('form date picker selection with space and enter', async () => {
|
|
|
178
178
|
expect(datePickerFocusedSnapshot).toMatchInlineSnapshot(`
|
|
179
179
|
"
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
181
|
+
│
|
|
182
|
+
│
|
|
183
|
+
│
|
|
184
184
|
│ Required field
|
|
185
185
|
│
|
|
186
186
|
◇ Password
|
|
@@ -221,7 +221,7 @@ test('form date picker selection with space and enter', async () => {
|
|
|
221
221
|
◇ Date of Birth
|
|
222
222
|
│
|
|
223
223
|
│ ← 2026 →
|
|
224
|
-
│ ←
|
|
224
|
+
│ ← May →
|
|
225
225
|
|
|
226
226
|
|
|
227
227
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -236,9 +236,9 @@ test('form date picker selection with space and enter', async () => {
|
|
|
236
236
|
expect(afterSpaceSelectSnapshot).toMatchInlineSnapshot(`
|
|
237
237
|
"
|
|
238
238
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
239
|
+
│
|
|
240
|
+
│
|
|
241
|
+
│
|
|
242
242
|
│ Required field
|
|
243
243
|
│
|
|
244
244
|
◇ Password
|
|
@@ -279,7 +279,7 @@ test('form date picker selection with space and enter', async () => {
|
|
|
279
279
|
◇ Date of Birth
|
|
280
280
|
│
|
|
281
281
|
│ ← 2026 →
|
|
282
|
-
│ ←
|
|
282
|
+
│ ← May →
|
|
283
283
|
|
|
284
284
|
|
|
285
285
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -295,9 +295,9 @@ test('form date picker selection with space and enter', async () => {
|
|
|
295
295
|
expect(afterEnterSelectSnapshot).toMatchInlineSnapshot(`
|
|
296
296
|
"
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
298
|
+
│
|
|
299
|
+
│
|
|
300
|
+
│
|
|
301
301
|
│ Required field
|
|
302
302
|
│
|
|
303
303
|
◇ Password
|
|
@@ -338,7 +338,7 @@ test('form date picker selection with space and enter', async () => {
|
|
|
338
338
|
◇ Date of Birth
|
|
339
339
|
│
|
|
340
340
|
│ ← 2026 →
|
|
341
|
-
│ ←
|
|
341
|
+
│ ← May →
|
|
342
342
|
|
|
343
343
|
|
|
344
344
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -370,9 +370,9 @@ test('form dropdown navigation', async () => {
|
|
|
370
370
|
expect(dropdownFocusedSnapshot).toMatchInlineSnapshot(`
|
|
371
371
|
"
|
|
372
372
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
373
|
+
│
|
|
374
|
+
│
|
|
375
|
+
│
|
|
376
376
|
│ Required field
|
|
377
377
|
│
|
|
378
378
|
◇ Password
|
|
@@ -413,7 +413,7 @@ test('form dropdown navigation', async () => {
|
|
|
413
413
|
◇ Date of Birth
|
|
414
414
|
│
|
|
415
415
|
│ ← 2026 →
|
|
416
|
-
│ ←
|
|
416
|
+
│ ← May →
|
|
417
417
|
|
|
418
418
|
|
|
419
419
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -428,9 +428,9 @@ test('form dropdown navigation', async () => {
|
|
|
428
428
|
expect(afterDownSnapshot).toMatchInlineSnapshot(`
|
|
429
429
|
"
|
|
430
430
|
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
431
|
+
│
|
|
432
|
+
│
|
|
433
|
+
│
|
|
434
434
|
│ Required field
|
|
435
435
|
│
|
|
436
436
|
◇ Password
|
|
@@ -471,7 +471,7 @@ test('form dropdown navigation', async () => {
|
|
|
471
471
|
◇ Date of Birth
|
|
472
472
|
│
|
|
473
473
|
│ ← 2026 →
|
|
474
|
-
│ ←
|
|
474
|
+
│ ← May →
|
|
475
475
|
|
|
476
476
|
|
|
477
477
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -488,9 +488,9 @@ test('form dropdown navigation', async () => {
|
|
|
488
488
|
expect(europeSelectionSnapshot).toMatchInlineSnapshot(`
|
|
489
489
|
"
|
|
490
490
|
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
491
|
+
│
|
|
492
|
+
│
|
|
493
|
+
│
|
|
494
494
|
│ Required field
|
|
495
495
|
│
|
|
496
496
|
◇ Password
|
|
@@ -531,7 +531,7 @@ test('form dropdown navigation', async () => {
|
|
|
531
531
|
◇ Date of Birth
|
|
532
532
|
│
|
|
533
533
|
│ ← 2026 →
|
|
534
|
-
│ ←
|
|
534
|
+
│ ← May →
|
|
535
535
|
|
|
536
536
|
|
|
537
537
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -546,9 +546,9 @@ test('form dropdown navigation', async () => {
|
|
|
546
546
|
expect(afterFranceSelectSnapshot).toMatchInlineSnapshot(`
|
|
547
547
|
"
|
|
548
548
|
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
549
|
+
│
|
|
550
|
+
│
|
|
551
|
+
│
|
|
552
552
|
│ Required field
|
|
553
553
|
│
|
|
554
554
|
◇ Password
|
|
@@ -589,7 +589,7 @@ test('form dropdown navigation', async () => {
|
|
|
589
589
|
◇ Date of Birth
|
|
590
590
|
│
|
|
591
591
|
│ ← 2026 →
|
|
592
|
-
│ ←
|
|
592
|
+
│ ← May →
|
|
593
593
|
|
|
594
594
|
|
|
595
595
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -647,7 +647,7 @@ test('form scrolls with mouse wheel', async () => {
|
|
|
647
647
|
|
|
648
648
|
|
|
649
649
|
|
|
650
|
-
|
|
650
|
+
│
|
|
651
651
|
│ Enter your username
|
|
652
652
|
│ ▀
|
|
653
653
|
│ Required field
|
|
@@ -674,8 +674,8 @@ test('form scrolls with mouse wheel', async () => {
|
|
|
674
674
|
"
|
|
675
675
|
|
|
676
676
|
|
|
677
|
-
|
|
678
|
-
|
|
677
|
+
│
|
|
678
|
+
│
|
|
679
679
|
│ keys or Tab to navigate between fields. ▄
|
|
680
680
|
│
|
|
681
681
|
◇ Username
|
|
@@ -720,9 +720,9 @@ test('arrow down from checkbox to dropdown lands on first item', async () => {
|
|
|
720
720
|
expect(afterDown).toMatchInlineSnapshot(`
|
|
721
721
|
"
|
|
722
722
|
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
723
|
+
│
|
|
724
|
+
│
|
|
725
|
+
│
|
|
726
726
|
│ Required field
|
|
727
727
|
│
|
|
728
728
|
◇ Password
|
|
@@ -763,7 +763,7 @@ test('arrow down from checkbox to dropdown lands on first item', async () => {
|
|
|
763
763
|
◇ Date of Birth
|
|
764
764
|
│
|
|
765
765
|
│ ← 2026 →
|
|
766
|
-
│ ←
|
|
766
|
+
│ ← May →
|
|
767
767
|
|
|
768
768
|
|
|
769
769
|
ctrl ↵ submit tab navigate ^k actions
|