@silvery/examples 0.4.2
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/bin/cli.ts +286 -0
- package/examples/apps/aichat/components.tsx +469 -0
- package/examples/apps/aichat/index.tsx +207 -0
- package/examples/apps/aichat/script.ts +460 -0
- package/examples/apps/aichat/state.ts +326 -0
- package/examples/apps/aichat/types.ts +19 -0
- package/examples/apps/app-todo.tsx +201 -0
- package/examples/apps/async-data.tsx +208 -0
- package/examples/apps/cli-wizard.tsx +332 -0
- package/examples/apps/clipboard.tsx +183 -0
- package/examples/apps/components.tsx +463 -0
- package/examples/apps/data-explorer.tsx +490 -0
- package/examples/apps/dev-tools.tsx +379 -0
- package/examples/apps/explorer.tsx +731 -0
- package/examples/apps/gallery.tsx +653 -0
- package/examples/apps/inline-bench.tsx +136 -0
- package/examples/apps/kanban.tsx +267 -0
- package/examples/apps/layout-ref.tsx +185 -0
- package/examples/apps/outline.tsx +171 -0
- package/examples/apps/panes/index.tsx +205 -0
- package/examples/apps/paste-demo.tsx +198 -0
- package/examples/apps/scroll.tsx +77 -0
- package/examples/apps/search-filter.tsx +240 -0
- package/examples/apps/task-list.tsx +271 -0
- package/examples/apps/terminal.tsx +800 -0
- package/examples/apps/textarea.tsx +103 -0
- package/examples/apps/theme.tsx +515 -0
- package/examples/apps/transform.tsx +242 -0
- package/examples/apps/virtual-10k.tsx +405 -0
- package/examples/components/counter.tsx +45 -0
- package/examples/components/hello.tsx +34 -0
- package/examples/components/progress-bar.tsx +48 -0
- package/examples/components/select-list.tsx +50 -0
- package/examples/components/spinner.tsx +40 -0
- package/examples/components/text-input.tsx +57 -0
- package/examples/components/virtual-list.tsx +52 -0
- package/package.json +27 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hello — The simplest silvery app
|
|
3
|
+
*
|
|
4
|
+
* Renders styled text and exits on any keypress.
|
|
5
|
+
*
|
|
6
|
+
* Usage: bun examples/components/hello.tsx
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React from "react"
|
|
10
|
+
import { Box, Text } from "../../src/index.js"
|
|
11
|
+
import { run, useInput } from "@silvery/ag-term/runtime"
|
|
12
|
+
|
|
13
|
+
function Hello() {
|
|
14
|
+
useInput(() => "exit" as const)
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Box flexDirection="column" padding={1}>
|
|
18
|
+
<Text bold color="$primary">
|
|
19
|
+
Hello, Silvery!
|
|
20
|
+
</Text>
|
|
21
|
+
<Text color="$muted">Press any key to exit.</Text>
|
|
22
|
+
</Box>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export const meta = {
|
|
27
|
+
name: "Hello",
|
|
28
|
+
description: "The simplest silvery app — styled text, exit on keypress",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (import.meta.main) {
|
|
32
|
+
const handle = await run(<Hello />)
|
|
33
|
+
await handle.waitUntilExit()
|
|
34
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ProgressBar — Determinate and indeterminate progress
|
|
3
|
+
*
|
|
4
|
+
* Press j/k to adjust progress. Shows determinate bars with
|
|
5
|
+
* percentage labels and an indeterminate animated bar.
|
|
6
|
+
*
|
|
7
|
+
* Usage: bun examples/components/progress-bar.tsx
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React, { useState } from "react"
|
|
11
|
+
import { Box, Text, ProgressBar } from "../../src/index.js"
|
|
12
|
+
import { run, useInput } from "@silvery/ag-term/runtime"
|
|
13
|
+
|
|
14
|
+
function ProgressBarDemo() {
|
|
15
|
+
const [progress, setProgress] = useState(0.4)
|
|
16
|
+
|
|
17
|
+
useInput((input, key) => {
|
|
18
|
+
if (input === "j" || key.rightArrow) setProgress((p) => Math.min(1, p + 0.05))
|
|
19
|
+
if (input === "k" || key.leftArrow) setProgress((p) => Math.max(0, p - 0.05))
|
|
20
|
+
if (input === "q" || key.escape) return "exit"
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
return (
|
|
24
|
+
<Box flexDirection="column" padding={1} gap={1}>
|
|
25
|
+
<Text bold>Determinate</Text>
|
|
26
|
+
<Box width={40}>
|
|
27
|
+
<ProgressBar value={progress} />
|
|
28
|
+
</Box>
|
|
29
|
+
|
|
30
|
+
<Text bold>Indeterminate</Text>
|
|
31
|
+
<Box width={40}>
|
|
32
|
+
<ProgressBar />
|
|
33
|
+
</Box>
|
|
34
|
+
|
|
35
|
+
<Text color="$muted">j/k: adjust q: quit</Text>
|
|
36
|
+
</Box>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const meta = {
|
|
41
|
+
name: "Progress Bar",
|
|
42
|
+
description: "Determinate and indeterminate progress bars",
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (import.meta.main) {
|
|
46
|
+
const handle = await run(<ProgressBarDemo />)
|
|
47
|
+
await handle.waitUntilExit()
|
|
48
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SelectList — Keyboard-navigable single-select
|
|
3
|
+
*
|
|
4
|
+
* Navigate with j/k or arrows, confirm with Enter.
|
|
5
|
+
* Disabled items are automatically skipped.
|
|
6
|
+
*
|
|
7
|
+
* Usage: bun examples/components/select-list.tsx
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React, { useState } from "react"
|
|
11
|
+
import { Box, Text, SelectList } from "../../src/index.js"
|
|
12
|
+
import { run, useInput } from "@silvery/ag-term/runtime"
|
|
13
|
+
|
|
14
|
+
const languages = [
|
|
15
|
+
{ label: "TypeScript", value: "ts" },
|
|
16
|
+
{ label: "Rust", value: "rs" },
|
|
17
|
+
{ label: "Go", value: "go" },
|
|
18
|
+
{ label: "Python", value: "py" },
|
|
19
|
+
{ label: "COBOL", value: "cob", disabled: true },
|
|
20
|
+
{ label: "Elixir", value: "ex" },
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
function SelectListDemo() {
|
|
24
|
+
const [selected, setSelected] = useState<string | null>(null)
|
|
25
|
+
|
|
26
|
+
useInput((_, key) => {
|
|
27
|
+
if (key.escape) return "exit"
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<Box flexDirection="column" padding={1} gap={1}>
|
|
32
|
+
<Text bold>Pick a language:</Text>
|
|
33
|
+
<Box borderStyle="round" borderColor="$border" paddingX={1}>
|
|
34
|
+
<SelectList items={languages} onSelect={(opt) => setSelected(opt.value)} />
|
|
35
|
+
</Box>
|
|
36
|
+
{selected && <Text color="$success">Selected: {selected}</Text>}
|
|
37
|
+
<Text color="$muted">j/k: navigate Enter: select Esc: quit</Text>
|
|
38
|
+
</Box>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const meta = {
|
|
43
|
+
name: "Select List",
|
|
44
|
+
description: "Keyboard-navigable single-select list",
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (import.meta.main) {
|
|
48
|
+
const handle = await run(<SelectListDemo />)
|
|
49
|
+
await handle.waitUntilExit()
|
|
50
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spinner — Animated loading indicators
|
|
3
|
+
*
|
|
4
|
+
* Shows all four built-in spinner styles side by side.
|
|
5
|
+
*
|
|
6
|
+
* Usage: bun examples/components/spinner.tsx
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import React from "react"
|
|
10
|
+
import { Box, Text, Spinner } from "../../src/index.js"
|
|
11
|
+
import { run, useInput } from "@silvery/ag-term/runtime"
|
|
12
|
+
|
|
13
|
+
function SpinnerDemo() {
|
|
14
|
+
useInput((input, key) => {
|
|
15
|
+
if (input === "q" || key.escape) return "exit"
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Box flexDirection="column" padding={1} gap={1}>
|
|
20
|
+
<Text bold>Spinner Styles</Text>
|
|
21
|
+
<Box flexDirection="column">
|
|
22
|
+
<Spinner type="dots" label="Loading packages..." />
|
|
23
|
+
<Spinner type="line" label="Compiling..." />
|
|
24
|
+
<Spinner type="arc" label="Optimizing..." />
|
|
25
|
+
<Spinner type="bounce" label="Connecting..." />
|
|
26
|
+
</Box>
|
|
27
|
+
<Text color="$muted">q: quit</Text>
|
|
28
|
+
</Box>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const meta = {
|
|
33
|
+
name: "Spinner",
|
|
34
|
+
description: "Four animated loading spinner styles",
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (import.meta.main) {
|
|
38
|
+
const handle = await run(<SpinnerDemo />)
|
|
39
|
+
await handle.waitUntilExit()
|
|
40
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TextInput — Single-line text entry
|
|
3
|
+
*
|
|
4
|
+
* Shows TextInput with placeholder, prompt, and submit handler.
|
|
5
|
+
* Full readline keybindings (Ctrl+A/E/K/U, Alt+B/F) are built in.
|
|
6
|
+
*
|
|
7
|
+
* Usage: bun examples/components/text-input.tsx
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React, { useState } from "react"
|
|
11
|
+
import { Box, Text, TextInput } from "../../src/index.js"
|
|
12
|
+
import { run, useInput } from "@silvery/ag-term/runtime"
|
|
13
|
+
|
|
14
|
+
function TextInputDemo() {
|
|
15
|
+
const [value, setValue] = useState("")
|
|
16
|
+
const [submitted, setSubmitted] = useState<string[]>([])
|
|
17
|
+
|
|
18
|
+
useInput((_, key) => {
|
|
19
|
+
if (key.escape) return "exit"
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Box flexDirection="column" padding={1} gap={1}>
|
|
24
|
+
<TextInput
|
|
25
|
+
value={value}
|
|
26
|
+
onChange={setValue}
|
|
27
|
+
onSubmit={(val) => {
|
|
28
|
+
setSubmitted((prev) => [...prev, val])
|
|
29
|
+
setValue("")
|
|
30
|
+
}}
|
|
31
|
+
placeholder="Type something and press Enter..."
|
|
32
|
+
prompt="> "
|
|
33
|
+
/>
|
|
34
|
+
{submitted.length > 0 && (
|
|
35
|
+
<Box flexDirection="column">
|
|
36
|
+
<Text color="$muted">Submitted:</Text>
|
|
37
|
+
{submitted.map((s, i) => (
|
|
38
|
+
<Text key={i} color="$success">
|
|
39
|
+
{s}
|
|
40
|
+
</Text>
|
|
41
|
+
))}
|
|
42
|
+
</Box>
|
|
43
|
+
)}
|
|
44
|
+
<Text color="$muted">Enter: submit Esc: quit</Text>
|
|
45
|
+
</Box>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const meta = {
|
|
50
|
+
name: "Text Input",
|
|
51
|
+
description: "Single-line text entry with readline keybindings",
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (import.meta.main) {
|
|
55
|
+
const handle = await run(<TextInputDemo />)
|
|
56
|
+
await handle.waitUntilExit()
|
|
57
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VirtualList — Efficient scrollable list
|
|
3
|
+
*
|
|
4
|
+
* Renders 200 items but only materializes visible rows.
|
|
5
|
+
* Built-in j/k navigation, page up/down, Home/End.
|
|
6
|
+
*
|
|
7
|
+
* Usage: bun examples/components/virtual-list.tsx
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import React from "react"
|
|
11
|
+
import { Box, Text, VirtualList } from "../../src/index.js"
|
|
12
|
+
import { run, useInput } from "@silvery/ag-term/runtime"
|
|
13
|
+
|
|
14
|
+
const items = Array.from({ length: 200 }, (_, i) => ({
|
|
15
|
+
id: i,
|
|
16
|
+
name: `Item ${i + 1}`,
|
|
17
|
+
}))
|
|
18
|
+
|
|
19
|
+
function VirtualListDemo() {
|
|
20
|
+
useInput((input, key) => {
|
|
21
|
+
if (input === "q" || key.escape) return "exit"
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Box flexDirection="column" padding={1} gap={1}>
|
|
26
|
+
<Text bold>200 items (virtualized)</Text>
|
|
27
|
+
<VirtualList
|
|
28
|
+
items={items}
|
|
29
|
+
height={12}
|
|
30
|
+
itemHeight={1}
|
|
31
|
+
interactive
|
|
32
|
+
renderItem={(item, _index, meta) => (
|
|
33
|
+
<Text key={item.id} color={meta?.isSelected ? "$primary" : undefined} bold={meta?.isSelected}>
|
|
34
|
+
{meta?.isSelected ? "> " : " "}
|
|
35
|
+
{item.name}
|
|
36
|
+
</Text>
|
|
37
|
+
)}
|
|
38
|
+
/>
|
|
39
|
+
<Text color="$muted">j/k: navigate q: quit</Text>
|
|
40
|
+
</Box>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const meta = {
|
|
45
|
+
name: "Virtual List",
|
|
46
|
+
description: "Efficient scrollable list with 200 virtualized items",
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (import.meta.main) {
|
|
50
|
+
const handle = await run(<VirtualListDemo />)
|
|
51
|
+
await handle.waitUntilExit()
|
|
52
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@silvery/examples",
|
|
3
|
+
"version": "0.4.2",
|
|
4
|
+
"description": "Example apps and component demos for silvery \u2014 bunx @silvery/examples <name>",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Bj\u00f8rn Stabell <bjorn@stabell.org>",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/beorn/silvery.git",
|
|
10
|
+
"directory": "packages/cli"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"bin",
|
|
14
|
+
"examples"
|
|
15
|
+
],
|
|
16
|
+
"type": "module",
|
|
17
|
+
"bin": {
|
|
18
|
+
"silvery-examples": "./bin/cli.ts"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"silvery": ">=0.4.0",
|
|
25
|
+
"@silvery/tea": ">=0.4.0"
|
|
26
|
+
}
|
|
27
|
+
}
|