silvery 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/README.md +41 -145
  2. package/package.json +64 -12
  3. package/src/index.ts +67 -1
  4. package/src/runtime.ts +4 -0
  5. package/src/theme.ts +4 -0
  6. package/src/ui/animation.ts +2 -0
  7. package/src/ui/ansi.ts +2 -0
  8. package/src/ui/cli.ts +2 -0
  9. package/src/ui/display.ts +2 -0
  10. package/src/ui/image.ts +2 -0
  11. package/src/ui/input.ts +2 -0
  12. package/src/ui/progress.ts +2 -0
  13. package/src/ui/react.ts +2 -0
  14. package/src/ui/utils.ts +2 -0
  15. package/src/ui/wrappers.ts +2 -0
  16. package/src/ui.ts +4 -0
  17. package/examples/CLAUDE.md +0 -75
  18. package/examples/_banner.tsx +0 -60
  19. package/examples/cli.ts +0 -228
  20. package/examples/index.md +0 -101
  21. package/examples/inline/inline-nontty.tsx +0 -98
  22. package/examples/inline/inline-progress.tsx +0 -79
  23. package/examples/inline/inline-simple.tsx +0 -63
  24. package/examples/inline/scrollback.tsx +0 -185
  25. package/examples/interactive/_input-debug.tsx +0 -110
  26. package/examples/interactive/_stdin-test.ts +0 -71
  27. package/examples/interactive/_textarea-bare.tsx +0 -45
  28. package/examples/interactive/aichat/components.tsx +0 -468
  29. package/examples/interactive/aichat/index.tsx +0 -207
  30. package/examples/interactive/aichat/script.ts +0 -460
  31. package/examples/interactive/aichat/state.ts +0 -326
  32. package/examples/interactive/aichat/types.ts +0 -19
  33. package/examples/interactive/app-todo.tsx +0 -198
  34. package/examples/interactive/async-data.tsx +0 -208
  35. package/examples/interactive/cli-wizard.tsx +0 -332
  36. package/examples/interactive/clipboard.tsx +0 -183
  37. package/examples/interactive/components.tsx +0 -463
  38. package/examples/interactive/data-explorer.tsx +0 -506
  39. package/examples/interactive/dev-tools.tsx +0 -379
  40. package/examples/interactive/explorer.tsx +0 -747
  41. package/examples/interactive/gallery.tsx +0 -652
  42. package/examples/interactive/inline-bench.tsx +0 -136
  43. package/examples/interactive/kanban.tsx +0 -267
  44. package/examples/interactive/layout-ref.tsx +0 -185
  45. package/examples/interactive/outline.tsx +0 -171
  46. package/examples/interactive/paste-demo.tsx +0 -198
  47. package/examples/interactive/scroll.tsx +0 -77
  48. package/examples/interactive/search-filter.tsx +0 -240
  49. package/examples/interactive/task-list.tsx +0 -279
  50. package/examples/interactive/terminal.tsx +0 -798
  51. package/examples/interactive/textarea.tsx +0 -103
  52. package/examples/interactive/theme.tsx +0 -336
  53. package/examples/interactive/transform.tsx +0 -256
  54. package/examples/interactive/virtual-10k.tsx +0 -413
  55. package/examples/kitty/canvas.tsx +0 -519
  56. package/examples/kitty/generate-samples.ts +0 -236
  57. package/examples/kitty/image-component.tsx +0 -273
  58. package/examples/kitty/images.tsx +0 -604
  59. package/examples/kitty/input.tsx +0 -371
  60. package/examples/kitty/keys.tsx +0 -378
  61. package/examples/kitty/paint.tsx +0 -1017
  62. package/examples/layout/dashboard.tsx +0 -551
  63. package/examples/layout/live-resize.tsx +0 -290
  64. package/examples/layout/overflow.tsx +0 -51
  65. package/examples/playground/README.md +0 -69
  66. package/examples/playground/build.ts +0 -61
  67. package/examples/playground/index.html +0 -420
  68. package/examples/playground/playground-app.tsx +0 -416
  69. package/examples/runtime/elm-counter.tsx +0 -206
  70. package/examples/runtime/hello-runtime.tsx +0 -73
  71. package/examples/runtime/pipe-composition.tsx +0 -184
  72. package/examples/runtime/run-counter.tsx +0 -78
  73. package/examples/runtime/runtime-counter.tsx +0 -197
  74. package/examples/screenshots/generate.tsx +0 -563
  75. package/examples/scrollback-perf.tsx +0 -230
  76. package/examples/viewer.tsx +0 -654
  77. package/examples/web/build.ts +0 -365
  78. package/examples/web/canvas-app.tsx +0 -80
  79. package/examples/web/canvas.html +0 -89
  80. package/examples/web/dom-app.tsx +0 -81
  81. package/examples/web/dom.html +0 -113
  82. package/examples/web/showcase-app.tsx +0 -107
  83. package/examples/web/showcase.html +0 -34
  84. package/examples/web/showcases/index.tsx +0 -56
  85. package/examples/web/viewer-app.tsx +0 -555
  86. package/examples/web/viewer.html +0 -30
  87. package/examples/web/xterm-app.tsx +0 -105
  88. package/examples/web/xterm.html +0 -118
@@ -1,113 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>silvery DOM Demo</title>
7
- <style>
8
- * {
9
- box-sizing: border-box;
10
- }
11
- body {
12
- margin: 0;
13
- padding: 20px;
14
- background: #1a1a2e;
15
- color: #eee;
16
- font-family: system-ui, sans-serif;
17
- }
18
- h1 {
19
- color: #4ec9b0;
20
- margin-bottom: 10px;
21
- }
22
- p {
23
- color: #808080;
24
- margin-top: 0;
25
- }
26
- #app {
27
- border: 1px solid #333;
28
- min-height: 300px;
29
- }
30
- .info {
31
- margin-top: 20px;
32
- padding: 15px;
33
- background: #16213e;
34
- border-radius: 4px;
35
- }
36
- .info h3 {
37
- color: #9cdcfe;
38
- margin-top: 0;
39
- }
40
- .info ul {
41
- margin: 0;
42
- padding-left: 20px;
43
- }
44
- .info li {
45
- margin: 5px 0;
46
- }
47
- .comparison {
48
- display: flex;
49
- gap: 20px;
50
- margin-top: 20px;
51
- }
52
- .comparison > div {
53
- flex: 1;
54
- }
55
- .comparison h3 {
56
- margin-top: 0;
57
- }
58
- code {
59
- background: #0f0f1a;
60
- padding: 2px 6px;
61
- border-radius: 3px;
62
- font-family: monospace;
63
- }
64
- </style>
65
- </head>
66
- <body>
67
- <h1>silvery DOM Adapter</h1>
68
- <p>React components rendered to DOM elements via silvery - try selecting text!</p>
69
-
70
- <div id="app"></div>
71
-
72
- <div class="comparison">
73
- <div class="info">
74
- <h3>DOM Advantages</h3>
75
- <ul>
76
- <li>Native text selection</li>
77
- <li>Screen reader accessible</li>
78
- <li>Browser font rendering</li>
79
- <li>CSS hover/focus states</li>
80
- <li>DevTools inspection</li>
81
- </ul>
82
- </div>
83
- <div class="info">
84
- <h3>Canvas Advantages</h3>
85
- <ul>
86
- <li>Pixel-perfect control</li>
87
- <li>Single DOM element</li>
88
- <li>Faster batch updates</li>
89
- <li>Export to image</li>
90
- <li>WebGL upgrade path</li>
91
- </ul>
92
- </div>
93
- </div>
94
-
95
- <div class="info">
96
- <h3>Code</h3>
97
- <pre><code>import { renderToDOM, Box, Text, useContentRect } from '@silvery/term/dom';
98
-
99
- function App() {
100
- const { width, height } = useContentRect();
101
- return (
102
- &lt;Box borderStyle="single"&gt;
103
- &lt;Text&gt;Size: {width}px × {height}px&lt;/Text&gt;
104
- &lt;/Box&gt;
105
- );
106
- }
107
-
108
- renderToDOM(&lt;App /&gt;, container);</code></pre>
109
- </div>
110
-
111
- <script type="module" src="./dist/dom-app.js"></script>
112
- </body>
113
- </html>
@@ -1,107 +0,0 @@
1
- /**
2
- * Showcase Demo Entry Point
3
- *
4
- * Renders silvery showcase components in xterm.js for embedding in VitePress docs.
5
- * Usage: showcase.html?demo=dashboard
6
- */
7
-
8
- import React from "react"
9
- import { Terminal } from "@xterm/xterm"
10
- import { FitAddon } from "@xterm/addon-fit"
11
- import { renderToXterm } from "@silvery/term/xterm/index.ts"
12
- import { SHOWCASES } from "./showcases/index.js"
13
-
14
- // Read demo name from URL params
15
- const params = new URLSearchParams(window.location.search)
16
- const demoName = params.get("demo") || "dashboard"
17
-
18
- // Get the showcase component
19
- const ShowcaseComponent = SHOWCASES[demoName]
20
-
21
- if (!ShowcaseComponent) {
22
- document.body.innerHTML = `<p style="color: red; padding: 20px;">Unknown demo: ${demoName}. Available: ${Object.keys(SHOWCASES).join(", ")}</p>`
23
- } else {
24
- // Set up xterm.js terminal
25
- const termContainer = document.getElementById("terminal") as HTMLElement
26
- if (termContainer) {
27
- const term = new Terminal({
28
- cursorBlink: true,
29
- convertEol: true,
30
- cols: 80,
31
- rows: 24,
32
- fontFamily: "'Cascadia Code', 'Fira Code', 'JetBrains Mono', Menlo, monospace",
33
- fontSize: 14,
34
- theme: {
35
- // Catppuccin Mocha palette — matches @silvery/theme's catppuccinMocha
36
- background: "#1E1E2E",
37
- foreground: "#CDD6F4",
38
- cursor: "#CDD6F4",
39
- cursorAccent: "#1E1E2E",
40
- selectionBackground: "#6C7086",
41
- selectionForeground: "#CDD6F4",
42
- black: "#11111B",
43
- red: "#F38BA8",
44
- green: "#A6E3A1",
45
- yellow: "#F9E2AF",
46
- blue: "#89B4FA",
47
- magenta: "#CBA6F7",
48
- cyan: "#94E2D5",
49
- white: "#A6ADC8",
50
- brightBlack: "#313244",
51
- brightRed: "#FAB387",
52
- brightGreen: "#BEF0B7",
53
- brightYellow: "#FFF0CD",
54
- brightBlue: "#A7C9FF",
55
- brightMagenta: "#F5C2E7",
56
- brightCyan: "#AFF0E4",
57
- brightWhite: "#CDD6F4",
58
- },
59
- })
60
-
61
- const fitAddon = new FitAddon()
62
- term.loadAddon(fitAddon)
63
- term.open(termContainer)
64
- fitAddon.fit()
65
-
66
- const instance = renderToXterm(<ShowcaseComponent />, term, {
67
- input: true, // enables useInput, useMouse, useTerminalFocused
68
- handleFocusCycling: false, // showcases handle Tab/Escape themselves
69
- })
70
-
71
- // Signal to parent (LiveDemo.vue) that the demo loaded successfully
72
- window.parent.postMessage({ type: "silvery-ready" }, "*")
73
-
74
- // Click anywhere on the terminal container to ensure focus
75
- // (browsers restrict auto-focus in iframes, so click-to-focus is essential)
76
- termContainer.addEventListener("click", () => term.focus())
77
-
78
- // Auto-focus terminal so keyboard input works immediately
79
- term.focus()
80
-
81
- // Re-fit and re-render on window resize
82
- // Must use resize() (not refresh()) — clears the old buffer so the
83
- // next render does a full repaint at the new dimensions.
84
- window.addEventListener("resize", () => {
85
- fitAddon.fit()
86
- instance.resize(term.cols, term.rows)
87
- })
88
-
89
- // Clean up when parent frame navigates away (VitePress SPA navigation)
90
- window.addEventListener("message", (event) => {
91
- if (event.data?.type === "silvery-cleanup") {
92
- instance.unmount()
93
- term.dispose()
94
- }
95
- })
96
-
97
- // Also clean up if the iframe is being unloaded (e.g., src removed)
98
- window.addEventListener("pagehide", () => {
99
- instance.unmount()
100
- term.dispose()
101
- })
102
-
103
- // Expose for debugging
104
- ;(window as any).silveryInstance = instance
105
- ;(window as any).xtermTerminal = term
106
- }
107
- }
@@ -1,34 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Silvery Showcase</title>
7
- <!-- Local dev path -->
8
- <link rel="stylesheet" href="../../node_modules/@xterm/xterm/css/xterm.css" />
9
- <!-- VitePress production path (copied by build.ts) -->
10
- <link rel="stylesheet" href="./xterm/xterm.css" />
11
- <style>
12
- * {
13
- box-sizing: border-box;
14
- margin: 0;
15
- padding: 0;
16
- }
17
- html,
18
- body {
19
- width: 100%;
20
- height: 100%;
21
- overflow: hidden;
22
- background: #1a1a2e;
23
- }
24
- #terminal {
25
- width: 100%;
26
- height: 100%;
27
- }
28
- </style>
29
- </head>
30
- <body>
31
- <div id="terminal"></div>
32
- <script type="module" src="./dist/showcase-app.js"></script>
33
- </body>
34
- </html>
@@ -1,56 +0,0 @@
1
- /**
2
- * Showcase registry — bridges terminal examples for web rendering.
3
- *
4
- * Each entry maps a URL-friendly key to a terminal example component.
5
- * These are the SAME components used by `bun examples/<name>` — no
6
- * separate web implementations.
7
- *
8
- * showcase-app.tsx renders them via renderToXterm() with input: true,
9
- * giving full useInput/useMouse/useTerminalFocused support.
10
- *
11
- * The 9 flagship showcases have clean URL keys (silvery.dev/examples/<key>):
12
- * aichat, gallery, kanban, explorer, wizard, dashboard, terminal, components, theme
13
- */
14
-
15
- import React from "react"
16
-
17
- // Import components from terminal examples (the single source of truth)
18
- import { Dashboard } from "../../layout/dashboard.js"
19
- import { KanbanBoard } from "../../interactive/kanban.js"
20
- import { CliWizard } from "../../interactive/cli-wizard.js"
21
- import { DevTools } from "../../interactive/dev-tools.js"
22
- import { DataExplorer } from "../../interactive/data-explorer.js"
23
- import { ScrollExample } from "../../interactive/scroll.js"
24
- import { AIChat, SCRIPT } from "../../interactive/aichat/index.js"
25
- import { SearchApp } from "../../interactive/search-filter.js"
26
- import { TransformDemo } from "../../interactive/transform.js"
27
- import { NoteEditor } from "../../interactive/textarea.js"
28
- import { Gallery } from "../../interactive/gallery.js"
29
- import { Explorer } from "../../interactive/explorer.js"
30
- import { TerminalDemo } from "../../interactive/terminal.js"
31
- import { ComponentsApp } from "../../interactive/components.js"
32
- import { ThemeExplorer } from "../../interactive/theme.js"
33
-
34
- /** Registry mapping URL keys to showcase components. */
35
- export const SHOWCASES: Record<string, () => JSX.Element> = {
36
- // --- 9 Flagship Showcases (clean URL keys) ---
37
- aichat: () => <AIChat script={SCRIPT} autoStart={false} fastMode={false} />,
38
- gallery: Gallery,
39
- kanban: KanbanBoard,
40
- explorer: Explorer,
41
- wizard: CliWizard,
42
- dashboard: Dashboard,
43
- terminal: () => <TerminalDemo kittySupported={false} />,
44
- components: ComponentsApp,
45
- theme: ThemeExplorer,
46
-
47
- // --- Additional terminal examples ---
48
- "ai-chat": () => <AIChat script={SCRIPT} autoStart={false} fastMode={false} />,
49
- "cli-wizard": CliWizard,
50
- "dev-tools": DevTools,
51
- "data-explorer": DataExplorer,
52
- scroll: ScrollExample,
53
- "search-filter": SearchApp,
54
- transform: TransformDemo,
55
- textarea: NoteEditor,
56
- }