@silvery/examples 0.5.5 → 0.17.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.
Files changed (43) hide show
  1. package/apps/aichat/index.tsx +1 -1
  2. package/apps/app-todo.tsx +2 -2
  3. package/apps/async-data.tsx +2 -2
  4. package/apps/cli-wizard.tsx +2 -2
  5. package/apps/clipboard.tsx +2 -2
  6. package/apps/components.tsx +1 -1
  7. package/apps/data-explorer.tsx +2 -2
  8. package/apps/dev-tools.tsx +2 -2
  9. package/apps/explorer.tsx +1 -1
  10. package/apps/gallery.tsx +1 -1
  11. package/apps/inline-bench.tsx +2 -2
  12. package/apps/kanban.tsx +2 -2
  13. package/apps/layout-ref.tsx +2 -2
  14. package/apps/outline.tsx +2 -2
  15. package/apps/panes/index.tsx +1 -1
  16. package/apps/paste-demo.tsx +2 -2
  17. package/apps/scroll.tsx +5 -2
  18. package/apps/search-filter.tsx +2 -2
  19. package/apps/selection.tsx +5 -1
  20. package/apps/spatial-focus-demo.tsx +5 -1
  21. package/apps/task-list.tsx +2 -2
  22. package/apps/terminal-caps-demo.tsx +2 -19
  23. package/apps/terminal.tsx +2 -18
  24. package/apps/text-selection-demo.tsx +5 -1
  25. package/apps/textarea.tsx +2 -2
  26. package/apps/theme.tsx +2 -2
  27. package/apps/transform.tsx +2 -2
  28. package/apps/virtual-10k.tsx +2 -2
  29. package/apps/vterm-demo/index.tsx +1 -1
  30. package/components/counter.tsx +5 -1
  31. package/components/hello.tsx +5 -1
  32. package/components/progress-bar.tsx +5 -1
  33. package/components/select-list.tsx +5 -1
  34. package/components/spinner.tsx +5 -1
  35. package/components/text-input.tsx +5 -1
  36. package/components/virtual-list.tsx +5 -1
  37. package/dist/cli.mjs +6 -7
  38. package/dist/cli.mjs.map +1 -1
  39. package/layout/dashboard.tsx +2 -2
  40. package/layout/live-resize.tsx +2 -2
  41. package/layout/overflow.tsx +2 -2
  42. package/layout/text-layout.tsx +2 -2
  43. package/package.json +2 -2
@@ -137,7 +137,7 @@ export async function main() {
137
137
  }
138
138
 
139
139
  if (import.meta.main) {
140
- main().catch(console.error)
140
+ await main()
141
141
  }
142
142
 
143
143
  // ============================================================================
package/apps/app-todo.tsx CHANGED
@@ -187,7 +187,7 @@ const app = pipe(
187
187
  // Main
188
188
  // ============================================================================
189
189
 
190
- async function main() {
190
+ export async function main() {
191
191
  // 3. run() needs no arguments — element and terminal are already bound
192
192
  const handle = (await app.run()) as AppHandle<State>
193
193
 
@@ -197,5 +197,5 @@ async function main() {
197
197
  }
198
198
 
199
199
  if (import.meta.main) {
200
- main().catch(console.error)
200
+ await main()
201
201
  }
@@ -180,7 +180,7 @@ export function AsyncDataApp() {
180
180
  // Main
181
181
  // ============================================================================
182
182
 
183
- async function main() {
183
+ export async function main() {
184
184
  using term = createTerm()
185
185
  const { waitUntilExit } = await render(
186
186
  <ExampleBanner meta={meta} controls="r refresh Esc/q quit">
@@ -192,5 +192,5 @@ async function main() {
192
192
  }
193
193
 
194
194
  if (import.meta.main) {
195
- main().catch(console.error)
195
+ await main()
196
196
  }
@@ -316,7 +316,7 @@ export function CliWizard() {
316
316
  // Main
317
317
  // ============================================================================
318
318
 
319
- async function main() {
319
+ export async function main() {
320
320
  using term = createTerm()
321
321
  const { waitUntilExit } = await render(
322
322
  <ExampleBanner meta={meta} controls="j/k navigate Enter select q/Esc quit">
@@ -328,5 +328,5 @@ async function main() {
328
328
  }
329
329
 
330
330
  if (import.meta.main) {
331
- main().catch(console.error)
331
+ await main()
332
332
  }
@@ -167,7 +167,7 @@ export function ClipboardDemo() {
167
167
  // Main
168
168
  // ============================================================================
169
169
 
170
- async function main() {
170
+ export async function main() {
171
171
  using term = createTerm()
172
172
  const { waitUntilExit } = await render(
173
173
  <ExampleBanner meta={meta} controls="j/k navigate c copy v paste Esc/q quit">
@@ -179,5 +179,5 @@ async function main() {
179
179
  }
180
180
 
181
181
  if (import.meta.main) {
182
- main().catch(console.error)
182
+ await main()
183
183
  }
@@ -654,5 +654,5 @@ export async function main() {
654
654
  }
655
655
 
656
656
  if (import.meta.main) {
657
- main().catch(console.error)
657
+ await main()
658
658
  }
@@ -474,7 +474,7 @@ export function DataExplorer() {
474
474
  // Main
475
475
  // ============================================================================
476
476
 
477
- async function main() {
477
+ export async function main() {
478
478
  using term = createTerm()
479
479
  const { waitUntilExit } = await render(
480
480
  <ExampleBanner meta={meta} controls="j/k navigate d/u half-page g/G start/end / search Esc/q quit">
@@ -486,5 +486,5 @@ async function main() {
486
486
  }
487
487
 
488
488
  if (import.meta.main) {
489
- main().catch(console.error)
489
+ await main()
490
490
  }
@@ -379,7 +379,7 @@ export function DevTools() {
379
379
  // Main
380
380
  // ============================================================================
381
381
 
382
- async function main() {
382
+ export async function main() {
383
383
  using term = createTerm()
384
384
  const { waitUntilExit } = await render(
385
385
  <ExampleBanner meta={meta} controls="j/k navigate g/G start/end d/i/w/e add log c clear Esc/q quit">
@@ -391,5 +391,5 @@ async function main() {
391
391
  }
392
392
 
393
393
  if (import.meta.main) {
394
- main().catch(console.error)
394
+ await main()
395
395
  }
package/apps/explorer.tsx CHANGED
@@ -727,5 +727,5 @@ export async function main() {
727
727
  }
728
728
 
729
729
  if (import.meta.main) {
730
- main().catch(console.error)
730
+ await main()
731
731
  }
package/apps/gallery.tsx CHANGED
@@ -649,5 +649,5 @@ export async function main() {
649
649
  }
650
650
 
651
651
  if (import.meta.main) {
652
- main().catch(console.error)
652
+ await main()
653
653
  }
@@ -111,7 +111,7 @@ function printComparison(full: BenchResult, incr: BenchResult): void {
111
111
  )
112
112
  }
113
113
 
114
- async function main() {
114
+ export async function main() {
115
115
  console.log(`\n═══ Inline Output Phase: Full vs Incremental (${RUNS} runs) ═══\n`)
116
116
 
117
117
  const configs = [
@@ -134,5 +134,5 @@ async function main() {
134
134
  }
135
135
 
136
136
  if (import.meta.main) {
137
- main().catch(console.error)
137
+ await main()
138
138
  }
package/apps/kanban.tsx CHANGED
@@ -249,7 +249,7 @@ export function KanbanBoard() {
249
249
  // Main
250
250
  // ============================================================================
251
251
 
252
- async function main() {
252
+ export async function main() {
253
253
  using term = createTerm()
254
254
  const { waitUntilExit } = await render(
255
255
  <ExampleBanner meta={meta} controls="h/l column j/k card </> move Esc/q quit">
@@ -261,5 +261,5 @@ async function main() {
261
261
  }
262
262
 
263
263
  if (import.meta.main) {
264
- main().catch(console.error)
264
+ await main()
265
265
  }
@@ -157,7 +157,7 @@ export function LayoutRefApp() {
157
157
  // Main
158
158
  // ============================================================================
159
159
 
160
- async function main() {
160
+ export async function main() {
161
161
  using term = createTerm()
162
162
  const { waitUntilExit } = await render(
163
163
  <ExampleBanner meta={meta} controls="i inspect Esc/q quit">
@@ -169,5 +169,5 @@ async function main() {
169
169
  }
170
170
 
171
171
  if (import.meta.main) {
172
- main().catch(console.error)
172
+ await main()
173
173
  }
package/apps/outline.tsx CHANGED
@@ -144,7 +144,7 @@ export function OutlineDemo() {
144
144
  // Main
145
145
  // ============================================================================
146
146
 
147
- async function main() {
147
+ export async function main() {
148
148
  using term = createTerm()
149
149
  const { waitUntilExit } = await render(
150
150
  <ExampleBanner meta={meta} controls="Tab toggle h/l style Esc/q quit">
@@ -156,5 +156,5 @@ async function main() {
156
156
  }
157
157
 
158
158
  if (import.meta.main) {
159
- main().catch(console.error)
159
+ await main()
160
160
  }
@@ -199,5 +199,5 @@ export async function main() {
199
199
  }
200
200
 
201
201
  if (import.meta.main) {
202
- main().catch(console.error)
202
+ await main()
203
203
  }
@@ -169,7 +169,7 @@ export function PasteDemo() {
169
169
  // Main
170
170
  // ============================================================================
171
171
 
172
- async function main() {
172
+ export async function main() {
173
173
  using term = createTerm()
174
174
  const { waitUntilExit } = await render(
175
175
  <ExampleBanner meta={meta} controls="Paste text to see events x clear Esc/q quit">
@@ -181,5 +181,5 @@ async function main() {
181
181
  }
182
182
 
183
183
  if (import.meta.main) {
184
- main().catch(console.error)
184
+ await main()
185
185
  }
package/apps/scroll.tsx CHANGED
@@ -65,8 +65,7 @@ export function ScrollExample() {
65
65
  )
66
66
  }
67
67
 
68
- // Run the app
69
- if (import.meta.main) {
68
+ export async function main() {
70
69
  using term = createTerm()
71
70
  await render(
72
71
  <ExampleBanner meta={meta} controls="j/k navigate Esc/q quit">
@@ -75,3 +74,7 @@ if (import.meta.main) {
75
74
  term,
76
75
  )
77
76
  }
77
+
78
+ if (import.meta.main) {
79
+ await main()
80
+ }
@@ -224,7 +224,7 @@ export function SearchApp() {
224
224
  // Main
225
225
  // ============================================================================
226
226
 
227
- async function main() {
227
+ export async function main() {
228
228
  using term = createTerm()
229
229
  const { waitUntilExit } = await render(
230
230
  <ExampleBanner meta={meta} controls="type to search Esc quit">
@@ -236,5 +236,5 @@ async function main() {
236
236
  }
237
237
 
238
238
  if (import.meta.main) {
239
- main().catch(console.error)
239
+ await main()
240
240
  }
@@ -336,7 +336,11 @@ export const meta = {
336
336
  features: ["Selection model", "mode ladder", "multi-select", "text editing"],
337
337
  }
338
338
 
339
- if (import.meta.main) {
339
+ export async function main() {
340
340
  using handle = await run(<SelectionDemo />, { mode: "fullscreen" })
341
341
  await handle.waitUntilExit()
342
342
  }
343
+
344
+ if (import.meta.main) {
345
+ await main()
346
+ }
@@ -362,7 +362,11 @@ export const meta = {
362
362
  features: ["spatial navigation", "kanban layout", "varied card heights", "column focus tracking"],
363
363
  }
364
364
 
365
- if (import.meta.main) {
365
+ export async function main() {
366
366
  using handle = await run(<SpatialFocusBoard />, { mode: "fullscreen" })
367
367
  await handle.waitUntilExit()
368
368
  }
369
+
370
+ if (import.meta.main) {
371
+ await main()
372
+ }
@@ -255,7 +255,7 @@ export function TaskList() {
255
255
  // Main
256
256
  // ============================================================================
257
257
 
258
- async function main() {
258
+ export async function main() {
259
259
  using term = createTerm()
260
260
  const { waitUntilExit } = await render(
261
261
  <ExampleBanner meta={meta} controls="j/k navigate space toggle enter expand Esc/q quit">
@@ -267,5 +267,5 @@ async function main() {
267
267
  }
268
268
 
269
269
  if (import.meta.main) {
270
- main().catch(console.error)
270
+ await main()
271
271
  }
@@ -251,7 +251,7 @@ function TerminalCapsApp({
251
251
  // Main
252
252
  // ============================================================================
253
253
 
254
- async function main() {
254
+ export async function main() {
255
255
  // Probe BEFORE render() starts — avoids stdin conflict with useInput.
256
256
  // Once render() owns stdin, protocol responses leak as visible text.
257
257
  let probeResults: {
@@ -312,23 +312,6 @@ async function main() {
312
312
  await waitUntilExit()
313
313
  }
314
314
 
315
- export { main }
316
-
317
315
  if (import.meta.main) {
318
- main().catch((err) => {
319
- // Ensure terminal is restored on error
320
- const stdout = process.stdout
321
- stdout.write("\x1b[?25h") // show cursor
322
- stdout.write("\x1b[?1049l") // leave alt screen
323
- stdout.write("\x1b[0m") // reset styles
324
- if (process.stdin.isTTY && process.stdin.isRaw) {
325
- try {
326
- process.stdin.setRawMode(false)
327
- } catch {
328
- /* noop */
329
- }
330
- }
331
- console.error(err)
332
- process.exit(1)
333
- })
316
+ await main()
334
317
  }
package/apps/terminal.tsx CHANGED
@@ -741,7 +741,7 @@ export function TerminalDemo({ kittySupported }: { kittySupported: boolean }) {
741
741
  // Main
742
742
  // ============================================================================
743
743
 
744
- async function main() {
744
+ export async function main() {
745
745
  // Detect Kitty support before starting the app
746
746
  const kittyResult = await detectKittyFromStdio(process.stdout, process.stdin)
747
747
 
@@ -779,22 +779,6 @@ async function main() {
779
779
  }
780
780
  }
781
781
 
782
- export { main }
783
-
784
782
  if (import.meta.main) {
785
- main().catch((err) => {
786
- const stdout = process.stdout
787
- stdout.write(disableMouse())
788
- disableFocusReporting((s) => stdout.write(s))
789
- stdout.write("\x1b[?25h")
790
- stdout.write("\x1b[?1049l")
791
- stdout.write("\x1b[0m")
792
- if (process.stdin.isTTY && process.stdin.isRaw) {
793
- try {
794
- process.stdin.setRawMode(false)
795
- } catch {}
796
- }
797
- console.error(err)
798
- process.exit(1)
799
- })
783
+ await main()
800
784
  }
@@ -173,7 +173,7 @@ function TextSelectionDemo(): React.ReactElement {
173
173
  // Main
174
174
  // ============================================================================
175
175
 
176
- if (import.meta.main) {
176
+ export async function main() {
177
177
  const app = pipe(
178
178
  createApp(() => () => ({})) as any,
179
179
  withReact(
@@ -187,3 +187,7 @@ if (import.meta.main) {
187
187
  using handle = await app.run()
188
188
  await handle.waitUntilExit()
189
189
  }
190
+
191
+ if (import.meta.main) {
192
+ await main()
193
+ }
package/apps/textarea.tsx CHANGED
@@ -139,7 +139,7 @@ export function NoteEditor() {
139
139
  )
140
140
  }
141
141
 
142
- async function main() {
142
+ export async function main() {
143
143
  using term = createTerm()
144
144
  const { waitUntilExit } = await render(
145
145
  <ExampleBanner meta={meta} controls="Tab switch pane Ctrl+Enter submit Esc quit">
@@ -151,5 +151,5 @@ async function main() {
151
151
  }
152
152
 
153
153
  if (import.meta.main) {
154
- main().catch(console.error)
154
+ await main()
155
155
  }
package/apps/theme.tsx CHANGED
@@ -483,7 +483,7 @@ export function ThemeExplorer({ entries }: { entries: ThemeEntry[] }) {
483
483
  // Main
484
484
  // ============================================================================
485
485
 
486
- async function main() {
486
+ export async function main() {
487
487
  // Detect terminal theme BEFORE entering alternate screen
488
488
  const detectedTheme = await detectTheme()
489
489
 
@@ -511,5 +511,5 @@ async function main() {
511
511
  }
512
512
 
513
513
  if (import.meta.main) {
514
- main().catch(console.error)
514
+ await main()
515
515
  }
@@ -213,7 +213,7 @@ export function TransformDemo() {
213
213
  // Main
214
214
  // ============================================================================
215
215
 
216
- async function main() {
216
+ export async function main() {
217
217
  using term = createTerm()
218
218
  const { waitUntilExit } = await render(
219
219
  <ExampleBanner meta={meta} controls="j/k select transform Esc/q quit">
@@ -225,5 +225,5 @@ async function main() {
225
225
  }
226
226
 
227
227
  if (import.meta.main) {
228
- main().catch(console.error)
228
+ await main()
229
229
  }
@@ -391,7 +391,7 @@ function VirtualBenchmark() {
391
391
  // Main
392
392
  // ============================================================================
393
393
 
394
- async function main() {
394
+ export async function main() {
395
395
  const handle = await run(
396
396
  <ExampleBanner meta={meta} controls="j/k navigate d/u half-page g/G start/end Enter detail Esc/q quit">
397
397
  <VirtualBenchmark />
@@ -401,5 +401,5 @@ async function main() {
401
401
  }
402
402
 
403
403
  if (import.meta.main) {
404
- main().catch(console.error)
404
+ await main()
405
405
  }
@@ -212,5 +212,5 @@ export async function main() {
212
212
  }
213
213
 
214
214
  if (import.meta.main) {
215
- main().catch(console.error)
215
+ await main()
216
216
  }
@@ -39,7 +39,11 @@ export const meta = {
39
39
  description: "Interactive counter with useState + useInput",
40
40
  }
41
41
 
42
- if (import.meta.main) {
42
+ export async function main() {
43
43
  const handle = await run(<Counter />)
44
44
  await handle.waitUntilExit()
45
45
  }
46
+
47
+ if (import.meta.main) {
48
+ await main()
49
+ }
@@ -28,7 +28,11 @@ export const meta = {
28
28
  description: "The simplest silvery app — styled text, exit on keypress",
29
29
  }
30
30
 
31
- if (import.meta.main) {
31
+ export async function main() {
32
32
  const handle = await run(<Hello />)
33
33
  await handle.waitUntilExit()
34
34
  }
35
+
36
+ if (import.meta.main) {
37
+ await main()
38
+ }
@@ -42,7 +42,11 @@ export const meta = {
42
42
  description: "Determinate and indeterminate progress bars",
43
43
  }
44
44
 
45
- if (import.meta.main) {
45
+ export async function main() {
46
46
  const handle = await run(<ProgressBarDemo />)
47
47
  await handle.waitUntilExit()
48
48
  }
49
+
50
+ if (import.meta.main) {
51
+ await main()
52
+ }
@@ -44,7 +44,11 @@ export const meta = {
44
44
  description: "Keyboard-navigable single-select list",
45
45
  }
46
46
 
47
- if (import.meta.main) {
47
+ export async function main() {
48
48
  const handle = await run(<SelectListDemo />)
49
49
  await handle.waitUntilExit()
50
50
  }
51
+
52
+ if (import.meta.main) {
53
+ await main()
54
+ }
@@ -34,7 +34,11 @@ export const meta = {
34
34
  description: "Four animated loading spinner styles",
35
35
  }
36
36
 
37
- if (import.meta.main) {
37
+ export async function main() {
38
38
  const handle = await run(<SpinnerDemo />)
39
39
  await handle.waitUntilExit()
40
40
  }
41
+
42
+ if (import.meta.main) {
43
+ await main()
44
+ }
@@ -51,7 +51,11 @@ export const meta = {
51
51
  description: "Single-line text entry with readline keybindings",
52
52
  }
53
53
 
54
- if (import.meta.main) {
54
+ export async function main() {
55
55
  const handle = await run(<TextInputDemo />)
56
56
  await handle.waitUntilExit()
57
57
  }
58
+
59
+ if (import.meta.main) {
60
+ await main()
61
+ }
@@ -46,7 +46,11 @@ export const meta = {
46
46
  description: "Efficient scrollable list with 200 virtualized items",
47
47
  }
48
48
 
49
- if (import.meta.main) {
49
+ export async function main() {
50
50
  const handle = await run(<ListViewDemo />)
51
51
  await handle.waitUntilExit()
52
52
  }
53
+
54
+ if (import.meta.main) {
55
+ await main()
56
+ }
package/dist/cli.mjs CHANGED
@@ -151,13 +151,12 @@ async function exampleCommand(args) {
151
151
  process.exit(1);
152
152
  }
153
153
  console.log(`${DIM}Running ${BOLD}${match.name}${RESET}${DIM}...${RESET}\n`);
154
- const { spawn } = await import("node:child_process");
155
- const runtime = typeof globalThis.Bun !== "undefined" ? "bun" : "node";
156
- spawn(runtime, runtime === "bun" ? ["run", match.file] : [
157
- "--experimental-strip-types",
158
- "--no-warnings",
159
- match.file
160
- ], { stdio: "inherit" }).on("exit", (code) => process.exit(code ?? 1));
154
+ const mod = await import(match.file);
155
+ if (typeof mod.main === "function") await mod.main();
156
+ else {
157
+ console.error(`${RED}Error:${RESET} Example does not export a main() function`);
158
+ process.exit(1);
159
+ }
161
160
  }
162
161
  async function main() {
163
162
  const args = process.argv.slice(2);
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../bin/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * silvery CLI\n *\n * Usage:\n * bunx silvery — show help\n * bunx silvery <name> — run an example by name (fuzzy match)\n * bunx silvery examples — list all available examples\n * bunx silvery doctor — check terminal capabilities\n * bunx silvery --help — show usage help\n */\n\n// =============================================================================\n// ANSI helpers (no deps — must work before anything is imported)\n// =============================================================================\n\nconst RESET = \"\\x1b[0m\"\nconst BOLD = \"\\x1b[1m\"\nconst DIM = \"\\x1b[2m\"\nconst RED = \"\\x1b[31m\"\nconst GREEN = \"\\x1b[32m\"\nconst YELLOW = \"\\x1b[33m\"\nconst BLUE = \"\\x1b[34m\"\nconst MAGENTA = \"\\x1b[35m\"\nconst CYAN = \"\\x1b[36m\"\nconst WHITE = \"\\x1b[37m\"\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface Example {\n name: string\n file: string\n description: string\n category: string\n features?: string[]\n}\n\n// =============================================================================\n// Auto-Discovery\n// =============================================================================\n\nconst CATEGORY_DIRS = [\"components\", \"apps\", \"layout\", \"runtime\", \"inline\", \"kitty\"] as const\n\nconst CATEGORY_DISPLAY: Record<string, string> = {\n kitty: \"Kitty Protocol\",\n}\n\nconst CATEGORY_ORDER: Record<string, number> = {\n Components: 0,\n Apps: 1,\n Layout: 2,\n Runtime: 3,\n Inline: 4,\n \"Kitty Protocol\": 5,\n}\n\nconst CATEGORY_COLOR: Record<string, string> = {\n Components: GREEN,\n Apps: CYAN,\n Layout: MAGENTA,\n Runtime: BLUE,\n Inline: YELLOW,\n \"Kitty Protocol\": BLUE,\n}\n\nasync function discoverExamples(): Promise<Example[]> {\n const { resolve, dirname } = await import(\"node:path\")\n const { fileURLToPath } = await import(\"node:url\")\n const { readdirSync } = await import(\"node:fs\")\n const __dirname = dirname(fileURLToPath(import.meta.url))\n const examplesDir = resolve(__dirname, \"..\")\n const results: Example[] = []\n\n for (const dir of CATEGORY_DIRS) {\n const category = CATEGORY_DISPLAY[dir] ?? dir.charAt(0).toUpperCase() + dir.slice(1)\n const dirPath = resolve(examplesDir, dir)\n\n try {\n const files = readdirSync(dirPath).filter((f: string) => f.endsWith(\".tsx\") && !f.startsWith(\"_\"))\n for (const file of files) {\n const name = file.replace(/\\.tsx$/, \"\").replace(/-/g, \" \")\n results.push({\n name,\n description: \"\",\n file: resolve(dirPath, file),\n category,\n })\n }\n } catch {\n // Directory doesn't exist — skip\n }\n }\n\n // Also scan aichat subdirectory\n const aichatDir = resolve(examplesDir, \"apps/aichat\")\n try {\n const indexFile = resolve(aichatDir, \"index.tsx\")\n const { stat } = await import(\"node:fs/promises\")\n await stat(indexFile)\n results.push({\n name: \"aichat\",\n description: \"AI Coding Agent demo\",\n file: indexFile,\n category: \"Apps\",\n })\n } catch {\n // No aichat\n }\n\n results.sort((a, b) => {\n const catDiff = (CATEGORY_ORDER[a.category] ?? 99) - (CATEGORY_ORDER[b.category] ?? 99)\n if (catDiff !== 0) return catDiff\n return a.name.localeCompare(b.name)\n })\n\n return results\n}\n\n// =============================================================================\n// Formatting\n// =============================================================================\n\nfunction printHelp(): void {\n console.log(`\n${BOLD}${YELLOW}@silvery/examples${RESET} — Try silvery without installing\n\n${BOLD}Usage:${RESET}\n bunx @silvery/examples ${DIM}<name>${RESET} Run an example by name (fuzzy match)\n bunx @silvery/examples List all available examples\n bunx @silvery/examples --help Show this help\n\n${BOLD}Quick start:${RESET}\n bunx @silvery/examples counter Simple counter (Hello World)\n bunx @silvery/examples dashboard Responsive layout demo\n bunx @silvery/examples kanban Kanban board with keyboard nav\n bunx @silvery/examples textarea Rich text editor\n\n${DIM}Documentation: https://silvery.dev${RESET}\n`)\n}\n\nfunction printExampleList(examples: Example[]): void {\n console.log(`\\n${BOLD}${YELLOW} silvery${RESET}${DIM} examples${RESET}\\n`)\n\n let currentCategory = \"\"\n\n for (const ex of examples) {\n if (ex.category !== currentCategory) {\n currentCategory = ex.category\n const color = CATEGORY_COLOR[currentCategory] ?? WHITE\n console.log(` ${color}${BOLD}${currentCategory}${RESET}`)\n }\n\n const nameStr = `${BOLD}${WHITE}${ex.name}${RESET}`\n const descStr = ex.description ? `${DIM}${ex.description}${RESET}` : \"\"\n console.log(` ${nameStr} ${descStr}`)\n }\n\n console.log(`\\n ${DIM}Run: bunx @silvery/examples <name>${RESET}\\n`)\n}\n\nfunction findExample(examples: Example[], query: string): Example | undefined {\n const q = query.toLowerCase().replace(/-/g, \" \")\n\n const exact = examples.find((ex) => ex.name.toLowerCase() === q)\n if (exact) return exact\n\n const prefix = examples.find((ex) => ex.name.toLowerCase().startsWith(q))\n if (prefix) return prefix\n\n const substring = examples.find((ex) => ex.name.toLowerCase().includes(q))\n if (substring) return substring\n\n return undefined\n}\n\nfunction printNoMatch(query: string, examples: Example[]): void {\n console.error(`\\n${RED}${BOLD}Error:${RESET} No example matching \"${query}\"\\n`)\n console.error(`${DIM}Available examples:${RESET}`)\n\n for (const ex of examples) {\n console.error(` ${WHITE}${ex.name}${RESET}`)\n }\n\n console.error(`\\n${DIM}Run ${BOLD}bunx @silvery/examples${RESET}${DIM} for full list.${RESET}\\n`)\n}\n\n// =============================================================================\n// Subcommands\n// =============================================================================\n\nasync function exampleCommand(args: string[]): Promise<void> {\n const examples = await discoverExamples()\n\n if (args.length === 0 || args[0] === \"--list\" || args[0] === \"-l\") {\n printExampleList(examples)\n return\n }\n\n const query = args.filter((a) => !a.startsWith(\"--\")).join(\" \")\n if (!query) {\n printExampleList(examples)\n return\n }\n\n const match = findExample(examples, query)\n if (!match) {\n printNoMatch(query, examples)\n process.exit(1)\n }\n\n console.log(`${DIM}Running ${BOLD}${match.name}${RESET}${DIM}...${RESET}\\n`)\n\n const { spawn } = await import(\"node:child_process\")\n const runtime = typeof globalThis.Bun !== \"undefined\" ? \"bun\" : \"node\"\n const runArgs = runtime === \"bun\" ? [\"run\", match.file] : [\"--experimental-strip-types\", \"--no-warnings\", match.file]\n const proc = spawn(runtime, runArgs, { stdio: \"inherit\" })\n proc.on(\"exit\", (code) => process.exit(code ?? 1))\n}\n\nasync function doctorCommand(): Promise<void> {\n const { resolve, dirname } = await import(\"node:path\")\n const { fileURLToPath } = await import(\"node:url\")\n const __dirname = dirname(fileURLToPath(import.meta.url))\n\n const candidates = [\n resolve(__dirname, \"../../ag-term/src/termtest.ts\"),\n resolve(__dirname, \"../node_modules/@silvery/ag-term/src/termtest.ts\"),\n ]\n\n for (const termtestPath of candidates) {\n try {\n const { stat } = await import(\"node:fs/promises\")\n await stat(termtestPath)\n const { spawn } = await import(\"node:child_process\")\n const runtime = typeof globalThis.Bun !== \"undefined\" ? \"bun\" : \"node\"\n const runArgs = runtime === \"bun\" ? [\"run\", termtestPath] : [\"--experimental-strip-types\", \"--no-warnings\", termtestPath]\n const proc = spawn(runtime, runArgs, { stdio: \"inherit\" })\n proc.on(\"exit\", (code) => process.exit(code ?? 1))\n return\n } catch {\n continue\n }\n }\n\n console.error(`${RED}Error:${RESET} Could not find terminal diagnostics.`)\n console.error(`${DIM}Make sure silvery is installed: npm install silvery${RESET}`)\n process.exit(1)\n}\n\n// =============================================================================\n// Main\n// =============================================================================\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2)\n\n // Top-level flags\n if (args.includes(\"--help\") || args.includes(\"-h\")) {\n printHelp()\n return\n }\n\n // No args → list examples\n if (args.length === 0) {\n const examples = await discoverExamples()\n printExampleList(examples)\n return\n }\n\n if (args.includes(\"--version\") || args.includes(\"-v\")) {\n try {\n const { resolve, dirname } = await import(\"node:path\")\n const { fileURLToPath } = await import(\"node:url\")\n const { readFileSync } = await import(\"node:fs\")\n const __dirname = dirname(fileURLToPath(import.meta.url))\n const pkgPath = resolve(__dirname, \"../package.json\")\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { version?: string }\n console.log(`@silvery/examples ${pkg.version}`)\n } catch {\n console.log(\"@silvery/examples (version unknown)\")\n }\n return\n }\n\n // \"bunx @silvery/examples counter\" → run counter example directly\n // \"bunx @silvery/examples\" → list (handled above by args.length === 0)\n await exampleCommand(args)\n}\n\nmain().catch((err) => {\n console.error(err)\n process.exit(1)\n})\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../bin/cli.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * silvery CLI\n *\n * Usage:\n * bunx silvery — show help\n * bunx silvery <name> — run an example by name (fuzzy match)\n * bunx silvery examples — list all available examples\n * bunx silvery doctor — check terminal capabilities\n * bunx silvery --help — show usage help\n */\n\n// =============================================================================\n// ANSI helpers (no deps — must work before anything is imported)\n// =============================================================================\n\nconst RESET = \"\\x1b[0m\"\nconst BOLD = \"\\x1b[1m\"\nconst DIM = \"\\x1b[2m\"\nconst RED = \"\\x1b[31m\"\nconst GREEN = \"\\x1b[32m\"\nconst YELLOW = \"\\x1b[33m\"\nconst BLUE = \"\\x1b[34m\"\nconst MAGENTA = \"\\x1b[35m\"\nconst CYAN = \"\\x1b[36m\"\nconst WHITE = \"\\x1b[37m\"\n\n// =============================================================================\n// Types\n// =============================================================================\n\ninterface Example {\n name: string\n file: string\n description: string\n category: string\n features?: string[]\n}\n\n// =============================================================================\n// Auto-Discovery\n// =============================================================================\n\nconst CATEGORY_DIRS = [\"components\", \"apps\", \"layout\", \"runtime\", \"inline\", \"kitty\"] as const\n\nconst CATEGORY_DISPLAY: Record<string, string> = {\n kitty: \"Kitty Protocol\",\n}\n\nconst CATEGORY_ORDER: Record<string, number> = {\n Components: 0,\n Apps: 1,\n Layout: 2,\n Runtime: 3,\n Inline: 4,\n \"Kitty Protocol\": 5,\n}\n\nconst CATEGORY_COLOR: Record<string, string> = {\n Components: GREEN,\n Apps: CYAN,\n Layout: MAGENTA,\n Runtime: BLUE,\n Inline: YELLOW,\n \"Kitty Protocol\": BLUE,\n}\n\nasync function discoverExamples(): Promise<Example[]> {\n const { resolve, dirname } = await import(\"node:path\")\n const { fileURLToPath } = await import(\"node:url\")\n const { readdirSync } = await import(\"node:fs\")\n const __dirname = dirname(fileURLToPath(import.meta.url))\n const examplesDir = resolve(__dirname, \"..\")\n const results: Example[] = []\n\n for (const dir of CATEGORY_DIRS) {\n const category = CATEGORY_DISPLAY[dir] ?? dir.charAt(0).toUpperCase() + dir.slice(1)\n const dirPath = resolve(examplesDir, dir)\n\n try {\n const files = readdirSync(dirPath).filter((f: string) => f.endsWith(\".tsx\") && !f.startsWith(\"_\"))\n for (const file of files) {\n const name = file.replace(/\\.tsx$/, \"\").replace(/-/g, \" \")\n results.push({\n name,\n description: \"\",\n file: resolve(dirPath, file),\n category,\n })\n }\n } catch {\n // Directory doesn't exist — skip\n }\n }\n\n // Also scan aichat subdirectory\n const aichatDir = resolve(examplesDir, \"apps/aichat\")\n try {\n const indexFile = resolve(aichatDir, \"index.tsx\")\n const { stat } = await import(\"node:fs/promises\")\n await stat(indexFile)\n results.push({\n name: \"aichat\",\n description: \"AI Coding Agent demo\",\n file: indexFile,\n category: \"Apps\",\n })\n } catch {\n // No aichat\n }\n\n results.sort((a, b) => {\n const catDiff = (CATEGORY_ORDER[a.category] ?? 99) - (CATEGORY_ORDER[b.category] ?? 99)\n if (catDiff !== 0) return catDiff\n return a.name.localeCompare(b.name)\n })\n\n return results\n}\n\n// =============================================================================\n// Formatting\n// =============================================================================\n\nfunction printHelp(): void {\n console.log(`\n${BOLD}${YELLOW}@silvery/examples${RESET} — Try silvery without installing\n\n${BOLD}Usage:${RESET}\n bunx @silvery/examples ${DIM}<name>${RESET} Run an example by name (fuzzy match)\n bunx @silvery/examples List all available examples\n bunx @silvery/examples --help Show this help\n\n${BOLD}Quick start:${RESET}\n bunx @silvery/examples counter Simple counter (Hello World)\n bunx @silvery/examples dashboard Responsive layout demo\n bunx @silvery/examples kanban Kanban board with keyboard nav\n bunx @silvery/examples textarea Rich text editor\n\n${DIM}Documentation: https://silvery.dev${RESET}\n`)\n}\n\nfunction printExampleList(examples: Example[]): void {\n console.log(`\\n${BOLD}${YELLOW} silvery${RESET}${DIM} examples${RESET}\\n`)\n\n let currentCategory = \"\"\n\n for (const ex of examples) {\n if (ex.category !== currentCategory) {\n currentCategory = ex.category\n const color = CATEGORY_COLOR[currentCategory] ?? WHITE\n console.log(` ${color}${BOLD}${currentCategory}${RESET}`)\n }\n\n const nameStr = `${BOLD}${WHITE}${ex.name}${RESET}`\n const descStr = ex.description ? `${DIM}${ex.description}${RESET}` : \"\"\n console.log(` ${nameStr} ${descStr}`)\n }\n\n console.log(`\\n ${DIM}Run: bunx @silvery/examples <name>${RESET}\\n`)\n}\n\nfunction findExample(examples: Example[], query: string): Example | undefined {\n const q = query.toLowerCase().replace(/-/g, \" \")\n\n const exact = examples.find((ex) => ex.name.toLowerCase() === q)\n if (exact) return exact\n\n const prefix = examples.find((ex) => ex.name.toLowerCase().startsWith(q))\n if (prefix) return prefix\n\n const substring = examples.find((ex) => ex.name.toLowerCase().includes(q))\n if (substring) return substring\n\n return undefined\n}\n\nfunction printNoMatch(query: string, examples: Example[]): void {\n console.error(`\\n${RED}${BOLD}Error:${RESET} No example matching \"${query}\"\\n`)\n console.error(`${DIM}Available examples:${RESET}`)\n\n for (const ex of examples) {\n console.error(` ${WHITE}${ex.name}${RESET}`)\n }\n\n console.error(`\\n${DIM}Run ${BOLD}bunx @silvery/examples${RESET}${DIM} for full list.${RESET}\\n`)\n}\n\n// =============================================================================\n// Subcommands\n// =============================================================================\n\nasync function exampleCommand(args: string[]): Promise<void> {\n const examples = await discoverExamples()\n\n if (args.length === 0 || args[0] === \"--list\" || args[0] === \"-l\") {\n printExampleList(examples)\n return\n }\n\n const query = args.filter((a) => !a.startsWith(\"--\")).join(\" \")\n if (!query) {\n printExampleList(examples)\n return\n }\n\n const match = findExample(examples, query)\n if (!match) {\n printNoMatch(query, examples)\n process.exit(1)\n }\n\n console.log(`${DIM}Running ${BOLD}${match.name}${RESET}${DIM}...${RESET}\\n`)\n\n const mod = await import(match.file)\n if (typeof mod.main === \"function\") {\n await mod.main()\n } else {\n console.error(`${RED}Error:${RESET} Example does not export a main() function`)\n process.exit(1)\n }\n}\n\nasync function doctorCommand(): Promise<void> {\n const { resolve, dirname } = await import(\"node:path\")\n const { fileURLToPath } = await import(\"node:url\")\n const __dirname = dirname(fileURLToPath(import.meta.url))\n\n const candidates = [\n resolve(__dirname, \"../../ag-term/src/termtest.ts\"),\n resolve(__dirname, \"../node_modules/@silvery/ag-term/src/termtest.ts\"),\n ]\n\n for (const termtestPath of candidates) {\n try {\n const { stat } = await import(\"node:fs/promises\")\n await stat(termtestPath)\n const mod = await import(termtestPath)\n if (typeof mod.main === \"function\") {\n await mod.main()\n } else {\n // Fallback: module runs on import (legacy pattern)\n }\n return\n } catch {\n continue\n }\n }\n\n console.error(`${RED}Error:${RESET} Could not find terminal diagnostics.`)\n console.error(`${DIM}Make sure silvery is installed: npm install silvery${RESET}`)\n process.exit(1)\n}\n\n// =============================================================================\n// Main\n// =============================================================================\n\nasync function main(): Promise<void> {\n const args = process.argv.slice(2)\n\n // Top-level flags\n if (args.includes(\"--help\") || args.includes(\"-h\")) {\n printHelp()\n return\n }\n\n // No args → list examples\n if (args.length === 0) {\n const examples = await discoverExamples()\n printExampleList(examples)\n return\n }\n\n if (args.includes(\"--version\") || args.includes(\"-v\")) {\n try {\n const { resolve, dirname } = await import(\"node:path\")\n const { fileURLToPath } = await import(\"node:url\")\n const { readFileSync } = await import(\"node:fs\")\n const __dirname = dirname(fileURLToPath(import.meta.url))\n const pkgPath = resolve(__dirname, \"../package.json\")\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf8\")) as { version?: string }\n console.log(`@silvery/examples ${pkg.version}`)\n } catch {\n console.log(\"@silvery/examples (version unknown)\")\n }\n return\n }\n\n // \"bunx @silvery/examples counter\" → run counter example directly\n // \"bunx @silvery/examples\" → list (handled above by args.length === 0)\n await exampleCommand(args)\n}\n\nmain().catch((err) => {\n console.error(err)\n process.exit(1)\n})\n"],"mappings":"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"}
@@ -937,7 +937,7 @@ export function Dashboard({ static: isStatic }: { static?: boolean } = {}) {
937
937
  // Main
938
938
  // ============================================================================
939
939
 
940
- async function main() {
940
+ export async function main() {
941
941
  using term = createTerm()
942
942
  const { waitUntilExit } = await render(
943
943
  <ExampleBanner meta={meta} controls="h/l tabs Esc/q quit">
@@ -949,5 +949,5 @@ async function main() {
949
949
  }
950
950
 
951
951
  if (import.meta.main) {
952
- main().catch(console.error)
952
+ await main()
953
953
  }
@@ -268,7 +268,7 @@ function LiveResize() {
268
268
  // Main
269
269
  // ============================================================================
270
270
 
271
- async function main() {
271
+ export async function main() {
272
272
  const handle = await run(
273
273
  <ExampleBanner meta={meta} controls="Resize terminal to see reflow Esc/q quit">
274
274
  <LiveResize />
@@ -278,5 +278,5 @@ async function main() {
278
278
  }
279
279
 
280
280
  if (import.meta.main) {
281
- main().catch(console.error)
281
+ await main()
282
282
  }
@@ -35,7 +35,7 @@ export function OverflowApp() {
35
35
  )
36
36
  }
37
37
 
38
- async function main() {
38
+ export async function main() {
39
39
  using term = createTerm()
40
40
  const { waitUntilExit } = await render(
41
41
  <ExampleBanner meta={meta} controls="Esc/q quit">
@@ -47,5 +47,5 @@ async function main() {
47
47
  }
48
48
 
49
49
  if (import.meta.main) {
50
- main().catch(console.error)
50
+ await main()
51
51
  }
@@ -269,7 +269,7 @@ function PretextDemo() {
269
269
  // Entry Point
270
270
  // ============================================================================
271
271
 
272
- async function main() {
272
+ export async function main() {
273
273
  const handle = await run(
274
274
  <ExampleBanner meta={meta} controls="j/k switch demo 1-3 jump Esc/q quit">
275
275
  <PretextDemo />
@@ -279,5 +279,5 @@ async function main() {
279
279
  }
280
280
 
281
281
  if (import.meta.main) {
282
- main().catch(console.error)
282
+ await main()
283
283
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@silvery/examples",
3
- "version": "0.5.5",
3
+ "version": "0.17.3",
4
4
  "description": "Example apps and component demos for silvery — npx @silvery/examples <name>",
5
5
  "license": "MIT",
6
6
  "author": "Bjørn Stabell <bjorn@stabell.org>",
@@ -39,7 +39,7 @@
39
39
  "clean": true
40
40
  },
41
41
  "dependencies": {
42
- "silvery": "0.17.2"
42
+ "silvery": "0.17.3"
43
43
  },
44
44
  "engines": {
45
45
  "bun": ">=1.0",