silvery 0.10.0 → 0.11.1
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/CHANGELOG.md +271 -0
- package/README.md +51 -29
- package/dist/chalk.js +4 -0
- package/dist/index.js +340 -0
- package/dist/ink.js +129 -0
- package/dist/runtime.js +127 -0
- package/dist/theme.js +7 -0
- package/dist/ui/animation.js +3 -0
- package/dist/ui/ansi.js +3 -0
- package/dist/ui/cli.js +9 -0
- package/dist/ui/display.js +4 -0
- package/dist/ui/image.js +4 -0
- package/dist/ui/input.js +3 -0
- package/dist/ui/progress.js +9 -0
- package/dist/ui/react.js +4 -0
- package/dist/ui/utils.js +3 -0
- package/dist/ui/wrappers.js +15 -0
- package/dist/ui.js +18 -0
- package/package.json +105 -21
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to Silvery are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
6
|
+
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.11.0] - 2026-04-09
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Ink 7.0 compat — BackgroundContext shim** — exposes Ink 7.0's context-based background inheritance API via `packages/ink/src/bg-context.ts`. Makes +27 Ink 7.0 tests pass on the compat layer.
|
|
15
|
+
- **Ink 7.0 compat — maxFps render throttle** — `maxFps` option in the compat renderer throttles render rate to match Ink 7.0's behavior.
|
|
16
|
+
- **Ink 7.0 compat — debug cursor API shim** — Ink-compatible cursor debug API for visibility/position interaction tests.
|
|
17
|
+
- **Ink 7.0 compat — `wrap="hard"`** — character-level text truncation for Ink 7.0 parity (vs word-boundary wrapping).
|
|
18
|
+
- **Ink 7.0 compat — per-side `borderBackgroundColor`** — `borderTopBackgroundColor`, `borderRightBackgroundColor`, etc., matching Ink 7.0's per-side border background prop API.
|
|
19
|
+
- **Text — CJK wide-character overlay clearing** — when overwriting a continuation cell, the owning wide-char cell is cleared to a space. Fixes rendering when CJK cells are partially occluded.
|
|
20
|
+
- **Flexily — overflow clipping at edges** — left/right overflow clipping works cleanly with borders and margins via `minCol` parameter in text render.
|
|
21
|
+
- **Pre-built `dist/` via tsup** — silvery now ships both raw TypeScript source (for Bun consumers, `src/`) and pre-built `.js` + `.d.ts` (for npm consumers, `dist/`) via conditional exports. Zero build step for Bun users; instant imports for everyone else.
|
|
22
|
+
- **Long-lived `Ag` renderer in `createApp`** — reuse Ag instance across frames instead of creating per-render. Combined with dirty node SET optimization for O(1) layout-dirty checks.
|
|
23
|
+
- **Dirty node SET + propsEqual collapse** — per-node dirty tracking with independent flags, 3-pass prop comparison collapsed into 1 pass. Yields measurable perf win on kanban and memo'd workloads.
|
|
24
|
+
- **Atomicity framing in docs + blog** — docs now explain the three axes of atomicity (time, space, content) that the layout-first pipeline + cell-level diff + DEC mode 2026 enable. See the updated homepage, `silvery-vs-ink.md`, and the forthcoming blog post on Claude Code's rendering dilemma.
|
|
25
|
+
- **Interactions runtime** — selection, find, copy-mode, and drag as composable runtime features (`SelectionFeature`, `FindFeature`, `CopyModeFeature`, `DragFeature`) in `@silvery/ag-term/features/`. Each feature is wired automatically by its provider (`withDomEvents` for selection and drag, `withFocus` for find and copy-mode).
|
|
26
|
+
- **InputRouter** — centralized input routing in `@silvery/create/internal/` dispatches keyboard and mouse events to registered feature handlers with priority ordering.
|
|
27
|
+
- **CapabilityRegistry** — runtime capability discovery in `@silvery/create/internal/`. Features register themselves; React components access them via `CapabilityRegistryContext`.
|
|
28
|
+
- **`useSelection` hook** — reads selection state from the CapabilityRegistry. Replaces the old `useTerminalSelection` + `TerminalSelectionProvider` pattern.
|
|
29
|
+
- **Composition docs** — new guide pages: [Providers and Plugins](docs/guide/providers.md) and [Headless Machines](docs/guide/headless-machines.md).
|
|
30
|
+
- **`@silvery/commander`: typed inline arg syntax** — `command("deploy <service> [env]")` now parses positional arguments embedded in the command name string and contributes them to the typed `Args` tuple and `ArgsRecord`.
|
|
31
|
+
- **`@silvery/commander`: `.actionMerged()`** — explicit opt-in for the merged named-object form. Receives `(params, cmd)` where `params` contains all positional args (camelCased) merged with options.
|
|
32
|
+
- **`@silvery/commander`: multi-line console blocks in help sections** — `addHelpSection` row terms can now contain `\n`-separated lines.
|
|
33
|
+
- **`@silvery/commander`: shell prompt detection across all sections** — lines starting with `$ `, `# `, `> `, or `❯ ` get console-block styling in any `addHelpSection`.
|
|
34
|
+
- **Rect hook rename** — `contentRect` → `boxRect`, `renderRect` → `screenRect`, `screenRect` → `scrollRect`. Six hooks consolidated into three via overloads. Migration guide in docs.
|
|
35
|
+
|
|
36
|
+
### Fixed
|
|
37
|
+
|
|
38
|
+
- **STRICT env bug** — `isStrictOutput()` treated the string `"0"` as truthy, so `SILVERY_STRICT=0` didn't actually disable STRICT mode. Bench runs before the fix paid full O(cells) verification overhead every iteration; post-fix numbers are 2.5-5.2× faster than Ink 7.0 on mounted workloads (all 16 scenarios).
|
|
39
|
+
- **Render phase typo** — `AgNode["boxRectt"]` → `AgNode["boxRect"]` in render-phase.ts.
|
|
40
|
+
- **Output phase — text clipping at left edge** — text in `overflow="hidden"` containers now clips correctly at the left edge via `minCol` parameter.
|
|
41
|
+
- **Ink compat — kitty keyboard default flags** — matches Ink's byte-wise compat for disambiguate escape codes.
|
|
42
|
+
- **Ink compat — stderr replay frame in debug mode** — emits replay frame for stderr writes during debug mode capture.
|
|
43
|
+
- **`useCallbackRect` subscription stability** — `getRect` was captured per-render, invalidating subscriptions on every re-render. Wrapped in a ref for stability, matching the `callbackRef` pattern.
|
|
44
|
+
- **Contentprops dead code** — removed deprecated `propsEqual` / `layoutPropsChanged` / `contentPropsChanged` with zero callers.
|
|
45
|
+
|
|
46
|
+
### Performance
|
|
47
|
+
|
|
48
|
+
- **Output phase — combined SGR codes** — combine consecutive SGR codes into a single escape sequence where possible.
|
|
49
|
+
- **2.5-5.2× faster than Ink 7.0** on mounted workloads (cursor move, kanban card edit, memo'd list toggles). Wins all 16 benchmark scenarios. Run `bun run bench` to reproduce.
|
|
50
|
+
- **28-192× less output** than full redraw on incremental updates — cell-level buffer diff + relative cursor addressing.
|
|
51
|
+
- **Bundle parity with Ink+Yoga** — `silvery/runtime` is 114.9 KB gzipped vs Ink+Yoga's 116.6 KB (0.99×). `silvery/ink` compat layer is 119.2 KB (+2.2 KB over Ink baseline).
|
|
52
|
+
|
|
53
|
+
### Documentation
|
|
54
|
+
|
|
55
|
+
- **Homepage** — "React for modern terminal apps" hero. Merged Responsive Layout and Atomic Rendering cards (same architectural root). Replaced "100x" claim with 2.5-5.2× honest numbers. Bulleted rendering mode list (inline incremental / fullscreen / static / virtual).
|
|
56
|
+
- **silvery-vs-ink.md** — added "The atomicity story" section covering time/space/content atomicity. Replaced cold-init perf table with canonical mounted benchmarks. Updated compat stats to 918+/931 (~98.6%) against Ink 7.0.
|
|
57
|
+
- **why-silvery.md, faq.md, README.md, about.md, compatibility.md** — uniform update to new framing and numbers.
|
|
58
|
+
|
|
59
|
+
### Breaking Changes
|
|
60
|
+
|
|
61
|
+
- **Removed hooks** — `useTerminalSelection`, `usePointerState`, `useFind`, `useFindProvider`, `useCopyMode`, `useCopyProvider` are superseded by the feature-based architecture. The old hooks still exist for backwards compatibility but are no longer the recommended API.
|
|
62
|
+
- **Text selection** now activates automatically via `withDomEvents()` — no explicit hook setup required.
|
|
63
|
+
- **Find** now activates automatically via `withFocus()` with `Ctrl+F` — no explicit `useFind` setup required.
|
|
64
|
+
- **Copy-mode** now activates automatically via `withFocus()` with `Esc, v` — no explicit `useCopyMode` setup required.
|
|
65
|
+
- **Rect hook rename** (see Added): if you use `contentRect` / `renderRect` / `screenRect` names, they've been renamed. See the Layout Coordinates guide for the migration.
|
|
66
|
+
|
|
67
|
+
## [0.9.0] - 2026-03-29
|
|
68
|
+
|
|
69
|
+
### Added
|
|
70
|
+
|
|
71
|
+
- **Interactive canvas rendering** — `renderToCanvas()` now supports full keyboard input via hidden textarea, RuntimeContext, FocusManager, ThemeProvider, and CursorProvider. Showcase demos switched from xterm.js to canvas.
|
|
72
|
+
- **Variable-height virtualizer** — `VirtualList` supports dynamic item heights via measurement, not just fixed `itemHeight`.
|
|
73
|
+
- **Canvas input handler** — new `createCanvasInput()` for DOM KeyboardEvent → terminal escape sequence conversion.
|
|
74
|
+
|
|
75
|
+
### Fixed
|
|
76
|
+
|
|
77
|
+
- **Kitty keyboard: shifted punctuation** — `Shift+1` now correctly produces `!` (not `1`) via `shifted_codepoint`. Default Kitty flags upgraded to `DISAMBIGUATE | REPORT_EVENTS | REPORT_ALL_KEYS` (11). Warns when shifted info is missing.
|
|
78
|
+
- **`matchHotkey` layout-independent** — single-character hotkeys (`"!"`, `"J"`, `"@"`) skip shift check. Works across all keyboard layouts.
|
|
79
|
+
- **Mouse mode 1003** — restored any-event tracking for hover support.
|
|
80
|
+
- **Commander: `NO_COLOR`** — `colorizeHelp` now respects `NO_COLOR` environment variable.
|
|
81
|
+
|
|
82
|
+
### Documentation
|
|
83
|
+
|
|
84
|
+
- Example pages: added `npx silvery examples` run commands with code-group tabs (npm/bun/pnpm/vp).
|
|
85
|
+
- Removed placeholder blog and live-demo pages.
|
|
86
|
+
- Showcase inventory updated for canvas renderer.
|
|
87
|
+
|
|
88
|
+
## [0.4.0] - 2026-03-23
|
|
89
|
+
|
|
90
|
+
### Breaking Changes
|
|
91
|
+
|
|
92
|
+
- **Era2 package renames** — `@silvery/react` → `@silvery/ag-react`, `@silvery/term` → `@silvery/ag-term`, `@silvery/ui` merged into `@silvery/ag-react/ui`, `@silvery/compat` → `@silvery/ink`
|
|
93
|
+
- **TeaNode → AgNode** — core node type renamed across the entire codebase
|
|
94
|
+
- **createApp moved to @silvery/create** — canonical import is now `@silvery/create/create-app` (ag-term re-exports for backwards compat)
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
|
|
98
|
+
- **`@silvery/ag` package** — core types (AgNode, BoxProps, keys, focus) extracted from tea
|
|
99
|
+
- **`render()` beginner API** — zero-ceremony entry point: `await render(<App />).run()`
|
|
100
|
+
- **Component-tier examples** — 7 simple examples using `run()` + React hooks (no TEA required)
|
|
101
|
+
- **Subpath exports** — `silvery/runtime`, `silvery/theme`, `silvery/ui` for targeted imports
|
|
102
|
+
- **Build script** — `bun run build` produces pre-built JS bundles via Bun.build()
|
|
103
|
+
|
|
104
|
+
### Changed
|
|
105
|
+
|
|
106
|
+
- **3 public packages** — `silvery`, `@silvery/create`, `@silvery/test`. Internal packages (`@silvery/ag`, `@silvery/ag-react`, `@silvery/ag-term`, `@silvery/theme`, `@silvery/ink`) are published but not user-facing.
|
|
107
|
+
- **Examples reorganized** — `examples/components/` (no TEA) and `examples/apps/` (with TEA)
|
|
108
|
+
- **Docs rewritten** — rendering-first positioning, TEA is optional, Ink-compatible messaging
|
|
109
|
+
|
|
110
|
+
### Fixed
|
|
111
|
+
|
|
112
|
+
- Border text overflow: scroll indicator text now truncates when box is narrower than indicator text
|
|
113
|
+
- Package export resolution in vitest (dist/ vs src/ conditions)
|
|
114
|
+
|
|
115
|
+
## [0.3.0] - 2026-03-20
|
|
116
|
+
|
|
117
|
+
README rewrite, website positioning, docs site restructuring. No code changes.
|
|
118
|
+
|
|
119
|
+
## [0.2.0] - 2026-03-09
|
|
120
|
+
|
|
121
|
+
The Silvery release. Complete rename from hightea to silvery, monorepo restructured as `@silvery/*` packages, and ecosystem-wide migration (loggily, flexily, @silvery/theme).
|
|
122
|
+
|
|
123
|
+
### Added
|
|
124
|
+
|
|
125
|
+
- `silvery/ink` and `silvery/chalk` compatibility subpaths for zero-effort migration from Ink/Chalk.
|
|
126
|
+
- `@silvery/ink` package for ink/chalk API compatibility layer.
|
|
127
|
+
- `@silvery/theme` package (absorbed from standalone swatch project) with 45 built-in color palettes and 33 semantic design tokens.
|
|
128
|
+
- `@silvery/test` package with unified `createRenderer()` API, auto-refreshing locators, and Playwright-style assertions.
|
|
129
|
+
- `@silvery/create` package for optional TEA (The Elm Architecture) state machines with `zustand-tea` middleware.
|
|
130
|
+
- `@silvery/ag-react/ui` package with 23+ components: ModalDialog, Toast, SplitView, CommandPalette, SelectList, Table, ScrollbackView, ErrorBoundary, Tabs, and more.
|
|
131
|
+
- VitePress documentation site at silvery.dev with migration guide, API reference, and live xterm.js demos.
|
|
132
|
+
- Examples directory with interactive demos (dashboard, live-resize, outline, scrollback, Kitty protocol).
|
|
133
|
+
|
|
134
|
+
### Changed
|
|
135
|
+
|
|
136
|
+
- **Renamed**: hightea -> silvery across all packages, imports, docs, and URLs.
|
|
137
|
+
- **Renamed**: decant -> loggily (logging library).
|
|
138
|
+
- **Renamed**: flexture -> flexily (layout engine).
|
|
139
|
+
- **Renamed**: swatch -> @silvery/theme (absorbed into monorepo).
|
|
140
|
+
- Package structure: monolith split into `@silvery/ag-react`, `@silvery/ag-term`, `@silvery/create`, `@silvery/ansi`, `@silvery/ag-react/ui`, `@silvery/theme`, `@silvery/test`, `@silvery/ink`.
|
|
141
|
+
- GitHub repositories renamed: beorn/hightea -> beorn/silvery, beorn/decant -> beorn/loggily, beorn/flexture -> beorn/flexily.
|
|
142
|
+
|
|
143
|
+
## [0.1.0] - 2026-03-05
|
|
144
|
+
|
|
145
|
+
The hightea release. Renamed from inkx to hightea, with new domain (hightea.dev) and monorepo consolidation.
|
|
146
|
+
|
|
147
|
+
### Added
|
|
148
|
+
|
|
149
|
+
- Custom domain: hightea.dev.
|
|
150
|
+
- `@hightea/core` package for shared types.
|
|
151
|
+
- `@hightea/ansi` merged into monorepo (previously standalone `@beorn/chalkx`).
|
|
152
|
+
- `@hightea/ui` merged into monorepo (previously standalone `@beorn/inkx-ui`).
|
|
153
|
+
|
|
154
|
+
### Changed
|
|
155
|
+
|
|
156
|
+
- **Renamed**: inkx -> hightea, chalkx -> @hightea/ansi across all source, docs, and URLs.
|
|
157
|
+
- Package structure: `@beorn/inkx` -> `@hightea/term`, `@beorn/chalkx` -> `@hightea/ansi`, `@beorn/inkx-ui` -> `@hightea/ui`.
|
|
158
|
+
|
|
159
|
+
## [0.0.x] - 2026-01-19 to 2026-03-04
|
|
160
|
+
|
|
161
|
+
The inkx era. Initial development as a high-performance Ink alternative with incremental rendering.
|
|
162
|
+
|
|
163
|
+
### Added — Rendering Engine
|
|
164
|
+
|
|
165
|
+
- **Incremental content phase**: per-node dirty tracking with 7 independent flags (`contentDirty`, `stylePropsDirty`, `bgDirty`, `subtreeDirty`, `childrenDirty`, `layoutDirty`, `layoutChangedThisFrame`). Only changed nodes re-render, producing 28-192x fewer bytes on typical incremental updates.
|
|
166
|
+
- **Three-tier scroll optimization**: buffer shift (Tier 1, scroll-only changes), full viewport clear (Tier 2, structural changes), and subtree-dirty-only (Tier 3, targeted re-render).
|
|
167
|
+
- **Sticky children**: `position="sticky"` with two-pass rendering (normal flow first, then sticky headers on top). Works inside and outside scroll containers.
|
|
168
|
+
- **Inline incremental rendering**: `createOutputPhase()` with instance-scoped cursor tracking. Relative cursor positioning for inline mode achieves parity with fullscreen incremental rendering.
|
|
169
|
+
- **Text background inheritance**: explicit `inheritedBg` parameter through the render tree, decoupling text rendering from buffer state. Eliminates `getCellBg` mismatches on incremental renders.
|
|
170
|
+
- **BgSegment tracking**: strips ANSI background from text content and tracks bg ranges per-segment, preventing background bleed across wrapped lines.
|
|
171
|
+
- **SILVERY_STRICT mode**: verifies incremental render produces identical output to fresh render, cell-by-cell, including vt100 ANSI output verification.
|
|
172
|
+
- **CJK/wide character support**: correct cursor advancement, continuation cells, and boundary handling for double-width characters.
|
|
173
|
+
- **True color row pre-check**: `rowExtrasEquals()` for Map-based data (true colors, underline colors, hyperlinks) prevents stale color artifacts.
|
|
174
|
+
|
|
175
|
+
### Added — Layout
|
|
176
|
+
|
|
177
|
+
- **Pluggable layout engine**: Yoga and Flexily adapters with zero-allocation option.
|
|
178
|
+
- `useBoxRect()` / `useScrollRect()` hooks for synchronous layout feedback (no useEffect, no layout thrashing).
|
|
179
|
+
- `overflow="scroll"` containers with `scrollTo` (edge-based) and `scrollOffset` (explicit) control.
|
|
180
|
+
- `position="sticky"` with `stickyTop` / `stickyBottom` offsets.
|
|
181
|
+
- `position="absolute"` with three-pass paint-order rendering (normal flow, sticky, absolute).
|
|
182
|
+
- `outlineStyle` prop: border characters that overlap content without affecting layout (CSS `outline` equivalent).
|
|
183
|
+
- `overflowIndicator` prop: scroll indicators on bordered or borderless containers.
|
|
184
|
+
- `display="none"` support.
|
|
185
|
+
|
|
186
|
+
### Added — Input and Terminal Protocols
|
|
187
|
+
|
|
188
|
+
- **Kitty keyboard protocol**: full support with key press/repeat/release events, super/hyper/capsLock/numLock modifiers, and auto-detection (`detectKittySupport`).
|
|
189
|
+
- **SGR mouse events**: DOM-level mouse event system with hit testing, `pointerEvents` prop, and cross-chunk buffering.
|
|
190
|
+
- **Bracketed paste**: automatic paste detection and handling.
|
|
191
|
+
- **Clipboard**: read/write via OSC 52.
|
|
192
|
+
- **Images**: sixel and Kitty image protocol support.
|
|
193
|
+
- **Hyperlinks**: native OSC 8 hyperlink rendering in the pipeline.
|
|
194
|
+
- **Synchronized updates**: mode 2026 for flicker-free rendering.
|
|
195
|
+
- **Cursor styles**: DECSCUSR cursor shape control.
|
|
196
|
+
- **Terminal queries**: cursor position, colors, device attributes, focus, DECRQM, pixel size.
|
|
197
|
+
- **Terminal capability detection**: `termtest` diagnostic suite for terminal feature verification.
|
|
198
|
+
|
|
199
|
+
### Added — Components and Hooks
|
|
200
|
+
|
|
201
|
+
- Core: `Box`, `Text`, `Transform`.
|
|
202
|
+
- Layout: `VirtualList`, `HorizontalVirtualList`, `ScrollbackView`, `ScrollbackList`, `SplitView`, `Fill`.
|
|
203
|
+
- Input: `TextInput`, `TextArea` (with selection and DECSCUSR cursor styles), `EditContext` (unified text editing with invertible ops), `InputBoundary`.
|
|
204
|
+
- UI: `SelectList`, `Table`, `Spinner`, `ProgressBar`, `Image`, `Link`, `Tabs`, `Toast`, `ModalDialog`, `CommandPalette`, `ErrorBoundary` (with resetKeys).
|
|
205
|
+
- Focus: DOM-native focus system with spatial navigation, peer scope system (`activateScope`), `useFocusable`, `useFocusWithin`.
|
|
206
|
+
- Hooks: `useInput`, `useApp`, `useBoxRect`, `useScrollRect`, `useCursor`, `useScrollback`, `useTerm`, `useConsole`.
|
|
207
|
+
- Runtime: `render()`, `run()`, `createApp()`, `createStore()`, `createTerm()`.
|
|
208
|
+
- Testing: `createRenderer()` with auto-refreshing locators, `withDiagnostics()`, `debugTree()`.
|
|
209
|
+
|
|
210
|
+
### Added — Theming
|
|
211
|
+
|
|
212
|
+
- `@silvery/theme` with `ColorPalette` and `Theme` types (33 semantic tokens).
|
|
213
|
+
- 45 built-in color palettes (Snazzy, Monokai, and more).
|
|
214
|
+
- `$token` color resolution in all style props via active theme context.
|
|
215
|
+
- `Box` `theme` prop for per-subtree theme override.
|
|
216
|
+
- `detectTheme()` / `deriveTheme()` for automatic terminal theme detection.
|
|
217
|
+
|
|
218
|
+
### Added — State Management
|
|
219
|
+
|
|
220
|
+
- TEA (The Elm Architecture) optional integration via `@silvery/create`.
|
|
221
|
+
- `zustand-tea` middleware: TEA effects for Zustand stores.
|
|
222
|
+
- `createSlice()` helper for ops-as-data patterns.
|
|
223
|
+
- Four-level state management progression documented: component -> store -> ops-as-data -> pure machine.
|
|
224
|
+
|
|
225
|
+
### Added — Developer Experience
|
|
226
|
+
|
|
227
|
+
- `SILVERY_INSTRUMENT=1`: exposes skip/render counts, cascade depth, scroll tier decisions.
|
|
228
|
+
- `DEBUG=silvery:* DEBUG_LOG=/tmp/silvery.log`: pipeline debug output.
|
|
229
|
+
- `renderString()` for static one-shot rendering.
|
|
230
|
+
- `app.resize()` for virtual terminal resize in tests.
|
|
231
|
+
- Bundle size measurement script for all entry points.
|
|
232
|
+
- Headless screenshot support.
|
|
233
|
+
- Slow frame warnings and render profiling (`SILVERY_PROFILE_RENDER`).
|
|
234
|
+
|
|
235
|
+
### Added — Browser Support
|
|
236
|
+
|
|
237
|
+
- xterm.js render target with VitePress live demo component.
|
|
238
|
+
- `Symbol.dispose` polyfill for Safari compatibility.
|
|
239
|
+
- `child_process` stub for browser builds.
|
|
240
|
+
|
|
241
|
+
### Fixed
|
|
242
|
+
|
|
243
|
+
- Scrollback compaction loop and resize corruption in `run()` runtime.
|
|
244
|
+
- `ScrollbackView` footer auto-sizes to content (deprecate `footerHeight`).
|
|
245
|
+
- `useBoxRect` returning 0x0 in xterm renderer.
|
|
246
|
+
- SGR mouse cross-chunk buffering and browser renderer coordinates.
|
|
247
|
+
- Text background bleed across wrapped lines (BgSegment fix).
|
|
248
|
+
- Output phase true-color row pre-check skipping Map diffs.
|
|
249
|
+
- CJK wide character cursor drift in `bufferToAnsi`.
|
|
250
|
+
- Scrollback promotion jump-up in leftover erasure.
|
|
251
|
+
- Window resize: clear scrollback + screen instead of selective re-emit.
|
|
252
|
+
- Inline mode resize: smart clear and persistent cursor tracking.
|
|
253
|
+
- Raw mode auto-enable in `render()` API for interactive apps.
|
|
254
|
+
- `useInput` graceful no-op without InputContext (renderStatic compat).
|
|
255
|
+
- Focus system: `useFocusWithin` edge cases and peer scope memory.
|
|
256
|
+
|
|
257
|
+
### Performance
|
|
258
|
+
|
|
259
|
+
- Incremental rendering: 28-192x fewer bytes per keystroke vs full re-render.
|
|
260
|
+
- Buffer shift optimization for scroll-only changes (Tier 1).
|
|
261
|
+
- Measure function caching: eliminates O(n) measure overhead.
|
|
262
|
+
- `contentDirty` scoping: border-only paint changes no longer cascade through child subtrees.
|
|
263
|
+
- `layoutChangedThisFrame` flag: eliminates permanent O(N) content-phase recalculation from stale `prevLayout`.
|
|
264
|
+
- Zero-allocation Flexily layout engine option.
|
|
265
|
+
|
|
266
|
+
[Unreleased]: https://github.com/beorn/silvery/compare/v0.9.0...HEAD
|
|
267
|
+
[0.9.0]: https://github.com/beorn/silvery/compare/v0.4.0...v0.9.0
|
|
268
|
+
[0.4.0]: https://github.com/beorn/silvery/compare/v0.2.0...v0.4.0
|
|
269
|
+
[0.2.0]: https://github.com/beorn/silvery/compare/v0.1.0...v0.2.0
|
|
270
|
+
[0.1.0]: https://github.com/beorn/silvery/compare/v0.0.1...v0.1.0
|
|
271
|
+
[0.0.x]: https://github.com/beorn/silvery/releases/tag/v0.0.1
|
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
# Silvery
|
|
1
|
+
# Silvery — React for modern terminal apps
|
|
2
2
|
|
|
3
|
-
**Polished
|
|
3
|
+
**Powerful apps. Polished UIs. Proudly terminal.**
|
|
4
4
|
|
|
5
|
-
Ink-compatible React renderer for
|
|
5
|
+
Ink-compatible React renderer for interactive terminal apps. Same `Box`, `Text`, `useInput` API you know.
|
|
6
6
|
|
|
7
7
|
> **Work in progress.** APIs may change. Feedback welcome.
|
|
8
8
|
|
|
@@ -33,38 +33,56 @@ await render(<Counter />).run()
|
|
|
33
33
|
|
|
34
34
|
- **React 18 + 19** — hooks, refs, effects, suspense — all works
|
|
35
35
|
- **Flexbox layout** — `Box` with `flexDirection`, `padding`, `gap`, `flexGrow`, just like Ink
|
|
36
|
-
- **Ink/Chalk compatible** —
|
|
37
|
-
|
|
38
|
-
###
|
|
39
|
-
|
|
40
|
-
- **
|
|
41
|
-
- **
|
|
42
|
-
- **
|
|
43
|
-
- **
|
|
44
|
-
- **
|
|
45
|
-
- **
|
|
46
|
-
- **
|
|
47
|
-
- **
|
|
48
|
-
- **
|
|
49
|
-
- **
|
|
50
|
-
- **
|
|
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)
|
|
37
|
+
|
|
38
|
+
### Shiny new stuff
|
|
39
|
+
|
|
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
|
|
54
|
+
|
|
55
|
+
### Why Silvery?
|
|
56
|
+
|
|
57
|
+
Silvery grew out of building a complex terminal app — a multi-pane workspace with thousands of nodes. Components needed to know their size during render. Updates needed to be fast. Scroll containers, mouse events, focus scopes, and Playwright-style testing needed to just work. What started as a renderer grew into a layout engine, then 45+ components, theming, testing infrastructure, and eventually a framework.
|
|
58
|
+
|
|
59
|
+
Along the way, three principles emerged. Take the best from the web, stay true to the terminal, and raise the bar for developer ergonomics, architecture composability, and performance.
|
|
60
|
+
|
|
61
|
+
[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)
|
|
51
62
|
|
|
52
63
|
## Packages
|
|
53
64
|
|
|
54
|
-
| Package
|
|
55
|
-
|
|
|
56
|
-
|
|
|
57
|
-
|
|
|
58
|
-
|
|
|
65
|
+
| Package | Description |
|
|
66
|
+
| --------------------------------- | ----------------------------------------------------------------- |
|
|
67
|
+
| `silvery` | Components, hooks, renderer — the one package you need |
|
|
68
|
+
| `@silvery/ink` / `@silvery/chalk` | Ink compatibility — 918/931 Ink 7.0 tests, 32/32 Chalk tests |
|
|
69
|
+
| `@silvery/test` | Playwright-style testing — locators, `press()`, buffer assertions |
|
|
70
|
+
| `@silvery/create` | Composable app builder — `pipe()` providers |
|
|
71
|
+
| `@silvery/theme` | 38 palettes, semantic tokens, auto-detect |
|
|
72
|
+
| `@silvery/commander` | **Beautiful CLIs for free** — help renders through Silvery itself |
|
|
73
|
+
| `@silvery/headless` | Pure state machines — portable, no React |
|
|
74
|
+
| `@silvery/ansi` | Terminal primitives — styling, SGR, detection |
|
|
59
75
|
|
|
60
76
|
## Ecosystem
|
|
61
77
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
| [
|
|
67
|
-
| [
|
|
78
|
+
Standalone projects Silvery builds on — each stands on its own:
|
|
79
|
+
|
|
80
|
+
| Project | What |
|
|
81
|
+
| -------------------------------------- | ----------------------------------------------------------------------- |
|
|
82
|
+
| [Flexily](https://beorn.codes/flexily) | Pure JS flexbox layout engine (Yoga-compatible, 2.5× faster, zero WASM) |
|
|
83
|
+
| [Termless](https://termless.dev) | Headless terminal testing — like Playwright for terminal apps |
|
|
84
|
+
| [terminfo.dev](https://terminfo.dev) | Terminal feature compatibility database (161 features, 19 terminals) |
|
|
85
|
+
| [Loggily](https://beorn.codes/loggily) | Structured logging + tracing + metrics |
|
|
68
86
|
|
|
69
87
|
## Coming
|
|
70
88
|
|
|
@@ -74,6 +92,10 @@ await render(<Counter />).run()
|
|
|
74
92
|
|
|
75
93
|
**Runtimes:** Bun >= 1.0 and Node.js >= 18. CLI (`silvery` command) requires Bun.
|
|
76
94
|
|
|
95
|
+
## Inspirations
|
|
96
|
+
|
|
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).
|
|
98
|
+
|
|
77
99
|
## License
|
|
78
100
|
|
|
79
101
|
MIT
|
package/dist/chalk.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
var CI_ENVS=["CI","GITHUB_ACTIONS","GITLAB_CI","JENKINS_URL","BUILDKITE","CIRCLECI","TRAVIS"];function detectColor(stdout){if(process.env.NO_COLOR!==void 0)return null;let forceColor=process.env.FORCE_COLOR;if(forceColor!==void 0){if(forceColor==="0"||forceColor==="false")return null;if(forceColor==="1")return"basic";if(forceColor==="2")return"256";if(forceColor==="3")return"truecolor";return"basic"}if(!stdout.isTTY)return null;if(process.env.TERM==="dumb")return null;let colorTerm=process.env.COLORTERM;if(colorTerm==="truecolor"||colorTerm==="24bit")return"truecolor";let term=process.env.TERM??"";if(term.includes("truecolor")||term.includes("24bit")||term.includes("xterm-ghostty")||term.includes("xterm-kitty")||term.includes("wezterm"))return"truecolor";if(term.includes("256color")||term.includes("256"))return"256";let termProgram=process.env.TERM_PROGRAM;if(termProgram==="iTerm.app"||termProgram==="Apple_Terminal")return termProgram==="iTerm.app"?"truecolor":"256";if(termProgram==="Ghostty"||termProgram==="WezTerm")return"truecolor";if(process.env.KITTY_WINDOW_ID)return"truecolor";if(term.includes("xterm")||term.includes("color")||term.includes("ansi"))return"basic";if(CI_ENVS.some((env)=>process.env[env]!==void 0))return"basic";if(process.env.WT_SESSION)return"truecolor";return"basic"}import stringWidth from"string-width";var MODIFIERS={reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29],overline:[53,55]},FG_COLORS={black:30,red:31,green:32,yellow:33,blue:34,magenta:35,cyan:36,white:37,blackBright:90,gray:90,grey:90,redBright:91,greenBright:92,yellowBright:93,blueBright:94,magentaBright:95,cyanBright:96,whiteBright:97},BG_COLORS={bgBlack:40,bgRed:41,bgGreen:42,bgYellow:43,bgBlue:44,bgMagenta:45,bgCyan:46,bgWhite:47,bgBlackBright:100,bgGray:100,bgGrey:100,bgRedBright:101,bgGreenBright:102,bgYellowBright:103,bgBlueBright:104,bgMagentaBright:105,bgCyanBright:106,bgWhiteBright:107},ANSI_16_COLORS=[[0,0,0],[128,0,0],[0,128,0],[128,128,0],[0,0,128],[128,0,128],[0,128,128],[192,192,192],[128,128,128],[255,0,0],[0,255,0],[255,255,0],[0,0,255],[255,0,255],[0,255,255],[255,255,255]];function nearestAnsi16(r,g,b){let bestIdx=0,bestDist=1/0;for(let i=0;i<16;i++){let[cr,cg,cb]=ANSI_16_COLORS[i],dist=(r-cr)**2+(g-cg)**2+(b-cb)**2;if(dist<bestDist)bestDist=dist,bestIdx=i}return bestIdx}function rgbToAnsi256(r,g,b){if(r===g&&g===b){if(r<8)return 16;if(r>248)return 231;return Math.round((r-8)/247*24)+232}let ri=Math.round(r/255*5),gi=Math.round(g/255*5),bi=Math.round(b/255*5);return 16+36*ri+6*gi+bi}function fgFromRgb(r,g,b,level){if(level==="truecolor")return`38;2;${r};${g};${b}`;if(level==="256")return`38;5;${rgbToAnsi256(r,g,b)}`;let idx=nearestAnsi16(r,g,b);return idx<8?`${30+idx}`:`${82+idx}`}function bgFromRgb(r,g,b,level){if(level==="truecolor")return`48;2;${r};${g};${b}`;if(level==="256")return`48;5;${rgbToAnsi256(r,g,b)}`;let idx=nearestAnsi16(r,g,b);return idx<8?`${40+idx}`:`${92+idx}`}function hexToRgb(hex){if(hex[0]!=="#")return null;let h=hex.slice(1);if(h.length===3)return[parseInt(h[0]+h[0],16),parseInt(h[1]+h[1],16),parseInt(h[2]+h[2],16)];if(h.length===6)return[parseInt(h.slice(0,2),16),parseInt(h.slice(2,4),16),parseInt(h.slice(4,6),16)];return null}var THEME_TOKEN_DEFAULTS={primary:33,secondary:36,accent:35,error:31,warning:33,success:32,info:36,muted:2,link:34,border:90,surface:37};function resolveToken(name,theme){if(!theme)return;let token=name.startsWith("$")?name.slice(1):name;if(token.startsWith("color")){let idx=parseInt(token.slice(5),10);if(idx>=0&&idx<16&&theme.palette&&idx<theme.palette.length)return theme.palette[idx]}let key=token.replace(/-/g,""),val=theme[key];return typeof val==="string"?val:void 0}var ESC="\x1B[",KNOWN_METHODS=new Set(["hex","rgb","bgHex","bgRgb","ansi256","bgAnsi256","resolve"]),THEME_TOKENS=new Set(["primary","secondary","accent","error","warning","success","info","muted","link","border","surface"]);function fromChalkLevel(n){if(n<=0)return null;if(n===1)return"basic";if(n===2)return"256";return"truecolor"}function toChalkLevel(cl){if(cl===null)return 0;if(cl==="basic")return 1;if(cl==="256")return 2;return 3}function createStyle(options){let ref={level:null,theme:options?.theme};if(options?.level!==void 0)ref.level=options.level;else try{ref.level=detectColor(process.stdout)}catch{ref.level=null}return createChainWithRef({opens:[],closes:[]},ref)}var style=createStyle();function createChainWithRef(state,ref){let proxyRef={proxy:null},proxy=new Proxy(function(){},{apply(_target,_thisArg,args){let level=ref.level;if(state.visible&&level===null)return"";let text;if(args.length===0)text="";else if(Array.isArray(args[0])&&"raw"in args[0])text=String.raw(args[0],...args.slice(1));else if(args.length>1)text=args.map((a)=>String(a??"")).join(" ");else text=String(args[0]??"");if(text==="")return"";if(level===null||state.opens.length===0)return text;let open=`${ESC}${state.opens.join(";")}m`,close=`${ESC}${state.closes.join(";")}m`;for(let closeCode of state.closes){let closeSeq=`${ESC}${closeCode}m`,parts=text.split(closeSeq);if(parts.length>1)text=parts.join(`${closeSeq}${open}`)}if(text.includes(`
|
|
2
|
+
`))text=text.replace(/\r?\n/g,`${close}$&${open}`);return`${open}${text}${close}`},get(_target,prop){if(typeof prop==="symbol")return;if(prop==="level")return toChalkLevel(ref.level);if(prop==="resolve")return(token)=>resolveToken(token,ref.theme);if(prop==="visible")return createChainWithRef({...state,visible:!0},ref);if(prop==="call"||prop==="apply"||prop==="bind")return Function.prototype[prop].bind(proxyRef.proxy);let level=ref.level;if(prop==="hex"||prop==="bgHex")return(color)=>{if(level===null)return createChainWithRef(state,ref);let rgb=hexToRgb(color);if(!rgb)return createChainWithRef(state,ref);let code=prop==="hex"?fgFromRgb(rgb[0],rgb[1],rgb[2],level):bgFromRgb(rgb[0],rgb[1],rgb[2],level),close=prop==="hex"?"39":"49";return createChainWithRef({opens:[...state.opens,code],closes:[...state.closes,close]},ref)};if(prop==="rgb"||prop==="bgRgb")return(r,g,b)=>{if(level===null)return createChainWithRef(state,ref);let code=prop==="rgb"?fgFromRgb(r,g,b,level):bgFromRgb(r,g,b,level),close=prop==="rgb"?"39":"49";return createChainWithRef({opens:[...state.opens,code],closes:[...state.closes,close]},ref)};if(prop==="ansi256")return(code)=>{if(level===null)return createChainWithRef(state,ref);return createChainWithRef({opens:[...state.opens,`38;5;${code}`],closes:[...state.closes,"39"]},ref)};if(prop==="bgAnsi256")return(code)=>{if(level===null)return createChainWithRef(state,ref);return createChainWithRef({opens:[...state.opens,`48;5;${code}`],closes:[...state.closes,"49"]},ref)};if(prop in MODIFIERS){if(level===null)return createChainWithRef(state,ref);let[open,close]=MODIFIERS[prop];return createChainWithRef({opens:[...state.opens,String(open)],closes:[...state.closes,String(close)]},ref)}if(prop in FG_COLORS){if(level===null)return createChainWithRef(state,ref);return createChainWithRef({opens:[...state.opens,String(FG_COLORS[prop])],closes:[...state.closes,"39"]},ref)}if(prop in BG_COLORS){if(level===null)return createChainWithRef(state,ref);return createChainWithRef({opens:[...state.opens,String(BG_COLORS[prop])],closes:[...state.closes,"49"]},ref)}if(THEME_TOKENS.has(prop)){if(level===null)return createChainWithRef(state,ref);let hex=resolveToken(prop,ref.theme);if(hex){let rgb=hexToRgb(hex);if(rgb){let code=fgFromRgb(rgb[0],rgb[1],rgb[2],level);if(prop==="link")return createChainWithRef({opens:[...state.opens,code,"4"],closes:[...state.closes,"39","24"]},ref);return createChainWithRef({opens:[...state.opens,code],closes:[...state.closes,"39"]},ref)}}let fallback=THEME_TOKEN_DEFAULTS[prop];if(fallback!==void 0){if(prop==="muted")return createChainWithRef({opens:[...state.opens,String(fallback)],closes:[...state.closes,"22"]},ref);if(prop==="link")return createChainWithRef({opens:[...state.opens,String(fallback),"4"],closes:[...state.closes,"39","24"]},ref);return createChainWithRef({opens:[...state.opens,String(fallback)],closes:[...state.closes,"39"]},ref)}}return},set(_target,prop,value){if(prop==="level")return ref.level=fromChalkLevel(value),!0;return!1},has(_target,prop){if(prop==="level")return!0;if(typeof prop==="symbol")return!1;return prop in MODIFIERS||prop in FG_COLORS||prop in BG_COLORS||THEME_TOKENS.has(prop)||KNOWN_METHODS.has(prop)}});return proxyRef.proxy=proxy,proxy}function toChalkLevel2(cl){if(cl===null)return 0;if(cl==="basic")return 1;if(cl==="256")return 2;return 3}function fromChalkLevel2(level){if(level===0)return null;if(level===1)return"basic";if(level===2)return"256";return"truecolor"}var detectedColor=typeof process<"u"&&process.stdout?detectColor(process.stdout):null,chalk=createStyle({level:detectedColor}),chalk_default=chalk;class Chalk{constructor(options){if(options?.level!==void 0){let lvl=options.level;if(typeof lvl!=="number"||!Number.isInteger(lvl)||lvl<0||lvl>3)throw Error("The `level` option should be an integer from 0 to 3")}return createStyle({level:fromChalkLevel2(options?.level??toChalkLevel2(detectedColor))})}}var detectedLevel=toChalkLevel2(detectedColor),supportsColor=detectedLevel===0?!1:{level:detectedLevel},supportsColorStderr=(()=>{if(!process?.stderr)return!1;let level=toChalkLevel2(detectColor(process.stderr));return level===0?!1:{level}})(),modifierNames=["reset","bold","dim","italic","underline","overline","inverse","hidden","strikethrough","visible"],foregroundColorNames=["black","red","green","yellow","blue","magenta","cyan","white","gray","grey","blackBright","redBright","greenBright","yellowBright","blueBright","magentaBright","cyanBright","whiteBright"],backgroundColorNames=["bgBlack","bgRed","bgGreen","bgYellow","bgBlue","bgMagenta","bgCyan","bgWhite","bgGray","bgGrey","bgBlackBright","bgRedBright","bgGreenBright","bgYellowBright","bgBlueBright","bgMagentaBright","bgCyanBright","bgWhiteBright"],colorNames=[...foregroundColorNames,...backgroundColorNames];export{toChalkLevel2 as toChalkLevel,supportsColorStderr,supportsColor,modifierNames,fromChalkLevel2 as fromChalkLevel,foregroundColorNames,detectColor,chalk_default as default,colorNames,backgroundColorNames,Chalk};
|
|
3
|
+
|
|
4
|
+
//# debugId=1708C60C7309496864756E2164756E21
|