@mdxui/terminal 2.0.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.
Files changed (191) hide show
  1. package/README.md +571 -0
  2. package/dist/ansi-css-Sk5mWtdK.d.ts +119 -0
  3. package/dist/ansi-css-V6JIHGsM.d.ts +119 -0
  4. package/dist/ansi-css-_3eSEU9d.d.ts +119 -0
  5. package/dist/chunk-3EFDH7PK.js +5235 -0
  6. package/dist/chunk-3RG5ZIWI.js +10 -0
  7. package/dist/chunk-3X5IR6WE.js +884 -0
  8. package/dist/chunk-4FV5ZDCE.js +5236 -0
  9. package/dist/chunk-4OVMSF2J.js +243 -0
  10. package/dist/chunk-63FEETIS.js +4048 -0
  11. package/dist/chunk-B43KP7XJ.js +884 -0
  12. package/dist/chunk-BMTJXWUV.js +655 -0
  13. package/dist/chunk-C3SVH4N7.js +882 -0
  14. package/dist/chunk-EVWR7Y47.js +874 -0
  15. package/dist/chunk-F6A5VWUC.js +1285 -0
  16. package/dist/chunk-FD7KW7GE.js +882 -0
  17. package/dist/chunk-GBQ6UD6I.js +655 -0
  18. package/dist/chunk-GMDD3M6U.js +5227 -0
  19. package/dist/chunk-JBHRXOXM.js +1058 -0
  20. package/dist/chunk-JFOO3EYO.js +1182 -0
  21. package/dist/chunk-JQ5H3WXL.js +1291 -0
  22. package/dist/chunk-JQD5NASE.js +234 -0
  23. package/dist/chunk-KRHJP5R7.js +592 -0
  24. package/dist/chunk-KWF6WVJE.js +962 -0
  25. package/dist/chunk-LHYQVN3H.js +1038 -0
  26. package/dist/chunk-M3TLQLGC.js +1032 -0
  27. package/dist/chunk-MVW4Q5OP.js +240 -0
  28. package/dist/chunk-NXCZSWLU.js +1294 -0
  29. package/dist/chunk-O25TNRO6.js +607 -0
  30. package/dist/chunk-PNECDA2I.js +884 -0
  31. package/dist/chunk-QIHWRLJR.js +962 -0
  32. package/dist/chunk-QW5YMQ7K.js +882 -0
  33. package/dist/chunk-R5U7XKVJ.js +16 -0
  34. package/dist/chunk-RP2MVQLR.js +962 -0
  35. package/dist/chunk-TP6RXGXA.js +1087 -0
  36. package/dist/chunk-TQQSTITZ.js +655 -0
  37. package/dist/chunk-X24GWXQV.js +1281 -0
  38. package/dist/components/index.d.ts +802 -0
  39. package/dist/components/index.js +149 -0
  40. package/dist/data/index.d.ts +2554 -0
  41. package/dist/data/index.js +51 -0
  42. package/dist/forms/index.d.ts +1596 -0
  43. package/dist/forms/index.js +464 -0
  44. package/dist/index-CQRFZntR.d.ts +867 -0
  45. package/dist/index.d.ts +579 -0
  46. package/dist/index.js +786 -0
  47. package/dist/interactive-D0JkWosD.d.ts +217 -0
  48. package/dist/keyboard/index.d.ts +2 -0
  49. package/dist/keyboard/index.js +43 -0
  50. package/dist/renderers/index.d.ts +546 -0
  51. package/dist/renderers/index.js +2157 -0
  52. package/dist/storybook/index.d.ts +396 -0
  53. package/dist/storybook/index.js +641 -0
  54. package/dist/theme/index.d.ts +1339 -0
  55. package/dist/theme/index.js +123 -0
  56. package/dist/types-Bxu5PAgA.d.ts +710 -0
  57. package/dist/types-CIlop5Ji.d.ts +701 -0
  58. package/dist/types-Ca8p_p5X.d.ts +710 -0
  59. package/package.json +90 -0
  60. package/src/__tests__/components/data/card.test.ts +458 -0
  61. package/src/__tests__/components/data/list.test.ts +473 -0
  62. package/src/__tests__/components/data/metrics.test.ts +541 -0
  63. package/src/__tests__/components/data/table.test.ts +448 -0
  64. package/src/__tests__/components/input/field.test.ts +555 -0
  65. package/src/__tests__/components/input/form.test.ts +870 -0
  66. package/src/__tests__/components/input/search.test.ts +1238 -0
  67. package/src/__tests__/components/input/select.test.ts +658 -0
  68. package/src/__tests__/components/navigation/breadcrumb.test.ts +923 -0
  69. package/src/__tests__/components/navigation/command-palette.test.ts +1095 -0
  70. package/src/__tests__/components/navigation/sidebar.test.ts +1018 -0
  71. package/src/__tests__/components/navigation/tabs.test.ts +995 -0
  72. package/src/__tests__/components.test.tsx +1197 -0
  73. package/src/__tests__/core/compiler.test.ts +986 -0
  74. package/src/__tests__/core/parser.test.ts +785 -0
  75. package/src/__tests__/core/tier-switcher.test.ts +1103 -0
  76. package/src/__tests__/core/types.test.ts +1398 -0
  77. package/src/__tests__/data/collections.test.ts +1337 -0
  78. package/src/__tests__/data/db.test.ts +1265 -0
  79. package/src/__tests__/data/reactive.test.ts +1010 -0
  80. package/src/__tests__/data/sync.test.ts +1614 -0
  81. package/src/__tests__/errors.test.ts +660 -0
  82. package/src/__tests__/forms/integration.test.ts +444 -0
  83. package/src/__tests__/integration.test.ts +905 -0
  84. package/src/__tests__/keyboard.test.ts +1791 -0
  85. package/src/__tests__/renderer.test.ts +489 -0
  86. package/src/__tests__/renderers/ansi-css.test.ts +948 -0
  87. package/src/__tests__/renderers/ansi.test.ts +1366 -0
  88. package/src/__tests__/renderers/ascii.test.ts +1360 -0
  89. package/src/__tests__/renderers/interactive.test.ts +2353 -0
  90. package/src/__tests__/renderers/markdown.test.ts +1483 -0
  91. package/src/__tests__/renderers/text.test.ts +1369 -0
  92. package/src/__tests__/renderers/unicode.test.ts +1307 -0
  93. package/src/__tests__/theme.test.ts +639 -0
  94. package/src/__tests__/utils/assertions.ts +685 -0
  95. package/src/__tests__/utils/index.ts +115 -0
  96. package/src/__tests__/utils/test-renderer.ts +381 -0
  97. package/src/__tests__/utils/utils.test.ts +560 -0
  98. package/src/components/containers/card.ts +56 -0
  99. package/src/components/containers/dialog.ts +53 -0
  100. package/src/components/containers/index.ts +9 -0
  101. package/src/components/containers/panel.ts +59 -0
  102. package/src/components/feedback/badge.ts +40 -0
  103. package/src/components/feedback/index.ts +8 -0
  104. package/src/components/feedback/spinner.ts +23 -0
  105. package/src/components/helpers.ts +81 -0
  106. package/src/components/index.ts +153 -0
  107. package/src/components/layout/breadcrumb.ts +31 -0
  108. package/src/components/layout/index.ts +10 -0
  109. package/src/components/layout/list.ts +29 -0
  110. package/src/components/layout/sidebar.ts +79 -0
  111. package/src/components/layout/table.ts +62 -0
  112. package/src/components/primitives/box.ts +95 -0
  113. package/src/components/primitives/button.ts +54 -0
  114. package/src/components/primitives/index.ts +11 -0
  115. package/src/components/primitives/input.ts +88 -0
  116. package/src/components/primitives/select.ts +97 -0
  117. package/src/components/primitives/text.ts +60 -0
  118. package/src/components/render.ts +155 -0
  119. package/src/components/templates/app.ts +43 -0
  120. package/src/components/templates/index.ts +8 -0
  121. package/src/components/templates/site.ts +54 -0
  122. package/src/components/types.ts +777 -0
  123. package/src/core/compiler.ts +718 -0
  124. package/src/core/parser.ts +127 -0
  125. package/src/core/tier-switcher.ts +607 -0
  126. package/src/core/types.ts +672 -0
  127. package/src/data/collection.ts +316 -0
  128. package/src/data/collections.ts +50 -0
  129. package/src/data/context.tsx +174 -0
  130. package/src/data/db.ts +127 -0
  131. package/src/data/hooks.ts +532 -0
  132. package/src/data/index.ts +138 -0
  133. package/src/data/reactive.ts +1225 -0
  134. package/src/data/saas-collections.ts +375 -0
  135. package/src/data/sync.ts +1213 -0
  136. package/src/data/types.ts +660 -0
  137. package/src/forms/converters.ts +512 -0
  138. package/src/forms/index.ts +133 -0
  139. package/src/forms/schemas.ts +403 -0
  140. package/src/forms/types.ts +476 -0
  141. package/src/index.ts +542 -0
  142. package/src/keyboard/focus.ts +748 -0
  143. package/src/keyboard/index.ts +96 -0
  144. package/src/keyboard/integration.ts +371 -0
  145. package/src/keyboard/manager.ts +377 -0
  146. package/src/keyboard/presets.ts +90 -0
  147. package/src/renderers/ansi-css.ts +576 -0
  148. package/src/renderers/ansi.ts +802 -0
  149. package/src/renderers/ascii.ts +680 -0
  150. package/src/renderers/breadcrumb.ts +480 -0
  151. package/src/renderers/command-palette.ts +802 -0
  152. package/src/renderers/components/field.ts +210 -0
  153. package/src/renderers/components/form.ts +327 -0
  154. package/src/renderers/components/index.ts +21 -0
  155. package/src/renderers/components/search.ts +449 -0
  156. package/src/renderers/components/select.ts +222 -0
  157. package/src/renderers/index.ts +101 -0
  158. package/src/renderers/interactive/component-handlers.ts +622 -0
  159. package/src/renderers/interactive/cursor-manager.ts +147 -0
  160. package/src/renderers/interactive/focus-manager.ts +279 -0
  161. package/src/renderers/interactive/index.ts +661 -0
  162. package/src/renderers/interactive/input-handler.ts +164 -0
  163. package/src/renderers/interactive/keyboard-handler.ts +212 -0
  164. package/src/renderers/interactive/mouse-handler.ts +167 -0
  165. package/src/renderers/interactive/state-manager.ts +109 -0
  166. package/src/renderers/interactive/types.ts +338 -0
  167. package/src/renderers/interactive-string.ts +299 -0
  168. package/src/renderers/interactive.ts +59 -0
  169. package/src/renderers/markdown.ts +950 -0
  170. package/src/renderers/sidebar.ts +549 -0
  171. package/src/renderers/tabs.ts +682 -0
  172. package/src/renderers/text.ts +791 -0
  173. package/src/renderers/unicode.ts +917 -0
  174. package/src/renderers/utils.ts +942 -0
  175. package/src/router/adapters.ts +383 -0
  176. package/src/router/types.ts +140 -0
  177. package/src/router/utils.ts +452 -0
  178. package/src/schemas.ts +205 -0
  179. package/src/storybook/index.ts +91 -0
  180. package/src/storybook/interactive-decorator.tsx +659 -0
  181. package/src/storybook/keyboard-simulator.ts +501 -0
  182. package/src/theme/ansi-codes.ts +80 -0
  183. package/src/theme/box-drawing.ts +132 -0
  184. package/src/theme/color-convert.ts +254 -0
  185. package/src/theme/color-support.ts +321 -0
  186. package/src/theme/index.ts +134 -0
  187. package/src/theme/strip-ansi.ts +50 -0
  188. package/src/theme/tailwind-map.ts +469 -0
  189. package/src/theme/text-styles.ts +206 -0
  190. package/src/theme/theme-system.ts +568 -0
  191. package/src/types.ts +103 -0
@@ -0,0 +1,867 @@
1
+ import React__default, { ReactNode, ReactElement } from 'react';
2
+
3
+ /**
4
+ * Keyboard Manager
5
+ *
6
+ * Core keyboard binding manager for handling key bindings and sequences.
7
+ * Supports single keys, modifier combinations, and multi-key sequences.
8
+ *
9
+ * @packageDocumentation
10
+ */
11
+ /**
12
+ * Modifier key state for a key press event.
13
+ *
14
+ * Tracks which modifier keys are held during a key press.
15
+ */
16
+ interface KeyModifiers {
17
+ /** Control key is pressed */
18
+ ctrl: boolean;
19
+ /** Alt/Option key is pressed */
20
+ alt: boolean;
21
+ /** Shift key is pressed */
22
+ shift: boolean;
23
+ /** Meta/Command key is pressed */
24
+ meta: boolean;
25
+ }
26
+ /**
27
+ * A keyboard action - either a string action name or a callback function.
28
+ *
29
+ * String actions are dispatched via the onAction handler.
30
+ * Function actions are called directly when the key is pressed.
31
+ */
32
+ type KeyboardAction = string | (() => void);
33
+ /**
34
+ * Maps key names/sequences to actions.
35
+ *
36
+ * Keys can be:
37
+ * - Single characters: 'j', 'k', 'q'
38
+ * - Special keys: 'enter', 'escape', 'tab'
39
+ * - Modifier combinations: 'ctrl+c', 'shift+tab'
40
+ * - Key sequences: 'gg', 'dd' (multi-character without '+')
41
+ */
42
+ type KeyBindings = Record<string, KeyboardAction>;
43
+ /**
44
+ * Context passed to action handlers with the triggering key and optional extra data.
45
+ */
46
+ interface ActionContext {
47
+ /** The key or sequence that triggered this action */
48
+ key: string;
49
+ /** Optional context data set via setContext() */
50
+ context?: Record<string, unknown>;
51
+ }
52
+ /**
53
+ * Callback invoked when a keyboard action is triggered.
54
+ *
55
+ * @param action - The action name (string actions only)
56
+ * @param context - Context including the key and optional data
57
+ */
58
+ type ActionHandler = (action: string, context: ActionContext) => void;
59
+ /**
60
+ * Configuration options for creating a keyboard manager.
61
+ */
62
+ interface KeyboardManagerOptions {
63
+ /** Key-to-action bindings */
64
+ bindings: KeyBindings;
65
+ /** Handler called when string actions are triggered */
66
+ onAction?: ActionHandler;
67
+ /** Whether the manager starts enabled (default: true) */
68
+ enabled?: boolean;
69
+ /** Optional context data passed to action handlers */
70
+ context?: Record<string, unknown> | null;
71
+ /** Timeout in ms for key sequences (default: 1000) */
72
+ sequenceTimeout?: number;
73
+ }
74
+ /**
75
+ * Interface for the keyboard manager returned by createKeyboardManager.
76
+ */
77
+ interface KeyboardManager {
78
+ /** Get the action bound to a specific key */
79
+ getAction(key: string): KeyboardAction | undefined;
80
+ /** Handle a key press, returns true if the key was handled */
81
+ handleKey(key: string, handler?: ActionHandler): boolean;
82
+ /** Add a new key binding */
83
+ addBinding(key: string, action: KeyboardAction): void;
84
+ /** Remove a key binding */
85
+ removeBinding(key: string): void;
86
+ /** Replace all bindings */
87
+ setBindings(bindings: KeyBindings): void;
88
+ /** Get all string bindings (excludes function bindings) */
89
+ getBindings(): Record<string, string>;
90
+ /** Disable the keyboard manager */
91
+ disable(): void;
92
+ /** Enable the keyboard manager */
93
+ enable(): void;
94
+ /** Toggle enabled state */
95
+ toggle(): void;
96
+ /** Check if the manager is enabled */
97
+ isEnabled(): boolean;
98
+ /** Get the current pending key sequence */
99
+ getPendingSequence(): string;
100
+ /** Set context data passed to action handlers */
101
+ setContext(context: Record<string, unknown>): void;
102
+ /** Clean up resources (clears pending sequence timer to prevent memory leaks) */
103
+ destroy(): void;
104
+ }
105
+ /**
106
+ * Common key constants for keyboard handling.
107
+ * Use these with matchKey() for consistent key comparisons.
108
+ */
109
+ declare const KEY: {
110
+ readonly ENTER: "enter";
111
+ readonly ESCAPE: "escape";
112
+ readonly UP: "up";
113
+ readonly DOWN: "down";
114
+ readonly LEFT: "left";
115
+ readonly RIGHT: "right";
116
+ readonly TAB: "tab";
117
+ readonly SPACE: "space";
118
+ readonly BACKSPACE: "backspace";
119
+ readonly DELETE: "delete";
120
+ };
121
+ /**
122
+ * Check if a key matches an expected key.
123
+ *
124
+ * @param key - The key to check
125
+ * @param expected - The expected key value
126
+ * @returns true if keys match
127
+ *
128
+ * @example
129
+ * ```tsx
130
+ * import { matchKey, KEY } from '@mdxui/terminal'
131
+ *
132
+ * if (matchKey(pressedKey, KEY.ENTER)) {
133
+ * handleSubmit()
134
+ * }
135
+ * ```
136
+ */
137
+ declare function matchKey(key: string, expected: string): boolean;
138
+ /**
139
+ * Creates a keyboard manager for handling key bindings and sequences.
140
+ *
141
+ * The manager supports:
142
+ * - Single key bindings ('j', 'enter', 'q')
143
+ * - Modifier combinations ('ctrl+c', 'shift+tab')
144
+ * - Multi-key sequences ('gg', 'dd') with configurable timeout
145
+ * - Dynamic binding changes at runtime
146
+ * - Enable/disable toggling
147
+ *
148
+ * @param options - Configuration options
149
+ * @returns A keyboard manager instance
150
+ *
151
+ * @example
152
+ * ```tsx
153
+ * const keyboard = createKeyboardManager({
154
+ * bindings: { ...VIM_BINDINGS, ...ARROW_BINDINGS },
155
+ * onAction: (action, ctx) => {
156
+ * switch (action) {
157
+ * case 'move-down': moveDown(); break
158
+ * case 'select': handleSelect(); break
159
+ * }
160
+ * }
161
+ * })
162
+ *
163
+ * // Later, handle input
164
+ * process.stdin.on('keypress', (ch, key) => {
165
+ * keyboard.handleKey(key.name || ch)
166
+ * })
167
+ * ```
168
+ */
169
+ declare function createKeyboardManager(options: KeyboardManagerOptions): KeyboardManager;
170
+
171
+ /**
172
+ * Preset Key Bindings
173
+ *
174
+ * Common keyboard binding presets for terminal applications.
175
+ * Includes Vim-style, arrow key, and common UI bindings.
176
+ *
177
+ * @packageDocumentation
178
+ */
179
+
180
+ /**
181
+ * Vim-style navigation bindings.
182
+ *
183
+ * Includes:
184
+ * - h/j/k/l for directional movement
185
+ * - gg/G for first/last
186
+ * - / and : for search/command
187
+ * - i for insert mode
188
+ * - enter/escape/q for select/back/quit
189
+ *
190
+ * @example
191
+ * ```tsx
192
+ * const keyboard = createKeyboardManager({
193
+ * bindings: VIM_BINDINGS,
194
+ * onAction: handleAction
195
+ * })
196
+ * ```
197
+ */
198
+ declare const VIM_BINDINGS: KeyBindings;
199
+ /**
200
+ * Arrow key navigation bindings.
201
+ *
202
+ * Maps arrow keys to directional movement actions.
203
+ */
204
+ declare const ARROW_BINDINGS: KeyBindings;
205
+ /**
206
+ * Common UI bindings for Enter, Escape, Tab, and Space.
207
+ *
208
+ * Maps common interaction keys to semantic actions:
209
+ * - enter: 'select'
210
+ * - escape: 'back'
211
+ * - tab/shift+tab: focus navigation
212
+ * - space: 'toggle'
213
+ */
214
+ declare const COMMON_BINDINGS: KeyBindings;
215
+ /**
216
+ * Emacs-style navigation bindings.
217
+ *
218
+ * Includes:
219
+ * - ctrl+f/b/n/p for forward/back/next/previous
220
+ * - ctrl+a/e for start/end of line
221
+ * - ctrl+g for cancel
222
+ */
223
+ declare const EMACS_BINDINGS: KeyBindings;
224
+
225
+ /**
226
+ * @mdxui/terminal Type Definitions
227
+ *
228
+ * Branded types and type utilities for type-safe terminal components.
229
+ *
230
+ * @packageDocumentation
231
+ */
232
+ /**
233
+ * Brand symbol for FocusId type.
234
+ * Used to create a nominal/branded type that prevents accidental string usage.
235
+ */
236
+ declare const FocusIdBrand: unique symbol;
237
+ /**
238
+ * Branded type for focus element IDs.
239
+ *
240
+ * This is a nominal/branded type that appears as a string at runtime but
241
+ * provides compile-time type safety. You cannot accidentally pass an
242
+ * arbitrary string where a FocusId is expected.
243
+ *
244
+ * @example
245
+ * ```tsx
246
+ * import { createFocusId, type FocusId } from '@mdxui/terminal'
247
+ *
248
+ * // Correct - use createFocusId to get a valid FocusId
249
+ * const id: FocusId = createFocusId('my-element')
250
+ *
251
+ * // Error - cannot assign plain string to FocusId
252
+ * const badId: FocusId = 'some-string' // TypeScript error!
253
+ * ```
254
+ */
255
+ type FocusId = string & {
256
+ readonly [FocusIdBrand]: true;
257
+ };
258
+ /**
259
+ * Creates a branded FocusId from an optional string.
260
+ *
261
+ * If no id is provided, generates a unique id like `focus-1`, `focus-2`, etc.
262
+ * The returned value is typed as FocusId, which provides compile-time
263
+ * safety against accidentally using wrong strings.
264
+ *
265
+ * @param id - Optional custom ID string. If not provided, auto-generates one.
266
+ * @returns A branded FocusId that can be used with focus management APIs.
267
+ *
268
+ * @example
269
+ * ```tsx
270
+ * import { createFocusId } from '@mdxui/terminal'
271
+ *
272
+ * // Auto-generate an ID
273
+ * const autoId = createFocusId() // 'focus-1', 'focus-2', etc.
274
+ *
275
+ * // Use a custom ID
276
+ * const customId = createFocusId('submit-button')
277
+ *
278
+ * // Use with useFocus
279
+ * const focusable = useFocus({ id: 'my-element' })
280
+ * console.log(focusable.id) // FocusId typed
281
+ * ```
282
+ */
283
+ declare function createFocusId(id?: string): FocusId;
284
+ /**
285
+ * Type guard to check if a value is a valid FocusId.
286
+ *
287
+ * At runtime, FocusId is just a string, so this check validates that
288
+ * the value is a non-empty string. For compile-time safety, use the
289
+ * branded type system instead.
290
+ *
291
+ * @param value - Value to check
292
+ * @returns True if value could be a valid FocusId
293
+ *
294
+ * @example
295
+ * ```tsx
296
+ * const maybeId: unknown = getUserInput()
297
+ * if (isFocusId(maybeId)) {
298
+ * // maybeId is now typed as FocusId
299
+ * focusManager.focusById(maybeId)
300
+ * }
301
+ * ```
302
+ */
303
+ declare function isFocusId(value: unknown): value is FocusId;
304
+ /**
305
+ * Resets the focus ID counter. For testing purposes only.
306
+ * @internal
307
+ */
308
+ declare function __resetFocusIdCounter(): void;
309
+
310
+ /**
311
+ * Focus Management System
312
+ *
313
+ * React hooks and context for managing focus state across terminal UI components.
314
+ * Provides focus tracking, navigation, and keyboard integration.
315
+ *
316
+ * @packageDocumentation
317
+ */
318
+
319
+ /**
320
+ * Options for the useKeyboard hook.
321
+ */
322
+ interface UseKeyboardOptions {
323
+ /** Whether keyboard handling is enabled (default: true) */
324
+ enabled?: boolean;
325
+ /** Priority for keyboard event handling (higher wins) */
326
+ priority?: number;
327
+ }
328
+ /**
329
+ * Return value from the useKeyboard hook.
330
+ */
331
+ interface UseKeyboardResult {
332
+ /** Whether keyboard handling is currently enabled */
333
+ enabled: boolean;
334
+ /** Current priority level */
335
+ priority: number;
336
+ /** Enable keyboard handling */
337
+ enable: () => void;
338
+ /** Disable keyboard handling */
339
+ disable: () => void;
340
+ /** Cleanup function (called on unmount) */
341
+ cleanup: () => void;
342
+ }
343
+ /**
344
+ * React hook for handling keyboard input with modifier key support.
345
+ *
346
+ * Provides a handler that receives key presses along with modifier state.
347
+ * Useful for building custom keyboard interaction patterns.
348
+ *
349
+ * @param handler - Callback receiving key name and modifier state
350
+ * @param options - Configuration options
351
+ * @returns Controls for enabling/disabling keyboard handling
352
+ *
353
+ * @example
354
+ * ```tsx
355
+ * function MyComponent() {
356
+ * const keyboard = useKeyboard((key, modifiers) => {
357
+ * if (modifiers.ctrl && key === 'c') {
358
+ * handleCopy()
359
+ * }
360
+ * })
361
+ *
362
+ * return <div>...</div>
363
+ * }
364
+ * ```
365
+ */
366
+ declare function useKeyboard(handler: (key: string, modifiers: KeyModifiers) => void, options?: UseKeyboardOptions): UseKeyboardResult;
367
+ /**
368
+ * Options for the useFocus hook.
369
+ */
370
+ interface UseFocusOptions {
371
+ /** Custom ID for the focusable element */
372
+ id?: string;
373
+ /** Whether to focus on mount (default: false) */
374
+ autoFocus?: boolean;
375
+ /** Tab order index */
376
+ tabIndex?: number;
377
+ /** Callback when element receives focus */
378
+ onFocus?: () => void;
379
+ /** Callback when element loses focus */
380
+ onBlur?: () => void;
381
+ }
382
+ /**
383
+ * Interface for a focusable element returned by useFocus.
384
+ */
385
+ interface FocusableElement {
386
+ /** Unique ID for this focusable element */
387
+ id: FocusId;
388
+ /** Whether this element currently has focus */
389
+ focused: boolean;
390
+ /** Tab order index */
391
+ tabIndex: number;
392
+ /** Programmatically focus this element */
393
+ focus: () => void;
394
+ /** Programmatically blur this element */
395
+ blur: () => void;
396
+ /** Move focus to the next focusable element */
397
+ focusNext: () => void;
398
+ /** Move focus to the previous focusable element */
399
+ focusPrev: () => void;
400
+ /** Move focus to the first focusable element */
401
+ focusFirst: () => void;
402
+ /** Move focus to the last focusable element */
403
+ focusLast: () => void;
404
+ }
405
+ /**
406
+ * React hook for focus management in terminal UIs.
407
+ *
408
+ * Provides focus state and navigation helpers for building
409
+ * accessible keyboard-navigable interfaces.
410
+ *
411
+ * @param options - Configuration options
412
+ * @returns Focus state and control methods
413
+ *
414
+ * @example
415
+ * ```tsx
416
+ * function MenuItem({ label }: { label: string }) {
417
+ * const { focused, focus, blur } = useFocus({
418
+ * onFocus: () => console.log('focused'),
419
+ * onBlur: () => console.log('blurred')
420
+ * })
421
+ *
422
+ * return (
423
+ * <Text color={focused ? 'primary' : undefined}>
424
+ * {focused ? '> ' : ' '}{label}
425
+ * </Text>
426
+ * )
427
+ * }
428
+ * ```
429
+ */
430
+ declare function useFocus(options?: UseFocusOptions): FocusableElement;
431
+ /**
432
+ * State and controls from the focus manager context.
433
+ */
434
+ interface FocusManagerState {
435
+ /** IDs of all registered focusable elements */
436
+ focusableIds: FocusId[];
437
+ /** ID of the currently focused element, or null */
438
+ focusedId: FocusId | null;
439
+ /** Whether focus is trapped within a container */
440
+ isTrapped: boolean;
441
+ /** Focus a specific element by ID */
442
+ focusById: (id: FocusId) => void;
443
+ /** Move focus to the next element */
444
+ focusNext: () => void;
445
+ /** Move focus to the previous element */
446
+ focusPrev: () => void;
447
+ /** Move focus to the first element */
448
+ focusFirst: () => void;
449
+ /** Move focus to the last element */
450
+ focusLast: () => void;
451
+ /** Register a focusable element with the provider */
452
+ registerFocusable: (id: FocusId, tabIndex: number) => void;
453
+ /** Unregister a focusable element from the provider */
454
+ unregisterFocusable: (id: FocusId) => void;
455
+ }
456
+ /**
457
+ * React context for focus manager state.
458
+ */
459
+ declare const FocusContext: React__default.Context<FocusManagerState | null>;
460
+ /**
461
+ * React hook to access the focus manager context.
462
+ *
463
+ * Must be used within a FocusProvider. Returns a default
464
+ * no-op implementation if used outside a provider.
465
+ *
466
+ * @returns Focus manager state and controls
467
+ *
468
+ * @example
469
+ * ```tsx
470
+ * function NavigationHelp() {
471
+ * const { focusFirst, focusLast } = useFocusManager()
472
+ *
473
+ * return (
474
+ * <Box>
475
+ * <Button onPress={focusFirst}>Go to start</Button>
476
+ * <Button onPress={focusLast}>Go to end</Button>
477
+ * </Box>
478
+ * )
479
+ * }
480
+ * ```
481
+ */
482
+ declare function useFocusManager(): FocusManagerState;
483
+ /**
484
+ * Options for the useNavigableList hook.
485
+ */
486
+ interface UseNavigableListOptions<T> {
487
+ /** Array of items to navigate */
488
+ items: T[];
489
+ /** Initial selected index (default: 0) */
490
+ initialIndex?: number;
491
+ /** Wrap around at list boundaries (default: false) */
492
+ wrap?: boolean;
493
+ /** Enable keyboard navigation (default: false) */
494
+ useKeyboard?: boolean;
495
+ /** Callback when an item is selected */
496
+ onSelect?: (item: T, index: number) => void;
497
+ }
498
+ /**
499
+ * Return value from the useNavigableList hook.
500
+ */
501
+ interface UseNavigableListResult<T> {
502
+ /** Current selected index */
503
+ currentIndex: number;
504
+ /** Current selected item */
505
+ currentItem: T | undefined;
506
+ /** Whether wrapping is enabled */
507
+ wrap: boolean;
508
+ /** Whether keyboard navigation is enabled */
509
+ keyboardEnabled: boolean;
510
+ /** Move selection up (decrease index) */
511
+ moveUp: () => void;
512
+ /** Move selection down (increase index) */
513
+ moveDown: () => void;
514
+ /** Move selection to the first item */
515
+ moveToFirst: () => void;
516
+ /** Move selection to the last item */
517
+ moveToLast: () => void;
518
+ /** Set the selection to a specific index */
519
+ setIndex: (index: number) => void;
520
+ }
521
+ /**
522
+ * React hook for keyboard-navigable lists.
523
+ *
524
+ * Manages selection state and provides navigation methods
525
+ * for building interactive list interfaces.
526
+ *
527
+ * @param options - Configuration options
528
+ * @returns Selection state and navigation controls
529
+ *
530
+ * @example
531
+ * ```tsx
532
+ * function Menu() {
533
+ * const items = ['File', 'Edit', 'View', 'Help']
534
+ * const { currentIndex, moveUp, moveDown } = useNavigableList({
535
+ * items,
536
+ * wrap: true,
537
+ * onSelect: (item) => console.log('Selected:', item)
538
+ * })
539
+ *
540
+ * return (
541
+ * <List items={items} selectedIndex={currentIndex} />
542
+ * )
543
+ * }
544
+ * ```
545
+ */
546
+ declare function useNavigableList<T>(options: UseNavigableListOptions<T>): UseNavigableListResult<T>;
547
+ /**
548
+ * Options for the useNavigableGrid hook.
549
+ */
550
+ interface UseNavigableGridOptions {
551
+ /** Number of rows in the grid */
552
+ rows: number;
553
+ /** Number of columns in the grid */
554
+ cols: number;
555
+ /** Initial row (default: 0) */
556
+ initialRow?: number;
557
+ /** Initial column (default: 0) */
558
+ initialCol?: number;
559
+ /** Wrap horizontally at column boundaries (default: false) */
560
+ wrapHorizontal?: boolean;
561
+ /** Wrap vertically at row boundaries (default: false) */
562
+ wrapVertical?: boolean;
563
+ /** Enable keyboard navigation (default: false) */
564
+ useKeyboard?: boolean;
565
+ }
566
+ /**
567
+ * Return value from the useNavigableGrid hook.
568
+ */
569
+ interface UseNavigableGridResult {
570
+ /** Current row position */
571
+ row: number;
572
+ /** Current column position */
573
+ col: number;
574
+ /** Whether horizontal wrapping is enabled */
575
+ wrapHorizontal: boolean;
576
+ /** Whether vertical wrapping is enabled */
577
+ wrapVertical: boolean;
578
+ /** Whether keyboard navigation is enabled */
579
+ keyboardEnabled: boolean;
580
+ /** Move up one row */
581
+ moveUp: () => void;
582
+ /** Move down one row */
583
+ moveDown: () => void;
584
+ /** Move left one column */
585
+ moveLeft: () => void;
586
+ /** Move right one column */
587
+ moveRight: () => void;
588
+ /** Move to a specific cell */
589
+ moveToCell: (row: number, col: number) => void;
590
+ }
591
+ /**
592
+ * React hook for keyboard-navigable grids.
593
+ *
594
+ * Manages 2D position state and provides navigation methods
595
+ * for building grid-based interactive interfaces.
596
+ *
597
+ * @param options - Configuration options
598
+ * @returns Position state and navigation controls
599
+ *
600
+ * @example
601
+ * ```tsx
602
+ * function Calendar() {
603
+ * const { row, col, moveUp, moveDown, moveLeft, moveRight } = useNavigableGrid({
604
+ * rows: 5,
605
+ * cols: 7,
606
+ * wrapHorizontal: true
607
+ * })
608
+ *
609
+ * // Render 5x7 calendar grid with selection at [row, col]
610
+ * }
611
+ * ```
612
+ */
613
+ declare function useNavigableGrid(options: UseNavigableGridOptions): UseNavigableGridResult;
614
+ /**
615
+ * Props for the FocusProvider component.
616
+ */
617
+ interface FocusProviderProps {
618
+ /** Child components */
619
+ children?: ReactNode;
620
+ /** Trap focus within this provider (default: false) */
621
+ trap?: boolean;
622
+ /** Wrap focus when reaching boundaries (default: false) */
623
+ wrapFocus?: boolean;
624
+ /** ID of element to focus initially */
625
+ initialFocus?: FocusId;
626
+ /** Focus first element on mount (default: false) */
627
+ focusFirstOnMount?: boolean;
628
+ /** Restore focus to previous element when provider unmounts */
629
+ restoreFocus?: boolean;
630
+ /** Group name for nested focus management */
631
+ group?: string;
632
+ }
633
+ /**
634
+ * Focus provider component for managing focus state across components.
635
+ *
636
+ * Provides focus management context to child components, enabling
637
+ * coordinated focus navigation within a container.
638
+ *
639
+ * **Features:**
640
+ * - Focus tracking across registered focusable elements
641
+ * - Focus trapping for modals and dialogs
642
+ * - Wrap-around navigation at boundaries
643
+ * - Initial focus and focus restoration support
644
+ * - Named focus groups for scoped management
645
+ *
646
+ * @param props - Configuration and children
647
+ * @returns React element with focus context
648
+ *
649
+ * @example
650
+ * ```tsx
651
+ * function Dialog() {
652
+ * return (
653
+ * <FocusProvider trap focusFirstOnMount>
654
+ * <Input label="Name" />
655
+ * <Input label="Email" />
656
+ * <Button>Submit</Button>
657
+ * </FocusProvider>
658
+ * )
659
+ * }
660
+ * ```
661
+ */
662
+ declare function FocusProvider(props: FocusProviderProps): ReactElement;
663
+
664
+ /**
665
+ * Terminal Input Integration
666
+ *
667
+ * Integration helpers for connecting keyboard managers to terminal input sources.
668
+ * Supports Node.js readline and OpenTUI key events.
669
+ *
670
+ * @packageDocumentation
671
+ */
672
+
673
+ /**
674
+ * Normalized key event structure for keyboard handling.
675
+ *
676
+ * This is the standardized format used internally by the keyboard manager.
677
+ * Input from various sources (readline, OpenTUI) is normalized to this format.
678
+ */
679
+ interface NormalizedKey {
680
+ /** The key name (e.g., 'a', 'enter', 'up', 'escape') */
681
+ name: string;
682
+ /** Whether Ctrl was held */
683
+ ctrl: boolean;
684
+ /** Whether Alt/Option was held */
685
+ alt: boolean;
686
+ /** Whether Shift was held */
687
+ shift: boolean;
688
+ /** Whether Meta/Cmd was held */
689
+ meta: boolean;
690
+ /** Raw character sequence if available */
691
+ sequence?: string;
692
+ }
693
+ /**
694
+ * Readline key event structure from Node.js readline module.
695
+ * @see https://nodejs.org/api/readline.html#event-keypress
696
+ */
697
+ interface ReadlineKey {
698
+ /** Key name */
699
+ name?: string;
700
+ /** Whether Ctrl was held */
701
+ ctrl?: boolean;
702
+ /** Whether Meta/Cmd was held */
703
+ meta?: boolean;
704
+ /** Whether Shift was held */
705
+ shift?: boolean;
706
+ /** Raw sequence */
707
+ sequence?: string;
708
+ }
709
+ /**
710
+ * Normalizes a readline key event to our standard NormalizedKey format.
711
+ *
712
+ * @param str - The character string from the keypress event
713
+ * @param key - The readline key object
714
+ * @returns Normalized key event
715
+ *
716
+ * @example
717
+ * ```typescript
718
+ * import { emitKeypressEvents } from 'readline'
719
+ *
720
+ * emitKeypressEvents(process.stdin)
721
+ * process.stdin.on('keypress', (str, key) => {
722
+ * const normalized = normalizeReadlineKey(str, key)
723
+ * console.log(normalized) // { name: 'a', ctrl: false, ... }
724
+ * })
725
+ * ```
726
+ */
727
+ declare function normalizeReadlineKey(str: string | undefined, key: ReadlineKey | undefined): NormalizedKey;
728
+ /**
729
+ * Converts a NormalizedKey to a string format for binding lookup.
730
+ *
731
+ * Produces strings like:
732
+ * - 'a' (plain key)
733
+ * - 'ctrl+c' (with ctrl modifier)
734
+ * - 'shift+tab' (with shift modifier)
735
+ * - 'ctrl+shift+s' (combined modifiers)
736
+ *
737
+ * @param key - The normalized key event
738
+ * @returns String representation for binding lookup
739
+ *
740
+ * @example
741
+ * ```typescript
742
+ * const key: NormalizedKey = { name: 'c', ctrl: true, alt: false, shift: false, meta: false }
743
+ * console.log(keyToBindingString(key)) // 'ctrl+c'
744
+ * ```
745
+ */
746
+ declare function keyToBindingString(key: NormalizedKey): string;
747
+ /**
748
+ * Configuration for attaching a keyboard manager to terminal input.
749
+ */
750
+ interface AttachKeyboardOptions {
751
+ /** Custom input stream (defaults to process.stdin) */
752
+ input?: NodeJS.ReadStream;
753
+ /** Whether to exit on Ctrl+C (defaults to true) */
754
+ exitOnCtrlC?: boolean;
755
+ }
756
+ /**
757
+ * Cleanup function returned by attachKeyboardManager.
758
+ * Call this to detach the keyboard manager from input.
759
+ */
760
+ type DetachKeyboard = () => void;
761
+ /**
762
+ * Attaches a keyboard manager to terminal stdin for receiving key events.
763
+ *
764
+ * This function sets up raw mode on stdin and processes keypress events,
765
+ * normalizing them and passing them to the keyboard manager.
766
+ *
767
+ * **Important:** This function requires a TTY stdin. It will throw if
768
+ * stdin is not a TTY (e.g., when input is piped).
769
+ *
770
+ * @param manager - The keyboard manager to receive key events
771
+ * @param options - Configuration options
772
+ * @returns A cleanup function to detach the keyboard manager
773
+ *
774
+ * @example
775
+ * ```typescript
776
+ * import { createKeyboardManager, attachKeyboardManager, VIM_BINDINGS } from '@mdxui/terminal'
777
+ *
778
+ * const manager = createKeyboardManager({
779
+ * bindings: VIM_BINDINGS,
780
+ * onAction: (action) => console.log('Action:', action),
781
+ * })
782
+ *
783
+ * const detach = attachKeyboardManager(manager)
784
+ *
785
+ * // Later, to clean up:
786
+ * detach()
787
+ * ```
788
+ *
789
+ * @example
790
+ * ```typescript
791
+ * // With custom options
792
+ * const detach = attachKeyboardManager(manager, {
793
+ * exitOnCtrlC: false, // Don't exit on Ctrl+C, let manager handle it
794
+ * })
795
+ * ```
796
+ */
797
+ declare function attachKeyboardManager(manager: KeyboardManager, options?: AttachKeyboardOptions): DetachKeyboard;
798
+ /**
799
+ * OpenTUI key event structure.
800
+ * Matches the KeyEvent interface from @opentui/core.
801
+ */
802
+ interface OpenTUIKeyEvent {
803
+ /** Key name (e.g., 'a', 'enter', 'escape') */
804
+ name: string;
805
+ /** Ctrl modifier */
806
+ ctrl: boolean;
807
+ /** Meta/Cmd modifier */
808
+ meta: boolean;
809
+ /** Shift modifier */
810
+ shift: boolean;
811
+ /** Option/Alt modifier */
812
+ option: boolean;
813
+ /** Raw sequence */
814
+ sequence: string;
815
+ /** Event type: 'press', 'repeat', or 'release' */
816
+ eventType?: 'press' | 'repeat' | 'release';
817
+ /** Whether this is a repeated key */
818
+ repeated?: boolean;
819
+ }
820
+ /**
821
+ * Normalizes an OpenTUI KeyEvent to our standard NormalizedKey format.
822
+ *
823
+ * @param event - The OpenTUI KeyEvent
824
+ * @returns Normalized key event
825
+ *
826
+ * @example
827
+ * ```typescript
828
+ * import { useKeyboard } from '@opentui/react'
829
+ *
830
+ * useKeyboard((event) => {
831
+ * const normalized = normalizeOpenTUIKey(event)
832
+ * manager.handleKey(keyToBindingString(normalized))
833
+ * })
834
+ * ```
835
+ */
836
+ declare function normalizeOpenTUIKey(event: OpenTUIKeyEvent): NormalizedKey;
837
+ /**
838
+ * Creates a keyboard event handler for use with OpenTUI's useKeyboard hook.
839
+ *
840
+ * This function returns a handler that can be passed directly to OpenTUI's
841
+ * useKeyboard hook to connect it to a KeyboardManager.
842
+ *
843
+ * @param manager - The keyboard manager to receive key events
844
+ * @returns A handler function for OpenTUI's useKeyboard hook
845
+ *
846
+ * @example
847
+ * ```tsx
848
+ * import { useKeyboard } from '@opentui/react'
849
+ * import { createKeyboardManager, createOpenTUIKeyHandler, VIM_BINDINGS } from '@mdxui/terminal'
850
+ *
851
+ * function MyComponent() {
852
+ * const manager = useMemo(() => createKeyboardManager({
853
+ * bindings: VIM_BINDINGS,
854
+ * onAction: (action) => console.log('Action:', action),
855
+ * }), [])
856
+ *
857
+ * const handler = useMemo(() => createOpenTUIKeyHandler(manager), [manager])
858
+ *
859
+ * useKeyboard(handler)
860
+ *
861
+ * return <div>...</div>
862
+ * }
863
+ * ```
864
+ */
865
+ declare function createOpenTUIKeyHandler(manager: KeyboardManager): (event: OpenTUIKeyEvent) => void;
866
+
867
+ export { type ActionContext as A, keyToBindingString as B, COMMON_BINDINGS as C, type DetachKeyboard as D, EMACS_BINDINGS as E, type FocusableElement as F, attachKeyboardManager as G, normalizeOpenTUIKey as H, createOpenTUIKeyHandler as I, type FocusId as J, type KeyModifiers as K, createFocusId as L, isFocusId as M, type NormalizedKey as N, type OpenTUIKeyEvent as O, type ReadlineKey as R, type UseKeyboardOptions as U, VIM_BINDINGS as V, __resetFocusIdCounter as _, type KeyboardAction as a, type KeyBindings as b, type ActionHandler as c, type KeyboardManagerOptions as d, type KeyboardManager as e, KEY as f, createKeyboardManager as g, ARROW_BINDINGS as h, type UseKeyboardResult as i, type UseFocusOptions as j, type FocusManagerState as k, type UseNavigableListOptions as l, matchKey as m, type UseNavigableListResult as n, type UseNavigableGridOptions as o, type UseNavigableGridResult as p, type FocusProviderProps as q, FocusContext as r, useFocus as s, useFocusManager as t, useKeyboard as u, useNavigableList as v, useNavigableGrid as w, FocusProvider as x, type AttachKeyboardOptions as y, normalizeReadlineKey as z };