silvery 0.11.1 → 0.11.3

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
@@ -2,9 +2,7 @@
2
2
 
3
3
  **Powerful apps. Polished UIs. Proudly terminal.**
4
4
 
5
- Ink-compatible React renderer for interactive terminal apps. Same `Box`, `Text`, `useInput` API you know.
6
-
7
- > **Work in progress.** APIs may change. Feedback welcome.
5
+ Ink-compatible React renderer for interactive terminal apps. Same `Box`, `Text`, `useInput` API you know. 3–6× faster in mounted rerender benchmarks.
8
6
 
9
7
  ```console
10
8
  $ npm install silvery react
@@ -33,24 +31,37 @@ await render(<Counter />).run()
33
31
 
34
32
  - **React 18 + 19** — hooks, refs, effects, suspense — all works
35
33
  - **Flexbox layout** — `Box` with `flexDirection`, `padding`, `gap`, `flexGrow`, just like Ink
36
- - **Ink/Chalk compatible** — [`@silvery/ink`](https://silvery.dev/guide/silvery-vs-ink) and `@silvery/chalk` drop-in compat layers. 99% of Ink's + 100% of Chalk's test suites pass. See the [full feature comparison](https://silvery.dev/guide/silvery-vs-ink)
34
+ - **[Ink-compatible](https://silvery.dev/guide/silvery-vs-ink#compatibility)** most code works with just an import change. 918/931 Ink 7.0 tests pass on silvery's compat layer. Drop-in migration via [`@silvery/ink`](https://silvery.dev/guide/silvery-vs-ink). See the [full feature comparison](https://silvery.dev/guide/silvery-vs-ink)
37
35
 
38
36
  ### Shiny new stuff
39
37
 
40
- - **[Layout-first rendering](https://silvery.dev/guide/silvery-vs-ink#responsive-layout)** — `useBoxRect()` returns actual dimensions during render. No post-render measurement, no two-pass layout cycle. Enables `overflow="scroll"`, `position="sticky"`, and ANSI-aware compositing with color blending
41
- - **[Dynamic scrollback](https://silvery.dev/examples/scrollback)** live React zone at the bottom, completed items graduate to terminal-owned scrollback. Cmd+F and text selection work natively. Inline mode gets fullscreen-level performance; fullscreen mode gets inline-level UX (app-managed scrollback). No hard split between the two
42
- - **Pure TypeScript, zero native deps** — no WASM, no build steps. Works on Alpine, CI, Docker, everywhere
43
- - **[Ink-compatible](https://silvery.dev/guide/silvery-vs-ink#compatibility)**918/931 Ink 7.0 tests pass on silvery's compat layer. Drop-in migration via [`@silvery/ink`](https://silvery.dev/guide/silvery-vs-ink). See the [full feature comparison](https://silvery.dev/guide/silvery-vs-ink)
44
- - **[Theme system](https://silvery.dev/guide/styling)**38 palettes, semantic design/color tokens (`$primary`, `$error`), auto-detects terminal colors
45
- - **[45+ components](https://silvery.dev/guides/components)**TextInput, TextArea, SelectList, ListView, Table, TreeView, Console, Tabs, CommandPalette, ModalDialog, Toast, and more
46
- - **[Focus system](https://silvery.dev/guide/silvery-vs-ink#focus-system)** — scoped focus, arrow-key directional nav, click-to-focus
47
- - **Text selection** mouse drag, word/line selection, `userSelect` boundaries, Alt+drag override. Works out of the box with `withDomEvents()`
48
- - **Find**`Ctrl+F` buffer search with match highlighting and `n`/`N` navigation. Works out of the box with `withFocus()`
49
- - **Copy-mode**`Esc, v` for vim-style keyboard-driven text selection and yanking
50
- - **Drag-and-drop** — mouse drag with hit testing, automatic via `withDomEvents()`
51
- - **Extremely composable** — use as just a renderer (`render`), add a runtime (`run`), or build full apps with any React state library (useState, Zustand, Jotai, Redux). Swap terminal backends (real TTY, headless, xterm.js emulator) for [testing](https://silvery.dev/guide/testing). Embed silvery components in existing CLIs. Use the layout engine standalone. Render to terminal, or (experimental) Canvas, or DOM
52
- - **[Terminal protocol support](https://silvery.dev/guide/silvery-vs-ink#terminal-protocol-coverage)**100+ escape sequences, all auto-negotiated: 12 OSC (hyperlinks, clipboard, palette, text sizing, semantic prompts, notifications), 35+ CSI (cursor, mouse modes, paste, focus, sync output, device queries), 50+ SGR (6 underline styles, underline colors, truecolor, 256-color), full Kitty keyboard (5 flags), full SGR mouse (any-event, drag, wheel)
53
- - **[Incremental rendering](https://silvery.dev/guide/silvery-vs-ink#performance-size)**cell-level dirty tracking, only changed cells emit to the terminal. Works in inline mode with native scrollback, not just fullscreen
38
+ - **[Best-in-class performance](https://silvery.dev/guide/silvery-vs-ink#performance-size)** — 3–6× faster than Ink in mounted rerender benchmarks, 10–20× less terminal output. Cell-level dirty tracking, only changed cells emit. Per-node skip for unchanged subtrees. Works in inline mode with native scrollback, not just fullscreen
39
+ - **Pure TypeScript, zero native deps** no WASM, no build steps. [Layout via Flexily](https://silvery.dev/guide/layout-engine) (or Yoga). Works on Alpine, CI, Docker, everywhere
40
+ - **[Web-like responsive layout](https://silvery.dev/guide/silvery-vs-ink#responsive-layout)** — `useBoxRect()` returns actual dimensions during render. No post-render measurement, no two-pass layout cycle. Enables:
41
+ - [Scroll containers](https://silvery.dev/guide/scrolling) — `overflow="scroll"` with virtualization
42
+ - [Sticky positioning](https://silvery.dev/guide/layout-coordinates) — `position="sticky"` for headers and footers
43
+ - [ANSI-aware compositing](https://silvery.dev/guide/ansi-layering) — color blending with alpha across overlapping layers
44
+ - **[Inline, fullscreen, or both](https://silvery.dev/guide/runtime-layers)** — same components, one-line switch. All with incremental rendering:
45
+ - [Fullscreen](https://silvery.dev/guide/runtime-getting-started)alt screen, traditional TUI
46
+ - [Inline with dynamic scrollback](https://silvery.dev/examples/scrollback) live React zone at bottom, completed items graduate to terminal-owned scrollback. Native Cmd+F and text selection
47
+ - [Virtual inline](https://silvery.dev/design/dynamic-scrollback)alt screen + app-managed scrollback history, scrollable and searchable
48
+ - **[Web-like interaction](https://silvery.dev/guide/event-handling)** — full keyboard and mouse events that just work. Modifier keys, mouse buttons, and drag all combine seamlessly into a single event model. Enables:
49
+ - [Focus scopes](https://silvery.dev/guide/silvery-vs-ink#focus-system) spatial arrow-key nav, Tab/Escape, click-to-focus
50
+ - [Text selection](https://silvery.dev/guide/text-selection) — mouse drag, word/line, `userSelect` boundaries, Alt+drag override
51
+ - [Find](https://silvery.dev/guide/find) — `Ctrl+F` with match highlighting and `n`/`N` navigation
52
+ - [Copy-mode](https://silvery.dev/guide/clipboard) — `Esc, v` for vim-style keyboard selection and yanking
53
+ - [Drag-and-drop](https://silvery.dev/guide/event-handling) — mouse drag with hit testing
54
+ - **[Rich component library](https://silvery.dev/guides/components)** — 45+ components: TextInput, SelectList, ListView, Table, TreeView, Tabs, CommandPalette, ModalDialog, Toast, and more. Every component automatically participates in focus, mouse, and keybindings (readline, vim) — no wiring needed. [38 theme palettes](https://silvery.dev/guide/styling) with semantic tokens (`$primary`, `$error`) and auto-detected terminal colors
55
+ - **[Playwright-style testing](https://silvery.dev/guide/testing)** — 3,000+ tests. Full access to terminal internals (scrollback buffer, cursor position, cell styles, window dimensions):
56
+ - `createRenderer` — fast unit tests with auto-refreshing CSS locators, cell-level color assertions, frame-by-frame inspection
57
+ - [Termless](https://termless.dev) — like Playwright for terminals. Full ANSI fidelity with [10 swappable backends](https://termless.dev/guide/backends) (xterm.js, Ghostty, Alacritty, WezTerm, Kitty, and more)
58
+ - [`SILVERY_STRICT`](https://silvery.dev/guide/debugging) — multi-level verification: buffer (incremental vs fresh), ANSI (internal parser), terminal (cross-backend), and accumulated replay
59
+ - **[Composable architecture](https://silvery.dev/guide/providers)** — every layer is independently swappable. [DI](https://silvery.dev/guide/providers) via `pipe()` providers:
60
+ - [Layout](https://silvery.dev/guide/layout-engine) — Flexily or Yoga
61
+ - [State](https://silvery.dev/guide/runtime-layers) — BYO (useState, Zustand, Jotai, Redux)
62
+ - [Term](https://silvery.dev/guide/runtime-layers) — real, headless, emulator
63
+ - [App](https://silvery.dev/guide/runtime-layers) — from stringify to rich app (withFocus, withDomEvents, withCommands). Render to terminal, Canvas, or DOM
64
+ - **[All modern terminal protocols](https://silvery.dev/guide/silvery-vs-ink#terminal-protocol-coverage)** — [60 years of terminal protocols](https://terminfo.dev/about), unified into clean APIs. 100+ escape sequences you'll never have to write — auto-negotiated and gracefully degraded: [Kitty keyboard](https://terminfo.dev) + [SGR mouse](https://terminfo.dev) become rich events with modifiers; [hyperlinks](https://terminfo.dev) are just props; [clipboard](https://terminfo.dev) is a function call. Truecolor, underline styles, synchronized output, bracketed paste, focus reporting, resize detection, inline images, and [more](https://silvery.dev/guide/silvery-vs-ink#terminal-protocol-coverage)
54
65
 
55
66
  ### Why Silvery?
56
67
 
@@ -60,6 +71,12 @@ Along the way, three principles emerged. Take the best from the web, stay true t
60
71
 
61
72
  [The Silvery Way](https://silvery.dev/guide/the-silvery-way) · [Silvery vs Ink](https://silvery.dev/guide/silvery-vs-ink) · [About](https://silvery.dev/about)
62
73
 
74
+ ### Next steps
75
+
76
+ - [Quick start](https://silvery.dev/getting-started/quick-start) — install, first app, deploy
77
+ - [Interactive examples](https://silvery.dev/examples) — `npx silvery examples` to try them locally
78
+ - [Silvery vs Ink](https://silvery.dev/guide/silvery-vs-ink) — feature comparison and migration guide
79
+
63
80
  ## Packages
64
81
 
65
82
  | Package | Description |
@@ -90,11 +107,11 @@ Standalone projects Silvery builds on — each stands on its own:
90
107
  - **Frameworks** — Svelte, Solid.js, Vue adapters
91
108
  - **@silvery/create** — Structured state management with commands, keybindings, effects-as-data
92
109
 
93
- **Runtimes:** Bun >= 1.0 and Node.js >= 18. CLI (`silvery` command) requires Bun.
110
+ **Runtimes:** Bun >= 1.0 and Node.js >= 23.6. CLI (`silvery` command) requires Bun.
94
111
 
95
112
  ## Inspirations
96
113
 
97
- Silvery builds on ideas from [Ink](https://github.com/vadimdemedes/ink) (React for terminals), [Ratatui](https://ratatui.rs/) (cell-level buffer model), [SlateJS](https://www.slatejs.org/) (plugin composition, operations-as-data), [The Elm Architecture](https://guide.elm-lang.org/architecture/) / [BubbleTea](https://github.com/charmbracelet/bubbletea) (TEA state machines), the CSS/Web platform (flexbox, container queries, DOM events, focus scopes), [VS Code](https://code.visualstudio.com/) (command palette, keybindings), [Playwright](https://playwright.dev/) (locator-based testing), [ProseMirror](https://prosemirror.net/) (selection model), [Blessed](https://github.com/chjj/blessed) (rich terminal UIs in JS), and [Textual](https://textual.textualize.io/) (CSS-like terminal theming).
114
+ Silvery builds on ideas from [Ink](https://github.com/vadimdemedes/ink) (React for terminals), [Ratatui](https://ratatui.rs/) (cell-level buffer model), [shadcn/ui](https://ui.shadcn.com/) (polished defaults, semantic theming), [SlateJS](https://www.slatejs.org/) (plugin composition, operations-as-data), [The Elm Architecture](https://guide.elm-lang.org/architecture/) / [BubbleTea](https://github.com/charmbracelet/bubbletea) (TEA state machines), the CSS/Web platform (flexbox, container queries, DOM events, focus scopes), [VS Code](https://code.visualstudio.com/) (command palette, keybindings), [Playwright](https://playwright.dev/) (locator-based testing), [ProseMirror](https://prosemirror.net/) (selection model), [Blessed](https://github.com/chjj/blessed) (rich terminal UIs in JS), and [Textual](https://textual.textualize.io/) (CSS-like terminal theming).
98
115
 
99
116
  ## License
100
117
 
package/bin/silvery.ts ADDED
@@ -0,0 +1,52 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * silvery CLI — delegates to @silvery/examples
4
+ * Works on both Node.js 23.6+ and Bun.
5
+ */
6
+ import { resolve, dirname, join } from "node:path"
7
+ import { readFileSync, existsSync } from "node:fs"
8
+ import { spawn } from "node:child_process"
9
+ import { fileURLToPath } from "node:url"
10
+
11
+ const __filename = fileURLToPath(import.meta.url)
12
+ const __dirname = dirname(__filename)
13
+
14
+ // Find package root by walking up looking for package.json with name "silvery"
15
+ function findPackageRoot(startDir: string): string {
16
+ let dir = startDir
17
+ for (let i = 0; i < 10; i++) {
18
+ const pkg = join(dir, "package.json")
19
+ if (existsSync(pkg)) {
20
+ try {
21
+ const json = JSON.parse(readFileSync(pkg, "utf8"))
22
+ if (json.name === "silvery") return dir
23
+ } catch {}
24
+ }
25
+ const parent = dirname(dir)
26
+ if (parent === dir) break
27
+ dir = parent
28
+ }
29
+ return dirname(startDir)
30
+ }
31
+
32
+ // Detect runtime for spawning child processes
33
+ const runtime = typeof globalThis.Bun !== "undefined" ? "bun" : "node"
34
+
35
+ const root = findPackageRoot(__dirname)
36
+ const args = process.argv.slice(2)
37
+ const examplesCli = resolve(root, "packages/examples/bin/cli.ts")
38
+
39
+ if (args.includes("--version") || args.includes("-v")) {
40
+ const pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf8"))
41
+ console.log(`silvery ${pkg.version}`)
42
+ process.exit(0)
43
+ }
44
+
45
+ // Strip "examples" subcommand — the examples CLI handles bare args as example names
46
+ const delegateArgs = args[0] === "examples" ? args.slice(1) : args
47
+
48
+ const runArgs = runtime === "bun" ? ["run", examplesCli, ...delegateArgs] : [examplesCli, ...delegateArgs]
49
+ const proc = spawn(runtime, runArgs, {
50
+ stdio: "inherit",
51
+ })
52
+ proc.on("exit", (code) => process.exit(code ?? 1))