@silvery/examples 0.17.3 → 0.17.5

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 (111) hide show
  1. package/dist/UPNG-ShUlaTDh.mjs +5074 -0
  2. package/dist/__vite-browser-external-2447137e-Bopa5BFR.mjs +4 -0
  3. package/dist/_banner-A70_y2Vi.mjs +43 -0
  4. package/dist/ansi-0VXlUmNn.mjs +16397 -0
  5. package/dist/apng-B0gRaDVT.mjs +3 -0
  6. package/dist/apng-BTRDTfDW.mjs +68 -0
  7. package/dist/apps/aichat/index.mjs +1298 -0
  8. package/dist/apps/app-todo.mjs +138 -0
  9. package/dist/apps/async-data.mjs +203 -0
  10. package/dist/apps/cli-wizard.mjs +338 -0
  11. package/dist/apps/clipboard.mjs +197 -0
  12. package/dist/apps/components.mjs +863 -0
  13. package/dist/apps/data-explorer.mjs +482 -0
  14. package/dist/apps/dev-tools.mjs +396 -0
  15. package/dist/apps/explorer.mjs +697 -0
  16. package/dist/apps/gallery.mjs +765 -0
  17. package/dist/apps/inline-bench.mjs +115 -0
  18. package/dist/apps/kanban.mjs +279 -0
  19. package/dist/apps/layout-ref.mjs +186 -0
  20. package/dist/apps/outline.mjs +202 -0
  21. package/dist/apps/paste-demo.mjs +188 -0
  22. package/dist/apps/scroll.mjs +85 -0
  23. package/dist/apps/search-filter.mjs +286 -0
  24. package/dist/apps/selection.mjs +354 -0
  25. package/dist/apps/spatial-focus-demo.mjs +387 -0
  26. package/dist/apps/task-list.mjs +257 -0
  27. package/dist/apps/terminal-caps-demo.mjs +314 -0
  28. package/dist/apps/terminal.mjs +871 -0
  29. package/dist/apps/text-selection-demo.mjs +253 -0
  30. package/dist/apps/textarea.mjs +177 -0
  31. package/dist/apps/theme.mjs +660 -0
  32. package/dist/apps/transform.mjs +214 -0
  33. package/dist/apps/virtual-10k.mjs +421 -0
  34. package/dist/assets/resvgjs.darwin-arm64-BtufyGW1.node +0 -0
  35. package/dist/backends-Dj-11kZF.mjs +1179 -0
  36. package/dist/backends-U3QwStfO.mjs +3 -0
  37. package/dist/{cli.mjs → bin/cli.mjs} +15 -19
  38. package/dist/chunk-BSw8zbkd.mjs +37 -0
  39. package/dist/components/counter.mjs +47 -0
  40. package/dist/components/hello.mjs +30 -0
  41. package/dist/components/progress-bar.mjs +58 -0
  42. package/dist/components/select-list.mjs +84 -0
  43. package/dist/components/spinner.mjs +56 -0
  44. package/dist/components/text-input.mjs +61 -0
  45. package/dist/components/virtual-list.mjs +50 -0
  46. package/dist/flexily-zero-adapter-ByVzLTFP.mjs +3374 -0
  47. package/dist/gif-B6NGH5gs.mjs +3 -0
  48. package/dist/gif-CfkOF-iG.mjs +71 -0
  49. package/dist/gifenc-BI4ihP_T.mjs +728 -0
  50. package/dist/key-mapping-5oYQdAQE.mjs +3 -0
  51. package/dist/key-mapping-D4LR1go6.mjs +130 -0
  52. package/dist/layout/dashboard.mjs +1203 -0
  53. package/dist/layout/live-resize.mjs +302 -0
  54. package/dist/layout/overflow.mjs +69 -0
  55. package/dist/layout/text-layout.mjs +334 -0
  56. package/dist/node-nsrAOjH4.mjs +1083 -0
  57. package/dist/plugins-CT0DdV_E.mjs +3056 -0
  58. package/dist/resvg-js-Cnk2o49d.mjs +201 -0
  59. package/dist/src-9ZhfQyzD.mjs +814 -0
  60. package/dist/src-CUUOuRH6.mjs +5322 -0
  61. package/dist/src-jO3Zuzjj.mjs +23538 -0
  62. package/dist/usingCtx-CsEf0xO3.mjs +57 -0
  63. package/dist/yoga-adapter-BSQHuMV9.mjs +237 -0
  64. package/package.json +21 -14
  65. package/_banner.tsx +0 -60
  66. package/apps/aichat/components.tsx +0 -469
  67. package/apps/aichat/index.tsx +0 -220
  68. package/apps/aichat/script.ts +0 -460
  69. package/apps/aichat/state.ts +0 -325
  70. package/apps/aichat/types.ts +0 -19
  71. package/apps/app-todo.tsx +0 -201
  72. package/apps/async-data.tsx +0 -196
  73. package/apps/cli-wizard.tsx +0 -332
  74. package/apps/clipboard.tsx +0 -183
  75. package/apps/components.tsx +0 -658
  76. package/apps/data-explorer.tsx +0 -490
  77. package/apps/dev-tools.tsx +0 -395
  78. package/apps/explorer.tsx +0 -731
  79. package/apps/gallery.tsx +0 -653
  80. package/apps/inline-bench.tsx +0 -138
  81. package/apps/kanban.tsx +0 -265
  82. package/apps/layout-ref.tsx +0 -173
  83. package/apps/outline.tsx +0 -160
  84. package/apps/panes/index.tsx +0 -203
  85. package/apps/paste-demo.tsx +0 -185
  86. package/apps/scroll.tsx +0 -80
  87. package/apps/search-filter.tsx +0 -240
  88. package/apps/selection.tsx +0 -346
  89. package/apps/spatial-focus-demo.tsx +0 -372
  90. package/apps/task-list.tsx +0 -271
  91. package/apps/terminal-caps-demo.tsx +0 -317
  92. package/apps/terminal.tsx +0 -784
  93. package/apps/text-selection-demo.tsx +0 -193
  94. package/apps/textarea.tsx +0 -155
  95. package/apps/theme.tsx +0 -515
  96. package/apps/transform.tsx +0 -229
  97. package/apps/virtual-10k.tsx +0 -405
  98. package/apps/vterm-demo/index.tsx +0 -216
  99. package/components/counter.tsx +0 -49
  100. package/components/hello.tsx +0 -38
  101. package/components/progress-bar.tsx +0 -52
  102. package/components/select-list.tsx +0 -54
  103. package/components/spinner.tsx +0 -44
  104. package/components/text-input.tsx +0 -61
  105. package/components/virtual-list.tsx +0 -56
  106. package/dist/cli.d.mts +0 -1
  107. package/dist/cli.mjs.map +0 -1
  108. package/layout/dashboard.tsx +0 -953
  109. package/layout/live-resize.tsx +0 -282
  110. package/layout/overflow.tsx +0 -51
  111. package/layout/text-layout.tsx +0 -283
@@ -0,0 +1,871 @@
1
+ import { t as _usingCtx } from "../usingCtx-CsEf0xO3.mjs";
2
+ import { t as ExampleBanner } from "../_banner-A70_y2Vi.mjs";
3
+ import { useEffect, useRef, useState } from "react";
4
+ import { Box, H2, Kbd, KittyFlags, Muted, Small, Tab, TabList, TabPanel, Tabs, Text, copyToClipboard, createTerm, detectKittyFromStdio, disableFocusReporting, disableKittyKeyboard, disableMouse, enableFocusReporting, enableKittyKeyboard, enableMouse, isMouseSequence, parseClipboardResponse, parseFocusEvent, parseKeypress, parseMouseSequence, render, requestClipboard, useApp, useInput, useStdout } from "silvery";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region apps/terminal.tsx
7
+ /**
8
+ * Terminal Kitchensink
9
+ *
10
+ * A tabbed demo showcasing terminal interaction capabilities:
11
+ * keyboard events, mouse tracking, clipboard (OSC 52), and
12
+ * terminal focus detection.
13
+ *
14
+ * Features:
15
+ * - Key event tester with color-coded modifier badges
16
+ * - Mouse position tracking, button state, scroll events
17
+ * - OSC 52 clipboard copy/paste
18
+ * - Terminal focus/blur tracking with event log
19
+ * - Kitty keyboard protocol auto-detection
20
+ *
21
+ * Run: bun vendor/silvery/examples/apps/terminal.tsx
22
+ */
23
+ const meta = {
24
+ name: "Terminal",
25
+ description: "Keyboard, mouse, clipboard, focus, and terminal capabilities",
26
+ demo: true,
27
+ features: [
28
+ "useInput",
29
+ "useMouse",
30
+ "clipboard",
31
+ "focus",
32
+ "Kitty protocol"
33
+ ]
34
+ };
35
+ const MODIFIER_DEFS = [
36
+ {
37
+ symbol: "⌃",
38
+ label: "Ctrl",
39
+ color: "$color1"
40
+ },
41
+ {
42
+ symbol: "⇧",
43
+ label: "Shift",
44
+ color: "$color3"
45
+ },
46
+ {
47
+ symbol: "⌥",
48
+ label: "Alt",
49
+ color: "$color4"
50
+ },
51
+ {
52
+ symbol: "⌘",
53
+ label: "Super",
54
+ color: "$color2"
55
+ },
56
+ {
57
+ symbol: "✦",
58
+ label: "Hyper",
59
+ color: "$color5"
60
+ }
61
+ ];
62
+ function now() {
63
+ const d = /* @__PURE__ */ new Date();
64
+ return `${d.getHours().toString().padStart(2, "0")}:${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}`;
65
+ }
66
+ function KeysTab({ kittySupported }) {
67
+ const [events, setEvents] = useState([]);
68
+ const [latest, setLatest] = useState(null);
69
+ const counterRef = useRef(0);
70
+ const stdin = process.stdin;
71
+ useEffect(() => {
72
+ const onData = (data) => {
73
+ const raw = data.toString();
74
+ if (raw.startsWith("\x1B[<")) return;
75
+ if (raw.startsWith("\x1B[I") || raw.startsWith("\x1B[O")) return;
76
+ const parsed = parseKeypress(raw);
77
+ if (parsed.name === "escape") return;
78
+ if (raw === "q" && !parsed.ctrl && !parsed.meta) return;
79
+ if (parsed.name === "left" || parsed.name === "right") return;
80
+ if (raw === "h" || raw === "l") return;
81
+ counterRef.current++;
82
+ const key = {
83
+ upArrow: parsed.name === "up",
84
+ downArrow: parsed.name === "down",
85
+ leftArrow: parsed.name === "left",
86
+ rightArrow: parsed.name === "right",
87
+ pageDown: parsed.name === "pagedown",
88
+ pageUp: parsed.name === "pageup",
89
+ home: parsed.name === "home",
90
+ end: parsed.name === "end",
91
+ return: parsed.name === "return",
92
+ escape: parsed.name === "escape",
93
+ ctrl: parsed.ctrl,
94
+ shift: parsed.shift,
95
+ tab: parsed.name === "tab",
96
+ backspace: parsed.name === "backspace",
97
+ delete: parsed.name === "delete",
98
+ meta: parsed.meta || parsed.option,
99
+ super: parsed.super,
100
+ hyper: parsed.hyper,
101
+ capsLock: parsed.capsLock ?? false,
102
+ numLock: parsed.numLock ?? false,
103
+ eventType: parsed.eventType
104
+ };
105
+ const input = parsed.name.length === 1 ? parsed.name : "";
106
+ const event = {
107
+ index: counterRef.current,
108
+ input,
109
+ key,
110
+ parsed,
111
+ raw
112
+ };
113
+ setLatest(event);
114
+ setEvents((prev) => [...prev.slice(-11), event]);
115
+ };
116
+ stdin.on("data", onData);
117
+ return () => {
118
+ stdin.off("data", onData);
119
+ };
120
+ }, [stdin]);
121
+ return /* @__PURE__ */ jsxs(Box, {
122
+ gap: 3,
123
+ paddingX: 1,
124
+ paddingTop: 1,
125
+ children: [/* @__PURE__ */ jsxs(Box, {
126
+ flexDirection: "column",
127
+ width: 46,
128
+ children: [
129
+ /* @__PURE__ */ jsx(H2, { children: "Last Key Pressed" }),
130
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
131
+ latest ? /* @__PURE__ */ jsx(KeyDetails, { event: latest }) : /* @__PURE__ */ jsx(KeyPlaceholder, { kittySupported })
132
+ ]
133
+ }), /* @__PURE__ */ jsxs(Box, {
134
+ flexDirection: "column",
135
+ flexGrow: 1,
136
+ children: [
137
+ /* @__PURE__ */ jsxs(H2, { children: [
138
+ "Event Log",
139
+ " ",
140
+ /* @__PURE__ */ jsxs(Small, { children: [
141
+ "(",
142
+ counterRef.current,
143
+ " ",
144
+ counterRef.current === 1 ? "event" : "events",
145
+ ")"
146
+ ] })
147
+ ] }),
148
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
149
+ events.length === 0 ? /* @__PURE__ */ jsx(Muted, { children: "Waiting for input..." }) : /* @__PURE__ */ jsx(Box, {
150
+ flexDirection: "column",
151
+ overflow: "scroll",
152
+ scrollTo: events.length - 1,
153
+ children: events.map((e, i) => /* @__PURE__ */ jsxs(Text, {
154
+ dimColor: i < events.length - 1,
155
+ children: [
156
+ /* @__PURE__ */ jsxs(Text, {
157
+ color: "$muted",
158
+ children: ["#", String(e.index).padStart(3)]
159
+ }),
160
+ " ",
161
+ formatKeyEventSummary(e)
162
+ ]
163
+ }, e.index))
164
+ })
165
+ ]
166
+ })]
167
+ });
168
+ }
169
+ function KeyPlaceholder({ kittySupported }) {
170
+ return /* @__PURE__ */ jsxs(Box, {
171
+ flexDirection: "column",
172
+ children: [
173
+ /* @__PURE__ */ jsx(Text, { children: "Try pressing some key combinations:" }),
174
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
175
+ /* @__PURE__ */ jsx(Text, { children: " Ctrl+A, Shift+Tab, Alt+Enter..." }),
176
+ kittySupported && /* @__PURE__ */ jsx(Text, { children: " Cmd+S, Hyper+X (Kitty-only)" }),
177
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
178
+ /* @__PURE__ */ jsx(Muted, { children: "Each keypress shows its full breakdown here." })
179
+ ]
180
+ });
181
+ }
182
+ function KeyDetails({ event }) {
183
+ const { parsed, raw } = event;
184
+ const modActive = [
185
+ parsed.ctrl,
186
+ parsed.shift,
187
+ parsed.meta || parsed.option,
188
+ parsed.super,
189
+ parsed.hyper
190
+ ];
191
+ return /* @__PURE__ */ jsxs(Box, {
192
+ flexDirection: "column",
193
+ children: [
194
+ /* @__PURE__ */ jsxs(Text, { children: [
195
+ /* @__PURE__ */ jsx(Text, {
196
+ bold: true,
197
+ children: "Name:"
198
+ }),
199
+ " ",
200
+ /* @__PURE__ */ jsx(Text, {
201
+ bold: true,
202
+ color: "$primary",
203
+ children: parsed.name || "(none)"
204
+ })
205
+ ] }),
206
+ /* @__PURE__ */ jsxs(Text, { children: [
207
+ /* @__PURE__ */ jsx(Text, {
208
+ bold: true,
209
+ children: "Input:"
210
+ }),
211
+ " ",
212
+ JSON.stringify(event.input)
213
+ ] }),
214
+ /* @__PURE__ */ jsx(Box, {
215
+ marginTop: 1,
216
+ gap: 1,
217
+ children: MODIFIER_DEFS.map((mod, i) => /* @__PURE__ */ jsx(ModBadge, {
218
+ mod,
219
+ active: modActive[i]
220
+ }, mod.symbol))
221
+ }),
222
+ parsed.eventType && /* @__PURE__ */ jsx(Box, {
223
+ marginTop: 1,
224
+ children: /* @__PURE__ */ jsxs(Text, { children: [
225
+ /* @__PURE__ */ jsx(Text, {
226
+ bold: true,
227
+ children: "Event type:"
228
+ }),
229
+ " ",
230
+ /* @__PURE__ */ jsx(Text, {
231
+ color: "$accent",
232
+ children: parsed.eventType
233
+ })
234
+ ] })
235
+ }),
236
+ /* @__PURE__ */ jsxs(Box, {
237
+ flexDirection: "column",
238
+ marginTop: 1,
239
+ children: [
240
+ /* @__PURE__ */ jsx(Text, {
241
+ bold: true,
242
+ color: "$muted",
243
+ children: "Kitty Extensions"
244
+ }),
245
+ /* @__PURE__ */ jsx(KittyField, {
246
+ label: "shiftedKey",
247
+ value: parsed.shiftedKey
248
+ }),
249
+ /* @__PURE__ */ jsx(KittyField, {
250
+ label: "baseLayoutKey",
251
+ value: parsed.baseLayoutKey
252
+ }),
253
+ /* @__PURE__ */ jsx(KittyField, {
254
+ label: "associatedText",
255
+ value: parsed.associatedText
256
+ }),
257
+ /* @__PURE__ */ jsx(KittyField, {
258
+ label: "capsLock",
259
+ value: parsed.capsLock
260
+ }),
261
+ /* @__PURE__ */ jsx(KittyField, {
262
+ label: "numLock",
263
+ value: parsed.numLock
264
+ })
265
+ ]
266
+ }),
267
+ /* @__PURE__ */ jsx(Box, {
268
+ marginTop: 1,
269
+ children: /* @__PURE__ */ jsxs(Text, { children: [
270
+ /* @__PURE__ */ jsx(Text, {
271
+ bold: true,
272
+ children: "Raw:"
273
+ }),
274
+ " ",
275
+ /* @__PURE__ */ jsx(Muted, { children: [...raw].map((c) => c.charCodeAt(0) < 32 || c.charCodeAt(0) === 127 ? `\\x${c.charCodeAt(0).toString(16).padStart(2, "0")}` : c).join("") })
276
+ ] })
277
+ })
278
+ ]
279
+ });
280
+ }
281
+ function ModBadge({ mod, active }) {
282
+ if (active) return /* @__PURE__ */ jsx(Text, {
283
+ backgroundColor: mod.color,
284
+ color: "$inversebg",
285
+ bold: true,
286
+ children: ` ${mod.symbol} ${mod.label} `
287
+ });
288
+ return /* @__PURE__ */ jsx(Text, {
289
+ color: "$muted",
290
+ children: ` ${mod.symbol} `
291
+ });
292
+ }
293
+ function KittyField({ label, value }) {
294
+ if (value === void 0) return /* @__PURE__ */ jsxs(Muted, { children: [
295
+ label,
296
+ ": ",
297
+ "--"
298
+ ] });
299
+ return /* @__PURE__ */ jsxs(Text, { children: [
300
+ label,
301
+ ": ",
302
+ /* @__PURE__ */ jsx(Text, {
303
+ color: "$warning",
304
+ children: String(value)
305
+ })
306
+ ] });
307
+ }
308
+ function formatKeyEventSummary(event) {
309
+ const parts = [];
310
+ const { parsed } = event;
311
+ if (parsed.ctrl) parts.push("⌃");
312
+ if (parsed.shift) parts.push("⇧");
313
+ if (parsed.meta || parsed.option) parts.push("⌥");
314
+ if (parsed.super) parts.push("⌘");
315
+ if (parsed.hyper) parts.push("✦");
316
+ parts.push(parsed.name || JSON.stringify(event.input));
317
+ if (parsed.eventType) parts.push(` (${parsed.eventType})`);
318
+ return parts.join("");
319
+ }
320
+ function MouseTab() {
321
+ const [mousePos, setMousePos] = useState(null);
322
+ const [events, setEvents] = useState([]);
323
+ const [clicks, setClicks] = useState({
324
+ left: 0,
325
+ middle: 0,
326
+ right: 0
327
+ });
328
+ const [scrollTotal, setScrollTotal] = useState(0);
329
+ const counterRef = useRef(0);
330
+ const stdin = process.stdin;
331
+ useEffect(() => {
332
+ const onData = (data) => {
333
+ const raw = data.toString();
334
+ if (!isMouseSequence(raw)) return;
335
+ const parsed = parseMouseSequence(raw);
336
+ if (!parsed) return;
337
+ setMousePos({
338
+ x: parsed.x,
339
+ y: parsed.y
340
+ });
341
+ const mods = [];
342
+ if (parsed.ctrl) mods.push("Ctrl");
343
+ if (parsed.shift) mods.push("Shift");
344
+ if (parsed.meta) mods.push("Alt");
345
+ const modStr = mods.join("+");
346
+ if (parsed.action === "down") {
347
+ const btn = [
348
+ "Left",
349
+ "Middle",
350
+ "Right"
351
+ ][parsed.button] ?? `Btn${parsed.button}`;
352
+ counterRef.current++;
353
+ setEvents((prev) => [...prev.slice(-11), {
354
+ index: counterRef.current,
355
+ action: "click",
356
+ button: btn,
357
+ x: parsed.x,
358
+ y: parsed.y,
359
+ mods: modStr,
360
+ timestamp: now()
361
+ }]);
362
+ if (parsed.button === 0) setClicks((c) => ({
363
+ ...c,
364
+ left: c.left + 1
365
+ }));
366
+ else if (parsed.button === 1) setClicks((c) => ({
367
+ ...c,
368
+ middle: c.middle + 1
369
+ }));
370
+ else if (parsed.button === 2) setClicks((c) => ({
371
+ ...c,
372
+ right: c.right + 1
373
+ }));
374
+ } else if (parsed.action === "wheel") {
375
+ counterRef.current++;
376
+ const dir = parsed.delta < 0 ? "up" : "down";
377
+ setEvents((prev) => [...prev.slice(-11), {
378
+ index: counterRef.current,
379
+ action: `scroll ${dir}`,
380
+ button: "wheel",
381
+ x: parsed.x,
382
+ y: parsed.y,
383
+ mods: modStr,
384
+ timestamp: now()
385
+ }]);
386
+ setScrollTotal((s) => s + 1);
387
+ } else if (parsed.action === "move") {}
388
+ };
389
+ stdin.on("data", onData);
390
+ return () => {
391
+ stdin.off("data", onData);
392
+ };
393
+ }, [stdin]);
394
+ return /* @__PURE__ */ jsxs(Box, {
395
+ gap: 3,
396
+ paddingX: 1,
397
+ paddingTop: 1,
398
+ children: [/* @__PURE__ */ jsxs(Box, {
399
+ flexDirection: "column",
400
+ width: 36,
401
+ children: [
402
+ /* @__PURE__ */ jsx(H2, { children: "Position" }),
403
+ /* @__PURE__ */ jsx(Box, {
404
+ marginTop: 1,
405
+ children: mousePos ? /* @__PURE__ */ jsxs(Box, {
406
+ flexDirection: "column",
407
+ children: [/* @__PURE__ */ jsxs(Text, { children: [
408
+ /* @__PURE__ */ jsx(Text, {
409
+ bold: true,
410
+ children: "X:"
411
+ }),
412
+ " ",
413
+ /* @__PURE__ */ jsx(Text, {
414
+ color: "$primary",
415
+ bold: true,
416
+ children: String(mousePos.x).padStart(4)
417
+ })
418
+ ] }), /* @__PURE__ */ jsxs(Text, { children: [
419
+ /* @__PURE__ */ jsx(Text, {
420
+ bold: true,
421
+ children: "Y:"
422
+ }),
423
+ " ",
424
+ /* @__PURE__ */ jsx(Text, {
425
+ color: "$primary",
426
+ bold: true,
427
+ children: String(mousePos.y).padStart(4)
428
+ })
429
+ ] })]
430
+ }) : /* @__PURE__ */ jsx(Muted, { children: "Move mouse to track position" })
431
+ }),
432
+ /* @__PURE__ */ jsxs(Box, {
433
+ marginTop: 1,
434
+ flexDirection: "column",
435
+ children: [/* @__PURE__ */ jsx(H2, { children: "Click Counts" }), /* @__PURE__ */ jsxs(Box, {
436
+ marginTop: 1,
437
+ flexDirection: "column",
438
+ children: [
439
+ /* @__PURE__ */ jsxs(Text, { children: [
440
+ /* @__PURE__ */ jsx(Text, {
441
+ bold: true,
442
+ children: "Left:"
443
+ }),
444
+ " ",
445
+ /* @__PURE__ */ jsx(Text, {
446
+ color: "$info",
447
+ children: clicks.left
448
+ })
449
+ ] }),
450
+ /* @__PURE__ */ jsxs(Text, { children: [
451
+ /* @__PURE__ */ jsx(Text, {
452
+ bold: true,
453
+ children: "Middle:"
454
+ }),
455
+ " ",
456
+ /* @__PURE__ */ jsx(Text, {
457
+ color: "$info",
458
+ children: clicks.middle
459
+ })
460
+ ] }),
461
+ /* @__PURE__ */ jsxs(Text, { children: [
462
+ /* @__PURE__ */ jsx(Text, {
463
+ bold: true,
464
+ children: "Right:"
465
+ }),
466
+ " ",
467
+ /* @__PURE__ */ jsx(Text, {
468
+ color: "$info",
469
+ children: clicks.right
470
+ })
471
+ ] }),
472
+ /* @__PURE__ */ jsxs(Text, { children: [
473
+ /* @__PURE__ */ jsx(Text, {
474
+ bold: true,
475
+ children: "Scroll:"
476
+ }),
477
+ " ",
478
+ /* @__PURE__ */ jsx(Text, {
479
+ color: "$info",
480
+ children: scrollTotal
481
+ })
482
+ ] })
483
+ ]
484
+ })]
485
+ })
486
+ ]
487
+ }), /* @__PURE__ */ jsxs(Box, {
488
+ flexDirection: "column",
489
+ flexGrow: 1,
490
+ children: [
491
+ /* @__PURE__ */ jsxs(H2, { children: ["Mouse Events ", /* @__PURE__ */ jsxs(Small, { children: [
492
+ "(",
493
+ counterRef.current,
494
+ ")"
495
+ ] })] }),
496
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
497
+ events.length === 0 ? /* @__PURE__ */ jsx(Muted, { children: "Click or scroll to see events..." }) : /* @__PURE__ */ jsx(Box, {
498
+ flexDirection: "column",
499
+ overflow: "scroll",
500
+ scrollTo: events.length - 1,
501
+ children: events.map((e, i) => /* @__PURE__ */ jsxs(Text, {
502
+ dimColor: i < events.length - 1,
503
+ children: [
504
+ /* @__PURE__ */ jsx(Small, { children: e.timestamp }),
505
+ " ",
506
+ /* @__PURE__ */ jsx(Text, {
507
+ color: e.action.startsWith("scroll") ? "$accent" : "$primary",
508
+ bold: true,
509
+ children: e.action
510
+ }),
511
+ " ",
512
+ e.button !== "wheel" && /* @__PURE__ */ jsxs(Text, { children: [e.button, " "] }),
513
+ /* @__PURE__ */ jsxs(Muted, { children: [
514
+ "(",
515
+ e.x,
516
+ ",",
517
+ e.y,
518
+ ")"
519
+ ] }),
520
+ e.mods ? /* @__PURE__ */ jsxs(Text, {
521
+ color: "$warning",
522
+ children: [" +", e.mods]
523
+ }) : null
524
+ ]
525
+ }, e.index))
526
+ })
527
+ ]
528
+ })]
529
+ });
530
+ }
531
+ function ClipboardTab() {
532
+ const { stdout } = useStdout();
533
+ const [selectedIndex, setSelectedIndex] = useState(0);
534
+ const [lastCopied, setLastCopied] = useState(null);
535
+ const [lastPasted, setLastPasted] = useState(null);
536
+ const [history, setHistory] = useState([]);
537
+ const snippets = [
538
+ "Hello, world!",
539
+ "The quick brown fox jumps over the lazy dog",
540
+ "OSC 52 clipboard protocol",
541
+ "npx silvery examples",
542
+ "console.log('silvery')",
543
+ "https://silvery.dev"
544
+ ];
545
+ useInput((input, key) => {
546
+ if (key.upArrow || input === "k") setSelectedIndex((i) => Math.max(0, i - 1));
547
+ if (key.downArrow || input === "j") setSelectedIndex((i) => Math.min(snippets.length - 1, i + 1));
548
+ if (input === "c") {
549
+ const text = snippets[selectedIndex];
550
+ copyToClipboard(stdout, text);
551
+ setLastCopied(text);
552
+ setHistory((h) => [...h.slice(-7), {
553
+ action: "copy",
554
+ text,
555
+ time: now()
556
+ }]);
557
+ }
558
+ if (input === "v") {
559
+ requestClipboard(stdout);
560
+ setHistory((h) => [...h.slice(-7), {
561
+ action: "request",
562
+ text: "(paste requested)",
563
+ time: now()
564
+ }]);
565
+ }
566
+ const parsed = parseClipboardResponse(input);
567
+ if (parsed) {
568
+ setLastPasted(parsed);
569
+ setHistory((h) => [...h.slice(-7), {
570
+ action: "paste",
571
+ text: parsed,
572
+ time: now()
573
+ }]);
574
+ }
575
+ });
576
+ return /* @__PURE__ */ jsxs(Box, {
577
+ flexDirection: "column",
578
+ paddingX: 1,
579
+ paddingTop: 1,
580
+ gap: 1,
581
+ children: [
582
+ /* @__PURE__ */ jsxs(Box, {
583
+ flexDirection: "column",
584
+ children: [/* @__PURE__ */ jsxs(H2, { children: [
585
+ "Snippets",
586
+ " ",
587
+ /* @__PURE__ */ jsxs(Small, { children: [
588
+ selectedIndex + 1,
589
+ "/",
590
+ snippets.length
591
+ ] })
592
+ ] }), /* @__PURE__ */ jsx(Box, {
593
+ flexDirection: "column",
594
+ marginTop: 1,
595
+ overflow: "scroll",
596
+ scrollTo: selectedIndex,
597
+ children: snippets.map((text, i) => /* @__PURE__ */ jsx(Box, {
598
+ paddingX: 1,
599
+ children: /* @__PURE__ */ jsxs(Text, {
600
+ color: i === selectedIndex ? "$bg" : void 0,
601
+ backgroundColor: i === selectedIndex ? "$primary" : void 0,
602
+ bold: i === selectedIndex,
603
+ children: [i === selectedIndex ? " > " : " ", text]
604
+ })
605
+ }, i))
606
+ })]
607
+ }),
608
+ /* @__PURE__ */ jsxs(Box, {
609
+ gap: 4,
610
+ children: [/* @__PURE__ */ jsxs(Box, {
611
+ flexDirection: "column",
612
+ children: [/* @__PURE__ */ jsx(Text, {
613
+ bold: true,
614
+ children: "Last Copied:"
615
+ }), lastCopied ? /* @__PURE__ */ jsxs(Text, {
616
+ color: "$success",
617
+ children: ["✓ ", lastCopied]
618
+ }) : /* @__PURE__ */ jsx(Muted, { children: "nothing" })]
619
+ }), /* @__PURE__ */ jsxs(Box, {
620
+ flexDirection: "column",
621
+ children: [/* @__PURE__ */ jsx(Text, {
622
+ bold: true,
623
+ children: "Last Pasted:"
624
+ }), lastPasted ? /* @__PURE__ */ jsx(Text, {
625
+ color: "$warning",
626
+ children: lastPasted
627
+ }) : /* @__PURE__ */ jsx(Muted, { children: "nothing" })]
628
+ })]
629
+ }),
630
+ history.length > 0 && /* @__PURE__ */ jsxs(Box, {
631
+ flexDirection: "column",
632
+ children: [/* @__PURE__ */ jsx(H2, { children: "History" }), /* @__PURE__ */ jsx(Box, {
633
+ flexDirection: "column",
634
+ overflow: "scroll",
635
+ scrollTo: history.length - 1,
636
+ children: history.map((h, i) => /* @__PURE__ */ jsxs(Text, {
637
+ dimColor: i < history.length - 1,
638
+ children: [
639
+ /* @__PURE__ */ jsx(Small, { children: h.time }),
640
+ " ",
641
+ /* @__PURE__ */ jsx(Text, {
642
+ color: h.action === "copy" ? "$success" : h.action === "paste" ? "$warning" : "$muted",
643
+ bold: true,
644
+ children: h.action
645
+ }),
646
+ " ",
647
+ /* @__PURE__ */ jsx(Text, { children: h.text.length > 40 ? h.text.slice(0, 37) + "..." : h.text })
648
+ ]
649
+ }, i))
650
+ })]
651
+ }),
652
+ /* @__PURE__ */ jsxs(Muted, { children: [
653
+ /* @__PURE__ */ jsx(Kbd, { children: "j/k" }),
654
+ " navigate ",
655
+ /* @__PURE__ */ jsx(Kbd, { children: "c" }),
656
+ " copy ",
657
+ /* @__PURE__ */ jsx(Kbd, { children: "v" }),
658
+ " paste (OSC 52)"
659
+ ] })
660
+ ]
661
+ });
662
+ }
663
+ function FocusTab() {
664
+ const [focused, setFocused] = useState(true);
665
+ const [events, setEvents] = useState([]);
666
+ const counterRef = useRef(0);
667
+ const stdin = process.stdin;
668
+ useEffect(() => {
669
+ const onData = (data) => {
670
+ const focusEvt = parseFocusEvent(data.toString());
671
+ if (!focusEvt) return;
672
+ const isFocused = focusEvt.type === "focus-in";
673
+ setFocused(isFocused);
674
+ counterRef.current++;
675
+ setEvents((prev) => [...prev.slice(-14), {
676
+ index: counterRef.current,
677
+ focused: isFocused,
678
+ timestamp: now()
679
+ }]);
680
+ };
681
+ stdin.on("data", onData);
682
+ return () => {
683
+ stdin.off("data", onData);
684
+ };
685
+ }, [stdin]);
686
+ return /* @__PURE__ */ jsxs(Box, {
687
+ gap: 3,
688
+ paddingX: 1,
689
+ paddingTop: 1,
690
+ children: [/* @__PURE__ */ jsxs(Box, {
691
+ flexDirection: "column",
692
+ width: 36,
693
+ children: [
694
+ /* @__PURE__ */ jsx(H2, { children: "Terminal Focus" }),
695
+ /* @__PURE__ */ jsxs(Box, {
696
+ marginTop: 1,
697
+ flexDirection: "column",
698
+ alignItems: "center",
699
+ gap: 1,
700
+ children: [/* @__PURE__ */ jsx(Text, {
701
+ bold: true,
702
+ color: focused ? "$success" : "$error",
703
+ children: focused ? " FOCUSED " : " UNFOCUSED "
704
+ }), /* @__PURE__ */ jsx(Text, {
705
+ color: focused ? "$success" : "$error",
706
+ children: focused ? "Terminal window is active" : "Terminal window lost focus"
707
+ })]
708
+ }),
709
+ /* @__PURE__ */ jsx(Box, {
710
+ marginTop: 2,
711
+ flexDirection: "column",
712
+ children: /* @__PURE__ */ jsx(Muted, { children: "Switch to another window and back to see focus events. Uses CSI I/O terminal focus reporting protocol." })
713
+ }),
714
+ /* @__PURE__ */ jsx(Box, {
715
+ marginTop: 1,
716
+ children: /* @__PURE__ */ jsxs(Text, { children: [
717
+ /* @__PURE__ */ jsx(Text, {
718
+ bold: true,
719
+ children: "Protocol:"
720
+ }),
721
+ " ",
722
+ /* @__PURE__ */ jsx(Text, {
723
+ color: "$info",
724
+ children: "CSI ?1004h (DECRPM focus events)"
725
+ })
726
+ ] })
727
+ })
728
+ ]
729
+ }), /* @__PURE__ */ jsxs(Box, {
730
+ flexDirection: "column",
731
+ flexGrow: 1,
732
+ children: [
733
+ /* @__PURE__ */ jsxs(H2, { children: ["Focus Events ", /* @__PURE__ */ jsxs(Small, { children: [
734
+ "(",
735
+ counterRef.current,
736
+ ")"
737
+ ] })] }),
738
+ /* @__PURE__ */ jsx(Box, { height: 1 }),
739
+ events.length === 0 ? /* @__PURE__ */ jsx(Muted, { children: "Switch windows to generate focus events..." }) : /* @__PURE__ */ jsx(Box, {
740
+ flexDirection: "column",
741
+ overflow: "scroll",
742
+ scrollTo: events.length - 1,
743
+ children: events.map((e, i) => /* @__PURE__ */ jsxs(Text, {
744
+ dimColor: i < events.length - 1,
745
+ children: [
746
+ /* @__PURE__ */ jsx(Small, { children: e.timestamp }),
747
+ " ",
748
+ /* @__PURE__ */ jsx(Text, {
749
+ color: e.focused ? "$success" : "$error",
750
+ bold: true,
751
+ children: e.focused ? "focus-in " : "focus-out"
752
+ }),
753
+ " ",
754
+ /* @__PURE__ */ jsx(Text, {
755
+ color: e.focused ? "$success" : "$error",
756
+ children: e.focused ? "Terminal gained focus" : "Terminal lost focus"
757
+ })
758
+ ]
759
+ }, e.index))
760
+ })
761
+ ]
762
+ })]
763
+ });
764
+ }
765
+ function TerminalDemo({ kittySupported }) {
766
+ const { exit } = useApp();
767
+ useInput((input, key) => {
768
+ if (input === "q" || key.escape) exit();
769
+ });
770
+ return /* @__PURE__ */ jsxs(Box, {
771
+ flexDirection: "column",
772
+ flexGrow: 1,
773
+ children: [
774
+ /* @__PURE__ */ jsx(Box, {
775
+ paddingX: 1,
776
+ gap: 2,
777
+ children: /* @__PURE__ */ jsxs(Text, { children: [
778
+ /* @__PURE__ */ jsx(Text, {
779
+ bold: true,
780
+ children: "Kitty:"
781
+ }),
782
+ " ",
783
+ kittySupported ? /* @__PURE__ */ jsx(Text, {
784
+ color: "$success",
785
+ children: "enabled"
786
+ }) : /* @__PURE__ */ jsx(Text, {
787
+ color: "$warning",
788
+ children: "legacy mode"
789
+ })
790
+ ] })
791
+ }),
792
+ /* @__PURE__ */ jsxs(Tabs, {
793
+ defaultValue: "keys",
794
+ children: [
795
+ /* @__PURE__ */ jsxs(TabList, { children: [
796
+ /* @__PURE__ */ jsx(Tab, {
797
+ value: "keys",
798
+ children: "Keys"
799
+ }),
800
+ /* @__PURE__ */ jsx(Tab, {
801
+ value: "mouse",
802
+ children: "Mouse"
803
+ }),
804
+ /* @__PURE__ */ jsx(Tab, {
805
+ value: "clipboard",
806
+ children: "Clipboard"
807
+ }),
808
+ /* @__PURE__ */ jsx(Tab, {
809
+ value: "focus",
810
+ children: "Focus"
811
+ })
812
+ ] }),
813
+ /* @__PURE__ */ jsx(TabPanel, {
814
+ value: "keys",
815
+ children: /* @__PURE__ */ jsx(KeysTab, { kittySupported })
816
+ }),
817
+ /* @__PURE__ */ jsx(TabPanel, {
818
+ value: "mouse",
819
+ children: /* @__PURE__ */ jsx(MouseTab, {})
820
+ }),
821
+ /* @__PURE__ */ jsx(TabPanel, {
822
+ value: "clipboard",
823
+ children: /* @__PURE__ */ jsx(ClipboardTab, {})
824
+ }),
825
+ /* @__PURE__ */ jsx(TabPanel, {
826
+ value: "focus",
827
+ children: /* @__PURE__ */ jsx(FocusTab, {})
828
+ })
829
+ ]
830
+ }),
831
+ /* @__PURE__ */ jsx(Box, {
832
+ paddingX: 1,
833
+ children: /* @__PURE__ */ jsxs(Muted, { children: [
834
+ /* @__PURE__ */ jsx(Kbd, { children: "h/l" }),
835
+ " switch tabs ",
836
+ /* @__PURE__ */ jsx(Kbd, { children: "Esc/q" }),
837
+ " quit"
838
+ ] })
839
+ })
840
+ ]
841
+ });
842
+ }
843
+ async function main() {
844
+ try {
845
+ var _usingCtx$1 = _usingCtx();
846
+ const kittyResult = await detectKittyFromStdio(process.stdout, process.stdin);
847
+ if (kittyResult.supported) {
848
+ const flags = KittyFlags.DISAMBIGUATE | KittyFlags.REPORT_EVENTS | KittyFlags.REPORT_ALTERNATE | KittyFlags.REPORT_ALL_KEYS | KittyFlags.REPORT_TEXT;
849
+ process.stdout.write(enableKittyKeyboard(flags));
850
+ }
851
+ const term = _usingCtx$1.u(createTerm());
852
+ process.stdout.write(enableMouse());
853
+ enableFocusReporting((s) => process.stdout.write(s));
854
+ const { waitUntilExit } = await render(/* @__PURE__ */ jsx(ExampleBanner, {
855
+ meta,
856
+ controls: "h/l tabs Esc/q quit",
857
+ children: /* @__PURE__ */ jsx(TerminalDemo, { kittySupported: kittyResult.supported })
858
+ }), term);
859
+ await waitUntilExit();
860
+ process.stdout.write(disableMouse());
861
+ disableFocusReporting((s) => process.stdout.write(s));
862
+ if (kittyResult.supported) process.stdout.write(disableKittyKeyboard());
863
+ } catch (_) {
864
+ _usingCtx$1.e = _;
865
+ } finally {
866
+ _usingCtx$1.d();
867
+ }
868
+ }
869
+ if (import.meta.main) await main();
870
+ //#endregion
871
+ export { TerminalDemo, main, meta };