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.
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +12 -0
- package/dist/build.js.map +1 -1
- package/dist/cli.js +5 -40
- package/dist/cli.js.map +1 -1
- package/dist/colors.d.ts +7 -7
- package/dist/colors.js +7 -7
- package/dist/compile.d.ts +6 -1
- package/dist/compile.d.ts.map +1 -1
- package/dist/compile.js +45 -26
- package/dist/compile.js.map +1 -1
- package/dist/components/actions.js +1 -1
- package/dist/components/actions.js.map +1 -1
- package/dist/components/bar-chart.d.ts +38 -0
- package/dist/components/bar-chart.d.ts.map +1 -0
- package/dist/components/bar-chart.js +158 -0
- package/dist/components/bar-chart.js.map +1 -0
- package/dist/components/bar-graph.d.ts +41 -0
- package/dist/components/bar-graph.d.ts.map +1 -0
- package/dist/components/bar-graph.js +95 -0
- package/dist/components/bar-graph.js.map +1 -0
- package/dist/components/detail.d.ts.map +1 -1
- package/dist/components/detail.js +5 -7
- package/dist/components/detail.js.map +1 -1
- package/dist/components/footer.d.ts.map +1 -1
- package/dist/components/footer.js +8 -9
- package/dist/components/footer.js.map +1 -1
- package/dist/components/form/date-picker.d.ts.map +1 -1
- package/dist/components/form/date-picker.js +7 -1
- package/dist/components/form/date-picker.js.map +1 -1
- package/dist/components/form/dropdown.d.ts.map +1 -1
- package/dist/components/form/dropdown.js +10 -2
- package/dist/components/form/dropdown.js.map +1 -1
- package/dist/components/form/index.d.ts.map +1 -1
- package/dist/components/form/index.js +4 -5
- package/dist/components/form/index.js.map +1 -1
- package/dist/components/form/use-form-navigation.d.ts.map +1 -1
- package/dist/components/form/use-form-navigation.js +6 -0
- package/dist/components/form/use-form-navigation.js.map +1 -1
- package/dist/components/graph.d.ts +111 -0
- package/dist/components/graph.d.ts.map +1 -0
- package/dist/components/graph.js +392 -0
- package/dist/components/graph.js.map +1 -0
- package/dist/components/icon.js +5 -5
- package/dist/components/icon.js.map +1 -1
- package/dist/components/list.d.ts +53 -5
- package/dist/components/list.d.ts.map +1 -1
- package/dist/components/list.js +125 -71
- package/dist/components/list.js.map +1 -1
- package/dist/components/loading-bar.js +3 -3
- package/dist/components/loading-bar.js.map +1 -1
- package/dist/components/loading-text.d.ts +1 -1
- package/dist/components/loading-text.d.ts.map +1 -1
- package/dist/components/loading-text.js +3 -1
- package/dist/components/loading-text.js.map +1 -1
- package/dist/components/metadata.js +2 -2
- package/dist/components/metadata.js.map +1 -1
- package/dist/components/row.d.ts +10 -0
- package/dist/components/row.d.ts.map +1 -0
- package/dist/components/row.js +12 -0
- package/dist/components/row.js.map +1 -0
- package/dist/components/table.d.ts +57 -0
- package/dist/components/table.d.ts.map +1 -0
- package/dist/components/table.js +365 -0
- package/dist/components/table.js.map +1 -0
- package/dist/descendants.js +13 -13
- package/dist/descendants.js.map +1 -1
- package/dist/examples/bar-graph-weekly.d.ts +2 -0
- package/dist/examples/bar-graph-weekly.d.ts.map +1 -0
- package/dist/examples/bar-graph-weekly.js +95 -0
- package/dist/examples/bar-graph-weekly.js.map +1 -0
- package/dist/examples/components-weird-places.d.ts +2 -0
- package/dist/examples/components-weird-places.d.ts.map +1 -0
- package/dist/examples/components-weird-places.js +46 -0
- package/dist/examples/components-weird-places.js.map +1 -0
- package/dist/examples/graph-bar-chart.d.ts +2 -0
- package/dist/examples/graph-bar-chart.d.ts.map +1 -0
- package/dist/examples/graph-bar-chart.js +270 -0
- package/dist/examples/graph-bar-chart.js.map +1 -0
- package/dist/examples/graph-multi-series.d.ts +2 -0
- package/dist/examples/graph-multi-series.d.ts.map +1 -0
- package/dist/examples/graph-multi-series.js +23 -0
- package/dist/examples/graph-multi-series.js.map +1 -0
- package/dist/examples/graph-polymarket.d.ts +2 -0
- package/dist/examples/graph-polymarket.d.ts.map +1 -0
- package/dist/examples/graph-polymarket.js +109 -0
- package/dist/examples/graph-polymarket.js.map +1 -0
- package/dist/examples/graph-row.d.ts +2 -0
- package/dist/examples/graph-row.d.ts.map +1 -0
- package/dist/examples/graph-row.js +226 -0
- package/dist/examples/graph-row.js.map +1 -0
- package/dist/examples/graph-styles.d.ts +2 -0
- package/dist/examples/graph-styles.d.ts.map +1 -0
- package/dist/examples/graph-styles.js +316 -0
- package/dist/examples/graph-styles.js.map +1 -0
- package/dist/examples/list-accessory-table.d.ts +2 -0
- package/dist/examples/list-accessory-table.d.ts.map +1 -0
- package/dist/examples/list-accessory-table.js +46 -0
- package/dist/examples/list-accessory-table.js.map +1 -0
- package/dist/examples/list-item-accessories.d.ts +2 -0
- package/dist/examples/list-item-accessories.d.ts.map +1 -0
- package/dist/examples/list-item-accessories.js +27 -0
- package/dist/examples/list-item-accessories.js.map +1 -0
- package/dist/examples/list-no-actions.d.ts +2 -0
- package/dist/examples/list-no-actions.d.ts.map +1 -0
- package/dist/examples/list-no-actions.js +7 -0
- package/dist/examples/list-no-actions.js.map +1 -0
- package/dist/examples/simple-detail-table.d.ts +2 -0
- package/dist/examples/simple-detail-table.d.ts.map +1 -0
- package/dist/examples/simple-detail-table.js +45 -0
- package/dist/examples/simple-detail-table.js.map +1 -0
- package/dist/examples/simple-graph.d.ts +2 -0
- package/dist/examples/simple-graph.d.ts.map +1 -0
- package/dist/examples/simple-graph.js +32 -0
- package/dist/examples/simple-graph.js.map +1 -0
- package/dist/examples/simple-table-wrap.d.ts +2 -0
- package/dist/examples/simple-table-wrap.d.ts.map +1 -0
- package/dist/examples/simple-table-wrap.js +37 -0
- package/dist/examples/simple-table-wrap.js.map +1 -0
- package/dist/examples/table-edge-cases.d.ts +2 -0
- package/dist/examples/table-edge-cases.d.ts.map +1 -0
- package/dist/examples/table-edge-cases.js +70 -0
- package/dist/examples/table-edge-cases.js.map +1 -0
- package/dist/examples/table-flex-grow.d.ts +2 -0
- package/dist/examples/table-flex-grow.d.ts.map +1 -0
- package/dist/examples/table-flex-grow.js +18 -0
- package/dist/examples/table-flex-grow.js.map +1 -0
- package/dist/extensions/dev.d.ts.map +1 -1
- package/dist/extensions/dev.js +5 -1
- package/dist/extensions/dev.js.map +1 -1
- package/dist/globals.d.ts +1 -0
- package/dist/globals.d.ts.map +1 -1
- package/dist/globals.js +2 -0
- package/dist/globals.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/date-picker-widget.d.ts.map +1 -1
- package/dist/internal/date-picker-widget.js +4 -0
- package/dist/internal/date-picker-widget.js.map +1 -1
- package/dist/internal/providers.d.ts.map +1 -1
- package/dist/internal/providers.js +1 -3
- package/dist/internal/providers.js.map +1 -1
- package/dist/markdown-utils.d.ts +22 -1
- package/dist/markdown-utils.d.ts.map +1 -1
- package/dist/markdown-utils.js +66 -1
- package/dist/markdown-utils.js.map +1 -1
- package/dist/opentui.d.ts +4 -0
- package/dist/opentui.d.ts.map +1 -0
- package/dist/opentui.js +3 -0
- package/dist/opentui.js.map +1 -0
- package/dist/release.d.ts +2 -1
- package/dist/release.d.ts.map +1 -1
- package/dist/release.js +2 -1
- package/dist/release.js.map +1 -1
- package/dist/state.d.ts +1 -0
- package/dist/state.d.ts.map +1 -1
- package/dist/state.js +1 -1
- package/dist/state.js.map +1 -1
- package/dist/theme.d.ts +1 -0
- package/dist/theme.d.ts.map +1 -1
- package/dist/theme.js +13 -0
- package/dist/theme.js.map +1 -1
- package/dist/themes/nerv.json +227 -0
- package/dist/themes/termcast.json +72 -71
- package/dist/themes.d.ts +2 -1
- package/dist/themes.d.ts.map +1 -1
- package/dist/themes.js +7 -5
- package/dist/themes.js.map +1 -1
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +3 -0
- package/dist/utils.js.map +1 -1
- package/package.json +13 -5
- package/src/build.tsx +13 -0
- package/src/cli.tsx +5 -49
- package/src/colors.tsx +7 -7
- package/src/compile.tsx +52 -29
- package/src/components/actions.tsx +1 -1
- package/src/components/bar-chart.tsx +271 -0
- package/src/components/bar-graph.tsx +214 -0
- package/src/components/detail.tsx +7 -8
- package/src/components/footer.tsx +14 -15
- package/src/components/form/date-picker.tsx +9 -0
- package/src/components/form/dropdown.tsx +13 -3
- package/src/components/form/index.tsx +4 -6
- package/src/components/form/use-form-navigation.tsx +6 -0
- package/src/components/graph.tsx +506 -0
- package/src/components/icon.tsx +5 -5
- package/src/components/list.tsx +210 -102
- package/src/components/loading-bar.tsx +3 -3
- package/src/components/loading-text.tsx +4 -2
- package/src/components/metadata.tsx +2 -2
- package/src/components/row.tsx +31 -0
- package/src/components/table.tsx +511 -0
- package/src/descendants.tsx +13 -13
- package/src/examples/action-shortcut.vitest.tsx +1 -1
- package/src/examples/actions-context.vitest.tsx +1 -1
- package/src/examples/bar-graph-weekly.tsx +264 -0
- package/src/examples/bar-graph-weekly.vitest.tsx +275 -0
- package/src/examples/detail-metadata-showcase.vitest.tsx +8 -8
- package/src/examples/form-basic.vitest.tsx +239 -0
- package/src/examples/form-dropdown.vitest.tsx +29 -29
- package/src/examples/form-tagpicker.vitest.tsx +27 -27
- package/src/examples/github.vitest.tsx +4 -4
- package/src/examples/graph-bar-chart.tsx +408 -0
- package/src/examples/graph-bar-chart.vitest.tsx +283 -0
- package/src/examples/graph-multi-series.tsx +36 -0
- package/src/examples/graph-multi-series.vitest.tsx +89 -0
- package/src/examples/graph-polymarket.tsx +182 -0
- package/src/examples/graph-polymarket.vitest.tsx +130 -0
- package/src/examples/graph-row.tsx +347 -0
- package/src/examples/graph-row.vitest.tsx +295 -0
- package/src/examples/graph-styles.tsx +457 -0
- package/src/examples/graph-styles.vitest.tsx +322 -0
- package/src/examples/list-accessory-table.tsx +77 -0
- package/src/examples/list-detail-metadata.vitest.tsx +21 -21
- package/src/examples/list-dropdown-default.vitest.tsx +12 -12
- package/src/examples/list-item-accessories.tsx +106 -0
- package/src/examples/list-item-accessories.vitest.tsx +115 -0
- package/src/examples/list-no-actions.tsx +18 -0
- package/src/examples/list-no-actions.vitest.tsx +97 -0
- package/src/examples/list-spacing-mode.vitest.tsx +6 -6
- package/src/examples/list-with-detail.vitest.tsx +92 -92
- package/src/examples/list-with-dropdown.vitest.tsx +49 -6
- package/src/examples/list-with-sections.vitest.tsx +61 -56
- package/src/examples/simple-detail-markdown.vitest.tsx +21 -17
- package/src/examples/simple-detail-table.tsx +65 -0
- package/src/examples/simple-detail-table.vitest.tsx +200 -0
- package/src/examples/simple-graph.tsx +51 -0
- package/src/examples/simple-graph.vitest.tsx +124 -0
- package/src/examples/simple-grid.vitest.tsx +3 -3
- package/src/examples/simple-list-search.vitest.tsx +65 -0
- package/src/examples/simple-navigation.vitest.tsx +3 -3
- package/src/examples/simple-table-wrap.tsx +55 -0
- package/src/examples/simple-table-wrap.vitest.tsx +91 -0
- package/src/examples/store.vitest.tsx +1 -1
- package/src/examples/table-edge-cases.tsx +72 -0
- package/src/examples/table-edge-cases.vitest.tsx +307 -0
- package/src/examples/table-flex-grow.tsx +53 -0
- package/src/examples/table-flex-grow.vitest.tsx +124 -0
- package/src/extensions/dev.tsx +7 -1
- package/src/globals.ts +3 -0
- package/src/index.tsx +31 -0
- package/src/internal/date-picker-widget.tsx +4 -0
- package/src/internal/providers.tsx +1 -4
- package/src/markdown-utils.tsx +82 -1
- package/src/opentui.tsx +5 -0
- package/src/release.tsx +3 -0
- package/src/state.tsx +2 -1
- package/src/theme.tsx +14 -0
- package/src/themes/nerv.json +231 -0
- package/src/themes/termcast.json +75 -71
- package/src/themes.ts +8 -5
- package/src/utils.tsx +4 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
// Example: Two graphs side by side using the Row component.
|
|
2
|
+
// Shows horizontal graph layouts in both List side-detail and
|
|
3
|
+
// full Detail view (pushed on Enter).
|
|
4
|
+
|
|
5
|
+
import React from 'react'
|
|
6
|
+
import { List, Detail, Graph, Color, Action, ActionPanel, Row } from 'termcast'
|
|
7
|
+
import { useNavigation } from 'termcast/src/internal/navigation'
|
|
8
|
+
import { renderWithProviders } from '../utils'
|
|
9
|
+
|
|
10
|
+
// ── Data ─────────────────────────────────────────────────────────────
|
|
11
|
+
|
|
12
|
+
const cpuData = [
|
|
13
|
+
25, 30, 45, 60, 55, 72, 80, 65, 50, 40,
|
|
14
|
+
35, 55, 70, 85, 90, 75, 60, 45, 38, 30,
|
|
15
|
+
]
|
|
16
|
+
const memData = [
|
|
17
|
+
40, 42, 44, 48, 52, 55, 58, 60, 62, 65,
|
|
18
|
+
68, 70, 72, 74, 76, 78, 80, 82, 84, 86,
|
|
19
|
+
]
|
|
20
|
+
const readOps = [
|
|
21
|
+
120, 85, 150, 200, 180, 95, 110, 250, 300, 275,
|
|
22
|
+
190, 160, 140, 220, 280, 310, 200, 170, 130, 100,
|
|
23
|
+
]
|
|
24
|
+
const writeOps = [
|
|
25
|
+
40, 55, 30, 80, 70, 45, 60, 90, 120, 100,
|
|
26
|
+
65, 50, 70, 85, 110, 130, 75, 60, 45, 35,
|
|
27
|
+
]
|
|
28
|
+
const revenue = [
|
|
29
|
+
10, 15, 12, 18, 25, 22, 30, 35, 28, 40,
|
|
30
|
+
45, 42, 50, 55, 60, 58, 65, 70, 68, 75,
|
|
31
|
+
]
|
|
32
|
+
const expenses = [
|
|
33
|
+
8, 10, 11, 14, 16, 18, 20, 22, 21, 25,
|
|
34
|
+
28, 30, 32, 34, 36, 38, 40, 42, 41, 45,
|
|
35
|
+
]
|
|
36
|
+
const temperature = [
|
|
37
|
+
15, 14, 16, 18, 22, 25, 28, 30, 29, 27,
|
|
38
|
+
24, 20, 17, 15, 14, 16, 19, 23, 26, 28,
|
|
39
|
+
]
|
|
40
|
+
const humidity = [
|
|
41
|
+
80, 82, 78, 72, 65, 58, 52, 48, 50, 55,
|
|
42
|
+
62, 70, 75, 80, 83, 78, 72, 60, 54, 52,
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
const sparseData = [
|
|
46
|
+
0, 0, 15, 30, 0, 0, 50, 80, 0, 0,
|
|
47
|
+
0, 45, 60, 0, 0, 0, 70, 90, 0, 0,
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
const hourLabels = ['0h', '6h', '12h', '18h', '24h']
|
|
51
|
+
const monthLabels = ['Jan', 'Apr', 'Jul', 'Oct']
|
|
52
|
+
|
|
53
|
+
// ── Items ────────────────────────────────────────────────────────────
|
|
54
|
+
|
|
55
|
+
interface PairItem {
|
|
56
|
+
title: string
|
|
57
|
+
subtitle: string
|
|
58
|
+
left: {
|
|
59
|
+
variant: 'area' | 'filled' | 'striped'
|
|
60
|
+
series: Array<{ data: number[]; color?: Color.ColorLike }>
|
|
61
|
+
xLabels: string[]
|
|
62
|
+
yRange?: [number, number]
|
|
63
|
+
stripeColors?: [Color.ColorLike, Color.ColorLike]
|
|
64
|
+
}
|
|
65
|
+
right: {
|
|
66
|
+
variant: 'area' | 'filled' | 'striped'
|
|
67
|
+
series: Array<{ data: number[]; color?: Color.ColorLike }>
|
|
68
|
+
xLabels: string[]
|
|
69
|
+
yRange?: [number, number]
|
|
70
|
+
stripeColors?: [Color.ColorLike, Color.ColorLike]
|
|
71
|
+
}
|
|
72
|
+
markdown?: string
|
|
73
|
+
meta: Array<{ title: string; text: string; color?: Color.ColorLike }>
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const items: PairItem[] = [
|
|
77
|
+
{
|
|
78
|
+
title: 'CPU vs Memory',
|
|
79
|
+
subtitle: 'Area + Filled side by side',
|
|
80
|
+
left: {
|
|
81
|
+
variant: 'area',
|
|
82
|
+
series: [{ data: cpuData, color: Color.Blue }],
|
|
83
|
+
xLabels: hourLabels,
|
|
84
|
+
yRange: [0, 100],
|
|
85
|
+
},
|
|
86
|
+
right: {
|
|
87
|
+
variant: 'filled',
|
|
88
|
+
series: [{ data: memData, color: Color.Green }],
|
|
89
|
+
xLabels: hourLabels,
|
|
90
|
+
yRange: [0, 100],
|
|
91
|
+
},
|
|
92
|
+
markdown: [
|
|
93
|
+
'## CPU vs Memory',
|
|
94
|
+
'',
|
|
95
|
+
'Area chart (left) shows CPU with high variance.',
|
|
96
|
+
'Filled chart (right) shows memory steadily climbing.',
|
|
97
|
+
].join('\n'),
|
|
98
|
+
meta: [
|
|
99
|
+
{ title: 'CPU Peak', text: '90%', color: Color.Blue },
|
|
100
|
+
{ title: 'Mem Peak', text: '86%', color: Color.Green },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
title: 'Disk I/O',
|
|
105
|
+
subtitle: 'Read vs Write operations',
|
|
106
|
+
left: {
|
|
107
|
+
variant: 'filled',
|
|
108
|
+
series: [{ data: readOps, color: Color.Orange }],
|
|
109
|
+
xLabels: hourLabels,
|
|
110
|
+
},
|
|
111
|
+
right: {
|
|
112
|
+
variant: 'filled',
|
|
113
|
+
series: [{ data: writeOps, color: Color.Purple }],
|
|
114
|
+
xLabels: hourLabels,
|
|
115
|
+
},
|
|
116
|
+
meta: [
|
|
117
|
+
{ title: 'Read Peak', text: '310 ops/s', color: Color.Orange },
|
|
118
|
+
{ title: 'Write Peak', text: '130 ops/s', color: Color.Purple },
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
title: 'Revenue vs Expenses',
|
|
123
|
+
subtitle: 'Striped comparison',
|
|
124
|
+
left: {
|
|
125
|
+
variant: 'striped',
|
|
126
|
+
series: [{ data: revenue }],
|
|
127
|
+
xLabels: monthLabels,
|
|
128
|
+
stripeColors: [Color.Green, Color.Blue],
|
|
129
|
+
},
|
|
130
|
+
right: {
|
|
131
|
+
variant: 'striped',
|
|
132
|
+
series: [{ data: expenses }],
|
|
133
|
+
xLabels: monthLabels,
|
|
134
|
+
stripeColors: [Color.Red, Color.Orange],
|
|
135
|
+
},
|
|
136
|
+
markdown: [
|
|
137
|
+
'## Revenue vs Expenses',
|
|
138
|
+
'',
|
|
139
|
+
'Revenue growing faster than expenses.',
|
|
140
|
+
'Profit margin widening over the year.',
|
|
141
|
+
'',
|
|
142
|
+
'- Revenue: **$10k** to **$75k**',
|
|
143
|
+
'- Expenses: **$8k** to **$45k**',
|
|
144
|
+
].join('\n'),
|
|
145
|
+
meta: [
|
|
146
|
+
{ title: 'Revenue', text: '$75k', color: Color.Green },
|
|
147
|
+
{ title: 'Expenses', text: '$45k', color: Color.Red },
|
|
148
|
+
{ title: 'Margin', text: '40%' },
|
|
149
|
+
],
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
title: 'Weather Station',
|
|
153
|
+
subtitle: 'Temperature + Humidity',
|
|
154
|
+
left: {
|
|
155
|
+
variant: 'area',
|
|
156
|
+
series: [{ data: temperature, color: Color.Red }],
|
|
157
|
+
xLabels: hourLabels,
|
|
158
|
+
yRange: [10, 35],
|
|
159
|
+
},
|
|
160
|
+
right: {
|
|
161
|
+
variant: 'area',
|
|
162
|
+
series: [{ data: humidity, color: Color.Blue }],
|
|
163
|
+
xLabels: hourLabels,
|
|
164
|
+
yRange: [40, 90],
|
|
165
|
+
},
|
|
166
|
+
markdown: [
|
|
167
|
+
'## Weather Station',
|
|
168
|
+
'',
|
|
169
|
+
'Temperature and humidity are **inversely correlated**.',
|
|
170
|
+
'As temperature rises, humidity drops.',
|
|
171
|
+
].join('\n'),
|
|
172
|
+
meta: [
|
|
173
|
+
{ title: 'Temp Range', text: '14-30\u00B0C', color: Color.Red },
|
|
174
|
+
{ title: 'Humidity', text: '48-83%', color: Color.Blue },
|
|
175
|
+
],
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
title: 'Mixed Variants',
|
|
179
|
+
subtitle: 'Area left, Striped right',
|
|
180
|
+
left: {
|
|
181
|
+
variant: 'area',
|
|
182
|
+
series: [
|
|
183
|
+
{ data: cpuData, color: Color.Blue },
|
|
184
|
+
{ data: memData, color: Color.Magenta },
|
|
185
|
+
],
|
|
186
|
+
xLabels: hourLabels,
|
|
187
|
+
yRange: [0, 100],
|
|
188
|
+
},
|
|
189
|
+
right: {
|
|
190
|
+
variant: 'striped',
|
|
191
|
+
series: [{ data: cpuData }],
|
|
192
|
+
xLabels: hourLabels,
|
|
193
|
+
yRange: [0, 100],
|
|
194
|
+
stripeColors: [Color.Yellow, Color.Red],
|
|
195
|
+
},
|
|
196
|
+
meta: [
|
|
197
|
+
{ title: 'Left', text: 'area (2 series)' },
|
|
198
|
+
{ title: 'Right', text: 'striped Yellow/Red' },
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
title: 'Sparse Data (Zeros)',
|
|
203
|
+
subtitle: 'Filled vs Striped with zero values',
|
|
204
|
+
left: {
|
|
205
|
+
variant: 'filled',
|
|
206
|
+
series: [{ data: sparseData, color: Color.Red }],
|
|
207
|
+
xLabels: hourLabels,
|
|
208
|
+
yRange: [0, 100],
|
|
209
|
+
},
|
|
210
|
+
right: {
|
|
211
|
+
variant: 'striped',
|
|
212
|
+
series: [{ data: sparseData }],
|
|
213
|
+
xLabels: hourLabels,
|
|
214
|
+
yRange: [0, 100],
|
|
215
|
+
stripeColors: [Color.Blue, Color.Green],
|
|
216
|
+
},
|
|
217
|
+
markdown: [
|
|
218
|
+
'## Sparse Data',
|
|
219
|
+
'',
|
|
220
|
+
'Data with many **zero values** should show a thin',
|
|
221
|
+
'baseline line so bars are visible even at zero.',
|
|
222
|
+
].join('\n'),
|
|
223
|
+
meta: [
|
|
224
|
+
{ title: 'Zeros', text: '12 of 20' },
|
|
225
|
+
{ title: 'Peak', text: '90' },
|
|
226
|
+
],
|
|
227
|
+
},
|
|
228
|
+
]
|
|
229
|
+
|
|
230
|
+
// ── Shared: render a graph from config ───────────────────────────────
|
|
231
|
+
|
|
232
|
+
function GraphFromConfig({ config, height }: {
|
|
233
|
+
config: PairItem['left']
|
|
234
|
+
height: number
|
|
235
|
+
}): any {
|
|
236
|
+
return (
|
|
237
|
+
<Graph
|
|
238
|
+
variant={config.variant}
|
|
239
|
+
height={height}
|
|
240
|
+
xLabels={config.xLabels}
|
|
241
|
+
yRange={config.yRange}
|
|
242
|
+
yTicks={4}
|
|
243
|
+
yFormat={(v) => v.toFixed(0)}
|
|
244
|
+
stripeColors={config.stripeColors}
|
|
245
|
+
>
|
|
246
|
+
{config.series.map((s, i) => {
|
|
247
|
+
return <Graph.Line key={i} data={s.data} color={s.color} />
|
|
248
|
+
})}
|
|
249
|
+
</Graph>
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// ── Full Detail view ─────────────────────────────────────────────────
|
|
254
|
+
|
|
255
|
+
function GraphRowDetail({ item }: { item: PairItem }): any {
|
|
256
|
+
const { pop } = useNavigation()
|
|
257
|
+
|
|
258
|
+
const markdown = [
|
|
259
|
+
`# ${item.title}`,
|
|
260
|
+
'',
|
|
261
|
+
item.subtitle,
|
|
262
|
+
...(item.markdown ? ['', item.markdown] : []),
|
|
263
|
+
].join('\n')
|
|
264
|
+
|
|
265
|
+
return (
|
|
266
|
+
<Detail
|
|
267
|
+
navigationTitle={item.title}
|
|
268
|
+
markdown={markdown}
|
|
269
|
+
metadata={
|
|
270
|
+
<Detail.Metadata>
|
|
271
|
+
<Row gap={1}>
|
|
272
|
+
<GraphFromConfig config={item.left} height={12} />
|
|
273
|
+
<GraphFromConfig config={item.right} height={12} />
|
|
274
|
+
</Row>
|
|
275
|
+
<Detail.Metadata.Separator />
|
|
276
|
+
{item.meta.map((m) => {
|
|
277
|
+
return (
|
|
278
|
+
<Detail.Metadata.Label
|
|
279
|
+
key={m.title}
|
|
280
|
+
title={m.title}
|
|
281
|
+
text={m.color ? { value: m.text, color: m.color } : m.text}
|
|
282
|
+
/>
|
|
283
|
+
)
|
|
284
|
+
})}
|
|
285
|
+
</Detail.Metadata>
|
|
286
|
+
}
|
|
287
|
+
actions={
|
|
288
|
+
<ActionPanel>
|
|
289
|
+
<Action title="Go Back" onAction={() => { pop() }} />
|
|
290
|
+
</ActionPanel>
|
|
291
|
+
}
|
|
292
|
+
/>
|
|
293
|
+
)
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// ── Main list ────────────────────────────────────────────────────────
|
|
297
|
+
|
|
298
|
+
function GraphRowExample() {
|
|
299
|
+
const { push } = useNavigation()
|
|
300
|
+
|
|
301
|
+
return (
|
|
302
|
+
<List navigationTitle="Graph Rows" isShowingDetail={true}>
|
|
303
|
+
{items.map((item) => {
|
|
304
|
+
return (
|
|
305
|
+
<List.Item
|
|
306
|
+
key={item.title}
|
|
307
|
+
title={item.title}
|
|
308
|
+
subtitle={item.subtitle}
|
|
309
|
+
detail={
|
|
310
|
+
<List.Item.Detail
|
|
311
|
+
markdown={item.markdown}
|
|
312
|
+
metadata={
|
|
313
|
+
<List.Item.Detail.Metadata>
|
|
314
|
+
<Row gap={1}>
|
|
315
|
+
<GraphFromConfig config={item.left} height={8} />
|
|
316
|
+
<GraphFromConfig config={item.right} height={8} />
|
|
317
|
+
</Row>
|
|
318
|
+
<List.Item.Detail.Metadata.Separator />
|
|
319
|
+
{item.meta.map((m) => {
|
|
320
|
+
return (
|
|
321
|
+
<List.Item.Detail.Metadata.Label
|
|
322
|
+
key={m.title}
|
|
323
|
+
title={m.title}
|
|
324
|
+
text={m.color ? { value: m.text, color: m.color } : m.text}
|
|
325
|
+
/>
|
|
326
|
+
)
|
|
327
|
+
})}
|
|
328
|
+
</List.Item.Detail.Metadata>
|
|
329
|
+
}
|
|
330
|
+
/>
|
|
331
|
+
}
|
|
332
|
+
actions={
|
|
333
|
+
<ActionPanel>
|
|
334
|
+
<Action
|
|
335
|
+
title="Open Detail"
|
|
336
|
+
onAction={() => { push(<GraphRowDetail item={item} />) }}
|
|
337
|
+
/>
|
|
338
|
+
</ActionPanel>
|
|
339
|
+
}
|
|
340
|
+
/>
|
|
341
|
+
)
|
|
342
|
+
})}
|
|
343
|
+
</List>
|
|
344
|
+
)
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
renderWithProviders(<GraphRowExample />)
|
|
@@ -0,0 +1,295 @@
|
|
|
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-row.tsx'],
|
|
10
|
+
cols: 100,
|
|
11
|
+
rows: 30,
|
|
12
|
+
})
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
session?.close()
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('side detail shows two graphs in a row', async () => {
|
|
20
|
+
const text = await session.text({
|
|
21
|
+
waitFor: (text) => {
|
|
22
|
+
return text.includes('CPU vs Memory') && text.includes('│')
|
|
23
|
+
},
|
|
24
|
+
timeout: 10000,
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
expect(text).toMatchInlineSnapshot(`
|
|
28
|
+
"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
Graph Rows ───────────────────────────────────────────────────────────────────────────────────
|
|
32
|
+
|
|
33
|
+
> Search...
|
|
34
|
+
|
|
35
|
+
›CPU vs Memory Area + Filled side by side │ CPU vs Memory
|
|
36
|
+
Disk I/O Read vs Write operations │
|
|
37
|
+
Revenue vs Expenses Striped comparison │ Area chart (left) shows CPU with high
|
|
38
|
+
Weather Station Temperature + Humidity │ variance.
|
|
39
|
+
Mixed Variants Area left, Striped right │ Filled chart (right) shows memory steadily
|
|
40
|
+
Sparse Data (Zeros) Filled vs Striped with zer │ climbing.
|
|
41
|
+
│
|
|
42
|
+
│ 100│ ⡀ 100│
|
|
43
|
+
│ │ ⡄ ⣼⣷⡀ │ ▄▄▀▀
|
|
44
|
+
│ 67│ ⣸⣿⡄ ⣸⣿⣿⣧ 67│ ▄▄▀▀▀▀▀▀▀
|
|
45
|
+
│ │ ⣼⣶⣿⣿⣷⡀ ⢰⣿⣿⣿⣿⣧ │ ▄▄▀▀▀▀▀▀▀▀▀▀▀▀
|
|
46
|
+
│ │ ⢸⣿⣿⣿⣿⣿⣷⣀⣿⣿⣿⣿⣿⣿⣇ │▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
47
|
+
│ 33│⣀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧ 33│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
48
|
+
│ │⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ │▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
49
|
+
│ 0│⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 0│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
50
|
+
│ 0h 6h 12h 18h24h 0h 6h 12h 18h24h
|
|
51
|
+
│
|
|
52
|
+
│ ───────────────────────────────────────────
|
|
53
|
+
│
|
|
54
|
+
│ CPU Peak: 90%
|
|
55
|
+
│
|
|
56
|
+
↵ open detail ↑↓ navigate ^k actions │ Mem Peak: 86%
|
|
57
|
+
|
|
58
|
+
"
|
|
59
|
+
`)
|
|
60
|
+
|
|
61
|
+
// Both graphs should render (braille for area, block for filled)
|
|
62
|
+
expect(text).toMatch(/[\u2800-\u28FF]/)
|
|
63
|
+
expect(text).toContain('CPU vs Memory')
|
|
64
|
+
}, 30000)
|
|
65
|
+
|
|
66
|
+
test('enter pushes full detail with two graphs', async () => {
|
|
67
|
+
await session.text({
|
|
68
|
+
waitFor: (text) => {
|
|
69
|
+
return text.includes('CPU vs Memory') && text.includes('│')
|
|
70
|
+
},
|
|
71
|
+
timeout: 10000,
|
|
72
|
+
})
|
|
73
|
+
|
|
74
|
+
await session.press('return')
|
|
75
|
+
|
|
76
|
+
const text = await session.text({
|
|
77
|
+
waitFor: (text) => {
|
|
78
|
+
return text.includes('CPU vs Memory') && text.includes('Area chart')
|
|
79
|
+
},
|
|
80
|
+
timeout: 5000,
|
|
81
|
+
})
|
|
82
|
+
|
|
83
|
+
expect(text).toMatchInlineSnapshot(`
|
|
84
|
+
"
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
█
|
|
88
|
+
█
|
|
89
|
+
CPU vs Memory ▀
|
|
90
|
+
|
|
91
|
+
Area + Filled side by side
|
|
92
|
+
|
|
93
|
+
CPU vs Memory
|
|
94
|
+
|
|
95
|
+
Area chart (left) shows CPU with high variance.
|
|
96
|
+
Filled chart (right) shows memory steadily climbing.
|
|
97
|
+
|
|
98
|
+
100│ 100│
|
|
99
|
+
│ ⢀⣠⣴⡄ │ ▄
|
|
100
|
+
│ ⣠⣦ ⣠⣿⣿⣿⣿⣦ │ ▄▄▄▄▄▀▀▀▀▀
|
|
101
|
+
│ ⢠⣾⣿⣿⣷⡄ ⢀⣼⣿⣿⣿⣿⣿⣿⣷⡀ │ ▄▄▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
102
|
+
67│ ⢀⡀ ⣰⣿⣿⣿⣿⣿⣿⡄ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣷⡀ 67│ ▄▄▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
103
|
+
│ ⢠⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⡄ ⢀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡄ │ ▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
104
|
+
│ ⣠⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣦⡀ ⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣄⡀ │ ▄▄▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
105
|
+
33│ ⢀⣴⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶⣤⣼⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣄ 33│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
106
|
+
│⣀⣤⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷ │▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
107
|
+
│⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ │▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
108
|
+
│⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ │▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
109
|
+
0│⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 0│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
esc go back ^k actions ↵ Go Back powered by termcast.app
|
|
113
|
+
|
|
114
|
+
"
|
|
115
|
+
`)
|
|
116
|
+
|
|
117
|
+
expect(text).toContain('CPU vs Memory')
|
|
118
|
+
expect(text).toContain('Area chart')
|
|
119
|
+
}, 30000)
|
|
120
|
+
|
|
121
|
+
test('esc returns from detail to list', async () => {
|
|
122
|
+
await session.text({
|
|
123
|
+
waitFor: (text) => {
|
|
124
|
+
return text.includes('CPU vs Memory') && text.includes('│')
|
|
125
|
+
},
|
|
126
|
+
timeout: 10000,
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
await session.press('return')
|
|
130
|
+
await session.text({
|
|
131
|
+
waitFor: (text) => {
|
|
132
|
+
return text.includes('Area chart')
|
|
133
|
+
},
|
|
134
|
+
timeout: 5000,
|
|
135
|
+
})
|
|
136
|
+
|
|
137
|
+
await session.press('escape')
|
|
138
|
+
|
|
139
|
+
const text = await session.text({
|
|
140
|
+
waitFor: (text) => {
|
|
141
|
+
return text.includes('›CPU vs Memory') && text.includes('Graph Rows')
|
|
142
|
+
},
|
|
143
|
+
timeout: 5000,
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
expect(text).toMatchInlineSnapshot(`
|
|
147
|
+
"
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
Graph Rows ───────────────────────────────────────────────────────────────────────────────────
|
|
151
|
+
|
|
152
|
+
> Search...
|
|
153
|
+
|
|
154
|
+
›CPU vs Memory Area + Filled side by side │ CPU vs Memory
|
|
155
|
+
Disk I/O Read vs Write operations │
|
|
156
|
+
Revenue vs Expenses Striped comparison │ Area chart (left) shows CPU with high
|
|
157
|
+
Weather Station Temperature + Humidity │ variance.
|
|
158
|
+
Mixed Variants Area left, Striped right │ Filled chart (right) shows memory steadily
|
|
159
|
+
Sparse Data (Zeros) Filled vs Striped with zer │ climbing.
|
|
160
|
+
│
|
|
161
|
+
│ 100│ ⡀ 100│
|
|
162
|
+
│ │ ⣠ ⢠⣾⣷⡀ │ ▄▄▀▀
|
|
163
|
+
│ 67│ ⣰⣿⣧ ⢀⣿⣿⣿⣇ 67│ ▄▄▀▀▀▀▀▀▀
|
|
164
|
+
│ │ ⢠⣷⣿⣿⣿⣆ ⣾⣿⣿⣿⣿⡄ │ ▄▄▀▀▀▀▀▀▀▀▀▀▀▀
|
|
165
|
+
│ │ ⢀⣿⣿⣿⣿⣿⣿⣆⣸⣿⣿⣿⣿⣿⣿⣄ │▄▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
166
|
+
│ 33│⣀⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧ 33│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
167
|
+
│ │⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ │▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
168
|
+
│ 0│⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ 0│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
169
|
+
│ 0h 6h 12h 18h24h 0h 6h 12h 18h24h
|
|
170
|
+
│
|
|
171
|
+
│ ────────────────────────────────────────────
|
|
172
|
+
│
|
|
173
|
+
│ CPU Peak: 90%
|
|
174
|
+
│
|
|
175
|
+
↵ open detail ↑↓ navigate ^k actions │ Mem Peak: 86%
|
|
176
|
+
|
|
177
|
+
"
|
|
178
|
+
`)
|
|
179
|
+
|
|
180
|
+
expect(text).toContain('›CPU vs Memory')
|
|
181
|
+
}, 30000)
|
|
182
|
+
|
|
183
|
+
test('sparse data with zeros shows baseline', async () => {
|
|
184
|
+
await session.text({
|
|
185
|
+
waitFor: (text) => {
|
|
186
|
+
return text.includes('Sparse Data')
|
|
187
|
+
},
|
|
188
|
+
timeout: 10000,
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
// Navigate to last item: "Sparse Data (Zeros)"
|
|
192
|
+
for (let i = 0; i < 5; i++) {
|
|
193
|
+
await session.press('down')
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
const text = await session.text({
|
|
197
|
+
waitFor: (text) => {
|
|
198
|
+
return text.includes('›Sparse Data')
|
|
199
|
+
},
|
|
200
|
+
timeout: 5000,
|
|
201
|
+
})
|
|
202
|
+
|
|
203
|
+
expect(text).toMatchInlineSnapshot(`
|
|
204
|
+
"
|
|
205
|
+
|
|
206
|
+
|
|
207
|
+
Graph Rows ───────────────────────────────────────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
> Search...
|
|
210
|
+
|
|
211
|
+
CPU vs Memory Area + Filled side by side │ Sparse Data
|
|
212
|
+
Disk I/O Read vs Write operations │
|
|
213
|
+
Revenue vs Expenses Striped comparison │ Data with many zero values should show a
|
|
214
|
+
Weather Station Temperature + Humidity │ thin
|
|
215
|
+
Mixed Variants Area left, Striped right │ baseline line so bars are visible even at
|
|
216
|
+
›Sparse Data (Zeros) Filled vs Striped with zer │ zero.
|
|
217
|
+
│
|
|
218
|
+
│ 100│ ▄ 100│ ▄
|
|
219
|
+
│ │ ▄ ▄▀ │ ▄ ▄▀
|
|
220
|
+
│ 67│ ▀ ▀▀ 67│ ▀ ▀▀
|
|
221
|
+
│ │ ▀▀ ▄▀ ▀▀ │ ▀▀ ▄▀ ▀▀
|
|
222
|
+
│ │ ▀▀ ▀▀ ▀▀▄ │ ▀▀ ▀▀ ▀▀▄
|
|
223
|
+
│ 33│ ▄ ▀▀▀ ▀▀▄▀▀▀▀ 33│ ▄ ▀▀▀ ▀▀▄ ▀▀▀
|
|
224
|
+
│ │ ▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀ │ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀
|
|
225
|
+
│ 0│▁▀▀▀▀▀▀▀▁▀▀▀▀▀▀▀▀▁ 0│▁▀▀▀▀▀▀▀▀▀▀▀▁▀▀▀▁
|
|
226
|
+
│ 0h 6h 12h 18h24h 0h 6h 12h 18h24h
|
|
227
|
+
│
|
|
228
|
+
│ ────────────────────────────────────────────
|
|
229
|
+
│
|
|
230
|
+
│ Zeros: 12 of 20
|
|
231
|
+
│
|
|
232
|
+
↵ open detail ↑↓ navigate ^k actions │ Peak: 90
|
|
233
|
+
|
|
234
|
+
"
|
|
235
|
+
`)
|
|
236
|
+
|
|
237
|
+
expect(text).toContain('›Sparse Data')
|
|
238
|
+
}, 30000)
|
|
239
|
+
|
|
240
|
+
test('navigate to striped pair', async () => {
|
|
241
|
+
await session.text({
|
|
242
|
+
waitFor: (text) => {
|
|
243
|
+
return text.includes('Revenue vs Expenses')
|
|
244
|
+
},
|
|
245
|
+
timeout: 10000,
|
|
246
|
+
})
|
|
247
|
+
|
|
248
|
+
// Navigate to 3rd item: "Revenue vs Expenses"
|
|
249
|
+
await session.press('down')
|
|
250
|
+
await session.press('down')
|
|
251
|
+
|
|
252
|
+
const text = await session.text({
|
|
253
|
+
waitFor: (text) => {
|
|
254
|
+
return text.includes('›Revenue vs Expenses')
|
|
255
|
+
},
|
|
256
|
+
timeout: 5000,
|
|
257
|
+
})
|
|
258
|
+
|
|
259
|
+
expect(text).toMatchInlineSnapshot(`
|
|
260
|
+
"
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
Graph Rows ───────────────────────────────────────────────────────────────────────────────────
|
|
264
|
+
|
|
265
|
+
> Search...
|
|
266
|
+
|
|
267
|
+
CPU vs Memory Area + Filled side by side │ Revenue vs Expenses ▲
|
|
268
|
+
Disk I/O Read vs Write operations │ █
|
|
269
|
+
›Revenue vs Expenses Striped comparison │ Revenue growing faster than expenses. █
|
|
270
|
+
Weather Station Temperature + Humidity │ Profit margin widening over the year. █
|
|
271
|
+
Mixed Variants Area left, Striped right │ █
|
|
272
|
+
Sparse Data (Zeros) Filled vs Striped with zer │ - Revenue: $10k to $75k
|
|
273
|
+
│ - Expenses: $8k to $45k
|
|
274
|
+
│
|
|
275
|
+
│
|
|
276
|
+
│ 78│ ▄ 47│ ▄
|
|
277
|
+
│ │ ▄▀▀▀ │ ▄▄▀▀▀
|
|
278
|
+
│ 54│ ▄▀▀▀▀▀ 33│ ▄▄▀▀▀▀▀
|
|
279
|
+
│ │ ▄▄▀▀▀▀▀▀▀ │ ▄▀▀▀▀▀▀▀▀
|
|
280
|
+
│ │ ▄ ▀▀▀▀▀▀▀▀▀▀ │ ▄▄▀▀▀▀▀▀▀▀▀▀
|
|
281
|
+
│ 31│ ▄▀▀▀▀▀▀▀▀▀▀▀▀▀ 20│ ▄▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
282
|
+
│ │ ▄ ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ │ ▄▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
283
|
+
│ 7│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ 6│▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀
|
|
284
|
+
│ Jan Apr Jul Oct Jan Apr Jul Oct
|
|
285
|
+
│
|
|
286
|
+
│ ───────────────────────────────────────────
|
|
287
|
+
│
|
|
288
|
+
↵ open detail ↑↓ navigate ^k actions │ Revenue: $75k ▼
|
|
289
|
+
|
|
290
|
+
"
|
|
291
|
+
`)
|
|
292
|
+
|
|
293
|
+
expect(text).toContain('›Revenue vs Expenses')
|
|
294
|
+
expect(text).toMatch(/[▄▀]/)
|
|
295
|
+
}, 30000)
|