@yuaone/cli 0.1.3 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/dist/cli.js +29 -4
  2. package/dist/cli.js.map +1 -1
  3. package/dist/tui/App.d.ts +33 -0
  4. package/dist/tui/App.d.ts.map +1 -0
  5. package/dist/tui/App.js +244 -0
  6. package/dist/tui/App.js.map +1 -0
  7. package/dist/tui/agent-bridge.d.ts +56 -0
  8. package/dist/tui/agent-bridge.d.ts.map +1 -0
  9. package/dist/tui/agent-bridge.js +138 -0
  10. package/dist/tui/agent-bridge.js.map +1 -0
  11. package/dist/tui/components/BashOutput.d.ts +12 -0
  12. package/dist/tui/components/BashOutput.d.ts.map +1 -0
  13. package/dist/tui/components/BashOutput.js +19 -0
  14. package/dist/tui/components/BashOutput.js.map +1 -0
  15. package/dist/tui/components/CollapsibleSection.d.ts +14 -0
  16. package/dist/tui/components/CollapsibleSection.d.ts.map +1 -0
  17. package/dist/tui/components/CollapsibleSection.js +7 -0
  18. package/dist/tui/components/CollapsibleSection.js.map +1 -0
  19. package/dist/tui/components/DiffView.d.ts +11 -0
  20. package/dist/tui/components/DiffView.d.ts.map +1 -0
  21. package/dist/tui/components/DiffView.js +20 -0
  22. package/dist/tui/components/DiffView.js.map +1 -0
  23. package/dist/tui/components/FooterBar.d.ts +11 -0
  24. package/dist/tui/components/FooterBar.d.ts.map +1 -0
  25. package/dist/tui/components/FooterBar.js +14 -0
  26. package/dist/tui/components/FooterBar.js.map +1 -0
  27. package/dist/tui/components/InputBox.d.ts +24 -0
  28. package/dist/tui/components/InputBox.d.ts.map +1 -0
  29. package/dist/tui/components/InputBox.js +124 -0
  30. package/dist/tui/components/InputBox.js.map +1 -0
  31. package/dist/tui/components/MarkdownRenderer.d.ts +11 -0
  32. package/dist/tui/components/MarkdownRenderer.d.ts.map +1 -0
  33. package/dist/tui/components/MarkdownRenderer.js +118 -0
  34. package/dist/tui/components/MarkdownRenderer.js.map +1 -0
  35. package/dist/tui/components/MessageBubble.d.ts +16 -0
  36. package/dist/tui/components/MessageBubble.d.ts.map +1 -0
  37. package/dist/tui/components/MessageBubble.js +38 -0
  38. package/dist/tui/components/MessageBubble.js.map +1 -0
  39. package/dist/tui/components/MessageList.d.ts +15 -0
  40. package/dist/tui/components/MessageList.d.ts.map +1 -0
  41. package/dist/tui/components/MessageList.js +31 -0
  42. package/dist/tui/components/MessageList.js.map +1 -0
  43. package/dist/tui/components/SlashMenu.d.ts +14 -0
  44. package/dist/tui/components/SlashMenu.d.ts.map +1 -0
  45. package/dist/tui/components/SlashMenu.js +21 -0
  46. package/dist/tui/components/SlashMenu.js.map +1 -0
  47. package/dist/tui/components/Spinner.d.ts +9 -0
  48. package/dist/tui/components/Spinner.d.ts.map +1 -0
  49. package/dist/tui/components/Spinner.js +19 -0
  50. package/dist/tui/components/Spinner.js.map +1 -0
  51. package/dist/tui/components/StatusBar.d.ts +13 -0
  52. package/dist/tui/components/StatusBar.d.ts.map +1 -0
  53. package/dist/tui/components/StatusBar.js +15 -0
  54. package/dist/tui/components/StatusBar.js.map +1 -0
  55. package/dist/tui/components/ThinkingDots.d.ts +9 -0
  56. package/dist/tui/components/ThinkingDots.d.ts.map +1 -0
  57. package/dist/tui/components/ThinkingDots.js +19 -0
  58. package/dist/tui/components/ThinkingDots.js.map +1 -0
  59. package/dist/tui/components/ToolCallTree.d.ts +12 -0
  60. package/dist/tui/components/ToolCallTree.d.ts.map +1 -0
  61. package/dist/tui/components/ToolCallTree.js +45 -0
  62. package/dist/tui/components/ToolCallTree.js.map +1 -0
  63. package/dist/tui/hooks/useAgentStream.d.ts +27 -0
  64. package/dist/tui/hooks/useAgentStream.d.ts.map +1 -0
  65. package/dist/tui/hooks/useAgentStream.js +212 -0
  66. package/dist/tui/hooks/useAgentStream.js.map +1 -0
  67. package/dist/tui/hooks/useInputHistory.d.ts +17 -0
  68. package/dist/tui/hooks/useInputHistory.d.ts.map +1 -0
  69. package/dist/tui/hooks/useInputHistory.js +49 -0
  70. package/dist/tui/hooks/useInputHistory.js.map +1 -0
  71. package/dist/tui/hooks/useKeyHandler.d.ts +12 -0
  72. package/dist/tui/hooks/useKeyHandler.d.ts.map +1 -0
  73. package/dist/tui/hooks/useKeyHandler.js +20 -0
  74. package/dist/tui/hooks/useKeyHandler.js.map +1 -0
  75. package/dist/tui/hooks/useScrollPosition.d.ts +27 -0
  76. package/dist/tui/hooks/useScrollPosition.d.ts.map +1 -0
  77. package/dist/tui/hooks/useScrollPosition.js +54 -0
  78. package/dist/tui/hooks/useScrollPosition.js.map +1 -0
  79. package/dist/tui/hooks/useSlashCommands.d.ts +22 -0
  80. package/dist/tui/hooks/useSlashCommands.d.ts.map +1 -0
  81. package/dist/tui/hooks/useSlashCommands.js +61 -0
  82. package/dist/tui/hooks/useSlashCommands.js.map +1 -0
  83. package/dist/tui/hooks/useTerminalSize.d.ts +11 -0
  84. package/dist/tui/hooks/useTerminalSize.d.ts.map +1 -0
  85. package/dist/tui/hooks/useTerminalSize.js +25 -0
  86. package/dist/tui/hooks/useTerminalSize.js.map +1 -0
  87. package/dist/tui/lib/ansi.d.ts +36 -0
  88. package/dist/tui/lib/ansi.d.ts.map +1 -0
  89. package/dist/tui/lib/ansi.js +40 -0
  90. package/dist/tui/lib/ansi.js.map +1 -0
  91. package/dist/tui/lib/box-drawing.d.ts +12 -0
  92. package/dist/tui/lib/box-drawing.d.ts.map +1 -0
  93. package/dist/tui/lib/box-drawing.js +30 -0
  94. package/dist/tui/lib/box-drawing.js.map +1 -0
  95. package/dist/tui/lib/diff-formatter.d.ts +9 -0
  96. package/dist/tui/lib/diff-formatter.d.ts.map +1 -0
  97. package/dist/tui/lib/diff-formatter.js +65 -0
  98. package/dist/tui/lib/diff-formatter.js.map +1 -0
  99. package/dist/tui/lib/tokens.d.ts +56 -0
  100. package/dist/tui/lib/tokens.d.ts.map +1 -0
  101. package/dist/tui/lib/tokens.js +61 -0
  102. package/dist/tui/lib/tokens.js.map +1 -0
  103. package/dist/tui/lib/truncate.d.ts +11 -0
  104. package/dist/tui/lib/truncate.d.ts.map +1 -0
  105. package/dist/tui/lib/truncate.js +69 -0
  106. package/dist/tui/lib/truncate.js.map +1 -0
  107. package/dist/tui/lib/update-checker.d.ts +21 -0
  108. package/dist/tui/lib/update-checker.d.ts.map +1 -0
  109. package/dist/tui/lib/update-checker.js +133 -0
  110. package/dist/tui/lib/update-checker.js.map +1 -0
  111. package/dist/tui/types.d.ts +77 -0
  112. package/dist/tui/types.d.ts.map +1 -0
  113. package/dist/tui/types.js +5 -0
  114. package/dist/tui/types.js.map +1 -0
  115. package/package.json +13 -3
@@ -0,0 +1,54 @@
1
+ /**
2
+ * useScrollPosition — virtual scroll state for MessageList.
3
+ * Tracks scroll offset, auto-scroll behavior, and scroll indicators.
4
+ */
5
+ import { useState, useCallback, useEffect } from "react";
6
+ export function useScrollPosition(totalMessages, viewportSize) {
7
+ const [offset, setOffset] = useState(0);
8
+ const [autoScroll, setAutoScroll] = useState(true);
9
+ // Auto-scroll when new messages arrive and autoScroll is engaged
10
+ useEffect(() => {
11
+ if (autoScroll && totalMessages > viewportSize) {
12
+ setOffset(Math.max(0, totalMessages - viewportSize));
13
+ }
14
+ }, [totalMessages, viewportSize, autoScroll]);
15
+ const scrollUp = useCallback((amount = 1) => {
16
+ setOffset((prev) => {
17
+ const next = Math.max(0, prev - amount);
18
+ if (next < prev)
19
+ setAutoScroll(false);
20
+ return next;
21
+ });
22
+ }, []);
23
+ const scrollDown = useCallback((amount = 1) => {
24
+ setOffset((prev) => {
25
+ const maxOffset = Math.max(0, totalMessages - viewportSize);
26
+ const next = Math.min(maxOffset, prev + amount);
27
+ if (next >= maxOffset)
28
+ setAutoScroll(true);
29
+ return next;
30
+ });
31
+ }, [totalMessages, viewportSize]);
32
+ const scrollToBottom = useCallback(() => {
33
+ setOffset(Math.max(0, totalMessages - viewportSize));
34
+ setAutoScroll(true);
35
+ }, [totalMessages, viewportSize]);
36
+ const pageUp = useCallback(() => {
37
+ scrollUp(Math.max(1, viewportSize - 2));
38
+ }, [scrollUp, viewportSize]);
39
+ const pageDown = useCallback(() => {
40
+ scrollDown(Math.max(1, viewportSize - 2));
41
+ }, [scrollDown, viewportSize]);
42
+ const aboveCount = offset;
43
+ const belowCount = Math.max(0, totalMessages - viewportSize - offset);
44
+ const state = {
45
+ offset,
46
+ total: totalMessages,
47
+ viewportSize,
48
+ autoScroll,
49
+ aboveCount,
50
+ belowCount,
51
+ };
52
+ return [state, { scrollUp, scrollDown, scrollToBottom, pageUp, pageDown }];
53
+ }
54
+ //# sourceMappingURL=useScrollPosition.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScrollPosition.js","sourceRoot":"","sources":["../../../src/tui/hooks/useScrollPosition.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * useSlashCommands — slash command registry and fuzzy matching.
3
+ */
4
+ import type { SlashCommand } from "../types.js";
5
+ /** Check if a string is a known command name (exact or alias match) */
6
+ export declare function isKnownCommand(input: string): boolean;
7
+ export interface SlashCommandState {
8
+ commands: SlashCommand[];
9
+ filtered: SlashCommand[];
10
+ selectedIndex: number;
11
+ isOpen: boolean;
12
+ }
13
+ export interface SlashCommandActions {
14
+ filter: (query: string) => void;
15
+ selectNext: () => void;
16
+ selectPrev: () => void;
17
+ getSelected: () => SlashCommand | null;
18
+ open: () => void;
19
+ close: () => void;
20
+ }
21
+ export declare function useSlashCommands(extraCommands?: SlashCommand[]): [SlashCommandState, SlashCommandActions];
22
+ //# sourceMappingURL=useSlashCommands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSlashCommands.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useSlashCommands.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAehD,uEAAuE;AACvE,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOrD;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,UAAU,EAAE,MAAM,IAAI,CAAC;IACvB,WAAW,EAAE,MAAM,YAAY,GAAG,IAAI,CAAC;IACvC,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB;AAED,wBAAgB,gBAAgB,CAC9B,aAAa,GAAE,YAAY,EAAO,GACjC,CAAC,iBAAiB,EAAE,mBAAmB,CAAC,CAkD1C"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * useSlashCommands — slash command registry and fuzzy matching.
3
+ */
4
+ import { useState, useMemo, useCallback } from "react";
5
+ const DEFAULT_COMMANDS = [
6
+ { name: "/help", description: "Show available commands", aliases: ["/h"] },
7
+ { name: "/status", description: "Model, tokens, session info" },
8
+ { name: "/clear", description: "Clear conversation history" },
9
+ { name: "/model", description: "Change model" },
10
+ { name: "/config", description: "Show/edit configuration" },
11
+ { name: "/session", description: "Session management" },
12
+ { name: "/diff", description: "Show recent diffs" },
13
+ { name: "/undo", description: "Undo last change" },
14
+ { name: "/settings", description: "Auto-update, preferences" },
15
+ { name: "/exit", description: "Exit YUAN", aliases: ["/quit", "/q"] },
16
+ ];
17
+ /** Check if a string is a known command name (exact or alias match) */
18
+ export function isKnownCommand(input) {
19
+ const q = input.trim().toLowerCase().split(" ")[0];
20
+ return DEFAULT_COMMANDS.some((cmd) => cmd.name === q ||
21
+ cmd.aliases?.includes(q));
22
+ }
23
+ export function useSlashCommands(extraCommands = []) {
24
+ const commands = useMemo(() => [...DEFAULT_COMMANDS, ...extraCommands], [extraCommands]);
25
+ const [query, setQuery] = useState("");
26
+ const [selectedIndex, setSelectedIndex] = useState(0);
27
+ const [isOpen, setIsOpen] = useState(false);
28
+ const filtered = useMemo(() => {
29
+ if (!query || query === "/")
30
+ return commands;
31
+ const q = query.toLowerCase();
32
+ return commands.filter((cmd) => cmd.name.toLowerCase().includes(q) ||
33
+ cmd.description.toLowerCase().includes(q) ||
34
+ cmd.aliases?.some((a) => a.toLowerCase().includes(q)));
35
+ }, [commands, query]);
36
+ const filter = useCallback((q) => {
37
+ setQuery(q);
38
+ setSelectedIndex(0);
39
+ setIsOpen(q.startsWith("/"));
40
+ }, []);
41
+ const selectNext = useCallback(() => {
42
+ setSelectedIndex((prev) => Math.min(prev + 1, filtered.length - 1));
43
+ }, [filtered.length]);
44
+ const selectPrev = useCallback(() => {
45
+ setSelectedIndex((prev) => Math.max(prev - 1, 0));
46
+ }, []);
47
+ const getSelected = useCallback(() => {
48
+ return filtered[selectedIndex] ?? null;
49
+ }, [filtered, selectedIndex]);
50
+ const open = useCallback(() => setIsOpen(true), []);
51
+ const close = useCallback(() => {
52
+ setIsOpen(false);
53
+ setQuery("");
54
+ setSelectedIndex(0);
55
+ }, []);
56
+ return [
57
+ { commands, filtered, selectedIndex, isOpen },
58
+ { filter, selectNext, selectPrev, getSelected, open, close },
59
+ ];
60
+ }
61
+ //# sourceMappingURL=useSlashCommands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSlashCommands.js","sourceRoot":"","sources":["../../../src/tui/hooks/useSlashCommands.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Hook: track terminal size and layout tier, update on resize.
3
+ */
4
+ import { type LayoutTier } from "../lib/tokens.js";
5
+ export interface TerminalSize {
6
+ columns: number;
7
+ rows: number;
8
+ tier: LayoutTier;
9
+ }
10
+ export declare function useTerminalSize(): TerminalSize;
11
+ //# sourceMappingURL=useTerminalSize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTerminalSize.d.ts","sourceRoot":"","sources":["../../../src/tui/hooks/useTerminalSize.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAiB,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,UAAU,CAAC;CAClB;AAED,wBAAgB,eAAe,IAAI,YAAY,CAqB9C"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Hook: track terminal size and layout tier, update on resize.
3
+ */
4
+ import { useState, useEffect } from "react";
5
+ import { getLayoutTier } from "../lib/tokens.js";
6
+ export function useTerminalSize() {
7
+ const [size, setSize] = useState(() => ({
8
+ columns: process.stdout.columns || 80,
9
+ rows: process.stdout.rows || 24,
10
+ tier: getLayoutTier(process.stdout.columns || 80),
11
+ }));
12
+ useEffect(() => {
13
+ const onResize = () => {
14
+ const columns = process.stdout.columns || 80;
15
+ const rows = process.stdout.rows || 24;
16
+ setSize({ columns, rows, tier: getLayoutTier(columns) });
17
+ };
18
+ process.stdout.on("resize", onResize);
19
+ return () => {
20
+ process.stdout.off("resize", onResize);
21
+ };
22
+ }, []);
23
+ return size;
24
+ }
25
+ //# sourceMappingURL=useTerminalSize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useTerminalSize.js","sourceRoot":"","sources":["../../../src/tui/hooks/useTerminalSize.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AAQlE,MAAM,UAAU,eAAe;IAC7B,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAe,GAAG,EAAE,CAAC,CAAC;QACpD,OAAO,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE;QACrC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE;QAC/B,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;KAClD,CAAC,CAAC,CAAC;IAEJ,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,QAAQ,GAAG,GAAG,EAAE;YACpB,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC;YAC7C,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACvC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC3D,CAAC,CAAC;QAEF,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACtC,OAAO,GAAG,EAAE;YACV,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QACzC,CAAC,CAAC;IACJ,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Raw ANSI escape helpers for screen buffer and cursor control.
3
+ */
4
+ export declare const ANSI: {
5
+ /** Enter alternate screen buffer */
6
+ readonly altScreenEnter: "\u001B[?1049h";
7
+ /** Exit alternate screen buffer */
8
+ readonly altScreenExit: "\u001B[?1049l";
9
+ /** Hide cursor */
10
+ readonly cursorHide: "\u001B[?25l";
11
+ /** Show cursor */
12
+ readonly cursorShow: "\u001B[?25h";
13
+ /** Enable mouse button tracking (preserves text selection) */
14
+ readonly mouseEnable: "\u001B[?1000h\u001B[?1006h";
15
+ /** Disable mouse tracking */
16
+ readonly mouseDisable: "\u001B[?1000l\u001B[?1006l";
17
+ /** Clear entire screen */
18
+ readonly clearScreen: "\u001B[2J\u001B[H";
19
+ /** Move cursor to position */
20
+ readonly moveTo: (row: number, col: number) => string;
21
+ /** Clear line from cursor */
22
+ readonly clearLine: "\u001B[K";
23
+ /** Scroll up N lines */
24
+ readonly scrollUp: (n: number) => string;
25
+ /** Scroll down N lines */
26
+ readonly scrollDown: (n: number) => string;
27
+ /** Set scroll region */
28
+ readonly setScrollRegion: (top: number, bottom: number) => string;
29
+ /** Reset scroll region */
30
+ readonly resetScrollRegion: "\u001B[r";
31
+ };
32
+ /** Enter TUI mode: alt screen + hide cursor + mouse */
33
+ export declare function enterTUI(): void;
34
+ /** Exit TUI mode: restore everything */
35
+ export declare function exitTUI(): void;
36
+ //# sourceMappingURL=ansi.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.d.ts","sourceRoot":"","sources":["../../../src/tui/lib/ansi.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,eAAO,MAAM,IAAI;IACf,oCAAoC;;IAEpC,mCAAmC;;IAGnC,kBAAkB;;IAElB,kBAAkB;;IAGlB,8DAA8D;;IAE9D,6BAA6B;;IAG7B,0BAA0B;;IAG1B,8BAA8B;2BAChB,MAAM,OAAO,MAAM;IAEjC,6BAA6B;;IAG7B,wBAAwB;2BACV,MAAM;IAEpB,0BAA0B;6BACV,MAAM;IAEtB,wBAAwB;oCACD,MAAM,UAAU,MAAM;IAE7C,0BAA0B;;CAElB,CAAC;AAEX,uDAAuD;AACvD,wBAAgB,QAAQ,IAAI,IAAI,CAI/B;AAED,wCAAwC;AACxC,wBAAgB,OAAO,IAAI,IAAI,CAI9B"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Raw ANSI escape helpers for screen buffer and cursor control.
3
+ */
4
+ export const ANSI = {
5
+ /** Enter alternate screen buffer */
6
+ altScreenEnter: "\x1b[?1049h",
7
+ /** Exit alternate screen buffer */
8
+ altScreenExit: "\x1b[?1049l",
9
+ /** Hide cursor */
10
+ cursorHide: "\x1b[?25l",
11
+ /** Show cursor */
12
+ cursorShow: "\x1b[?25h",
13
+ /** Enable mouse button tracking (preserves text selection) */
14
+ mouseEnable: "\x1b[?1000h\x1b[?1006h",
15
+ /** Disable mouse tracking */
16
+ mouseDisable: "\x1b[?1000l\x1b[?1006l",
17
+ /** Clear entire screen */
18
+ clearScreen: "\x1b[2J\x1b[H",
19
+ /** Move cursor to position */
20
+ moveTo: (row, col) => `\x1b[${row};${col}H`,
21
+ /** Clear line from cursor */
22
+ clearLine: "\x1b[K",
23
+ /** Scroll up N lines */
24
+ scrollUp: (n) => `\x1b[${n}S`,
25
+ /** Scroll down N lines */
26
+ scrollDown: (n) => `\x1b[${n}T`,
27
+ /** Set scroll region */
28
+ setScrollRegion: (top, bottom) => `\x1b[${top};${bottom}r`,
29
+ /** Reset scroll region */
30
+ resetScrollRegion: "\x1b[r",
31
+ };
32
+ /** Enter TUI mode: alt screen + hide cursor + mouse */
33
+ export function enterTUI() {
34
+ process.stdout.write(ANSI.altScreenEnter + ANSI.cursorHide + ANSI.mouseEnable);
35
+ }
36
+ /** Exit TUI mode: restore everything */
37
+ export function exitTUI() {
38
+ process.stdout.write(ANSI.mouseDisable + ANSI.cursorShow + ANSI.altScreenExit);
39
+ }
40
+ //# sourceMappingURL=ansi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ansi.js","sourceRoot":"","sources":["../../../src/tui/lib/ansi.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,CAAC,MAAM,IAAI,GAAG;IAClB,oCAAoC;IACpC,cAAc,EAAE,aAAa;IAC7B,mCAAmC;IACnC,aAAa,EAAE,aAAa;IAE5B,kBAAkB;IAClB,UAAU,EAAE,WAAW;IACvB,kBAAkB;IAClB,UAAU,EAAE,WAAW;IAEvB,8DAA8D;IAC9D,WAAW,EAAE,wBAAwB;IACrC,6BAA6B;IAC7B,YAAY,EAAE,wBAAwB;IAEtC,0BAA0B;IAC1B,WAAW,EAAE,eAAe;IAE5B,8BAA8B;IAC9B,MAAM,EAAE,CAAC,GAAW,EAAE,GAAW,EAAE,EAAE,CAAC,QAAQ,GAAG,IAAI,GAAG,GAAG;IAE3D,6BAA6B;IAC7B,SAAS,EAAE,QAAQ;IAEnB,wBAAwB;IACxB,QAAQ,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG;IAErC,0BAA0B;IAC1B,UAAU,EAAE,CAAC,CAAS,EAAE,EAAE,CAAC,QAAQ,CAAC,GAAG;IAEvC,wBAAwB;IACxB,eAAe,EAAE,CAAC,GAAW,EAAE,MAAc,EAAE,EAAE,CAAC,QAAQ,GAAG,IAAI,MAAM,GAAG;IAE1E,0BAA0B;IAC1B,iBAAiB,EAAE,QAAQ;CACnB,CAAC;AAEX,uDAAuD;AACvD,MAAM,UAAU,QAAQ;IACtB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,CACzD,CAAC;AACJ,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,OAAO;IACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CACzD,CAAC;AACJ,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Box drawing utilities for rounded-corner panels.
3
+ */
4
+ /** Draw a horizontal line of given width */
5
+ export declare function hLine(width: number): string;
6
+ /** Draw top border with optional title */
7
+ export declare function topBorder(width: number, title?: string): string;
8
+ /** Draw bottom border */
9
+ export declare function bottomBorder(width: number): string;
10
+ /** Wrap a single line of content in box side borders, padded to width */
11
+ export declare function boxLine(content: string, width: number, contentWidth: number): string;
12
+ //# sourceMappingURL=box-drawing.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box-drawing.d.ts","sourceRoot":"","sources":["../../../src/tui/lib/box-drawing.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,4CAA4C;AAC5C,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,0CAA0C;AAC1C,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ/D;AAED,yBAAyB;AACzB,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAElD;AAED,yEAAyE;AACzE,wBAAgB,OAAO,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAGpF"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Box drawing utilities for rounded-corner panels.
3
+ */
4
+ import { TOKENS } from "./tokens.js";
5
+ const B = TOKENS.box;
6
+ /** Draw a horizontal line of given width */
7
+ export function hLine(width) {
8
+ return B.horizontal.repeat(Math.max(0, width));
9
+ }
10
+ /** Draw top border with optional title */
11
+ export function topBorder(width, title) {
12
+ if (title) {
13
+ const titleStr = ` ${title} `;
14
+ const remaining = width - 2 - titleStr.length;
15
+ if (remaining < 0)
16
+ return B.topLeft + hLine(width - 2) + B.topRight;
17
+ return B.topLeft + B.horizontal + titleStr + hLine(remaining - 1) + B.topRight;
18
+ }
19
+ return B.topLeft + hLine(width - 2) + B.topRight;
20
+ }
21
+ /** Draw bottom border */
22
+ export function bottomBorder(width) {
23
+ return B.bottomLeft + hLine(width - 2) + B.bottomRight;
24
+ }
25
+ /** Wrap a single line of content in box side borders, padded to width */
26
+ export function boxLine(content, width, contentWidth) {
27
+ const padding = Math.max(0, width - 2 - contentWidth);
28
+ return B.vertical + content + " ".repeat(padding) + B.vertical;
29
+ }
30
+ //# sourceMappingURL=box-drawing.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"box-drawing.js","sourceRoot":"","sources":["../../../src/tui/lib/box-drawing.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC;AAErB,4CAA4C;AAC5C,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;AACjD,CAAC;AAED,0CAA0C;AAC1C,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,KAAc;IACrD,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,QAAQ,GAAG,IAAI,KAAK,GAAG,CAAC;QAC9B,MAAM,SAAS,GAAG,KAAK,GAAG,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC9C,IAAI,SAAS,GAAG,CAAC;YAAE,OAAO,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;QACpE,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,UAAU,GAAG,QAAQ,GAAG,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IACjF,CAAC;IACD,OAAO,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AACnD,CAAC;AAED,yBAAyB;AACzB,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,OAAO,CAAC,CAAC,UAAU,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC;AACzD,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,OAAO,CAAC,OAAe,EAAE,KAAa,EAAE,YAAoB;IAC1E,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC;IACtD,OAAO,CAAC,CAAC,QAAQ,GAAG,OAAO,GAAG,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AACjE,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * diff-formatter — parse unified diff string into structured ParsedDiff.
3
+ */
4
+ import type { ParsedDiff } from "../types.js";
5
+ /**
6
+ * Parse a unified diff string into a ParsedDiff structure.
7
+ */
8
+ export declare function parseDiff(diffText: string, filePath?: string): ParsedDiff;
9
+ //# sourceMappingURL=diff-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-formatter.d.ts","sourceRoot":"","sources":["../../../src/tui/lib/diff-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAkC,MAAM,aAAa,CAAC;AAE9E;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,SAAK,GAAG,UAAU,CA2DrE"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * diff-formatter — parse unified diff string into structured ParsedDiff.
3
+ */
4
+ /**
5
+ * Parse a unified diff string into a ParsedDiff structure.
6
+ */
7
+ export function parseDiff(diffText, filePath = "") {
8
+ const lines = diffText.split("\n");
9
+ const hunks = [];
10
+ let additions = 0;
11
+ let deletions = 0;
12
+ let currentHunk = null;
13
+ let oldLine = 0;
14
+ let newLine = 0;
15
+ for (const line of lines) {
16
+ // Detect file path from diff header
17
+ if (line.startsWith("--- a/") || line.startsWith("+++ b/")) {
18
+ if (!filePath && line.startsWith("+++ b/")) {
19
+ filePath = line.slice(6);
20
+ }
21
+ continue;
22
+ }
23
+ // Hunk header
24
+ const hunkMatch = line.match(/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/);
25
+ if (hunkMatch) {
26
+ currentHunk = {
27
+ startOld: parseInt(hunkMatch[1], 10),
28
+ startNew: parseInt(hunkMatch[2], 10),
29
+ lines: [],
30
+ };
31
+ oldLine = currentHunk.startOld;
32
+ newLine = currentHunk.startNew;
33
+ hunks.push(currentHunk);
34
+ continue;
35
+ }
36
+ if (!currentHunk)
37
+ continue;
38
+ if (line.startsWith("+")) {
39
+ currentHunk.lines.push({
40
+ type: "add",
41
+ content: line.slice(1),
42
+ newLineNo: newLine++,
43
+ });
44
+ additions++;
45
+ }
46
+ else if (line.startsWith("-")) {
47
+ currentHunk.lines.push({
48
+ type: "delete",
49
+ content: line.slice(1),
50
+ oldLineNo: oldLine++,
51
+ });
52
+ deletions++;
53
+ }
54
+ else if (line.startsWith(" ")) {
55
+ currentHunk.lines.push({
56
+ type: "context",
57
+ content: line.slice(1),
58
+ oldLineNo: oldLine++,
59
+ newLineNo: newLine++,
60
+ });
61
+ }
62
+ }
63
+ return { filePath, hunks, additions, deletions };
64
+ }
65
+ //# sourceMappingURL=diff-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"diff-formatter.js","sourceRoot":"","sources":["../../../src/tui/lib/diff-formatter.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,QAAgB,EAAE,QAAQ,GAAG,EAAE;IACvD,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,KAAK,GAAqB,EAAE,CAAC;IACnC,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,WAAW,GAA0B,IAAI,CAAC;IAC9C,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,OAAO,GAAG,CAAC,CAAC;IAEhB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,oCAAoC;QACpC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC3D,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC3C,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;YACD,SAAS;QACX,CAAC;QAED,cAAc;QACd,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;QACxE,IAAI,SAAS,EAAE,CAAC;YACd,WAAW,GAAG;gBACZ,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACpC,QAAQ,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;gBACpC,KAAK,EAAE,EAAE;aACV,CAAC;YACF,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC;YAC/B,OAAO,GAAG,WAAW,CAAC,QAAQ,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YACxB,SAAS;QACX,CAAC;QAED,IAAI,CAAC,WAAW;YAAE,SAAS;QAE3B,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACzB,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;gBACrB,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtB,SAAS,EAAE,OAAO,EAAE;aACrB,CAAC,CAAC;YACH,SAAS,EAAE,CAAC;QACd,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;gBACrB,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtB,SAAS,EAAE,OAAO,EAAE;aACrB,CAAC,CAAC;YACH,SAAS,EAAE,CAAC;QACd,CAAC;aAAM,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAChC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC;gBACrB,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;gBACtB,SAAS,EAAE,OAAO,EAAE;gBACpB,SAAS,EAAE,OAAO,EAAE;aACrB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,CAAC;AACnD,CAAC"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * YUAN TUI Design Tokens
3
+ * Monochrome gray + white palette. Professional, quiet, fast.
4
+ */
5
+ export declare const TOKENS: {
6
+ readonly brand: {
7
+ readonly prefix: "◆";
8
+ readonly name: "yuan";
9
+ readonly prompt: "▸";
10
+ readonly userPrefix: "●";
11
+ };
12
+ readonly color: {
13
+ readonly primary: "white";
14
+ readonly secondary: "gray";
15
+ readonly accent: "white";
16
+ readonly success: "green";
17
+ readonly error: "red";
18
+ readonly warning: "yellow";
19
+ readonly diffAdd: "green";
20
+ readonly diffDel: "red";
21
+ readonly muted: "dim";
22
+ };
23
+ readonly spinner: {
24
+ readonly frames: readonly string[];
25
+ readonly interval: 80;
26
+ readonly style: "dim";
27
+ };
28
+ readonly dots: {
29
+ readonly frames: readonly string[];
30
+ readonly interval: 150;
31
+ readonly style: "dim";
32
+ };
33
+ readonly box: {
34
+ readonly topLeft: "╭";
35
+ readonly topRight: "╮";
36
+ readonly bottomLeft: "╰";
37
+ readonly bottomRight: "╯";
38
+ readonly horizontal: "─";
39
+ readonly vertical: "│";
40
+ readonly style: "dim";
41
+ };
42
+ readonly tree: {
43
+ readonly branch: "├─";
44
+ readonly last: "└─";
45
+ readonly pipe: "│ ";
46
+ readonly style: "dim";
47
+ };
48
+ readonly layout: {
49
+ readonly compact: 80;
50
+ readonly normal: 120;
51
+ readonly padding: 2;
52
+ };
53
+ };
54
+ export type LayoutTier = "compact" | "normal" | "wide";
55
+ export declare function getLayoutTier(columns: number): LayoutTier;
56
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../../src/tui/lib/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;yBAqB+C,SAAS,MAAM,EAAE;;;;;yBAMhC,SAAS,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;CA2B1D,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,QAAQ,GAAG,MAAM,CAAC;AAEvD,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,UAAU,CAIzD"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * YUAN TUI Design Tokens
3
+ * Monochrome gray + white palette. Professional, quiet, fast.
4
+ */
5
+ export const TOKENS = {
6
+ brand: {
7
+ prefix: "◆",
8
+ name: "yuan",
9
+ prompt: "▸",
10
+ userPrefix: "●",
11
+ },
12
+ color: {
13
+ primary: "white",
14
+ secondary: "gray",
15
+ accent: "white",
16
+ success: "green",
17
+ error: "red",
18
+ warning: "yellow",
19
+ diffAdd: "green",
20
+ diffDel: "red",
21
+ muted: "dim",
22
+ },
23
+ spinner: {
24
+ frames: ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"],
25
+ interval: 80,
26
+ style: "dim",
27
+ },
28
+ dots: {
29
+ frames: ["·", "··", "···", "····", "·····"],
30
+ interval: 150,
31
+ style: "dim",
32
+ },
33
+ box: {
34
+ topLeft: "╭",
35
+ topRight: "╮",
36
+ bottomLeft: "╰",
37
+ bottomRight: "╯",
38
+ horizontal: "─",
39
+ vertical: "│",
40
+ style: "dim",
41
+ },
42
+ tree: {
43
+ branch: "├─",
44
+ last: "└─",
45
+ pipe: "│ ",
46
+ style: "dim",
47
+ },
48
+ layout: {
49
+ compact: 80,
50
+ normal: 120,
51
+ padding: 2,
52
+ },
53
+ };
54
+ export function getLayoutTier(columns) {
55
+ if (columns < TOKENS.layout.compact)
56
+ return "compact";
57
+ if (columns < TOKENS.layout.normal)
58
+ return "normal";
59
+ return "wide";
60
+ }
61
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../../src/tui/lib/tokens.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,KAAK,EAAE;QACL,MAAM,EAAE,GAAG;QACX,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,GAAG;QACX,UAAU,EAAE,GAAG;KAChB;IAED,KAAK,EAAE;QACL,OAAO,EAAE,OAAO;QAChB,SAAS,EAAE,MAAM;QACjB,MAAM,EAAE,OAAO;QACf,OAAO,EAAE,OAAO;QAChB,KAAK,EAAE,KAAK;QACZ,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,KAAK;QACd,KAAK,EAAE,KAAK;KACb;IAED,OAAO,EAAE;QACP,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAsB;QAC/E,QAAQ,EAAE,EAAE;QACZ,KAAK,EAAE,KAAc;KACtB;IAED,IAAI,EAAE;QACJ,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,CAAsB;QAChE,QAAQ,EAAE,GAAG;QACb,KAAK,EAAE,KAAc;KACtB;IAED,GAAG,EAAE;QACH,OAAO,EAAE,GAAG;QACZ,QAAQ,EAAE,GAAG;QACb,UAAU,EAAE,GAAG;QACf,WAAW,EAAE,GAAG;QAChB,UAAU,EAAE,GAAG;QACf,QAAQ,EAAE,GAAG;QACb,KAAK,EAAE,KAAc;KACtB;IAED,IAAI,EAAE;QACJ,MAAM,EAAE,IAAI;QACZ,IAAI,EAAE,IAAI;QACV,IAAI,EAAE,IAAI;QACV,KAAK,EAAE,KAAc;KACtB;IAED,MAAM,EAAE;QACN,OAAO,EAAE,EAAE;QACX,MAAM,EAAE,GAAG;QACX,OAAO,EAAE,CAAC;KACX;CACO,CAAC;AAIX,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,IAAI,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IACtD,IAAI,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IACpD,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * truncate — Unicode-aware string truncation.
3
+ * Handles wide characters (CJK), ANSI escape sequences, and emoji.
4
+ */
5
+ /** Get visible width of a string (strips ANSI, counts CJK as 2) */
6
+ export declare function visibleWidth(str: string): number;
7
+ /** Truncate string to maxWidth visible chars, appending suffix if truncated */
8
+ export declare function truncate(str: string, maxWidth: number, suffix?: string): string;
9
+ /** Pad string to exact visible width */
10
+ export declare function padEnd(str: string, targetWidth: number, char?: string): string;
11
+ //# sourceMappingURL=truncate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../../src/tui/lib/truncate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,mEAAmE;AACnE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAwBhD;AAED,+EAA+E;AAC/E,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAM,GAAG,MAAM,CA8B5E;AAED,wCAAwC;AACxC,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,IAAI,SAAM,GAAG,MAAM,CAI3E"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * truncate — Unicode-aware string truncation.
3
+ * Handles wide characters (CJK), ANSI escape sequences, and emoji.
4
+ */
5
+ // Strip ANSI escape codes for width calculation
6
+ const ANSI_RE = /\x1b\[[0-9;]*m/g;
7
+ /** Get visible width of a string (strips ANSI, counts CJK as 2) */
8
+ export function visibleWidth(str) {
9
+ const stripped = str.replace(ANSI_RE, "");
10
+ let width = 0;
11
+ for (const char of stripped) {
12
+ const code = char.codePointAt(0) ?? 0;
13
+ // CJK Unified Ideographs, CJK Compatibility, Hangul, fullwidth
14
+ if ((code >= 0x1100 && code <= 0x115F) || // Hangul Jamo
15
+ (code >= 0x2E80 && code <= 0x303E) || // CJK Radicals
16
+ (code >= 0x3040 && code <= 0x33BF) || // Japanese
17
+ (code >= 0x3400 && code <= 0x4DBF) || // CJK Ext A
18
+ (code >= 0x4E00 && code <= 0x9FFF) || // CJK Unified
19
+ (code >= 0xAC00 && code <= 0xD7AF) || // Hangul Syllables
20
+ (code >= 0xF900 && code <= 0xFAFF) || // CJK Compat
21
+ (code >= 0xFE30 && code <= 0xFE6F) || // CJK Compat Forms
22
+ (code >= 0xFF01 && code <= 0xFF60) || // Fullwidth
23
+ (code >= 0x20000 && code <= 0x2FA1F) // CJK Ext B-F
24
+ ) {
25
+ width += 2;
26
+ }
27
+ else {
28
+ width += 1;
29
+ }
30
+ }
31
+ return width;
32
+ }
33
+ /** Truncate string to maxWidth visible chars, appending suffix if truncated */
34
+ export function truncate(str, maxWidth, suffix = "…") {
35
+ if (visibleWidth(str) <= maxWidth)
36
+ return str;
37
+ const suffixWidth = visibleWidth(suffix);
38
+ const target = maxWidth - suffixWidth;
39
+ if (target <= 0)
40
+ return suffix.slice(0, maxWidth);
41
+ const stripped = str.replace(ANSI_RE, "");
42
+ let width = 0;
43
+ let i = 0;
44
+ for (const char of stripped) {
45
+ const code = char.codePointAt(0) ?? 0;
46
+ const charWidth = (code >= 0x1100 && code <= 0x115F) ||
47
+ (code >= 0x2E80 && code <= 0x9FFF) ||
48
+ (code >= 0xAC00 && code <= 0xD7AF) ||
49
+ (code >= 0xF900 && code <= 0xFAFF) ||
50
+ (code >= 0xFE30 && code <= 0xFE6F) ||
51
+ (code >= 0xFF01 && code <= 0xFF60) ||
52
+ (code >= 0x20000 && code <= 0x2FA1F)
53
+ ? 2
54
+ : 1;
55
+ if (width + charWidth > target)
56
+ break;
57
+ width += charWidth;
58
+ i += char.length;
59
+ }
60
+ return stripped.slice(0, i) + suffix;
61
+ }
62
+ /** Pad string to exact visible width */
63
+ export function padEnd(str, targetWidth, char = " ") {
64
+ const current = visibleWidth(str);
65
+ if (current >= targetWidth)
66
+ return str;
67
+ return str + char.repeat(targetWidth - current);
68
+ }
69
+ //# sourceMappingURL=truncate.js.map