@alcyone-labs/arg-parser 2.13.4 → 2.13.5

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 (39) hide show
  1. package/README.md +53 -10
  2. package/dist/config/ConfigurationManager.d.ts.map +1 -1
  3. package/dist/config/plugins/ConfigPlugin.d.ts.map +1 -1
  4. package/dist/config/plugins/TomlConfigPlugin.d.ts.map +1 -1
  5. package/dist/config/plugins/YamlConfigPlugin.d.ts.map +1 -1
  6. package/dist/config/plugins/index.d.ts +2 -2
  7. package/dist/config/plugins/index.d.ts.map +1 -1
  8. package/dist/core/ArgParser.d.ts.map +1 -1
  9. package/dist/core/ArgParserBase.d.ts.map +1 -1
  10. package/dist/core/FlagManager.d.ts.map +1 -1
  11. package/dist/core/dxt-path-resolver.d.ts.map +1 -1
  12. package/dist/core/log-path-utils.d.ts.map +1 -1
  13. package/dist/core/types.d.ts.map +1 -1
  14. package/dist/dxt/DxtGenerator-testUtils.d.ts.map +1 -1
  15. package/dist/dxt/DxtGenerator.d.ts.map +1 -1
  16. package/dist/index.cjs +7445 -10350
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.min.mjs +5188 -6369
  21. package/dist/index.min.mjs.map +1 -1
  22. package/dist/index.mjs +7377 -10338
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/mcp/ArgParserMcp.d.ts.map +1 -1
  25. package/dist/mcp/mcp-integration.d.ts.map +1 -1
  26. package/dist/mcp/mcp-notifications.d.ts.map +1 -1
  27. package/dist/mcp/mcp-prompts.d.ts.map +1 -1
  28. package/dist/mcp/mcp-protocol-versions.d.ts.map +1 -1
  29. package/dist/mcp/mcp-resources.d.ts.map +1 -1
  30. package/dist/mcp/zod-compatibility.d.ts.map +1 -1
  31. package/dist/testing/fuzzy-test-cli.d.ts.map +1 -1
  32. package/dist/testing/fuzzy-tester.d.ts.map +1 -1
  33. package/dist/tui/index.d.ts +7 -18
  34. package/dist/tui.cjs +951 -969
  35. package/dist/tui.cjs.map +1 -1
  36. package/dist/tui.mjs +901 -986
  37. package/dist/tui.mjs.map +1 -1
  38. package/dist/utils/debug-utils.d.ts.map +1 -1
  39. package/package.json +68 -64
package/dist/tui.cjs CHANGED
@@ -1,1043 +1,968 @@
1
- "use strict";
2
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const solid = require("@opentui/solid");
4
- const solidJs = require("solid-js");
5
- const web = require("solid-js/web");
6
- const EXIT_GUARD_STATE_KEY = /* @__PURE__ */ Symbol.for("@alcyone-labs/arg-parser/tui/ExitGuardState");
2
+ let __opentui_solid = require("@opentui/solid");
3
+ let solid_js = require("solid-js");
4
+ let solid_js_web = require("solid-js/web");
5
+ var EXIT_GUARD_STATE_KEY = Symbol.for("@alcyone-labs/arg-parser/tui/ExitGuardState");
7
6
  function getExitGuardState() {
8
- return process[EXIT_GUARD_STATE_KEY];
7
+ return process[EXIT_GUARD_STATE_KEY];
9
8
  }
10
9
  function setExitGuardState(state) {
11
- if (state) {
12
- process[EXIT_GUARD_STATE_KEY] = state;
13
- } else {
14
- delete process[EXIT_GUARD_STATE_KEY];
15
- }
10
+ if (state) process[EXIT_GUARD_STATE_KEY] = state;
11
+ else delete process[EXIT_GUARD_STATE_KEY];
16
12
  }
17
13
  function ExitGuard(props) {
18
- const renderer = solid.useRenderer();
19
- let state = getExitGuardState();
20
- if (!state) {
21
- const originalExit = process.exit.bind(process);
22
- state = {
23
- originalExit,
24
- renderers: /* @__PURE__ */ new Set(),
25
- activeCount: 0,
26
- isExiting: false
27
- };
28
- setExitGuardState(state);
29
- const guardedExit = ((code) => {
30
- const currentState = getExitGuardState();
31
- if (!currentState) {
32
- return originalExit(code);
33
- }
34
- if (currentState.isExiting) {
35
- return currentState.originalExit(code);
36
- }
37
- currentState.isExiting = true;
38
- try {
39
- if (typeof code === "number") {
40
- process.exitCode = code;
41
- }
42
- for (const r of currentState.renderers) {
43
- try {
44
- r.destroy();
45
- } catch {
46
- }
47
- }
48
- } finally {
49
- return currentState.originalExit(code);
50
- }
51
- });
52
- process.exit = guardedExit;
53
- }
54
- state.activeCount++;
55
- state.renderers.add(renderer);
56
- solidJs.onCleanup(() => {
57
- const state2 = getExitGuardState();
58
- if (!state2) {
59
- return;
60
- }
61
- state2.renderers.delete(renderer);
62
- state2.activeCount = Math.max(0, state2.activeCount - 1);
63
- if (state2.activeCount === 0) {
64
- process.exit = state2.originalExit;
65
- setExitGuardState(void 0);
66
- }
67
- });
68
- return props.children;
14
+ const renderer = (0, __opentui_solid.useRenderer)();
15
+ let state = getExitGuardState();
16
+ if (!state) {
17
+ const originalExit = process.exit.bind(process);
18
+ state = {
19
+ originalExit,
20
+ renderers: /* @__PURE__ */ new Set(),
21
+ activeCount: 0,
22
+ isExiting: false
23
+ };
24
+ setExitGuardState(state);
25
+ const guardedExit = ((code) => {
26
+ const currentState = getExitGuardState();
27
+ if (!currentState) return originalExit(code);
28
+ if (currentState.isExiting) return currentState.originalExit(code);
29
+ currentState.isExiting = true;
30
+ try {
31
+ if (typeof code === "number") process.exitCode = code;
32
+ for (const r of currentState.renderers) try {
33
+ r.destroy();
34
+ } catch {}
35
+ } finally {
36
+ return currentState.originalExit(code);
37
+ }
38
+ });
39
+ process.exit = guardedExit;
40
+ }
41
+ state.activeCount++;
42
+ state.renderers.add(renderer);
43
+ (0, solid_js.onCleanup)(() => {
44
+ const state$1 = getExitGuardState();
45
+ if (!state$1) return;
46
+ state$1.renderers.delete(renderer);
47
+ state$1.activeCount = Math.max(0, state$1.activeCount - 1);
48
+ if (state$1.activeCount === 0) {
49
+ process.exit = state$1.originalExit;
50
+ setExitGuardState(void 0);
51
+ }
52
+ });
53
+ return props.children;
69
54
  }
70
- const ShortcutContext = solidJs.createContext();
55
+ var ShortcutContext = (0, solid_js.createContext)();
71
56
  function ShortcutProvider(props) {
72
- const [registeredBindings, setRegisteredBindings] = solidJs.createSignal(props.bindings ?? []);
73
- const [pending, setPending] = solidJs.createSignal(null);
74
- const register = (binding) => {
75
- setRegisteredBindings((prev) => [...prev, binding]);
76
- return () => {
77
- setRegisteredBindings((prev) => prev.filter((b) => b !== binding));
78
- };
79
- };
80
- const value = {
81
- register,
82
- pending,
83
- bindings: registeredBindings
84
- };
85
- return solid.createComponent(ShortcutContext.Provider, {
86
- value,
87
- get children() {
88
- return props.children;
89
- }
90
- });
57
+ const [registeredBindings, setRegisteredBindings] = (0, solid_js.createSignal)(props.bindings ?? []);
58
+ const [pending, setPending] = (0, solid_js.createSignal)(null);
59
+ const register = (binding) => {
60
+ setRegisteredBindings((prev) => [...prev, binding]);
61
+ return () => {
62
+ setRegisteredBindings((prev) => prev.filter((b) => b !== binding));
63
+ };
64
+ };
65
+ const value = {
66
+ register,
67
+ pending,
68
+ bindings: registeredBindings
69
+ };
70
+ return (0, __opentui_solid.createComponent)(ShortcutContext.Provider, {
71
+ value,
72
+ get children() {
73
+ return props.children;
74
+ }
75
+ });
91
76
  }
92
77
  function useShortcuts() {
93
- const context = solidJs.useContext(ShortcutContext);
94
- if (!context) {
95
- throw new Error("useShortcuts must be used within a ShortcutProvider");
96
- }
97
- return context;
78
+ const context = (0, solid_js.useContext)(ShortcutContext);
79
+ if (!context) throw new Error("useShortcuts must be used within a ShortcutProvider");
80
+ return context;
98
81
  }
99
82
  const TuiThemes = {
100
- dark: {
101
- name: "dark",
102
- colors: {
103
- text: "#ffffff",
104
- muted: "#888888",
105
- background: "#1a1a1a",
106
- accent: "#00d4ff",
107
- success: "#00ff88",
108
- warning: "#ffaa00",
109
- error: "#ff4444",
110
- border: "#444444",
111
- selection: "#0066cc"
112
- }
113
- },
114
- light: {
115
- name: "light",
116
- colors: {
117
- text: "#000000",
118
- // Black text for readability
119
- muted: "#333333",
120
- // Dark gray muted
121
- background: "#e8e8e8",
122
- // Light gray background
123
- accent: "#0044aa",
124
- // Deep blue accent
125
- success: "#005500",
126
- // Dark green
127
- warning: "#885500",
128
- // Dark orange
129
- error: "#880000",
130
- // Dark red
131
- border: "#888888",
132
- selection: "#0044aa"
133
- }
134
- },
135
- monokai: {
136
- name: "monokai",
137
- colors: {
138
- text: "#f8f8f2",
139
- muted: "#75715e",
140
- background: "#272822",
141
- accent: "#ae81ff",
142
- success: "#a6e22e",
143
- warning: "#e6db74",
144
- error: "#f92672",
145
- border: "#49483e",
146
- selection: "#49483e"
147
- }
148
- },
149
- dracula: {
150
- name: "dracula",
151
- colors: {
152
- text: "#f8f8f2",
153
- muted: "#6272a4",
154
- background: "#282a36",
155
- accent: "#bd93f9",
156
- success: "#50fa7b",
157
- warning: "#f1fa8c",
158
- error: "#ff5555",
159
- border: "#44475a",
160
- selection: "#44475a"
161
- }
162
- },
163
- nord: {
164
- name: "nord",
165
- colors: {
166
- text: "#eceff4",
167
- muted: "#4c566a",
168
- background: "#2e3440",
169
- accent: "#88c0d0",
170
- success: "#a3be8c",
171
- warning: "#ebcb8b",
172
- error: "#bf616a",
173
- border: "#3b4252",
174
- selection: "#4c566a"
175
- }
176
- },
177
- solarized: {
178
- name: "solarized",
179
- colors: {
180
- text: "#839496",
181
- muted: "#586e75",
182
- background: "#002b36",
183
- accent: "#268bd2",
184
- success: "#859900",
185
- warning: "#b58900",
186
- error: "#dc322f",
187
- border: "#073642",
188
- selection: "#073642"
189
- }
190
- }
83
+ dark: {
84
+ name: "dark",
85
+ colors: {
86
+ text: "#ffffff",
87
+ muted: "#888888",
88
+ background: "#1a1a1a",
89
+ accent: "#00d4ff",
90
+ success: "#00ff88",
91
+ warning: "#ffaa00",
92
+ error: "#ff4444",
93
+ border: "#444444",
94
+ selection: "#0066cc"
95
+ }
96
+ },
97
+ light: {
98
+ name: "light",
99
+ colors: {
100
+ text: "#000000",
101
+ muted: "#333333",
102
+ background: "#e8e8e8",
103
+ accent: "#0044aa",
104
+ success: "#005500",
105
+ warning: "#885500",
106
+ error: "#880000",
107
+ border: "#888888",
108
+ selection: "#0044aa"
109
+ }
110
+ },
111
+ monokai: {
112
+ name: "monokai",
113
+ colors: {
114
+ text: "#f8f8f2",
115
+ muted: "#75715e",
116
+ background: "#272822",
117
+ accent: "#ae81ff",
118
+ success: "#a6e22e",
119
+ warning: "#e6db74",
120
+ error: "#f92672",
121
+ border: "#49483e",
122
+ selection: "#49483e"
123
+ }
124
+ },
125
+ dracula: {
126
+ name: "dracula",
127
+ colors: {
128
+ text: "#f8f8f2",
129
+ muted: "#6272a4",
130
+ background: "#282a36",
131
+ accent: "#bd93f9",
132
+ success: "#50fa7b",
133
+ warning: "#f1fa8c",
134
+ error: "#ff5555",
135
+ border: "#44475a",
136
+ selection: "#44475a"
137
+ }
138
+ },
139
+ nord: {
140
+ name: "nord",
141
+ colors: {
142
+ text: "#eceff4",
143
+ muted: "#4c566a",
144
+ background: "#2e3440",
145
+ accent: "#88c0d0",
146
+ success: "#a3be8c",
147
+ warning: "#ebcb8b",
148
+ error: "#bf616a",
149
+ border: "#3b4252",
150
+ selection: "#4c566a"
151
+ }
152
+ },
153
+ solarized: {
154
+ name: "solarized",
155
+ colors: {
156
+ text: "#839496",
157
+ muted: "#586e75",
158
+ background: "#002b36",
159
+ accent: "#268bd2",
160
+ success: "#859900",
161
+ warning: "#b58900",
162
+ error: "#dc322f",
163
+ border: "#073642",
164
+ selection: "#073642"
165
+ }
166
+ }
191
167
  };
192
168
  const THEMES = TuiThemes;
193
169
  const Theme = {
194
- /**
195
- * Start building a theme from an existing base theme.
196
- */
197
- from: (base) => ({
198
- /**
199
- * Extend the base theme with overrides.
200
- * Color overrides are shallow-merged with the base colors.
201
- */
202
- extend: (overrides) => ({
203
- name: overrides.name ?? `${base.name}-extended`,
204
- colors: { ...base.colors, ...overrides.colors }
205
- })
206
- }),
207
- /**
208
- * Create a new theme from scratch.
209
- */
210
- create: (theme) => theme,
211
- /**
212
- * Get all available theme names.
213
- */
214
- names: () => Object.keys(TuiThemes),
215
- /**
216
- * Get a theme by name, with fallback to dark theme.
217
- */
218
- get: (name) => TuiThemes[name] ?? TuiThemes["dark"]
170
+ from: (base) => ({ extend: (overrides) => ({
171
+ name: overrides.name ?? `${base.name}-extended`,
172
+ colors: {
173
+ ...base.colors,
174
+ ...overrides.colors
175
+ }
176
+ }) }),
177
+ create: (theme) => theme,
178
+ names: () => Object.keys(TuiThemes),
179
+ get: (name) => TuiThemes[name] ?? TuiThemes["dark"]
219
180
  };
220
- const ThemeContext = solidJs.createContext();
181
+ var ThemeContext = (0, solid_js.createContext)();
221
182
  function ThemeProvider(props) {
222
- const themes = { ...TuiThemes };
223
- const initialTheme = themes[props.initial ?? "dark"] ?? themes["dark"];
224
- const [current, setCurrent] = solidJs.createSignal(initialTheme);
225
- const setTheme = (name) => {
226
- if (themes[name]) {
227
- setCurrent(themes[name]);
228
- }
229
- };
230
- const cycle = () => {
231
- const currentName = current().name;
232
- const names2 = Object.keys(themes);
233
- const currentIndex = names2.indexOf(currentName);
234
- const nextIndex = (currentIndex + 1) % names2.length;
235
- setCurrent(themes[names2[nextIndex]]);
236
- };
237
- const register = (theme) => {
238
- themes[theme.name] = theme;
239
- };
240
- const names = () => Object.keys(themes);
241
- const value = {
242
- current,
243
- setTheme,
244
- cycle,
245
- register,
246
- names
247
- };
248
- return solid.createComponent(ThemeContext.Provider, {
249
- value,
250
- get children() {
251
- return props.children;
252
- }
253
- });
183
+ const themes = { ...TuiThemes };
184
+ const [current, setCurrent] = (0, solid_js.createSignal)(themes[props.initial ?? "dark"] ?? themes["dark"]);
185
+ const setTheme = (name) => {
186
+ if (themes[name]) setCurrent(themes[name]);
187
+ };
188
+ const cycle = () => {
189
+ const currentName = current().name;
190
+ const names$1 = Object.keys(themes);
191
+ setCurrent(themes[names$1[(names$1.indexOf(currentName) + 1) % names$1.length]]);
192
+ };
193
+ const register = (theme) => {
194
+ themes[theme.name] = theme;
195
+ };
196
+ const names = () => Object.keys(themes);
197
+ const value = {
198
+ current,
199
+ setTheme,
200
+ cycle,
201
+ register,
202
+ names
203
+ };
204
+ return (0, __opentui_solid.createComponent)(ThemeContext.Provider, {
205
+ value,
206
+ get children() {
207
+ return props.children;
208
+ }
209
+ });
254
210
  }
255
211
  function useTheme() {
256
- const context = solidJs.useContext(ThemeContext);
257
- if (!context) {
258
- throw new Error("useTheme must be used within a ThemeProvider");
259
- }
260
- return context;
212
+ const context = (0, solid_js.useContext)(ThemeContext);
213
+ if (!context) throw new Error("useTheme must be used within a ThemeProvider");
214
+ return context;
261
215
  }
262
- const ToastContext = solidJs.createContext();
263
- const DEFAULT_DURATION = 3e3;
216
+ var ToastContext = (0, solid_js.createContext)();
217
+ var DEFAULT_DURATION = 3e3;
264
218
  function ToastProvider(props) {
265
- const [state, setState] = solidJs.createSignal({
266
- message: "",
267
- type: "info",
268
- visible: false
269
- });
270
- let hideTimeout = null;
271
- const show = (message, type, duration) => {
272
- if (hideTimeout) {
273
- clearTimeout(hideTimeout);
274
- }
275
- setState({ message, type, visible: true });
276
- hideTimeout = setTimeout(() => {
277
- setState((prev) => ({ ...prev, visible: false }));
278
- }, duration);
279
- };
280
- const hide = () => {
281
- if (hideTimeout) {
282
- clearTimeout(hideTimeout);
283
- hideTimeout = null;
284
- }
285
- setState((prev) => ({ ...prev, visible: false }));
286
- };
287
- const value = {
288
- info: (message, duration = DEFAULT_DURATION) => show(message, "info", duration),
289
- success: (message, duration = DEFAULT_DURATION) => show(message, "success", duration),
290
- error: (message, duration = DEFAULT_DURATION) => show(message, "error", duration),
291
- warning: (message, duration = DEFAULT_DURATION) => show(message, "warning", duration),
292
- state,
293
- hide
294
- };
295
- return solid.createComponent(ToastContext.Provider, {
296
- value,
297
- get children() {
298
- return props.children;
299
- }
300
- });
219
+ const [state, setState] = (0, solid_js.createSignal)({
220
+ message: "",
221
+ type: "info",
222
+ visible: false
223
+ });
224
+ let hideTimeout = null;
225
+ const show = (message, type, duration) => {
226
+ if (hideTimeout) clearTimeout(hideTimeout);
227
+ setState({
228
+ message,
229
+ type,
230
+ visible: true
231
+ });
232
+ hideTimeout = setTimeout(() => {
233
+ setState((prev) => ({
234
+ ...prev,
235
+ visible: false
236
+ }));
237
+ }, duration);
238
+ };
239
+ const hide = () => {
240
+ if (hideTimeout) {
241
+ clearTimeout(hideTimeout);
242
+ hideTimeout = null;
243
+ }
244
+ setState((prev) => ({
245
+ ...prev,
246
+ visible: false
247
+ }));
248
+ };
249
+ const value = {
250
+ info: (message, duration = DEFAULT_DURATION) => show(message, "info", duration),
251
+ success: (message, duration = DEFAULT_DURATION) => show(message, "success", duration),
252
+ error: (message, duration = DEFAULT_DURATION) => show(message, "error", duration),
253
+ warning: (message, duration = DEFAULT_DURATION) => show(message, "warning", duration),
254
+ state,
255
+ hide
256
+ };
257
+ return (0, __opentui_solid.createComponent)(ToastContext.Provider, {
258
+ value,
259
+ get children() {
260
+ return props.children;
261
+ }
262
+ });
301
263
  }
302
264
  function useToast() {
303
- const context = solidJs.useContext(ToastContext);
304
- if (!context) {
305
- throw new Error("useToast must be used within a ToastProvider");
306
- }
307
- return context;
265
+ const context = (0, solid_js.useContext)(ToastContext);
266
+ if (!context) throw new Error("useToast must be used within a ToastProvider");
267
+ return context;
268
+ }
269
+ function enableMouseReporting() {
270
+ process.stdout.write("\x1B[?1000h");
271
+ process.stdout.write("\x1B[?1006h");
272
+ }
273
+ function disableMouseReporting() {
274
+ process.stdout.write("\x1B[?1000l");
275
+ process.stdout.write("\x1B[?1002l");
276
+ process.stdout.write("\x1B[?1003l");
277
+ process.stdout.write("\x1B[?1006l");
278
+ process.stdout.write("\x1B[?1015l");
279
+ }
280
+ function clearScreen() {
281
+ process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
282
+ }
283
+ function resetAttributes() {
284
+ process.stdout.write("\x1B[0m");
285
+ }
286
+ function restoreStdin() {
287
+ if (process.stdin.isTTY && process.stdin.setRawMode) try {
288
+ process.stdin.setRawMode(false);
289
+ } catch {}
290
+ }
291
+ function switchToAlternateScreen() {
292
+ process.stdout.write("\x1B[?1049h");
293
+ }
294
+ function switchToMainScreen() {
295
+ process.stdout.write("\x1B[?1049l");
296
+ }
297
+ function cleanupTerminal() {
298
+ switchToMainScreen();
299
+ disableMouseReporting();
300
+ clearScreen();
301
+ resetAttributes();
302
+ restoreStdin();
303
+ }
304
+ function parseMouseScroll(data) {
305
+ const sgrMatch = data.toString().match(/\x1b\[<(\d+);(\d+);(\d+)([Mm])/);
306
+ if (sgrMatch) {
307
+ const button = parseInt(sgrMatch[1], 10);
308
+ if (button === 64) return -1;
309
+ if (button === 65) return 1;
310
+ }
311
+ return 0;
308
312
  }
309
313
  function createTuiApp(App, config = {}) {
310
- const { theme = "dark", shortcuts = [], onDestroy } = config;
311
- return solid.render(
312
- () => solid.createComponent(ExitGuard, {
313
- get children() {
314
- return solid.createComponent(ThemeProvider, {
315
- get initial() {
316
- return theme;
317
- },
318
- get children() {
319
- return solid.createComponent(ShortcutProvider, {
320
- get bindings() {
321
- return shortcuts;
322
- },
323
- get children() {
324
- return solid.createComponent(ToastProvider, {
325
- get children() {
326
- return solid.createComponent(App, {});
327
- }
328
- });
329
- }
330
- });
331
- }
332
- });
333
- }
334
- }),
335
- { onDestroy }
336
- );
314
+ const { theme = "dark", shortcuts = [], onDestroy } = config;
315
+ switchToAlternateScreen();
316
+ enableMouseReporting();
317
+ return (0, __opentui_solid.render)(() => (0, __opentui_solid.createComponent)(ExitGuard, { get children() {
318
+ return (0, __opentui_solid.createComponent)(ThemeProvider, {
319
+ get initial() {
320
+ return theme;
321
+ },
322
+ get children() {
323
+ return (0, __opentui_solid.createComponent)(ShortcutProvider, {
324
+ get bindings() {
325
+ return shortcuts;
326
+ },
327
+ get children() {
328
+ return (0, __opentui_solid.createComponent)(ToastProvider, { get children() {
329
+ return (0, __opentui_solid.createComponent)(App, {});
330
+ } });
331
+ }
332
+ });
333
+ }
334
+ });
335
+ } }), { onDestroy: () => {
336
+ cleanupTerminal();
337
+ onDestroy?.();
338
+ } });
337
339
  }
338
- var _tmpl$$4 = ['<box width="100%" height="100%">', "</box>"];
339
- const TuiContext = solidJs.createContext();
340
+ var _tmpl$$4 = ["<box width=\"100%\" height=\"100%\">", "</box>"];
341
+ var TuiContext = (0, solid_js.createContext)();
340
342
  function useTui() {
341
- const context = solidJs.useContext(TuiContext);
342
- if (!context) {
343
- throw new Error("useTui must be used within a TuiProvider");
344
- }
345
- return context;
343
+ const context = (0, solid_js.useContext)(TuiContext);
344
+ if (!context) throw new Error("useTui must be used within a TuiProvider");
345
+ return context;
346
346
  }
347
347
  function TuiProvider(props) {
348
- const renderer = solid.useRenderer();
349
- const reservedRows = props.reservedRows ?? 8;
350
- props.scrollSpeed ?? 3;
351
- const [viewportHeight, setViewportHeight] = solidJs.createSignal(Math.max(10, renderer.height - reservedRows));
352
- const [viewportWidth, setViewportWidth] = solidJs.createSignal(renderer.width);
353
- const exit = (code = 0) => {
354
- process.exitCode = code;
355
- renderer.destroy();
356
- };
357
- const handleResize = (width, height) => {
358
- setViewportHeight(Math.max(10, height - reservedRows));
359
- setViewportWidth(width);
360
- };
361
- solidJs.onMount(() => {
362
- renderer.on("resize", handleResize);
363
- });
364
- solidJs.onCleanup(() => {
365
- renderer.off("resize", handleResize);
366
- });
367
- const contextValue = {
368
- viewportHeight,
369
- viewportWidth,
370
- exit
371
- };
372
- const themeName = typeof props.theme === "string" ? props.theme : props.theme?.name ?? "dark";
373
- return solid.createComponent(ExitGuard, {
374
- get children() {
375
- return solid.createComponent(TuiContext.Provider, {
376
- value: contextValue,
377
- get children() {
378
- return solid.createComponent(ThemeProvider, {
379
- initial: themeName,
380
- get children() {
381
- return solid.createComponent(ShortcutProvider, {
382
- get bindings() {
383
- return props.shortcuts ?? [];
384
- },
385
- get children() {
386
- return solid.createComponent(ToastProvider, {
387
- get children() {
388
- return web.ssr(_tmpl$$4, web.escape(props.children));
389
- }
390
- });
391
- }
392
- });
393
- }
394
- });
395
- }
396
- });
397
- }
398
- });
348
+ const renderer = (0, __opentui_solid.useRenderer)();
349
+ const reservedRows = props.reservedRows ?? 8;
350
+ props.scrollSpeed;
351
+ const [viewportHeight, setViewportHeight] = (0, solid_js.createSignal)(Math.max(10, renderer.height - reservedRows));
352
+ const [viewportWidth, setViewportWidth] = (0, solid_js.createSignal)(renderer.width);
353
+ const exit = (code = 0) => {
354
+ process.exitCode = code;
355
+ renderer.destroy();
356
+ };
357
+ const handleResize = (width, height) => {
358
+ setViewportHeight(Math.max(10, height - reservedRows));
359
+ setViewportWidth(width);
360
+ };
361
+ (0, solid_js.onMount)(() => {
362
+ switchToAlternateScreen();
363
+ enableMouseReporting();
364
+ renderer.on("resize", handleResize);
365
+ });
366
+ (0, solid_js.onCleanup)(() => {
367
+ renderer.off("resize", handleResize);
368
+ cleanupTerminal();
369
+ });
370
+ const contextValue = {
371
+ viewportHeight,
372
+ viewportWidth,
373
+ exit
374
+ };
375
+ const themeName = typeof props.theme === "string" ? props.theme : props.theme?.name ?? "dark";
376
+ return (0, __opentui_solid.createComponent)(ExitGuard, { get children() {
377
+ return (0, __opentui_solid.createComponent)(TuiContext.Provider, {
378
+ value: contextValue,
379
+ get children() {
380
+ return (0, __opentui_solid.createComponent)(ThemeProvider, {
381
+ initial: themeName,
382
+ get children() {
383
+ return (0, __opentui_solid.createComponent)(ShortcutProvider, {
384
+ get bindings() {
385
+ return props.shortcuts ?? [];
386
+ },
387
+ get children() {
388
+ return (0, __opentui_solid.createComponent)(ToastProvider, { get children() {
389
+ return (0, solid_js_web.ssr)(_tmpl$$4, (0, solid_js_web.escape)(props.children));
390
+ } });
391
+ }
392
+ });
393
+ }
394
+ });
395
+ }
396
+ });
397
+ } });
399
398
  }
400
- var _tmpl$$3 = ['<box height="1" paddingleft="2">', "</box>"], _tmpl$2$3 = ["<text", " bold>", "</text>"], _tmpl$3$2 = ["<text", "> ", " </text>"];
399
+ var _tmpl$$3 = ["<box height=\"1\" paddingleft=\"2\">", "</box>"], _tmpl$2$3 = [
400
+ "<text",
401
+ " bold>",
402
+ "</text>"
403
+ ], _tmpl$3$2 = [
404
+ "<text",
405
+ "> ",
406
+ " </text>"
407
+ ];
401
408
  function Breadcrumb(props) {
402
- const {
403
- current: theme
404
- } = useTheme();
405
- const separator = props.separator ?? "›";
406
- const accentColor = () => props.accentColor ?? theme().colors.accent;
407
- const mutedColor = () => props.mutedColor ?? theme().colors.muted;
408
- return web.ssr(_tmpl$$3, web.escape(web.createComponent(solidJs.For, {
409
- get each() {
410
- return props.segments;
411
- },
412
- children: (segment, idx) => [idx() > 0 && web.ssr(_tmpl$3$2, web.ssrAttribute("color", web.escape(mutedColor(), true), false), web.escape(separator)), web.ssr(_tmpl$2$3, web.ssrAttribute("color", web.escape(accentColor(), true), false), web.escape(segment))]
413
- })));
409
+ const { current: theme } = useTheme();
410
+ const separator = props.separator ?? "›";
411
+ const accentColor = () => props.accentColor ?? theme().colors.accent;
412
+ const mutedColor = () => props.mutedColor ?? theme().colors.muted;
413
+ return (0, solid_js_web.ssr)(_tmpl$$3, (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.For, {
414
+ get each() {
415
+ return props.segments;
416
+ },
417
+ children: (segment, idx) => [idx() > 0 && (0, solid_js_web.ssr)(_tmpl$3$2, (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(mutedColor(), true), false), (0, solid_js_web.escape)(separator)), (0, solid_js_web.ssr)(_tmpl$2$3, (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(accentColor(), true), false), (0, solid_js_web.escape)(segment))]
418
+ })));
414
419
  }
415
- var _tmpl$$2 = ['<box height="1"', "><text", ">", "", "</text></box>"], _tmpl$2$2 = ["<text bold", ' marginBottom="1">', " (", "/", ")</text>"], _tmpl$3$1 = ['<box flexdirection="column" flexgrow="1">', "", "</box>"];
420
+ var _tmpl$$2 = [
421
+ "<box height=\"1\"",
422
+ "><text",
423
+ ">",
424
+ "",
425
+ "</text></box>"
426
+ ], _tmpl$2$2 = [
427
+ "<text bold",
428
+ " marginBottom=\"1\">",
429
+ " (",
430
+ "/",
431
+ ")</text>"
432
+ ], _tmpl$3$1 = [
433
+ "<box flexdirection=\"column\" flexgrow=\"1\">",
434
+ "",
435
+ "</box>"
436
+ ];
416
437
  function unwrap(value) {
417
- return typeof value === "function" ? value() : value;
438
+ return typeof value === "function" ? value() : value;
418
439
  }
419
440
  function VirtualList(props) {
420
- const {
421
- current: theme
422
- } = useTheme();
423
- const [scrollOffset, setScrollOffset] = solidJs.createSignal(0);
424
- const items = () => unwrap(props.items);
425
- const selectedIndex = () => unwrap(props.selectedIndex);
426
- const viewportHeight = () => unwrap(props.viewportHeight ?? 20);
427
- const showIndicator = props.showIndicator ?? true;
428
- const visibleItems = solidJs.createMemo(() => {
429
- const allItems = items();
430
- const vh = viewportHeight();
431
- const start = scrollOffset();
432
- const end = Math.min(start + vh, allItems.length);
433
- return allItems.slice(start, end).map((item, localIdx) => ({
434
- item,
435
- globalIndex: start + localIdx
436
- }));
437
- });
438
- const defaultRenderItem = (item, index, selected) => {
439
- const label = props.getLabel ? props.getLabel(item) : String(item);
440
- const t = theme();
441
- return web.ssr(_tmpl$$2, web.ssrAttribute("backgroundcolor", selected ? web.escape(t.colors.selection, true) : web.escape(void 0, true), false), web.ssrAttribute("color", selected ? web.escape(t.colors.background, true) : web.escape(t.colors.text, true), false), showIndicator ? selected ? "› " : " " : "", web.escape(label));
442
- };
443
- const renderItem = props.renderItem ?? defaultRenderItem;
444
- return web.ssr(_tmpl$3$1, web.escape(web.createComponent(solidJs.Show, {
445
- get when() {
446
- return props.title;
447
- },
448
- get children() {
449
- return web.ssr(_tmpl$2$2, web.ssrAttribute("color", web.escape(theme().colors.text, true), false), web.escape(props.title), web.escape(selectedIndex()) + 1, web.escape(items().length));
450
- }
451
- })), web.escape(web.createComponent(solidJs.For, {
452
- get each() {
453
- return visibleItems();
454
- },
455
- children: ({
456
- item,
457
- globalIndex
458
- }) => renderItem(item, globalIndex, globalIndex === selectedIndex())
459
- })));
441
+ const { current: theme } = useTheme();
442
+ const [scrollOffset, setScrollOffset] = (0, solid_js.createSignal)(0);
443
+ const items = () => unwrap(props.items);
444
+ const selectedIndex = () => unwrap(props.selectedIndex);
445
+ const viewportHeight = () => unwrap(props.viewportHeight ?? 20);
446
+ const showIndicator = props.showIndicator ?? true;
447
+ const visibleItems = (0, solid_js.createMemo)(() => {
448
+ const allItems = items();
449
+ const vh = viewportHeight();
450
+ const start = scrollOffset();
451
+ const end = Math.min(start + vh, allItems.length);
452
+ return allItems.slice(start, end).map((item, localIdx) => ({
453
+ item,
454
+ globalIndex: start + localIdx
455
+ }));
456
+ });
457
+ const defaultRenderItem = (item, index, selected) => {
458
+ const label = props.getLabel ? props.getLabel(item) : String(item);
459
+ const t = theme();
460
+ return (0, solid_js_web.ssr)(_tmpl$$2, (0, solid_js_web.ssrAttribute)("backgroundcolor", selected ? (0, solid_js_web.escape)(t.colors.selection, true) : (0, solid_js_web.escape)(void 0, true), false), (0, solid_js_web.ssrAttribute)("color", selected ? (0, solid_js_web.escape)(t.colors.background, true) : (0, solid_js_web.escape)(t.colors.text, true), false), showIndicator ? selected ? "› " : " " : "", (0, solid_js_web.escape)(label));
461
+ };
462
+ const renderItem = props.renderItem ?? defaultRenderItem;
463
+ return (0, solid_js_web.ssr)(_tmpl$3$1, (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
464
+ get when() {
465
+ return props.title;
466
+ },
467
+ get children() {
468
+ return (0, solid_js_web.ssr)(_tmpl$2$2, (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(theme().colors.text, true), false), (0, solid_js_web.escape)(props.title), (0, solid_js_web.escape)(selectedIndex()) + 1, (0, solid_js_web.escape)(items().length));
469
+ }
470
+ })), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.For, {
471
+ get each() {
472
+ return visibleItems();
473
+ },
474
+ children: ({ item, globalIndex }) => renderItem(item, globalIndex, globalIndex === selectedIndex())
475
+ })));
460
476
  }
461
477
  function createVirtualListController(items, selectedIndex, setSelectedIndex, viewportHeight) {
462
- const [scrollOffset, setScrollOffset] = solidJs.createSignal(0);
463
- const adjustScroll = (newIdx) => {
464
- const vh = viewportHeight();
465
- const currentOffset = scrollOffset();
466
- if (newIdx < currentOffset) {
467
- setScrollOffset(newIdx);
468
- } else if (newIdx >= currentOffset + vh) {
469
- setScrollOffset(newIdx - vh + 1);
470
- }
471
- };
472
- const scrollBy = (delta) => {
473
- const maxOffset = Math.max(0, items().length - viewportHeight());
474
- setScrollOffset((o) => Math.max(0, Math.min(maxOffset, o + delta)));
475
- };
476
- const selectPrevious = () => {
477
- const newIdx = Math.max(0, selectedIndex() - 1);
478
- setSelectedIndex(newIdx);
479
- adjustScroll(newIdx);
480
- };
481
- const selectNext = () => {
482
- const newIdx = Math.min(items().length - 1, selectedIndex() + 1);
483
- setSelectedIndex(newIdx);
484
- adjustScroll(newIdx);
485
- };
486
- return {
487
- scrollOffset,
488
- adjustScroll,
489
- scrollBy,
490
- selectPrevious,
491
- selectNext
492
- };
478
+ const [scrollOffset, setScrollOffset] = (0, solid_js.createSignal)(0);
479
+ const adjustScroll = (newIdx) => {
480
+ const vh = viewportHeight();
481
+ const currentOffset = scrollOffset();
482
+ if (newIdx < currentOffset) setScrollOffset(newIdx);
483
+ else if (newIdx >= currentOffset + vh) setScrollOffset(newIdx - vh + 1);
484
+ };
485
+ const scrollBy = (delta) => {
486
+ const maxOffset = Math.max(0, items().length - viewportHeight());
487
+ setScrollOffset((o) => Math.max(0, Math.min(maxOffset, o + delta)));
488
+ };
489
+ const selectPrevious = () => {
490
+ const newIdx = Math.max(0, selectedIndex() - 1);
491
+ setSelectedIndex(newIdx);
492
+ adjustScroll(newIdx);
493
+ };
494
+ const selectNext = () => {
495
+ const newIdx = Math.min(items().length - 1, selectedIndex() + 1);
496
+ setSelectedIndex(newIdx);
497
+ adjustScroll(newIdx);
498
+ };
499
+ return {
500
+ scrollOffset,
501
+ adjustScroll,
502
+ scrollBy,
503
+ selectPrevious,
504
+ selectNext
505
+ };
493
506
  }
494
- var _tmpl$$1 = ['<box height="1"', "><text", "> ", "</text></box>"], _tmpl$2$1 = ['<box width="100%" height="100%" flexdirection="column"', '><box height="3" borderstyle="single"', ' justifycontent="center" alignitems="center"><text bold', ">", "", " </text></box>", '<box flexgrow="1" flexdirection="row"><box', ' borderstyle="single"', ' flexdirection="column" padding="1">', '</box><box flexgrow="1" borderstyle="single"', ' flexdirection="column" padding="2">', "</box></box>", "</box>"];
507
+ var _tmpl$$1 = [
508
+ "<box height=\"1\"",
509
+ "><text",
510
+ "> ",
511
+ "</text></box>"
512
+ ], _tmpl$2$1 = [
513
+ "<box width=\"100%\" height=\"100%\" flexdirection=\"column\"",
514
+ "><box height=\"3\" borderstyle=\"single\"",
515
+ " justifycontent=\"center\" alignitems=\"center\"><text bold",
516
+ ">",
517
+ "",
518
+ " </text></box>",
519
+ "<box flexgrow=\"1\" flexdirection=\"row\"><box",
520
+ " borderstyle=\"single\"",
521
+ " flexdirection=\"column\" padding=\"1\">",
522
+ "</box><box flexgrow=\"1\" borderstyle=\"single\"",
523
+ " flexdirection=\"column\" padding=\"2\">",
524
+ "</box></box>",
525
+ "</box>"
526
+ ];
495
527
  function MasterDetail(props) {
496
- const {
497
- current: theme
498
- } = useTheme();
499
- const masterWidth = props.masterWidth ?? "35%";
500
- return web.ssr(_tmpl$2$1, web.ssrAttribute("backgroundcolor", web.escape(theme().colors.background, true), false), web.ssrAttribute("bordercolor", web.escape(theme().colors.accent, true), false), web.ssrAttribute("color", web.escape(theme().colors.accent, true), false), props.headerIcon ? ` ${web.escape(props.headerIcon)} ` : " ", web.escape(props.header), web.escape(web.createComponent(solidJs.Show, {
501
- get when() {
502
- return props.breadcrumb && props.breadcrumb.length > 0;
503
- },
504
- get children() {
505
- return web.createComponent(Breadcrumb, {
506
- get segments() {
507
- return props.breadcrumb;
508
- }
509
- });
510
- }
511
- })), web.ssrAttribute("width", web.escape(masterWidth, true), false), web.ssrAttribute("bordercolor", web.escape(theme().colors.border, true), false), web.escape(props.master), web.ssrAttribute("bordercolor", web.escape(theme().colors.border, true), false), web.escape(props.detail), web.escape(web.createComponent(solidJs.Show, {
512
- get when() {
513
- return props.footer;
514
- },
515
- get children() {
516
- return web.ssr(_tmpl$$1, web.ssrAttribute("backgroundcolor", web.escape(theme().colors.background, true), false), web.ssrAttribute("color", web.escape(theme().colors.muted, true), false), web.escape(props.footer));
517
- }
518
- })));
528
+ const { current: theme } = useTheme();
529
+ const masterWidth = props.masterWidth ?? "35%";
530
+ return (0, solid_js_web.ssr)(_tmpl$2$1, (0, solid_js_web.ssrAttribute)("backgroundcolor", (0, solid_js_web.escape)(theme().colors.background, true), false), (0, solid_js_web.ssrAttribute)("bordercolor", (0, solid_js_web.escape)(theme().colors.accent, true), false), (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(theme().colors.accent, true), false), props.headerIcon ? ` ${(0, solid_js_web.escape)(props.headerIcon)} ` : " ", (0, solid_js_web.escape)(props.header), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
531
+ get when() {
532
+ return props.breadcrumb && props.breadcrumb.length > 0;
533
+ },
534
+ get children() {
535
+ return (0, solid_js_web.createComponent)(Breadcrumb, { get segments() {
536
+ return props.breadcrumb;
537
+ } });
538
+ }
539
+ })), (0, solid_js_web.ssrAttribute)("width", (0, solid_js_web.escape)(masterWidth, true), false), (0, solid_js_web.ssrAttribute)("bordercolor", (0, solid_js_web.escape)(theme().colors.border, true), false), (0, solid_js_web.escape)(props.master), (0, solid_js_web.ssrAttribute)("bordercolor", (0, solid_js_web.escape)(theme().colors.border, true), false), (0, solid_js_web.escape)(props.detail), (0, solid_js_web.escape)((0, solid_js_web.createComponent)(solid_js.Show, {
540
+ get when() {
541
+ return props.footer;
542
+ },
543
+ get children() {
544
+ return (0, solid_js_web.ssr)(_tmpl$$1, (0, solid_js_web.ssrAttribute)("backgroundcolor", (0, solid_js_web.escape)(theme().colors.background, true), false), (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(theme().colors.muted, true), false), (0, solid_js_web.escape)(props.footer));
545
+ }
546
+ })));
519
547
  }
520
548
  function parseWidth(width) {
521
- if (width === void 0) return "30%";
522
- if (typeof width === "number") return width;
523
- if (width.endsWith("%")) {
524
- const percent = parseInt(width.replace("%", ""), 10);
525
- return `${percent}%`;
526
- }
527
- return width;
549
+ if (width === void 0) return "30%";
550
+ if (typeof width === "number") return width;
551
+ if (width.endsWith("%")) return `${parseInt(width.replace("%", ""), 10)}%`;
552
+ return width;
528
553
  }
529
- function MasterDetailLayout$1(props) {
530
- const masterWidth = parseWidth(props.masterWidth);
531
- const gap = props.gap ?? 1;
532
- const showDivider = props.showDivider ?? true;
533
- return {
534
- type: "box",
535
- props: {
536
- flexDirection: "row",
537
- width: "100%",
538
- height: "100%"
539
- },
540
- children: [
541
- // Master panel
542
- {
543
- type: "box",
544
- props: {
545
- flexBasis: masterWidth,
546
- flexShrink: 0,
547
- overflow: "scroll"
548
- },
549
- children: props.master
550
- },
551
- // Divider (optional)
552
- ...showDivider ? [
553
- {
554
- type: "box",
555
- props: {
556
- width: 1,
557
- marginLeft: Math.floor(gap / 2),
558
- marginRight: Math.ceil(gap / 2)
559
- },
560
- children: {
561
- type: "text",
562
- props: {
563
- style: { fg: "#444444" }
564
- },
565
- children: "│".repeat(100)
566
- // Repeating for height
567
- }
568
- }
569
- ] : [],
570
- // Detail panel
571
- {
572
- type: "box",
573
- props: {
574
- flexGrow: 1,
575
- overflow: "scroll"
576
- },
577
- children: props.detail
578
- }
579
- ]
580
- };
554
+ function MasterDetailLayout(props) {
555
+ const masterWidth = parseWidth(props.masterWidth);
556
+ const gap = props.gap ?? 1;
557
+ const showDivider = props.showDivider ?? true;
558
+ return {
559
+ type: "box",
560
+ props: {
561
+ flexDirection: "row",
562
+ width: "100%",
563
+ height: "100%"
564
+ },
565
+ children: [
566
+ {
567
+ type: "box",
568
+ props: {
569
+ flexBasis: masterWidth,
570
+ flexShrink: 0,
571
+ overflow: "scroll"
572
+ },
573
+ children: props.master
574
+ },
575
+ ...showDivider ? [{
576
+ type: "box",
577
+ props: {
578
+ width: 1,
579
+ marginLeft: Math.floor(gap / 2),
580
+ marginRight: Math.ceil(gap / 2)
581
+ },
582
+ children: {
583
+ type: "text",
584
+ props: { style: { fg: "#444444" } },
585
+ children: "│".repeat(100)
586
+ }
587
+ }] : [],
588
+ {
589
+ type: "box",
590
+ props: {
591
+ flexGrow: 1,
592
+ overflow: "scroll"
593
+ },
594
+ children: props.detail
595
+ }
596
+ ]
597
+ };
581
598
  }
582
599
  function DrillDownNavigator(props) {
583
- const [stack, setStack] = solidJs.createSignal([]);
584
- const push = (view) => {
585
- setStack((prev) => [...prev, view]);
586
- props.onNavigate?.(stack().length + 1);
587
- };
588
- const pop = () => {
589
- if (stack().length > 0) {
590
- setStack((prev) => prev.slice(0, -1));
591
- props.onNavigate?.(stack().length - 1);
592
- }
593
- };
594
- const replace = (view) => {
595
- if (stack().length > 0) {
596
- setStack((prev) => [...prev.slice(0, -1), view]);
597
- } else {
598
- push(view);
599
- }
600
- };
601
- const reset = () => {
602
- setStack([]);
603
- props.onNavigate?.(0);
604
- };
605
- const depth = () => stack().length;
606
- const canGoBack = () => stack().length > 0;
607
- const api = {
608
- push,
609
- pop,
610
- replace,
611
- reset,
612
- depth,
613
- canGoBack
614
- };
615
- const currentView = () => {
616
- const currentStack = stack();
617
- if (currentStack.length > 0) {
618
- return currentStack[currentStack.length - 1]();
619
- }
620
- return props.children(api);
621
- };
622
- return {
623
- type: "box",
624
- props: {
625
- width: "100%",
626
- height: "100%",
627
- onKeyDown: (event) => {
628
- if (event.defaultPrevented) return;
629
- if ((event.key === "Escape" || event.key === "ArrowLeft") && canGoBack()) {
630
- pop();
631
- }
632
- }
633
- },
634
- children: currentView()
635
- };
600
+ const [stack, setStack] = (0, solid_js.createSignal)([]);
601
+ const push = (view) => {
602
+ setStack((prev) => [...prev, view]);
603
+ props.onNavigate?.(stack().length + 1);
604
+ };
605
+ const pop = () => {
606
+ if (stack().length > 0) {
607
+ setStack((prev) => prev.slice(0, -1));
608
+ props.onNavigate?.(stack().length - 1);
609
+ }
610
+ };
611
+ const replace = (view) => {
612
+ if (stack().length > 0) setStack((prev) => [...prev.slice(0, -1), view]);
613
+ else push(view);
614
+ };
615
+ const reset = () => {
616
+ setStack([]);
617
+ props.onNavigate?.(0);
618
+ };
619
+ const depth = () => stack().length;
620
+ const canGoBack = () => stack().length > 0;
621
+ const api = {
622
+ push,
623
+ pop,
624
+ replace,
625
+ reset,
626
+ depth,
627
+ canGoBack
628
+ };
629
+ const currentView = () => {
630
+ const currentStack = stack();
631
+ if (currentStack.length > 0) return currentStack[currentStack.length - 1]();
632
+ return props.children(api);
633
+ };
634
+ return {
635
+ type: "box",
636
+ props: {
637
+ width: "100%",
638
+ height: "100%",
639
+ onKeyDown: (event) => {
640
+ if (event.defaultPrevented) return;
641
+ if ((event.key === "Escape" || event.key === "ArrowLeft") && canGoBack()) pop();
642
+ }
643
+ },
644
+ children: currentView()
645
+ };
636
646
  }
637
647
  function Card(props) {
638
- const borderStyle = props.borderStyle ?? "single";
639
- const padding = props.padding ?? 1;
640
- let borderColor = props.borderColor;
641
- if (!borderColor) {
642
- try {
643
- const { current } = useTheme();
644
- borderColor = current().colors.border;
645
- } catch {
646
- borderColor = "#444444";
647
- }
648
- }
649
- return {
650
- type: "box",
651
- props: {
652
- flexDirection: "column",
653
- width: props.width,
654
- height: props.height,
655
- ...props.onClick && { onMouseDown: props.onClick },
656
- style: {
657
- border: borderStyle !== "none" ? borderStyle : void 0,
658
- borderColor,
659
- padding
660
- }
661
- },
662
- children: [
663
- // Title row (if provided)
664
- ...props.title ? [
665
- {
666
- type: "text",
667
- props: {
668
- style: { bold: true }
669
- },
670
- children: ` ${props.title} `
671
- }
672
- ] : [],
673
- // Content
674
- props.children
675
- ]
676
- };
648
+ const borderStyle = props.borderStyle ?? "single";
649
+ const padding = props.padding ?? 1;
650
+ let borderColor = props.borderColor;
651
+ if (!borderColor) try {
652
+ const { current } = useTheme();
653
+ borderColor = current().colors.border;
654
+ } catch {
655
+ borderColor = "#444444";
656
+ }
657
+ return {
658
+ type: "box",
659
+ props: {
660
+ flexDirection: "column",
661
+ width: props.width,
662
+ height: props.height,
663
+ ...props.onClick && { onMouseDown: props.onClick },
664
+ style: {
665
+ border: borderStyle !== "none" ? borderStyle : void 0,
666
+ borderColor,
667
+ padding
668
+ }
669
+ },
670
+ children: [...props.title ? [{
671
+ type: "text",
672
+ props: { style: { bold: true } },
673
+ children: ` ${props.title} `
674
+ }] : [], props.children]
675
+ };
677
676
  }
678
677
  function formatValue(value, format, currency) {
679
- if (typeof value === "string") return value;
680
- switch (format) {
681
- case "compact":
682
- if (value >= 1e9)
683
- return `${(value / 1e9).toFixed(1)}B`;
684
- if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
685
- if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
686
- return value.toString();
687
- case "percent":
688
- return `${(value * 100).toFixed(1)}%`;
689
- case "currency":
690
- return new Intl.NumberFormat("en-US", {
691
- style: "currency",
692
- currency: currency ?? "USD",
693
- minimumFractionDigits: 0,
694
- maximumFractionDigits: 2
695
- }).format(value);
696
- case "number":
697
- default:
698
- return new Intl.NumberFormat("en-US").format(value);
699
- }
678
+ if (typeof value === "string") return value;
679
+ switch (format) {
680
+ case "compact":
681
+ if (value >= 1e9) return `${(value / 1e9).toFixed(1)}B`;
682
+ if (value >= 1e6) return `${(value / 1e6).toFixed(1)}M`;
683
+ if (value >= 1e3) return `${(value / 1e3).toFixed(1)}K`;
684
+ return value.toString();
685
+ case "percent": return `${(value * 100).toFixed(1)}%`;
686
+ case "currency": return new Intl.NumberFormat("en-US", {
687
+ style: "currency",
688
+ currency: currency ?? "USD",
689
+ minimumFractionDigits: 0,
690
+ maximumFractionDigits: 2
691
+ }).format(value);
692
+ case "number":
693
+ default: return new Intl.NumberFormat("en-US").format(value);
694
+ }
700
695
  }
701
696
  function getTrendIndicator(trend) {
702
- switch (trend) {
703
- case "up":
704
- return { symbol: "▲", color: "#00ff88" };
705
- case "down":
706
- return { symbol: "▼", color: "#ff4444" };
707
- case "neutral":
708
- default:
709
- return { symbol: "─", color: "#888888" };
710
- }
697
+ switch (trend) {
698
+ case "up": return {
699
+ symbol: "▲",
700
+ color: "#00ff88"
701
+ };
702
+ case "down": return {
703
+ symbol: "▼",
704
+ color: "#ff4444"
705
+ };
706
+ case "neutral":
707
+ default: return {
708
+ symbol: "─",
709
+ color: "#888888"
710
+ };
711
+ }
711
712
  }
712
713
  function StatCard(props) {
713
- const formattedValue = formatValue(
714
- props.value,
715
- props.format ?? "number",
716
- props.currency
717
- );
718
- const trendIndicator = props.trend ? getTrendIndicator(props.trend) : null;
719
- return {
720
- type: "box",
721
- props: {
722
- flexDirection: "column",
723
- width: props.width,
724
- padding: 1,
725
- style: {
726
- border: "single"
727
- },
728
- ...props.onClick && { onMouseDown: props.onClick }
729
- },
730
- children: [
731
- // Label
732
- {
733
- type: "text",
734
- props: {
735
- style: { fg: "#888888" }
736
- },
737
- children: props.label
738
- },
739
- // Value with optional trend
740
- {
741
- type: "box",
742
- props: {
743
- flexDirection: "row",
744
- gap: 1
745
- },
746
- children: [
747
- {
748
- type: "text",
749
- props: {
750
- style: { bold: true, fg: "#ffffff" }
751
- },
752
- children: formattedValue
753
- },
754
- ...trendIndicator ? [
755
- {
756
- type: "text",
757
- props: {
758
- style: { fg: trendIndicator.color }
759
- },
760
- children: trendIndicator.symbol
761
- }
762
- ] : []
763
- ]
764
- }
765
- ]
766
- };
714
+ const formattedValue = formatValue(props.value, props.format ?? "number", props.currency);
715
+ const trendIndicator = props.trend ? getTrendIndicator(props.trend) : null;
716
+ return {
717
+ type: "box",
718
+ props: {
719
+ flexDirection: "column",
720
+ width: props.width,
721
+ padding: 1,
722
+ style: { border: "single" },
723
+ ...props.onClick && { onMouseDown: props.onClick }
724
+ },
725
+ children: [{
726
+ type: "text",
727
+ props: { style: { fg: "#888888" } },
728
+ children: props.label
729
+ }, {
730
+ type: "box",
731
+ props: {
732
+ flexDirection: "row",
733
+ gap: 1
734
+ },
735
+ children: [{
736
+ type: "text",
737
+ props: { style: {
738
+ bold: true,
739
+ fg: "#ffffff"
740
+ } },
741
+ children: formattedValue
742
+ }, ...trendIndicator ? [{
743
+ type: "text",
744
+ props: { style: { fg: trendIndicator.color } },
745
+ children: trendIndicator.symbol
746
+ }] : []]
747
+ }]
748
+ };
767
749
  }
768
750
  function MarkdownBlock(props) {
769
- const { current } = useTheme();
770
- return {
771
- type: "box",
772
- props: {
773
- flexDirection: "column",
774
- width: props.width ?? "100%",
775
- height: props.height,
776
- padding: props.padding ?? 0,
777
- overflow: "scroll"
778
- },
779
- children: [
780
- {
781
- type: "text",
782
- props: {
783
- style: {
784
- fg: current().colors.text
785
- },
786
- text: props.content
787
- }
788
- }
789
- ]
790
- };
751
+ const { current } = useTheme();
752
+ return {
753
+ type: "box",
754
+ props: {
755
+ flexDirection: "column",
756
+ width: props.width ?? "100%",
757
+ height: props.height,
758
+ padding: props.padding ?? 0,
759
+ overflow: "scroll"
760
+ },
761
+ children: [{
762
+ type: "text",
763
+ props: {
764
+ style: { fg: current().colors.text },
765
+ text: props.content
766
+ }
767
+ }]
768
+ };
791
769
  }
792
770
  function Button(props) {
793
- const { current } = useTheme();
794
- const [isHovered, setIsHovered] = solidJs.createSignal(false);
795
- const [isPressed, setIsPressed] = solidJs.createSignal(false);
796
- const getBackgroundColor = () => {
797
- if (props.disabled) return current().colors.muted;
798
- switch (props.variant) {
799
- case "danger":
800
- return isPressed() ? "#bd2c00" : isHovered() ? "#c82829" : current().colors.error;
801
- case "primary":
802
- default:
803
- return isPressed() ? current().colors.selection : isHovered() ? current().colors.accent : current().colors.accent;
804
- }
805
- };
806
- const getTextColor = () => {
807
- if (props.disabled) return current().colors.background;
808
- return props.variant === "primary" || props.variant === "danger" ? "#ffffff" : current().colors.text;
809
- };
810
- return {
811
- type: "box",
812
- props: {
813
- width: props.width,
814
- height: 3,
815
- // Standard button height with border
816
- flexDirection: "row",
817
- alignItems: "center",
818
- justifyContent: "center",
819
- style: {
820
- border: "single",
821
- borderColor: isHovered() && !props.disabled ? current().colors.text : current().colors.border,
822
- bg: getBackgroundColor()
823
- },
824
- // Event handlers
825
- onMouseOver: () => !props.disabled && setIsHovered(true),
826
- onMouseOut: () => {
827
- setIsHovered(false);
828
- setIsPressed(false);
829
- },
830
- onMouseDown: () => !props.disabled && setIsPressed(true),
831
- onMouseUp: () => {
832
- if (!props.disabled && isPressed()) {
833
- setIsPressed(false);
834
- props.onClick?.();
835
- }
836
- }
837
- },
838
- children: [
839
- {
840
- type: "text",
841
- props: {
842
- style: {
843
- fg: getTextColor(),
844
- bold: true
845
- },
846
- text: ` ${props.label} `
847
- }
848
- }
849
- ]
850
- };
771
+ const { current } = useTheme();
772
+ const [isHovered, setIsHovered] = (0, solid_js.createSignal)(false);
773
+ const [isPressed, setIsPressed] = (0, solid_js.createSignal)(false);
774
+ const getBackgroundColor = () => {
775
+ if (props.disabled) return current().colors.muted;
776
+ switch (props.variant) {
777
+ case "danger": return isPressed() ? "#bd2c00" : isHovered() ? "#c82829" : current().colors.error;
778
+ case "primary":
779
+ default: return isPressed() ? current().colors.selection : isHovered() ? current().colors.accent : current().colors.accent;
780
+ }
781
+ };
782
+ const getTextColor = () => {
783
+ if (props.disabled) return current().colors.background;
784
+ return props.variant === "primary" || props.variant === "danger" ? "#ffffff" : current().colors.text;
785
+ };
786
+ return {
787
+ type: "box",
788
+ props: {
789
+ width: props.width,
790
+ height: 3,
791
+ flexDirection: "row",
792
+ alignItems: "center",
793
+ justifyContent: "center",
794
+ style: {
795
+ border: "single",
796
+ borderColor: isHovered() && !props.disabled ? current().colors.text : current().colors.border,
797
+ bg: getBackgroundColor()
798
+ },
799
+ onMouseOver: () => !props.disabled && setIsHovered(true),
800
+ onMouseOut: () => {
801
+ setIsHovered(false);
802
+ setIsPressed(false);
803
+ },
804
+ onMouseDown: () => !props.disabled && setIsPressed(true),
805
+ onMouseUp: () => {
806
+ if (!props.disabled && isPressed()) {
807
+ setIsPressed(false);
808
+ props.onClick?.();
809
+ }
810
+ }
811
+ },
812
+ children: [{
813
+ type: "text",
814
+ props: {
815
+ style: {
816
+ fg: getTextColor(),
817
+ bold: true
818
+ },
819
+ text: ` ${props.label} `
820
+ }
821
+ }]
822
+ };
851
823
  }
852
- var _tmpl$ = ['<box width="100%" height="100%" flexdirection="column"', '><box height="3" borderstyle="single"', ' justifycontent="center" alignitems="center"><text bold', "> ", " </text></box>", '<box flexgrow="1" flexdirection="row">', "</box>", "</box>"], _tmpl$2 = ['<box height="1" paddingleft="2"', ">", "</box>"], _tmpl$3 = ["<text", " bold>", "</text>"], _tmpl$4 = ["<text", "> › </text>"], _tmpl$5 = ['<box height="1"', "><text", "> ", "</text></box>"], _tmpl$6 = ["<box", ' borderstyle="single"', ' flexdirection="column" padding="1">', "</box>"], _tmpl$7 = ['<box flexgrow="1" borderstyle="single"', ' flexdirection="column" padding="2">', "</box>"], _tmpl$8 = ['<box height="1"', "><text", ">", "", "</text></box>"];
824
+ var _tmpl$ = [
825
+ "<box width=\"100%\" height=\"100%\" flexdirection=\"column\"",
826
+ "><box height=\"3\" borderstyle=\"single\"",
827
+ " justifycontent=\"center\" alignitems=\"center\"><text bold",
828
+ "> ",
829
+ " </text></box>",
830
+ "<box flexgrow=\"1\" flexdirection=\"row\">",
831
+ "</box>",
832
+ "</box>"
833
+ ], _tmpl$2 = [
834
+ "<box height=\"1\" paddingleft=\"2\"",
835
+ ">",
836
+ "</box>"
837
+ ], _tmpl$3 = [
838
+ "<text",
839
+ " bold>",
840
+ "</text>"
841
+ ], _tmpl$4 = ["<text", "> › </text>"], _tmpl$5 = [
842
+ "<box height=\"1\"",
843
+ "><text",
844
+ "> ",
845
+ "</text></box>"
846
+ ], _tmpl$6 = [
847
+ "<box",
848
+ " borderstyle=\"single\"",
849
+ " flexdirection=\"column\" padding=\"1\">",
850
+ "</box>"
851
+ ], _tmpl$7 = [
852
+ "<box flexgrow=\"1\" borderstyle=\"single\"",
853
+ " flexdirection=\"column\" padding=\"2\">",
854
+ "</box>"
855
+ ], _tmpl$8 = [
856
+ "<box height=\"1\"",
857
+ "><text",
858
+ ">",
859
+ "",
860
+ "</text></box>"
861
+ ];
853
862
  const LAYOUT_THEMES = {
854
- dark: {
855
- bg: "#0d0d0d",
856
- fg: "#f5f5f5",
857
- accent: "#00d4ff",
858
- muted: "#999999",
859
- error: "#ff4444",
860
- success: "#44ff44",
861
- border: "#444444",
862
- selection: "#00d4ff",
863
- selectionFg: "#000000"
864
- },
865
- light: {
866
- bg: "#e8e8e8",
867
- fg: "#000000",
868
- accent: "#0044aa",
869
- muted: "#333333",
870
- error: "#880000",
871
- success: "#005500",
872
- border: "#888888",
873
- selection: "#0044aa",
874
- selectionFg: "#ffffff"
875
- },
876
- monokai: {
877
- bg: "#272822",
878
- fg: "#f8f8f2",
879
- accent: "#a6e22e",
880
- muted: "#75715e",
881
- error: "#f92672",
882
- success: "#a6e22e",
883
- border: "#49483e",
884
- selection: "#a6e22e",
885
- selectionFg: "#272822"
886
- }
863
+ dark: {
864
+ bg: "#0d0d0d",
865
+ fg: "#f5f5f5",
866
+ accent: "#00d4ff",
867
+ muted: "#999999",
868
+ error: "#ff4444",
869
+ success: "#44ff44",
870
+ border: "#444444",
871
+ selection: "#00d4ff",
872
+ selectionFg: "#000000"
873
+ },
874
+ light: {
875
+ bg: "#e8e8e8",
876
+ fg: "#000000",
877
+ accent: "#0044aa",
878
+ muted: "#333333",
879
+ error: "#880000",
880
+ success: "#005500",
881
+ border: "#888888",
882
+ selection: "#0044aa",
883
+ selectionFg: "#ffffff"
884
+ },
885
+ monokai: {
886
+ bg: "#272822",
887
+ fg: "#f8f8f2",
888
+ accent: "#a6e22e",
889
+ muted: "#75715e",
890
+ error: "#f92672",
891
+ success: "#a6e22e",
892
+ border: "#49483e",
893
+ selection: "#a6e22e",
894
+ selectionFg: "#272822"
895
+ }
887
896
  };
888
897
  function resolveTheme(theme) {
889
- if (!theme) return LAYOUT_THEMES.dark;
890
- if (typeof theme === "string") return LAYOUT_THEMES[theme] ?? LAYOUT_THEMES.dark;
891
- return theme;
898
+ if (!theme) return LAYOUT_THEMES.dark;
899
+ if (typeof theme === "string") return LAYOUT_THEMES[theme] ?? LAYOUT_THEMES.dark;
900
+ return theme;
892
901
  }
893
- function MasterDetailLayout(props) {
894
- const t = resolveTheme(props.theme);
895
- props.masterWidth ?? "35%";
896
- return web.ssr(_tmpl$, web.ssrAttribute("backgroundcolor", web.escape(t.bg, true), false), web.ssrAttribute("bordercolor", web.escape(t.accent, true), false), web.ssrAttribute("color", web.escape(t.accent, true), false), web.escape(props.header), props.breadcrumb && props.breadcrumb.length > 0 && web.ssr(_tmpl$2, web.ssrAttribute("backgroundcolor", web.escape(t.bg, true), false), web.escape(props.breadcrumb.map((segment, idx) => [idx > 0 && web.ssr(_tmpl$4, web.ssrAttribute("color", web.escape(t.muted, true), false)), web.ssr(_tmpl$3, web.ssrAttribute("color", web.escape(t.accent, true), false), web.escape(segment))]))), web.escape(props.children), props.footer && web.ssr(_tmpl$5, web.ssrAttribute("backgroundcolor", web.escape(t.bg, true), false), web.ssrAttribute("color", web.escape(t.muted, true), false), web.escape(props.footer)));
902
+ function MasterDetailLayout$1(props) {
903
+ const t = resolveTheme(props.theme);
904
+ props.masterWidth;
905
+ return (0, solid_js_web.ssr)(_tmpl$, (0, solid_js_web.ssrAttribute)("backgroundcolor", (0, solid_js_web.escape)(t.bg, true), false), (0, solid_js_web.ssrAttribute)("bordercolor", (0, solid_js_web.escape)(t.accent, true), false), (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(t.accent, true), false), (0, solid_js_web.escape)(props.header), props.breadcrumb && props.breadcrumb.length > 0 && (0, solid_js_web.ssr)(_tmpl$2, (0, solid_js_web.ssrAttribute)("backgroundcolor", (0, solid_js_web.escape)(t.bg, true), false), (0, solid_js_web.escape)(props.breadcrumb.map((segment, idx) => [idx > 0 && (0, solid_js_web.ssr)(_tmpl$4, (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(t.muted, true), false)), (0, solid_js_web.ssr)(_tmpl$3, (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(t.accent, true), false), (0, solid_js_web.escape)(segment))]))), (0, solid_js_web.escape)(props.children), props.footer && (0, solid_js_web.ssr)(_tmpl$5, (0, solid_js_web.ssrAttribute)("backgroundcolor", (0, solid_js_web.escape)(t.bg, true), false), (0, solid_js_web.ssrAttribute)("color", (0, solid_js_web.escape)(t.muted, true), false), (0, solid_js_web.escape)(props.footer)));
897
906
  }
898
907
  function MasterPanel(props) {
899
- const t = resolveTheme(props.theme);
900
- return web.ssr(_tmpl$6, web.ssrAttribute("width", web.escape(props.width, true) ?? "35%", false), web.ssrAttribute("bordercolor", web.escape(t.border, true), false), web.escape(props.children));
908
+ const t = resolveTheme(props.theme);
909
+ return (0, solid_js_web.ssr)(_tmpl$6, (0, solid_js_web.ssrAttribute)("width", (0, solid_js_web.escape)(props.width, true) ?? "35%", false), (0, solid_js_web.ssrAttribute)("bordercolor", (0, solid_js_web.escape)(t.border, true), false), (0, solid_js_web.escape)(props.children));
901
910
  }
902
911
  function DetailPanel(props) {
903
- const t = resolveTheme(props.theme);
904
- return web.ssr(_tmpl$7, web.ssrAttribute("bordercolor", web.escape(t.border, true), false), web.escape(props.children));
912
+ return (0, solid_js_web.ssr)(_tmpl$7, (0, solid_js_web.ssrAttribute)("bordercolor", (0, solid_js_web.escape)(resolveTheme(props.theme).border, true), false), (0, solid_js_web.escape)(props.children));
905
913
  }
906
914
  function ListItem(props) {
907
- const t = resolveTheme(props.theme);
908
- return web.ssr(_tmpl$8, web.ssrAttribute("backgroundcolor", props.selected ? web.escape(t.selection, true) : web.escape(void 0, true), false), web.ssrAttribute("color", props.selected ? web.escape(t.selectionFg, true) : web.escape(t.fg, true), false), props.selected ? "› " : " ", web.escape(props.label));
915
+ const t = resolveTheme(props.theme);
916
+ return (0, solid_js_web.ssr)(_tmpl$8, (0, solid_js_web.ssrAttribute)("backgroundcolor", props.selected ? (0, solid_js_web.escape)(t.selection, true) : (0, solid_js_web.escape)(void 0, true), false), (0, solid_js_web.ssrAttribute)("color", props.selected ? (0, solid_js_web.escape)(t.selectionFg, true) : (0, solid_js_web.escape)(t.fg, true), false), props.selected ? "› " : " ", (0, solid_js_web.escape)(props.label));
909
917
  }
910
918
  function useVirtualScroll(items, _selectedIdx, viewportHeight) {
911
- const [scrollOffset, setScrollOffset] = solidJs.createSignal(0);
912
- const adjustScroll = (newIdx) => {
913
- const vh = viewportHeight();
914
- const currentOffset = scrollOffset();
915
- if (newIdx < currentOffset) {
916
- setScrollOffset(newIdx);
917
- } else if (newIdx >= currentOffset + vh) {
918
- setScrollOffset(newIdx - vh + 1);
919
- }
920
- };
921
- const visibleItems = solidJs.createMemo(() => {
922
- const allItems = items();
923
- const vh = viewportHeight();
924
- const start = scrollOffset();
925
- const end = Math.min(start + vh, allItems.length);
926
- return allItems.slice(start, end).map((item, localIdx) => ({
927
- item,
928
- globalIndex: start + localIdx
929
- }));
930
- });
931
- const scrollBy = (delta) => {
932
- const maxOffset = Math.max(0, items().length - viewportHeight());
933
- setScrollOffset((o) => Math.max(0, Math.min(maxOffset, o + delta)));
934
- };
935
- return { visibleItems, adjustScroll, scrollOffset, scrollBy };
919
+ const [scrollOffset, setScrollOffset] = (0, solid_js.createSignal)(0);
920
+ const adjustScroll = (newIdx) => {
921
+ const vh = viewportHeight();
922
+ const currentOffset = scrollOffset();
923
+ if (newIdx < currentOffset) setScrollOffset(newIdx);
924
+ else if (newIdx >= currentOffset + vh) setScrollOffset(newIdx - vh + 1);
925
+ };
926
+ const visibleItems = (0, solid_js.createMemo)(() => {
927
+ const allItems = items();
928
+ const vh = viewportHeight();
929
+ const start = scrollOffset();
930
+ const end = Math.min(start + vh, allItems.length);
931
+ return allItems.slice(start, end).map((item, localIdx) => ({
932
+ item,
933
+ globalIndex: start + localIdx
934
+ }));
935
+ });
936
+ const scrollBy = (delta) => {
937
+ const maxOffset = Math.max(0, items().length - viewportHeight());
938
+ setScrollOffset((o) => Math.max(0, Math.min(maxOffset, o + delta)));
939
+ };
940
+ return {
941
+ visibleItems,
942
+ adjustScroll,
943
+ scrollOffset,
944
+ scrollBy
945
+ };
936
946
  }
937
947
  function getViewportHeight(reservedRows = 8, minHeight = 10) {
938
- return Math.max(minHeight, (process.stdout.rows || 24) - reservedRows);
939
- }
940
- function enableMouseReporting() {
941
- process.stdout.write("\x1B[?1000h");
942
- process.stdout.write("\x1B[?1006h");
943
- }
944
- function disableMouseReporting() {
945
- process.stdout.write("\x1B[?1000l");
946
- process.stdout.write("\x1B[?1002l");
947
- process.stdout.write("\x1B[?1003l");
948
- process.stdout.write("\x1B[?1006l");
949
- process.stdout.write("\x1B[?1015l");
950
- }
951
- function clearScreen() {
952
- process.stdout.write("\x1B[2J\x1B[3J\x1B[H");
953
- }
954
- function resetAttributes() {
955
- process.stdout.write("\x1B[0m");
956
- }
957
- function restoreStdin() {
958
- if (process.stdin.isTTY && process.stdin.setRawMode) {
959
- try {
960
- process.stdin.setRawMode(false);
961
- } catch {
962
- }
963
- }
964
- }
965
- function switchToMainScreen() {
966
- process.stdout.write("\x1B[?1049l");
967
- }
968
- function cleanupTerminal() {
969
- switchToMainScreen();
970
- disableMouseReporting();
971
- clearScreen();
972
- resetAttributes();
973
- restoreStdin();
974
- }
975
- function parseMouseScroll(data) {
976
- const str = data.toString();
977
- const sgrMatch = str.match(/\x1b\[<(\d+);(\d+);(\d+)([Mm])/);
978
- if (sgrMatch) {
979
- const button = parseInt(sgrMatch[1], 10);
980
- if (button === 64) return -1;
981
- if (button === 65) return 1;
982
- }
983
- return 0;
948
+ return Math.max(minHeight, (process.stdout.rows || 24) - reservedRows);
984
949
  }
985
950
  function useMouse(options = {}) {
986
- const { onScroll, scrollSpeed = 3 } = options;
987
- const handleInput = (data) => {
988
- const scrollDir = parseMouseScroll(data);
989
- if (scrollDir !== 0 && onScroll) {
990
- onScroll(scrollDir * scrollSpeed);
991
- }
992
- };
993
- solidJs.onMount(() => {
994
- enableMouseReporting();
995
- if (process.stdin.isTTY) {
996
- process.stdin.setRawMode(true);
997
- }
998
- process.stdin.on("data", handleInput);
999
- });
1000
- solidJs.onCleanup(() => {
1001
- disableMouseReporting();
1002
- process.stdin.off("data", handleInput);
1003
- });
951
+ const { onScroll, scrollSpeed = 3 } = options;
952
+ const handleInput = (data) => {
953
+ const scrollDir = parseMouseScroll(data);
954
+ if (scrollDir !== 0 && onScroll) onScroll(scrollDir * scrollSpeed);
955
+ };
956
+ (0, solid_js.onMount)(() => {
957
+ enableMouseReporting();
958
+ if (process.stdin.isTTY) process.stdin.setRawMode(true);
959
+ process.stdin.on("data", handleInput);
960
+ });
961
+ (0, solid_js.onCleanup)(() => {
962
+ disableMouseReporting();
963
+ process.stdin.off("data", handleInput);
964
+ });
1004
965
  }
1005
- Object.defineProperty(exports, "createComponent", {
1006
- enumerable: true,
1007
- get: () => solid.createComponent
1008
- });
1009
- Object.defineProperty(exports, "effect", {
1010
- enumerable: true,
1011
- get: () => solid.effect
1012
- });
1013
- Object.defineProperty(exports, "insert", {
1014
- enumerable: true,
1015
- get: () => solid.insert
1016
- });
1017
- Object.defineProperty(exports, "memo", {
1018
- enumerable: true,
1019
- get: () => solid.memo
1020
- });
1021
- Object.defineProperty(exports, "mergeProps", {
1022
- enumerable: true,
1023
- get: () => solid.mergeProps
1024
- });
1025
- Object.defineProperty(exports, "render", {
1026
- enumerable: true,
1027
- get: () => solid.render
1028
- });
1029
- Object.defineProperty(exports, "spread", {
1030
- enumerable: true,
1031
- get: () => solid.spread
1032
- });
1033
- Object.defineProperty(exports, "useKeyboard", {
1034
- enumerable: true,
1035
- get: () => solid.useKeyboard
1036
- });
1037
- Object.defineProperty(exports, "useRenderer", {
1038
- enumerable: true,
1039
- get: () => solid.useRenderer
1040
- });
1041
966
  exports.Breadcrumb = Breadcrumb;
1042
967
  exports.Button = Button;
1043
968
  exports.Card = Card;
@@ -1047,8 +972,8 @@ exports.LAYOUT_THEMES = LAYOUT_THEMES;
1047
972
  exports.ListItem = ListItem;
1048
973
  exports.MarkdownBlock = MarkdownBlock;
1049
974
  exports.MasterDetail = MasterDetail;
1050
- exports.MasterDetailLayout = MasterDetailLayout$1;
1051
- exports.MasterDetailTemplate = MasterDetailLayout;
975
+ exports.MasterDetailLayout = MasterDetailLayout;
976
+ exports.MasterDetailTemplate = MasterDetailLayout$1;
1052
977
  exports.MasterPanel = MasterPanel;
1053
978
  exports.ShortcutProvider = ShortcutProvider;
1054
979
  exports.StatCard = StatCard;
@@ -1061,18 +986,75 @@ exports.TuiThemes = TuiThemes;
1061
986
  exports.VirtualList = VirtualList;
1062
987
  exports.cleanupTerminal = cleanupTerminal;
1063
988
  exports.clearScreen = clearScreen;
989
+ Object.defineProperty(exports, "createComponent", {
990
+ enumerable: true,
991
+ get: function() {
992
+ return __opentui_solid.createComponent;
993
+ }
994
+ });
1064
995
  exports.createTuiApp = createTuiApp;
1065
996
  exports.createVirtualListController = createVirtualListController;
1066
997
  exports.disableMouseReporting = disableMouseReporting;
998
+ Object.defineProperty(exports, "effect", {
999
+ enumerable: true,
1000
+ get: function() {
1001
+ return __opentui_solid.effect;
1002
+ }
1003
+ });
1067
1004
  exports.enableMouseReporting = enableMouseReporting;
1068
1005
  exports.getViewportHeight = getViewportHeight;
1006
+ Object.defineProperty(exports, "insert", {
1007
+ enumerable: true,
1008
+ get: function() {
1009
+ return __opentui_solid.insert;
1010
+ }
1011
+ });
1012
+ Object.defineProperty(exports, "memo", {
1013
+ enumerable: true,
1014
+ get: function() {
1015
+ return __opentui_solid.memo;
1016
+ }
1017
+ });
1018
+ Object.defineProperty(exports, "mergeProps", {
1019
+ enumerable: true,
1020
+ get: function() {
1021
+ return __opentui_solid.mergeProps;
1022
+ }
1023
+ });
1069
1024
  exports.parseMouseScroll = parseMouseScroll;
1025
+ Object.defineProperty(exports, "render", {
1026
+ enumerable: true,
1027
+ get: function() {
1028
+ return __opentui_solid.render;
1029
+ }
1030
+ });
1070
1031
  exports.resetAttributes = resetAttributes;
1071
1032
  exports.restoreStdin = restoreStdin;
1033
+ Object.defineProperty(exports, "spread", {
1034
+ enumerable: true,
1035
+ get: function() {
1036
+ return __opentui_solid.spread;
1037
+ }
1038
+ });
1039
+ exports.switchToAlternateScreen = switchToAlternateScreen;
1040
+ exports.switchToMainScreen = switchToMainScreen;
1041
+ Object.defineProperty(exports, "useKeyboard", {
1042
+ enumerable: true,
1043
+ get: function() {
1044
+ return __opentui_solid.useKeyboard;
1045
+ }
1046
+ });
1072
1047
  exports.useMouse = useMouse;
1048
+ Object.defineProperty(exports, "useRenderer", {
1049
+ enumerable: true,
1050
+ get: function() {
1051
+ return __opentui_solid.useRenderer;
1052
+ }
1053
+ });
1073
1054
  exports.useShortcuts = useShortcuts;
1074
1055
  exports.useTheme = useTheme;
1075
1056
  exports.useToast = useToast;
1076
1057
  exports.useTui = useTui;
1077
1058
  exports.useVirtualScroll = useVirtualScroll;
1078
- //# sourceMappingURL=tui.cjs.map
1059
+
1060
+ //# sourceMappingURL=tui.cjs.map