@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.
- package/apps/aichat/index.tsx +1 -1
- package/apps/app-todo.tsx +2 -2
- package/apps/async-data.tsx +2 -2
- package/apps/cli-wizard.tsx +2 -2
- package/apps/clipboard.tsx +2 -2
- package/apps/components.tsx +1 -1
- package/apps/data-explorer.tsx +2 -2
- package/apps/dev-tools.tsx +2 -2
- package/apps/explorer.tsx +1 -1
- package/apps/gallery.tsx +1 -1
- package/apps/inline-bench.tsx +2 -2
- package/apps/kanban.tsx +2 -2
- package/apps/layout-ref.tsx +2 -2
- package/apps/outline.tsx +2 -2
- package/apps/panes/index.tsx +1 -1
- package/apps/paste-demo.tsx +2 -2
- package/apps/scroll.tsx +5 -2
- package/apps/search-filter.tsx +2 -2
- package/apps/selection.tsx +5 -1
- package/apps/spatial-focus-demo.tsx +5 -1
- package/apps/task-list.tsx +2 -2
- package/apps/terminal-caps-demo.tsx +2 -19
- package/apps/terminal.tsx +2 -18
- package/apps/text-selection-demo.tsx +5 -1
- package/apps/textarea.tsx +2 -2
- package/apps/theme.tsx +2 -2
- package/apps/transform.tsx +2 -2
- package/apps/virtual-10k.tsx +2 -2
- package/apps/vterm-demo/index.tsx +1 -1
- package/components/counter.tsx +5 -1
- package/components/hello.tsx +5 -1
- package/components/progress-bar.tsx +5 -1
- package/components/select-list.tsx +5 -1
- package/components/spinner.tsx +5 -1
- package/components/text-input.tsx +5 -1
- package/components/virtual-list.tsx +5 -1
- package/dist/cli.mjs +6 -7
- package/dist/cli.mjs.map +1 -1
- package/layout/dashboard.tsx +2 -2
- package/layout/live-resize.tsx +2 -2
- package/layout/overflow.tsx +2 -2
- package/layout/text-layout.tsx +2 -2
- package/package.json +2 -2
package/apps/aichat/index.tsx
CHANGED
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()
|
|
200
|
+
await main()
|
|
201
201
|
}
|
package/apps/async-data.tsx
CHANGED
|
@@ -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()
|
|
195
|
+
await main()
|
|
196
196
|
}
|
package/apps/cli-wizard.tsx
CHANGED
|
@@ -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()
|
|
331
|
+
await main()
|
|
332
332
|
}
|
package/apps/clipboard.tsx
CHANGED
|
@@ -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()
|
|
182
|
+
await main()
|
|
183
183
|
}
|
package/apps/components.tsx
CHANGED
package/apps/data-explorer.tsx
CHANGED
|
@@ -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()
|
|
489
|
+
await main()
|
|
490
490
|
}
|
package/apps/dev-tools.tsx
CHANGED
|
@@ -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()
|
|
394
|
+
await main()
|
|
395
395
|
}
|
package/apps/explorer.tsx
CHANGED
package/apps/gallery.tsx
CHANGED
package/apps/inline-bench.tsx
CHANGED
|
@@ -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()
|
|
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()
|
|
264
|
+
await main()
|
|
265
265
|
}
|
package/apps/layout-ref.tsx
CHANGED
|
@@ -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()
|
|
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()
|
|
159
|
+
await main()
|
|
160
160
|
}
|
package/apps/panes/index.tsx
CHANGED
package/apps/paste-demo.tsx
CHANGED
|
@@ -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()
|
|
184
|
+
await main()
|
|
185
185
|
}
|
package/apps/scroll.tsx
CHANGED
|
@@ -65,8 +65,7 @@ export function ScrollExample() {
|
|
|
65
65
|
)
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
|
|
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
|
+
}
|
package/apps/search-filter.tsx
CHANGED
|
@@ -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()
|
|
239
|
+
await main()
|
|
240
240
|
}
|
package/apps/selection.tsx
CHANGED
|
@@ -336,7 +336,11 @@ export const meta = {
|
|
|
336
336
|
features: ["Selection model", "mode ladder", "multi-select", "text editing"],
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/apps/task-list.tsx
CHANGED
|
@@ -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()
|
|
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()
|
|
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()
|
|
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
|
-
|
|
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()
|
|
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()
|
|
514
|
+
await main()
|
|
515
515
|
}
|
package/apps/transform.tsx
CHANGED
|
@@ -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()
|
|
228
|
+
await main()
|
|
229
229
|
}
|
package/apps/virtual-10k.tsx
CHANGED
|
@@ -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()
|
|
404
|
+
await main()
|
|
405
405
|
}
|
package/components/counter.tsx
CHANGED
|
@@ -39,7 +39,11 @@ export const meta = {
|
|
|
39
39
|
description: "Interactive counter with useState + useInput",
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
|
|
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
|
+
}
|
package/components/hello.tsx
CHANGED
|
@@ -28,7 +28,11 @@ export const meta = {
|
|
|
28
28
|
description: "The simplest silvery app — styled text, exit on keypress",
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|
package/components/spinner.tsx
CHANGED
|
@@ -34,7 +34,11 @@ export const meta = {
|
|
|
34
34
|
description: "Four animated loading spinner styles",
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
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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"}
|
package/layout/dashboard.tsx
CHANGED
|
@@ -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()
|
|
952
|
+
await main()
|
|
953
953
|
}
|
package/layout/live-resize.tsx
CHANGED
|
@@ -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()
|
|
281
|
+
await main()
|
|
282
282
|
}
|
package/layout/overflow.tsx
CHANGED
|
@@ -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()
|
|
50
|
+
await main()
|
|
51
51
|
}
|
package/layout/text-layout.tsx
CHANGED
|
@@ -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()
|
|
282
|
+
await main()
|
|
283
283
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@silvery/examples",
|
|
3
|
-
"version": "0.
|
|
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.
|
|
42
|
+
"silvery": "0.17.3"
|
|
43
43
|
},
|
|
44
44
|
"engines": {
|
|
45
45
|
"bun": ">=1.0",
|