@zakmandhro/bunti 0.1.4 → 0.2.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.
Files changed (203) hide show
  1. package/AGENTS.md +65 -0
  2. package/README.md +145 -34
  3. package/dist/cli.d.ts +44 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +147 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/colors.d.ts +144 -0
  8. package/dist/colors.d.ts.map +1 -0
  9. package/dist/colors.js +426 -0
  10. package/dist/colors.js.map +1 -0
  11. package/dist/components/Box.d.ts +11 -0
  12. package/dist/components/Box.d.ts.map +1 -0
  13. package/dist/components/Box.js +9 -0
  14. package/dist/components/Box.js.map +1 -0
  15. package/dist/components/Button.d.ts +24 -0
  16. package/dist/components/Button.d.ts.map +1 -0
  17. package/dist/components/Button.js +102 -0
  18. package/dist/components/Button.js.map +1 -0
  19. package/dist/components/Card.d.ts +33 -0
  20. package/dist/components/Card.d.ts.map +1 -0
  21. package/dist/components/Card.js +79 -0
  22. package/dist/components/Card.js.map +1 -0
  23. package/dist/components/Header.d.ts +23 -0
  24. package/dist/components/Header.d.ts.map +1 -0
  25. package/dist/components/Header.js +58 -0
  26. package/dist/components/Header.js.map +1 -0
  27. package/dist/components/Input.d.ts +25 -0
  28. package/dist/components/Input.d.ts.map +1 -0
  29. package/dist/components/Input.js +232 -0
  30. package/dist/components/Input.js.map +1 -0
  31. package/dist/components/Link.d.ts +21 -0
  32. package/dist/components/Link.d.ts.map +1 -0
  33. package/dist/components/Link.js +29 -0
  34. package/dist/components/Link.js.map +1 -0
  35. package/dist/components/Modal.d.ts +38 -0
  36. package/dist/components/Modal.d.ts.map +1 -0
  37. package/dist/components/Modal.js +87 -0
  38. package/dist/components/Modal.js.map +1 -0
  39. package/dist/components/Progress.d.ts +27 -0
  40. package/dist/components/Progress.d.ts.map +1 -0
  41. package/dist/components/Progress.js +39 -0
  42. package/dist/components/Progress.js.map +1 -0
  43. package/dist/components/Spinner.d.ts +19 -0
  44. package/dist/components/Spinner.d.ts.map +1 -0
  45. package/dist/components/Spinner.js +27 -0
  46. package/dist/components/Spinner.js.map +1 -0
  47. package/dist/components/index.d.ts +10 -0
  48. package/dist/components/index.d.ts.map +1 -0
  49. package/dist/components/index.js +10 -0
  50. package/dist/components/index.js.map +1 -0
  51. package/dist/data/nf-glyphs.d.ts +11 -0
  52. package/dist/data/nf-glyphs.d.ts.map +1 -0
  53. package/dist/data/nf-glyphs.js +535 -0
  54. package/dist/data/nf-glyphs.js.map +1 -0
  55. package/dist/data/nf-names.d.ts +8 -0
  56. package/dist/data/nf-names.d.ts.map +1 -0
  57. package/dist/data/nf-names.js +2 -0
  58. package/dist/data/nf-names.js.map +1 -0
  59. package/dist/demo-registry.d.ts +27 -0
  60. package/dist/demo-registry.d.ts.map +1 -0
  61. package/dist/demo-registry.js +57 -0
  62. package/dist/demo-registry.js.map +1 -0
  63. package/dist/demos/2048.ts +743 -0
  64. package/dist/demos/animation.ts +246 -0
  65. package/dist/demos/demo-layout.ts +124 -0
  66. package/dist/demos/engine.ts +374 -0
  67. package/dist/demos/interaction.ts +91 -0
  68. package/dist/demos/login.ts +203 -0
  69. package/dist/demos/mission-control.ts +558 -0
  70. package/dist/demos/showcase.ts +224 -0
  71. package/dist/detect.d.ts +104 -0
  72. package/dist/detect.d.ts.map +1 -0
  73. package/dist/detect.js +227 -0
  74. package/dist/detect.js.map +1 -0
  75. package/dist/diagnostics.d.ts +73 -0
  76. package/dist/diagnostics.d.ts.map +1 -0
  77. package/dist/diagnostics.js +225 -0
  78. package/dist/diagnostics.js.map +1 -0
  79. package/dist/dsl/context.d.ts +11 -0
  80. package/dist/dsl/context.d.ts.map +1 -0
  81. package/dist/dsl/context.js +563 -0
  82. package/dist/dsl/context.js.map +1 -0
  83. package/dist/dsl/hooks.d.ts +12 -0
  84. package/dist/dsl/hooks.d.ts.map +1 -0
  85. package/dist/dsl/hooks.js +148 -0
  86. package/dist/dsl/hooks.js.map +1 -0
  87. package/dist/dsl/interaction.d.ts +16 -0
  88. package/dist/dsl/interaction.d.ts.map +1 -0
  89. package/dist/dsl/interaction.js +101 -0
  90. package/dist/dsl/interaction.js.map +1 -0
  91. package/dist/dsl/layers.d.ts +14 -0
  92. package/dist/dsl/layers.d.ts.map +1 -0
  93. package/dist/dsl/layers.js +87 -0
  94. package/dist/dsl/layers.js.map +1 -0
  95. package/dist/dsl/motion.d.ts +10 -0
  96. package/dist/dsl/motion.d.ts.map +1 -0
  97. package/dist/dsl/motion.js +150 -0
  98. package/dist/dsl/motion.js.map +1 -0
  99. package/dist/dsl/render.d.ts +22 -0
  100. package/dist/dsl/render.d.ts.map +1 -0
  101. package/dist/dsl/render.js +69 -0
  102. package/dist/dsl/render.js.map +1 -0
  103. package/dist/dsl/types.d.ts +510 -0
  104. package/dist/dsl/types.d.ts.map +1 -0
  105. package/dist/dsl/types.js +33 -0
  106. package/dist/dsl/types.js.map +1 -0
  107. package/dist/dsl.d.ts +18 -0
  108. package/dist/dsl.d.ts.map +1 -0
  109. package/dist/dsl.js +17 -0
  110. package/dist/dsl.js.map +1 -0
  111. package/dist/easing.d.ts +45 -0
  112. package/dist/easing.d.ts.map +1 -0
  113. package/dist/easing.js +121 -0
  114. package/dist/easing.js.map +1 -0
  115. package/dist/geometry.d.ts +77 -0
  116. package/dist/geometry.d.ts.map +1 -0
  117. package/dist/geometry.js +130 -0
  118. package/dist/geometry.js.map +1 -0
  119. package/dist/icons-full.d.ts +5 -0
  120. package/dist/icons-full.d.ts.map +1 -0
  121. package/dist/icons-full.js +31 -0
  122. package/dist/icons-full.js.map +1 -0
  123. package/dist/icons.d.ts +442 -0
  124. package/dist/icons.d.ts.map +1 -0
  125. package/dist/icons.js +314 -0
  126. package/dist/icons.js.map +1 -0
  127. package/dist/index.d.ts +228 -0
  128. package/dist/index.d.ts.map +1 -0
  129. package/dist/index.js +46 -0
  130. package/dist/index.js.map +1 -0
  131. package/dist/input.d.ts +177 -0
  132. package/dist/input.d.ts.map +1 -0
  133. package/dist/input.js +533 -0
  134. package/dist/input.js.map +1 -0
  135. package/dist/layout.d.ts +194 -0
  136. package/dist/layout.d.ts.map +1 -0
  137. package/dist/layout.js +673 -0
  138. package/dist/layout.js.map +1 -0
  139. package/dist/render.d.ts +49 -0
  140. package/dist/render.d.ts.map +1 -0
  141. package/dist/render.js +650 -0
  142. package/dist/render.js.map +1 -0
  143. package/dist/state.d.ts +226 -0
  144. package/dist/state.d.ts.map +1 -0
  145. package/dist/state.js +130 -0
  146. package/dist/state.js.map +1 -0
  147. package/dist/theme.d.ts +129 -0
  148. package/dist/theme.d.ts.map +1 -0
  149. package/dist/theme.js +167 -0
  150. package/dist/theme.js.map +1 -0
  151. package/dist/themes/catppuccin-mocha.d.ts +19 -0
  152. package/dist/themes/catppuccin-mocha.d.ts.map +1 -0
  153. package/dist/themes/catppuccin-mocha.js +36 -0
  154. package/dist/themes/catppuccin-mocha.js.map +1 -0
  155. package/dist/themes/dracula.d.ts +21 -0
  156. package/dist/themes/dracula.d.ts.map +1 -0
  157. package/dist/themes/dracula.js +37 -0
  158. package/dist/themes/dracula.js.map +1 -0
  159. package/dist/themes/github-light.d.ts +21 -0
  160. package/dist/themes/github-light.d.ts.map +1 -0
  161. package/dist/themes/github-light.js +36 -0
  162. package/dist/themes/github-light.js.map +1 -0
  163. package/dist/themes/index.d.ts +19 -0
  164. package/dist/themes/index.d.ts.map +1 -0
  165. package/dist/themes/index.js +17 -0
  166. package/dist/themes/index.js.map +1 -0
  167. package/dist/themes/nord.d.ts +23 -0
  168. package/dist/themes/nord.d.ts.map +1 -0
  169. package/dist/themes/nord.js +38 -0
  170. package/dist/themes/nord.js.map +1 -0
  171. package/dist/themes/one-dark-pro.d.ts +21 -0
  172. package/dist/themes/one-dark-pro.d.ts.map +1 -0
  173. package/dist/themes/one-dark-pro.js +36 -0
  174. package/dist/themes/one-dark-pro.js.map +1 -0
  175. package/dist/themes/tokyo-night.d.ts +20 -0
  176. package/dist/themes/tokyo-night.d.ts.map +1 -0
  177. package/dist/themes/tokyo-night.js +37 -0
  178. package/dist/themes/tokyo-night.js.map +1 -0
  179. package/dist/utils.d.ts +28 -0
  180. package/dist/utils.d.ts.map +1 -0
  181. package/dist/utils.js +158 -0
  182. package/dist/utils.js.map +1 -0
  183. package/dist/vendor/colors.d.ts +45 -0
  184. package/dist/vendor/colors.d.ts.map +1 -0
  185. package/dist/vendor/colors.js +72 -0
  186. package/dist/vendor/colors.js.map +1 -0
  187. package/llms.txt +79 -0
  188. package/package.json +52 -11
  189. package/src/colors.ts +0 -255
  190. package/src/components/Button.ts +0 -104
  191. package/src/components/Card.ts +0 -53
  192. package/src/components/Header.ts +0 -65
  193. package/src/components/Input.ts +0 -124
  194. package/src/components/index.ts +0 -4
  195. package/src/data/glyphs.ts +0 -30
  196. package/src/detect.ts +0 -60
  197. package/src/dsl.ts +0 -661
  198. package/src/icons.ts +0 -186
  199. package/src/index.ts +0 -72
  200. package/src/layout.ts +0 -640
  201. package/src/render.ts +0 -302
  202. package/src/state.ts +0 -148
  203. package/src/utils.ts +0 -165
package/AGENTS.md ADDED
@@ -0,0 +1,65 @@
1
+ # AGENTS.md
2
+
3
+ How to build good terminal apps with Bunti. The API itself is documented
4
+ where you'll actually read it — JSDoc in the package's `dist/*.d.ts` and
5
+ the quick reference in `llms.txt`; dev-mode hints on stderr catch the
6
+ common wiring mistakes. This file covers what types can't: layout taste
7
+ and app structure.
8
+
9
+ Start from `examples/starter.ts` in the repo — it is the shape most
10
+ dashboards want (header bar, `ctx.split` tracks, keyboard selection,
11
+ themed panels).
12
+
13
+ ## Not React
14
+
15
+ Bunti is immediate mode: the render callback redraws the whole frame
16
+ from state and Bunti flushes only the terminal diff. Do not build
17
+ component trees, providers, reducers, or reconciliation-style
18
+ abstractions unless the user explicitly asks. Build the screen directly
19
+ with `ctx` primitives; keep domain logic in plain TypeScript functions
20
+ outside the render callback.
21
+
22
+ ## Layout model
23
+
24
+ - Everything is a cell rect. `x`/`y` are local to the current context:
25
+ the whole screen at the root, the padded interior inside a `box()`.
26
+ Use `ctx.offsetX`/`ctx.offsetY` to convert local to absolute when
27
+ drawing with `rect()`/`blit()`.
28
+ - Root-level `box()` paints directly to the screen and **centers**
29
+ itself unless you pass `x`/`y`. Nested boxes join the parent's text
30
+ flow. Both return the rendered string.
31
+ - Carve screens with `ctx.split({ direction, constraints: [24, '1fr'] })`
32
+ and draw one box per track — don't hand-compute column math.
33
+ - Terminal cells are taller than wide: a 1-row vertical gap balances a
34
+ 2-column horizontal gap, and `padding: [1, 2]` looks square-ish.
35
+ - Name repeated dimensions (`SIDEBAR_W`, `ROW_H`, `GAP_X`) instead of
36
+ scattering magic numbers.
37
+ - Prefer `border: 'none'` for dense canvases and work surfaces; borders
38
+ are a design choice, not a default.
39
+
40
+ ## App patterns
41
+
42
+ - `useState(key, initial)` for view state; `usePersistentState` only
43
+ for values that must survive restarts; `useAsync(key, fetcher,
44
+ { interval })` for data — never block the render loop.
45
+ - Components (`Card`, `Button`, `Input`, `Modal`, ...) for common
46
+ controls; direct `rect()`/`blit()` for dense dashboards, charts,
47
+ maps, and canvas-like regions.
48
+ - `ctx.layer()` for command palettes, confirmations, notifications, and
49
+ HUDs — anything that overlaps other content. Draw order alone does
50
+ not stack.
51
+ - Style from `ctx.theme` tokens (`theme.surface`, `theme.primary`,
52
+ `theme.muted`, ...) rather than hardcoded colors, so live theme swaps
53
+ and the built-in presets keep working.
54
+ - Animate on time, not frame count: `ctx.animate`/`ctx.transition`/
55
+ `ctx.dt`. UI transitions feel right around 150-250ms. Prefer stable
56
+ geometry with color/brightness interpolation over adding/removing
57
+ cells step-by-step.
58
+
59
+ ## Before handing code to the user
60
+
61
+ - Import from `@zakmandhro/bunti`, never repo-relative paths.
62
+ - Run it if possible. It renders to pipes, but keyboard input needs a
63
+ real PTY — see the "Agent & CI testing" section of the README for a
64
+ copy-paste PTY harness.
65
+ - Remove debug/preview state and fix TypeScript errors first.
package/README.md CHANGED
@@ -12,48 +12,86 @@ Bunti (pronounced *Bun-ty*) is a zero-dependency, double-buffered layout engine
12
12
  - 📐 **Tactical Standard**: Opinionated border styles (`default`, `rounded`, `frame`, `thick-frame`).
13
13
  - 🌈 **24-bit TrueColor**: High-fidelity RGB gradients with native hex parsing and relative contrast.
14
14
  - 🖱️ **Interactive**: Built-in SGR mouse tracking and focus detection with automatic FPS throttling.
15
+ - 🎞️ **Animation Helpers**: Timeline progress, color fades, flicker, and typewriter text with block cursors.
15
16
 
16
17
  ## 📦 Installation
17
18
 
18
- Bunti is designed for Bun, but works in standard Node.js environments (v18+) as well.
19
+ Bunti is Bun-native and ships compiled ESM plus TypeScript declarations — with zero runtime dependencies.
19
20
 
20
21
  ```bash
21
22
  bun add @zakmandhro/bunti
22
23
  ```
23
24
 
24
- Or using npm/pnpm/yarn:
25
-
26
- ```bash
27
- npm install @zakmandhro/bunti
28
- ```
25
+ > Bunti requires the [Bun](https://bun.sh) runtime (>= 1.0). It uses Bun-native APIs for rendering, so Node.js is not supported.
29
26
 
30
27
  ## 🚀 Quick Start
31
28
 
32
29
  ```typescript
33
30
  import { bunti } from '@zakmandhro/bunti';
31
+ import { Box, Button, Input } from '@zakmandhro/bunti/components';
32
+
33
+ bunti.render((ctx) => {
34
+ const { color, icon, wallpaper, gradient } = ctx;
35
+
36
+ wallpaper(gradient({ colors: ['midnight', 'plasma'] }));
34
37
 
35
- bunti.render(({ wallpaper, box, color, icon, span }) => {
36
- // 1. Set a dynamic gradient background
37
- wallpaper(bunti.gradient({ colors: ['midnight', 'plasma'] }));
38
-
39
- // 2. Define a centered high-contrast card
40
- box({
41
- size: "auto",
42
- bgColor: "white",
43
- color: "blank", // Automatic high-contrast black
44
- border: 'frame' // Tactical block border
45
- }, ({ text }) => {
38
+ Box(ctx, {
39
+ width: 48,
40
+ border: 'frame',
41
+ bgColor: 'white',
42
+ color: 'black'
43
+ }, (sub) => {
44
+ const { text } = sub;
46
45
  text(` ${icon('rocket')} `);
47
- text(color.bold("MISSION CONTROL\n\n"));
48
-
49
- span({ color: color.dim }, ({ text }) => {
50
- text("STATUS: ");
46
+ text(color.bold('MISSION CONTROL\n\n'));
47
+
48
+ Input(sub, {
49
+ id: 'mission',
50
+ label: 'MISSION:',
51
+ placeholder: 'Enter mission name...',
52
+ width: 36
53
+ });
54
+
55
+ Button(sub, {
56
+ id: 'deploy',
57
+ label: 'Deploy',
58
+ variant: 'primary'
51
59
  });
52
- text("NOMINAL");
53
60
  });
54
- }, { fps: 60, mouse: true });
61
+ }, { fps: 60, mouse: true, keyboard: true, defaultFg: 'silver' });
62
+ ```
63
+
64
+ ## 📏 Layout Model
65
+
66
+ Everything is a cell rect, and coordinates are **local to the current
67
+ context**: the whole screen at the root, the padded interior inside a
68
+ `box()`. A root-level `box()` paints directly into the screen buffer and
69
+ **centers itself** unless you pass `x`/`y`; a nested `box()` joins its
70
+ parent's text flow instead. Every drawing call also *returns* the rendered
71
+ string, so you can compose with `joinHorizontal`/`joinVertical` or place
72
+ output manually. Carve responsive layouts with tracks instead of column
73
+ math:
74
+
75
+ ```typescript
76
+ const [sidebar, main] = ctx.split({
77
+ direction: 'horizontal',
78
+ constraints: [24, '1fr'], // cells, percentages, and fr fill units
79
+ });
80
+ ctx.box({ x: sidebar.x, y: 2, width: sidebar.width, border: 'rounded' }, drawNav);
55
81
  ```
56
82
 
83
+ Under the hood it is Rect-first:
84
+
85
+ - `Rect` is the geometry primitive.
86
+ - `Box`, `Button`, `Input`, `Card`, and `Header` resolve a rect before rendering.
87
+ - Hitboxes and rendered output share the same resolved rect.
88
+ - `splitRect()` and `ctx.split()` create responsive tracks from fixed sizes, percentages, and `fr` fill units.
89
+ - `ctx.resolveLocalRect()` places components within the current parent area, including left/center/right and top/center/bottom defaults.
90
+
91
+ A complete, runnable dashboard template lives at
92
+ [`examples/starter.ts`](./examples/starter.ts) — copy it as your app's
93
+ starting point.
94
+
57
95
  ## 📐 Border Archetypes
58
96
 
59
97
  Bunti categorizes containers into three visual archetypes:
@@ -68,25 +106,96 @@ Bunti categorizes containers into three visual archetypes:
68
106
 
69
107
  Bunti is built for speed. By leveraging `Bun.stdout.writer()` and surgical diffing, it can maintain **60-120 FPS** on complex layouts while keeping TTY bytes significantly lower than standard stream-based libraries.
70
108
 
109
+ ## 🤖 Agent & CI testing
110
+
111
+ Bunti renders fine to plain pipes — `bun app.ts | cat` produces real ANSI
112
+ frames, so screenshot-style assertions work anywhere. **Keyboard input is
113
+ different: it needs a real TTY.** When stdin is a pipe (CI, agent
114
+ harnesses, `echo q | bun app.ts`), raw-mode input is never attached and
115
+ keys are silently ignored — Bunti prints a dev hint to stderr on exit when
116
+ this happens (silence hints with `BUNTI_NO_HINTS=1`).
117
+
118
+ To drive keyboard input headlessly, wrap the run in a PTY. On macOS and
119
+ Linux, `script` is the zero-dependency way — mind the argument-order trap:
120
+
121
+ ```bash
122
+ # macOS: the transcript file comes BEFORE the command.
123
+ (sleep 2; printf 'q') | script -q /dev/null bun app.ts
124
+
125
+ # Linux (util-linux script): the command is passed via -c.
126
+ (sleep 2; printf 'q') | script -qec "bun app.ts" /dev/null
127
+ ```
128
+
129
+ Using the Linux syntax on macOS (`script -q bun app.ts`) does not run your
130
+ app — it clobbers a file literally named `bun` with the session transcript
131
+ and drops you into an interactive shell.
132
+
133
+ A copy-paste PTY smoke test (spawn, send a key, assert clean exit):
134
+
135
+ ```typescript
136
+ // pty-test.ts — bun pty-test.ts
137
+ const proc = Bun.spawn(
138
+ ['script', '-q', '/dev/null', 'bun', 'app.ts'], // macOS arg order
139
+ { stdin: 'pipe', stdout: 'pipe', stderr: 'inherit' },
140
+ );
141
+ await Bun.sleep(2000); // let it render a few frames
142
+ proc.stdin.write('q'); // your app's quit key
143
+ proc.stdin.end();
144
+ const code = await proc.exited;
145
+ const frames = await new Response(proc.stdout).text();
146
+ if (code !== 0 || !frames.includes('MISSION CONTROL')) process.exit(1);
147
+ console.log('PTY smoke test passed');
148
+ ```
149
+
150
+ For pure rendering checks, skip the PTY entirely: `render(cb, { once:
151
+ true })` draws one frame and returns.
152
+
153
+ ## 🎮 Demos
154
+
155
+ Run a public demo:
156
+
157
+ ```bash
158
+ bun demo 2048
159
+ bun demo showcase
160
+ bun demo animation
161
+ bun demo interaction
162
+ bun demo dashboard
163
+ bun demo engine
164
+ bun demo login
165
+ ```
166
+
167
+ Internal/debug demos are still available by name in the runner, but the public list favors fewer, richer examples.
168
+
71
169
  ## 🛠️ Tooling
72
170
 
73
- ### TSGO (High-Performance TypeScript)
74
- Bunti uses **[tsgo](https://github.com/d-ts/tsgo)** for its type-checking pipeline.
171
+ ### TypeScript
172
+ Bunti uses the standard TypeScript compiler for type checking so local development and GitHub Actions run the same toolchain.
75
173
 
76
- We chose `tsgo` over the standard `tsc` because:
77
- - **Speed**: It leverages a Go-based core to provide near-instant feedback during development.
78
- - **Agent-Friendly**: Its predictable and high-performance output makes it ideal for automated engineering workflows.
79
- - **Strict Integrity**: It ensures that Bunti's functional architecture remains 100% type-safe without the overhead of standard Node-based compilers.
174
+ Run a full check with: `bun run typecheck`
80
175
 
81
- Run a full check with: `npm run type-check`
176
+ Build the published package with:
177
+
178
+ ```bash
179
+ bun run build
180
+ npm pack --dry-run
181
+ ```
82
182
 
83
183
  ## 📚 Documentation
84
184
 
85
- Dive deeper into Bunti's architecture and layout engine:
185
+ Dive deeper into Bunti's architecture and layout engine at
186
+ [zakmandhro.github.io/bunti](https://zakmandhro.github.io/bunti/):
187
+
188
+ - [The Box Model & Layout Math](https://zakmandhro.github.io/bunti/layout.html)
189
+ - [Bunti Components & Primitives](https://zakmandhro.github.io/bunti/components.html)
190
+ - [Theming & Colors](https://zakmandhro.github.io/bunti/theming.html)
191
+ - [Animations & Canvas](https://zakmandhro.github.io/bunti/animations.html)
192
+ - [Engine & Utilities](https://zakmandhro.github.io/bunti/engine.html)
193
+ - [Bunti vs. The TUI Ecosystem](https://zakmandhro.github.io/bunti/comparison.html)
86
194
 
87
- - [The Box Model & Layout Math](./docs/layout.md)
88
- - [Bunti Components & Primitives](./docs/components.md)
89
- - [Bunti vs. The TUI Ecosystem](./docs/comparison.md)
195
+ The package also ships [`AGENTS.md`](./AGENTS.md) (agent playbook) and
196
+ [`llms.txt`](./llms.txt) (compact API reference, generated from the JSDoc
197
+ by `bun scripts/gen-llms.ts`) — the full documented API lives in the
198
+ shipped `dist/*.d.ts`.
90
199
 
91
200
  ## 🤝 Contributing
92
201
 
@@ -96,6 +205,8 @@ Contributions are welcome! Please feel free to submit a Pull Request. Since Bunt
96
205
  bun run lint
97
206
  bun run typecheck
98
207
  bun run test
208
+ bun run build
209
+ npm pack --dry-run
99
210
  bun run bench
100
211
  ```
101
212
 
package/dist/cli.d.ts ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * The `bunti` CLI — the zero-install front door:
4
+ *
5
+ * bunx @zakmandhro/bunti demo list the public demos
6
+ * bunx @zakmandhro/bunti demo mission-control run one
7
+ * bunx @zakmandhro/bunti doctor terminal capability report
8
+ * bunx @zakmandhro/bunti --version
9
+ *
10
+ * Demos are plain Bun-runnable TypeScript copied into dist/demos/ at build
11
+ * time (see scripts/build-demos.ts); `demo <name>` simply imports one, which
12
+ * starts its render loop in-process.
13
+ */
14
+ import { type ColorTier, type TerminalProfile } from './detect';
15
+ export type CliCommand = {
16
+ cmd: 'help';
17
+ } | {
18
+ cmd: 'version';
19
+ } | {
20
+ cmd: 'doctor';
21
+ } | {
22
+ cmd: 'list-demos';
23
+ } | {
24
+ cmd: 'run-demo';
25
+ name: string;
26
+ } | {
27
+ cmd: 'unknown-demo';
28
+ name: string;
29
+ } | {
30
+ cmd: 'unknown';
31
+ arg: string;
32
+ };
33
+ /** Pure argv parser (argv excludes the runtime + script entries). */
34
+ export declare function parseCliArgs(argv: string[]): CliCommand;
35
+ /** `name description` listing lines for the public demos. */
36
+ export declare function demoListLines(): string[];
37
+ export declare function helpText(version: string): string;
38
+ /**
39
+ * The `bunti doctor` report: env-detected terminal profile, color tier, and
40
+ * the Nerd Font policy driving the icon engine. Pure function of its inputs
41
+ * so tests can pin the exact shape.
42
+ */
43
+ export declare function doctorReport(profile: TerminalProfile, tier: ColorTier, version: string, bunVersion: string): string[];
44
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;GAWG;AAGH,OAAO,EACL,KAAK,SAAS,EAGd,KAAK,eAAe,EACrB,MAAM,UAAU,CAAC;AAElB,MAAM,MAAM,UAAU,GAClB;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GACf;IAAE,GAAG,EAAE,SAAS,CAAA;CAAE,GAClB;IAAE,GAAG,EAAE,QAAQ,CAAA;CAAE,GACjB;IAAE,GAAG,EAAE,YAAY,CAAA;CAAE,GACrB;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,GAAG,EAAE,cAAc,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACrC;IAAE,GAAG,EAAE,SAAS,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpC,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAoBvD;AAED,8DAA8D;AAC9D,wBAAgB,aAAa,IAAI,MAAM,EAAE,CAGxC;AAED,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAehD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,eAAe,EACxB,IAAI,EAAE,SAAS,EACf,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,GACjB,MAAM,EAAE,CAgCV"}
package/dist/cli.js ADDED
@@ -0,0 +1,147 @@
1
+ #!/usr/bin/env bun
2
+ /**
3
+ * The `bunti` CLI — the zero-install front door:
4
+ *
5
+ * bunx @zakmandhro/bunti demo list the public demos
6
+ * bunx @zakmandhro/bunti demo mission-control run one
7
+ * bunx @zakmandhro/bunti doctor terminal capability report
8
+ * bunx @zakmandhro/bunti --version
9
+ *
10
+ * Demos are plain Bun-runnable TypeScript copied into dist/demos/ at build
11
+ * time (see scripts/build-demos.ts); `demo <name>` simply imports one, which
12
+ * starts its render loop in-process.
13
+ */
14
+ import { findDemo, PUBLIC_DEMOS } from './demo-registry';
15
+ import { detectColorTier, identifyTerminal, } from './detect';
16
+ /** Pure argv parser (argv excludes the runtime + script entries). */
17
+ export function parseCliArgs(argv) {
18
+ const [first, second] = argv;
19
+ if (first === undefined ||
20
+ first === 'help' ||
21
+ first === '--help' ||
22
+ first === '-h') {
23
+ return { cmd: 'help' };
24
+ }
25
+ if (first === 'version' || first === '--version' || first === '-v') {
26
+ return { cmd: 'version' };
27
+ }
28
+ if (first === 'doctor')
29
+ return { cmd: 'doctor' };
30
+ if (first === 'demo') {
31
+ if (second === undefined)
32
+ return { cmd: 'list-demos' };
33
+ if (findDemo(second))
34
+ return { cmd: 'run-demo', name: second };
35
+ return { cmd: 'unknown-demo', name: second };
36
+ }
37
+ return { cmd: 'unknown', arg: first };
38
+ }
39
+ /** `name description` listing lines for the public demos. */
40
+ export function demoListLines() {
41
+ const pad = Math.max(...PUBLIC_DEMOS.map((d) => d.name.length)) + 2;
42
+ return PUBLIC_DEMOS.map((d) => ` ${d.name.padEnd(pad)}${d.description}`);
43
+ }
44
+ export function helpText(version) {
45
+ return [
46
+ `bunti v${version} — Bun-native terminal UI engine`,
47
+ '',
48
+ 'Usage:',
49
+ ' bunti demo list the public demos',
50
+ ' bunti demo <name> run a demo',
51
+ ' bunti doctor terminal capability report',
52
+ ' bunti --version print the version',
53
+ '',
54
+ 'Demos:',
55
+ ...demoListLines(),
56
+ '',
57
+ 'Zero-install: bunx @zakmandhro/bunti demo mission-control',
58
+ ].join('\n');
59
+ }
60
+ /**
61
+ * The `bunti doctor` report: env-detected terminal profile, color tier, and
62
+ * the Nerd Font policy driving the icon engine. Pure function of its inputs
63
+ * so tests can pin the exact shape.
64
+ */
65
+ export function doctorReport(profile, tier, version, bunVersion) {
66
+ const terminal = profile.app === 'unknown'
67
+ ? 'unknown'
68
+ : `${profile.app}${profile.version ? ` ${profile.version}` : ''}`;
69
+ const tierLabel = tier === 'truecolor'
70
+ ? 'truecolor (24-bit)'
71
+ : tier === '256'
72
+ ? '256 colors'
73
+ : tier === '16'
74
+ ? '16 colors'
75
+ : 'monochrome';
76
+ const nf = {
77
+ yes: 'yes - glyphs enabled',
78
+ 'assumed-yes': 'assumed yes - glyphs enabled',
79
+ 'assumed-no': 'assumed no - ascii fallback',
80
+ no: 'no - ascii fallback',
81
+ };
82
+ const lines = [
83
+ `bunti v${version} (bun ${bunVersion})`,
84
+ `terminal ${terminal}`,
85
+ ];
86
+ if (profile.multiplexer)
87
+ lines.push(`multiplexer ${profile.multiplexer}`);
88
+ lines.push(`colors ${tierLabel}`, `sync output ${profile.syncOutput ? 'yes (mode 2026)' : 'no'}`, `nerd font ${nf[profile.nerdFont]}${profile.source === 'override' ? ' (env override)' : ''}`);
89
+ return lines;
90
+ }
91
+ async function packageVersion() {
92
+ try {
93
+ const pkg = await Bun.file(new URL('../package.json', import.meta.url)).json();
94
+ return typeof pkg.version === 'string' ? pkg.version : 'unknown';
95
+ }
96
+ catch {
97
+ return 'unknown';
98
+ }
99
+ }
100
+ async function runDemo(file) {
101
+ // Published layout: dist/cli.js + dist/demos/*.ts. Dev layout (running
102
+ // src/cli.ts directly): ../demo/*.ts. Prefer the packaged copy.
103
+ const packaged = new URL(`./demos/${file}`, import.meta.url);
104
+ const dev = new URL(`../demo/${file}`, import.meta.url);
105
+ const target = (await Bun.file(packaged).exists()) ? packaged : dev;
106
+ await import(target.href);
107
+ }
108
+ async function main() {
109
+ const command = parseCliArgs(process.argv.slice(2));
110
+ switch (command.cmd) {
111
+ case 'help':
112
+ console.log(helpText(await packageVersion()));
113
+ return;
114
+ case 'version':
115
+ console.log(await packageVersion());
116
+ return;
117
+ case 'doctor': {
118
+ const report = doctorReport(identifyTerminal(), detectColorTier(), await packageVersion(), Bun.version);
119
+ console.log(report.join('\n'));
120
+ return;
121
+ }
122
+ case 'list-demos':
123
+ console.log('Public demos:\n');
124
+ console.log(demoListLines().join('\n'));
125
+ console.log('\nRun one: bunti demo <name>');
126
+ return;
127
+ case 'run-demo': {
128
+ const entry = findDemo(command.name);
129
+ if (entry)
130
+ await runDemo(entry.file);
131
+ return;
132
+ }
133
+ case 'unknown-demo':
134
+ console.error(`Unknown demo "${command.name}". Available demos:\n`);
135
+ console.error(demoListLines().join('\n'));
136
+ process.exitCode = 1;
137
+ return;
138
+ case 'unknown':
139
+ console.error(`Unknown command "${command.arg}". Try: bunti --help`);
140
+ process.exitCode = 1;
141
+ return;
142
+ }
143
+ }
144
+ if (import.meta.main) {
145
+ await main();
146
+ }
147
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Bunti Semantic & Palette Color System
3
+ */
4
+ import type { RGB } from './state';
5
+ import type { ThemeColor } from './theme';
6
+ /**
7
+ * A resolved multi-stop gradient, accepted anywhere bgColor is (rect fills,
8
+ * box backgrounds, wallpaper). Build one with ctx.gradient().
9
+ */
10
+ export interface Gradient {
11
+ /** Interpolated RGB stops, one per step. */
12
+ colors: RGB[];
13
+ /** Axis the stops sweep along. */
14
+ direction: 'vertical' | 'horizontal';
15
+ /** Number of interpolated stops. */
16
+ steps: number;
17
+ }
18
+ /**
19
+ * Any value Bunti accepts where a color is expected.
20
+ */
21
+ export type ColorValue = string | number | RGB | ThemeColor;
22
+ /**
23
+ * Internal brand carried by ThemeColor instances so callable theme tokens can
24
+ * be distinguished from plain function-style border wrappers.
25
+ */
26
+ export declare const THEME_COLOR: unique symbol;
27
+ /**
28
+ * Returns true when the value is a ThemeColor (callable fg-styler carrying
29
+ * `.rgb` and `.hex`), detected via the internal brand symbol.
30
+ */
31
+ export declare function isThemeColor(value: unknown): value is ThemeColor;
32
+ /**
33
+ * Bunti's named color palette (ANSI-256 codes). Any name here works as a
34
+ * color value: `fg('bunti-blue', text)`, `{ bgColor: 'midnight' }`.
35
+ */
36
+ export declare const PALETTE: {
37
+ readonly slate: "235";
38
+ readonly ash: "240";
39
+ readonly gray: "244";
40
+ readonly silver: "247";
41
+ readonly white: "255";
42
+ readonly black: "0";
43
+ readonly midnight: "17";
44
+ readonly ocean: "24";
45
+ readonly sky: "33";
46
+ readonly 'bunti-blue': "38";
47
+ readonly 'deep-navy': "17";
48
+ readonly nebula: "61";
49
+ readonly plasma: "165";
50
+ readonly success: "40";
51
+ readonly warning: "214";
52
+ readonly error: "196";
53
+ readonly info: "39";
54
+ readonly gold: "220";
55
+ readonly rose: "211";
56
+ readonly mint: "121";
57
+ };
58
+ export type PaletteColor = keyof typeof PALETTE;
59
+ /**
60
+ * Parses a hex color string (#RGB, #RGBA, #RRGGBB, or #RRGGBBAA) to an RGB
61
+ * object. Alpha channels are composited over `base` (defaults to black), so
62
+ * `#ffffff80` over black resolves to mid-gray.
63
+ */
64
+ export declare function hexToRGB(hex: string, base?: RGB): RGB;
65
+ /**
66
+ * Formats an RGB object as a #rrggbb hex string.
67
+ */
68
+ export declare function rgbToHex(rgb: RGB): string;
69
+ /**
70
+ * Converts an ANSI-256 code to its exact xterm RGB value
71
+ * (16 base + 6x6x6 color cube + 24-step gray ramp).
72
+ */
73
+ export declare function ansi256ToRGB(code: number): RGB;
74
+ /**
75
+ * Quantizes an RGB value to the nearest ANSI-256 code
76
+ * (best of the 6x6x6 cube vs the gray ramp).
77
+ */
78
+ export declare function rgbTo256(rgb: RGB): number;
79
+ /**
80
+ * Quantizes an RGB value to the nearest of the 16 base ANSI colors.
81
+ */
82
+ export declare function rgbTo16(rgb: RGB): number;
83
+ /**
84
+ * Resolves a palette name, color code, RGB object, or ThemeColor to an ANSI
85
+ * color code, quantized to the active color tier. Returns undefined on the
86
+ * 'mono' tier (NO_COLOR), which suppresses color output entirely.
87
+ */
88
+ export declare function resolveColor(color: PaletteColor | ColorValue): string | number | undefined;
89
+ /**
90
+ * Creates a multi-stop gradient (array of RGB objects) between multiple colors.
91
+ */
92
+ export declare function createGradient(arg1: ColorValue[] | ColorValue, arg2?: ColorValue | number, arg3?: number): RGB[];
93
+ /**
94
+ * Resolves any color value (name, hex, ANSI-256 code, RGB, ThemeColor) to an
95
+ * exact RGB object. Numeric codes use the exact xterm 256-color table.
96
+ */
97
+ export declare function resolveColorToRGB(color: unknown): RGB;
98
+ /**
99
+ * WCAG 2.x relative luminance (0 = black, 1 = white) of any color value.
100
+ */
101
+ export declare function relativeLuminance(color: ColorValue): number;
102
+ /**
103
+ * Picks pure black or pure white text for maximum WCAG contrast against the
104
+ * given background color. (White wins below luminance ~0.179, the point where
105
+ * both contrast ratios are equal.)
106
+ */
107
+ export declare function contrastText(bgColor: ColorValue): RGB;
108
+ /**
109
+ * Adjusts the brightness of a color.
110
+ */
111
+ export declare function adjustBrightness(color: any, amount: number): RGB;
112
+ /**
113
+ * Interpolates between two colors and returns an RGB value.
114
+ */
115
+ export declare function fade(from: ColorValue, to: ColorValue, progress: number): RGB;
116
+ /**
117
+ * Returns a function that darkens a color and can be used as a style wrapper.
118
+ */
119
+ export declare function darken(color: any, amount?: number): (text: string) => string;
120
+ /**
121
+ * Returns a function that lightens a color and can be used as a style wrapper.
122
+ */
123
+ export declare function lighten(color: any, amount?: number): (text: string) => string;
124
+ /**
125
+ * Returns an RGB object for TrueColor rendering.
126
+ */
127
+ export declare function rgb(r: number, g: number, b: number): {
128
+ r: number;
129
+ g: number;
130
+ b: number;
131
+ };
132
+ /**
133
+ * Wraps text in a foreground-color ANSI sequence (any color value:
134
+ * palette name, hex, ANSI-256 code, RGB, ThemeColor). On the 'mono' tier
135
+ * the text is returned unstyled.
136
+ * @example fg('#3bbce1', 'hello') // truecolor cyan text
137
+ */
138
+ export declare function fg(color: any, text: string): string;
139
+ /**
140
+ * Wraps text in a background-color ANSI sequence (any color value). On the
141
+ * 'mono' tier the text is returned unstyled.
142
+ */
143
+ export declare function bg(color: any, text: string): string;
144
+ //# sourceMappingURL=colors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"colors.d.ts","sourceRoot":"","sources":["../src/colors.ts"],"names":[],"mappings":"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"}