giggles 0.3.7 → 0.3.9
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-X5PYVHXM.js → chunk-CKA5JJ4B.js} +57 -54
- package/dist/chunk-PVXJL6SX.js +29 -0
- package/dist/chunk-TFYBLNEZ.js +93 -0
- package/dist/index.js +5 -3
- package/dist/markdown/index.d.ts +8 -0
- package/dist/markdown/index.js +122 -0
- package/dist/ui/index.d.ts +40 -1
- package/dist/ui/index.js +86 -2
- package/package.json +12 -3
|
@@ -119,7 +119,13 @@ var FocusProvider = ({ children }) => {
|
|
|
119
119
|
const nodes = nodesRef.current;
|
|
120
120
|
const parent = nodes.get(parentId);
|
|
121
121
|
if (parent && parent.childrenIds.length > 0) {
|
|
122
|
-
|
|
122
|
+
let target = parent.childrenIds[0];
|
|
123
|
+
let targetNode = nodes.get(target);
|
|
124
|
+
while (targetNode && targetNode.childrenIds.length > 0) {
|
|
125
|
+
target = targetNode.childrenIds[0];
|
|
126
|
+
targetNode = nodes.get(target);
|
|
127
|
+
}
|
|
128
|
+
focusNode(target);
|
|
123
129
|
} else {
|
|
124
130
|
pendingFocusFirstChildRef.current.add(parentId);
|
|
125
131
|
}
|
|
@@ -196,16 +202,34 @@ var FocusProvider = ({ children }) => {
|
|
|
196
202
|
return pathArray;
|
|
197
203
|
}, [focusedId]);
|
|
198
204
|
const navigateSibling = useCallback2(
|
|
199
|
-
(direction, wrap = true) => {
|
|
200
|
-
|
|
201
|
-
if (!currentId) return;
|
|
205
|
+
(direction, wrap = true, groupId) => {
|
|
206
|
+
if (!focusedId) return;
|
|
202
207
|
const nodes = nodesRef.current;
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
208
|
+
let currentChildId;
|
|
209
|
+
let siblings;
|
|
210
|
+
if (groupId) {
|
|
211
|
+
const group = nodes.get(groupId);
|
|
212
|
+
if (!group || group.childrenIds.length === 0) return;
|
|
213
|
+
siblings = group.childrenIds;
|
|
214
|
+
let cursor = focusedId;
|
|
215
|
+
while (cursor) {
|
|
216
|
+
const node = nodes.get(cursor);
|
|
217
|
+
if ((node == null ? void 0 : node.parentId) === groupId) {
|
|
218
|
+
currentChildId = cursor;
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
cursor = (node == null ? void 0 : node.parentId) ?? null;
|
|
222
|
+
}
|
|
223
|
+
if (!currentChildId) return;
|
|
224
|
+
} else {
|
|
225
|
+
const currentNode = nodes.get(focusedId);
|
|
226
|
+
if (!(currentNode == null ? void 0 : currentNode.parentId)) return;
|
|
227
|
+
const parent = nodes.get(currentNode.parentId);
|
|
228
|
+
if (!parent || parent.childrenIds.length === 0) return;
|
|
229
|
+
siblings = parent.childrenIds;
|
|
230
|
+
currentChildId = focusedId;
|
|
231
|
+
}
|
|
232
|
+
const currentIndex = siblings.indexOf(currentChildId);
|
|
209
233
|
if (currentIndex === -1) return;
|
|
210
234
|
let nextIndex;
|
|
211
235
|
if (wrap) {
|
|
@@ -213,9 +237,15 @@ var FocusProvider = ({ children }) => {
|
|
|
213
237
|
} else {
|
|
214
238
|
nextIndex = direction === "next" ? Math.min(currentIndex + 1, siblings.length - 1) : Math.max(currentIndex - 1, 0);
|
|
215
239
|
}
|
|
216
|
-
|
|
240
|
+
const targetId = siblings[nextIndex];
|
|
241
|
+
const target = nodes.get(targetId);
|
|
242
|
+
if (target && target.childrenIds.length > 0) {
|
|
243
|
+
focusFirstChild(targetId);
|
|
244
|
+
} else {
|
|
245
|
+
focusNode(targetId);
|
|
246
|
+
}
|
|
217
247
|
},
|
|
218
|
-
[focusedId, focusNode]
|
|
248
|
+
[focusedId, focusNode, focusFirstChild]
|
|
219
249
|
);
|
|
220
250
|
return /* @__PURE__ */ jsx2(
|
|
221
251
|
FocusContext.Provider,
|
|
@@ -311,18 +341,18 @@ function InputRouter({ children }) {
|
|
|
311
341
|
if (!keyName) return;
|
|
312
342
|
for (const nodeId of path) {
|
|
313
343
|
const nodeBindings = getNodeBindings(nodeId);
|
|
314
|
-
if (
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
344
|
+
if (nodeBindings) {
|
|
345
|
+
const entry = nodeBindings.bindings.get(keyName);
|
|
346
|
+
if (entry && entry.when !== "mounted") {
|
|
347
|
+
entry.handler(input, key);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
if (nodeBindings.capture && nodeBindings.onKeypress) {
|
|
351
|
+
if (!((_a = nodeBindings.passthrough) == null ? void 0 : _a.has(keyName))) {
|
|
352
|
+
nodeBindings.onKeypress(input, key);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
323
355
|
}
|
|
324
|
-
nodeBindings.onKeypress(input, key);
|
|
325
|
-
return;
|
|
326
356
|
}
|
|
327
357
|
if (nodeId === trapNodeId) {
|
|
328
358
|
return;
|
|
@@ -401,8 +431,8 @@ function FocusGroup({
|
|
|
401
431
|
const bindContextValue = useMemo(() => value ? { register, unregister } : null, [value, register, unregister]);
|
|
402
432
|
const navigationKeys = useMemo(() => {
|
|
403
433
|
if (!navigable) return {};
|
|
404
|
-
const next = () => navigateSibling("next", wrap);
|
|
405
|
-
const prev = () => navigateSibling("prev", wrap);
|
|
434
|
+
const next = () => navigateSibling("next", wrap, focus.id);
|
|
435
|
+
const prev = () => navigateSibling("prev", wrap, focus.id);
|
|
406
436
|
const base = direction === "vertical" ? {
|
|
407
437
|
j: next,
|
|
408
438
|
k: prev,
|
|
@@ -415,7 +445,7 @@ function FocusGroup({
|
|
|
415
445
|
left: prev
|
|
416
446
|
};
|
|
417
447
|
return { ...base, tab: next, "shift+tab": prev };
|
|
418
|
-
}, [navigable, direction, wrap, navigateSibling]);
|
|
448
|
+
}, [navigable, direction, wrap, navigateSibling, focus.id]);
|
|
419
449
|
const mergedBindings = useMemo(
|
|
420
450
|
() => ({ ...navigationKeys, ...customBindings }),
|
|
421
451
|
[navigationKeys, customBindings]
|
|
@@ -452,31 +482,6 @@ function FocusTrap({ children }) {
|
|
|
452
482
|
return /* @__PURE__ */ jsx5(FocusNodeContext.Provider, { value: id, children });
|
|
453
483
|
}
|
|
454
484
|
|
|
455
|
-
// src/core/theme.tsx
|
|
456
|
-
import { createContext as createContext4, useContext as useContext4 } from "react";
|
|
457
|
-
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
458
|
-
var defaultTheme = {
|
|
459
|
-
accentColor: "#6B9FD4",
|
|
460
|
-
borderColor: "#5C5C5C",
|
|
461
|
-
selectedColor: "#8FBF7F",
|
|
462
|
-
hintColor: "#8A8A8A",
|
|
463
|
-
hintDimColor: "#5C5C5C",
|
|
464
|
-
hintHighlightColor: "#D4D4D4",
|
|
465
|
-
hintHighlightDimColor: "#A0A0A0",
|
|
466
|
-
indicator: "\u25B8",
|
|
467
|
-
checkedIndicator: "\u2713",
|
|
468
|
-
uncheckedIndicator: "\u25CB"
|
|
469
|
-
};
|
|
470
|
-
var ThemeContext = createContext4(defaultTheme);
|
|
471
|
-
function ThemeProvider({ theme, children }) {
|
|
472
|
-
const parent = useContext4(ThemeContext);
|
|
473
|
-
const merged = { ...parent, ...theme };
|
|
474
|
-
return /* @__PURE__ */ jsx6(ThemeContext.Provider, { value: merged, children });
|
|
475
|
-
}
|
|
476
|
-
function useTheme() {
|
|
477
|
-
return useContext4(ThemeContext);
|
|
478
|
-
}
|
|
479
|
-
|
|
480
485
|
export {
|
|
481
486
|
GigglesError,
|
|
482
487
|
FocusProvider,
|
|
@@ -489,7 +494,5 @@ export {
|
|
|
489
494
|
FocusTrap,
|
|
490
495
|
useFocus,
|
|
491
496
|
FocusGroup,
|
|
492
|
-
useFocusState
|
|
493
|
-
ThemeProvider,
|
|
494
|
-
useTheme
|
|
497
|
+
useFocusState
|
|
495
498
|
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/core/theme.tsx
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
var defaultTheme = {
|
|
5
|
+
accentColor: "#6B9FD4",
|
|
6
|
+
borderColor: "#5C5C5C",
|
|
7
|
+
selectedColor: "#8FBF7F",
|
|
8
|
+
hintColor: "#8A8A8A",
|
|
9
|
+
hintDimColor: "#5C5C5C",
|
|
10
|
+
hintHighlightColor: "#D4D4D4",
|
|
11
|
+
hintHighlightDimColor: "#A0A0A0",
|
|
12
|
+
indicator: "\u25B8",
|
|
13
|
+
checkedIndicator: "\u2713",
|
|
14
|
+
uncheckedIndicator: "\u25CB"
|
|
15
|
+
};
|
|
16
|
+
var ThemeContext = createContext(defaultTheme);
|
|
17
|
+
function ThemeProvider({ theme, children }) {
|
|
18
|
+
const parent = useContext(ThemeContext);
|
|
19
|
+
const merged = { ...parent, ...theme };
|
|
20
|
+
return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: merged, children });
|
|
21
|
+
}
|
|
22
|
+
function useTheme() {
|
|
23
|
+
return useContext(ThemeContext);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export {
|
|
27
|
+
ThemeProvider,
|
|
28
|
+
useTheme
|
|
29
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useTheme
|
|
3
|
+
} from "./chunk-PVXJL6SX.js";
|
|
4
|
+
|
|
5
|
+
// src/ui/CodeBlock.tsx
|
|
6
|
+
import Prism from "prismjs";
|
|
7
|
+
import { Box, Text } from "ink";
|
|
8
|
+
import { jsx } from "react/jsx-runtime";
|
|
9
|
+
var defaultTokenColors = {
|
|
10
|
+
keyword: "#C678DD",
|
|
11
|
+
string: "#98C379",
|
|
12
|
+
number: "#D19A66",
|
|
13
|
+
comment: "#5C6370",
|
|
14
|
+
function: "#61AFEF",
|
|
15
|
+
operator: "#56B6C2",
|
|
16
|
+
punctuation: "#ABB2BF",
|
|
17
|
+
builtin: "#E5C07B",
|
|
18
|
+
className: "#E5C07B",
|
|
19
|
+
inserted: "#98C379",
|
|
20
|
+
deleted: "#E06C75"
|
|
21
|
+
};
|
|
22
|
+
function CodeBlock({ children, language, showBorder = true, tokenColors }) {
|
|
23
|
+
const theme = useTheme();
|
|
24
|
+
const colors = { ...defaultTokenColors, ...tokenColors };
|
|
25
|
+
const grammar = language ? Prism.languages[language] : void 0;
|
|
26
|
+
const content = grammar ? renderTokens(Prism.tokenize(children, grammar), colors) : /* @__PURE__ */ jsx(Text, { children });
|
|
27
|
+
if (!showBorder) {
|
|
28
|
+
return /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { children: content }) });
|
|
29
|
+
}
|
|
30
|
+
return /* @__PURE__ */ jsx(Box, { paddingX: 1, borderStyle: "single", borderColor: theme.borderColor, children: /* @__PURE__ */ jsx(Text, { children: content }) });
|
|
31
|
+
}
|
|
32
|
+
function renderTokens(tokens, colors) {
|
|
33
|
+
return tokens.map((token, idx) => {
|
|
34
|
+
if (typeof token === "string") {
|
|
35
|
+
return /* @__PURE__ */ jsx(Text, { children: token }, idx);
|
|
36
|
+
}
|
|
37
|
+
const color = getTokenColor(token.type, colors);
|
|
38
|
+
const content = Array.isArray(token.content) ? renderTokens(token.content, colors) : typeof token.content === "string" ? token.content : renderTokens([token.content], colors);
|
|
39
|
+
return color ? /* @__PURE__ */ jsx(Text, { color, children: content }, idx) : /* @__PURE__ */ jsx(Text, { children: content }, idx);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function getTokenColor(type, colors) {
|
|
43
|
+
switch (type) {
|
|
44
|
+
case "keyword":
|
|
45
|
+
case "tag":
|
|
46
|
+
case "boolean":
|
|
47
|
+
case "important":
|
|
48
|
+
return colors.keyword;
|
|
49
|
+
case "string":
|
|
50
|
+
case "char":
|
|
51
|
+
case "template-string":
|
|
52
|
+
case "attr-value":
|
|
53
|
+
return colors.string;
|
|
54
|
+
case "number":
|
|
55
|
+
return colors.number;
|
|
56
|
+
case "comment":
|
|
57
|
+
case "prolog":
|
|
58
|
+
case "doctype":
|
|
59
|
+
case "cdata":
|
|
60
|
+
return colors.comment;
|
|
61
|
+
case "function":
|
|
62
|
+
case "function-variable":
|
|
63
|
+
return colors.function;
|
|
64
|
+
case "operator":
|
|
65
|
+
case "arrow":
|
|
66
|
+
return colors.operator;
|
|
67
|
+
case "punctuation":
|
|
68
|
+
return colors.punctuation;
|
|
69
|
+
case "builtin":
|
|
70
|
+
case "constant":
|
|
71
|
+
case "symbol":
|
|
72
|
+
return colors.builtin;
|
|
73
|
+
case "class-name":
|
|
74
|
+
case "maybe-class-name":
|
|
75
|
+
return colors.className;
|
|
76
|
+
case "attr-name":
|
|
77
|
+
return colors.function;
|
|
78
|
+
case "inserted-sign":
|
|
79
|
+
case "inserted":
|
|
80
|
+
return colors.inserted;
|
|
81
|
+
case "deleted-sign":
|
|
82
|
+
case "deleted":
|
|
83
|
+
return colors.deleted;
|
|
84
|
+
case "unchanged":
|
|
85
|
+
return colors.comment;
|
|
86
|
+
default:
|
|
87
|
+
return void 0;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export {
|
|
92
|
+
CodeBlock
|
|
93
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -9,14 +9,16 @@ import {
|
|
|
9
9
|
GigglesError,
|
|
10
10
|
InputProvider,
|
|
11
11
|
InputRouter,
|
|
12
|
-
ThemeProvider,
|
|
13
12
|
useFocus,
|
|
14
13
|
useFocusContext,
|
|
15
14
|
useFocusState,
|
|
16
15
|
useKeybindingRegistry,
|
|
17
|
-
useKeybindings
|
|
16
|
+
useKeybindings
|
|
17
|
+
} from "./chunk-CKA5JJ4B.js";
|
|
18
|
+
import {
|
|
19
|
+
ThemeProvider,
|
|
18
20
|
useTheme
|
|
19
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-PVXJL6SX.js";
|
|
20
22
|
|
|
21
23
|
// src/core/GigglesProvider.tsx
|
|
22
24
|
import { jsx } from "react/jsx-runtime";
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CodeBlock
|
|
3
|
+
} from "../chunk-TFYBLNEZ.js";
|
|
4
|
+
import {
|
|
5
|
+
useTheme
|
|
6
|
+
} from "../chunk-PVXJL6SX.js";
|
|
7
|
+
|
|
8
|
+
// src/ui/Markdown.tsx
|
|
9
|
+
import Table from "cli-table3";
|
|
10
|
+
import { marked } from "marked";
|
|
11
|
+
import { useMemo } from "react";
|
|
12
|
+
import { Box, Text } from "ink";
|
|
13
|
+
import Link from "ink-link";
|
|
14
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
15
|
+
function Markdown({ children }) {
|
|
16
|
+
const tokens = useMemo(() => marked.lexer(children), [children]);
|
|
17
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: tokens.map((token, idx) => /* @__PURE__ */ jsx(TokenRenderer, { token }, idx)) });
|
|
18
|
+
}
|
|
19
|
+
function TokenRenderer({ token }) {
|
|
20
|
+
var _a, _b;
|
|
21
|
+
const theme = useTheme();
|
|
22
|
+
switch (token.type) {
|
|
23
|
+
case "heading":
|
|
24
|
+
return /* @__PURE__ */ jsx(Box, { marginTop: token.depth === 1 ? 0 : 1, children: /* @__PURE__ */ jsx(Text, { bold: true, underline: token.depth === 1, children: renderInline(token.tokens, theme) }) });
|
|
25
|
+
case "paragraph": {
|
|
26
|
+
const hasLinks = (_a = token.tokens) == null ? void 0 : _a.some(
|
|
27
|
+
(t) => {
|
|
28
|
+
var _a2;
|
|
29
|
+
return t.type === "link" || t.type === "strong" && "tokens" in t && ((_a2 = t.tokens) == null ? void 0 : _a2.some((st) => st.type === "link"));
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
if (hasLinks) {
|
|
33
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "row", flexWrap: "wrap", children: renderInline(token.tokens, theme) });
|
|
34
|
+
}
|
|
35
|
+
return /* @__PURE__ */ jsx(Text, { children: renderInline(token.tokens, theme) });
|
|
36
|
+
}
|
|
37
|
+
case "code":
|
|
38
|
+
return /* @__PURE__ */ jsx(Box, { marginY: 1, children: /* @__PURE__ */ jsx(CodeBlock, { language: token.lang || void 0, children: token.text }) });
|
|
39
|
+
case "blockquote":
|
|
40
|
+
return /* @__PURE__ */ jsxs(Box, { marginY: 1, children: [
|
|
41
|
+
/* @__PURE__ */ jsx(Text, { color: theme.borderColor, children: "\u2502 " }),
|
|
42
|
+
/* @__PURE__ */ jsx(Text, { dimColor: true, children: (_b = token.tokens) == null ? void 0 : _b.map((t, idx) => /* @__PURE__ */ jsx(TokenRenderer, { token: t }, idx)) })
|
|
43
|
+
] });
|
|
44
|
+
case "list":
|
|
45
|
+
return /* @__PURE__ */ jsx(Box, { flexDirection: "column", marginY: 1, children: token.items.map((item, idx) => /* @__PURE__ */ jsxs(Box, { children: [
|
|
46
|
+
/* @__PURE__ */ jsx(Text, { children: token.ordered ? `${idx + 1}. ` : "\u2022 " }),
|
|
47
|
+
/* @__PURE__ */ jsx(Box, { flexDirection: "column", children: item.tokens.map((t, i) => /* @__PURE__ */ jsx(TokenRenderer, { token: t }, i)) })
|
|
48
|
+
] }, idx)) });
|
|
49
|
+
case "table":
|
|
50
|
+
return /* @__PURE__ */ jsx(TableRenderer, { token });
|
|
51
|
+
case "hr":
|
|
52
|
+
return /* @__PURE__ */ jsx(Text, { dimColor: true, children: "\u2500".repeat(40) });
|
|
53
|
+
case "space":
|
|
54
|
+
return null;
|
|
55
|
+
default:
|
|
56
|
+
if ("text" in token && typeof token.text === "string") {
|
|
57
|
+
return /* @__PURE__ */ jsx(Text, { children: token.text });
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function TableRenderer({ token }) {
|
|
63
|
+
const table = new Table({
|
|
64
|
+
head: token.header.map((cell) => renderInlineToString(cell.tokens)),
|
|
65
|
+
style: { head: [], border: [] }
|
|
66
|
+
});
|
|
67
|
+
for (const row of token.rows) {
|
|
68
|
+
table.push(row.map((cell) => renderInlineToString(cell.tokens)));
|
|
69
|
+
}
|
|
70
|
+
return /* @__PURE__ */ jsx(Text, { children: table.toString() });
|
|
71
|
+
}
|
|
72
|
+
function renderInline(tokens, theme) {
|
|
73
|
+
if (!tokens) return null;
|
|
74
|
+
return tokens.map((token, idx) => {
|
|
75
|
+
switch (token.type) {
|
|
76
|
+
case "text":
|
|
77
|
+
return /* @__PURE__ */ jsx(Text, { children: token.text }, idx);
|
|
78
|
+
case "strong":
|
|
79
|
+
return /* @__PURE__ */ jsx(Text, { bold: true, children: renderInline(token.tokens, theme) }, idx);
|
|
80
|
+
case "em":
|
|
81
|
+
return /* @__PURE__ */ jsx(Text, { italic: true, children: renderInline(token.tokens, theme) }, idx);
|
|
82
|
+
case "codespan":
|
|
83
|
+
return /* @__PURE__ */ jsxs(Text, { color: theme.accentColor, children: [
|
|
84
|
+
"`",
|
|
85
|
+
token.text,
|
|
86
|
+
"`"
|
|
87
|
+
] }, idx);
|
|
88
|
+
case "link":
|
|
89
|
+
return /* @__PURE__ */ jsx(Link, { url: token.href, children: /* @__PURE__ */ jsx(Text, { color: theme.accentColor, children: renderInlineToString(token.tokens) }) }, idx);
|
|
90
|
+
case "image":
|
|
91
|
+
return /* @__PURE__ */ jsxs(Text, { color: theme.accentColor, children: [
|
|
92
|
+
"[Image: ",
|
|
93
|
+
token.text || token.href,
|
|
94
|
+
"]"
|
|
95
|
+
] }, idx);
|
|
96
|
+
case "br":
|
|
97
|
+
return /* @__PURE__ */ jsx(Text, { children: "\n" }, idx);
|
|
98
|
+
case "del":
|
|
99
|
+
return /* @__PURE__ */ jsx(Text, { strikethrough: true, children: renderInline(token.tokens, theme) }, idx);
|
|
100
|
+
default:
|
|
101
|
+
if ("text" in token && typeof token.text === "string") {
|
|
102
|
+
return /* @__PURE__ */ jsx(Text, { children: token.text }, idx);
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function renderInlineToString(tokens) {
|
|
109
|
+
if (!tokens) return "";
|
|
110
|
+
return tokens.map((token) => {
|
|
111
|
+
if ("text" in token && typeof token.text === "string") {
|
|
112
|
+
return token.text;
|
|
113
|
+
}
|
|
114
|
+
if ("tokens" in token && Array.isArray(token.tokens)) {
|
|
115
|
+
return renderInlineToString(token.tokens);
|
|
116
|
+
}
|
|
117
|
+
return "";
|
|
118
|
+
}).join("");
|
|
119
|
+
}
|
|
120
|
+
export {
|
|
121
|
+
Markdown
|
|
122
|
+
};
|
package/dist/ui/index.d.ts
CHANGED
|
@@ -168,4 +168,43 @@ type ModalProps = {
|
|
|
168
168
|
};
|
|
169
169
|
declare function Modal({ children, onClose, title, borderStyle }: ModalProps): react_jsx_runtime.JSX.Element;
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
type BadgeVariant = 'round' | 'arrow' | 'plain';
|
|
172
|
+
type BadgeProps = {
|
|
173
|
+
children: string;
|
|
174
|
+
color?: string;
|
|
175
|
+
background?: string;
|
|
176
|
+
variant?: BadgeVariant;
|
|
177
|
+
};
|
|
178
|
+
declare function Badge({ children, color, background, variant }: BadgeProps): react_jsx_runtime.JSX.Element;
|
|
179
|
+
|
|
180
|
+
type PanelProps = {
|
|
181
|
+
children: React__default.ReactNode;
|
|
182
|
+
title?: string;
|
|
183
|
+
width?: number;
|
|
184
|
+
borderColor?: string;
|
|
185
|
+
footer?: React__default.ReactNode;
|
|
186
|
+
};
|
|
187
|
+
declare function Panel({ children, title, width, borderColor, footer }: PanelProps): react_jsx_runtime.JSX.Element;
|
|
188
|
+
|
|
189
|
+
type TokenColors = {
|
|
190
|
+
keyword: string;
|
|
191
|
+
string: string;
|
|
192
|
+
number: string;
|
|
193
|
+
comment: string;
|
|
194
|
+
function: string;
|
|
195
|
+
operator: string;
|
|
196
|
+
punctuation: string;
|
|
197
|
+
builtin: string;
|
|
198
|
+
className: string;
|
|
199
|
+
inserted: string;
|
|
200
|
+
deleted: string;
|
|
201
|
+
};
|
|
202
|
+
type CodeBlockProps = {
|
|
203
|
+
children: string;
|
|
204
|
+
language?: string;
|
|
205
|
+
showBorder?: boolean;
|
|
206
|
+
tokenColors?: Partial<TokenColors>;
|
|
207
|
+
};
|
|
208
|
+
declare function CodeBlock({ children, language, showBorder, tokenColors }: CodeBlockProps): react_jsx_runtime.JSX.Element;
|
|
209
|
+
|
|
210
|
+
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 ViewportRenderProps, VirtualList, type VirtualListRenderProps };
|
package/dist/ui/index.js
CHANGED
|
@@ -3,9 +3,14 @@ import {
|
|
|
3
3
|
GigglesError,
|
|
4
4
|
useFocus,
|
|
5
5
|
useKeybindingRegistry,
|
|
6
|
-
useKeybindings
|
|
6
|
+
useKeybindings
|
|
7
|
+
} from "../chunk-CKA5JJ4B.js";
|
|
8
|
+
import {
|
|
9
|
+
CodeBlock
|
|
10
|
+
} from "../chunk-TFYBLNEZ.js";
|
|
11
|
+
import {
|
|
7
12
|
useTheme
|
|
8
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-PVXJL6SX.js";
|
|
9
14
|
|
|
10
15
|
// src/ui/CommandPalette.tsx
|
|
11
16
|
import { useState } from "react";
|
|
@@ -756,13 +761,92 @@ function ModalInner({ children, onClose, title, borderStyle = "round" }) {
|
|
|
756
761
|
function Modal({ children, onClose, title, borderStyle }) {
|
|
757
762
|
return /* @__PURE__ */ jsx9(FocusTrap, { children: /* @__PURE__ */ jsx9(ModalInner, { onClose, title, borderStyle, children }) });
|
|
758
763
|
}
|
|
764
|
+
|
|
765
|
+
// src/ui/Badge.tsx
|
|
766
|
+
import { Text as Text10 } from "ink";
|
|
767
|
+
import { jsx as jsx10, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
768
|
+
var glyphs = {
|
|
769
|
+
round: ["\uE0B6", "\uE0B4"],
|
|
770
|
+
arrow: ["\uE0B2", "\uE0B0"],
|
|
771
|
+
plain: ["", ""]
|
|
772
|
+
};
|
|
773
|
+
function Badge({ children, color, background, variant = "round" }) {
|
|
774
|
+
const theme = useTheme();
|
|
775
|
+
const bg = background ?? theme.accentColor;
|
|
776
|
+
const fg = color ?? "#000000";
|
|
777
|
+
const [left, right] = glyphs[variant];
|
|
778
|
+
const label = variant === "plain" ? ` ${children} ` : children;
|
|
779
|
+
return /* @__PURE__ */ jsxs11(Text10, { children: [
|
|
780
|
+
left && /* @__PURE__ */ jsx10(Text10, { color: bg, children: left }),
|
|
781
|
+
/* @__PURE__ */ jsx10(Text10, { color: fg, backgroundColor: bg, bold: true, children: label }),
|
|
782
|
+
right && /* @__PURE__ */ jsx10(Text10, { color: bg, children: right })
|
|
783
|
+
] });
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// src/ui/Panel.tsx
|
|
787
|
+
import { useState as useState7 } from "react";
|
|
788
|
+
import { Box as Box8, Text as Text11, measureElement } from "ink";
|
|
789
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
790
|
+
function Panel({ children, title, width, borderColor, footer }) {
|
|
791
|
+
const theme = useTheme();
|
|
792
|
+
const color = borderColor ?? theme.borderColor;
|
|
793
|
+
const [measuredWidth, setMeasuredWidth] = useState7(width ?? 0);
|
|
794
|
+
const effectiveWidth = width ?? measuredWidth;
|
|
795
|
+
const renderTopBorder = () => {
|
|
796
|
+
if (effectiveWidth === 0) return null;
|
|
797
|
+
if (title == null) {
|
|
798
|
+
return /* @__PURE__ */ jsxs12(Text11, { color, children: [
|
|
799
|
+
"\u256D",
|
|
800
|
+
"\u2500".repeat(Math.max(0, effectiveWidth - 2)),
|
|
801
|
+
"\u256E"
|
|
802
|
+
] });
|
|
803
|
+
}
|
|
804
|
+
const maxTitleWidth = Math.max(0, effectiveWidth - 5);
|
|
805
|
+
const displayTitle = title.length > maxTitleWidth ? title.slice(0, maxTitleWidth - 1) + "\u2026" : title;
|
|
806
|
+
const titlePart = `\u256D ${displayTitle} `;
|
|
807
|
+
const totalDashes = Math.max(1, effectiveWidth - titlePart.length - 1);
|
|
808
|
+
return /* @__PURE__ */ jsxs12(Text11, { children: [
|
|
809
|
+
/* @__PURE__ */ jsx11(Text11, { color, children: "\u256D " }),
|
|
810
|
+
/* @__PURE__ */ jsx11(Text11, { color, bold: true, children: displayTitle }),
|
|
811
|
+
/* @__PURE__ */ jsxs12(Text11, { color, children: [
|
|
812
|
+
" ",
|
|
813
|
+
"\u2500".repeat(totalDashes),
|
|
814
|
+
"\u256E"
|
|
815
|
+
] })
|
|
816
|
+
] });
|
|
817
|
+
};
|
|
818
|
+
return /* @__PURE__ */ jsxs12(
|
|
819
|
+
Box8,
|
|
820
|
+
{
|
|
821
|
+
flexDirection: "column",
|
|
822
|
+
width,
|
|
823
|
+
flexGrow: width == null ? 1 : void 0,
|
|
824
|
+
ref: (node) => {
|
|
825
|
+
if (node) {
|
|
826
|
+
const { width: w } = measureElement(node);
|
|
827
|
+
if (w !== measuredWidth) setMeasuredWidth(w);
|
|
828
|
+
}
|
|
829
|
+
},
|
|
830
|
+
children: [
|
|
831
|
+
renderTopBorder(),
|
|
832
|
+
/* @__PURE__ */ jsx11(Box8, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderTop: false, borderColor: color, paddingX: 1, children: footer ? /* @__PURE__ */ jsxs12(Fragment3, { children: [
|
|
833
|
+
/* @__PURE__ */ jsx11(Box8, { flexDirection: "column", flexGrow: 1, children }),
|
|
834
|
+
footer
|
|
835
|
+
] }) : children })
|
|
836
|
+
]
|
|
837
|
+
}
|
|
838
|
+
);
|
|
839
|
+
}
|
|
759
840
|
export {
|
|
760
841
|
Autocomplete,
|
|
842
|
+
Badge,
|
|
843
|
+
CodeBlock,
|
|
761
844
|
CommandPalette,
|
|
762
845
|
Confirm,
|
|
763
846
|
Modal,
|
|
764
847
|
MultiSelect,
|
|
765
848
|
Paginator,
|
|
849
|
+
Panel,
|
|
766
850
|
Select,
|
|
767
851
|
TextInput,
|
|
768
852
|
Viewport,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "giggles",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.9",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"./ui": {
|
|
22
22
|
"import": "./dist/ui/index.js",
|
|
23
23
|
"types": "./dist/ui/index.d.ts"
|
|
24
|
+
},
|
|
25
|
+
"./markdown": {
|
|
26
|
+
"import": "./dist/markdown/index.js",
|
|
27
|
+
"types": "./dist/markdown/index.d.ts"
|
|
24
28
|
}
|
|
25
29
|
},
|
|
26
30
|
"keywords": [
|
|
@@ -37,7 +41,7 @@
|
|
|
37
41
|
"build": "tsup",
|
|
38
42
|
"build:watch": "nodemon --watch src --ext ts,tsx --exec tsup",
|
|
39
43
|
"dev": "tsx --watch playground/index.tsx",
|
|
40
|
-
"dev:docs": "pnpm build &&
|
|
44
|
+
"dev:docs": "pnpm build && pnpm --filter documentation dev",
|
|
41
45
|
"lint": "prettier --write . && eslint . --fix"
|
|
42
46
|
},
|
|
43
47
|
"files": [
|
|
@@ -50,6 +54,7 @@
|
|
|
50
54
|
"devDependencies": {
|
|
51
55
|
"@trivago/prettier-plugin-sort-imports": "^4.3.0",
|
|
52
56
|
"@types/node": "^22.0.0",
|
|
57
|
+
"@types/prismjs": "^1.26.6",
|
|
53
58
|
"@types/react": "^19.2.13",
|
|
54
59
|
"eslint": "^9.0.0",
|
|
55
60
|
"eslint-plugin-react": "^7.32.2",
|
|
@@ -64,6 +69,10 @@
|
|
|
64
69
|
"typescript-eslint": "^8.0.0"
|
|
65
70
|
},
|
|
66
71
|
"dependencies": {
|
|
67
|
-
"
|
|
72
|
+
"cli-table3": "^0.6.5",
|
|
73
|
+
"execa": "^9.6.1",
|
|
74
|
+
"ink-link": "^5.0.0",
|
|
75
|
+
"marked": "^17.0.3",
|
|
76
|
+
"prismjs": "^1.30.0"
|
|
68
77
|
}
|
|
69
78
|
}
|