@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.
- package/README.md +571 -0
- package/dist/ansi-css-Sk5mWtdK.d.ts +119 -0
- package/dist/ansi-css-V6JIHGsM.d.ts +119 -0
- package/dist/ansi-css-_3eSEU9d.d.ts +119 -0
- package/dist/chunk-3EFDH7PK.js +5235 -0
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/chunk-3X5IR6WE.js +884 -0
- package/dist/chunk-4FV5ZDCE.js +5236 -0
- package/dist/chunk-4OVMSF2J.js +243 -0
- package/dist/chunk-63FEETIS.js +4048 -0
- package/dist/chunk-B43KP7XJ.js +884 -0
- package/dist/chunk-BMTJXWUV.js +655 -0
- package/dist/chunk-C3SVH4N7.js +882 -0
- package/dist/chunk-EVWR7Y47.js +874 -0
- package/dist/chunk-F6A5VWUC.js +1285 -0
- package/dist/chunk-FD7KW7GE.js +882 -0
- package/dist/chunk-GBQ6UD6I.js +655 -0
- package/dist/chunk-GMDD3M6U.js +5227 -0
- package/dist/chunk-JBHRXOXM.js +1058 -0
- package/dist/chunk-JFOO3EYO.js +1182 -0
- package/dist/chunk-JQ5H3WXL.js +1291 -0
- package/dist/chunk-JQD5NASE.js +234 -0
- package/dist/chunk-KRHJP5R7.js +592 -0
- package/dist/chunk-KWF6WVJE.js +962 -0
- package/dist/chunk-LHYQVN3H.js +1038 -0
- package/dist/chunk-M3TLQLGC.js +1032 -0
- package/dist/chunk-MVW4Q5OP.js +240 -0
- package/dist/chunk-NXCZSWLU.js +1294 -0
- package/dist/chunk-O25TNRO6.js +607 -0
- package/dist/chunk-PNECDA2I.js +884 -0
- package/dist/chunk-QIHWRLJR.js +962 -0
- package/dist/chunk-QW5YMQ7K.js +882 -0
- package/dist/chunk-R5U7XKVJ.js +16 -0
- package/dist/chunk-RP2MVQLR.js +962 -0
- package/dist/chunk-TP6RXGXA.js +1087 -0
- package/dist/chunk-TQQSTITZ.js +655 -0
- package/dist/chunk-X24GWXQV.js +1281 -0
- package/dist/components/index.d.ts +802 -0
- package/dist/components/index.js +149 -0
- package/dist/data/index.d.ts +2554 -0
- package/dist/data/index.js +51 -0
- package/dist/forms/index.d.ts +1596 -0
- package/dist/forms/index.js +464 -0
- package/dist/index-CQRFZntR.d.ts +867 -0
- package/dist/index.d.ts +579 -0
- package/dist/index.js +786 -0
- package/dist/interactive-D0JkWosD.d.ts +217 -0
- package/dist/keyboard/index.d.ts +2 -0
- package/dist/keyboard/index.js +43 -0
- package/dist/renderers/index.d.ts +546 -0
- package/dist/renderers/index.js +2157 -0
- package/dist/storybook/index.d.ts +396 -0
- package/dist/storybook/index.js +641 -0
- package/dist/theme/index.d.ts +1339 -0
- package/dist/theme/index.js +123 -0
- package/dist/types-Bxu5PAgA.d.ts +710 -0
- package/dist/types-CIlop5Ji.d.ts +701 -0
- package/dist/types-Ca8p_p5X.d.ts +710 -0
- package/package.json +90 -0
- package/src/__tests__/components/data/card.test.ts +458 -0
- package/src/__tests__/components/data/list.test.ts +473 -0
- package/src/__tests__/components/data/metrics.test.ts +541 -0
- package/src/__tests__/components/data/table.test.ts +448 -0
- package/src/__tests__/components/input/field.test.ts +555 -0
- package/src/__tests__/components/input/form.test.ts +870 -0
- package/src/__tests__/components/input/search.test.ts +1238 -0
- package/src/__tests__/components/input/select.test.ts +658 -0
- package/src/__tests__/components/navigation/breadcrumb.test.ts +923 -0
- package/src/__tests__/components/navigation/command-palette.test.ts +1095 -0
- package/src/__tests__/components/navigation/sidebar.test.ts +1018 -0
- package/src/__tests__/components/navigation/tabs.test.ts +995 -0
- package/src/__tests__/components.test.tsx +1197 -0
- package/src/__tests__/core/compiler.test.ts +986 -0
- package/src/__tests__/core/parser.test.ts +785 -0
- package/src/__tests__/core/tier-switcher.test.ts +1103 -0
- package/src/__tests__/core/types.test.ts +1398 -0
- package/src/__tests__/data/collections.test.ts +1337 -0
- package/src/__tests__/data/db.test.ts +1265 -0
- package/src/__tests__/data/reactive.test.ts +1010 -0
- package/src/__tests__/data/sync.test.ts +1614 -0
- package/src/__tests__/errors.test.ts +660 -0
- package/src/__tests__/forms/integration.test.ts +444 -0
- package/src/__tests__/integration.test.ts +905 -0
- package/src/__tests__/keyboard.test.ts +1791 -0
- package/src/__tests__/renderer.test.ts +489 -0
- package/src/__tests__/renderers/ansi-css.test.ts +948 -0
- package/src/__tests__/renderers/ansi.test.ts +1366 -0
- package/src/__tests__/renderers/ascii.test.ts +1360 -0
- package/src/__tests__/renderers/interactive.test.ts +2353 -0
- package/src/__tests__/renderers/markdown.test.ts +1483 -0
- package/src/__tests__/renderers/text.test.ts +1369 -0
- package/src/__tests__/renderers/unicode.test.ts +1307 -0
- package/src/__tests__/theme.test.ts +639 -0
- package/src/__tests__/utils/assertions.ts +685 -0
- package/src/__tests__/utils/index.ts +115 -0
- package/src/__tests__/utils/test-renderer.ts +381 -0
- package/src/__tests__/utils/utils.test.ts +560 -0
- package/src/components/containers/card.ts +56 -0
- package/src/components/containers/dialog.ts +53 -0
- package/src/components/containers/index.ts +9 -0
- package/src/components/containers/panel.ts +59 -0
- package/src/components/feedback/badge.ts +40 -0
- package/src/components/feedback/index.ts +8 -0
- package/src/components/feedback/spinner.ts +23 -0
- package/src/components/helpers.ts +81 -0
- package/src/components/index.ts +153 -0
- package/src/components/layout/breadcrumb.ts +31 -0
- package/src/components/layout/index.ts +10 -0
- package/src/components/layout/list.ts +29 -0
- package/src/components/layout/sidebar.ts +79 -0
- package/src/components/layout/table.ts +62 -0
- package/src/components/primitives/box.ts +95 -0
- package/src/components/primitives/button.ts +54 -0
- package/src/components/primitives/index.ts +11 -0
- package/src/components/primitives/input.ts +88 -0
- package/src/components/primitives/select.ts +97 -0
- package/src/components/primitives/text.ts +60 -0
- package/src/components/render.ts +155 -0
- package/src/components/templates/app.ts +43 -0
- package/src/components/templates/index.ts +8 -0
- package/src/components/templates/site.ts +54 -0
- package/src/components/types.ts +777 -0
- package/src/core/compiler.ts +718 -0
- package/src/core/parser.ts +127 -0
- package/src/core/tier-switcher.ts +607 -0
- package/src/core/types.ts +672 -0
- package/src/data/collection.ts +316 -0
- package/src/data/collections.ts +50 -0
- package/src/data/context.tsx +174 -0
- package/src/data/db.ts +127 -0
- package/src/data/hooks.ts +532 -0
- package/src/data/index.ts +138 -0
- package/src/data/reactive.ts +1225 -0
- package/src/data/saas-collections.ts +375 -0
- package/src/data/sync.ts +1213 -0
- package/src/data/types.ts +660 -0
- package/src/forms/converters.ts +512 -0
- package/src/forms/index.ts +133 -0
- package/src/forms/schemas.ts +403 -0
- package/src/forms/types.ts +476 -0
- package/src/index.ts +542 -0
- package/src/keyboard/focus.ts +748 -0
- package/src/keyboard/index.ts +96 -0
- package/src/keyboard/integration.ts +371 -0
- package/src/keyboard/manager.ts +377 -0
- package/src/keyboard/presets.ts +90 -0
- package/src/renderers/ansi-css.ts +576 -0
- package/src/renderers/ansi.ts +802 -0
- package/src/renderers/ascii.ts +680 -0
- package/src/renderers/breadcrumb.ts +480 -0
- package/src/renderers/command-palette.ts +802 -0
- package/src/renderers/components/field.ts +210 -0
- package/src/renderers/components/form.ts +327 -0
- package/src/renderers/components/index.ts +21 -0
- package/src/renderers/components/search.ts +449 -0
- package/src/renderers/components/select.ts +222 -0
- package/src/renderers/index.ts +101 -0
- package/src/renderers/interactive/component-handlers.ts +622 -0
- package/src/renderers/interactive/cursor-manager.ts +147 -0
- package/src/renderers/interactive/focus-manager.ts +279 -0
- package/src/renderers/interactive/index.ts +661 -0
- package/src/renderers/interactive/input-handler.ts +164 -0
- package/src/renderers/interactive/keyboard-handler.ts +212 -0
- package/src/renderers/interactive/mouse-handler.ts +167 -0
- package/src/renderers/interactive/state-manager.ts +109 -0
- package/src/renderers/interactive/types.ts +338 -0
- package/src/renderers/interactive-string.ts +299 -0
- package/src/renderers/interactive.ts +59 -0
- package/src/renderers/markdown.ts +950 -0
- package/src/renderers/sidebar.ts +549 -0
- package/src/renderers/tabs.ts +682 -0
- package/src/renderers/text.ts +791 -0
- package/src/renderers/unicode.ts +917 -0
- package/src/renderers/utils.ts +942 -0
- package/src/router/adapters.ts +383 -0
- package/src/router/types.ts +140 -0
- package/src/router/utils.ts +452 -0
- package/src/schemas.ts +205 -0
- package/src/storybook/index.ts +91 -0
- package/src/storybook/interactive-decorator.tsx +659 -0
- package/src/storybook/keyboard-simulator.ts +501 -0
- package/src/theme/ansi-codes.ts +80 -0
- package/src/theme/box-drawing.ts +132 -0
- package/src/theme/color-convert.ts +254 -0
- package/src/theme/color-support.ts +321 -0
- package/src/theme/index.ts +134 -0
- package/src/theme/strip-ansi.ts +50 -0
- package/src/theme/tailwind-map.ts +469 -0
- package/src/theme/text-styles.ts +206 -0
- package/src/theme/theme-system.ts +568 -0
- package/src/types.ts +103 -0
|
@@ -0,0 +1,396 @@
|
|
|
1
|
+
import { I as InteractiveRenderer, a as InteractiveRendererConfig } from '../interactive-D0JkWosD.js';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
import { Decorator } from '@storybook/react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @mdxui/terminal Keyboard Simulator
|
|
7
|
+
*
|
|
8
|
+
* Provides utilities for simulating keyboard events in Storybook stories
|
|
9
|
+
* for testing interactive terminal components.
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```tsx
|
|
15
|
+
* import { createKeyboardSimulator, KeySequence } from '@mdxui/terminal/storybook'
|
|
16
|
+
*
|
|
17
|
+
* const simulator = createKeyboardSimulator({ renderer })
|
|
18
|
+
*
|
|
19
|
+
* // Single key press
|
|
20
|
+
* simulator.press('enter')
|
|
21
|
+
*
|
|
22
|
+
* // Key with modifiers
|
|
23
|
+
* simulator.press('s', { ctrl: true })
|
|
24
|
+
*
|
|
25
|
+
* // Predefined sequences
|
|
26
|
+
* simulator.sequence(KeySequence.NAVIGATE_DOWN_3)
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Key modifiers for keyboard events
|
|
32
|
+
*/
|
|
33
|
+
interface KeyModifiers {
|
|
34
|
+
/** Ctrl key pressed */
|
|
35
|
+
ctrl?: boolean;
|
|
36
|
+
/** Alt/Option key pressed */
|
|
37
|
+
alt?: boolean;
|
|
38
|
+
/** Shift key pressed */
|
|
39
|
+
shift?: boolean;
|
|
40
|
+
/** Meta/Command key pressed */
|
|
41
|
+
meta?: boolean;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Single key press event
|
|
45
|
+
*/
|
|
46
|
+
interface KeyPress {
|
|
47
|
+
/** Key name (e.g., 'enter', 'tab', 'a', 'escape') */
|
|
48
|
+
key: string;
|
|
49
|
+
/** Key modifiers */
|
|
50
|
+
modifiers?: KeyModifiers;
|
|
51
|
+
/** Delay in ms before this key press (default: 0) */
|
|
52
|
+
delay?: number;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Configuration for the keyboard simulator
|
|
56
|
+
*/
|
|
57
|
+
interface KeyboardSimulatorConfig {
|
|
58
|
+
/** Interactive renderer instance */
|
|
59
|
+
renderer: InteractiveRenderer;
|
|
60
|
+
/** Default delay between key presses in ms (default: 0) */
|
|
61
|
+
defaultDelay?: number;
|
|
62
|
+
/** Callback when key is pressed */
|
|
63
|
+
onKeyPress?: (key: string, modifiers: KeyModifiers) => void;
|
|
64
|
+
/** Callback when sequence completes */
|
|
65
|
+
onSequenceComplete?: (sequence: KeyPress[]) => void;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Keyboard simulator instance
|
|
69
|
+
*/
|
|
70
|
+
interface KeyboardSimulator {
|
|
71
|
+
/** Press a single key */
|
|
72
|
+
press(key: string, modifiers?: KeyModifiers): void;
|
|
73
|
+
/** Press a key and return a promise that resolves after the default delay */
|
|
74
|
+
pressAsync(key: string, modifiers?: KeyModifiers): Promise<void>;
|
|
75
|
+
/** Execute a sequence of key presses */
|
|
76
|
+
sequence(keys: KeyPress[]): void;
|
|
77
|
+
/** Execute a sequence of key presses with delays */
|
|
78
|
+
sequenceAsync(keys: KeyPress[]): Promise<void>;
|
|
79
|
+
/** Type a string character by character */
|
|
80
|
+
type(text: string): void;
|
|
81
|
+
/** Type a string character by character with delays */
|
|
82
|
+
typeAsync(text: string, charDelay?: number): Promise<void>;
|
|
83
|
+
/** Reset simulator state */
|
|
84
|
+
reset(): void;
|
|
85
|
+
/** Get list of pressed keys (for assertions) */
|
|
86
|
+
getPressedKeys(): string[];
|
|
87
|
+
/** Clear pressed keys history */
|
|
88
|
+
clearHistory(): void;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Common key sequences for testing navigation patterns
|
|
92
|
+
*/
|
|
93
|
+
declare const KeySequence: {
|
|
94
|
+
/** Navigate down one item */
|
|
95
|
+
readonly NAVIGATE_DOWN: KeyPress[];
|
|
96
|
+
/** Navigate down three items */
|
|
97
|
+
readonly NAVIGATE_DOWN_3: KeyPress[];
|
|
98
|
+
/** Navigate up one item */
|
|
99
|
+
readonly NAVIGATE_UP: KeyPress[];
|
|
100
|
+
/** Navigate up three items */
|
|
101
|
+
readonly NAVIGATE_UP_3: KeyPress[];
|
|
102
|
+
/** Tab forward through focusables */
|
|
103
|
+
readonly TAB_FORWARD: KeyPress[];
|
|
104
|
+
/** Tab forward three times */
|
|
105
|
+
readonly TAB_FORWARD_3: KeyPress[];
|
|
106
|
+
/** Tab backward through focusables */
|
|
107
|
+
readonly TAB_BACKWARD: KeyPress[];
|
|
108
|
+
/** Tab backward three times */
|
|
109
|
+
readonly TAB_BACKWARD_3: KeyPress[];
|
|
110
|
+
/** Select/activate focused element */
|
|
111
|
+
readonly SELECT: KeyPress[];
|
|
112
|
+
/** Toggle focused element (e.g., checkbox) */
|
|
113
|
+
readonly TOGGLE: KeyPress[];
|
|
114
|
+
/** Cancel/escape current action */
|
|
115
|
+
readonly CANCEL: KeyPress[];
|
|
116
|
+
/** Navigate to first item (vim: gg) */
|
|
117
|
+
readonly GOTO_FIRST: KeyPress[];
|
|
118
|
+
/** Navigate to last item (vim: G) */
|
|
119
|
+
readonly GOTO_LAST: KeyPress[];
|
|
120
|
+
/** Open search mode (vim: /) */
|
|
121
|
+
readonly SEARCH: KeyPress[];
|
|
122
|
+
/** Navigate down and select */
|
|
123
|
+
readonly NAVIGATE_DOWN_SELECT: KeyPress[];
|
|
124
|
+
/** Navigate to next item using j (vim) */
|
|
125
|
+
readonly VIM_DOWN: KeyPress[];
|
|
126
|
+
/** Navigate to previous item using k (vim) */
|
|
127
|
+
readonly VIM_UP: KeyPress[];
|
|
128
|
+
/** Navigate left using h (vim) */
|
|
129
|
+
readonly VIM_LEFT: KeyPress[];
|
|
130
|
+
/** Navigate right using l (vim) */
|
|
131
|
+
readonly VIM_RIGHT: KeyPress[];
|
|
132
|
+
/** Delete sequence (vim: dd) */
|
|
133
|
+
readonly VIM_DELETE: KeyPress[];
|
|
134
|
+
/** Home key - jump to beginning */
|
|
135
|
+
readonly HOME: KeyPress[];
|
|
136
|
+
/** End key - jump to end */
|
|
137
|
+
readonly END: KeyPress[];
|
|
138
|
+
/** Page down */
|
|
139
|
+
readonly PAGE_DOWN: KeyPress[];
|
|
140
|
+
/** Page up */
|
|
141
|
+
readonly PAGE_UP: KeyPress[];
|
|
142
|
+
/** Ctrl+C - cancel/interrupt */
|
|
143
|
+
readonly INTERRUPT: KeyPress[];
|
|
144
|
+
/** Ctrl+S - save */
|
|
145
|
+
readonly SAVE: KeyPress[];
|
|
146
|
+
};
|
|
147
|
+
/**
|
|
148
|
+
* Creates a keyboard simulator for testing interactive terminal components.
|
|
149
|
+
*
|
|
150
|
+
* The simulator wraps the interactive renderer's `emitKey` method and provides
|
|
151
|
+
* higher-level abstractions for common keyboard testing patterns.
|
|
152
|
+
*
|
|
153
|
+
* @param config - Simulator configuration
|
|
154
|
+
* @returns Keyboard simulator instance
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* ```tsx
|
|
158
|
+
* const renderer = await createInteractiveRenderer({ vimBindings: true })
|
|
159
|
+
* const simulator = createKeyboardSimulator({ renderer })
|
|
160
|
+
*
|
|
161
|
+
* // Register some focusable elements
|
|
162
|
+
* renderer.registerFocusable('item-1', { tabIndex: 0 })
|
|
163
|
+
* renderer.registerFocusable('item-2', { tabIndex: 0 })
|
|
164
|
+
* renderer.registerFocusable('item-3', { tabIndex: 0 })
|
|
165
|
+
*
|
|
166
|
+
* // Focus first item
|
|
167
|
+
* renderer.focusById('item-1')
|
|
168
|
+
*
|
|
169
|
+
* // Navigate down using simulator
|
|
170
|
+
* simulator.press('j') // vim down
|
|
171
|
+
* expect(renderer.getFocusedId()).toBe('item-2')
|
|
172
|
+
*
|
|
173
|
+
* // Or use predefined sequences
|
|
174
|
+
* simulator.sequence(KeySequence.NAVIGATE_DOWN)
|
|
175
|
+
* expect(renderer.getFocusedId()).toBe('item-3')
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
declare function createKeyboardSimulator(config: KeyboardSimulatorConfig): KeyboardSimulator;
|
|
179
|
+
/**
|
|
180
|
+
* Assert that a specific key was pressed
|
|
181
|
+
*/
|
|
182
|
+
declare function expectKeyPressed(simulator: KeyboardSimulator, key: string, modifiers?: KeyModifiers): void;
|
|
183
|
+
/**
|
|
184
|
+
* Assert that a sequence of keys was pressed in order
|
|
185
|
+
*/
|
|
186
|
+
declare function expectSequencePressed(simulator: KeyboardSimulator, sequence: KeyPress[]): void;
|
|
187
|
+
/**
|
|
188
|
+
* Assert that no keys were pressed
|
|
189
|
+
*/
|
|
190
|
+
declare function expectNoKeysPressed(simulator: KeyboardSimulator): void;
|
|
191
|
+
/**
|
|
192
|
+
* Assert total number of key presses
|
|
193
|
+
*/
|
|
194
|
+
declare function expectKeyPressCount(simulator: KeyboardSimulator, count: number): void;
|
|
195
|
+
/**
|
|
196
|
+
* Map DOM KeyboardEvent to our key format
|
|
197
|
+
*/
|
|
198
|
+
declare function mapDOMKeyEvent(event: KeyboardEvent): KeyPress;
|
|
199
|
+
/**
|
|
200
|
+
* Create a keyboard event handler for DOM events that forwards to simulator
|
|
201
|
+
*/
|
|
202
|
+
declare function createDOMKeyHandler(simulator: KeyboardSimulator, options?: {
|
|
203
|
+
/** Prevent default browser behavior */
|
|
204
|
+
preventDefault?: boolean;
|
|
205
|
+
/** Stop event propagation */
|
|
206
|
+
stopPropagation?: boolean;
|
|
207
|
+
/** Keys to ignore (don't forward to simulator) */
|
|
208
|
+
ignoreKeys?: string[];
|
|
209
|
+
}): (event: KeyboardEvent) => void;
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @mdxui/terminal Interactive Decorator
|
|
213
|
+
*
|
|
214
|
+
* Storybook decorator and utilities for testing interactive terminal components.
|
|
215
|
+
* Provides keyboard event capture and visual feedback for navigation testing.
|
|
216
|
+
*
|
|
217
|
+
* @packageDocumentation
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* ```tsx
|
|
221
|
+
* // In your story file
|
|
222
|
+
* import type { Meta, StoryObj } from '@storybook/react'
|
|
223
|
+
* import { InteractiveDecorator, useKeyboardNavigation } from '@mdxui/terminal/storybook'
|
|
224
|
+
* import { Select } from './Select'
|
|
225
|
+
*
|
|
226
|
+
* const meta: Meta<typeof Select> = {
|
|
227
|
+
* title: 'Terminal/Select',
|
|
228
|
+
* component: Select,
|
|
229
|
+
* decorators: [InteractiveDecorator],
|
|
230
|
+
* parameters: {
|
|
231
|
+
* interactive: {
|
|
232
|
+
* vimBindings: true,
|
|
233
|
+
* showKeyLog: true,
|
|
234
|
+
* },
|
|
235
|
+
* },
|
|
236
|
+
* }
|
|
237
|
+
* ```
|
|
238
|
+
*/
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Parameters for the interactive decorator
|
|
242
|
+
*/
|
|
243
|
+
interface InteractiveDecoratorParameters {
|
|
244
|
+
/** Interactive renderer configuration */
|
|
245
|
+
interactive?: InteractiveRendererConfig & {
|
|
246
|
+
/** Show key press log panel */
|
|
247
|
+
showKeyLog?: boolean;
|
|
248
|
+
/** Maximum key log entries to display */
|
|
249
|
+
maxKeyLogEntries?: number;
|
|
250
|
+
/** Show focus indicator overlay */
|
|
251
|
+
showFocusOverlay?: boolean;
|
|
252
|
+
/** Keys to ignore from DOM forwarding */
|
|
253
|
+
ignoreKeys?: string[];
|
|
254
|
+
/** Auto-focus the interactive container */
|
|
255
|
+
autoFocus?: boolean;
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Interactive context for stories
|
|
260
|
+
*/
|
|
261
|
+
interface InteractiveContext {
|
|
262
|
+
/** The interactive renderer instance */
|
|
263
|
+
renderer: InteractiveRenderer | null;
|
|
264
|
+
/** The keyboard simulator instance */
|
|
265
|
+
simulator: KeyboardSimulator | null;
|
|
266
|
+
/** List of pressed keys */
|
|
267
|
+
keyLog: string[];
|
|
268
|
+
/** Currently focused element ID */
|
|
269
|
+
focusedId: string | null;
|
|
270
|
+
/** Clear the key log */
|
|
271
|
+
clearKeyLog: () => void;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Context for accessing interactive state in stories
|
|
275
|
+
*/
|
|
276
|
+
declare const InteractiveContext: React__default.Context<InteractiveContext>;
|
|
277
|
+
/**
|
|
278
|
+
* Hook to access interactive context in story components
|
|
279
|
+
*/
|
|
280
|
+
declare function useInteractiveContext(): InteractiveContext;
|
|
281
|
+
/**
|
|
282
|
+
* Storybook decorator for interactive terminal component testing.
|
|
283
|
+
*
|
|
284
|
+
* This decorator:
|
|
285
|
+
* - Creates an InteractiveRenderer instance
|
|
286
|
+
* - Captures keyboard events from the DOM
|
|
287
|
+
* - Forwards them to the renderer
|
|
288
|
+
* - Optionally shows a key log panel for debugging
|
|
289
|
+
* - Provides context for accessing the renderer/simulator in stories
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```tsx
|
|
293
|
+
* // meta configuration
|
|
294
|
+
* const meta: Meta<typeof MyComponent> = {
|
|
295
|
+
* title: 'Terminal/MyComponent',
|
|
296
|
+
* component: MyComponent,
|
|
297
|
+
* decorators: [InteractiveDecorator],
|
|
298
|
+
* parameters: {
|
|
299
|
+
* interactive: {
|
|
300
|
+
* vimBindings: true,
|
|
301
|
+
* showKeyLog: true,
|
|
302
|
+
* maxKeyLogEntries: 10,
|
|
303
|
+
* },
|
|
304
|
+
* },
|
|
305
|
+
* }
|
|
306
|
+
*
|
|
307
|
+
* // Access context in story
|
|
308
|
+
* export const Interactive: Story = {
|
|
309
|
+
* render: () => {
|
|
310
|
+
* const { renderer, simulator } = useInteractiveContext()
|
|
311
|
+
* // Use renderer/simulator in your component
|
|
312
|
+
* return <MyComponent renderer={renderer} />
|
|
313
|
+
* },
|
|
314
|
+
* }
|
|
315
|
+
* ```
|
|
316
|
+
*/
|
|
317
|
+
declare const InteractiveDecorator: Decorator;
|
|
318
|
+
/**
|
|
319
|
+
* Hook for stories that need manual keyboard navigation setup.
|
|
320
|
+
*
|
|
321
|
+
* Use this when you need more control over the keyboard handling
|
|
322
|
+
* or don't want to use the decorator.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* ```tsx
|
|
326
|
+
* function MyInteractiveStory() {
|
|
327
|
+
* const { renderer, simulator, keyLog, containerProps } = useKeyboardNavigation({
|
|
328
|
+
* vimBindings: true,
|
|
329
|
+
* })
|
|
330
|
+
*
|
|
331
|
+
* useEffect(() => {
|
|
332
|
+
* if (!renderer) return
|
|
333
|
+
*
|
|
334
|
+
* renderer.registerFocusable('item-1', { tabIndex: 0 })
|
|
335
|
+
* renderer.registerFocusable('item-2', { tabIndex: 0 })
|
|
336
|
+
* renderer.focusById('item-1')
|
|
337
|
+
* }, [renderer])
|
|
338
|
+
*
|
|
339
|
+
* return (
|
|
340
|
+
* <div {...containerProps}>
|
|
341
|
+
* <div data-focused={renderer?.getFocusedId() === 'item-1'}>Item 1</div>
|
|
342
|
+
* <div data-focused={renderer?.getFocusedId() === 'item-2'}>Item 2</div>
|
|
343
|
+
* </div>
|
|
344
|
+
* )
|
|
345
|
+
* }
|
|
346
|
+
* ```
|
|
347
|
+
*/
|
|
348
|
+
declare function useKeyboardNavigation(config?: InteractiveRendererConfig): {
|
|
349
|
+
renderer: InteractiveRenderer | null;
|
|
350
|
+
simulator: KeyboardSimulator | null;
|
|
351
|
+
keyLog: string[];
|
|
352
|
+
focusedId: string | null;
|
|
353
|
+
clearKeyLog: () => void;
|
|
354
|
+
containerProps: {
|
|
355
|
+
ref: React__default.RefObject<HTMLDivElement>;
|
|
356
|
+
tabIndex: number;
|
|
357
|
+
onKeyDown: (event: React__default.KeyboardEvent<HTMLDivElement>) => void;
|
|
358
|
+
onFocus: () => void;
|
|
359
|
+
style: React__default.CSSProperties;
|
|
360
|
+
};
|
|
361
|
+
};
|
|
362
|
+
/**
|
|
363
|
+
* Programmatically simulate keyboard navigation in a story.
|
|
364
|
+
*
|
|
365
|
+
* Useful for creating animated demos or testing specific navigation flows.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```tsx
|
|
369
|
+
* export const AnimatedDemo: Story = {
|
|
370
|
+
* render: () => {
|
|
371
|
+
* const { renderer, simulator } = useInteractiveContext()
|
|
372
|
+
*
|
|
373
|
+
* useEffect(() => {
|
|
374
|
+
* if (!simulator) return
|
|
375
|
+
*
|
|
376
|
+
* // Simulate navigation sequence
|
|
377
|
+
* const cleanup = simulateKeyboardDemo(simulator, [
|
|
378
|
+
* { keys: [{ key: 'tab' }], delay: 500 },
|
|
379
|
+
* { keys: [{ key: 'tab' }], delay: 500 },
|
|
380
|
+
* { keys: [{ key: 'enter' }], delay: 500 },
|
|
381
|
+
* ])
|
|
382
|
+
*
|
|
383
|
+
* return cleanup
|
|
384
|
+
* }, [simulator])
|
|
385
|
+
*
|
|
386
|
+
* return <MyComponent />
|
|
387
|
+
* },
|
|
388
|
+
* }
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
declare function simulateKeyboardDemo(simulator: KeyboardSimulator, steps: Array<{
|
|
392
|
+
keys: KeyPress[];
|
|
393
|
+
delay: number;
|
|
394
|
+
}>): () => void;
|
|
395
|
+
|
|
396
|
+
export { InteractiveContext, InteractiveContext as InteractiveContextType, InteractiveDecorator, type InteractiveDecoratorParameters, type KeyModifiers, type KeyPress, KeySequence, type KeyboardSimulator, type KeyboardSimulatorConfig, createDOMKeyHandler, createKeyboardSimulator, expectKeyPressCount, expectKeyPressed, expectNoKeysPressed, expectSequencePressed, mapDOMKeyEvent, simulateKeyboardDemo, useInteractiveContext, useKeyboardNavigation };
|