termcast 1.4.1 → 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/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 +6 -8
- 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 +12 -12
- package/src/examples/form-basic.vitest.tsx +11 -11
- 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-heatmap.vitest.tsx +9 -9
- 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/extensions/dev.vitest.tsx +8 -8
- package/src/index.tsx +21 -0
- 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,8 +160,6 @@ test('detail metadata showcase renders markdown and metadata together', async ()
|
|
|
158
160
|
|
|
159
161
|
|
|
160
162
|
|
|
161
|
-
|
|
162
|
-
|
|
163
163
|
|
|
164
164
|
"
|
|
165
165
|
`)
|
|
@@ -216,7 +216,8 @@ test('detail metadata renders long values in column layout', async () => {
|
|
|
216
216
|
|
|
217
217
|
|
|
218
218
|
This detail view demonstrates markdown content alongside metadata.
|
|
219
|
-
|
|
219
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
220
|
+
|
|
220
221
|
Summary
|
|
221
222
|
|
|
222
223
|
|
|
@@ -238,7 +239,8 @@ test('detail metadata renders long values in column layout', async () => {
|
|
|
238
239
|
- Finishing the remaining user migrations
|
|
239
240
|
- Implementing the new dashboard
|
|
240
241
|
- Writing integration tests
|
|
241
|
-
|
|
242
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
243
|
+
|
|
242
244
|
Last updated: January 20, 2024
|
|
243
245
|
|
|
244
246
|
Basic Information
|
|
@@ -324,8 +326,6 @@ test('detail metadata renders long values in column layout', async () => {
|
|
|
324
326
|
|
|
325
327
|
|
|
326
328
|
|
|
327
|
-
|
|
328
|
-
|
|
329
329
|
|
|
330
330
|
"
|
|
331
331
|
`)
|
|
@@ -397,7 +397,8 @@ test('detail metadata renders tag lists with multiple items', async () => {
|
|
|
397
397
|
|
|
398
398
|
|
|
399
399
|
This detail view demonstrates markdown content alongside metadata.
|
|
400
|
-
|
|
400
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
401
|
+
|
|
401
402
|
Summary
|
|
402
403
|
|
|
403
404
|
|
|
@@ -419,7 +420,8 @@ test('detail metadata renders tag lists with multiple items', async () => {
|
|
|
419
420
|
- Finishing the remaining user migrations
|
|
420
421
|
- Implementing the new dashboard
|
|
421
422
|
- Writing integration tests
|
|
422
|
-
|
|
423
|
+
─────────────────────────────────────────────────────────────────────────────────────────────
|
|
424
|
+
|
|
423
425
|
Last updated: January 20, 2024
|
|
424
426
|
|
|
425
427
|
Basic Information
|
|
@@ -505,8 +507,6 @@ test('detail metadata renders tag lists with multiple items', async () => {
|
|
|
505
507
|
|
|
506
508
|
|
|
507
509
|
|
|
508
|
-
|
|
509
|
-
|
|
510
510
|
|
|
511
511
|
"
|
|
512
512
|
`)
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
|
@@ -674,10 +674,9 @@ test('form scrolls with mouse wheel', async () => {
|
|
|
674
674
|
"
|
|
675
675
|
|
|
676
676
|
|
|
677
|
-
|
|
678
677
|
│
|
|
679
|
-
│
|
|
680
|
-
│ keys or Tab to navigate between fields.
|
|
678
|
+
│
|
|
679
|
+
│ keys or Tab to navigate between fields. ▄
|
|
681
680
|
│
|
|
682
681
|
◇ Username
|
|
683
682
|
│ Enter your username
|
|
@@ -687,6 +686,7 @@ test('form scrolls with mouse wheel', async () => {
|
|
|
687
686
|
◇ Password
|
|
688
687
|
│ Enter secure password
|
|
689
688
|
│
|
|
689
|
+
│ Must be at least 8 characters
|
|
690
690
|
|
|
691
691
|
|
|
692
692
|
ctrl ↵ submit tab navigate ^k actions
|
|
@@ -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
|
|
@@ -102,7 +102,7 @@ test('form dropdown shows inline options', async () => {
|
|
|
102
102
|
|
|
103
103
|
|
|
104
104
|
|
|
105
|
-
|
|
105
|
+
▪︎ Dropdown Component Demo █
|
|
106
106
|
│ Test dropdown with sections, multiple selection, and more █
|
|
107
107
|
│ features █
|
|
108
108
|
│ █
|
|
@@ -162,7 +162,7 @@ test('form dropdown shows inline options', async () => {
|
|
|
162
162
|
|
|
163
163
|
|
|
164
164
|
|
|
165
|
-
|
|
165
|
+
▪︎ Dropdown Component Demo █
|
|
166
166
|
│ Test dropdown with sections, multiple selection, and more █
|
|
167
167
|
│ features █
|
|
168
168
|
│ █
|
|
@@ -219,7 +219,7 @@ test('form dropdown shows inline options', async () => {
|
|
|
219
219
|
|
|
220
220
|
|
|
221
221
|
|
|
222
|
-
|
|
222
|
+
▪︎ Dropdown Component Demo █
|
|
223
223
|
│ Test dropdown with sections, multiple selection, and more █
|
|
224
224
|
│ features █
|
|
225
225
|
│ █
|
|
@@ -344,7 +344,7 @@ test('form dropdown keyboard navigation', async () => {
|
|
|
344
344
|
|
|
345
345
|
|
|
346
346
|
|
|
347
|
-
|
|
347
|
+
▪︎ Dropdown Component Demo █
|
|
348
348
|
│ Test dropdown with sections, multiple selection, and more █
|
|
349
349
|
│ features █
|
|
350
350
|
│ █
|
|
@@ -401,7 +401,7 @@ test('form dropdown keyboard navigation', async () => {
|
|
|
401
401
|
|
|
402
402
|
|
|
403
403
|
|
|
404
|
-
|
|
404
|
+
▪︎ Dropdown Component Demo █
|
|
405
405
|
│ Test dropdown with sections, multiple selection, and more █
|
|
406
406
|
│ features █
|
|
407
407
|
│ █
|
|
@@ -458,7 +458,7 @@ test('form dropdown keyboard navigation', async () => {
|
|
|
458
458
|
|
|
459
459
|
|
|
460
460
|
|
|
461
|
-
|
|
461
|
+
▪︎ Dropdown Component Demo █
|
|
462
462
|
│ Test dropdown with sections, multiple selection, and more █
|
|
463
463
|
│ features █
|
|
464
464
|
│ █
|
|
@@ -515,7 +515,7 @@ test('form dropdown keyboard navigation', async () => {
|
|
|
515
515
|
|
|
516
516
|
|
|
517
517
|
|
|
518
|
-
|
|
518
|
+
▪︎ Dropdown Component Demo █
|
|
519
519
|
│ Test dropdown with sections, multiple selection, and more █
|
|
520
520
|
│ features █
|
|
521
521
|
│ █
|
|
@@ -580,7 +580,7 @@ test('form dropdown with default value', async () => {
|
|
|
580
580
|
|
|
581
581
|
|
|
582
582
|
|
|
583
|
-
|
|
583
|
+
▪︎ Dropdown Component Demo █
|
|
584
584
|
│ Test dropdown with sections, multiple selection, and more █
|
|
585
585
|
│ features █
|
|
586
586
|
│ █
|
|
@@ -637,7 +637,7 @@ test('form dropdown with default value', async () => {
|
|
|
637
637
|
|
|
638
638
|
|
|
639
639
|
|
|
640
|
-
|
|
640
|
+
▪︎ Dropdown Component Demo █
|
|
641
641
|
│ Test dropdown with sections, multiple selection, and more █
|
|
642
642
|
│ features █
|
|
643
643
|
│ █
|
|
@@ -708,7 +708,7 @@ test('selecting second-to-last visible item should not scroll', async () => {
|
|
|
708
708
|
|
|
709
709
|
|
|
710
710
|
|
|
711
|
-
|
|
711
|
+
▪︎ Dropdown Component Demo █
|
|
712
712
|
│ Test dropdown with sections, multiple selection, and more █
|
|
713
713
|
│ features █
|
|
714
714
|
│ █
|
|
@@ -765,7 +765,7 @@ test('selecting second-to-last visible item should not scroll', async () => {
|
|
|
765
765
|
|
|
766
766
|
|
|
767
767
|
|
|
768
|
-
|
|
768
|
+
▪︎ Dropdown Component Demo █
|
|
769
769
|
│ Test dropdown with sections, multiple selection, and more █
|
|
770
770
|
│ features █
|
|
771
771
|
│ █
|