@svelterm/core 0.1.0 → 0.23.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 (166) hide show
  1. package/CHANGELOG.md +465 -0
  2. package/README.md +42 -29
  3. package/dist/src/cli/build.d.ts +13 -0
  4. package/dist/src/cli/build.js +119 -0
  5. package/dist/src/cli/bundle.d.ts +25 -0
  6. package/dist/src/cli/bundle.js +61 -0
  7. package/dist/src/cli/dev.d.ts +10 -0
  8. package/dist/src/cli/dev.js +152 -0
  9. package/dist/src/cli/devtools.d.ts +9 -0
  10. package/dist/src/cli/devtools.js +47 -0
  11. package/dist/src/cli/init.d.ts +8 -0
  12. package/dist/src/cli/init.js +153 -0
  13. package/dist/src/cli/main.d.ts +9 -0
  14. package/dist/src/cli/main.js +52 -0
  15. package/dist/src/cli/svt-bin.d.ts +2 -0
  16. package/dist/src/cli/svt-bin.js +6 -0
  17. package/dist/src/cli/svt.d.ts +14 -0
  18. package/dist/src/cli/svt.js +76 -0
  19. package/dist/src/components/text-buffer.js +8 -5
  20. package/dist/src/css/animation-runner.d.ts +15 -6
  21. package/dist/src/css/animation-runner.js +80 -29
  22. package/dist/src/css/animation.d.ts +12 -0
  23. package/dist/src/css/animation.js +21 -0
  24. package/dist/src/css/calc.js +4 -3
  25. package/dist/src/css/color.d.ts +19 -0
  26. package/dist/src/css/color.js +371 -62
  27. package/dist/src/css/compute.d.ts +31 -4
  28. package/dist/src/css/compute.js +273 -34
  29. package/dist/src/css/defaults.d.ts +1 -1
  30. package/dist/src/css/defaults.js +9 -0
  31. package/dist/src/css/easing.d.ts +9 -0
  32. package/dist/src/css/easing.js +95 -0
  33. package/dist/src/css/incremental.d.ts +1 -1
  34. package/dist/src/css/incremental.js +2 -2
  35. package/dist/src/css/interpolate.d.ts +13 -0
  36. package/dist/src/css/interpolate.js +41 -0
  37. package/dist/src/css/parser.js +59 -3
  38. package/dist/src/css/pseudo-elements.d.ts +9 -0
  39. package/dist/src/css/pseudo-elements.js +97 -0
  40. package/dist/src/css/selector.d.ts +17 -2
  41. package/dist/src/css/selector.js +128 -13
  42. package/dist/src/css/specificity.js +17 -6
  43. package/dist/src/css/values.d.ts +6 -1
  44. package/dist/src/css/values.js +13 -6
  45. package/dist/src/debug/context.d.ts +13 -0
  46. package/dist/src/debug/context.js +11 -0
  47. package/dist/src/debug/css.d.ts +12 -0
  48. package/dist/src/debug/css.js +28 -0
  49. package/dist/src/debug/dom.d.ts +17 -0
  50. package/dist/src/debug/dom.js +92 -0
  51. package/dist/src/devtools/DevTools.compiled.js +327 -0
  52. package/dist/src/devtools/DevTools.css.js +1 -0
  53. package/dist/src/devtools/client.d.ts +36 -0
  54. package/dist/src/devtools/client.js +76 -0
  55. package/dist/src/framelog.d.ts +54 -0
  56. package/dist/src/framelog.js +99 -0
  57. package/dist/src/headless.js +12 -4
  58. package/dist/src/index.d.ts +66 -3
  59. package/dist/src/index.js +610 -81
  60. package/dist/src/input/checkable.d.ts +8 -0
  61. package/dist/src/input/checkable.js +66 -0
  62. package/dist/src/input/details.d.ts +6 -0
  63. package/dist/src/input/details.js +34 -0
  64. package/dist/src/input/focus.d.ts +6 -0
  65. package/dist/src/input/focus.js +27 -9
  66. package/dist/src/input/keyboard.d.ts +2 -2
  67. package/dist/src/input/keyboard.js +32 -5
  68. package/dist/src/input/label.d.ts +8 -0
  69. package/dist/src/input/label.js +53 -0
  70. package/dist/src/input/modal.d.ts +9 -0
  71. package/dist/src/input/modal.js +28 -0
  72. package/dist/src/input/mouse.d.ts +2 -2
  73. package/dist/src/input/mouse.js +15 -2
  74. package/dist/src/input/select.d.ts +12 -0
  75. package/dist/src/input/select.js +63 -0
  76. package/dist/src/input/selection.d.ts +48 -0
  77. package/dist/src/input/selection.js +150 -0
  78. package/dist/src/layout/engine.d.ts +2 -0
  79. package/dist/src/layout/engine.js +1092 -142
  80. package/dist/src/layout/flex.js +4 -4
  81. package/dist/src/layout/size.js +3 -2
  82. package/dist/src/layout/text.d.ts +3 -2
  83. package/dist/src/layout/text.js +96 -17
  84. package/dist/src/layout/unicode.d.ts +20 -0
  85. package/dist/src/layout/unicode.js +121 -0
  86. package/dist/src/render/animation-clock.d.ts +57 -0
  87. package/dist/src/render/animation-clock.js +221 -0
  88. package/dist/src/render/ansi-text.d.ts +26 -0
  89. package/dist/src/render/ansi-text.js +131 -0
  90. package/dist/src/render/ansi.d.ts +18 -0
  91. package/dist/src/render/ansi.js +64 -19
  92. package/dist/src/render/border.js +166 -17
  93. package/dist/src/render/buffer.d.ts +1 -0
  94. package/dist/src/render/buffer.js +5 -2
  95. package/dist/src/render/clock.d.ts +35 -0
  96. package/dist/src/render/clock.js +67 -0
  97. package/dist/src/render/color-depth.d.ts +8 -0
  98. package/dist/src/render/color-depth.js +59 -0
  99. package/dist/src/render/context.d.ts +1 -0
  100. package/dist/src/render/context.js +17 -21
  101. package/dist/src/render/cursor-emit.d.ts +18 -0
  102. package/dist/src/render/cursor-emit.js +50 -0
  103. package/dist/src/render/diff.d.ts +12 -0
  104. package/dist/src/render/diff.js +120 -0
  105. package/dist/src/render/generation.d.ts +9 -0
  106. package/dist/src/render/generation.js +14 -0
  107. package/dist/src/render/graphics-layer.d.ts +27 -0
  108. package/dist/src/render/graphics-layer.js +86 -0
  109. package/dist/src/render/image.d.ts +27 -0
  110. package/dist/src/render/image.js +113 -0
  111. package/dist/src/render/incremental-paint.d.ts +7 -3
  112. package/dist/src/render/incremental-paint.js +52 -79
  113. package/dist/src/render/inline.d.ts +59 -0
  114. package/dist/src/render/inline.js +219 -0
  115. package/dist/src/render/kitty-graphics.d.ts +24 -0
  116. package/dist/src/render/kitty-graphics.js +58 -0
  117. package/dist/src/render/paint-text.js +68 -22
  118. package/dist/src/render/paint.d.ts +8 -1
  119. package/dist/src/render/paint.js +358 -31
  120. package/dist/src/render/png.d.ts +13 -0
  121. package/dist/src/render/png.js +145 -0
  122. package/dist/src/render/scrollbar.d.ts +8 -2
  123. package/dist/src/render/scrollbar.js +71 -14
  124. package/dist/src/render/snapshot.js +3 -1
  125. package/dist/src/renderer/default.d.ts +7 -0
  126. package/dist/src/renderer/default.js +11 -0
  127. package/dist/src/renderer/index.d.ts +8 -2
  128. package/dist/src/renderer/index.js +4 -2
  129. package/dist/src/renderer/node.d.ts +109 -0
  130. package/dist/src/renderer/node.js +165 -1
  131. package/dist/src/terminal/capabilities.d.ts +33 -0
  132. package/dist/src/terminal/capabilities.js +66 -0
  133. package/dist/src/terminal/clipboard.d.ts +9 -0
  134. package/dist/src/terminal/clipboard.js +39 -0
  135. package/dist/src/terminal/io.d.ts +82 -0
  136. package/dist/src/terminal/io.js +155 -0
  137. package/dist/src/terminal/screen.d.ts +3 -10
  138. package/dist/src/terminal/screen.js +5 -28
  139. package/dist/src/terminal/stdin-router.d.ts +8 -5
  140. package/dist/src/terminal/stdin-router.js +22 -11
  141. package/dist/src/utils/node-map.d.ts +24 -0
  142. package/dist/src/utils/node-map.js +75 -0
  143. package/dist/src/vite/config.d.ts +62 -0
  144. package/dist/src/vite/config.js +191 -0
  145. package/docs/compatibility.md +67 -0
  146. package/docs/debug/devtools.md +40 -0
  147. package/docs/debug/svt.md +50 -0
  148. package/docs/distribution.md +106 -0
  149. package/docs/elements.md +120 -0
  150. package/docs/getting-started.md +177 -0
  151. package/docs/guide/css.md +187 -0
  152. package/docs/guide/input.md +143 -0
  153. package/docs/guide/layout.md +171 -0
  154. package/docs/guide/theming.md +94 -0
  155. package/docs/how-it-works.md +115 -0
  156. package/docs/inline-mode.md +77 -0
  157. package/docs/layout.md +112 -0
  158. package/docs/motion.md +91 -0
  159. package/docs/reference/README.md +65 -0
  160. package/docs/reference/css/properties/border-corner.md +82 -0
  161. package/docs/reference/css/properties/border-style.md +168 -0
  162. package/docs/reference.md +227 -0
  163. package/docs/selectors.md +80 -0
  164. package/docs/terminal-css.md +149 -0
  165. package/docs/terminals.md +83 -0
  166. package/package.json +28 -7
package/CHANGELOG.md ADDED
@@ -0,0 +1,465 @@
1
+ # Changelog
2
+
3
+ ## 0.23.0 — 2026-07-05
4
+
5
+ Positioning: `relative` offsets apply, and `sticky` arrives.
6
+
7
+ ### Added
8
+
9
+ - **`position: relative`** — `top/right/bottom/left` now shift the box
10
+ and its descendants visually while flow position and size behave as if
11
+ unshifted, per spec (previously parsed and dropped).
12
+ - **`position: sticky`** (top edge) — inside a scroll container the
13
+ element pins to the container top + `top` once scrolled past, painting
14
+ above in-flow content; descendants move with it. Deviations
15
+ (documented): top-only, no push-out at the containing-block end, and
16
+ hit-testing targets the flow position.
17
+
18
+ ### Fixed
19
+
20
+ - **Opaque backgrounds now cover what's beneath** — an element's
21
+ background fill previously kept stale glyphs from earlier paints, so
22
+ overlapping paints (sticky, absolute) showed old content through the
23
+ background. Fills now clear covered cells.
24
+
25
+ ## 0.22.0 — 2026-07-05
26
+
27
+ ### Added
28
+
29
+ - **`Clock` seam for deterministic animation tests** — the animation
30
+ engine's time source *and* its frame scheduler now go through a
31
+ `Clock` interface. `TestClock` (exported) lets tests set time and
32
+ advance it, firing the frame timer at each tick — so the animation and
33
+ transition frame lifecycle is exact, not `setInterval`/`Date.now`
34
+ dependent. `run()` uses the real `systemClock` by default.
35
+
36
+ ### Fixed
37
+
38
+ - **Docs: `<img>` rendering** — `reference.md` still listed `img` as
39
+ "not rendered", and `elements.md`'s intro contradicted its own Images
40
+ section. Both now describe the half-block + kitty-graphics rendering
41
+ shipped in 0.15.0 / 0.19.0.
42
+
43
+ ## 0.21.0 — 2026-07-05
44
+
45
+ DevTools polish.
46
+
47
+ ### Changed
48
+
49
+ - **Collapsible tree** — ← / → (or Enter) fold and unfold subtrees in
50
+ `svelterm devtools`; nodes with children show a ▸/▾ marker.
51
+ - **Fuller style panel** — the selected node's panel now lists every
52
+ non-default resolved value, instead of a fixed subset of keys.
53
+ - **Clearer connect error** — `svt` and `devtools` both name the exact
54
+ call to enable debugging (`run(App, { debug: true })`) when they can't
55
+ reach a server.
56
+
57
+ ## 0.20.0 — 2026-07-05
58
+
59
+ DevTools: a terminal inspector, itself a svelterm app.
60
+
61
+ ### Added
62
+
63
+ - **`svelterm devtools`** — connects to a `run(App, { debug: true })`
64
+ app's debug server and shows its live node tree (left) with each
65
+ selected node's computed style and layout box (right); ↑/↓ to select,
66
+ r to refresh. Built with svelterm and the DOM/CSS debug domains — it
67
+ dogfoods the renderer it inspects. See `docs/debug/devtools.md`.
68
+ - The DevTools component is precompiled into the package at build time,
69
+ so it runs without a build step in your project.
70
+
71
+ ## 0.19.0 — 2026-07-05
72
+
73
+ Kitty graphics: crisp `<img>` pixels where the terminal supports them.
74
+
75
+ ### Added
76
+
77
+ - **Kitty graphics protocol** — on kitty, Ghostty, and WezTerm (detected
78
+ via XTVERSION), `<img>` transmits real RGBA pixels scaled to its cell
79
+ box instead of half-blocks. Pixel data transmits once per (element,
80
+ src); each frame re-places over the box and deletes placements for
81
+ images that moved, scrolled away, or unmounted; teardown and suspend
82
+ clear them. Half-blocks stay the buffer fallback everywhere else.
83
+
84
+ ## 0.18.0 — 2026-07-04
85
+
86
+ Scroll-region diffing, and a border-clip fix found along the way.
87
+
88
+ ### Added
89
+
90
+ - **DECSTBM scroll diffing** — when a repaint is a clean vertical
91
+ translation of the previous frame (a full-viewport scroll), the diff
92
+ emits a scroll-region command + index/reverse-index and paints only
93
+ the newly revealed rows, instead of rewriting the screen. ~13× less
94
+ output on an 80×40 one-line scroll (`scripts/bench-scroll-bytes.mjs`).
95
+ Falls back to the normal cell diff for any non-translation change.
96
+
97
+ ### Fixed
98
+
99
+ - **Scrolled content painted over borders** — a bordered
100
+ `overflow: auto`/`scroll` box clipped its children to the box
101
+ *including* the border cells, so scrolled content overwrote the top
102
+ and bottom border rows. The clip now insets by the border. (Regression
103
+ from 0.13.0's virtual scrolling.)
104
+
105
+ ## 0.17.0 — 2026-07-04
106
+
107
+ Debug tooling: a minimal DevTools for terminal apps.
108
+
109
+ ### Added
110
+
111
+ - **DOM and CSS debug domains** — over the existing (opt-in) debug
112
+ WebSocket server: `DOM.getDocument` serialises the live node tree,
113
+ `DOM.querySelector` finds nodes by selector, `DOM.getBoxModel` reports
114
+ layout, `DOM.setAttribute`/`removeAttribute` mutate and repaint;
115
+ `CSS.getComputedStyle` returns the resolved style svelterm painted.
116
+ - **`svt` CLI** (`svelterm inspect`) — a client for the protocol:
117
+ `svt tree | query <sel> | style <id> | box <id> | console | raw`,
118
+ JSON on stdout for `jq`. Point it at a `run(App, { debug: true })`
119
+ app.
120
+
121
+ ## 0.16.0 — 2026-07-04
122
+
123
+ ### Fixed
124
+
125
+ - **`svelterm build` with symlinked component libraries** — a library
126
+ installed via `file:`/`link:` (e.g. a local `@svelterm/ui`) resolves
127
+ its imports from its real path, where the app's `node_modules` isn't
128
+ visible, so `@svelterm/core` and `svelte` failed to resolve. The
129
+ bundler now pins those packages to the project's own installation.
130
+
131
+ ## 0.15.0 — 2026-07-04
132
+
133
+ Images: `<img>` on the cell grid.
134
+
135
+ ### Added
136
+
137
+ - **`<img>`** — renders as half-blocks (two pixels per cell) from file
138
+ paths or `data:image/png;base64` URIs. PNG decoding (8-bit
139
+ RGB/RGBA/greyscale/palette) is built in with no dependencies, via
140
+ `node:zlib`. Intrinsic size is 1 column per pixel and 1 row per two;
141
+ CSS `width`/`height` scale nearest-neighbour. Loading is async — the
142
+ layout reflows when pixels arrive; transparent pixels show the
143
+ terminal background. (Kitty graphics passthrough is deliberately not
144
+ included yet — half-blocks work everywhere.)
145
+
146
+ ## 0.14.0 — 2026-07-04
147
+
148
+ Inline-mode maturity: the mouse works in the live area.
149
+
150
+ ### Added
151
+
152
+ - **Inline-mode mouse** — the zone's screen origin comes from a CPR
153
+ (cursor position report) query, snapshotted as the query bytes go out,
154
+ shifted as frames archive, and clamped when growth scrolls the zone.
155
+ Mouse coordinates map through it; clicks on shell history are ignored.
156
+ Origins re-query after resize and suspend/resume.
157
+ - **Playground example** — `inline mode` example with a `svelterm:inline`
158
+ marker that the site preview and the `run/*.mjs` bundles honour.
159
+
160
+ ### Fixed
161
+
162
+ - An explicit `mode` now wins over the `fullscreen` flag —
163
+ `mode: 'fullscreen', fullscreen: false` is full-viewport rendering
164
+ without the alternate screen again (embedded previews), instead of
165
+ being forced inline.
166
+
167
+ ## 0.13.0 — 2026-07-04
168
+
169
+ Virtual scrolling: long lists repaint at the speed of what's visible.
170
+
171
+ ### Changed
172
+
173
+ - **Paint culling** — subtrees fully outside the active clip are skipped
174
+ in the paint walk (cell writes were already clipped, so output is
175
+ identical). A 10,000-row `overflow: scroll` list drops from ~228 ms to
176
+ ~1.4 ms per scroll repaint on the benchmark machine
177
+ (`scripts/bench-scroll.mjs`); first paint from ~254 ms to ~5 ms.
178
+ - **Scrollbar extent caching** — the content-size walk behind scrollbar
179
+ overlays is memoized per layout, instead of re-walking every child on
180
+ every frame of the fade.
181
+
182
+ ### Fixed
183
+
184
+ - A focused input culled offscreen no longer reports a stale cursor
185
+ position — cursor positions carry the paint generation that wrote
186
+ them, and the terminal cursor hides when its owner leaves the
187
+ viewport.
188
+
189
+ ## 0.12.0 — 2026-07-04
190
+
191
+ Terminal matrix evidence: proof the emitted bytes work, per terminal
192
+ class.
193
+
194
+ ### Added
195
+
196
+ - **Round-trip test suite** — svelterm's emitted ANSI (full frames,
197
+ incremental diffs, the inline live zone) replays through a terminal
198
+ model in CI and must reproduce the exact cell grid, at every colour
199
+ depth (truecolor / 256 / 16 / mono) and with wide glyphs.
200
+ - **Support matrix** in `docs/terminals.md` — verified vs expected vs
201
+ unknown, per terminal, with the capability columns that matter
202
+ (truecolor, DEC 2026, kitty keys, OSC 52).
203
+
204
+ ## 0.11.0 — 2026-07-04
205
+
206
+ Unicode correctness: non-Latin text stops breaking layout.
207
+
208
+ ### Fixed
209
+
210
+ - **Cell widths** — text measurement previously assumed one JavaScript
211
+ character = one terminal cell, so CJK, fullwidth forms, and emoji
212
+ misaligned borders, wrapping, and diffs. Layout, paint, truncation,
213
+ and the inline renderer now work in grapheme clusters with East Asian
214
+ Width cell widths; wide glyphs own a continuation cell that diff
215
+ emission skips.
216
+ - **Input editing** — cursor movement, backspace, and delete operate on
217
+ grapheme boundaries (arrow keys no longer split surrogate pairs or ZWJ
218
+ emoji); the terminal cursor position accounts for wide glyphs.
219
+
220
+ ## 0.10.0 — 2026-07-04
221
+
222
+ Colour blending: real alpha compositing on the cell grid.
223
+
224
+ ### Added
225
+
226
+ - **Alpha colours** — `rgba()`, `hsl(... / a)`, `#rrggbbaa` keep their
227
+ alpha and composite over whatever the cell already holds at paint
228
+ time. Blending over ANSI names uses nominal xterm values; over the
229
+ terminal's default background it assumes black.
230
+ - **Numeric `opacity`** — folds into the element's colours as a blend
231
+ factor (previously any `opacity < 1` just set the dim attribute; the
232
+ non-standard `opacity: dim` still does).
233
+
234
+ ## 0.9.0 — 2026-07-04
235
+
236
+ Text & content: wrapping control, path-friendly truncation, and raw
237
+ ANSI passthrough.
238
+
239
+ ### Added
240
+
241
+ - **`word-break: break-all`** — wrap at any character (URLs, hashes,
242
+ paths) instead of only at spaces; inherits as in CSS and applies in
243
+ both layout and paint.
244
+ - **`text-overflow: ellipsis-middle`** — the parsed-but-unwired middle
245
+ truncation now paints: `/Users/tom/…/index.ts` style, keeping both
246
+ ends of long paths.
247
+ - **`<svt-ansi>`** — raw ANSI passthrough element: pre-styled output
248
+ (git diff, ls --color, build logs) renders with its own SGR colours
249
+ (16/256/truecolor + attributes); non-SGR sequences are stripped,
250
+ content is `pre`-formatted.
251
+
252
+ ## 0.8.0 — 2026-07-04
253
+
254
+ Input completeness: modern key reporting, honest job control, and
255
+ browser-style modals.
256
+
257
+ ### Added
258
+
259
+ - **Kitty keyboard protocol** — CSI u key reports parse with correct
260
+ modifiers (`Ctrl+Enter`, `Shift+Space`, …); the protocol is pushed at
261
+ startup and popped on exit and suspend. Terminals without it ignore
262
+ the push and keep the legacy encoding.
263
+ - **Suspend/resume** — `Ctrl+Z` restores the terminal for the shell
264
+ without unmounting; `fg` (SIGCONT) re-enters raw mode, alt screen,
265
+ mouse and keyboard modes, and repaints with component state intact.
266
+ Previously Ctrl+Z tore the app down.
267
+ - **`exitOn` option** — opt into `Ctrl+D` EOF-style exit
268
+ (`run(App, { exitOn: ['ctrl+c', 'ctrl+d'] })`).
269
+ - **Modal `<dialog open>`** — captures keys: Tab/Shift+Tab trap inside
270
+ the dialog, focus pulls in from outside, Escape removes `open` and
271
+ dispatches `close`.
272
+
273
+ ### Fixed
274
+
275
+ - Legacy CSI modifier parsing was off by one — `Shift+Arrow` reported
276
+ as Alt, `Ctrl+Arrow` as Shift+Alt.
277
+
278
+ ## 0.7.0 — 2026-07-04
279
+
280
+ Inline rendering: svelterm apps that live in the main buffer like a
281
+ CLI tool, not a fullscreen TUI.
282
+
283
+ ### Added
284
+
285
+ - **`mode: 'inline'`** — render at the shell cursor: the live area sizes
286
+ to content, updates via cell diffs with relative-only cursor movement
287
+ (LF to grow, erase-below to shrink), and leaves its output in place on
288
+ exit. `fullscreen: false` now routes here too. Mouse reporting is off
289
+ in inline mode (screen-absolute coordinates can't map to an unknown
290
+ origin); keyboard, focus, and the input cursor work as usual.
291
+ - **`FrameLog`** — append-only frame log for streaming sessions:
292
+ `append(Component, props)` / `update` / `archive` / `remove`.
293
+ Archived frames' rows scroll into the terminal's real history
294
+ untouched and their components unmount, so a long session's memory
295
+ tracks the live area, not the transcript. See `docs/inline-mode.md`.
296
+ - **`demo/inline`** — five streaming turns, each archived into
297
+ scrollback (`DEMO=inline npm run demo`).
298
+
299
+ ## 0.6.0 — 2026-07-04
300
+
301
+ Terminal integration: selection, clipboard, and a cursor that reads as
302
+ an insertion point.
303
+
304
+ ### Added
305
+
306
+ - **Text selection** — drag selects a row-major cell range (painted
307
+ inverted), double-click selects the word, triple-click the line.
308
+ Releasing copies the selection; the next click clears it. Works over
309
+ the diff pipeline without repainting the tree.
310
+ - **Clipboard** — selections copy via OSC 52 (in-band, ssh-safe) plus
311
+ the platform tool (`pbcopy`, `wl-copy`/`xclip`, `clip`) when present;
312
+ `copyToClipboard` is exported for apps.
313
+ - **Cursor shape** — a focused `<input>`/`<textarea>` shows a bar cursor
314
+ (DECSCUSR 6); the terminal's configured shape is restored otherwise
315
+ and on exit.
316
+
317
+ ## 0.5.0 — 2026-07-04
318
+
319
+ Terminal robustness: the same app now degrades gracefully from a
320
+ truecolor GPU terminal down to `TERM=xterm` — and respects `NO_COLOR`.
321
+
322
+ ### Added
323
+
324
+ - **Capability detection** — colour depth from
325
+ `NO_COLOR`/`COLORTERM`/`TERM`, plus an XTVERSION query identifying
326
+ known-truecolor terminals; DEC 2026 synchronized-output support probed
327
+ via DECRQM. Detection runs in the background with timeouts; the first
328
+ frame paints with modern defaults and re-paints on a downgrade.
329
+ - **Colour degradation** — hex/RGB colours quantize at emit time: xterm
330
+ 256 cube/grey-ramp on 256-colour terminals, nearest base colour on
331
+ 16-colour terminals, no colour under `NO_COLOR`. ANSI names always
332
+ pass through. Override with `run(App, { colorDepth })`.
333
+ - **Gated synchronized output** — frames wrap in DEC 2026 only when the
334
+ terminal reports the mode (previously sent unconditionally).
335
+ - **`docs/terminals.md`** — what svelterm emits and queries, per depth.
336
+
337
+ ## 0.4.0 — 2026-07-04
338
+
339
+ The developer-experience release: `npx @svelterm/core init` to a running,
340
+ hot-reloading, shippable app in one minute.
341
+
342
+ ### Added
343
+
344
+ - **`svelterm init <dir>`** — scaffold a working project: counter
345
+ component, vite config, dev/app/build scripts, fork-setup README.
346
+ - **`svelterm build [entry]`** — bundle the component graph, Svelte
347
+ runtime and svelterm into one self-contained `.mjs` (rolldown, node
348
+ platform) that runs with plain `node`. Global CSS via `--css` or
349
+ `src/main.css` convention; component CSS travels in the bundle through
350
+ the new `registerComponentCss` registry that `run()` falls back to.
351
+ - **Terminal-environment `.svelte` compilation** — `terminalServer()`
352
+ compiles components for the terminal environment itself, so
353
+ terminal-only projects need no `vite-plugin-svelte` (the registry
354
+ plugin is not environment-aware and emitted empty component stubs for
355
+ custom environments, rendering a blank screen).
356
+ - **Console forwarding in dev** — `console.log` from the app streams to
357
+ the vite terminal prefixed `[svelterm]`; previously any console call
358
+ crashed `svelterm dev`.
359
+
360
+ ### Changed
361
+
362
+ - The `svelterm` bin now dispatches `init` / `dev` / `build`
363
+ subcommands (previously `dev` only).
364
+ - The terminal environment marks `svelte` and `@svelterm/core` as
365
+ `noExternal` so a natively-imported second copy can't split module
366
+ state.
367
+
368
+ ## 0.3.0 — 2026-07-04
369
+
370
+ Motion completeness: easing everywhere, and keyframes that understand
371
+ your theme.
372
+
373
+ ### Added
374
+
375
+ - **Easing functions** — `animation-timing-function` and
376
+ `transition-timing-function` (longhands and inside the shorthands)
377
+ support `linear`, `ease`, `ease-in`, `ease-out`, `ease-in-out`,
378
+ `cubic-bezier()`, `steps(n[, start|end])`, `step-start` and `step-end`.
379
+ Easing applies per keyframe segment; non-interpolable values switch when
380
+ eased progress crosses the midpoint, as in CSS.
381
+ - **Keyframe `var()` / `light-dark()`** — keyframe declarations resolve
382
+ custom properties and colour-scheme pairs against the animated element
383
+ when the animation starts.
384
+
385
+ ### Changed
386
+
387
+ - Timing functions default to `ease` per spec (previously everything
388
+ interpolated linearly). Declare `linear` explicitly to keep the old
389
+ behaviour.
390
+
391
+ ## 0.2.0 — 2026-07-04
392
+
393
+ The browser-compatibility release: any HTML/CSS feature with a sensible
394
+ cell-grid meaning now works as a browser author expects. Full support matrix
395
+ in [`docs/reference.md`](docs/reference.md); manual in [`docs/`](docs/).
396
+
397
+ **Requires** a Svelte fork with the custom renderer API. Until
398
+ [sveltejs/svelte#18505](https://github.com/sveltejs/svelte/pull/18505) lands,
399
+ use [`tomyan/svelte#svelte-custom-renderer`](https://github.com/tomyan/svelte/tree/svelte-custom-renderer)
400
+ (upstream plus the `svelte/renderer` mount export svelterm needs on Node).
401
+
402
+ ### Added
403
+
404
+ - **CSS grid** — column and row templates with `fr`/`repeat()`/`minmax()`,
405
+ `grid-column`/`grid-row` placement and spans, `grid-template-areas` with
406
+ named `grid-area`
407
+ - **CSS tables** — `display: table*` including `inline-table`, sections and
408
+ captions, `colspan`/`rowspan`, `vertical-align`, `border-collapse` with
409
+ shared box-drawing grid lines, anonymous table boxes
410
+ - **Animations & transitions** — `@keyframes` wired into the render loop
411
+ with RGB colour interpolation between stops, cell-stepped length
412
+ animation, discrete stepping for other properties; `transition` on style
413
+ changes
414
+ - **Selectors** — attribute operators (`^=`, `$=`, `*=`, `~=`, `|=`),
415
+ `:is()`/`:where()`, the `:nth-child()` family, structural pseudo-classes
416
+ (`:empty`, `:first/last/only-of-type`, `:only-child`),
417
+ `:checked`/`:disabled`/`:enabled`, `::before`/`::after` with `content`
418
+ - **Form controls** — checkboxes and radios, cycling `<select>`,
419
+ `<progress>`/`<meter>` block-glyph bars, `<details>`/`<summary>`,
420
+ labels activate their controls on click
421
+ - **CSS values** — Color Level 4 syntax, `light-dark()`, inline `style`
422
+ attributes, `box-sizing`, `text-transform`, the `ch` unit as a `cell`
423
+ alias
424
+ - **Scrolling** — viewport scrolling with overlay scrollbars, horizontal
425
+ scroll, scroll clamping on resize
426
+ - **Borders** — block-character border styles with half-cell corner
427
+ treatment
428
+ - **IO abstraction** — `ProcessIO` (with `/dev/tty` fallback when stdin is
429
+ piped) and `InProcessIO` for embedding; browser-compatible input parsing
430
+ - **Dev mode** — `svelterm dev` CLI with Vite environments, HMR, and a
431
+ two-process WebSocket bridge
432
+ - **Docs** — chaptered manual under `docs/` and a full feature support
433
+ matrix with MDN links in `docs/reference.md`
434
+
435
+ ### Changed
436
+
437
+ - Tracks the upstream unified `mount({ renderer, target, props })` API from
438
+ the `svelte-custom-renderer` branch
439
+ - Exact hex/computed colours are no longer remapped to nearest ANSI names
440
+ - Flex `align-items: stretch` no longer overrides an explicit cross-axis
441
+ size
442
+
443
+ ### Fixed
444
+
445
+ - Incremental repaint artifacts (borders, list markers), flex `min-height:
446
+ auto` shrinking per spec, nested `@media` inside selector blocks, inline
447
+ whitespace and list bullets, scroll position clamping after relayout
448
+
449
+ ## 0.1.0
450
+
451
+ Initial release — name reservation and early preview.
452
+
453
+ **Requires** the unmerged [`svelte-custom-renderer`](https://github.com/paoloricciuti/svelte/tree/svelte-custom-renderer) branch of Svelte 5.
454
+
455
+ ### Features
456
+
457
+ - **CSS engine** — selectors, specificity, cascade, inheritance, scoped styles, `var()`, `calc()`, `@media`, `@keyframes`, `:focus`, `:hover`
458
+ - **Flexbox layout** — `flex-direction`, `justify-content`, `align-items`, `flex-grow`, `flex-shrink`, `flex-basis`, `gap`, `flex-wrap`, `order`
459
+ - **Terminal rendering** — ANSI colors (16, 256, truecolor), box-drawing borders (`single`, `double`, `rounded`, `heavy`), text styles, differential output
460
+ - **Incremental updates** — mutations classified as paint-only, style-resolve, layout-subtree, or layout-bubble to avoid full recomputation
461
+ - **Input handling** — keyboard events, mouse (click, scroll, motion), focus management with Tab/Shift+Tab, bracketed paste
462
+ - **Text input** — `<input>` and `<textarea>` with readline-like editing
463
+ - **Color scheme detection** — automatic `prefers-color-scheme` via OSC 11 terminal query
464
+ - **Debug protocol** — WebSocket-based CDP-inspired server with Console domain
465
+ - **Dual-target components** — same `.svelte` component renders in terminal and browser via `@media (display-mode: terminal/screen)`
package/README.md CHANGED
@@ -4,6 +4,14 @@ Svelte 5 components rendered to the terminal with real CSS.
4
4
 
5
5
  Write standard Svelte components with `<style>` blocks. They render in the terminal with ANSI escape sequences — flexbox layout, scoped styles, CSS variables, pseudo-classes, all on a cell grid.
6
6
 
7
+ **Try it:** live playground and docs at [svelterm.dev](https://svelterm.dev), or pipe a demo straight into a real terminal:
8
+
9
+ ```bash
10
+ curl -fsSL https://svelterm.dev/run/counter.mjs | node --input-type=module -
11
+ ```
12
+
13
+ svelterm is largely LLM-written — designed and directed by a human, with most of the code produced in pair-programming sessions with Claude, test-driven and reviewed as it landed. If that's not your thing, there are plenty of artisanal, hand-typed frameworks out there.
14
+
7
15
  > **Early release.** Svelterm requires an unmerged Svelte branch (`svelte-custom-renderer` by [@paoloricciuti](https://github.com/paoloricciuti)) that adds the custom renderer API. It is not usable with mainline Svelte yet.
8
16
 
9
17
  ## Example
@@ -88,21 +96,39 @@ Standard CSS works as expected. These are the terminal-specific additions:
88
96
 
89
97
  ## Features
90
98
 
91
- - **CSS engine** — selectors, specificity, cascade, inheritance, scoped styles, `var()`, `calc()`, `@media`, `@keyframes`
99
+ - **CSS engine** — selectors (attribute operators, structural/state pseudo-classes, `::before`/`::after`), specificity, cascade, inheritance, scoped styles, `var()`, `calc()`, `@media`, `@container`, `@supports`, `@keyframes`
92
100
  - **Flexbox layout** — `flex-direction`, `justify-content`, `align-items`, `flex-grow`, `flex-shrink`, `gap`, `flex-wrap`
101
+ - **CSS grid** — column and row templates with `fr`/`repeat()`/`minmax()`, `grid-column`/`grid-row` placement and spans, `grid-template-areas` with named `grid-area`
102
+ - **CSS tables** — `display: table*` including `inline-table`, sections and captions, `colspan`/`rowspan`, column sizing, `vertical-align`, `border-collapse` with shared box-drawing grid lines, anonymous boxes
103
+ - **Animations & transitions** — `@keyframes` with RGB colour interpolation and cell-stepped length animation, `transition` on style changes, easing functions
93
104
  - **Terminal rendering** — ANSI colors (16, 256, truecolor), borders, text styles, differential output
94
105
  - **Input** — keyboard events, mouse click and scroll, focus management with Tab/Shift+Tab, `:focus` and `:hover` pseudo-classes
95
- - **Text input** — `<input>` and `<textarea>` with readline-like editing
106
+ - **Form controls** — `<input>`/`<textarea>` editing, checkboxes and radios, cycling `<select>`, `<progress>`/`<meter>` bars, `<details>`/`<summary>`
96
107
  - **Incremental updates** — mutation tracking classifies changes as paint-only, style-resolve, or layout to avoid full recomputation
97
108
  - **Color scheme** — automatic `prefers-color-scheme` detection via terminal queries
98
109
 
110
+ ### Browser compatibility
111
+
112
+ Any HTML/CSS feature with a sensible cell-grid meaning works as a browser
113
+ author expects; pixel-derived features are dropped silently and targeted
114
+ per mode with `@media (display-mode: terminal | browser)`. The manual
115
+ lives in [`docs/`](docs/) — [getting started](docs/getting-started.md),
116
+ [terminal CSS](docs/terminal-css.md), [layout](docs/layout.md),
117
+ [selectors](docs/selectors.md), [elements & input](docs/elements.md),
118
+ [motion](docs/motion.md), [compatibility](docs/compatibility.md),
119
+ [terminal support](docs/terminals.md),
120
+ [inline mode](docs/inline-mode.md) — with
121
+ the one-page support matrix in [`docs/reference.md`](docs/reference.md)
122
+ and the design rationale in
123
+ [`DESIGN-browser-compat.md`](DESIGN-browser-compat.md).
124
+
99
125
  ## Prerequisites
100
126
 
101
- Svelterm requires the experimental custom renderer API, available on the [`svelte-custom-renderer`](https://github.com/paoloricciuti/svelte/tree/svelte-custom-renderer) branch:
127
+ Svelterm requires the experimental custom renderer API from the [`svelte-custom-renderer`](https://github.com/sveltejs/svelte/pull/18042) branch by [@paoloricciuti](https://github.com/paoloricciuti). Until [sveltejs/svelte#18505](https://github.com/sveltejs/svelte/pull/18505) lands (it exposes `mount`/`unmount` from `svelte/renderer`, which svelterm needs on Node), clone the branch from the svelterm fork, which tracks upstream plus that fix:
102
128
 
103
129
  ```bash
104
130
  # Clone the branch
105
- git clone -b svelte-custom-renderer https://github.com/paoloricciuti/svelte.git svelte-fork
131
+ git clone -b svelte-custom-renderer https://github.com/tomyan/svelte.git svelte-fork
106
132
  cd svelte-fork
107
133
  pnpm install
108
134
  pnpm -C packages/svelte build
@@ -120,34 +146,21 @@ Then reference it in your project's `package.json`:
120
146
 
121
147
  ## Setup
122
148
 
123
- Configure the Svelte compiler to use svelterm as the custom renderer:
149
+ Scaffold a project with the CLI (the Svelte fork above must be a sibling
150
+ directory, or adjust the `svelte` path in the generated `package.json`):
124
151
 
125
- ```typescript
126
- // vite.config.ts
127
- import { defineConfig } from 'vite'
128
- import { svelte } from '@sveltejs/vite-plugin-svelte'
129
-
130
- export default defineConfig({
131
- plugins: [
132
- svelte({
133
- compilerOptions: {
134
- experimental: {
135
- customRenderer: '@svelterm/core',
136
- },
137
- css: 'external',
138
- },
139
- }),
140
- ],
141
- build: {
142
- target: 'node22',
143
- rollupOptions: {
144
- external: ['svelte', 'svelte/renderer', 'svelte/internal',
145
- 'svelte/internal/client', 'ws', 'http', 'crypto'],
146
- },
147
- },
148
- })
152
+ ```bash
153
+ npx @svelterm/core init my-app
154
+ cd my-app && npm install
155
+ npm run dev # vite dev server (terminal 1)
156
+ npm run app # the app, hot-reloading, in this terminal (terminal 2)
157
+ npm run build # → dist/app.mjs — self-contained, runs with plain node
149
158
  ```
150
159
 
160
+ `console.log` output from the app streams to the vite terminal, like a
161
+ browser console. See [docs/getting-started.md](docs/getting-started.md)
162
+ for manual setup and dual-target configuration.
163
+
151
164
  ## API
152
165
 
153
166
  ### `run(component, options?)`
@@ -0,0 +1,13 @@
1
+ /**
2
+ * svelterm build — bundle a terminal app into one self-contained .mjs
3
+ * that any Node runtime can execute directly:
4
+ *
5
+ * svelterm build # src/App.svelte → dist/app.mjs
6
+ * svelterm build src/App.svelte -o dist/app.mjs
7
+ *
8
+ * Components compile with the project's Svelte (the custom-renderer
9
+ * fork) targeting @svelterm/core; each carries its extracted CSS via
10
+ * registerComponentCss. Requires rolldown (a dependency of vite 8 —
11
+ * `npm i -D rolldown` if resolution fails).
12
+ */
13
+ export declare function runBuild(argv: string[]): Promise<void>;