@silvery/examples 0.5.6 → 0.17.4

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 (112) hide show
  1. package/dist/UPNG-Cy7ViL8f.mjs +5074 -0
  2. package/dist/__vite-browser-external-2447137e-BML7CYau.mjs +4 -0
  3. package/dist/_banner-DLPxCqVy.mjs +44 -0
  4. package/dist/ansi-CCE2pVS0.mjs +16397 -0
  5. package/dist/apng-HhhBjRGt.mjs +68 -0
  6. package/dist/apng-mwUQbTTF.mjs +3 -0
  7. package/dist/apps/aichat/index.mjs +1299 -0
  8. package/dist/apps/app-todo.mjs +139 -0
  9. package/dist/apps/async-data.mjs +204 -0
  10. package/dist/apps/cli-wizard.mjs +339 -0
  11. package/dist/apps/clipboard.mjs +198 -0
  12. package/dist/apps/components.mjs +864 -0
  13. package/dist/apps/data-explorer.mjs +483 -0
  14. package/dist/apps/dev-tools.mjs +397 -0
  15. package/dist/apps/explorer.mjs +698 -0
  16. package/dist/apps/gallery.mjs +766 -0
  17. package/dist/apps/inline-bench.mjs +115 -0
  18. package/dist/apps/kanban.mjs +280 -0
  19. package/dist/apps/layout-ref.mjs +187 -0
  20. package/dist/apps/outline.mjs +203 -0
  21. package/dist/apps/paste-demo.mjs +189 -0
  22. package/dist/apps/scroll.mjs +86 -0
  23. package/dist/apps/search-filter.mjs +287 -0
  24. package/dist/apps/selection.mjs +355 -0
  25. package/dist/apps/spatial-focus-demo.mjs +388 -0
  26. package/dist/apps/task-list.mjs +258 -0
  27. package/dist/apps/terminal-caps-demo.mjs +315 -0
  28. package/dist/apps/terminal.mjs +872 -0
  29. package/dist/apps/text-selection-demo.mjs +254 -0
  30. package/dist/apps/textarea.mjs +178 -0
  31. package/dist/apps/theme.mjs +661 -0
  32. package/dist/apps/transform.mjs +215 -0
  33. package/dist/apps/virtual-10k.mjs +422 -0
  34. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  35. package/dist/backends-Bahh9mKN.mjs +1179 -0
  36. package/dist/backends-CCtCDQ94.mjs +3 -0
  37. package/dist/{cli.mjs → bin/cli.mjs} +21 -25
  38. package/dist/chunk-BSw8zbkd.mjs +37 -0
  39. package/dist/components/counter.mjs +48 -0
  40. package/dist/components/hello.mjs +31 -0
  41. package/dist/components/progress-bar.mjs +59 -0
  42. package/dist/components/select-list.mjs +85 -0
  43. package/dist/components/spinner.mjs +57 -0
  44. package/dist/components/text-input.mjs +62 -0
  45. package/dist/components/virtual-list.mjs +51 -0
  46. package/dist/flexily-zero-adapter-UB-ra8fR.mjs +3374 -0
  47. package/dist/gif-BZaqPPVX.mjs +3 -0
  48. package/dist/gif-BtnXuxLF.mjs +71 -0
  49. package/dist/gifenc-CLRW41dk.mjs +728 -0
  50. package/dist/jsx-runtime-dMs_8fNu.mjs +241 -0
  51. package/dist/key-mapping-5oYQdAQE.mjs +3 -0
  52. package/dist/key-mapping-D4LR1go6.mjs +130 -0
  53. package/dist/layout/dashboard.mjs +1204 -0
  54. package/dist/layout/live-resize.mjs +303 -0
  55. package/dist/layout/overflow.mjs +70 -0
  56. package/dist/layout/text-layout.mjs +335 -0
  57. package/dist/node-NuJ94BWl.mjs +1083 -0
  58. package/dist/plugins-D1KtkT4a.mjs +3057 -0
  59. package/dist/resvg-js-C_8Wps1F.mjs +201 -0
  60. package/dist/src-BTEVGpd9.mjs +23538 -0
  61. package/dist/src-CUUOuRH6.mjs +5322 -0
  62. package/dist/src-CzfRafCQ.mjs +814 -0
  63. package/dist/usingCtx-CsEf0xO3.mjs +57 -0
  64. package/dist/yoga-adapter-BVtQ5OJR.mjs +237 -0
  65. package/package.json +19 -14
  66. package/_banner.tsx +0 -60
  67. package/apps/aichat/components.tsx +0 -469
  68. package/apps/aichat/index.tsx +0 -220
  69. package/apps/aichat/script.ts +0 -460
  70. package/apps/aichat/state.ts +0 -325
  71. package/apps/aichat/types.ts +0 -19
  72. package/apps/app-todo.tsx +0 -201
  73. package/apps/async-data.tsx +0 -196
  74. package/apps/cli-wizard.tsx +0 -332
  75. package/apps/clipboard.tsx +0 -183
  76. package/apps/components.tsx +0 -658
  77. package/apps/data-explorer.tsx +0 -490
  78. package/apps/dev-tools.tsx +0 -395
  79. package/apps/explorer.tsx +0 -731
  80. package/apps/gallery.tsx +0 -653
  81. package/apps/inline-bench.tsx +0 -138
  82. package/apps/kanban.tsx +0 -265
  83. package/apps/layout-ref.tsx +0 -173
  84. package/apps/outline.tsx +0 -160
  85. package/apps/panes/index.tsx +0 -203
  86. package/apps/paste-demo.tsx +0 -185
  87. package/apps/scroll.tsx +0 -77
  88. package/apps/search-filter.tsx +0 -240
  89. package/apps/selection.tsx +0 -342
  90. package/apps/spatial-focus-demo.tsx +0 -368
  91. package/apps/task-list.tsx +0 -271
  92. package/apps/terminal-caps-demo.tsx +0 -334
  93. package/apps/terminal.tsx +0 -800
  94. package/apps/text-selection-demo.tsx +0 -189
  95. package/apps/textarea.tsx +0 -155
  96. package/apps/theme.tsx +0 -515
  97. package/apps/transform.tsx +0 -229
  98. package/apps/virtual-10k.tsx +0 -405
  99. package/apps/vterm-demo/index.tsx +0 -216
  100. package/components/counter.tsx +0 -45
  101. package/components/hello.tsx +0 -34
  102. package/components/progress-bar.tsx +0 -48
  103. package/components/select-list.tsx +0 -50
  104. package/components/spinner.tsx +0 -40
  105. package/components/text-input.tsx +0 -57
  106. package/components/virtual-list.tsx +0 -52
  107. package/dist/cli.d.mts +0 -1
  108. package/dist/cli.mjs.map +0 -1
  109. package/layout/dashboard.tsx +0 -953
  110. package/layout/live-resize.tsx +0 -282
  111. package/layout/overflow.tsx +0 -51
  112. package/layout/text-layout.tsx +0 -283
@@ -1,189 +0,0 @@
1
- /**
2
- * Text Selection Demo
3
- *
4
- * Demonstrates silvery's real text selection system using the useSelection hook.
5
- * Shows userSelect modes (text, none, contain) and live selection state readout.
6
- *
7
- * Run: bun vendor/silvery/examples/apps/text-selection-demo.tsx
8
- */
9
-
10
- import React from "react"
11
- import { Box, Text, H1, H2, Small, Muted, Strong, Kbd, HR } from "silvery"
12
- import { createApp } from "@silvery/create/create-app"
13
- import { pipe, withReact, withTerminal, withDomEvents } from "@silvery/create/plugins"
14
- import { ExampleBanner, type ExampleMeta } from "../_banner.js"
15
- import { useSelection } from "../../packages/ag-react/src/hooks/useSelection"
16
-
17
- export const meta: ExampleMeta = {
18
- name: "Text Selection",
19
- description: "Real selection via useSelection hook, userSelect modes, live state readout",
20
- demo: true,
21
- features: ["useSelection()", "userSelect prop", "CapabilityRegistry", "mouse drag selection"],
22
- }
23
-
24
- // ============================================================================
25
- // Selectable text panel (default — userSelect="text")
26
- // ============================================================================
27
-
28
- function SelectableTextPanel(): React.ReactElement {
29
- return (
30
- <Box flexDirection="column" borderStyle="round" borderColor="$border" paddingX={1} flexGrow={1}>
31
- <H2>Selectable Text</H2>
32
- <Small>userSelect="text" (default)</Small>
33
- <Box height={1} />
34
- <Text>Drag your mouse over this text to select it.</Text>
35
- <Text>Multi-line selections work across paragraphs.</Text>
36
- <Box height={1} />
37
- <Text color="$muted">The quick brown fox jumps over the lazy dog. Pack my box with five dozen liquor jugs.</Text>
38
- </Box>
39
- )
40
- }
41
-
42
- // ============================================================================
43
- // Non-selectable panel (userSelect="none")
44
- // ============================================================================
45
-
46
- function NonSelectablePanel(): React.ReactElement {
47
- return (
48
- <Box flexDirection="column" borderStyle="round" borderColor="$border" paddingX={1} flexGrow={1} userSelect="none">
49
- <H2>Non-Selectable</H2>
50
- <Small>userSelect="none"</Small>
51
- <Box height={1} />
52
- <Text>This area cannot be selected by mouse drag.</Text>
53
- <Text>Click events still work normally here.</Text>
54
- <Box height={1} />
55
- <Muted>Hold Alt and drag to override and select anyway.</Muted>
56
- </Box>
57
- )
58
- }
59
-
60
- // ============================================================================
61
- // Contained panel (userSelect="contain")
62
- // ============================================================================
63
-
64
- function ContainedPanel(): React.ReactElement {
65
- return (
66
- <Box flexDirection="column" borderStyle="round" borderColor="$warning" paddingX={1} flexGrow={1}>
67
- <H2 color="$warning">Contained Selection</H2>
68
- <Small>userSelect="contain"</Small>
69
- <Box height={1} />
70
- <Box flexDirection="column" borderStyle="round" borderColor="$primary" paddingX={1} userSelect="contain">
71
- <Text bold color="$primary">
72
- Selection Boundary
73
- </Text>
74
- <Box height={1} />
75
- <Text>Selection cannot escape this container.</Text>
76
- <Text>Try dragging past the border — it clips.</Text>
77
- <Box height={1} />
78
- <Text color="$success">Useful for modals, side panes, overlays.</Text>
79
- </Box>
80
- </Box>
81
- )
82
- }
83
-
84
- // ============================================================================
85
- // Live selection state readout via useSelection()
86
- // ============================================================================
87
-
88
- function SelectionStatePanel(): React.ReactElement {
89
- const selection = useSelection()
90
-
91
- return (
92
- <Box flexDirection="column" borderStyle="round" borderColor="$info" paddingX={1} flexGrow={1}>
93
- <H2 color="$info">Selection State</H2>
94
- <Small>Live readout from useSelection()</Small>
95
- <Box height={1} />
96
- {!selection ? (
97
- <Text color="$muted">useSelection() returned undefined — feature not installed</Text>
98
- ) : selection.range ? (
99
- <>
100
- <Box gap={1}>
101
- <Strong>Status:</Strong>
102
- <Text color="$success">{selection.selecting ? "Selecting..." : "Selected"}</Text>
103
- </Box>
104
- <Box gap={1}>
105
- <Strong>Source:</Strong>
106
- <Text>{selection.source ?? "unknown"}</Text>
107
- </Box>
108
- <Box gap={1}>
109
- <Strong>Anchor:</Strong>
110
- <Text>
111
- ({selection.range.anchor.col}, {selection.range.anchor.row})
112
- </Text>
113
- </Box>
114
- <Box gap={1}>
115
- <Strong>Head:</Strong>
116
- <Text>
117
- ({selection.range.head.col}, {selection.range.head.row})
118
- </Text>
119
- </Box>
120
- </>
121
- ) : (
122
- <Text color="$muted">No active selection — drag to select text</Text>
123
- )}
124
- </Box>
125
- )
126
- }
127
-
128
- // ============================================================================
129
- // Status bar
130
- // ============================================================================
131
-
132
- function StatusBar(): React.ReactElement {
133
- return (
134
- <Box flexDirection="row" gap={2} paddingX={1} flexShrink={0} userSelect="none">
135
- <Muted>
136
- <Kbd>Drag</Kbd> select <Kbd>Alt+Drag</Kbd> force select <Kbd>Ctrl+C</Kbd> quit
137
- </Muted>
138
- </Box>
139
- )
140
- }
141
-
142
- // ============================================================================
143
- // Main app
144
- // ============================================================================
145
-
146
- function TextSelectionDemo(): React.ReactElement {
147
- return (
148
- <Box flexDirection="column" padding={1} gap={1} height="100%">
149
- <Box>
150
- <H1 color="$primary">Text Selection Demo</H1>
151
- <Muted> — real selection via useSelection()</Muted>
152
- </Box>
153
-
154
- {/* Top row: selectable + non-selectable */}
155
- <Box flexDirection="row" gap={1} flexGrow={1}>
156
- <SelectableTextPanel />
157
- <NonSelectablePanel />
158
- </Box>
159
-
160
- {/* Bottom row: contained + live state readout */}
161
- <Box flexDirection="row" gap={1} flexGrow={1}>
162
- <ContainedPanel />
163
- <SelectionStatePanel />
164
- </Box>
165
-
166
- <HR />
167
- <StatusBar />
168
- </Box>
169
- )
170
- }
171
-
172
- // ============================================================================
173
- // Main
174
- // ============================================================================
175
-
176
- if (import.meta.main) {
177
- const app = pipe(
178
- createApp(() => () => ({})) as any,
179
- withReact(
180
- <ExampleBanner meta={meta} controls="Drag select Alt+Drag force select Ctrl+C quit">
181
- <TextSelectionDemo />
182
- </ExampleBanner>,
183
- ),
184
- withTerminal(process as any, { mouse: true }),
185
- withDomEvents(),
186
- )
187
- using handle = await app.run()
188
- await handle.waitUntilExit()
189
- }
package/apps/textarea.tsx DELETED
@@ -1,155 +0,0 @@
1
- /**
2
- * TextArea Example — Split-Pane Note Editor
3
- *
4
- * A note-taking app demonstrating:
5
- * - Multi-line text input with word wrapping and pre-filled content
6
- * - Split-pane layout: editor (2/3) + saved notes sidebar (1/3)
7
- * - Tab focus cycling between panes
8
- * - Cursor movement (arrow keys, Home/End, Ctrl+A/E)
9
- * - Kill operations (Ctrl+K, Ctrl+U)
10
- * - Word/character stats in the header
11
- * - Submit with Ctrl+Enter to collect notes
12
- */
13
-
14
- import React, { useState } from "react"
15
- import { render, Box, Text, H1, Strong, Muted, TextArea, useInput, useApp, createTerm, type Key } from "silvery"
16
- import { ExampleBanner, type ExampleMeta } from "../_banner.js"
17
-
18
- export const meta: ExampleMeta = {
19
- name: "TextArea",
20
- description: "Split-pane note editor with word wrap, kill ring, and note collection",
21
- features: ["TextArea", "Split pane layout", "Ctrl+Enter submit", "Tab focus cycling"],
22
- }
23
-
24
- const INITIAL_CONTENT = `# Release Notes — Silvery v0.1
25
-
26
- ## New Features
27
-
28
- - **Flexbox layout engine** — CSS-compatible sizing,
29
- wrapping, and gap support via Flexily
30
- - **38 built-in color palettes** — from Dracula
31
- to Solarized, Nord to Catppuccin
32
- - **Incremental rendering** — only changed cells
33
- are repainted, no full-screen flicker
34
-
35
- ## Breaking Changes
36
-
37
- - Dropped Node.js 18 support (now requires >=20)
38
- - Renamed \`useTerminal()\` to \`useTerm()\`
39
-
40
- ## Performance
41
-
42
- Benchmark results on an M4 MacBook Pro:
43
- Initial render: 2.1ms (80x24)
44
- Incremental: 0.3ms (typical diff)
45
- Layout: 0.8ms (1000 nodes)
46
-
47
- Thanks to all contributors!`
48
-
49
- export function NoteEditor() {
50
- const { exit } = useApp()
51
- const [notes, setNotes] = useState<string[]>([])
52
- const [value, setValue] = useState(INITIAL_CONTENT)
53
- const [focusIndex, setFocusIndex] = useState(0)
54
-
55
- useInput((input: string, key: Key) => {
56
- if (key.escape) {
57
- exit()
58
- }
59
- if (key.tab && !key.shift) {
60
- setFocusIndex((prev) => (prev + 1) % 2)
61
- }
62
- if (key.tab && key.shift) {
63
- setFocusIndex((prev) => (prev - 1 + 2) % 2)
64
- }
65
- })
66
-
67
- function handleSubmit(text: string) {
68
- if (text.trim()) {
69
- setNotes((prev) => [...prev, text.trim()])
70
- setValue("")
71
- }
72
- }
73
-
74
- const lines = value.split("\n").length
75
- const chars = value.length
76
- const words = value.split(/\s+/).filter(Boolean).length
77
-
78
- return (
79
- <Box flexDirection="column" flexGrow={1} padding={1}>
80
- <Box flexDirection="row" gap={1} flexGrow={1}>
81
- {/* Main editor */}
82
- <Box
83
- borderStyle="round"
84
- borderColor={focusIndex === 0 ? "$primary" : "$border"}
85
- flexDirection="column"
86
- flexGrow={3}
87
- flexBasis={0}
88
- >
89
- <Box paddingX={1} justifyContent="space-between">
90
- <H1>Editor</H1>
91
- <Muted>
92
- {lines} lines, {words} words, {chars} chars
93
- </Muted>
94
- </Box>
95
- <Text> </Text>
96
- <Box paddingX={1} flexGrow={1}>
97
- <TextArea
98
- value={value}
99
- onChange={setValue}
100
- onSubmit={handleSubmit}
101
- height={16}
102
- isActive={focusIndex === 0}
103
- />
104
- </Box>
105
- </Box>
106
-
107
- {/* Saved notes sidebar */}
108
- <Box
109
- borderStyle="round"
110
- borderColor={focusIndex === 1 ? "$primary" : "$border"}
111
- flexDirection="column"
112
- flexGrow={2}
113
- flexBasis={0}
114
- >
115
- <Box paddingX={1}>
116
- <H1>Notes</H1>
117
- <Muted> ({notes.length})</Muted>
118
- </Box>
119
- <Text> </Text>
120
- <Box flexDirection="column" paddingX={1} overflow="scroll" flexGrow={1}>
121
- {notes.length === 0 ? (
122
- <Muted>No notes yet.</Muted>
123
- ) : (
124
- notes.map((note, i) => (
125
- <Box key={i} flexDirection="column" marginBottom={1}>
126
- <Text wrap="truncate">
127
- <Strong color="$success">#{i + 1}</Strong> {note.split("\n")[0]}
128
- </Text>
129
- <Muted>
130
- {note.split("\n").length} lines, {note.length} chars
131
- </Muted>
132
- </Box>
133
- ))
134
- )}
135
- </Box>
136
- </Box>
137
- </Box>
138
- </Box>
139
- )
140
- }
141
-
142
- async function main() {
143
- using term = createTerm()
144
- const { waitUntilExit } = await render(
145
- <ExampleBanner meta={meta} controls="Tab switch pane Ctrl+Enter submit Esc quit">
146
- <NoteEditor />
147
- </ExampleBanner>,
148
- term,
149
- )
150
- await waitUntilExit()
151
- }
152
-
153
- if (import.meta.main) {
154
- main().catch(console.error)
155
- }