@cli-use/tui 0.1.0

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.
@@ -0,0 +1,280 @@
1
+ /**
2
+ * @license MIT
3
+ * cli-use - React-based Terminal UI Framework
4
+ * Inspired by Ratatui (https://ratatui.rs)
5
+ */
6
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
7
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
8
+ }) : x)(function(x) {
9
+ if (typeof require !== "undefined") return require.apply(this, arguments);
10
+ throw Error('Dynamic require of "' + x + '" is not supported');
11
+ });
12
+
13
+ // src/hooks/useApp.ts
14
+ import { useEffect, useState, useRef } from "react";
15
+ var useApp = (options = {}) => {
16
+ const rendererRef = useRef(null);
17
+ const [size, setSize] = useState({ cols: 80, rows: 24 });
18
+ const [running, setRunning] = useState(false);
19
+ useEffect(() => {
20
+ const cleanupResize = () => {
21
+ };
22
+ setRunning(true);
23
+ return () => {
24
+ setRunning(false);
25
+ cleanupResize();
26
+ };
27
+ }, []);
28
+ const exit = () => {
29
+ if (rendererRef.current) {
30
+ setRunning(false);
31
+ }
32
+ };
33
+ return {
34
+ renderer: rendererRef.current,
35
+ size,
36
+ running,
37
+ exit
38
+ };
39
+ };
40
+
41
+ // src/hooks/useInput.ts
42
+ import { useEffect as useEffect2, useCallback } from "react";
43
+ var useInput = (callback, deps = []) => {
44
+ useEffect2(() => {
45
+ const readline = __require("readline");
46
+ const handler = (chunk, key) => {
47
+ if (!key) return;
48
+ callback({
49
+ key: key.name || "",
50
+ name: key.name || "",
51
+ ctrl: key.ctrl || false,
52
+ meta: key.meta || false,
53
+ shift: key.shift || false,
54
+ sequence: key.sequence || ""
55
+ });
56
+ };
57
+ process.stdin.setRawMode(true);
58
+ readline.emitKeypressEvents(process.stdin);
59
+ process.stdin.on("keypress", handler);
60
+ return () => {
61
+ process.stdin.off("keypress", handler);
62
+ };
63
+ }, [callback, ...deps]);
64
+ };
65
+ var useKey = (keyName, callback, deps = []) => {
66
+ const keys = Array.isArray(keyName) ? keyName : [keyName];
67
+ useInput(
68
+ useCallback(
69
+ ({ key, ctrl, meta }) => {
70
+ if (ctrl || meta) return;
71
+ if (keys.includes(key)) {
72
+ callback();
73
+ }
74
+ },
75
+ [callback, keys]
76
+ ),
77
+ deps
78
+ );
79
+ };
80
+
81
+ // src/hooks/useFocus.ts
82
+ import { useState as useState2, useCallback as useCallback2, useRef as useRef2, useEffect as useEffect3 } from "react";
83
+ var useFocus = (initialFocus = 0, itemCount) => {
84
+ const [focusedIndex, setFocusedIndex] = useState2(initialFocus);
85
+ const focusableRefs = useRef2(/* @__PURE__ */ new Map());
86
+ const focusNext = useCallback2(() => {
87
+ setFocusedIndex((current) => (current + 1) % itemCount);
88
+ }, [itemCount]);
89
+ const focusPrevious = useCallback2(() => {
90
+ setFocusedIndex((current) => (current - 1 + itemCount) % itemCount);
91
+ }, [itemCount]);
92
+ const setFocus = useCallback2((index) => {
93
+ if (index >= 0 && index < itemCount) {
94
+ setFocusedIndex(index);
95
+ }
96
+ }, [itemCount]);
97
+ const isFocused = useCallback2(
98
+ (index) => index === focusedIndex,
99
+ [focusedIndex]
100
+ );
101
+ useEffect3(() => {
102
+ const readline = __require("readline");
103
+ readline.emitKeypressEvents(process.stdin);
104
+ process.stdin.setRawMode(true);
105
+ const handleKeyPress = (_chunk, key) => {
106
+ if (key.name === "tab" || key.name === "right") {
107
+ focusNext();
108
+ } else if (key.name === "left") {
109
+ focusPrevious();
110
+ }
111
+ };
112
+ process.stdin.on("keypress", handleKeyPress);
113
+ return () => {
114
+ process.stdin.off("keypress", handleKeyPress);
115
+ };
116
+ }, [focusNext, focusPrevious]);
117
+ return {
118
+ focusedIndex,
119
+ focusNext,
120
+ focusPrevious,
121
+ setFocus,
122
+ isFocused
123
+ };
124
+ };
125
+
126
+ // src/hooks/useStdout.ts
127
+ import { useCallback as useCallback3, useEffect as useEffect4, useState as useState3 } from "react";
128
+ var useStdoutDimensions = () => {
129
+ const [dimensions, setDimensions] = useState3(() => ({
130
+ columns: process.stdout.columns || 80,
131
+ rows: process.stdout.rows || 24
132
+ }));
133
+ useEffect4(() => {
134
+ const handleResize = () => {
135
+ setDimensions({
136
+ columns: process.stdout.columns || 80,
137
+ rows: process.stdout.rows || 24
138
+ });
139
+ };
140
+ process.stdout.on("resize", handleResize);
141
+ return () => {
142
+ process.stdout.off("resize", handleResize);
143
+ };
144
+ }, []);
145
+ return dimensions;
146
+ };
147
+ var useStdout = () => {
148
+ const write = useCallback3((data) => {
149
+ process.stdout.write(data);
150
+ }, []);
151
+ return { write };
152
+ };
153
+
154
+ // src/hooks/useInterval.ts
155
+ import { useEffect as useEffect5, useRef as useRef3 } from "react";
156
+ var useInterval = (callback, delay) => {
157
+ const savedCallback = useRef3(callback);
158
+ useEffect5(() => {
159
+ savedCallback.current = callback;
160
+ }, [callback]);
161
+ useEffect5(() => {
162
+ if (delay === null) return;
163
+ const tick = () => savedCallback.current();
164
+ const id = setInterval(tick, delay);
165
+ return () => clearInterval(id);
166
+ }, [delay]);
167
+ };
168
+ var useTimeout = (callback, delay) => {
169
+ const savedCallback = useRef3(callback);
170
+ useEffect5(() => {
171
+ savedCallback.current = callback;
172
+ }, [callback]);
173
+ useEffect5(() => {
174
+ if (delay === null) return;
175
+ const tick = () => savedCallback.current();
176
+ const id = setTimeout(tick, delay);
177
+ return () => clearTimeout(id);
178
+ }, [delay]);
179
+ };
180
+
181
+ // src/hooks/useAppState.ts
182
+ import { useState as useState4, useCallback as useCallback4 } from "react";
183
+ var useAppState = (initialState = "idle") => {
184
+ const [state, setState] = useState4(initialState);
185
+ const [error, setError] = useState4(null);
186
+ const setLoading = useCallback4(() => {
187
+ setState("loading");
188
+ setError(null);
189
+ }, []);
190
+ const setSuccess = useCallback4(() => {
191
+ setState("success");
192
+ setError(null);
193
+ }, []);
194
+ const setErrorState = useCallback4((err) => {
195
+ setState("error");
196
+ setError(err);
197
+ }, []);
198
+ const setIdle = useCallback4(() => {
199
+ setState("idle");
200
+ setError(null);
201
+ }, []);
202
+ const isLoading = state === "loading";
203
+ const isSuccess = state === "success";
204
+ const isError = state === "error";
205
+ const isIdle = state === "idle";
206
+ return {
207
+ state,
208
+ error,
209
+ isLoading,
210
+ isSuccess,
211
+ isError,
212
+ isIdle,
213
+ setLoading,
214
+ setSuccess,
215
+ setError: setErrorState,
216
+ setIdle
217
+ };
218
+ };
219
+
220
+ // src/hooks/useList.ts
221
+ import { useState as useState5, useCallback as useCallback5 } from "react";
222
+ var useList = ({
223
+ initialItems = [],
224
+ initialIndex = 0,
225
+ loop = true
226
+ } = {}) => {
227
+ const [items, setItems] = useState5(initialItems);
228
+ const [index, setIndex] = useState5(initialIndex);
229
+ const next = useCallback5(() => {
230
+ setIndex((current) => {
231
+ if (items.length === 0) return 0;
232
+ const nextIndex = current + 1;
233
+ if (nextIndex >= items.length) {
234
+ return loop ? 0 : items.length - 1;
235
+ }
236
+ return nextIndex;
237
+ });
238
+ }, [items.length, loop]);
239
+ const previous = useCallback5(() => {
240
+ setIndex((current) => {
241
+ if (items.length === 0) return 0;
242
+ const prevIndex = current - 1;
243
+ if (prevIndex < 0) {
244
+ return loop ? items.length - 1 : 0;
245
+ }
246
+ return prevIndex;
247
+ });
248
+ }, [items.length, loop]);
249
+ const select = useCallback5((item) => {
250
+ const newIndex = items.indexOf(item);
251
+ if (newIndex !== -1) {
252
+ setIndex(newIndex);
253
+ }
254
+ }, [items]);
255
+ const selectedIndex = index;
256
+ const selectedItem = items[index] ?? null;
257
+ return {
258
+ items,
259
+ setItems,
260
+ index: selectedIndex,
261
+ setIndex,
262
+ selectedItem,
263
+ next,
264
+ previous,
265
+ select
266
+ };
267
+ };
268
+ export {
269
+ useApp,
270
+ useAppState,
271
+ useFocus,
272
+ useInput,
273
+ useInterval,
274
+ useKey,
275
+ useList,
276
+ useStdout,
277
+ useStdoutDimensions,
278
+ useTimeout
279
+ };
280
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/useApp.ts","../../src/hooks/useInput.ts","../../src/hooks/useFocus.ts","../../src/hooks/useStdout.ts","../../src/hooks/useInterval.ts","../../src/hooks/useAppState.ts","../../src/hooks/useList.ts"],"sourcesContent":["import { Renderer } from '../renderer/index.js';\nimport { useEffect, useState, useRef } from 'react';\n\ninterface AppOptions {\n fullscreen?: boolean;\n alternateScreen?: boolean;\n mouseCapture?: boolean;\n}\n\n/**\n * useApp - Hook for managing the application lifecycle\n */\nexport const useApp = (options: AppOptions = {}) => {\n const rendererRef = useRef<Renderer | null>(null);\n const [size, setSize] = useState({ cols: 80, rows: 24 });\n const [running, setRunning] = useState(false);\n\n useEffect(() => {\n // Note: Renderer is not fully implemented yet, this is a skeleton\n // const renderer = new Renderer();\n // rendererRef.current = renderer;\n //\n // renderer.start();\n //\n // // Set initial size\n // setSize(renderer.getSize());\n //\n // // Setup resize handler\n // const cleanupResize = renderer.getTerminal().onResize((newSize) => {\n // setSize(newSize);\n // });\n //\n // setRunning(true);\n\n const cleanupResize = () => {\n // Cleanup function\n };\n\n setRunning(true);\n\n return () => {\n setRunning(false);\n cleanupResize();\n // renderer.stop();\n };\n }, []);\n\n const exit = () => {\n if (rendererRef.current) {\n // rendererRef.current.stop();\n setRunning(false);\n }\n };\n\n return {\n renderer: rendererRef.current,\n size,\n running,\n exit,\n };\n};\n","import { useEffect, useCallback } from 'react';\n\ninterface InputEvent {\n key: string;\n name: string;\n ctrl: boolean;\n meta: boolean;\n shift: boolean;\n sequence: string;\n}\n\ninterface ReadlineKey {\n name?: string;\n ctrl?: boolean;\n meta?: boolean;\n shift?: boolean;\n sequence?: string;\n}\n\ntype InputCallback = (input: InputEvent) => void;\n\n/**\n * useInput - Hook for capturing keyboard input\n */\nexport const useInput = (callback: InputCallback, deps: any[] = []) => {\n useEffect(() => {\n const readline = require('node:readline');\n\n const handler = (chunk: Buffer, key: ReadlineKey) => {\n if (!key) return;\n\n callback({\n key: key.name || '',\n name: key.name || '',\n ctrl: key.ctrl || false,\n meta: key.meta || false,\n shift: key.shift || false,\n sequence: key.sequence || '',\n });\n };\n\n process.stdin.setRawMode(true);\n readline.emitKeypressEvents(process.stdin);\n\n process.stdin.on('keypress', handler);\n\n return () => {\n process.stdin.off('keypress', handler);\n };\n }, [callback, ...deps]);\n};\n\n/**\n * useKey - Hook for capturing specific key presses\n */\nexport const useKey = (\n keyName: string | string[],\n callback: () => void,\n deps: any[] = []\n) => {\n const keys = Array.isArray(keyName) ? keyName : [keyName];\n\n useInput(\n useCallback(\n ({ key, ctrl, meta }) => {\n // Don't trigger if modifier keys are pressed (unless specified)\n if (ctrl || meta) return;\n\n if (keys.includes(key)) {\n callback();\n }\n },\n [callback, keys]\n ),\n deps\n );\n};\n","import { useState, useCallback, useRef, useEffect } from 'react';\n\ninterface FocusableElement {\n id: string;\n index: number;\n}\n\ninterface KeyPressEvent {\n name?: string;\n}\n\n/**\n * useFocus - Hook for managing focus state in forms and lists\n */\nexport const useFocus = (initialFocus = 0, itemCount: number) => {\n const [focusedIndex, setFocusedIndex] = useState(initialFocus);\n const focusableRefs = useRef<Map<number, HTMLElement>>(new Map());\n\n const focusNext = useCallback(() => {\n setFocusedIndex((current) => (current + 1) % itemCount);\n }, [itemCount]);\n\n const focusPrevious = useCallback(() => {\n setFocusedIndex((current) => (current - 1 + itemCount) % itemCount);\n }, [itemCount]);\n\n const setFocus = useCallback((index: number) => {\n if (index >= 0 && index < itemCount) {\n setFocusedIndex(index);\n }\n }, [itemCount]);\n\n const isFocused = useCallback(\n (index: number) => index === focusedIndex,\n [focusedIndex]\n );\n\n // Keyboard navigation\n useEffect(() => {\n const readline = require('node:readline');\n readline.emitKeypressEvents(process.stdin);\n process.stdin.setRawMode(true);\n\n const handleKeyPress = (_chunk: Buffer, key: KeyPressEvent) => {\n if (key.name === 'tab' || key.name === 'right') {\n focusNext();\n } else if (key.name === 'left') {\n focusPrevious();\n }\n };\n\n process.stdin.on('keypress', handleKeyPress);\n\n return () => {\n process.stdin.off('keypress', handleKeyPress);\n };\n }, [focusNext, focusPrevious]);\n\n return {\n focusedIndex,\n focusNext,\n focusPrevious,\n setFocus,\n isFocused,\n };\n};\n","import { useCallback, useEffect, useState } from 'react';\n\n/**\n * useStdoutDimensions - Hook for getting terminal dimensions\n */\nexport const useStdoutDimensions = () => {\n const [dimensions, setDimensions] = useState(() => ({\n columns: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n }));\n\n useEffect(() => {\n const handleResize = () => {\n setDimensions({\n columns: process.stdout.columns || 80,\n rows: process.stdout.rows || 24,\n });\n };\n\n process.stdout.on('resize', handleResize);\n\n return () => {\n process.stdout.off('resize', handleResize);\n };\n }, []);\n\n return dimensions;\n};\n\n/**\n * useStdout - Hook for stdout operations\n */\nexport const useStdout = () => {\n const write = useCallback((data: string) => {\n process.stdout.write(data);\n }, []);\n\n return { write };\n};\n","import { useEffect, useRef } from 'react';\n\n/**\n * useInterval - Hook for setting up intervals\n */\nexport const useInterval = (callback: () => void, delay: number | null) => {\n const savedCallback = useRef(callback);\n\n // Remember the latest callback\n useEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n // Set up the interval\n useEffect(() => {\n if (delay === null) return;\n\n const tick = () => savedCallback.current();\n\n const id = setInterval(tick, delay);\n\n return () => clearInterval(id);\n }, [delay]);\n};\n\n/**\n * useTimeout - Hook for setting up timeouts\n */\nexport const useTimeout = (callback: () => void, delay: number | null) => {\n const savedCallback = useRef(callback);\n\n useEffect(() => {\n savedCallback.current = callback;\n }, [callback]);\n\n useEffect(() => {\n if (delay === null) return;\n\n const tick = () => savedCallback.current();\n\n const id = setTimeout(tick, delay);\n\n return () => clearTimeout(id);\n }, [delay]);\n};\n","import { useState, useCallback } from 'react';\n\ntype AppState = 'idle' | 'loading' | 'success' | 'error';\n\n/**\n * useAppState - Hook for managing application state\n */\nexport const useAppState = (initialState: AppState = 'idle') => {\n const [state, setState] = useState<AppState>(initialState);\n const [error, setError] = useState<Error | null>(null);\n\n const setLoading = useCallback(() => {\n setState('loading');\n setError(null);\n }, []);\n\n const setSuccess = useCallback(() => {\n setState('success');\n setError(null);\n }, []);\n\n const setErrorState = useCallback((err: Error) => {\n setState('error');\n setError(err);\n }, []);\n\n const setIdle = useCallback(() => {\n setState('idle');\n setError(null);\n }, []);\n\n const isLoading = state === 'loading';\n const isSuccess = state === 'success';\n const isError = state === 'error';\n const isIdle = state === 'idle';\n\n return {\n state,\n error,\n isLoading,\n isSuccess,\n isError,\n isIdle,\n setLoading,\n setSuccess,\n setError: setErrorState,\n setIdle,\n };\n};\n","import { useState, useCallback } from 'react';\n\ninterface ListOptions<T> {\n initialItems?: T[];\n initialIndex?: number;\n loop?: boolean;\n}\n\n/**\n * useList - Hook for managing list navigation\n */\nexport const useList = <T>({\n initialItems = [],\n initialIndex = 0,\n loop = true,\n}: ListOptions<T> = {}) => {\n const [items, setItems] = useState<T[]>(initialItems);\n const [index, setIndex] = useState(initialIndex);\n\n const next = useCallback(() => {\n setIndex((current) => {\n if (items.length === 0) return 0;\n\n const nextIndex = current + 1;\n\n if (nextIndex >= items.length) {\n return loop ? 0 : items.length - 1;\n }\n\n return nextIndex;\n });\n }, [items.length, loop]);\n\n const previous = useCallback(() => {\n setIndex((current) => {\n if (items.length === 0) return 0;\n\n const prevIndex = current - 1;\n\n if (prevIndex < 0) {\n return loop ? items.length - 1 : 0;\n }\n\n return prevIndex;\n });\n }, [items.length, loop]);\n\n const select = useCallback((item: T) => {\n const newIndex = items.indexOf(item);\n if (newIndex !== -1) {\n setIndex(newIndex);\n }\n }, [items]);\n\n const selectedIndex = index;\n const selectedItem = items[index] ?? null;\n\n return {\n items,\n setItems,\n index: selectedIndex,\n setIndex,\n selectedItem,\n next,\n previous,\n select,\n };\n};\n"],"mappings":";;;;;;;;;;;;;AACA,SAAS,WAAW,UAAU,cAAc;AAWrC,IAAM,SAAS,CAAC,UAAsB,CAAC,MAAM;AAClD,QAAM,cAAc,OAAwB,IAAI;AAChD,QAAM,CAAC,MAAM,OAAO,IAAI,SAAS,EAAE,MAAM,IAAI,MAAM,GAAG,CAAC;AACvD,QAAM,CAAC,SAAS,UAAU,IAAI,SAAS,KAAK;AAE5C,YAAU,MAAM;AAiBd,UAAM,gBAAgB,MAAM;AAAA,IAE5B;AAEA,eAAW,IAAI;AAEf,WAAO,MAAM;AACX,iBAAW,KAAK;AAChB,oBAAc;AAAA,IAEhB;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,QAAM,OAAO,MAAM;AACjB,QAAI,YAAY,SAAS;AAEvB,iBAAW,KAAK;AAAA,IAClB;AAAA,EACF;AAEA,SAAO;AAAA,IACL,UAAU,YAAY;AAAA,IACtB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AC5DA,SAAS,aAAAA,YAAW,mBAAmB;AAwBhC,IAAM,WAAW,CAAC,UAAyB,OAAc,CAAC,MAAM;AACrE,EAAAA,WAAU,MAAM;AACd,UAAM,WAAW,UAAQ,UAAe;AAExC,UAAM,UAAU,CAAC,OAAe,QAAqB;AACnD,UAAI,CAAC,IAAK;AAEV,eAAS;AAAA,QACP,KAAK,IAAI,QAAQ;AAAA,QACjB,MAAM,IAAI,QAAQ;AAAA,QAClB,MAAM,IAAI,QAAQ;AAAA,QAClB,MAAM,IAAI,QAAQ;AAAA,QAClB,OAAO,IAAI,SAAS;AAAA,QACpB,UAAU,IAAI,YAAY;AAAA,MAC5B,CAAC;AAAA,IACH;AAEA,YAAQ,MAAM,WAAW,IAAI;AAC7B,aAAS,mBAAmB,QAAQ,KAAK;AAEzC,YAAQ,MAAM,GAAG,YAAY,OAAO;AAEpC,WAAO,MAAM;AACX,cAAQ,MAAM,IAAI,YAAY,OAAO;AAAA,IACvC;AAAA,EACF,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC;AACxB;AAKO,IAAM,SAAS,CACpB,SACA,UACA,OAAc,CAAC,MACZ;AACH,QAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;AAExD;AAAA,IACE;AAAA,MACE,CAAC,EAAE,KAAK,MAAM,KAAK,MAAM;AAEvB,YAAI,QAAQ,KAAM;AAElB,YAAI,KAAK,SAAS,GAAG,GAAG;AACtB,mBAAS;AAAA,QACX;AAAA,MACF;AAAA,MACA,CAAC,UAAU,IAAI;AAAA,IACjB;AAAA,IACA;AAAA,EACF;AACF;;;AC5EA,SAAS,YAAAC,WAAU,eAAAC,cAAa,UAAAC,SAAQ,aAAAC,kBAAiB;AAclD,IAAM,WAAW,CAAC,eAAe,GAAG,cAAsB;AAC/D,QAAM,CAAC,cAAc,eAAe,IAAIH,UAAS,YAAY;AAC7D,QAAM,gBAAgBE,QAAiC,oBAAI,IAAI,CAAC;AAEhE,QAAM,YAAYD,aAAY,MAAM;AAClC,oBAAgB,CAAC,aAAa,UAAU,KAAK,SAAS;AAAA,EACxD,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,gBAAgBA,aAAY,MAAM;AACtC,oBAAgB,CAAC,aAAa,UAAU,IAAI,aAAa,SAAS;AAAA,EACpE,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,WAAWA,aAAY,CAAC,UAAkB;AAC9C,QAAI,SAAS,KAAK,QAAQ,WAAW;AACnC,sBAAgB,KAAK;AAAA,IACvB;AAAA,EACF,GAAG,CAAC,SAAS,CAAC;AAEd,QAAM,YAAYA;AAAA,IAChB,CAAC,UAAkB,UAAU;AAAA,IAC7B,CAAC,YAAY;AAAA,EACf;AAGA,EAAAE,WAAU,MAAM;AACd,UAAM,WAAW,UAAQ,UAAe;AACxC,aAAS,mBAAmB,QAAQ,KAAK;AACzC,YAAQ,MAAM,WAAW,IAAI;AAE7B,UAAM,iBAAiB,CAAC,QAAgB,QAAuB;AAC7D,UAAI,IAAI,SAAS,SAAS,IAAI,SAAS,SAAS;AAC9C,kBAAU;AAAA,MACZ,WAAW,IAAI,SAAS,QAAQ;AAC9B,sBAAc;AAAA,MAChB;AAAA,IACF;AAEA,YAAQ,MAAM,GAAG,YAAY,cAAc;AAE3C,WAAO,MAAM;AACX,cAAQ,MAAM,IAAI,YAAY,cAAc;AAAA,IAC9C;AAAA,EACF,GAAG,CAAC,WAAW,aAAa,CAAC;AAE7B,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;ACjEA,SAAS,eAAAC,cAAa,aAAAC,YAAW,YAAAC,iBAAgB;AAK1C,IAAM,sBAAsB,MAAM;AACvC,QAAM,CAAC,YAAY,aAAa,IAAIA,UAAS,OAAO;AAAA,IAClD,SAAS,QAAQ,OAAO,WAAW;AAAA,IACnC,MAAM,QAAQ,OAAO,QAAQ;AAAA,EAC/B,EAAE;AAEF,EAAAD,WAAU,MAAM;AACd,UAAM,eAAe,MAAM;AACzB,oBAAc;AAAA,QACZ,SAAS,QAAQ,OAAO,WAAW;AAAA,QACnC,MAAM,QAAQ,OAAO,QAAQ;AAAA,MAC/B,CAAC;AAAA,IACH;AAEA,YAAQ,OAAO,GAAG,UAAU,YAAY;AAExC,WAAO,MAAM;AACX,cAAQ,OAAO,IAAI,UAAU,YAAY;AAAA,IAC3C;AAAA,EACF,GAAG,CAAC,CAAC;AAEL,SAAO;AACT;AAKO,IAAM,YAAY,MAAM;AAC7B,QAAM,QAAQD,aAAY,CAAC,SAAiB;AAC1C,YAAQ,OAAO,MAAM,IAAI;AAAA,EAC3B,GAAG,CAAC,CAAC;AAEL,SAAO,EAAE,MAAM;AACjB;;;ACtCA,SAAS,aAAAG,YAAW,UAAAC,eAAc;AAK3B,IAAM,cAAc,CAAC,UAAsB,UAAyB;AACzE,QAAM,gBAAgBA,QAAO,QAAQ;AAGrC,EAAAD,WAAU,MAAM;AACd,kBAAc,UAAU;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAGb,EAAAA,WAAU,MAAM;AACd,QAAI,UAAU,KAAM;AAEpB,UAAM,OAAO,MAAM,cAAc,QAAQ;AAEzC,UAAM,KAAK,YAAY,MAAM,KAAK;AAElC,WAAO,MAAM,cAAc,EAAE;AAAA,EAC/B,GAAG,CAAC,KAAK,CAAC;AACZ;AAKO,IAAM,aAAa,CAAC,UAAsB,UAAyB;AACxE,QAAM,gBAAgBC,QAAO,QAAQ;AAErC,EAAAD,WAAU,MAAM;AACd,kBAAc,UAAU;AAAA,EAC1B,GAAG,CAAC,QAAQ,CAAC;AAEb,EAAAA,WAAU,MAAM;AACd,QAAI,UAAU,KAAM;AAEpB,UAAM,OAAO,MAAM,cAAc,QAAQ;AAEzC,UAAM,KAAK,WAAW,MAAM,KAAK;AAEjC,WAAO,MAAM,aAAa,EAAE;AAAA,EAC9B,GAAG,CAAC,KAAK,CAAC;AACZ;;;AC5CA,SAAS,YAAAE,WAAU,eAAAC,oBAAmB;AAO/B,IAAM,cAAc,CAAC,eAAyB,WAAW;AAC9D,QAAM,CAAC,OAAO,QAAQ,IAAID,UAAmB,YAAY;AACzD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAuB,IAAI;AAErD,QAAM,aAAaC,aAAY,MAAM;AACnC,aAAS,SAAS;AAClB,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,QAAM,aAAaA,aAAY,MAAM;AACnC,aAAS,SAAS;AAClB,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,QAAM,gBAAgBA,aAAY,CAAC,QAAe;AAChD,aAAS,OAAO;AAChB,aAAS,GAAG;AAAA,EACd,GAAG,CAAC,CAAC;AAEL,QAAM,UAAUA,aAAY,MAAM;AAChC,aAAS,MAAM;AACf,aAAS,IAAI;AAAA,EACf,GAAG,CAAC,CAAC;AAEL,QAAM,YAAY,UAAU;AAC5B,QAAM,YAAY,UAAU;AAC5B,QAAM,UAAU,UAAU;AAC1B,QAAM,SAAS,UAAU;AAEzB,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV;AAAA,EACF;AACF;;;AChDA,SAAS,YAAAC,WAAU,eAAAC,oBAAmB;AAW/B,IAAM,UAAU,CAAI;AAAA,EACzB,eAAe,CAAC;AAAA,EAChB,eAAe;AAAA,EACf,OAAO;AACT,IAAoB,CAAC,MAAM;AACzB,QAAM,CAAC,OAAO,QAAQ,IAAID,UAAc,YAAY;AACpD,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,YAAY;AAE/C,QAAM,OAAOC,aAAY,MAAM;AAC7B,aAAS,CAAC,YAAY;AACpB,UAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,YAAM,YAAY,UAAU;AAE5B,UAAI,aAAa,MAAM,QAAQ;AAC7B,eAAO,OAAO,IAAI,MAAM,SAAS;AAAA,MACnC;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,QAAQ,IAAI,CAAC;AAEvB,QAAM,WAAWA,aAAY,MAAM;AACjC,aAAS,CAAC,YAAY;AACpB,UAAI,MAAM,WAAW,EAAG,QAAO;AAE/B,YAAM,YAAY,UAAU;AAE5B,UAAI,YAAY,GAAG;AACjB,eAAO,OAAO,MAAM,SAAS,IAAI;AAAA,MACnC;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH,GAAG,CAAC,MAAM,QAAQ,IAAI,CAAC;AAEvB,QAAM,SAASA,aAAY,CAAC,SAAY;AACtC,UAAM,WAAW,MAAM,QAAQ,IAAI;AACnC,QAAI,aAAa,IAAI;AACnB,eAAS,QAAQ;AAAA,IACnB;AAAA,EACF,GAAG,CAAC,KAAK,CAAC;AAEV,QAAM,gBAAgB;AACtB,QAAM,eAAe,MAAM,KAAK,KAAK;AAErC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;","names":["useEffect","useState","useCallback","useRef","useEffect","useCallback","useEffect","useState","useEffect","useRef","useState","useCallback","useState","useCallback"]}
@@ -0,0 +1,272 @@
1
+ import { ReadStream, WriteStream } from 'node:tty';
2
+ import * as readline from 'node:readline';
3
+ import * as React from 'react';
4
+
5
+ /**
6
+ * Terminal cell representation
7
+ */
8
+ interface Cell {
9
+ char: string;
10
+ fg?: number;
11
+ bg?: number;
12
+ bold?: boolean;
13
+ dim?: boolean;
14
+ italic?: boolean;
15
+ underline?: boolean;
16
+ strikethrough?: boolean;
17
+ }
18
+ /**
19
+ * Terminal buffer - a 2D grid of cells
20
+ */
21
+ declare class Buffer {
22
+ width: number;
23
+ height: number;
24
+ cells: Cell[][];
25
+ constructor(width: number, height: number, cells?: Cell[][]);
26
+ setCell(x: number, y: number, cell: Cell): void;
27
+ getCell(x: number, y: number): Cell | undefined;
28
+ clear(): void;
29
+ resize(width: number, height: number): void;
30
+ clone(): Buffer;
31
+ }
32
+ /**
33
+ * Terminal size
34
+ */
35
+ interface Size {
36
+ cols: number;
37
+ rows: number;
38
+ }
39
+
40
+ type ProcessStdin = ReadStream & NodeJS.ReadStream;
41
+ type ProcessStdout = WriteStream & NodeJS.WriteStream;
42
+ /**
43
+ * ANSI escape codes for terminal control
44
+ */
45
+ declare const ANSI: {
46
+ readonly CLEAR_SCREEN: "\u001B[2J";
47
+ readonly RESET_CURSOR: "\u001B[H";
48
+ readonly ALTERNATE_SCREEN_ENABLE: "\u001B[?1049h";
49
+ readonly ALTERNATE_SCREEN_DISABLE: "\u001B[?1049l";
50
+ readonly HIDE_CURSOR: "\u001B[?25l";
51
+ readonly SHOW_CURSOR: "\u001B[?25h";
52
+ readonly MOVE_CURSOR: (x: number, y: number) => string;
53
+ readonly RESET_STYLE: "\u001B[0m";
54
+ readonly FG_COLOR_256: (color: number) => string;
55
+ readonly BG_COLOR_256: (color: number) => string;
56
+ readonly FG_COLOR_RGB: (r: number, g: number, b: number) => string;
57
+ readonly BG_COLOR_RGB: (r: number, g: number, b: number) => string;
58
+ readonly BOLD: "\u001B[1m";
59
+ readonly DIM: "\u001B[2m";
60
+ readonly ITALIC: "\u001B[3m";
61
+ readonly UNDERLINE: "\u001B[4m";
62
+ readonly STRIKETHROUGH: "\u001B[9m";
63
+ readonly BOLD_OFF: "\u001B[22m";
64
+ readonly DIM_OFF: "\u001B[22m";
65
+ readonly ITALIC_OFF: "\u001B[23m";
66
+ readonly UNDERLINE_OFF: "\u001B[24m";
67
+ readonly STRIKETHROUGH_OFF: "\u001B[29m";
68
+ };
69
+ /**
70
+ * Terminal interface - handles low-level terminal I/O
71
+ */
72
+ declare class Terminal {
73
+ private stdin;
74
+ private stdout;
75
+ private _size;
76
+ private rawMode;
77
+ private alternateScreen;
78
+ constructor(stdin?: ProcessStdin, stdout?: ProcessStdout);
79
+ get size(): Size;
80
+ /**
81
+ * Enable raw mode for character-by-character input
82
+ */
83
+ enableRawMode(): void;
84
+ /**
85
+ * Disable raw mode
86
+ */
87
+ disableRawMode(): void;
88
+ /**
89
+ * Enable alternate screen buffer
90
+ */
91
+ enableAlternateScreen(): void;
92
+ /**
93
+ * Disable alternate screen buffer
94
+ */
95
+ disableAlternateScreen(): void;
96
+ /**
97
+ * Hide cursor
98
+ */
99
+ hideCursor(): void;
100
+ /**
101
+ * Show cursor
102
+ */
103
+ showCursor(): void;
104
+ /**
105
+ * Clear the entire screen
106
+ */
107
+ clear(): void;
108
+ /**
109
+ * Write buffer to terminal
110
+ */
111
+ write(buffer: Buffer): void;
112
+ /**
113
+ * Build ANSI style string from cell
114
+ */
115
+ private buildStyleString;
116
+ /**
117
+ * Set up SIGWINCH handler for terminal resize
118
+ */
119
+ onResize(callback: (size: Size) => void): () => void;
120
+ /**
121
+ * Set up input handler
122
+ */
123
+ onInput(callback: (chunk: Buffer, key: readline.Key) => void): () => void;
124
+ /**
125
+ * Clean up terminal state
126
+ */
127
+ restore(): void;
128
+ }
129
+
130
+ /**
131
+ * Renderer - manages the rendering lifecycle
132
+ */
133
+ declare class Renderer {
134
+ private terminal;
135
+ private buffer?;
136
+ private previousBuffer?;
137
+ private currentSize;
138
+ private running;
139
+ constructor(terminal?: Terminal);
140
+ /**
141
+ * Start the renderer
142
+ */
143
+ start(): void;
144
+ /**
145
+ * Stop the renderer
146
+ */
147
+ stop(): void;
148
+ /**
149
+ * Get a writable buffer for the current frame
150
+ */
151
+ getBuffer(): Buffer;
152
+ /**
153
+ * Present the current buffer to the terminal
154
+ */
155
+ present(): void;
156
+ /**
157
+ * Get the current terminal size
158
+ */
159
+ getSize(): Size;
160
+ /**
161
+ * Get the terminal instance for direct access
162
+ */
163
+ getTerminal(): Terminal;
164
+ }
165
+
166
+ interface AppOptions {
167
+ fullscreen?: boolean;
168
+ alternateScreen?: boolean;
169
+ mouseCapture?: boolean;
170
+ }
171
+ /**
172
+ * useApp - Hook for managing the application lifecycle
173
+ */
174
+ declare const useApp: (options?: AppOptions) => {
175
+ renderer: Renderer | null;
176
+ size: {
177
+ cols: number;
178
+ rows: number;
179
+ };
180
+ running: boolean;
181
+ exit: () => void;
182
+ };
183
+
184
+ interface InputEvent {
185
+ key: string;
186
+ name: string;
187
+ ctrl: boolean;
188
+ meta: boolean;
189
+ shift: boolean;
190
+ sequence: string;
191
+ }
192
+ type InputCallback = (input: InputEvent) => void;
193
+ /**
194
+ * useInput - Hook for capturing keyboard input
195
+ */
196
+ declare const useInput: (callback: InputCallback, deps?: any[]) => void;
197
+ /**
198
+ * useKey - Hook for capturing specific key presses
199
+ */
200
+ declare const useKey: (keyName: string | string[], callback: () => void, deps?: any[]) => void;
201
+
202
+ /**
203
+ * useFocus - Hook for managing focus state in forms and lists
204
+ */
205
+ declare const useFocus: (initialFocus: number | undefined, itemCount: number) => {
206
+ focusedIndex: number;
207
+ focusNext: () => void;
208
+ focusPrevious: () => void;
209
+ setFocus: (index: number) => void;
210
+ isFocused: (index: number) => boolean;
211
+ };
212
+
213
+ /**
214
+ * useStdoutDimensions - Hook for getting terminal dimensions
215
+ */
216
+ declare const useStdoutDimensions: () => {
217
+ columns: number;
218
+ rows: number;
219
+ };
220
+ /**
221
+ * useStdout - Hook for stdout operations
222
+ */
223
+ declare const useStdout: () => {
224
+ write: (data: string) => void;
225
+ };
226
+
227
+ /**
228
+ * useInterval - Hook for setting up intervals
229
+ */
230
+ declare const useInterval: (callback: () => void, delay: number | null) => void;
231
+ /**
232
+ * useTimeout - Hook for setting up timeouts
233
+ */
234
+ declare const useTimeout: (callback: () => void, delay: number | null) => void;
235
+
236
+ type AppState = 'idle' | 'loading' | 'success' | 'error';
237
+ /**
238
+ * useAppState - Hook for managing application state
239
+ */
240
+ declare const useAppState: (initialState?: AppState) => {
241
+ state: AppState;
242
+ error: Error | null;
243
+ isLoading: boolean;
244
+ isSuccess: boolean;
245
+ isError: boolean;
246
+ isIdle: boolean;
247
+ setLoading: () => void;
248
+ setSuccess: () => void;
249
+ setError: (err: Error) => void;
250
+ setIdle: () => void;
251
+ };
252
+
253
+ interface ListOptions<T> {
254
+ initialItems?: T[];
255
+ initialIndex?: number;
256
+ loop?: boolean;
257
+ }
258
+ /**
259
+ * useList - Hook for managing list navigation
260
+ */
261
+ declare const useList: <T>({ initialItems, initialIndex, loop, }?: ListOptions<T>) => {
262
+ items: T[];
263
+ setItems: React.Dispatch<React.SetStateAction<T[]>>;
264
+ index: number;
265
+ setIndex: React.Dispatch<React.SetStateAction<number>>;
266
+ selectedItem: NonNullable<T> | null;
267
+ next: () => void;
268
+ previous: () => void;
269
+ select: (item: T) => void;
270
+ };
271
+
272
+ export { ANSI as A, Buffer as B, Renderer as R, Terminal as T, useAppState as a, useFocus as b, useInput as c, useInterval as d, useKey as e, useList as f, useStdout as g, useStdoutDimensions as h, useTimeout as i, useApp as u };