1ch 0.2.0 → 0.4.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/README.md +54 -153
- package/dist/index.d.ts +271 -317
- package/dist/index.js +1892 -1866
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/package.json +4 -15
package/README.md
CHANGED
|
@@ -1,181 +1,82 @@
|
|
|
1
1
|
# 1ch
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Character-grid UI that runs in the browser. One `<term-ui>` element turns semantic HTML into a fixed-width terminal render -- boxes, tables, charts, progress bars, status lines -- all from standard tags.
|
|
4
4
|
|
|
5
|
-

|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
[Playground](https://1ch.app/repl) · [Docs](https://1ch.app/docs) · [npm](https://www.npmjs.com/package/1ch)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
8
10
|
|
|
9
11
|
```bash
|
|
10
|
-
npm install 1ch
|
|
12
|
+
npm install 1ch
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
##
|
|
15
|
+
## Use
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
import { TermUI, TBox, TVStack, TTable, TBar } from "1ch";
|
|
17
|
-
import "1ch/style.css";
|
|
17
|
+
Register once, then forget about it:
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
<TVStack gap={1}>
|
|
24
|
-
<TBar label="CPU" value={73} max={100} />
|
|
25
|
-
<TBar label="MEM" value={4.2} max={8} />
|
|
26
|
-
<TTable
|
|
27
|
-
columns={[
|
|
28
|
-
{ key: "service", width: 20 },
|
|
29
|
-
{ key: "status", width: 10 },
|
|
30
|
-
{ key: "uptime", width: 12 },
|
|
31
|
-
]}
|
|
32
|
-
data={[
|
|
33
|
-
{ service: "api-gateway", status: "UP", uptime: "14d 3h" },
|
|
34
|
-
{ service: "worker-pool", status: "UP", uptime: "14d 3h" },
|
|
35
|
-
{ service: "cache", status: "WARN", uptime: "2h 41m" },
|
|
36
|
-
]}
|
|
37
|
-
/>
|
|
38
|
-
</TVStack>
|
|
39
|
-
</TBox>
|
|
40
|
-
</TermUI>
|
|
41
|
-
);
|
|
42
|
-
}
|
|
19
|
+
```ts
|
|
20
|
+
import { registerTermUIElement } from "1ch";
|
|
21
|
+
import "1ch/style.css";
|
|
22
|
+
registerTermUIElement();
|
|
43
23
|
```
|
|
44
24
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
## Why this exists
|
|
48
|
-
|
|
49
|
-
Most UI components are styled `<div>`s pretending to be something else. Terminal UIs skip the pretense - every character is either content or structure, and the grid makes boundaries obvious.
|
|
50
|
-
|
|
51
|
-
Under the hood, 1ch uses a custom React reconciler that turns your component tree into character grids. React handles lifecycle, hooks, state. The reconciler handles layout. Resize the container and everything reflows.
|
|
52
|
-
|
|
53
|
-
## Components
|
|
54
|
-
|
|
55
|
-
**Layout** - `TVStack`, `THStack`, `TBox`, `TSeparator`, `TBlank`, `TLine`, `TSpan`
|
|
56
|
-
|
|
57
|
-
**Data** - `TTable`, `TTree`, `TList`, `TCode`, `TDiff`, `TBar`, `TSpark`
|
|
58
|
-
|
|
59
|
-
**Interactive** - `TTabs`, `TButton`, `TStatusbar`
|
|
60
|
-
|
|
61
|
-
**Documents** - `TMarkdown`, `THtml`, `TJson`
|
|
62
|
-
|
|
63
|
-
The document components accept raw strings. Feed `TMarkdown` a markdown string, `THtml` an HTML string, or `TJson` a JSON object, and you get terminal-styled output back.
|
|
64
|
-
|
|
65
|
-
## A more complete example
|
|
25
|
+
Drop it in with your preferred reactivity provider:
|
|
66
26
|
|
|
67
27
|
```tsx
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
function App() {
|
|
72
|
-
const [tab, setTab] = useState(0);
|
|
28
|
+
function DeployPanel() {
|
|
29
|
+
const [build, setBuild] = useState(0);
|
|
30
|
+
const { metrics } = useMetrics();
|
|
73
31
|
|
|
74
32
|
return (
|
|
75
|
-
<
|
|
76
|
-
<
|
|
77
|
-
<
|
|
78
|
-
<
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
{ key: "message", width: 40 },
|
|
92
|
-
]}
|
|
93
|
-
data={[
|
|
94
|
-
{
|
|
95
|
-
time: "14:03:21",
|
|
96
|
-
level: "INFO",
|
|
97
|
-
message: "Server started on :3000",
|
|
98
|
-
},
|
|
99
|
-
{
|
|
100
|
-
time: "14:03:22",
|
|
101
|
-
level: "INFO",
|
|
102
|
-
message: "Connected to database",
|
|
103
|
-
},
|
|
104
|
-
{ time: "14:05:01", level: "WARN", message: "Slow query: 2.3s" },
|
|
105
|
-
]}
|
|
106
|
-
/>
|
|
107
|
-
</TTab>
|
|
108
|
-
|
|
109
|
-
<TTab name="Config">
|
|
110
|
-
<TCode
|
|
111
|
-
code={`export default {
|
|
112
|
-
port: 3000,
|
|
113
|
-
database: "postgres://localhost/app",
|
|
114
|
-
cache: { ttl: 300, max: 1000 },
|
|
115
|
-
};`}
|
|
116
|
-
language="typescript"
|
|
117
|
-
title="config.ts"
|
|
118
|
-
/>
|
|
119
|
-
</TTab>
|
|
120
|
-
</TTabs>
|
|
121
|
-
</TermUI>
|
|
33
|
+
<term-ui width="60" mode="dark">
|
|
34
|
+
<section gap="1">
|
|
35
|
+
<article title="deploy v2.4.1">
|
|
36
|
+
<progress data-label="build" value={build} max="100"></progress>
|
|
37
|
+
<progress data-label="tests" value="94" max="100"></progress>
|
|
38
|
+
</article>
|
|
39
|
+
<figure height="4" fill>
|
|
40
|
+
{metrics.map(v => <data value={v} />)}
|
|
41
|
+
</figure>
|
|
42
|
+
<nav>
|
|
43
|
+
<button onClick={() => deploy()}>deploy</button>
|
|
44
|
+
<button onClick={() => rollback()}>rollback</button>
|
|
45
|
+
</nav>
|
|
46
|
+
<footer left=" healthy" right="64s ago "></footer>
|
|
47
|
+
</section>
|
|
48
|
+
</term-ui>
|
|
122
49
|
);
|
|
123
50
|
}
|
|
124
51
|
```
|
|
125
52
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
Every component has an imperative equivalent that returns a layout function. Call it with a width and get a character grid back.
|
|
129
|
-
|
|
130
|
-
```typescript
|
|
131
|
-
import { box, vstack, table, code, bar } from "1ch";
|
|
132
|
-
|
|
133
|
-
const layout = vstack(
|
|
134
|
-
box(
|
|
135
|
-
vstack(
|
|
136
|
-
bar(73, 100, 40),
|
|
137
|
-
table(
|
|
138
|
-
[
|
|
139
|
-
{ key: "name", header: "Name", width: 20 },
|
|
140
|
-
{ key: "value", header: "Value", width: 10 },
|
|
141
|
-
],
|
|
142
|
-
[
|
|
143
|
-
{ name: "requests", value: "1.2k/s" },
|
|
144
|
-
{ name: "errors", value: "0.03%" },
|
|
145
|
-
]
|
|
146
|
-
)
|
|
147
|
-
),
|
|
148
|
-
{ title: "Metrics" }
|
|
149
|
-
),
|
|
150
|
-
code(`console.log("hello")`, { language: "javascript" })
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
const block = layout(80);
|
|
154
|
-
```
|
|
53
|
+
`<article>` is a box. `<progress>` is a bar. `<figure>` is a chart. `<nav>` lays out horizontally. `<footer>` is a status line. No wrapper components, no special syntax -- just HTML that happens to render as a terminal.
|
|
155
54
|
|
|
156
|
-
##
|
|
55
|
+
## Why
|
|
157
56
|
|
|
158
|
-
|
|
57
|
+
Tables draw with `│─┼`. Progress bars fill with `████░░░░`. Buttons are `[ deploy ]`. Everything snaps to a character grid and it just looks *right*.
|
|
159
58
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
const parsed = parseThemeSpec(userThemeJson);
|
|
169
|
-
const spec = parsed.ok ? parsed.theme : defaultThemeSpec;
|
|
170
|
-
|
|
171
|
-
<TermThemeProvider initialTheme={spec} initialMode="system">
|
|
172
|
-
<TermUI width={80}>{/* components inherit the theme */}</TermUI>
|
|
173
|
-
</TermThemeProvider>;
|
|
174
|
-
```
|
|
59
|
+
Who needs designs for internal tools when a character grid gives you a clean UI for free? Dashboards, admin panels, monitoring views, CLI-style apps -- just write the HTML and it looks like something you'd actually want to use.
|
|
60
|
+
|
|
61
|
+
Your CSS still works -- `display: grid`, `gap`, `grid-template-columns` get picked up from `getComputedStyle` and mapped to the grid. It's a web component, so React, Vue, Svelte, htmx, plain HTML -- whatever. `onClick` on a `<button>` fires like you'd expect.
|
|
62
|
+
|
|
63
|
+
Zero dependencies. Also does markdown and JSON (`source-format="markdown"` on the element).
|
|
64
|
+
|
|
65
|
+
## Quick reference
|
|
175
66
|
|
|
176
|
-
|
|
67
|
+
| Element | Becomes |
|
|
68
|
+
|---------|---------|
|
|
69
|
+
| `<article title="X">` | box |
|
|
70
|
+
| `<figure>` | chart (text content, `<data>` children, or `data-values`) |
|
|
71
|
+
| `<footer left="X" right="Y">` | status bar |
|
|
72
|
+
| `<nav>` | horizontal stack |
|
|
73
|
+
| `<progress>` | bar |
|
|
74
|
+
| `<hr>` / `<hr label="X">` | separator / divider |
|
|
75
|
+
| `<pre>` | code block |
|
|
76
|
+
| `<table>` | table |
|
|
77
|
+
| `<section>`, `<div>` | container (layout from CSS) |
|
|
177
78
|
|
|
178
|
-
|
|
79
|
+
`data-term="..."` and `term-*` tags available when you need to be explicit. Custom tag compilers via `registerHtmlTagCompiler()`. Full details in the [docs](https://1ch.app/docs).
|
|
179
80
|
|
|
180
81
|
## License
|
|
181
82
|
|