1ch 0.3.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 CHANGED
@@ -1,181 +1,82 @@
1
1
  # 1ch
2
2
 
3
- **Terminal UI components for React.** For those who'd rather be in the terminal.
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
- ![1ch dashboard example](https://raw.githubusercontent.com/twoabove/1ch/main/demo/assets/demo.png)
5
+ ![1ch](https://raw.githubusercontent.com/twoabove/1ch/main/demo/assets/demo.png)
6
6
 
7
- The smallest unit is one character cell. A button is `[ OK ]`. A progress bar is `████░░░░`. A table border is `│` and `─` and `┼`. The whole thing is a grid.
7
+ [Playground](https://1ch.app/repl) &middot; [Docs](https://1ch.app/docs) &middot; [npm](https://www.npmjs.com/package/1ch)
8
+
9
+ ## Install
8
10
 
9
11
  ```bash
10
- npm install 1ch react react-dom
12
+ npm install 1ch
11
13
  ```
12
14
 
13
- ## What it looks like
15
+ ## Use
14
16
 
15
- ```tsx
16
- import { TermUI, TBox, TVStack, TTable, TBar } from "1ch";
17
- import "1ch/style.css";
17
+ Register once, then forget about it:
18
18
 
19
- function Dashboard() {
20
- return (
21
- <TermUI width={60}>
22
- <TBox title="Server Status">
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
- <!-- TODO: Add screenshot of the above rendering -->
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`, `TUnifiedDiff`, `TDiffCompute`, `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
- import { TermUI, TBox, TCode, TTabs, TTab, TTable, TBar, TVStack } from "1ch";
69
- import "1ch/style.css";
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
- <TermUI width={80}>
76
- <TTabs active={tab} onSelect={setTab}>
77
- <TTab name="Overview">
78
- <TBox title="Status">
79
- <TVStack>
80
- <TBar label="CPU" value={73} max={100} />
81
- <TBar label="MEM" value={4.2} max={8} />
82
- </TVStack>
83
- </TBox>
84
- </TTab>
85
-
86
- <TTab name="Logs">
87
- <TTable
88
- columns={[
89
- { key: "time", width: 12 },
90
- { key: "level", width: 8 },
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
- ## Don't want React? Skip it.
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
- ## Theming
55
+ ## Why
157
56
 
158
- Dark and light themes built in, and are switchable at runtime. You can override everything via JSON - palette, semantic colors, syntax highlighting, markdown rendering, component tokens. Use `parseThemeSpec()` to check the JSON before applying it.
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
- ```tsx
161
- import {
162
- TermThemeProvider,
163
- TermUI,
164
- parseThemeSpec,
165
- defaultThemeSpec,
166
- } from "1ch";
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
- ## Docs
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
- Full API reference, theme spec details, hooks (`useSpinner`, `useTick`, `useTermWidth`, `useStreamingText`), and the document pipeline - all in the [docs](1ch.app) (coming soon).
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