giggles 0.3.10 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-4LEJFY5C.js +56 -0
- package/dist/chunk-5BONVNP7.js +49 -0
- package/dist/{chunk-WJRBHS5J.js → chunk-JTJH45JR.js} +3 -6
- package/dist/index.d.ts +2 -1
- package/dist/index.js +5 -5
- package/dist/markdown/index.js +1 -1
- package/dist/terminal/index.d.ts +4 -2
- package/dist/terminal/index.js +7 -76
- package/dist/ui/index.d.ts +83 -25
- package/dist/ui/index.js +194 -65
- package/package.json +1 -1
- package/dist/chunk-7PDVDYFB.js +0 -23
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// src/terminal/hooks/useTerminalFocus.ts
|
|
2
|
+
import { useEffect, useRef } from "react";
|
|
3
|
+
function useTerminalFocus(callback) {
|
|
4
|
+
const callbackRef = useRef(callback);
|
|
5
|
+
callbackRef.current = callback;
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const handler = (data) => {
|
|
8
|
+
const str = data.toString();
|
|
9
|
+
if (str.includes("\x1B[I")) callbackRef.current(true);
|
|
10
|
+
if (str.includes("\x1B[O")) callbackRef.current(false);
|
|
11
|
+
};
|
|
12
|
+
process.stdin.on("data", handler);
|
|
13
|
+
const timer = setTimeout(() => {
|
|
14
|
+
process.stdout.write("\x1B[?1004h");
|
|
15
|
+
}, 0);
|
|
16
|
+
return () => {
|
|
17
|
+
clearTimeout(timer);
|
|
18
|
+
process.stdout.write("\x1B[?1004l");
|
|
19
|
+
process.stdin.off("data", handler);
|
|
20
|
+
};
|
|
21
|
+
}, []);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// src/terminal/hooks/useShellout.ts
|
|
25
|
+
import { execa } from "execa";
|
|
26
|
+
import { useCallback, useState } from "react";
|
|
27
|
+
import { useStdin } from "ink";
|
|
28
|
+
function useShellOut() {
|
|
29
|
+
const [, setRedrawCount] = useState(0);
|
|
30
|
+
const { setRawMode } = useStdin();
|
|
31
|
+
const run = useCallback(
|
|
32
|
+
async (command) => {
|
|
33
|
+
process.stdout.write("\x1B[?1049l");
|
|
34
|
+
setRawMode(false);
|
|
35
|
+
try {
|
|
36
|
+
const result = await execa(command, { stdio: "inherit", shell: true, reject: false });
|
|
37
|
+
return { exitCode: result.exitCode ?? 0 };
|
|
38
|
+
} finally {
|
|
39
|
+
setRawMode(true);
|
|
40
|
+
process.stdout.write("\x1B[?1049h");
|
|
41
|
+
process.stdout.write("\x1B[2J");
|
|
42
|
+
process.stdout.write("\x1B[H");
|
|
43
|
+
setRedrawCount((c) => c + 1);
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
[setRawMode]
|
|
47
|
+
);
|
|
48
|
+
return {
|
|
49
|
+
run
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export {
|
|
54
|
+
useTerminalFocus,
|
|
55
|
+
useShellOut
|
|
56
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
// src/terminal/hooks/useTerminalSize.ts
|
|
2
|
+
import { useEffect, useState } from "react";
|
|
3
|
+
function useTerminalSize() {
|
|
4
|
+
const [size, setSize] = useState({
|
|
5
|
+
rows: process.stdout.rows,
|
|
6
|
+
columns: process.stdout.columns
|
|
7
|
+
});
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
const handleResize = () => {
|
|
10
|
+
setSize({
|
|
11
|
+
rows: process.stdout.rows,
|
|
12
|
+
columns: process.stdout.columns
|
|
13
|
+
});
|
|
14
|
+
};
|
|
15
|
+
process.stdout.on("resize", handleResize);
|
|
16
|
+
return () => {
|
|
17
|
+
process.stdout.off("resize", handleResize);
|
|
18
|
+
};
|
|
19
|
+
}, []);
|
|
20
|
+
return size;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// src/terminal/components/AlternateScreen.tsx
|
|
24
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
25
|
+
import { Box } from "ink";
|
|
26
|
+
import { Fragment, jsx } from "react/jsx-runtime";
|
|
27
|
+
var _a;
|
|
28
|
+
var isTTY = typeof process !== "undefined" && ((_a = process.stdout) == null ? void 0 : _a.write);
|
|
29
|
+
function AlternateScreen({ children, fullScreen = true }) {
|
|
30
|
+
const [ready, setReady] = useState2(!isTTY);
|
|
31
|
+
const { rows, columns } = useTerminalSize();
|
|
32
|
+
useEffect2(() => {
|
|
33
|
+
if (!isTTY) return;
|
|
34
|
+
process.stdout.write("\x1B[?1049h");
|
|
35
|
+
process.stdout.write("\x1B[2J");
|
|
36
|
+
process.stdout.write("\x1B[H");
|
|
37
|
+
setReady(true);
|
|
38
|
+
return () => {
|
|
39
|
+
process.stdout.write("\x1B[?1049l");
|
|
40
|
+
};
|
|
41
|
+
}, []);
|
|
42
|
+
if (!ready) return null;
|
|
43
|
+
return fullScreen ? /* @__PURE__ */ jsx(Box, { height: rows, width: columns, children }) : /* @__PURE__ */ jsx(Fragment, { children });
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export {
|
|
47
|
+
useTerminalSize,
|
|
48
|
+
AlternateScreen
|
|
49
|
+
};
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
} from "./chunk-EVD6YPS3.js";
|
|
4
4
|
|
|
5
5
|
// src/ui/CodeBlock.tsx
|
|
6
|
-
import Prism from "prismjs";
|
|
7
6
|
import { Box, Text } from "ink";
|
|
7
|
+
import Prism from "prismjs";
|
|
8
8
|
import { jsx } from "react/jsx-runtime";
|
|
9
9
|
var defaultTokenColors = {
|
|
10
10
|
keyword: "#C678DD",
|
|
@@ -22,15 +22,12 @@ var defaultTokenColors = {
|
|
|
22
22
|
inserted: "#98C379",
|
|
23
23
|
deleted: "#E06C75"
|
|
24
24
|
};
|
|
25
|
-
function CodeBlock({ children, language,
|
|
25
|
+
function CodeBlock({ children, language, tokenColors, ...boxProps }) {
|
|
26
26
|
const theme = useTheme();
|
|
27
27
|
const colors = { ...defaultTokenColors, ...tokenColors };
|
|
28
28
|
const grammar = language ? Prism.languages[language] : void 0;
|
|
29
29
|
const content = grammar ? renderTokens(Prism.tokenize(children, grammar), colors) : /* @__PURE__ */ jsx(Text, { children });
|
|
30
|
-
|
|
31
|
-
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: content }) });
|
|
32
|
-
}
|
|
33
|
-
return /* @__PURE__ */ jsx(Box, { paddingX: 1, borderStyle: "single", borderColor: theme.borderColor, children: /* @__PURE__ */ jsx(Text, { children: content }) });
|
|
30
|
+
return /* @__PURE__ */ jsx(Box, { paddingX: 1, borderStyle: "round", borderColor: theme.borderColor, ...boxProps, children: /* @__PURE__ */ jsx(Text, { children: content }) });
|
|
34
31
|
}
|
|
35
32
|
function renderTokens(tokens, colors) {
|
|
36
33
|
return tokens.map((token, idx) => {
|
package/dist/index.d.ts
CHANGED
|
@@ -30,9 +30,10 @@ declare function useTheme(): GigglesTheme;
|
|
|
30
30
|
|
|
31
31
|
type GigglesProviderProps = {
|
|
32
32
|
theme?: Partial<GigglesTheme>;
|
|
33
|
+
fullScreen?: boolean;
|
|
33
34
|
children: React__default.ReactNode;
|
|
34
35
|
};
|
|
35
|
-
declare function GigglesProvider({ theme, children }: GigglesProviderProps): react_jsx_runtime.JSX.Element;
|
|
36
|
+
declare function GigglesProvider({ theme, fullScreen, children }: GigglesProviderProps): react_jsx_runtime.JSX.Element;
|
|
36
37
|
|
|
37
38
|
declare function useKeybindings(focus: FocusHandle, bindings: Keybindings, options?: KeybindingOptions): void;
|
|
38
39
|
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AlternateScreen
|
|
3
|
-
} from "./chunk-7PDVDYFB.js";
|
|
4
1
|
import {
|
|
5
2
|
FocusGroup,
|
|
6
3
|
FocusNodeContext,
|
|
@@ -19,11 +16,14 @@ import {
|
|
|
19
16
|
ThemeProvider,
|
|
20
17
|
useTheme
|
|
21
18
|
} from "./chunk-EVD6YPS3.js";
|
|
19
|
+
import {
|
|
20
|
+
AlternateScreen
|
|
21
|
+
} from "./chunk-5BONVNP7.js";
|
|
22
22
|
|
|
23
23
|
// src/core/GigglesProvider.tsx
|
|
24
24
|
import { jsx } from "react/jsx-runtime";
|
|
25
|
-
function GigglesProvider({ theme, children }) {
|
|
26
|
-
return /* @__PURE__ */ jsx(AlternateScreen, { children: /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx(FocusProvider, { children: /* @__PURE__ */ jsx(InputProvider, { children: /* @__PURE__ */ jsx(InputRouter, { children }) }) }) }) });
|
|
25
|
+
function GigglesProvider({ theme, fullScreen, children }) {
|
|
26
|
+
return /* @__PURE__ */ jsx(AlternateScreen, { fullScreen, children: /* @__PURE__ */ jsx(ThemeProvider, { theme, children: /* @__PURE__ */ jsx(FocusProvider, { children: /* @__PURE__ */ jsx(InputProvider, { children: /* @__PURE__ */ jsx(InputRouter, { children }) }) }) }) });
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
// src/core/router/Router.tsx
|
package/dist/markdown/index.js
CHANGED
package/dist/terminal/index.d.ts
CHANGED
|
@@ -10,9 +10,11 @@ declare function useTerminalSize(): TerminalSize;
|
|
|
10
10
|
|
|
11
11
|
declare function useTerminalFocus(callback: (focused: boolean) => void): void;
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
type AlternateScreenProps = {
|
|
14
14
|
children: ReactNode;
|
|
15
|
-
|
|
15
|
+
fullScreen?: boolean;
|
|
16
|
+
};
|
|
17
|
+
declare function AlternateScreen({ children, fullScreen }: AlternateScreenProps): react_jsx_runtime.JSX.Element | null;
|
|
16
18
|
|
|
17
19
|
declare function useShellOut(): {
|
|
18
20
|
run: (command: string) => Promise<{
|
package/dist/terminal/index.js
CHANGED
|
@@ -1,80 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
rows: process.stdout.rows,
|
|
10
|
-
columns: process.stdout.columns
|
|
11
|
-
});
|
|
12
|
-
useEffect(() => {
|
|
13
|
-
const handleResize = () => {
|
|
14
|
-
setSize({
|
|
15
|
-
rows: process.stdout.rows,
|
|
16
|
-
columns: process.stdout.columns
|
|
17
|
-
});
|
|
18
|
-
};
|
|
19
|
-
process.stdout.on("resize", handleResize);
|
|
20
|
-
return () => {
|
|
21
|
-
process.stdout.off("resize", handleResize);
|
|
22
|
-
};
|
|
23
|
-
}, []);
|
|
24
|
-
return size;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
// src/terminal/hooks/useTerminalFocus.ts
|
|
28
|
-
import { useEffect as useEffect2, useRef } from "react";
|
|
29
|
-
function useTerminalFocus(callback) {
|
|
30
|
-
const callbackRef = useRef(callback);
|
|
31
|
-
callbackRef.current = callback;
|
|
32
|
-
useEffect2(() => {
|
|
33
|
-
const handler = (data) => {
|
|
34
|
-
const str = data.toString();
|
|
35
|
-
if (str.includes("\x1B[I")) callbackRef.current(true);
|
|
36
|
-
if (str.includes("\x1B[O")) callbackRef.current(false);
|
|
37
|
-
};
|
|
38
|
-
process.stdin.on("data", handler);
|
|
39
|
-
const timer = setTimeout(() => {
|
|
40
|
-
process.stdout.write("\x1B[?1004h");
|
|
41
|
-
}, 0);
|
|
42
|
-
return () => {
|
|
43
|
-
clearTimeout(timer);
|
|
44
|
-
process.stdout.write("\x1B[?1004l");
|
|
45
|
-
process.stdin.off("data", handler);
|
|
46
|
-
};
|
|
47
|
-
}, []);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// src/terminal/hooks/useShellout.ts
|
|
51
|
-
import { execa } from "execa";
|
|
52
|
-
import { useCallback, useState as useState2 } from "react";
|
|
53
|
-
import { useStdin } from "ink";
|
|
54
|
-
function useShellOut() {
|
|
55
|
-
const [, setRedrawCount] = useState2(0);
|
|
56
|
-
const { setRawMode } = useStdin();
|
|
57
|
-
const run = useCallback(
|
|
58
|
-
async (command) => {
|
|
59
|
-
process.stdout.write("\x1B[?1049l");
|
|
60
|
-
setRawMode(false);
|
|
61
|
-
try {
|
|
62
|
-
const result = await execa(command, { stdio: "inherit", shell: true, reject: false });
|
|
63
|
-
return { exitCode: result.exitCode ?? 0 };
|
|
64
|
-
} finally {
|
|
65
|
-
setRawMode(true);
|
|
66
|
-
process.stdout.write("\x1B[?1049h");
|
|
67
|
-
process.stdout.write("\x1B[2J");
|
|
68
|
-
process.stdout.write("\x1B[H");
|
|
69
|
-
setRedrawCount((c) => c + 1);
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
[setRawMode]
|
|
73
|
-
);
|
|
74
|
-
return {
|
|
75
|
-
run
|
|
76
|
-
};
|
|
77
|
-
}
|
|
2
|
+
useShellOut,
|
|
3
|
+
useTerminalFocus
|
|
4
|
+
} from "../chunk-4LEJFY5C.js";
|
|
5
|
+
import {
|
|
6
|
+
AlternateScreen,
|
|
7
|
+
useTerminalSize
|
|
8
|
+
} from "../chunk-5BONVNP7.js";
|
|
78
9
|
export {
|
|
79
10
|
AlternateScreen,
|
|
80
11
|
useShellOut,
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import { R as RegisteredKeybinding } from '../types-Dmw9TKt4.js';
|
|
3
3
|
import React__default from 'react';
|
|
4
|
-
import 'ink';
|
|
4
|
+
import { BoxProps } from 'ink';
|
|
5
5
|
|
|
6
6
|
type CommandPaletteRenderProps = {
|
|
7
7
|
query: string;
|
|
@@ -144,29 +144,30 @@ type VirtualListProps<T> = VirtualListBase<T> & ({
|
|
|
144
144
|
});
|
|
145
145
|
declare function VirtualList<T>({ items, highlightIndex, scrollOffset: controlledOffset, gap, maxVisible, paginatorStyle, render }: VirtualListProps<T>): react_jsx_runtime.JSX.Element;
|
|
146
146
|
|
|
147
|
-
type
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
147
|
+
type ViewportRef = {
|
|
148
|
+
scrollTo: (offset: number) => void;
|
|
149
|
+
scrollBy: (delta: number) => void;
|
|
150
|
+
scrollToTop: () => void;
|
|
151
|
+
scrollToBottom: () => void;
|
|
152
|
+
scrollToItem: (index: number) => void;
|
|
153
|
+
getScrollOffset: () => number;
|
|
154
|
+
getContentHeight: () => number;
|
|
155
|
+
getViewportHeight: () => number;
|
|
151
156
|
};
|
|
152
|
-
type ViewportProps
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
paginatorStyle?: PaginatorStyle;
|
|
158
|
-
render?: (props: ViewportRenderProps<T>) => React__default.ReactNode;
|
|
157
|
+
type ViewportProps = {
|
|
158
|
+
children?: React__default.ReactNode;
|
|
159
|
+
height: number;
|
|
160
|
+
keybindings?: boolean;
|
|
161
|
+
footer?: React__default.ReactNode;
|
|
159
162
|
};
|
|
160
|
-
declare
|
|
163
|
+
declare const Viewport: React__default.ForwardRefExoticComponent<ViewportProps & React__default.RefAttributes<ViewportRef>>;
|
|
161
164
|
|
|
162
|
-
type
|
|
163
|
-
type ModalProps = {
|
|
165
|
+
type ModalProps = Omit<BoxProps, 'children'> & {
|
|
164
166
|
children: React__default.ReactNode;
|
|
165
167
|
onClose: () => void;
|
|
166
168
|
title?: string;
|
|
167
|
-
borderStyle?: BorderStyle;
|
|
168
169
|
};
|
|
169
|
-
declare function Modal({ children, onClose, title,
|
|
170
|
+
declare function Modal({ children, onClose, title, ...boxProps }: ModalProps): react_jsx_runtime.JSX.Element;
|
|
170
171
|
|
|
171
172
|
type BadgeVariant = 'round' | 'arrow' | 'plain';
|
|
172
173
|
type BadgeProps = {
|
|
@@ -177,14 +178,12 @@ type BadgeProps = {
|
|
|
177
178
|
};
|
|
178
179
|
declare function Badge({ children, color, background, variant }: BadgeProps): react_jsx_runtime.JSX.Element;
|
|
179
180
|
|
|
180
|
-
type PanelProps = {
|
|
181
|
+
type PanelProps = Omit<BoxProps, 'children'> & {
|
|
181
182
|
children: React__default.ReactNode;
|
|
182
183
|
title?: string;
|
|
183
|
-
width?: number;
|
|
184
|
-
borderColor?: string;
|
|
185
184
|
footer?: React__default.ReactNode;
|
|
186
185
|
};
|
|
187
|
-
declare function Panel({ children, title, width, borderColor, footer }: PanelProps): react_jsx_runtime.JSX.Element;
|
|
186
|
+
declare function Panel({ children, title, width, borderColor, footer, ...boxProps }: PanelProps): react_jsx_runtime.JSX.Element;
|
|
188
187
|
|
|
189
188
|
type TokenColors = {
|
|
190
189
|
keyword: string;
|
|
@@ -202,12 +201,71 @@ type TokenColors = {
|
|
|
202
201
|
inserted: string;
|
|
203
202
|
deleted: string;
|
|
204
203
|
};
|
|
205
|
-
type CodeBlockProps = {
|
|
204
|
+
type CodeBlockProps = Omit<BoxProps, 'children'> & {
|
|
206
205
|
children: string;
|
|
207
206
|
language?: string;
|
|
208
|
-
showBorder?: boolean;
|
|
209
207
|
tokenColors?: Partial<TokenColors>;
|
|
210
208
|
};
|
|
211
|
-
declare function CodeBlock({ children, language,
|
|
209
|
+
declare function CodeBlock({ children, language, tokenColors, ...boxProps }: CodeBlockProps): react_jsx_runtime.JSX.Element;
|
|
210
|
+
|
|
211
|
+
type SpinnerDef = {
|
|
212
|
+
frames: string[];
|
|
213
|
+
interval: number;
|
|
214
|
+
};
|
|
215
|
+
declare const spinners: {
|
|
216
|
+
line: {
|
|
217
|
+
frames: string[];
|
|
218
|
+
interval: number;
|
|
219
|
+
};
|
|
220
|
+
dot: {
|
|
221
|
+
frames: string[];
|
|
222
|
+
interval: number;
|
|
223
|
+
};
|
|
224
|
+
miniDot: {
|
|
225
|
+
frames: string[];
|
|
226
|
+
interval: number;
|
|
227
|
+
};
|
|
228
|
+
jump: {
|
|
229
|
+
frames: string[];
|
|
230
|
+
interval: number;
|
|
231
|
+
};
|
|
232
|
+
pulse: {
|
|
233
|
+
frames: string[];
|
|
234
|
+
interval: number;
|
|
235
|
+
};
|
|
236
|
+
points: {
|
|
237
|
+
frames: string[];
|
|
238
|
+
interval: number;
|
|
239
|
+
};
|
|
240
|
+
clock: {
|
|
241
|
+
frames: string[];
|
|
242
|
+
interval: number;
|
|
243
|
+
};
|
|
244
|
+
hearts: {
|
|
245
|
+
frames: string[];
|
|
246
|
+
interval: number;
|
|
247
|
+
};
|
|
248
|
+
moon: {
|
|
249
|
+
frames: string[];
|
|
250
|
+
interval: number;
|
|
251
|
+
};
|
|
252
|
+
meter: {
|
|
253
|
+
frames: string[];
|
|
254
|
+
interval: number;
|
|
255
|
+
};
|
|
256
|
+
hamburger: {
|
|
257
|
+
frames: string[];
|
|
258
|
+
interval: number;
|
|
259
|
+
};
|
|
260
|
+
ellipsis: {
|
|
261
|
+
frames: string[];
|
|
262
|
+
interval: number;
|
|
263
|
+
};
|
|
264
|
+
};
|
|
265
|
+
type SpinnerProps = {
|
|
266
|
+
spinner?: SpinnerDef;
|
|
267
|
+
color?: string;
|
|
268
|
+
};
|
|
269
|
+
declare function Spinner({ spinner, color }: SpinnerProps): react_jsx_runtime.JSX.Element;
|
|
212
270
|
|
|
213
|
-
export { Autocomplete, type AutocompleteRenderProps, Badge, type BadgeProps, type BadgeVariant, CodeBlock, CommandPalette, type CommandPaletteRenderProps, Confirm, Modal, MultiSelect, type MultiSelectRenderProps, Paginator, type PaginatorStyle, Panel, type PanelProps, Select, type SelectOption, type SelectRenderProps, TextInput, type TextInputRenderProps, type TokenColors, Viewport, type
|
|
271
|
+
export { Autocomplete, type AutocompleteRenderProps, Badge, type BadgeProps, type BadgeVariant, CodeBlock, CommandPalette, type CommandPaletteRenderProps, Confirm, Modal, MultiSelect, type MultiSelectRenderProps, Paginator, type PaginatorStyle, Panel, type PanelProps, Select, type SelectOption, type SelectRenderProps, Spinner, type SpinnerDef, TextInput, type TextInputRenderProps, type TokenColors, Viewport, type ViewportRef, VirtualList, type VirtualListRenderProps, spinners };
|
package/dist/ui/index.js
CHANGED
|
@@ -7,10 +7,14 @@ import {
|
|
|
7
7
|
} from "../chunk-CKA5JJ4B.js";
|
|
8
8
|
import {
|
|
9
9
|
CodeBlock
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-JTJH45JR.js";
|
|
11
11
|
import {
|
|
12
12
|
useTheme
|
|
13
13
|
} from "../chunk-EVD6YPS3.js";
|
|
14
|
+
import "../chunk-4LEJFY5C.js";
|
|
15
|
+
import {
|
|
16
|
+
useTerminalSize
|
|
17
|
+
} from "../chunk-5BONVNP7.js";
|
|
14
18
|
|
|
15
19
|
// src/ui/CommandPalette.tsx
|
|
16
20
|
import { useState } from "react";
|
|
@@ -689,81 +693,166 @@ function Autocomplete({
|
|
|
689
693
|
}
|
|
690
694
|
|
|
691
695
|
// src/ui/Viewport.tsx
|
|
692
|
-
import {
|
|
693
|
-
|
|
696
|
+
import {
|
|
697
|
+
Children,
|
|
698
|
+
forwardRef,
|
|
699
|
+
isValidElement,
|
|
700
|
+
useCallback,
|
|
701
|
+
useImperativeHandle,
|
|
702
|
+
useLayoutEffect,
|
|
703
|
+
useRef as useRef4,
|
|
704
|
+
useState as useState6
|
|
705
|
+
} from "react";
|
|
706
|
+
import { Box as Box7, measureElement } from "ink";
|
|
694
707
|
import { jsx as jsx8, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
695
|
-
function
|
|
708
|
+
function MeasurableItem({
|
|
709
|
+
children,
|
|
710
|
+
index,
|
|
711
|
+
onMeasure
|
|
712
|
+
}) {
|
|
713
|
+
const ref = useRef4(null);
|
|
714
|
+
useLayoutEffect(() => {
|
|
715
|
+
if (ref.current) {
|
|
716
|
+
const { height } = measureElement(ref.current);
|
|
717
|
+
onMeasure(index, height);
|
|
718
|
+
}
|
|
719
|
+
}, [index, onMeasure, children]);
|
|
720
|
+
return /* @__PURE__ */ jsx8(Box7, { ref, flexShrink: 0, width: "100%", flexDirection: "column", children });
|
|
721
|
+
}
|
|
722
|
+
var Viewport = forwardRef(function Viewport2({ children, height, keybindings: enableKeybindings = true, footer }, ref) {
|
|
696
723
|
const focus = useFocus();
|
|
697
724
|
const [scrollOffset, setScrollOffset] = useState6(0);
|
|
698
|
-
const
|
|
699
|
-
const
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
pageup: () => scroll(-maxVisible),
|
|
709
|
-
g: () => setScrollOffset(0),
|
|
710
|
-
G: () => setScrollOffset(maxOffset)
|
|
725
|
+
const contentHeightRef = useRef4(0);
|
|
726
|
+
const itemHeightsRef = useRef4({});
|
|
727
|
+
const itemKeysRef = useRef4([]);
|
|
728
|
+
const scrollOffsetRef = useRef4(0);
|
|
729
|
+
scrollOffsetRef.current = scrollOffset;
|
|
730
|
+
const childKeys = [];
|
|
731
|
+
Children.forEach(children, (child, index) => {
|
|
732
|
+
if (!child) return;
|
|
733
|
+
const key = isValidElement(child) ? child.key : null;
|
|
734
|
+
childKeys[index] = key !== null ? key : index;
|
|
711
735
|
});
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
{
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
736
|
+
itemKeysRef.current = childKeys;
|
|
737
|
+
const getMaxOffset = useCallback(() => Math.max(0, contentHeightRef.current - height), [height]);
|
|
738
|
+
const clampAndSetOffset = useCallback(
|
|
739
|
+
(offset) => {
|
|
740
|
+
const clamped = Math.max(0, Math.min(offset, getMaxOffset()));
|
|
741
|
+
setScrollOffset(clamped);
|
|
742
|
+
},
|
|
743
|
+
[getMaxOffset]
|
|
744
|
+
);
|
|
745
|
+
const handleItemMeasure = useCallback(
|
|
746
|
+
(index, measuredHeight) => {
|
|
747
|
+
const key = itemKeysRef.current[index] ?? index;
|
|
748
|
+
if (itemHeightsRef.current[key] === measuredHeight) return;
|
|
749
|
+
itemHeightsRef.current[key] = measuredHeight;
|
|
750
|
+
let total = 0;
|
|
751
|
+
for (const k of itemKeysRef.current) {
|
|
752
|
+
total += itemHeightsRef.current[k] ?? 0;
|
|
753
|
+
}
|
|
754
|
+
contentHeightRef.current = total;
|
|
755
|
+
const maxOffset = Math.max(0, total - height);
|
|
756
|
+
if (scrollOffsetRef.current > maxOffset) {
|
|
757
|
+
setScrollOffset(maxOffset);
|
|
732
758
|
}
|
|
759
|
+
},
|
|
760
|
+
[height]
|
|
761
|
+
);
|
|
762
|
+
const getItemTop = useCallback((index) => {
|
|
763
|
+
let top = 0;
|
|
764
|
+
for (let i = 0; i < index && i < itemKeysRef.current.length; i++) {
|
|
765
|
+
const key = itemKeysRef.current[i] ?? i;
|
|
766
|
+
top += itemHeightsRef.current[key] ?? 0;
|
|
733
767
|
}
|
|
768
|
+
return top;
|
|
769
|
+
}, []);
|
|
770
|
+
useImperativeHandle(
|
|
771
|
+
ref,
|
|
772
|
+
() => ({
|
|
773
|
+
scrollTo: (offset) => clampAndSetOffset(offset),
|
|
774
|
+
scrollBy: (delta) => clampAndSetOffset(scrollOffsetRef.current + delta),
|
|
775
|
+
scrollToTop: () => setScrollOffset(0),
|
|
776
|
+
scrollToBottom: () => setScrollOffset(getMaxOffset()),
|
|
777
|
+
scrollToItem: (index) => {
|
|
778
|
+
const itemTop = getItemTop(index);
|
|
779
|
+
const key = itemKeysRef.current[index] ?? index;
|
|
780
|
+
const itemHeight = itemHeightsRef.current[key] ?? 0;
|
|
781
|
+
const itemBottom = itemTop + itemHeight;
|
|
782
|
+
const current = scrollOffsetRef.current;
|
|
783
|
+
if (itemTop < current) {
|
|
784
|
+
clampAndSetOffset(itemTop);
|
|
785
|
+
} else if (itemBottom > current + height) {
|
|
786
|
+
clampAndSetOffset(itemBottom - height);
|
|
787
|
+
}
|
|
788
|
+
},
|
|
789
|
+
getScrollOffset: () => scrollOffsetRef.current,
|
|
790
|
+
getContentHeight: () => contentHeightRef.current,
|
|
791
|
+
getViewportHeight: () => height
|
|
792
|
+
}),
|
|
793
|
+
[clampAndSetOffset, getMaxOffset, getItemTop, height]
|
|
734
794
|
);
|
|
735
|
-
|
|
795
|
+
useKeybindings(
|
|
796
|
+
focus,
|
|
797
|
+
enableKeybindings ? {
|
|
798
|
+
j: () => clampAndSetOffset(scrollOffsetRef.current + 1),
|
|
799
|
+
k: () => clampAndSetOffset(scrollOffsetRef.current - 1),
|
|
800
|
+
down: () => clampAndSetOffset(scrollOffsetRef.current + 1),
|
|
801
|
+
up: () => clampAndSetOffset(scrollOffsetRef.current - 1),
|
|
802
|
+
pagedown: () => clampAndSetOffset(scrollOffsetRef.current + height),
|
|
803
|
+
pageup: () => clampAndSetOffset(scrollOffsetRef.current - height),
|
|
804
|
+
g: () => setScrollOffset(0),
|
|
805
|
+
G: () => setScrollOffset(getMaxOffset())
|
|
806
|
+
} : {}
|
|
807
|
+
);
|
|
808
|
+
return /* @__PURE__ */ jsxs9(Box7, { flexDirection: "column", children: [
|
|
809
|
+
/* @__PURE__ */ jsx8(Box7, { height, overflow: "hidden", children: /* @__PURE__ */ jsx8(Box7, { marginTop: -scrollOffset, flexDirection: "column", width: "100%", children: Children.map(children, (child, index) => {
|
|
810
|
+
if (!child) return null;
|
|
811
|
+
return /* @__PURE__ */ jsx8(
|
|
812
|
+
MeasurableItem,
|
|
813
|
+
{
|
|
814
|
+
index,
|
|
815
|
+
onMeasure: handleItemMeasure,
|
|
816
|
+
children: child
|
|
817
|
+
},
|
|
818
|
+
isValidElement(child) ? child.key ?? index : index
|
|
819
|
+
);
|
|
820
|
+
}) }) }),
|
|
821
|
+
footer
|
|
822
|
+
] });
|
|
823
|
+
});
|
|
736
824
|
|
|
737
825
|
// src/ui/Modal.tsx
|
|
738
|
-
import { Box as
|
|
826
|
+
import { Box as Box8, Text as Text8 } from "ink";
|
|
739
827
|
import { jsx as jsx9, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
740
|
-
function ModalInner({ children, onClose, title,
|
|
828
|
+
function ModalInner({ children, onClose, title, ...boxProps }) {
|
|
741
829
|
const focus = useFocus();
|
|
742
830
|
const theme = useTheme();
|
|
743
831
|
useKeybindings(focus, {
|
|
744
832
|
escape: onClose
|
|
745
833
|
});
|
|
746
834
|
return /* @__PURE__ */ jsxs10(
|
|
747
|
-
|
|
835
|
+
Box8,
|
|
748
836
|
{
|
|
749
837
|
flexDirection: "column",
|
|
750
838
|
alignSelf: "flex-start",
|
|
751
|
-
borderStyle,
|
|
839
|
+
borderStyle: "round",
|
|
752
840
|
borderColor: theme.borderColor,
|
|
753
841
|
paddingX: 1,
|
|
842
|
+
...boxProps,
|
|
754
843
|
children: [
|
|
755
|
-
title != null && /* @__PURE__ */ jsx9(
|
|
844
|
+
title != null && /* @__PURE__ */ jsx9(Text8, { bold: true, children: title }),
|
|
756
845
|
children
|
|
757
846
|
]
|
|
758
847
|
}
|
|
759
848
|
);
|
|
760
849
|
}
|
|
761
|
-
function Modal({ children, onClose, title,
|
|
762
|
-
return /* @__PURE__ */ jsx9(FocusTrap, { children: /* @__PURE__ */ jsx9(ModalInner, { onClose, title,
|
|
850
|
+
function Modal({ children, onClose, title, ...boxProps }) {
|
|
851
|
+
return /* @__PURE__ */ jsx9(FocusTrap, { children: /* @__PURE__ */ jsx9(ModalInner, { onClose, title, ...boxProps, children }) });
|
|
763
852
|
}
|
|
764
853
|
|
|
765
854
|
// src/ui/Badge.tsx
|
|
766
|
-
import { Text as
|
|
855
|
+
import { Text as Text9 } from "ink";
|
|
767
856
|
import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
768
857
|
var glyphs = {
|
|
769
858
|
round: ["\uE0B6", "\uE0B4"],
|
|
@@ -776,26 +865,32 @@ function Badge({ children, color, background, variant = "round" }) {
|
|
|
776
865
|
const fg = color ?? "#000000";
|
|
777
866
|
const [left, right] = glyphs[variant];
|
|
778
867
|
const label = variant === "plain" ? ` ${children} ` : children;
|
|
779
|
-
return /* @__PURE__ */ jsxs11(
|
|
780
|
-
left && /* @__PURE__ */ jsx10(
|
|
781
|
-
/* @__PURE__ */ jsx10(
|
|
782
|
-
right && /* @__PURE__ */ jsx10(
|
|
868
|
+
return /* @__PURE__ */ jsxs11(Text9, { children: [
|
|
869
|
+
left && /* @__PURE__ */ jsx10(Text9, { color: bg, children: left }),
|
|
870
|
+
/* @__PURE__ */ jsx10(Text9, { color: fg, backgroundColor: bg, bold: true, children: label }),
|
|
871
|
+
right && /* @__PURE__ */ jsx10(Text9, { color: bg, children: right })
|
|
783
872
|
] });
|
|
784
873
|
}
|
|
785
874
|
|
|
786
875
|
// src/ui/Panel.tsx
|
|
787
876
|
import { useState as useState7 } from "react";
|
|
788
|
-
import { Box as
|
|
877
|
+
import { Box as Box9, Text as Text10, measureElement as measureElement2 } from "ink";
|
|
789
878
|
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
790
|
-
function
|
|
879
|
+
function parsePercentage(value, total) {
|
|
880
|
+
const pct = parseFloat(value);
|
|
881
|
+
return isNaN(pct) ? 0 : Math.floor(pct / 100 * total);
|
|
882
|
+
}
|
|
883
|
+
function Panel({ children, title, width, borderColor, footer, ...boxProps }) {
|
|
791
884
|
const theme = useTheme();
|
|
885
|
+
const { columns } = useTerminalSize();
|
|
792
886
|
const color = borderColor ?? theme.borderColor;
|
|
793
|
-
const
|
|
794
|
-
const
|
|
887
|
+
const initialWidth = typeof width === "number" ? width : typeof width === "string" && width.endsWith("%") ? parsePercentage(width, columns) : 0;
|
|
888
|
+
const [measuredWidth, setMeasuredWidth] = useState7(initialWidth);
|
|
889
|
+
const effectiveWidth = typeof width === "number" ? width : measuredWidth;
|
|
795
890
|
const renderTopBorder = () => {
|
|
796
891
|
if (effectiveWidth === 0) return null;
|
|
797
892
|
if (title == null) {
|
|
798
|
-
return /* @__PURE__ */ jsxs12(
|
|
893
|
+
return /* @__PURE__ */ jsxs12(Text10, { color, children: [
|
|
799
894
|
"\u256D",
|
|
800
895
|
"\u2500".repeat(Math.max(0, effectiveWidth - 2)),
|
|
801
896
|
"\u256E"
|
|
@@ -805,10 +900,10 @@ function Panel({ children, title, width, borderColor, footer }) {
|
|
|
805
900
|
const displayTitle = title.length > maxTitleWidth ? title.slice(0, maxTitleWidth - 1) + "\u2026" : title;
|
|
806
901
|
const titlePart = `\u256D ${displayTitle} `;
|
|
807
902
|
const totalDashes = Math.max(1, effectiveWidth - titlePart.length - 1);
|
|
808
|
-
return /* @__PURE__ */ jsxs12(
|
|
809
|
-
/* @__PURE__ */ jsx11(
|
|
810
|
-
/* @__PURE__ */ jsx11(
|
|
811
|
-
/* @__PURE__ */ jsxs12(
|
|
903
|
+
return /* @__PURE__ */ jsxs12(Text10, { children: [
|
|
904
|
+
/* @__PURE__ */ jsx11(Text10, { color, children: "\u256D " }),
|
|
905
|
+
/* @__PURE__ */ jsx11(Text10, { color, bold: true, children: displayTitle }),
|
|
906
|
+
/* @__PURE__ */ jsxs12(Text10, { color, children: [
|
|
812
907
|
" ",
|
|
813
908
|
"\u2500".repeat(totalDashes),
|
|
814
909
|
"\u256E"
|
|
@@ -816,27 +911,59 @@ function Panel({ children, title, width, borderColor, footer }) {
|
|
|
816
911
|
] });
|
|
817
912
|
};
|
|
818
913
|
return /* @__PURE__ */ jsxs12(
|
|
819
|
-
|
|
914
|
+
Box9,
|
|
820
915
|
{
|
|
821
916
|
flexDirection: "column",
|
|
822
917
|
width,
|
|
823
918
|
flexGrow: width == null ? 1 : void 0,
|
|
824
919
|
ref: (node) => {
|
|
825
920
|
if (node) {
|
|
826
|
-
const { width: w } =
|
|
827
|
-
if (w !== measuredWidth) setMeasuredWidth(w);
|
|
921
|
+
const { width: w } = measureElement2(node);
|
|
922
|
+
if (w > 0 && w !== measuredWidth) setMeasuredWidth(w);
|
|
828
923
|
}
|
|
829
924
|
},
|
|
925
|
+
...boxProps,
|
|
830
926
|
children: [
|
|
831
927
|
renderTopBorder(),
|
|
832
|
-
/* @__PURE__ */ jsx11(
|
|
833
|
-
/* @__PURE__ */ jsx11(
|
|
928
|
+
/* @__PURE__ */ jsx11(Box9, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderTop: false, borderColor: color, paddingX: 1, children: footer ? /* @__PURE__ */ jsxs12(Fragment3, { children: [
|
|
929
|
+
/* @__PURE__ */ jsx11(Box9, { flexDirection: "column", flexGrow: 1, children }),
|
|
834
930
|
footer
|
|
835
931
|
] }) : children })
|
|
836
932
|
]
|
|
837
933
|
}
|
|
838
934
|
);
|
|
839
935
|
}
|
|
936
|
+
|
|
937
|
+
// src/ui/Spinner.tsx
|
|
938
|
+
import { useEffect as useEffect5, useState as useState8 } from "react";
|
|
939
|
+
import { Text as Text11 } from "ink";
|
|
940
|
+
import { jsx as jsx12 } from "react/jsx-runtime";
|
|
941
|
+
var spinners = {
|
|
942
|
+
line: { frames: ["-", "\\", "|", "/"], interval: 130 },
|
|
943
|
+
dot: { frames: ["\u28FE", "\u28FD", "\u28FB", "\u28BF", "\u287F", "\u28DF", "\u28EF", "\u28F7"], interval: 130 },
|
|
944
|
+
miniDot: { frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"], interval: 80 },
|
|
945
|
+
jump: { frames: ["\u2884", "\u2882", "\u2881", "\u2841", "\u2848", "\u2850", "\u2860"], interval: 100 },
|
|
946
|
+
pulse: { frames: ["\u2588", "\u2593", "\u2592", "\u2591"], interval: 120 },
|
|
947
|
+
points: { frames: ["\u2219\u2219\u2219", "\u25CF\u2219\u2219", "\u2219\u25CF\u2219", "\u2219\u2219\u25CF"], interval: 200 },
|
|
948
|
+
clock: { frames: ["\u{1F55B}", "\u{1F550}", "\u{1F551}", "\u{1F552}", "\u{1F553}", "\u{1F554}", "\u{1F555}", "\u{1F556}", "\u{1F557}", "\u{1F558}", "\u{1F559}", "\u{1F55A}"], interval: 100 },
|
|
949
|
+
hearts: { frames: ["\u2764\uFE0F", "\u{1F9E1}", "\u{1F49B}", "\u{1F49A}", "\u{1F499}", "\u{1F49C}"], interval: 120 },
|
|
950
|
+
moon: { frames: ["\u{1F311}", "\u{1F312}", "\u{1F313}", "\u{1F314}", "\u{1F315}", "\u{1F316}", "\u{1F317}", "\u{1F318}"], interval: 180 },
|
|
951
|
+
meter: { frames: ["\u25B1\u25B1\u25B1", "\u25B0\u25B1\u25B1", "\u25B0\u25B0\u25B1", "\u25B0\u25B0\u25B0", "\u25B0\u25B0\u25B1", "\u25B0\u25B1\u25B1", "\u25B1\u25B1\u25B1"], interval: 100 },
|
|
952
|
+
hamburger: { frames: ["\u2631", "\u2632", "\u2634"], interval: 100 },
|
|
953
|
+
ellipsis: { frames: [". ", ".. ", "...", " "], interval: 300 }
|
|
954
|
+
};
|
|
955
|
+
function Spinner({ spinner = spinners.line, color }) {
|
|
956
|
+
const theme = useTheme();
|
|
957
|
+
const [frame, setFrame] = useState8(0);
|
|
958
|
+
useEffect5(() => {
|
|
959
|
+
setFrame(0);
|
|
960
|
+
const id = setInterval(() => {
|
|
961
|
+
setFrame((f) => (f + 1) % spinner.frames.length);
|
|
962
|
+
}, spinner.interval);
|
|
963
|
+
return () => clearInterval(id);
|
|
964
|
+
}, [spinner]);
|
|
965
|
+
return /* @__PURE__ */ jsx12(Text11, { color: color ?? theme.accentColor, children: spinner.frames[frame] });
|
|
966
|
+
}
|
|
840
967
|
export {
|
|
841
968
|
Autocomplete,
|
|
842
969
|
Badge,
|
|
@@ -848,7 +975,9 @@ export {
|
|
|
848
975
|
Paginator,
|
|
849
976
|
Panel,
|
|
850
977
|
Select,
|
|
978
|
+
Spinner,
|
|
851
979
|
TextInput,
|
|
852
980
|
Viewport,
|
|
853
|
-
VirtualList
|
|
981
|
+
VirtualList,
|
|
982
|
+
spinners
|
|
854
983
|
};
|
package/package.json
CHANGED
package/dist/chunk-7PDVDYFB.js
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
// src/terminal/components/AlternateScreen.tsx
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
3
|
-
import { Fragment, jsx } from "react/jsx-runtime";
|
|
4
|
-
var _a;
|
|
5
|
-
var isTTY = typeof process !== "undefined" && ((_a = process.stdout) == null ? void 0 : _a.write);
|
|
6
|
-
function AlternateScreen({ children }) {
|
|
7
|
-
const [ready, setReady] = useState(!isTTY);
|
|
8
|
-
useEffect(() => {
|
|
9
|
-
if (!isTTY) return;
|
|
10
|
-
process.stdout.write("\x1B[?1049h");
|
|
11
|
-
process.stdout.write("\x1B[2J");
|
|
12
|
-
process.stdout.write("\x1B[H");
|
|
13
|
-
setReady(true);
|
|
14
|
-
return () => {
|
|
15
|
-
process.stdout.write("\x1B[?1049l");
|
|
16
|
-
};
|
|
17
|
-
}, []);
|
|
18
|
-
return ready ? /* @__PURE__ */ jsx(Fragment, { children }) : null;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export {
|
|
22
|
-
AlternateScreen
|
|
23
|
-
};
|