ink-cartridge 3.6.1

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 (151) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +249 -0
  3. package/dist/binary-storage/BinaryStorage.d.ts +308 -0
  4. package/dist/binary-storage/BinaryStorage.js +548 -0
  5. package/dist/binary-storage/StreamingReader.d.ts +53 -0
  6. package/dist/binary-storage/StreamingReader.js +530 -0
  7. package/dist/binary-storage/index.d.ts +91 -0
  8. package/dist/binary-storage/index.js +91 -0
  9. package/dist/binary-storage/types.d.ts +400 -0
  10. package/dist/binary-storage/types.js +15 -0
  11. package/dist/cli/index.d.ts +2 -0
  12. package/dist/cli/index.js +214 -0
  13. package/dist/cli/initTheme.d.ts +14 -0
  14. package/dist/cli/initTheme.js +124 -0
  15. package/dist/cli/makeLanguageType.d.ts +46 -0
  16. package/dist/cli/makeLanguageType.js +264 -0
  17. package/dist/cli/makeThemeType.d.ts +43 -0
  18. package/dist/cli/makeThemeType.js +222 -0
  19. package/dist/components/badge/Badge.d.ts +7 -0
  20. package/dist/components/badge/Badge.js +9 -0
  21. package/dist/components/dialog/ConfirmDialog.d.ts +23 -0
  22. package/dist/components/dialog/ConfirmDialog.js +57 -0
  23. package/dist/components/dialog/types.d.ts +20 -0
  24. package/dist/components/dialog/types.js +1 -0
  25. package/dist/components/divider/Divider.d.ts +8 -0
  26. package/dist/components/divider/Divider.js +10 -0
  27. package/dist/components/fold/Fold.d.ts +3 -0
  28. package/dist/components/fold/Fold.js +44 -0
  29. package/dist/components/fold/types.d.ts +28 -0
  30. package/dist/components/fold/types.js +1 -0
  31. package/dist/components/form/Field.d.ts +30 -0
  32. package/dist/components/form/Field.js +59 -0
  33. package/dist/components/form/Form.d.ts +32 -0
  34. package/dist/components/form/Form.js +163 -0
  35. package/dist/components/form/context.d.ts +14 -0
  36. package/dist/components/form/context.js +20 -0
  37. package/dist/components/form/types.d.ts +115 -0
  38. package/dist/components/form/types.js +1 -0
  39. package/dist/components/key-hint/KeyHint.d.ts +10 -0
  40. package/dist/components/key-hint/KeyHint.js +12 -0
  41. package/dist/components/multi-select/MultiSelectInput.d.ts +125 -0
  42. package/dist/components/multi-select/MultiSelectInput.js +287 -0
  43. package/dist/components/multi-select/types.d.ts +100 -0
  44. package/dist/components/multi-select/types.js +1 -0
  45. package/dist/components/number-input/NumberInput.d.ts +11 -0
  46. package/dist/components/number-input/NumberInput.js +44 -0
  47. package/dist/components/progress-bar/ProgressBar.d.ts +11 -0
  48. package/dist/components/progress-bar/ProgressBar.js +9 -0
  49. package/dist/components/search-input/SearchInput.d.ts +10 -0
  50. package/dist/components/search-input/SearchInput.js +15 -0
  51. package/dist/components/select/SelectInput.d.ts +100 -0
  52. package/dist/components/select/SelectInput.js +147 -0
  53. package/dist/components/select/types.d.ts +63 -0
  54. package/dist/components/select/types.js +1 -0
  55. package/dist/components/spinner/Spinner.d.ts +12 -0
  56. package/dist/components/spinner/Spinner.js +24 -0
  57. package/dist/components/tabs/Tabs.d.ts +3 -0
  58. package/dist/components/tabs/Tabs.js +57 -0
  59. package/dist/components/tabs/types.d.ts +32 -0
  60. package/dist/components/tabs/types.js +1 -0
  61. package/dist/components/text/TextInput.d.ts +39 -0
  62. package/dist/components/text/TextInput.js +233 -0
  63. package/dist/components/text/types.d.ts +62 -0
  64. package/dist/components/text/types.js +1 -0
  65. package/dist/dev/dev-screen.d.ts +36 -0
  66. package/dist/dev/dev-screen.js +142 -0
  67. package/dist/dev/entrance.d.ts +51 -0
  68. package/dist/dev/entrance.js +67 -0
  69. package/dist/dev/globalKey-display.d.ts +2 -0
  70. package/dist/dev/globalKey-display.js +8 -0
  71. package/dist/dev/types.d.ts +9 -0
  72. package/dist/dev/types.js +1 -0
  73. package/dist/index.d.ts +46 -0
  74. package/dist/index.js +50 -0
  75. package/dist/keyboard/check-global-key.d.ts +18 -0
  76. package/dist/keyboard/check-global-key.js +52 -0
  77. package/dist/keyboard/context.d.ts +398 -0
  78. package/dist/keyboard/context.js +9 -0
  79. package/dist/keyboard/global-key-processor/index.d.ts +16 -0
  80. package/dist/keyboard/global-key-processor/index.js +75 -0
  81. package/dist/keyboard/global-sequence-processor/index.d.ts +14 -0
  82. package/dist/keyboard/global-sequence-processor/index.js +165 -0
  83. package/dist/keyboard/hook.d.ts +51 -0
  84. package/dist/keyboard/hook.js +105 -0
  85. package/dist/keyboard/index.d.ts +5 -0
  86. package/dist/keyboard/index.js +3 -0
  87. package/dist/keyboard/keyNormalizer.d.ts +37 -0
  88. package/dist/keyboard/keyNormalizer.js +119 -0
  89. package/dist/keyboard/layer-handler.d.ts +57 -0
  90. package/dist/keyboard/layer-handler.js +274 -0
  91. package/dist/keyboard/modal-processor/index.d.ts +16 -0
  92. package/dist/keyboard/modal-processor/index.js +97 -0
  93. package/dist/keyboard/overlay-processor/index.d.ts +16 -0
  94. package/dist/keyboard/overlay-processor/index.js +30 -0
  95. package/dist/keyboard/pipeline/chain.d.ts +10 -0
  96. package/dist/keyboard/pipeline/chain.js +45 -0
  97. package/dist/keyboard/pipeline/context.d.ts +34 -0
  98. package/dist/keyboard/pipeline/context.js +42 -0
  99. package/dist/keyboard/pipeline/index.d.ts +3 -0
  100. package/dist/keyboard/pipeline/index.js +2 -0
  101. package/dist/keyboard/provider.d.ts +32 -0
  102. package/dist/keyboard/provider.js +985 -0
  103. package/dist/keyboard/screen-stack-processor/index.d.ts +14 -0
  104. package/dist/keyboard/screen-stack-processor/index.js +32 -0
  105. package/dist/keyboard/types.d.ts +632 -0
  106. package/dist/keyboard/types.js +1 -0
  107. package/dist/language/context.d.ts +7 -0
  108. package/dist/language/context.js +7 -0
  109. package/dist/language/hook.d.ts +19 -0
  110. package/dist/language/hook.js +26 -0
  111. package/dist/language/index.d.ts +3 -0
  112. package/dist/language/index.js +2 -0
  113. package/dist/language/provider.d.ts +30 -0
  114. package/dist/language/provider.js +155 -0
  115. package/dist/language/types.d.ts +124 -0
  116. package/dist/language/types.js +1 -0
  117. package/dist/screen/ModalContext.d.ts +11 -0
  118. package/dist/screen/ModalContext.js +12 -0
  119. package/dist/screen/OverlayContext.d.ts +9 -0
  120. package/dist/screen/OverlayContext.js +10 -0
  121. package/dist/screen/context.d.ts +61 -0
  122. package/dist/screen/context.js +8 -0
  123. package/dist/screen/current-screen.d.ts +16 -0
  124. package/dist/screen/current-screen.js +38 -0
  125. package/dist/screen/hook.d.ts +13 -0
  126. package/dist/screen/hook.js +20 -0
  127. package/dist/screen/index.d.ts +7 -0
  128. package/dist/screen/index.js +5 -0
  129. package/dist/screen/provider.d.ts +112 -0
  130. package/dist/screen/provider.js +577 -0
  131. package/dist/screen/registry.d.ts +27 -0
  132. package/dist/screen/registry.js +71 -0
  133. package/dist/screen/types.d.ts +227 -0
  134. package/dist/screen/types.js +1 -0
  135. package/dist/storage/index.d.ts +45 -0
  136. package/dist/storage/index.js +46 -0
  137. package/dist/storage/storage.d.ts +139 -0
  138. package/dist/storage/storage.js +236 -0
  139. package/dist/storage/types.d.ts +145 -0
  140. package/dist/storage/types.js +1 -0
  141. package/dist/theme/context.d.ts +7 -0
  142. package/dist/theme/context.js +7 -0
  143. package/dist/theme/hook.d.ts +11 -0
  144. package/dist/theme/hook.js +18 -0
  145. package/dist/theme/index.d.ts +4 -0
  146. package/dist/theme/index.js +2 -0
  147. package/dist/theme/provider.d.ts +18 -0
  148. package/dist/theme/provider.js +308 -0
  149. package/dist/theme/types.d.ts +53 -0
  150. package/dist/theme/types.js +1 -0
  151. package/package.json +71 -0
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,36 @@
1
+ import React from "react";
2
+ import { DevProps } from "./types.js";
3
+ /**
4
+ * Developer debugging modal for the ink-cartridge screen system.
5
+ *
6
+ * Renders as an absolutely-positioned panel showing real-time navigation
7
+ * state: the current screen path as a breadcrumb, a list of open overlays
8
+ * (green = active, gray = inactive), open modals, screen count, and the
9
+ * panel's vertical offset.
10
+ *
11
+ * Keyboard controls (bound on mount):
12
+ * - **↑ / ↓** — move the panel vertically, clamped to the terminal bounds.
13
+ * The position automatically re-clamps on terminal resize so the panel
14
+ * never drifts off-screen.
15
+ * - **Escape** — close the DevScreen modal.
16
+ *
17
+ * Must be opened via {@link openDevTool} (which calls `openModal`).
18
+ * The panel registers itself via `registerComponent` so it participates
19
+ * in the modal keyboard layer automatically.
20
+ *
21
+ * As a modal, DevScreen blocks all keyboard events from reaching overlays
22
+ * and screens while open.
23
+ *
24
+ * @param top - Initial vertical position in rows (0 = top of terminal).
25
+ * @param left - Horizontal position in columns.
26
+ *
27
+ * @example
28
+ * ```ts
29
+ * // Open from any screen or keyboard handler:
30
+ * import { openDevTool } from 'ink-cartridge/dev';
31
+ * openDevTool({ top: 0, left: 0 });
32
+ * ```
33
+ *
34
+ * @2026-06-23 3.6.1
35
+ */
36
+ export declare function DevScreen({ top: initialTop, left }: DevProps): React.JSX.Element;
@@ -0,0 +1,142 @@
1
+ import React, { useCallback, useContext, useEffect, useRef, useState } from "react";
2
+ import { Box, Text, useWindowSize } from "ink";
3
+ import { useScreenSystem } from "../screen/hook.js";
4
+ import { useKeyboard, useModalMissListener } from "../keyboard/hook.js";
5
+ import { ModalContext } from "../screen/ModalContext.js";
6
+ import { registerComponent } from "../screen/registry.js";
7
+ import { closeDevTool } from "./entrance.js";
8
+ const PANEL_HEIGHT = 30;
9
+ /**
10
+ * Developer debugging modal for the ink-cartridge screen system.
11
+ *
12
+ * Renders as an absolutely-positioned panel showing real-time navigation
13
+ * state: the current screen path as a breadcrumb, a list of open overlays
14
+ * (green = active, gray = inactive), open modals, screen count, and the
15
+ * panel's vertical offset.
16
+ *
17
+ * Keyboard controls (bound on mount):
18
+ * - **↑ / ↓** — move the panel vertically, clamped to the terminal bounds.
19
+ * The position automatically re-clamps on terminal resize so the panel
20
+ * never drifts off-screen.
21
+ * - **Escape** — close the DevScreen modal.
22
+ *
23
+ * Must be opened via {@link openDevTool} (which calls `openModal`).
24
+ * The panel registers itself via `registerComponent` so it participates
25
+ * in the modal keyboard layer automatically.
26
+ *
27
+ * As a modal, DevScreen blocks all keyboard events from reaching overlays
28
+ * and screens while open.
29
+ *
30
+ * @param top - Initial vertical position in rows (0 = top of terminal).
31
+ * @param left - Horizontal position in columns.
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * // Open from any screen or keyboard handler:
36
+ * import { openDevTool } from 'ink-cartridge/dev';
37
+ * openDevTool({ top: 0, left: 0 });
38
+ * ```
39
+ *
40
+ * @2026-06-23 3.6.1
41
+ */
42
+ export function DevScreen({ top: initialTop, left }) {
43
+ const { currentPath, displayedOverlays, activeOverlayIds, modalQueue, activeModalId, } = useScreenSystem();
44
+ const { boundKeyboard } = useKeyboard();
45
+ const modalId = useContext(ModalContext);
46
+ const { rows } = useWindowSize();
47
+ const [offsetTop, setOffsetTop] = useState(initialTop);
48
+ const [flashBorder, setFlashBorder] = useState(false);
49
+ const flashTimerRef = useRef(null);
50
+ // Stable ref so the []-deps keyboard effect always reads the latest
51
+ // rows-based clamp, preventing a stale-closure on the initial size.
52
+ const clampTopRef = useRef((next) => next);
53
+ clampTopRef.current = (next) => Math.max(0, Math.min(next, rows - PANEL_HEIGHT));
54
+ useModalMissListener(useCallback((evt) => {
55
+ if (evt.miss) {
56
+ setFlashBorder(true);
57
+ if (flashTimerRef.current)
58
+ clearTimeout(flashTimerRef.current);
59
+ flashTimerRef.current = setTimeout(() => {
60
+ setFlashBorder(false);
61
+ flashTimerRef.current = null;
62
+ }, 200);
63
+ }
64
+ }, []));
65
+ // Cleanup flash timer on unmount
66
+ useEffect(() => {
67
+ return () => {
68
+ if (flashTimerRef.current)
69
+ clearTimeout(flashTimerRef.current);
70
+ };
71
+ }, []);
72
+ useEffect(() => {
73
+ const u1 = boundKeyboard(['up'], () => setOffsetTop(prev => clampTopRef.current(prev - 1)));
74
+ const u2 = boundKeyboard(['down'], () => setOffsetTop(prev => clampTopRef.current(prev + 1)));
75
+ const u3 = boundKeyboard(['escape'], () => {
76
+ if (modalId)
77
+ closeDevTool();
78
+ });
79
+ return () => {
80
+ u1();
81
+ u2();
82
+ u3();
83
+ };
84
+ }, [modalId]);
85
+ // When the terminal is resized the current position may land outside
86
+ // the new bounds — re-clamp so the panel stays visible immediately.
87
+ useEffect(() => {
88
+ setOffsetTop(prev => clampTopRef.current(prev));
89
+ }, [rows]);
90
+ return (React.createElement(Box, { borderColor: flashBorder ? 'yellow' : 'blue', borderStyle: 'round', position: "absolute", top: offsetTop, left: left, height: PANEL_HEIGHT, width: '100%', flexDirection: "column", paddingX: 1, paddingY: 1, backgroundColor: 'black' },
91
+ React.createElement(Box, { flexDirection: "row" },
92
+ React.createElement(Text, { color: "cyan", bold: true }, "Path "),
93
+ currentPath.map((component, index) => {
94
+ const name = component.displayName || component.name || 'Unknown';
95
+ const isLast = index === currentPath.length - 1;
96
+ return (React.createElement(Box, { key: index, flexDirection: "row" },
97
+ React.createElement(Text, { color: "gray" },
98
+ " ",
99
+ '>',
100
+ " "),
101
+ React.createElement(Text, { color: isLast ? 'yellow' : 'gray', bold: isLast }, name)));
102
+ })),
103
+ React.createElement(Box, { flexDirection: "row", paddingTop: 1 },
104
+ React.createElement(Text, { color: "cyan" }, "Overlays "),
105
+ React.createElement(Text, { dimColor: true },
106
+ "(",
107
+ displayedOverlays.length,
108
+ ")"),
109
+ displayedOverlays.length === 0 ? (React.createElement(Text, { color: "gray" }, " \u2014 none")) : (displayedOverlays.map((entry, i) => {
110
+ const name = entry.component.displayName || entry.component.name || 'Unknown';
111
+ const active = activeOverlayIds.includes(entry.id);
112
+ return (React.createElement(Box, { key: entry.id, flexDirection: "row" },
113
+ React.createElement(Text, { color: "gray" }, i > 0 ? ', ' : ' — '),
114
+ React.createElement(Text, { color: active ? 'green' : 'gray' }, name)));
115
+ }))),
116
+ React.createElement(Box, { flexDirection: "row", paddingTop: 0 },
117
+ React.createElement(Text, { color: "cyan" }, "Modals "),
118
+ React.createElement(Text, { dimColor: true },
119
+ "(",
120
+ modalQueue.length,
121
+ ")"),
122
+ modalQueue.length === 0 ? (React.createElement(Text, { color: "gray" }, " \u2014 none")) : (modalQueue.map((entry, i) => {
123
+ const name = entry.component.displayName || entry.component.name || 'Unknown';
124
+ const active = entry.id === activeModalId;
125
+ return (React.createElement(Box, { key: entry.id, flexDirection: "row" },
126
+ React.createElement(Text, { color: "gray" }, i > 0 ? ', ' : ' — '),
127
+ React.createElement(Text, { color: active ? 'green' : 'gray' }, name)));
128
+ }))),
129
+ React.createElement(Box, { width: '100%', paddingY: 1 },
130
+ React.createElement(Text, { color: "blue", dimColor: true }, "─".repeat(60))),
131
+ React.createElement(Box, { flexDirection: "column" },
132
+ React.createElement(Text, { dimColor: true },
133
+ "Screens: ",
134
+ currentPath.length,
135
+ " | \u2191\u2193 Move | Esc Close"),
136
+ React.createElement(Text, { dimColor: true },
137
+ "Top: ",
138
+ offsetTop,
139
+ "/",
140
+ rows - PANEL_HEIGHT))));
141
+ }
142
+ registerComponent(DevScreen, { top: 0, left: 0 });
@@ -0,0 +1,51 @@
1
+ import { DevProps } from "./types.js";
2
+ /**
3
+ * Open the developer debugging modal.
4
+ *
5
+ * Calls {@link openModal} with the fixed modal ID `_Dev-Tool_` and
6
+ * the {@link DevScreen} component. Repeated calls while the modal is
7
+ * already open will throw — guard with a ref or state flag to implement
8
+ * a toggle (see example).
9
+ *
10
+ * When open, DevScreen blocks all keyboard events from reaching
11
+ * overlays and screens. The modal provides its own close mechanism
12
+ * via the Escape key.
13
+ *
14
+ * @param top - Initial vertical position in rows (0 = top of terminal).
15
+ * @param left - Horizontal position in columns.
16
+ *
17
+ * @throws If `ScenarioManagementProvider` is not mounted, or the modal
18
+ * ID `_Dev-Tool_` is already open.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * // Toggle with a ref to avoid duplicate-open errors:
23
+ * const devOpenRef = useRef(false);
24
+ * boundKeyboard(['ctrl+d'], () => {
25
+ * if (devOpenRef.current) {
26
+ * closeDevTool();
27
+ * devOpenRef.current = false;
28
+ * } else {
29
+ * openDevTool({ top: 0, left: 0 });
30
+ * devOpenRef.current = true;
31
+ * }
32
+ * });
33
+ * ```
34
+ */
35
+ export declare function openDevTool({ top, left, zindex }: DevProps & {
36
+ zindex?: number;
37
+ }): void;
38
+ /**
39
+ * Close the developer debugging modal.
40
+ *
41
+ * Calls {@link closeModal} for the fixed modal ID `_Dev-Tool_`.
42
+ * Safe to call even if the modal is not currently open — acts as
43
+ * a no-op in that case to support toggle patterns where the modal
44
+ * may have been closed by its own Escape binding.
45
+ *
46
+ * @example
47
+ * ```ts
48
+ * boundKeyboard(['escape'], () => closeDevTool());
49
+ * ```
50
+ */
51
+ export declare function closeDevTool(): void;
@@ -0,0 +1,67 @@
1
+ import { closeModal, openModal } from "../screen/provider.js";
2
+ import { DevScreen } from "./dev-screen.js";
3
+ /**
4
+ * Open the developer debugging modal.
5
+ *
6
+ * Calls {@link openModal} with the fixed modal ID `_Dev-Tool_` and
7
+ * the {@link DevScreen} component. Repeated calls while the modal is
8
+ * already open will throw — guard with a ref or state flag to implement
9
+ * a toggle (see example).
10
+ *
11
+ * When open, DevScreen blocks all keyboard events from reaching
12
+ * overlays and screens. The modal provides its own close mechanism
13
+ * via the Escape key.
14
+ *
15
+ * @param top - Initial vertical position in rows (0 = top of terminal).
16
+ * @param left - Horizontal position in columns.
17
+ *
18
+ * @throws If `ScenarioManagementProvider` is not mounted, or the modal
19
+ * ID `_Dev-Tool_` is already open.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * // Toggle with a ref to avoid duplicate-open errors:
24
+ * const devOpenRef = useRef(false);
25
+ * boundKeyboard(['ctrl+d'], () => {
26
+ * if (devOpenRef.current) {
27
+ * closeDevTool();
28
+ * devOpenRef.current = false;
29
+ * } else {
30
+ * openDevTool({ top: 0, left: 0 });
31
+ * devOpenRef.current = true;
32
+ * }
33
+ * });
34
+ * ```
35
+ */
36
+ export function openDevTool({ top, left, zindex }) {
37
+ openModal('_Dev-Tool_', DevScreen, {
38
+ top: top,
39
+ left: left
40
+ }, {
41
+ zIndex: zindex,
42
+ renderNow: true
43
+ });
44
+ }
45
+ /**
46
+ * Close the developer debugging modal.
47
+ *
48
+ * Calls {@link closeModal} for the fixed modal ID `_Dev-Tool_`.
49
+ * Safe to call even if the modal is not currently open — acts as
50
+ * a no-op in that case to support toggle patterns where the modal
51
+ * may have been closed by its own Escape binding.
52
+ *
53
+ * @example
54
+ * ```ts
55
+ * boundKeyboard(['escape'], () => closeDevTool());
56
+ * ```
57
+ */
58
+ export function closeDevTool() {
59
+ try {
60
+ closeModal('_Dev-Tool_');
61
+ }
62
+ catch {
63
+ // Modal already closed — no-op. This handles the case where
64
+ // the Escape key inside DevScreen closed the modal, leaving
65
+ // an external toggle ref stale.
66
+ }
67
+ }
@@ -0,0 +1,2 @@
1
+ import React from "react";
2
+ export default function GlobalKeyDisplayBox(): React.JSX.Element;
@@ -0,0 +1,8 @@
1
+ import { Box } from "ink";
2
+ import React from "react";
3
+ // This modal box is used to display information about all registered global keys.
4
+ // Because it is a modal box, its keyboard is independent and will not be affected by DevTool.
5
+ // Also make sure that the zindex is greater than the zindex of the DevTool so that the visual effects and keyboard reception are applied correctly when the modal box is opened
6
+ export default function GlobalKeyDisplayBox() {
7
+ return (React.createElement(Box, { position: "absolute" }));
8
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Props accepted by the {@link DevScreen} debugging overlay.
3
+ */
4
+ export interface DevProps {
5
+ /** Vertical position in rows — 0 is the top of the terminal. */
6
+ top: number;
7
+ /** Horizontal position in columns — 0 is the left edge. */
8
+ left: number;
9
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ export { registerComponent, ScenarioManagementProvider, CurrentScreen, skip, back, gotoScreen, openOverlay, closeOverlay, closeAllOverlays, activateOverlay, deactivateOverlay, openModal, closeModal, closeAllModals, useScreenSystem, ModalContext, } from "./screen/index.js";
2
+ export type { SkipOptions, SkipFn, BackFn, GotoScreenFn, OpenOverlayFn, CloseOverlayFn, CloseAllOverlaysFn, ActivateOverlayFn, DeactivateOverlayFn, OpenModalFn, CloseModalFn, CloseAllModalsFn, OpenOverlayOptions, OpenModalOptions, OverlayEntry, ModalEntry, RegisterOptions, ScenarioManagementProviderProps, } from "./screen/index.js";
3
+ export { KeyboardProvider, useKeyboard } from "./keyboard/index.js";
4
+ export { normalizeKeyNames, isNormalCharacter } from "./keyboard/index.js";
5
+ export type { KeyHandler, BoundKeyboardOptions, BoundKeyEntry, ScreenKeyboardLayer, KeyboardProviderProps, GlobalKeyEntry, GlobalSequenceEntry, } from "./keyboard/index.js";
6
+ export type { BlockedKeyOptions, StopOptions, FocusTarget, SequenceOptions, ShortcutOperationEntry, SequenceOperationEntry, ModalMissEvent, ModalMissCallback, ModalMissOptions, ResolvedGlobalKeyEntry, } from "./keyboard/index.js";
7
+ export { useFocusState } from "./keyboard/index.js";
8
+ export { SelectInput } from "./components/select/SelectInput.js";
9
+ export type { Item } from "./components/select/types.js";
10
+ export type { SelectInputProps } from "./components/select/types.js";
11
+ export { MultiSelectInput } from "./components/multi-select/MultiSelectInput.js";
12
+ export type { MultiSelectInputProps } from "./components/multi-select/types.js";
13
+ export { TextInput, UncontrolledTextInput } from "./components/text/TextInput.js";
14
+ export type { TextInputProps, UncontrolledTextInputProps } from "./components/text/types.js";
15
+ export { ConfirmDialog } from "./components/dialog/ConfirmDialog.js";
16
+ export type { ConfirmDialogProps } from "./components/dialog/types.js";
17
+ export { Spinner } from "./components/spinner/Spinner.js";
18
+ export type { SpinnerType } from "./components/spinner/Spinner.js";
19
+ export { ProgressBar } from "./components/progress-bar/ProgressBar.js";
20
+ export { Divider } from "./components/divider/Divider.js";
21
+ export { Badge } from "./components/badge/Badge.js";
22
+ export { KeyHint } from "./components/key-hint/KeyHint.js";
23
+ export { NumberInput } from "./components/number-input/NumberInput.js";
24
+ export { SearchInput } from "./components/search-input/SearchInput.js";
25
+ export { Tabs } from "./components/tabs/Tabs.js";
26
+ export type { Tab, TabsProps } from "./components/tabs/types.js";
27
+ export { Fold } from "./components/fold/Fold.js";
28
+ export type { FoldProps } from "./components/fold/types.js";
29
+ export { Form } from "./components/form/Form.js";
30
+ export { Field } from "./components/form/Field.js";
31
+ export { useFormContext } from "./components/form/context.js";
32
+ export type { FormProps, FieldProps, FieldRenderProps, FormContextValue, Validator, } from "./components/form/types.js";
33
+ export { LanguageProvider } from "./language/index.js";
34
+ export { useI18n } from "./language/index.js";
35
+ export type { LanguageProviderProps, I18nContextValue } from "./language/index.js";
36
+ export { ThemeProvider } from "./theme/index.js";
37
+ export { useTheme } from "./theme/index.js";
38
+ export type { ThemeProviderProps, ThemeContextValue, ThemeDefinition } from "./theme/index.js";
39
+ export { createStorage } from "./storage/index.js";
40
+ export type { StorageOptions, StorageAPI } from "./storage/index.js";
41
+ export { createBinaryStorage, TypeTag, TAG_NAMES } from "./binary-storage/index.js";
42
+ export type { BinaryStorageOptions, BinaryStorageAPI } from "./binary-storage/index.js";
43
+ export { createStreamingReader, StreamCorruptError } from "./binary-storage/StreamingReader.js";
44
+ export type { StreamingReaderOptions, StreamingReaderAPI } from "./binary-storage/StreamingReader.js";
45
+ export { openDevTool, closeDevTool } from "./dev/entrance.js";
46
+ export type { DevProps } from "./dev/types.js";
package/dist/index.js ADDED
@@ -0,0 +1,50 @@
1
+ // ── Screen System ──────────────────────────────────────────
2
+ export { registerComponent, ScenarioManagementProvider, CurrentScreen, skip, back, gotoScreen, openOverlay, closeOverlay, closeAllOverlays, activateOverlay, deactivateOverlay, openModal, closeModal, closeAllModals, useScreenSystem, ModalContext, } from "./screen/index.js";
3
+ // ── Keyboard System ────────────────────────────────────────
4
+ export { KeyboardProvider, useKeyboard } from "./keyboard/index.js";
5
+ export { normalizeKeyNames, isNormalCharacter } from "./keyboard/index.js";
6
+ export { useFocusState } from "./keyboard/index.js";
7
+ // Components — SelectInput
8
+ export { SelectInput } from "./components/select/SelectInput.js";
9
+ // Components — MultiSelectInput
10
+ export { MultiSelectInput } from "./components/multi-select/MultiSelectInput.js";
11
+ // Components — TextInput
12
+ export { TextInput, UncontrolledTextInput } from "./components/text/TextInput.js";
13
+ // Components — Dialog
14
+ export { ConfirmDialog } from "./components/dialog/ConfirmDialog.js";
15
+ // Components — Spinner
16
+ export { Spinner } from "./components/spinner/Spinner.js";
17
+ // Components — ProgressBar
18
+ export { ProgressBar } from "./components/progress-bar/ProgressBar.js";
19
+ // Components — Divider
20
+ export { Divider } from "./components/divider/Divider.js";
21
+ // Components — Badge
22
+ export { Badge } from "./components/badge/Badge.js";
23
+ // Components — KeyHint
24
+ export { KeyHint } from "./components/key-hint/KeyHint.js";
25
+ // Components — NumberInput
26
+ export { NumberInput } from "./components/number-input/NumberInput.js";
27
+ // Components — SearchInput
28
+ export { SearchInput } from "./components/search-input/SearchInput.js";
29
+ // Components — Tabs
30
+ export { Tabs } from "./components/tabs/Tabs.js";
31
+ // Components — Fold
32
+ export { Fold } from "./components/fold/Fold.js";
33
+ // Components — Form
34
+ export { Form } from "./components/form/Form.js";
35
+ export { Field } from "./components/form/Field.js";
36
+ export { useFormContext } from "./components/form/context.js";
37
+ // I18n — Language
38
+ export { LanguageProvider } from "./language/index.js";
39
+ export { useI18n } from "./language/index.js";
40
+ // Theme System
41
+ export { ThemeProvider } from "./theme/index.js";
42
+ export { useTheme } from "./theme/index.js";
43
+ // Persistence System
44
+ export { createStorage } from "./storage/index.js";
45
+ // Binary Persistence System
46
+ export { createBinaryStorage, TAG_NAMES } from "./binary-storage/index.js";
47
+ // Binary Streaming Reader
48
+ export { createStreamingReader, StreamCorruptError } from "./binary-storage/StreamingReader.js";
49
+ // Dev Tool
50
+ export { openDevTool, closeDevTool } from "./dev/entrance.js";
@@ -0,0 +1,18 @@
1
+ import type React from 'react';
2
+ import type { LayerOwner } from './context.js';
3
+ import type { GlobalKeyEntry, ScreenKeyboardLayer } from './types.js';
4
+ /**
5
+ * Check whether a global key entry should fire for the current event.
6
+ *
7
+ * Evaluates key-name matching, category whitelist, and screen-level
8
+ * global-key override (cover mechanism).
9
+ *
10
+ * @param entry The global key entry to evaluate.
11
+ * @param eventNames Normalized key names from the current event.
12
+ * @param topComponent The topmost screen component, or null if no screen is active.
13
+ * @param layersRef Mutable ref to all keyboard layers.
14
+ * @returns true if the global key matches and is not overridden.
15
+ *
16
+ * @2026-06-14 v3.4.0
17
+ */
18
+ export declare function checkGlobalKey(entry: GlobalKeyEntry, eventNames: string[], topComponent: React.ComponentType<any> | null, layersRef: React.MutableRefObject<Map<LayerOwner, ScreenKeyboardLayer>>): boolean;
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Check whether a global key entry should fire for the current event.
3
+ *
4
+ * Evaluates key-name matching, category whitelist, and screen-level
5
+ * global-key override (cover mechanism).
6
+ *
7
+ * @param entry The global key entry to evaluate.
8
+ * @param eventNames Normalized key names from the current event.
9
+ * @param topComponent The topmost screen component, or null if no screen is active.
10
+ * @param layersRef Mutable ref to all keyboard layers.
11
+ * @returns true if the global key matches and is not overridden.
12
+ *
13
+ * @2026-06-14 v3.4.0
14
+ */
15
+ export function checkGlobalKey(entry, eventNames, topComponent, layersRef) {
16
+ const keyNames = Array.isArray(entry.key) ? entry.key : [entry.key];
17
+ if (!keyNames.some((k) => eventNames.includes(k)))
18
+ return false;
19
+ if (!topComponent)
20
+ return false;
21
+ const cat = entry.category;
22
+ if (cat === undefined || cat === '*') {
23
+ }
24
+ else if (Array.isArray(cat) && cat.length === 0) {
25
+ return false;
26
+ }
27
+ else if (Array.isArray(cat)) {
28
+ if (!cat.includes(topComponent))
29
+ return false;
30
+ }
31
+ const topLayer = layersRef.current.get(topComponent);
32
+ // Global Key rules (affectOverlay + cover)
33
+ //
34
+ // When an Overlay is active:
35
+ // - [true, true] : Affects Overlay, can be overridden only by Overlay
36
+ // - [true, false]: Affects Overlay, cannot be overridden by anyone
37
+ // - [false, true] : Does NOT affect Overlay; works on Screen Stack, can be overridden by Screen Stack
38
+ // - [false, false]: Does NOT affect Overlay; works on Screen Stack, cannot be overridden by Screen Stack
39
+ //
40
+ // When NO Overlay is active (default):
41
+ // - affectOverlay = true → Key becomes inactive
42
+ // - affectOverlay = false → Key remains active on Screen Stack (override rules as above)
43
+ //
44
+ // Option executeWhenNoOverlay (only if affectOverlay = true):
45
+ // Keeps the key active on Screen Stack even without an Overlay, while preserving the original cover rule.
46
+ // @2026-06-11 v3.3.0
47
+ if (topLayer && !entry.affectOverlay && (entry.cover ?? true)) {
48
+ if (keyNames.some((k) => topLayer.globalKeyOverrides.has(k)))
49
+ return false;
50
+ }
51
+ return true;
52
+ }