silvery 0.3.0 → 0.4.1
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/README.md +41 -145
- package/dist/chalk.js +3 -0
- package/dist/chalk.js.map +11 -0
- package/dist/index.js +340 -0
- package/dist/index.js.map +282 -0
- package/dist/ink.js +129 -0
- package/dist/ink.js.map +140 -0
- package/dist/runtime.js +394 -0
- package/dist/runtime.js.map +286 -0
- package/dist/theme.js +343 -0
- package/dist/theme.js.map +286 -0
- package/dist/ui/animation.js +3 -0
- package/dist/ui/animation.js.map +15 -0
- package/dist/ui/ansi.js +3 -0
- package/dist/ui/ansi.js.map +10 -0
- package/dist/ui/cli.js +8 -0
- package/dist/ui/cli.js.map +14 -0
- package/dist/ui/display.js +4 -0
- package/dist/ui/display.js.map +10 -0
- package/dist/ui/image.js +4 -0
- package/dist/ui/image.js.map +15 -0
- package/dist/ui/input.js +3 -0
- package/dist/ui/input.js.map +11 -0
- package/dist/ui/progress.js +8 -0
- package/dist/ui/progress.js.map +20 -0
- package/dist/ui/react.js +3 -0
- package/dist/ui/react.js.map +15 -0
- package/dist/ui/utils.js +3 -0
- package/dist/ui/utils.js.map +10 -0
- package/dist/ui/wrappers.js +14 -0
- package/dist/ui/wrappers.js.map +19 -0
- package/dist/ui.js +17 -0
- package/dist/ui.js.map +20 -0
- package/package.json +67 -15
- package/src/index.ts +67 -1
- package/src/runtime.ts +4 -0
- package/src/theme.ts +4 -0
- package/src/ui/animation.ts +2 -0
- package/src/ui/ansi.ts +2 -0
- package/src/ui/cli.ts +2 -0
- package/src/ui/display.ts +2 -0
- package/src/ui/image.ts +2 -0
- package/src/ui/input.ts +2 -0
- package/src/ui/progress.ts +2 -0
- package/src/ui/react.ts +2 -0
- package/src/ui/utils.ts +2 -0
- package/src/ui/wrappers.ts +2 -0
- package/src/ui.ts +4 -0
- package/examples/CLAUDE.md +0 -75
- package/examples/_banner.tsx +0 -60
- package/examples/cli.ts +0 -228
- package/examples/index.md +0 -101
- package/examples/inline/inline-nontty.tsx +0 -98
- package/examples/inline/inline-progress.tsx +0 -79
- package/examples/inline/inline-simple.tsx +0 -63
- package/examples/inline/scrollback.tsx +0 -185
- package/examples/interactive/_input-debug.tsx +0 -110
- package/examples/interactive/_stdin-test.ts +0 -71
- package/examples/interactive/_textarea-bare.tsx +0 -45
- package/examples/interactive/aichat/components.tsx +0 -468
- package/examples/interactive/aichat/index.tsx +0 -207
- package/examples/interactive/aichat/script.ts +0 -460
- package/examples/interactive/aichat/state.ts +0 -326
- package/examples/interactive/aichat/types.ts +0 -19
- package/examples/interactive/app-todo.tsx +0 -198
- package/examples/interactive/async-data.tsx +0 -208
- package/examples/interactive/cli-wizard.tsx +0 -332
- package/examples/interactive/clipboard.tsx +0 -183
- package/examples/interactive/components.tsx +0 -463
- package/examples/interactive/data-explorer.tsx +0 -506
- package/examples/interactive/dev-tools.tsx +0 -379
- package/examples/interactive/explorer.tsx +0 -747
- package/examples/interactive/gallery.tsx +0 -652
- package/examples/interactive/inline-bench.tsx +0 -136
- package/examples/interactive/kanban.tsx +0 -267
- package/examples/interactive/layout-ref.tsx +0 -185
- package/examples/interactive/outline.tsx +0 -171
- package/examples/interactive/paste-demo.tsx +0 -198
- package/examples/interactive/scroll.tsx +0 -77
- package/examples/interactive/search-filter.tsx +0 -240
- package/examples/interactive/task-list.tsx +0 -279
- package/examples/interactive/terminal.tsx +0 -798
- package/examples/interactive/textarea.tsx +0 -103
- package/examples/interactive/theme.tsx +0 -336
- package/examples/interactive/transform.tsx +0 -256
- package/examples/interactive/virtual-10k.tsx +0 -413
- package/examples/kitty/canvas.tsx +0 -519
- package/examples/kitty/generate-samples.ts +0 -236
- package/examples/kitty/image-component.tsx +0 -273
- package/examples/kitty/images.tsx +0 -604
- package/examples/kitty/input.tsx +0 -371
- package/examples/kitty/keys.tsx +0 -378
- package/examples/kitty/paint.tsx +0 -1017
- package/examples/layout/dashboard.tsx +0 -551
- package/examples/layout/live-resize.tsx +0 -290
- package/examples/layout/overflow.tsx +0 -51
- package/examples/playground/README.md +0 -69
- package/examples/playground/build.ts +0 -61
- package/examples/playground/index.html +0 -420
- package/examples/playground/playground-app.tsx +0 -416
- package/examples/runtime/elm-counter.tsx +0 -206
- package/examples/runtime/hello-runtime.tsx +0 -73
- package/examples/runtime/pipe-composition.tsx +0 -184
- package/examples/runtime/run-counter.tsx +0 -78
- package/examples/runtime/runtime-counter.tsx +0 -197
- package/examples/screenshots/generate.tsx +0 -563
- package/examples/scrollback-perf.tsx +0 -230
- package/examples/viewer.tsx +0 -654
- package/examples/web/build.ts +0 -365
- package/examples/web/canvas-app.tsx +0 -80
- package/examples/web/canvas.html +0 -89
- package/examples/web/dom-app.tsx +0 -81
- package/examples/web/dom.html +0 -113
- package/examples/web/showcase-app.tsx +0 -107
- package/examples/web/showcase.html +0 -34
- package/examples/web/showcases/index.tsx +0 -56
- package/examples/web/viewer-app.tsx +0 -555
- package/examples/web/viewer.html +0 -30
- package/examples/web/xterm-app.tsx +0 -105
- package/examples/web/xterm.html +0 -118
package/examples/kitty/input.tsx
DELETED
|
@@ -1,371 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Rich Input
|
|
3
|
-
*
|
|
4
|
-
* Combined keyboard + mouse showcase demonstrating all rich terminal input
|
|
5
|
-
* features: Kitty protocol modifiers, mouse tracking, mode switching, and
|
|
6
|
-
* a live event log.
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Keybinding display using parseHotkey with ⌘ ⌥ ⌃ ⇧ ✦ symbols
|
|
10
|
-
* - Mouse-clickable UI elements
|
|
11
|
-
* - Mode switching (normal/insert)
|
|
12
|
-
* - Event log showing all input events
|
|
13
|
-
* - Kitty auto-detection
|
|
14
|
-
*
|
|
15
|
-
* Run: bun vendor/silvery/examples/kitty/rich-input.tsx
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import React, { useState, useRef, useEffect } from "react"
|
|
19
|
-
import {
|
|
20
|
-
render,
|
|
21
|
-
Box,
|
|
22
|
-
Text,
|
|
23
|
-
useInput,
|
|
24
|
-
useApp,
|
|
25
|
-
createTerm,
|
|
26
|
-
parseHotkey,
|
|
27
|
-
parseMouseSequence,
|
|
28
|
-
isMouseSequence,
|
|
29
|
-
KittyFlags,
|
|
30
|
-
enableKittyKeyboard,
|
|
31
|
-
disableKittyKeyboard,
|
|
32
|
-
enableMouse,
|
|
33
|
-
disableMouse,
|
|
34
|
-
detectKittyFromStdio,
|
|
35
|
-
type Key,
|
|
36
|
-
type ParsedMouse,
|
|
37
|
-
} from "../../src/index.js"
|
|
38
|
-
import { ExampleBanner, type ExampleMeta } from "../_banner.js"
|
|
39
|
-
|
|
40
|
-
export const meta: ExampleMeta = {
|
|
41
|
-
name: "Mouse & Keys",
|
|
42
|
-
description: "Combined keyboard + mouse input showcase with Kitty protocol",
|
|
43
|
-
features: ["parseHotkey()", "parseMouseSequence()", "⌘ ⌥ ⌃ ⇧ ✦"],
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
type Mode = "normal" | "insert"
|
|
47
|
-
type EventEntry = {
|
|
48
|
-
index: number
|
|
49
|
-
type: "key" | "mouse"
|
|
50
|
-
summary: string
|
|
51
|
-
color?: string
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Keybinding definitions with macOS symbols
|
|
55
|
-
const KEYBINDINGS = [
|
|
56
|
-
{ hotkey: "i", action: "Enter insert mode", mode: "normal" as const },
|
|
57
|
-
{ hotkey: "Escape", action: "Return to normal mode", mode: "insert" as const },
|
|
58
|
-
{ hotkey: "⌃c", action: "Quit", mode: "both" as const },
|
|
59
|
-
{ hotkey: "j", action: "Move down", mode: "normal" as const },
|
|
60
|
-
{ hotkey: "k", action: "Move up", mode: "normal" as const },
|
|
61
|
-
{ hotkey: "⇧J", action: "Move item down", mode: "normal" as const },
|
|
62
|
-
{ hotkey: "⇧K", action: "Move item up", mode: "normal" as const },
|
|
63
|
-
{ hotkey: "⌘s", action: "Save (Kitty only)", mode: "both" as const },
|
|
64
|
-
{ hotkey: "✦⌘x", action: "Special action (Kitty only)", mode: "normal" as const },
|
|
65
|
-
{ hotkey: "q", action: "Quit", mode: "normal" as const },
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
const ITEMS = ["Inbox", "Today", "Upcoming", "Projects", "Archive", "Trash"]
|
|
69
|
-
|
|
70
|
-
function RichInputDemo({ kittySupported }: { kittySupported: boolean }): JSX.Element {
|
|
71
|
-
const { exit } = useApp()
|
|
72
|
-
const stdin = process.stdin
|
|
73
|
-
const [mode, setMode] = useState<Mode>("normal")
|
|
74
|
-
const [cursor, setCursor] = useState(0)
|
|
75
|
-
const [events, setEvents] = useState<EventEntry[]>([])
|
|
76
|
-
const [insertText, setInsertText] = useState("")
|
|
77
|
-
const [mousePos, setMousePos] = useState<{ x: number; y: number } | null>(null)
|
|
78
|
-
const counterRef = useRef(0)
|
|
79
|
-
|
|
80
|
-
// Enable mouse tracking
|
|
81
|
-
useEffect(() => {
|
|
82
|
-
process.stdout.write(enableMouse())
|
|
83
|
-
return () => {
|
|
84
|
-
process.stdout.write(disableMouse())
|
|
85
|
-
}
|
|
86
|
-
}, [])
|
|
87
|
-
|
|
88
|
-
function addEvent(type: "key" | "mouse", summary: string, color?: string) {
|
|
89
|
-
counterRef.current++
|
|
90
|
-
setEvents((prev) => [...prev.slice(-18), { index: counterRef.current, type, summary, color }])
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Listen to raw stdin for mouse events + Kitty key details
|
|
94
|
-
useEffect(() => {
|
|
95
|
-
const onData = (data: Buffer) => {
|
|
96
|
-
const raw = data.toString()
|
|
97
|
-
|
|
98
|
-
if (isMouseSequence(raw)) {
|
|
99
|
-
const parsed = parseMouseSequence(raw)
|
|
100
|
-
if (!parsed) return
|
|
101
|
-
|
|
102
|
-
setMousePos({ x: parsed.x, y: parsed.y })
|
|
103
|
-
|
|
104
|
-
const mods: string[] = []
|
|
105
|
-
if (parsed.ctrl) mods.push("⌃")
|
|
106
|
-
if (parsed.shift) mods.push("⇧")
|
|
107
|
-
if (parsed.meta) mods.push("⌥")
|
|
108
|
-
const modStr = mods.length > 0 ? mods.join("") + " " : ""
|
|
109
|
-
|
|
110
|
-
if (parsed.action === "down") {
|
|
111
|
-
const btn = ["Left", "Middle", "Right"][parsed.button] ?? `Btn${parsed.button}`
|
|
112
|
-
addEvent("mouse", `${modStr}${btn} click at (${parsed.x},${parsed.y})`, "blue")
|
|
113
|
-
} else if (parsed.action === "wheel") {
|
|
114
|
-
addEvent(
|
|
115
|
-
"mouse",
|
|
116
|
-
`${modStr}Scroll ${parsed.delta! < 0 ? "up" : "down"} at (${parsed.x},${parsed.y})`,
|
|
117
|
-
"magenta",
|
|
118
|
-
)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
stdin.on("data", onData)
|
|
124
|
-
return () => {
|
|
125
|
-
stdin.off("data", onData)
|
|
126
|
-
}
|
|
127
|
-
}, [stdin])
|
|
128
|
-
|
|
129
|
-
useInput((input: string, key: Key) => {
|
|
130
|
-
// Always: Ctrl+C or q (in normal mode) to quit
|
|
131
|
-
if (key.ctrl && input === "c") {
|
|
132
|
-
addEvent("key", "⌃C Quit", "red")
|
|
133
|
-
exit()
|
|
134
|
-
return
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
if (mode === "normal") {
|
|
138
|
-
if (input === "q") {
|
|
139
|
-
addEvent("key", "q Quit", "red")
|
|
140
|
-
exit()
|
|
141
|
-
return
|
|
142
|
-
}
|
|
143
|
-
if (input === "i") {
|
|
144
|
-
setMode("insert")
|
|
145
|
-
setInsertText("")
|
|
146
|
-
addEvent("key", "i Enter insert mode", "green")
|
|
147
|
-
return
|
|
148
|
-
}
|
|
149
|
-
if (input === "j" || key.downArrow) {
|
|
150
|
-
setCursor((c) => Math.min(c + 1, ITEMS.length - 1))
|
|
151
|
-
addEvent("key", `${input === "j" ? "j" : "Arrow"} Move down`)
|
|
152
|
-
return
|
|
153
|
-
}
|
|
154
|
-
if (input === "k" || key.upArrow) {
|
|
155
|
-
setCursor((c) => Math.max(c - 1, 0))
|
|
156
|
-
addEvent("key", `${input === "k" ? "k" : "Arrow"} Move up`)
|
|
157
|
-
return
|
|
158
|
-
}
|
|
159
|
-
if (input === "J" && key.shift) {
|
|
160
|
-
addEvent("key", "⇧J Move item down", "yellow")
|
|
161
|
-
return
|
|
162
|
-
}
|
|
163
|
-
if (input === "K" && key.shift) {
|
|
164
|
-
addEvent("key", "⇧K Move item up", "yellow")
|
|
165
|
-
return
|
|
166
|
-
}
|
|
167
|
-
// Kitty-only: Super modifier
|
|
168
|
-
if (key.super && input === "s") {
|
|
169
|
-
addEvent("key", "⌘S Save", "green")
|
|
170
|
-
return
|
|
171
|
-
}
|
|
172
|
-
if (key.hyper && key.super && input === "x") {
|
|
173
|
-
addEvent("key", "✦⌘X Special action!", "magenta")
|
|
174
|
-
return
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
// Log unhandled keys
|
|
178
|
-
if (input && input >= " ") {
|
|
179
|
-
addEvent("key", `${input} (unbound)`, "gray")
|
|
180
|
-
}
|
|
181
|
-
} else if (mode === "insert") {
|
|
182
|
-
if (key.escape) {
|
|
183
|
-
setMode("normal")
|
|
184
|
-
addEvent("key", "Esc Normal mode", "green")
|
|
185
|
-
return
|
|
186
|
-
}
|
|
187
|
-
if (key.backspace) {
|
|
188
|
-
setInsertText((t) => t.slice(0, -1))
|
|
189
|
-
addEvent("key", "Backspace", "gray")
|
|
190
|
-
return
|
|
191
|
-
}
|
|
192
|
-
if (input && input >= " ") {
|
|
193
|
-
setInsertText((t) => t + input)
|
|
194
|
-
addEvent("key", `'${input}'`, "gray")
|
|
195
|
-
return
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
})
|
|
199
|
-
|
|
200
|
-
return (
|
|
201
|
-
<Box flexDirection="column" padding={1}>
|
|
202
|
-
{/* Top bar */}
|
|
203
|
-
<Box gap={2} marginBottom={1}>
|
|
204
|
-
<Text>
|
|
205
|
-
<Text bold>Mode:</Text>{" "}
|
|
206
|
-
<Text color={mode === "normal" ? "cyan" : "green"} bold>
|
|
207
|
-
{mode.toUpperCase()}
|
|
208
|
-
</Text>
|
|
209
|
-
</Text>
|
|
210
|
-
<Text>
|
|
211
|
-
<Text bold>Kitty:</Text> {kittySupported ? <Text color="green">yes</Text> : <Text color="yellow">no</Text>}
|
|
212
|
-
</Text>
|
|
213
|
-
{mousePos && (
|
|
214
|
-
<Text>
|
|
215
|
-
<Text bold>Mouse:</Text> ({mousePos.x},{mousePos.y})
|
|
216
|
-
</Text>
|
|
217
|
-
)}
|
|
218
|
-
</Box>
|
|
219
|
-
|
|
220
|
-
<Box gap={2}>
|
|
221
|
-
{/* Left: List + keybindings */}
|
|
222
|
-
<Box flexDirection="column" width={35}>
|
|
223
|
-
{/* Interactive list */}
|
|
224
|
-
<Text bold color="cyan">
|
|
225
|
-
Items
|
|
226
|
-
</Text>
|
|
227
|
-
<Box flexDirection="column" marginTop={1}>
|
|
228
|
-
{ITEMS.map((item, i) => (
|
|
229
|
-
<Text key={i}>
|
|
230
|
-
<Text color={i === cursor ? "cyan" : "white"} bold={i === cursor}>
|
|
231
|
-
{i === cursor ? ">" : " "} {item}
|
|
232
|
-
</Text>
|
|
233
|
-
</Text>
|
|
234
|
-
))}
|
|
235
|
-
</Box>
|
|
236
|
-
|
|
237
|
-
{/* Insert mode text */}
|
|
238
|
-
{mode === "insert" && (
|
|
239
|
-
<Box marginTop={1} borderStyle="single" borderColor="green" paddingX={1}>
|
|
240
|
-
<Text>
|
|
241
|
-
<Text bold color="green">
|
|
242
|
-
Input:
|
|
243
|
-
</Text>{" "}
|
|
244
|
-
{insertText}
|
|
245
|
-
<Text color="green">|</Text>
|
|
246
|
-
</Text>
|
|
247
|
-
</Box>
|
|
248
|
-
)}
|
|
249
|
-
|
|
250
|
-
{/* Keybinding reference */}
|
|
251
|
-
<Box flexDirection="column" marginTop={1}>
|
|
252
|
-
<Text bold dim>
|
|
253
|
-
Keybindings
|
|
254
|
-
</Text>
|
|
255
|
-
{KEYBINDINGS.filter((kb) => kb.mode === "both" || kb.mode === mode).map((kb, i) => {
|
|
256
|
-
const parsed = parseHotkey(kb.hotkey)
|
|
257
|
-
const hotkeyDisplay = formatHotkey(kb.hotkey, parsed)
|
|
258
|
-
const needsKitty = kb.hotkey.includes("⌘") || kb.hotkey.includes("✦")
|
|
259
|
-
return (
|
|
260
|
-
<Text key={i} dimColor={needsKitty && !kittySupported}>
|
|
261
|
-
<Text bold color="yellow">
|
|
262
|
-
{hotkeyDisplay.padEnd(10)}
|
|
263
|
-
</Text>{" "}
|
|
264
|
-
{kb.action}
|
|
265
|
-
{needsKitty && !kittySupported ? <Text dim> (needs Kitty)</Text> : ""}
|
|
266
|
-
</Text>
|
|
267
|
-
)
|
|
268
|
-
})}
|
|
269
|
-
</Box>
|
|
270
|
-
</Box>
|
|
271
|
-
|
|
272
|
-
{/* Right: Event log */}
|
|
273
|
-
<Box flexDirection="column" width={45}>
|
|
274
|
-
<Text bold color="cyan">
|
|
275
|
-
All Events ({counterRef.current})
|
|
276
|
-
</Text>
|
|
277
|
-
<Box height={1} />
|
|
278
|
-
{events.length === 0 ? (
|
|
279
|
-
<Text dim>Interact to see events...</Text>
|
|
280
|
-
) : (
|
|
281
|
-
events.map((e, i) => (
|
|
282
|
-
<Text key={i} dimColor={i < events.length - 1}>
|
|
283
|
-
<Text color={e.type === "key" ? "cyan" : "blue"}>{e.type === "key" ? "KEY" : "PTR"}</Text>{" "}
|
|
284
|
-
<Text color={(e.color ?? "white") as any}>{e.summary}</Text>
|
|
285
|
-
</Text>
|
|
286
|
-
))
|
|
287
|
-
)}
|
|
288
|
-
</Box>
|
|
289
|
-
</Box>
|
|
290
|
-
</Box>
|
|
291
|
-
)
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function formatHotkey(raw: string, parsed: ReturnType<typeof parseHotkey>): string {
|
|
295
|
-
// Use the raw string if it already uses symbols
|
|
296
|
-
if (/[⌘⌥⌃⇧✦]/.test(raw)) return raw
|
|
297
|
-
// Otherwise build from parsed
|
|
298
|
-
const parts: string[] = []
|
|
299
|
-
if (parsed.ctrl) parts.push("⌃")
|
|
300
|
-
if (parsed.shift) parts.push("⇧")
|
|
301
|
-
if (parsed.alt) parts.push("⌥")
|
|
302
|
-
if (parsed.super) parts.push("⌘")
|
|
303
|
-
if (parsed.hyper) parts.push("✦")
|
|
304
|
-
parts.push(parsed.key)
|
|
305
|
-
return parts.join("")
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
async function main() {
|
|
309
|
-
const cleanup = () => {
|
|
310
|
-
const stdout = process.stdout
|
|
311
|
-
stdout.write("\x1b[?1003l\x1b[?1006l") // Disable mouse
|
|
312
|
-
stdout.write("\x1b[?25h") // Show cursor
|
|
313
|
-
stdout.write("\x1b[?1049l") // Exit alternate screen
|
|
314
|
-
stdout.write("\x1b[0m") // Reset colors
|
|
315
|
-
if (process.stdin.isTTY && process.stdin.isRaw) {
|
|
316
|
-
try {
|
|
317
|
-
process.stdin.setRawMode(false)
|
|
318
|
-
} catch {}
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
process.on("uncaughtException", (err) => {
|
|
322
|
-
cleanup()
|
|
323
|
-
throw err
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
// Detect Kitty support
|
|
327
|
-
const kittyResult = await detectKittyFromStdio(process.stdout, process.stdin)
|
|
328
|
-
|
|
329
|
-
// Enable Kitty with full flags if supported
|
|
330
|
-
if (kittyResult.supported) {
|
|
331
|
-
const flags =
|
|
332
|
-
KittyFlags.DISAMBIGUATE |
|
|
333
|
-
KittyFlags.REPORT_EVENTS |
|
|
334
|
-
KittyFlags.REPORT_ALTERNATE |
|
|
335
|
-
KittyFlags.REPORT_ALL_KEYS |
|
|
336
|
-
KittyFlags.REPORT_TEXT
|
|
337
|
-
process.stdout.write(enableKittyKeyboard(flags))
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
using term = createTerm()
|
|
341
|
-
const { waitUntilExit } = await render(
|
|
342
|
-
<ExampleBanner meta={meta} controls="i insert Esc normal j/k navigate q quit">
|
|
343
|
-
<RichInputDemo kittySupported={kittyResult.supported} />
|
|
344
|
-
</ExampleBanner>,
|
|
345
|
-
term,
|
|
346
|
-
)
|
|
347
|
-
await waitUntilExit()
|
|
348
|
-
|
|
349
|
-
// Cleanup
|
|
350
|
-
if (kittyResult.supported) {
|
|
351
|
-
process.stdout.write(disableKittyKeyboard())
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
if (import.meta.main) {
|
|
356
|
-
main().catch((err) => {
|
|
357
|
-
// Restore terminal on crash
|
|
358
|
-
const stdout = process.stdout
|
|
359
|
-
stdout.write("\x1b[?1003l\x1b[?1006l") // Disable mouse
|
|
360
|
-
stdout.write("\x1b[?25h") // Show cursor
|
|
361
|
-
stdout.write("\x1b[?1049l") // Exit alternate screen
|
|
362
|
-
stdout.write("\x1b[0m") // Reset colors
|
|
363
|
-
if (process.stdin.isTTY && process.stdin.isRaw) {
|
|
364
|
-
try {
|
|
365
|
-
process.stdin.setRawMode(false)
|
|
366
|
-
} catch {}
|
|
367
|
-
}
|
|
368
|
-
console.error(err)
|
|
369
|
-
process.exit(1)
|
|
370
|
-
})
|
|
371
|
-
}
|