@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
@@ -0,0 +1,115 @@
1
+ import { D as TerminalBuffer, N as init_buffer, i as outputPhase, r as createOutputPhase } from "../ansi-CCE2pVS0.mjs";
2
+ //#region apps/inline-bench.tsx
3
+ init_buffer();
4
+ const RUNS = 500;
5
+ function fillBuffer(buf, rows, prefix = "") {
6
+ for (let y = 0; y < rows; y++) {
7
+ const text = `${prefix}Item ${y}: Content line with some styling and longer text here`;
8
+ for (let x = 0; x < Math.min(text.length, buf.width); x++) buf.setCell(x, y, { char: text[x] });
9
+ }
10
+ }
11
+ function benchmarkOutputPhase(name, width, height, contentRows, changedCells, forceFullRender) {
12
+ const timings = [];
13
+ const bytes = [];
14
+ for (let i = 0; i < RUNS; i++) {
15
+ const prev = new TerminalBuffer(width, height);
16
+ fillBuffer(prev, contentRows);
17
+ const next = new TerminalBuffer(width, height);
18
+ fillBuffer(next, contentRows);
19
+ for (let c = 0; c < changedCells; c++) {
20
+ const row = Math.floor(c / Math.max(changedCells, 1) * contentRows);
21
+ const col = c % Math.min(10, width);
22
+ next.setCell(col, row, { char: "X" });
23
+ }
24
+ if (forceFullRender) {
25
+ outputPhase(null, prev, "inline", 0, height);
26
+ const t0 = performance.now();
27
+ const output = outputPhase(prev, next, "inline", 0, height);
28
+ const t1 = performance.now();
29
+ timings.push(t1 - t0);
30
+ bytes.push(output.length);
31
+ } else {
32
+ const render = createOutputPhase({});
33
+ render(null, prev, "inline", 0, height);
34
+ const t0 = performance.now();
35
+ const output = render(prev, next, "inline", 0, height);
36
+ const t1 = performance.now();
37
+ timings.push(t1 - t0);
38
+ bytes.push(output.length);
39
+ }
40
+ }
41
+ timings.sort((a, b) => a - b);
42
+ bytes.sort((a, b) => a - b);
43
+ return {
44
+ name,
45
+ timings,
46
+ bytes
47
+ };
48
+ }
49
+ function printResult(r) {
50
+ const p50t = r.timings[Math.floor(r.timings.length * .5)];
51
+ const p95t = r.timings[Math.floor(r.timings.length * .95)];
52
+ const p50b = r.bytes[Math.floor(r.bytes.length * .5)];
53
+ const avgB = r.bytes.reduce((a, b) => a + b, 0) / r.bytes.length;
54
+ console.log(` ${r.name.padEnd(40)} p50=${p50t.toFixed(3).padStart(7)}ms p95=${p95t.toFixed(3).padStart(7)}ms bytes=${Math.round(p50b).toString().padStart(6)} (avg ${Math.round(avgB)})`);
55
+ }
56
+ function printComparison(full, incr) {
57
+ const fullP50b = full.bytes[Math.floor(full.bytes.length * .5)];
58
+ const incrP50b = incr.bytes[Math.floor(incr.bytes.length * .5)];
59
+ const fullP50t = full.timings[Math.floor(full.timings.length * .5)];
60
+ const incrP50t = incr.timings[Math.floor(incr.timings.length * .5)];
61
+ const byteRatio = fullP50b / Math.max(incrP50b, 1);
62
+ const timeRatio = fullP50t / Math.max(incrP50t, .001);
63
+ console.log(` ${"→ savings".padEnd(40)} time=${timeRatio.toFixed(1)}x faster bytes=${byteRatio.toFixed(0)}x fewer (${fullP50b} → ${incrP50b})`);
64
+ }
65
+ async function main() {
66
+ console.log(`\n═══ Inline Output Phase: Full vs Incremental (${RUNS} runs) ═══\n`);
67
+ for (const cfg of [
68
+ {
69
+ label: "10 rows, 1 change",
70
+ w: 80,
71
+ h: 20,
72
+ rows: 10,
73
+ changes: 1
74
+ },
75
+ {
76
+ label: "30 rows, 1 change",
77
+ w: 120,
78
+ h: 40,
79
+ rows: 30,
80
+ changes: 1
81
+ },
82
+ {
83
+ label: "50 rows, 1 change",
84
+ w: 120,
85
+ h: 60,
86
+ rows: 50,
87
+ changes: 1
88
+ },
89
+ {
90
+ label: "50 rows, 3 changes",
91
+ w: 120,
92
+ h: 60,
93
+ rows: 50,
94
+ changes: 3
95
+ },
96
+ {
97
+ label: "50 rows, 10 changes",
98
+ w: 120,
99
+ h: 60,
100
+ rows: 50,
101
+ changes: 10
102
+ }
103
+ ]) {
104
+ console.log(`--- ${cfg.label} ---`);
105
+ const full = benchmarkOutputPhase(`full render`, cfg.w, cfg.h, cfg.rows, cfg.changes, true);
106
+ const incr = benchmarkOutputPhase(`incremental`, cfg.w, cfg.h, cfg.rows, cfg.changes, false);
107
+ printResult(full);
108
+ printResult(incr);
109
+ printComparison(full, incr);
110
+ console.log();
111
+ }
112
+ }
113
+ if (import.meta.main) await main();
114
+ //#endregion
115
+ export { main };
@@ -0,0 +1,280 @@
1
+ import { t as _usingCtx } from "../usingCtx-CsEf0xO3.mjs";
2
+ import { t as require_jsx_runtime } from "../jsx-runtime-dMs_8fNu.mjs";
3
+ import { t as ExampleBanner } from "../_banner-DLPxCqVy.mjs";
4
+ import { useState } from "react";
5
+ import { Box, Text, createTerm, render, useApp, useInput } from "silvery";
6
+ //#region apps/kanban.tsx
7
+ /**
8
+ * Kanban Board Example
9
+ *
10
+ * A 3-column kanban board demonstrating:
11
+ * - Todo, In Progress, Done columns
12
+ * - Move items between columns with arrow keys
13
+ * - Each column uses native overflow="scroll" for scrolling
14
+ * - Flexbox layout for proportional sizing
15
+ */
16
+ var import_jsx_runtime = require_jsx_runtime();
17
+ const meta = {
18
+ name: "Kanban Board",
19
+ description: "3-column kanban with card movement and independent scroll",
20
+ demo: true,
21
+ features: [
22
+ "Box flexDirection",
23
+ "useInput",
24
+ "backgroundColor",
25
+ "multi-column layout"
26
+ ]
27
+ };
28
+ const initialColumns = [
29
+ {
30
+ id: "todo",
31
+ title: "To Do",
32
+ cards: [
33
+ {
34
+ id: 1,
35
+ title: "Design new landing page",
36
+ tags: ["design"]
37
+ },
38
+ {
39
+ id: 2,
40
+ title: "Write API documentation",
41
+ tags: ["docs"]
42
+ },
43
+ {
44
+ id: 3,
45
+ title: "Set up monitoring",
46
+ tags: ["devops"]
47
+ },
48
+ {
49
+ id: 4,
50
+ title: "Create onboarding flow",
51
+ tags: ["ux"]
52
+ },
53
+ {
54
+ id: 5,
55
+ title: "Database optimization",
56
+ tags: ["backend"]
57
+ },
58
+ {
59
+ id: 6,
60
+ title: "Mobile responsive fixes",
61
+ tags: ["frontend"]
62
+ },
63
+ {
64
+ id: 7,
65
+ title: "Add dark mode",
66
+ tags: ["frontend", "ux"]
67
+ },
68
+ {
69
+ id: 8,
70
+ title: "Implement caching",
71
+ tags: ["backend"]
72
+ }
73
+ ]
74
+ },
75
+ {
76
+ id: "inProgress",
77
+ title: "In Progress",
78
+ cards: [
79
+ {
80
+ id: 9,
81
+ title: "User authentication",
82
+ tags: ["backend", "security"]
83
+ },
84
+ {
85
+ id: 10,
86
+ title: "Dashboard redesign",
87
+ tags: ["frontend", "design"]
88
+ },
89
+ {
90
+ id: 11,
91
+ title: "API rate limiting",
92
+ tags: ["backend"]
93
+ }
94
+ ]
95
+ },
96
+ {
97
+ id: "done",
98
+ title: "Done",
99
+ cards: [
100
+ {
101
+ id: 12,
102
+ title: "Project setup",
103
+ tags: ["devops"]
104
+ },
105
+ {
106
+ id: 13,
107
+ title: "CI/CD pipeline",
108
+ tags: ["devops"]
109
+ },
110
+ {
111
+ id: 14,
112
+ title: "Initial wireframes",
113
+ tags: ["design"]
114
+ },
115
+ {
116
+ id: 15,
117
+ title: "Database schema",
118
+ tags: ["backend"]
119
+ }
120
+ ]
121
+ }
122
+ ];
123
+ const tagColors = {
124
+ frontend: "$info",
125
+ backend: "$accent",
126
+ design: "$warning",
127
+ devops: "$success",
128
+ docs: "$primary",
129
+ ux: "$muted",
130
+ security: "$error"
131
+ };
132
+ function Tag({ name }) {
133
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
134
+ color: tagColors[name] ?? "$muted",
135
+ dim: true,
136
+ children: ["#", name]
137
+ });
138
+ }
139
+ function CardComponent({ card, isSelected }) {
140
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
141
+ flexDirection: "column",
142
+ borderStyle: "round",
143
+ borderColor: isSelected ? "$primary" : "$border",
144
+ children: [isSelected ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
145
+ backgroundColor: "$primary",
146
+ paddingX: 1,
147
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
148
+ color: "$primary-fg",
149
+ bold: true,
150
+ wrap: "truncate",
151
+ children: card.title
152
+ })
153
+ }) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
154
+ paddingX: 1,
155
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
156
+ wrap: "truncate",
157
+ children: card.title
158
+ })
159
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
160
+ gap: 1,
161
+ paddingX: 1,
162
+ children: card.tags.map((tag) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { name: tag }, tag))
163
+ })]
164
+ });
165
+ }
166
+ function ColumnComponent({ column, isSelected, selectedCardIndex }) {
167
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
168
+ flexDirection: "column",
169
+ flexGrow: 1,
170
+ flexBasis: 0,
171
+ borderStyle: "single",
172
+ borderColor: isSelected ? "$primary" : "$border",
173
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
174
+ backgroundColor: isSelected ? "$primary" : void 0,
175
+ paddingX: 1,
176
+ children: [/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
177
+ bold: true,
178
+ color: isSelected ? "$primary-fg" : "$text",
179
+ children: column.title
180
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
181
+ color: isSelected ? "$primary-fg" : "$muted",
182
+ children: [
183
+ " (",
184
+ column.cards.length,
185
+ ")"
186
+ ]
187
+ })]
188
+ }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
189
+ flexDirection: "column",
190
+ paddingX: 1,
191
+ overflow: "scroll",
192
+ scrollTo: isSelected ? selectedCardIndex : void 0,
193
+ flexGrow: 1,
194
+ children: [column.cards.map((card, cardIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CardComponent, {
195
+ card,
196
+ isSelected: isSelected && cardIndex === selectedCardIndex
197
+ }, card.id)), column.cards.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
198
+ dim: true,
199
+ italic: true,
200
+ children: "No cards"
201
+ })]
202
+ })]
203
+ });
204
+ }
205
+ function KanbanBoard() {
206
+ const { exit } = useApp();
207
+ const [columns, setColumns] = useState(initialColumns);
208
+ const [selectedColumn, setSelectedColumn] = useState(0);
209
+ const [selectedCard, setSelectedCard] = useState(0);
210
+ const currentColumnCards = columns[selectedColumn]?.cards ?? [];
211
+ const boundedSelectedCard = Math.min(selectedCard, Math.max(0, currentColumnCards.length - 1));
212
+ useInput((input, key) => {
213
+ if (input === "q" || key.escape) exit();
214
+ if (key.leftArrow || input === "h") {
215
+ setSelectedColumn((prev) => Math.max(0, prev - 1));
216
+ setSelectedCard(0);
217
+ }
218
+ if (key.rightArrow || input === "l") {
219
+ setSelectedColumn((prev) => Math.min(columns.length - 1, prev + 1));
220
+ setSelectedCard(0);
221
+ }
222
+ if (key.upArrow || input === "k") setSelectedCard((prev) => Math.max(0, prev - 1));
223
+ if (key.downArrow || input === "j") setSelectedCard((prev) => Math.min(currentColumnCards.length - 1, prev + 1));
224
+ if (input === "<" || input === ",") moveCard(-1);
225
+ if (input === ">" || input === ".") moveCard(1);
226
+ });
227
+ function moveCard(direction) {
228
+ const targetColumnIndex = selectedColumn + direction;
229
+ if (targetColumnIndex < 0 || targetColumnIndex >= columns.length) return;
230
+ if (currentColumnCards.length === 0) return;
231
+ const cardToMove = currentColumnCards[boundedSelectedCard];
232
+ if (!cardToMove) return;
233
+ setColumns((prev) => {
234
+ const next = prev.map((col) => ({
235
+ ...col,
236
+ cards: [...col.cards]
237
+ }));
238
+ next[selectedColumn].cards.splice(boundedSelectedCard, 1);
239
+ next[targetColumnIndex].cards.push(cardToMove);
240
+ return next;
241
+ });
242
+ setSelectedColumn(targetColumnIndex);
243
+ setSelectedCard(columns[targetColumnIndex].cards.length);
244
+ }
245
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
246
+ flexDirection: "column",
247
+ padding: 1,
248
+ height: "100%",
249
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
250
+ flexGrow: 1,
251
+ flexDirection: "row",
252
+ gap: 1,
253
+ overflow: "hidden",
254
+ children: columns.map((column, colIndex) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ColumnComponent, {
255
+ column,
256
+ isSelected: colIndex === selectedColumn,
257
+ selectedCardIndex: colIndex === selectedColumn ? boundedSelectedCard : -1
258
+ }, column.id))
259
+ })
260
+ });
261
+ }
262
+ async function main() {
263
+ try {
264
+ var _usingCtx$1 = _usingCtx();
265
+ const term = _usingCtx$1.u(createTerm());
266
+ const { waitUntilExit } = await render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExampleBanner, {
267
+ meta,
268
+ controls: "h/l column j/k card </> move Esc/q quit",
269
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(KanbanBoard, {})
270
+ }), term);
271
+ await waitUntilExit();
272
+ } catch (_) {
273
+ _usingCtx$1.e = _;
274
+ } finally {
275
+ _usingCtx$1.d();
276
+ }
277
+ }
278
+ if (import.meta.main) await main();
279
+ //#endregion
280
+ export { KanbanBoard, main, meta };
@@ -0,0 +1,187 @@
1
+ import { t as _usingCtx } from "../usingCtx-CsEf0xO3.mjs";
2
+ import { t as require_jsx_runtime } from "../jsx-runtime-dMs_8fNu.mjs";
3
+ import { t as ExampleBanner } from "../_banner-DLPxCqVy.mjs";
4
+ import { useRef, useState } from "react";
5
+ import { Box, H1, Kbd, Muted, Text, createTerm, render, useApp, useInput } from "silvery";
6
+ //#region apps/layout-ref.tsx
7
+ /**
8
+ * Layout Ref Example
9
+ *
10
+ * Demonstrates imperative access to layout information:
11
+ * - forwardRef on Box and Text components
12
+ * - BoxHandle for accessing layout info imperatively
13
+ * - onLayout callback for responding to size changes
14
+ */
15
+ var import_jsx_runtime = require_jsx_runtime();
16
+ const meta = {
17
+ name: "Layout Ref",
18
+ description: "useBoxRect + useScrollRect for imperative layout measurement",
19
+ features: [
20
+ "forwardRef",
21
+ "BoxHandle",
22
+ "onLayout",
23
+ "getBoxRect()"
24
+ ]
25
+ };
26
+ function ResizablePane({ title, color, onLayoutChange }) {
27
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
28
+ ref: useRef(null),
29
+ flexGrow: 1,
30
+ borderStyle: "round",
31
+ borderColor: color,
32
+ padding: 1,
33
+ onLayout: (layout) => onLayoutChange(layout),
34
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(H1, {
35
+ color,
36
+ children: title
37
+ })
38
+ });
39
+ }
40
+ function ImperativeAccessDemo() {
41
+ const boxRef = useRef(null);
42
+ const [info, setInfo] = useState("Click 'i' to inspect");
43
+ const inspect = () => {
44
+ if (!boxRef.current) {
45
+ setInfo("No ref attached");
46
+ return;
47
+ }
48
+ const content = boxRef.current.getBoxRect();
49
+ const screen = boxRef.current.getScrollRect();
50
+ const node = boxRef.current.getNode();
51
+ setInfo(`Content: ${content?.width}x${content?.height} at (${content?.x},${content?.y})\nScreen: ${screen?.width}x${screen?.height} at (${screen?.x},${screen?.y})\nNode: ${node ? "available" : "null"}`);
52
+ };
53
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
54
+ ref: boxRef,
55
+ flexDirection: "column",
56
+ borderStyle: "double",
57
+ borderColor: "$accent",
58
+ padding: 1,
59
+ children: [
60
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(H1, {
61
+ color: "$accent",
62
+ children: "Imperative Access (BoxHandle)"
63
+ }),
64
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Muted, { children: "Press 'i' to inspect this box" }),
65
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
66
+ marginTop: 1,
67
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, { children: info })
68
+ }),
69
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(InspectTrigger, { onInspect: inspect })
70
+ ]
71
+ });
72
+ }
73
+ function InspectTrigger({ onInspect }) {
74
+ useInput((input) => {
75
+ if (input === "i") onInspect();
76
+ });
77
+ return null;
78
+ }
79
+ function LayoutRefApp() {
80
+ const { exit } = useApp();
81
+ const [layouts, setLayouts] = useState({});
82
+ useInput((input, key) => {
83
+ if (input === "q" || key.escape) exit();
84
+ });
85
+ const handleLayoutChange = (pane) => (info) => {
86
+ setLayouts((prev) => ({
87
+ ...prev,
88
+ [pane]: info
89
+ }));
90
+ };
91
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
92
+ flexDirection: "column",
93
+ padding: 1,
94
+ children: [
95
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
96
+ flexDirection: "row",
97
+ gap: 1,
98
+ height: 8,
99
+ children: [
100
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResizablePane, {
101
+ title: "Pane A",
102
+ color: "$success",
103
+ onLayoutChange: handleLayoutChange("a")
104
+ }),
105
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResizablePane, {
106
+ title: "Pane B",
107
+ color: "$info",
108
+ onLayoutChange: handleLayoutChange("b")
109
+ }),
110
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ResizablePane, {
111
+ title: "Pane C",
112
+ color: "$primary",
113
+ onLayoutChange: handleLayoutChange("c")
114
+ })
115
+ ]
116
+ }),
117
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
118
+ marginTop: 1,
119
+ borderStyle: "single",
120
+ borderColor: "$border",
121
+ padding: 1,
122
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Box, {
123
+ flexDirection: "column",
124
+ children: [
125
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
126
+ bold: true,
127
+ dim: true,
128
+ children: "onLayout Results:"
129
+ }),
130
+ Object.entries(layouts).map(([pane, info]) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Text, {
131
+ dim: true,
132
+ children: [
133
+ "Pane ",
134
+ pane.toUpperCase(),
135
+ ": ",
136
+ info.width,
137
+ "x",
138
+ info.height,
139
+ " at (",
140
+ info.x,
141
+ ",",
142
+ info.y,
143
+ ")"
144
+ ]
145
+ }, pane)),
146
+ Object.keys(layouts).length === 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Text, {
147
+ dim: true,
148
+ italic: true,
149
+ children: "Waiting for layout..."
150
+ })
151
+ ]
152
+ })
153
+ }),
154
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Box, {
155
+ flexGrow: 1,
156
+ marginTop: 1,
157
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ImperativeAccessDemo, {})
158
+ }),
159
+ /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(Muted, { children: [
160
+ " ",
161
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Kbd, { children: "i" }),
162
+ " inspect ",
163
+ /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Kbd, { children: "Esc/q" }),
164
+ " quit"
165
+ ] })
166
+ ]
167
+ });
168
+ }
169
+ async function main() {
170
+ try {
171
+ var _usingCtx$1 = _usingCtx();
172
+ const term = _usingCtx$1.u(createTerm());
173
+ const { waitUntilExit } = await render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(ExampleBanner, {
174
+ meta,
175
+ controls: "i inspect Esc/q quit",
176
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(LayoutRefApp, {})
177
+ }), term);
178
+ await waitUntilExit();
179
+ } catch (_) {
180
+ _usingCtx$1.e = _;
181
+ } finally {
182
+ _usingCtx$1.d();
183
+ }
184
+ }
185
+ if (import.meta.main) await main();
186
+ //#endregion
187
+ export { LayoutRefApp, main, meta };