@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,377 @@
1
+ /**
2
+ * Keyboard Manager
3
+ *
4
+ * Core keyboard binding manager for handling key bindings and sequences.
5
+ * Supports single keys, modifier combinations, and multi-key sequences.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ // ============================================================================
11
+ // Types
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Modifier key state for a key press event.
16
+ *
17
+ * Tracks which modifier keys are held during a key press.
18
+ */
19
+ export interface KeyModifiers {
20
+ /** Control key is pressed */
21
+ ctrl: boolean
22
+ /** Alt/Option key is pressed */
23
+ alt: boolean
24
+ /** Shift key is pressed */
25
+ shift: boolean
26
+ /** Meta/Command key is pressed */
27
+ meta: boolean
28
+ }
29
+
30
+ /**
31
+ * A keyboard action - either a string action name or a callback function.
32
+ *
33
+ * String actions are dispatched via the onAction handler.
34
+ * Function actions are called directly when the key is pressed.
35
+ */
36
+ export type KeyboardAction = string | (() => void)
37
+
38
+ /**
39
+ * Maps key names/sequences to actions.
40
+ *
41
+ * Keys can be:
42
+ * - Single characters: 'j', 'k', 'q'
43
+ * - Special keys: 'enter', 'escape', 'tab'
44
+ * - Modifier combinations: 'ctrl+c', 'shift+tab'
45
+ * - Key sequences: 'gg', 'dd' (multi-character without '+')
46
+ */
47
+ export type KeyBindings = Record<string, KeyboardAction>
48
+
49
+ /**
50
+ * Context passed to action handlers with the triggering key and optional extra data.
51
+ */
52
+ export interface ActionContext {
53
+ /** The key or sequence that triggered this action */
54
+ key: string
55
+ /** Optional context data set via setContext() */
56
+ context?: Record<string, unknown>
57
+ }
58
+
59
+ /**
60
+ * Callback invoked when a keyboard action is triggered.
61
+ *
62
+ * @param action - The action name (string actions only)
63
+ * @param context - Context including the key and optional data
64
+ */
65
+ export type ActionHandler = (action: string, context: ActionContext) => void
66
+
67
+ /**
68
+ * Configuration options for creating a keyboard manager.
69
+ */
70
+ export interface KeyboardManagerOptions {
71
+ /** Key-to-action bindings */
72
+ bindings: KeyBindings
73
+ /** Handler called when string actions are triggered */
74
+ onAction?: ActionHandler
75
+ /** Whether the manager starts enabled (default: true) */
76
+ enabled?: boolean
77
+ /** Optional context data passed to action handlers */
78
+ context?: Record<string, unknown> | null
79
+ /** Timeout in ms for key sequences (default: 1000) */
80
+ sequenceTimeout?: number
81
+ }
82
+
83
+ /**
84
+ * Interface for the keyboard manager returned by createKeyboardManager.
85
+ */
86
+ export interface KeyboardManager {
87
+ /** Get the action bound to a specific key */
88
+ getAction(key: string): KeyboardAction | undefined
89
+ /** Handle a key press, returns true if the key was handled */
90
+ handleKey(key: string, handler?: ActionHandler): boolean
91
+ /** Add a new key binding */
92
+ addBinding(key: string, action: KeyboardAction): void
93
+ /** Remove a key binding */
94
+ removeBinding(key: string): void
95
+ /** Replace all bindings */
96
+ setBindings(bindings: KeyBindings): void
97
+ /** Get all string bindings (excludes function bindings) */
98
+ getBindings(): Record<string, string>
99
+ /** Disable the keyboard manager */
100
+ disable(): void
101
+ /** Enable the keyboard manager */
102
+ enable(): void
103
+ /** Toggle enabled state */
104
+ toggle(): void
105
+ /** Check if the manager is enabled */
106
+ isEnabled(): boolean
107
+ /** Get the current pending key sequence */
108
+ getPendingSequence(): string
109
+ /** Set context data passed to action handlers */
110
+ setContext(context: Record<string, unknown>): void
111
+ /** Clean up resources (clears pending sequence timer to prevent memory leaks) */
112
+ destroy(): void
113
+ }
114
+
115
+ // ============================================================================
116
+ // KEY Constants
117
+ // ============================================================================
118
+
119
+ /**
120
+ * Common key constants for keyboard handling.
121
+ * Use these with matchKey() for consistent key comparisons.
122
+ */
123
+ export const KEY = {
124
+ ENTER: 'enter',
125
+ ESCAPE: 'escape',
126
+ UP: 'up',
127
+ DOWN: 'down',
128
+ LEFT: 'left',
129
+ RIGHT: 'right',
130
+ TAB: 'tab',
131
+ SPACE: 'space',
132
+ BACKSPACE: 'backspace',
133
+ DELETE: 'delete',
134
+ } as const
135
+
136
+ /**
137
+ * Check if a key matches an expected key.
138
+ *
139
+ * @param key - The key to check
140
+ * @param expected - The expected key value
141
+ * @returns true if keys match
142
+ *
143
+ * @example
144
+ * ```tsx
145
+ * import { matchKey, KEY } from '@mdxui/terminal'
146
+ *
147
+ * if (matchKey(pressedKey, KEY.ENTER)) {
148
+ * handleSubmit()
149
+ * }
150
+ * ```
151
+ */
152
+ export function matchKey(key: string, expected: string): boolean {
153
+ return key === expected
154
+ }
155
+
156
+ // ============================================================================
157
+ // createKeyboardManager
158
+ // ============================================================================
159
+
160
+ /**
161
+ * Creates a keyboard manager for handling key bindings and sequences.
162
+ *
163
+ * The manager supports:
164
+ * - Single key bindings ('j', 'enter', 'q')
165
+ * - Modifier combinations ('ctrl+c', 'shift+tab')
166
+ * - Multi-key sequences ('gg', 'dd') with configurable timeout
167
+ * - Dynamic binding changes at runtime
168
+ * - Enable/disable toggling
169
+ *
170
+ * @param options - Configuration options
171
+ * @returns A keyboard manager instance
172
+ *
173
+ * @example
174
+ * ```tsx
175
+ * const keyboard = createKeyboardManager({
176
+ * bindings: { ...VIM_BINDINGS, ...ARROW_BINDINGS },
177
+ * onAction: (action, ctx) => {
178
+ * switch (action) {
179
+ * case 'move-down': moveDown(); break
180
+ * case 'select': handleSelect(); break
181
+ * }
182
+ * }
183
+ * })
184
+ *
185
+ * // Later, handle input
186
+ * process.stdin.on('keypress', (ch, key) => {
187
+ * keyboard.handleKey(key.name || ch)
188
+ * })
189
+ * ```
190
+ */
191
+ export function createKeyboardManager(options: KeyboardManagerOptions): KeyboardManager {
192
+ let bindings = { ...options.bindings }
193
+ let enabled = options.enabled !== false
194
+ let context: Record<string, unknown> | null = options.context ?? null
195
+ const onAction = options.onAction
196
+ const sequenceTimeout = options.sequenceTimeout ?? 1000
197
+
198
+ // Track pending key sequence for multi-key bindings like 'gg'
199
+ let pendingSequence = ''
200
+ let sequenceTimer: ReturnType<typeof setTimeout> | null = null
201
+
202
+ // Find all multi-key bindings (sequences)
203
+ function getSequenceBindings(): string[] {
204
+ return Object.keys(bindings).filter((key) => key.length > 1 && !key.includes('+'))
205
+ }
206
+
207
+ // Check if a key could start a sequence
208
+ function startsSequence(key: string): boolean {
209
+ const sequences = getSequenceBindings()
210
+ return sequences.some((seq) => seq.startsWith(key))
211
+ }
212
+
213
+ // Check if a key could continue the pending sequence
214
+ function continuesSequence(key: string): boolean {
215
+ if (!pendingSequence) return false
216
+ const potential = pendingSequence + key
217
+ const sequences = getSequenceBindings()
218
+ return sequences.some((seq) => seq.startsWith(potential))
219
+ }
220
+
221
+ function clearSequence(): void {
222
+ pendingSequence = ''
223
+ if (sequenceTimer) {
224
+ clearTimeout(sequenceTimer)
225
+ sequenceTimer = null
226
+ }
227
+ }
228
+
229
+ function buildActionContext(key: string): ActionContext {
230
+ const actionContext: ActionContext = { key }
231
+ if (context !== null) {
232
+ actionContext.context = context
233
+ }
234
+ return actionContext
235
+ }
236
+
237
+ function handleSequenceTimeout(): void {
238
+ // When sequence times out, try to execute the pending sequence as-is
239
+ if (pendingSequence && bindings[pendingSequence]) {
240
+ const action = bindings[pendingSequence]
241
+ if (typeof action === 'function') {
242
+ action()
243
+ } else if (onAction) {
244
+ onAction(action, buildActionContext(pendingSequence))
245
+ }
246
+ }
247
+ clearSequence()
248
+ }
249
+
250
+ const manager: KeyboardManager = {
251
+ getAction(key: string): KeyboardAction | undefined {
252
+ return bindings[key]
253
+ },
254
+
255
+ handleKey(key: string, handler?: ActionHandler): boolean {
256
+ if (!enabled) return false
257
+
258
+ // Handle escape - clears pending sequence
259
+ if (key === 'escape') {
260
+ if (pendingSequence) {
261
+ clearSequence()
262
+ // Don't trigger escape action if we just cleared a sequence
263
+ return true
264
+ }
265
+ // Fall through to normal handling if no pending sequence
266
+ }
267
+
268
+ // Check if this key could be part of a sequence
269
+ const potentialSequence = pendingSequence + key
270
+
271
+ // Check if the potential sequence matches a binding
272
+ if (bindings[potentialSequence]) {
273
+ clearSequence()
274
+ const action = bindings[potentialSequence]
275
+ if (typeof action === 'function') {
276
+ action()
277
+ } else {
278
+ const effectiveHandler = handler || onAction
279
+ if (effectiveHandler) {
280
+ effectiveHandler(action, buildActionContext(potentialSequence))
281
+ }
282
+ }
283
+ return true
284
+ }
285
+
286
+ // Check if this could continue or start a sequence
287
+ if (continuesSequence(key) || (!pendingSequence && startsSequence(key))) {
288
+ pendingSequence = potentialSequence
289
+
290
+ // Set timeout to execute fallback or clear sequence
291
+ if (sequenceTimer) clearTimeout(sequenceTimer)
292
+ sequenceTimer = setTimeout(handleSequenceTimeout, sequenceTimeout)
293
+
294
+ return true
295
+ }
296
+
297
+ // Not a sequence - check for direct binding
298
+ if (pendingSequence) {
299
+ // Had a pending sequence but this key doesn't continue it
300
+ // Clear and don't handle
301
+ clearSequence()
302
+ }
303
+
304
+ const action = bindings[key]
305
+ if (action === undefined) {
306
+ return false
307
+ }
308
+
309
+ if (typeof action === 'function') {
310
+ action()
311
+ } else {
312
+ const effectiveHandler = handler || onAction
313
+ if (effectiveHandler) {
314
+ effectiveHandler(action, buildActionContext(key))
315
+ }
316
+ }
317
+
318
+ return true
319
+ },
320
+
321
+ addBinding(key: string, action: KeyboardAction): void {
322
+ bindings[key] = action
323
+ },
324
+
325
+ removeBinding(key: string): void {
326
+ delete bindings[key]
327
+ },
328
+
329
+ setBindings(newBindings: KeyBindings): void {
330
+ bindings = { ...newBindings }
331
+ },
332
+
333
+ getBindings(): Record<string, string> {
334
+ const result: Record<string, string> = {}
335
+ for (const [key, action] of Object.entries(bindings)) {
336
+ if (typeof action === 'string') {
337
+ result[key] = action
338
+ }
339
+ }
340
+ return result
341
+ },
342
+
343
+ disable(): void {
344
+ enabled = false
345
+ },
346
+
347
+ enable(): void {
348
+ enabled = true
349
+ },
350
+
351
+ toggle(): void {
352
+ enabled = !enabled
353
+ },
354
+
355
+ isEnabled(): boolean {
356
+ return enabled
357
+ },
358
+
359
+ getPendingSequence(): string {
360
+ return pendingSequence
361
+ },
362
+
363
+ setContext(newContext: Record<string, unknown>): void {
364
+ context = newContext
365
+ },
366
+
367
+ destroy(): void {
368
+ if (sequenceTimer) {
369
+ clearTimeout(sequenceTimer)
370
+ sequenceTimer = null
371
+ }
372
+ pendingSequence = ''
373
+ },
374
+ }
375
+
376
+ return manager
377
+ }
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Preset Key Bindings
3
+ *
4
+ * Common keyboard binding presets for terminal applications.
5
+ * Includes Vim-style, arrow key, and common UI bindings.
6
+ *
7
+ * @packageDocumentation
8
+ */
9
+
10
+ import type { KeyBindings } from './manager'
11
+
12
+ /**
13
+ * Vim-style navigation bindings.
14
+ *
15
+ * Includes:
16
+ * - h/j/k/l for directional movement
17
+ * - gg/G for first/last
18
+ * - / and : for search/command
19
+ * - i for insert mode
20
+ * - enter/escape/q for select/back/quit
21
+ *
22
+ * @example
23
+ * ```tsx
24
+ * const keyboard = createKeyboardManager({
25
+ * bindings: VIM_BINDINGS,
26
+ * onAction: handleAction
27
+ * })
28
+ * ```
29
+ */
30
+ export const VIM_BINDINGS: KeyBindings = {
31
+ h: 'move-left',
32
+ j: 'move-down',
33
+ k: 'move-up',
34
+ l: 'move-right',
35
+ gg: 'move-first',
36
+ G: 'move-last',
37
+ '/': 'search',
38
+ ':': 'command',
39
+ i: 'insert',
40
+ enter: 'select',
41
+ escape: 'back',
42
+ q: 'quit',
43
+ }
44
+
45
+ /**
46
+ * Arrow key navigation bindings.
47
+ *
48
+ * Maps arrow keys to directional movement actions.
49
+ */
50
+ export const ARROW_BINDINGS: KeyBindings = {
51
+ up: 'move-up',
52
+ down: 'move-down',
53
+ left: 'move-left',
54
+ right: 'move-right',
55
+ }
56
+
57
+ /**
58
+ * Common UI bindings for Enter, Escape, Tab, and Space.
59
+ *
60
+ * Maps common interaction keys to semantic actions:
61
+ * - enter: 'select'
62
+ * - escape: 'back'
63
+ * - tab/shift+tab: focus navigation
64
+ * - space: 'toggle'
65
+ */
66
+ export const COMMON_BINDINGS: KeyBindings = {
67
+ enter: 'select',
68
+ escape: 'back',
69
+ tab: 'focus-next',
70
+ 'shift+tab': 'focus-prev',
71
+ space: 'toggle',
72
+ }
73
+
74
+ /**
75
+ * Emacs-style navigation bindings.
76
+ *
77
+ * Includes:
78
+ * - ctrl+f/b/n/p for forward/back/next/previous
79
+ * - ctrl+a/e for start/end of line
80
+ * - ctrl+g for cancel
81
+ */
82
+ export const EMACS_BINDINGS: KeyBindings = {
83
+ 'ctrl+f': 'move-right',
84
+ 'ctrl+b': 'move-left',
85
+ 'ctrl+n': 'move-down',
86
+ 'ctrl+p': 'move-up',
87
+ 'ctrl+a': 'move-first',
88
+ 'ctrl+e': 'move-last',
89
+ 'ctrl+g': 'back',
90
+ }