@dungle-scrubs/tallow 0.9.4 → 0.9.6

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 (195) hide show
  1. package/dist/cli.js +7 -4
  2. package/dist/cli.js.map +1 -1
  3. package/dist/config.d.ts +1 -1
  4. package/dist/config.js +1 -1
  5. package/dist/interactive-mode-patch.d.ts +24 -12
  6. package/dist/interactive-mode-patch.d.ts.map +1 -1
  7. package/dist/interactive-mode-patch.js +229 -146
  8. package/dist/interactive-mode-patch.js.map +1 -1
  9. package/dist/interactive-reset.d.ts +49 -0
  10. package/dist/interactive-reset.d.ts.map +1 -0
  11. package/dist/interactive-reset.js +40 -0
  12. package/dist/interactive-reset.js.map +1 -0
  13. package/dist/pi-tui-editor-patch.d.ts +10 -0
  14. package/dist/pi-tui-editor-patch.d.ts.map +1 -0
  15. package/dist/pi-tui-editor-patch.js +159 -0
  16. package/dist/pi-tui-editor-patch.js.map +1 -0
  17. package/dist/pi-tui-patch.d.ts +2 -0
  18. package/dist/pi-tui-patch.d.ts.map +1 -0
  19. package/dist/pi-tui-patch.js +563 -0
  20. package/dist/pi-tui-patch.js.map +1 -0
  21. package/dist/pi-tui-settings-list-patch.d.ts +11 -0
  22. package/dist/pi-tui-settings-list-patch.d.ts.map +1 -0
  23. package/dist/pi-tui-settings-list-patch.js +38 -0
  24. package/dist/pi-tui-settings-list-patch.js.map +1 -0
  25. package/dist/reset-diagnostics.d.ts +69 -0
  26. package/dist/reset-diagnostics.d.ts.map +1 -0
  27. package/dist/reset-diagnostics.js +41 -0
  28. package/dist/reset-diagnostics.js.map +1 -0
  29. package/dist/sdk.d.ts +5 -21
  30. package/dist/sdk.d.ts.map +1 -1
  31. package/dist/sdk.js +180 -149
  32. package/dist/sdk.js.map +1 -1
  33. package/dist/workspace-transition-interactive.d.ts +1 -0
  34. package/dist/workspace-transition-interactive.d.ts.map +1 -1
  35. package/dist/workspace-transition-interactive.js +7 -17
  36. package/dist/workspace-transition-interactive.js.map +1 -1
  37. package/extensions/__integration__/audit-findings.test.ts +4 -5
  38. package/extensions/_icons/index.ts +2 -4
  39. package/extensions/_shared/__tests__/image-metadata.test.ts +33 -0
  40. package/extensions/_shared/__tests__/terminal-links.test.ts +18 -0
  41. package/extensions/_shared/image-metadata.ts +99 -0
  42. package/extensions/_shared/inline-preview.ts +1 -1
  43. package/extensions/_shared/terminal-links.ts +22 -0
  44. package/extensions/ask-user-question-tool/index.ts +0 -3
  45. package/extensions/clear/__tests__/clear.test.ts +269 -2
  46. package/extensions/command-expansion/index.ts +1 -1
  47. package/extensions/context-files/index.ts +5 -1
  48. package/extensions/context-fork/__tests__/context-fork.test.ts +94 -1
  49. package/extensions/context-fork/extension.json +1 -1
  50. package/extensions/context-fork/index.ts +32 -0
  51. package/extensions/edit-tool-enhanced/index.ts +2 -1
  52. package/extensions/hooks/index.ts +33 -11
  53. package/extensions/loop/index.ts +14 -1
  54. package/extensions/lsp/index.ts +64 -13
  55. package/extensions/lsp/package.json +2 -2
  56. package/extensions/random-spinner/index.ts +7 -642
  57. package/extensions/read-tool-enhanced/index.ts +6 -8
  58. package/extensions/render-stabilizer/__tests__/render-stabilizer.test.ts +2 -3
  59. package/extensions/render-stabilizer/index.ts +6 -6
  60. package/extensions/slash-command-bridge/__tests__/slash-command-bridge.test.ts +26 -0
  61. package/extensions/slash-command-bridge/index.ts +14 -2
  62. package/extensions/subagent-tool/model-resolver.ts +274 -7
  63. package/extensions/tasks/commands/register-tasks-extension.ts +9 -9
  64. package/extensions/teams-tool/tools/register-extension.ts +1 -3
  65. package/extensions/web-search-tool/index.ts +2 -1
  66. package/extensions/write-tool-enhanced/index.ts +2 -1
  67. package/node_modules/@mariozechner/pi-tui/README.md +56 -34
  68. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts +18 -13
  69. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.d.ts.map +1 -1
  70. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js +182 -113
  71. package/node_modules/@mariozechner/pi-tui/dist/autocomplete.js.map +1 -1
  72. package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js +3 -3
  73. package/node_modules/@mariozechner/pi-tui/dist/components/cancellable-loader.js.map +1 -1
  74. package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts +45 -36
  75. package/node_modules/@mariozechner/pi-tui/dist/components/editor.d.ts.map +1 -1
  76. package/node_modules/@mariozechner/pi-tui/dist/components/editor.js +489 -325
  77. package/node_modules/@mariozechner/pi-tui/dist/components/editor.js.map +1 -1
  78. package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts +1 -99
  79. package/node_modules/@mariozechner/pi-tui/dist/components/image.d.ts.map +1 -1
  80. package/node_modules/@mariozechner/pi-tui/dist/components/image.js +17 -192
  81. package/node_modules/@mariozechner/pi-tui/dist/components/image.js.map +1 -1
  82. package/node_modules/@mariozechner/pi-tui/dist/components/input.d.ts.map +1 -1
  83. package/node_modules/@mariozechner/pi-tui/dist/components/input.js +57 -60
  84. package/node_modules/@mariozechner/pi-tui/dist/components/input.js.map +1 -1
  85. package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts +2 -69
  86. package/node_modules/@mariozechner/pi-tui/dist/components/loader.d.ts.map +1 -1
  87. package/node_modules/@mariozechner/pi-tui/dist/components/loader.js +5 -102
  88. package/node_modules/@mariozechner/pi-tui/dist/components/loader.js.map +1 -1
  89. package/node_modules/@mariozechner/pi-tui/dist/components/markdown.d.ts.map +1 -1
  90. package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js +111 -53
  91. package/node_modules/@mariozechner/pi-tui/dist/components/markdown.js.map +1 -1
  92. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts +19 -1
  93. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.d.ts.map +1 -1
  94. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js +78 -67
  95. package/node_modules/@mariozechner/pi-tui/dist/components/select-list.js.map +1 -1
  96. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts +1 -25
  97. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.d.ts.map +1 -1
  98. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js +13 -50
  99. package/node_modules/@mariozechner/pi-tui/dist/components/settings-list.js.map +1 -1
  100. package/node_modules/@mariozechner/pi-tui/dist/index.d.ts +8 -10
  101. package/node_modules/@mariozechner/pi-tui/dist/index.d.ts.map +1 -1
  102. package/node_modules/@mariozechner/pi-tui/dist/index.js +6 -9
  103. package/node_modules/@mariozechner/pi-tui/dist/index.js.map +1 -1
  104. package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts +108 -238
  105. package/node_modules/@mariozechner/pi-tui/dist/keybindings.d.ts.map +1 -1
  106. package/node_modules/@mariozechner/pi-tui/dist/keybindings.js +108 -365
  107. package/node_modules/@mariozechner/pi-tui/dist/keybindings.js.map +1 -1
  108. package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts +33 -48
  109. package/node_modules/@mariozechner/pi-tui/dist/keys.d.ts.map +1 -1
  110. package/node_modules/@mariozechner/pi-tui/dist/keys.js +239 -155
  111. package/node_modules/@mariozechner/pi-tui/dist/keys.js.map +1 -1
  112. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts +14 -94
  113. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.d.ts.map +1 -1
  114. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js +44 -186
  115. package/node_modules/@mariozechner/pi-tui/dist/terminal-image.js.map +1 -1
  116. package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts +13 -58
  117. package/node_modules/@mariozechner/pi-tui/dist/terminal.d.ts.map +1 -1
  118. package/node_modules/@mariozechner/pi-tui/dist/terminal.js +78 -111
  119. package/node_modules/@mariozechner/pi-tui/dist/terminal.js.map +1 -1
  120. package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts +24 -110
  121. package/node_modules/@mariozechner/pi-tui/dist/tui.d.ts.map +1 -1
  122. package/node_modules/@mariozechner/pi-tui/dist/tui.js +188 -435
  123. package/node_modules/@mariozechner/pi-tui/dist/tui.js.map +1 -1
  124. package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts +0 -18
  125. package/node_modules/@mariozechner/pi-tui/dist/utils.d.ts.map +1 -1
  126. package/node_modules/@mariozechner/pi-tui/dist/utils.js +251 -119
  127. package/node_modules/@mariozechner/pi-tui/dist/utils.js.map +1 -1
  128. package/node_modules/@mariozechner/pi-tui/package.json +6 -6
  129. package/node_modules/@mariozechner/pi-tui/src/__tests__/__snapshots__/render.test.ts.snap +3 -40
  130. package/node_modules/@mariozechner/pi-tui/src/__tests__/image-component.test.ts +71 -81
  131. package/node_modules/@mariozechner/pi-tui/src/__tests__/render.test.ts +0 -33
  132. package/node_modules/@mariozechner/pi-tui/src/__tests__/terminal-image.test.ts +93 -334
  133. package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-render-scheduling.test.ts +1 -1
  134. package/node_modules/@mariozechner/pi-tui/src/__tests__/utils.test.ts +11 -196
  135. package/node_modules/@mariozechner/pi-tui/src/autocomplete.ts +228 -142
  136. package/node_modules/@mariozechner/pi-tui/src/components/cancellable-loader.ts +3 -3
  137. package/node_modules/@mariozechner/pi-tui/src/components/editor.ts +624 -390
  138. package/node_modules/@mariozechner/pi-tui/src/components/image.ts +17 -227
  139. package/node_modules/@mariozechner/pi-tui/src/components/input.ts +71 -63
  140. package/node_modules/@mariozechner/pi-tui/src/components/loader.ts +5 -137
  141. package/node_modules/@mariozechner/pi-tui/src/components/markdown.ts +143 -52
  142. package/node_modules/@mariozechner/pi-tui/src/components/select-list.ts +136 -70
  143. package/node_modules/@mariozechner/pi-tui/src/components/settings-list.ts +12 -51
  144. package/node_modules/@mariozechner/pi-tui/src/index.ts +17 -36
  145. package/node_modules/@mariozechner/pi-tui/src/keybindings.ts +148 -421
  146. package/node_modules/@mariozechner/pi-tui/src/keys.ts +253 -181
  147. package/node_modules/@mariozechner/pi-tui/src/terminal-image.ts +51 -252
  148. package/node_modules/@mariozechner/pi-tui/src/terminal.ts +78 -133
  149. package/node_modules/@mariozechner/pi-tui/src/tui.ts +202 -478
  150. package/node_modules/@mariozechner/pi-tui/src/utils.ts +289 -125
  151. package/node_modules/@mariozechner/pi-tui/tsconfig.build.json +1 -0
  152. package/package.json +13 -13
  153. package/packages/tallow-tui/node_modules/@types/mime-types/README.md +8 -2
  154. package/packages/tallow-tui/node_modules/@types/mime-types/index.d.ts +6 -0
  155. package/packages/tallow-tui/node_modules/@types/mime-types/package.json +9 -3
  156. package/packages/tallow-tui/node_modules/get-east-asian-width/lookup-data.js +18 -0
  157. package/packages/tallow-tui/node_modules/get-east-asian-width/lookup.js +116 -384
  158. package/packages/tallow-tui/node_modules/get-east-asian-width/package.json +5 -4
  159. package/packages/tallow-tui/node_modules/get-east-asian-width/utilities.js +24 -0
  160. package/packages/tallow-tui/node_modules/marked/README.md +5 -4
  161. package/packages/tallow-tui/node_modules/marked/bin/main.js +10 -8
  162. package/packages/tallow-tui/node_modules/marked/bin/marked.js +2 -1
  163. package/packages/tallow-tui/node_modules/marked/lib/marked.d.ts +156 -125
  164. package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js +67 -2179
  165. package/packages/tallow-tui/node_modules/marked/lib/marked.esm.js.map +3 -3
  166. package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js +67 -2201
  167. package/packages/tallow-tui/node_modules/marked/lib/marked.umd.js.map +3 -3
  168. package/packages/tallow-tui/node_modules/marked/man/marked.1 +4 -2
  169. package/packages/tallow-tui/node_modules/marked/man/marked.1.md +2 -1
  170. package/packages/tallow-tui/node_modules/marked/package.json +26 -34
  171. package/skills/tallow-expert/SKILL.md +1 -3
  172. package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts +0 -32
  173. package/node_modules/@mariozechner/pi-tui/dist/border-styles.d.ts.map +0 -1
  174. package/node_modules/@mariozechner/pi-tui/dist/border-styles.js +0 -46
  175. package/node_modules/@mariozechner/pi-tui/dist/border-styles.js.map +0 -1
  176. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts +0 -52
  177. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.d.ts.map +0 -1
  178. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js +0 -89
  179. package/node_modules/@mariozechner/pi-tui/dist/components/bordered-box.js.map +0 -1
  180. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts +0 -14
  181. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.d.ts.map +0 -1
  182. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js +0 -55
  183. package/node_modules/@mariozechner/pi-tui/dist/test-utils/capability-env.js.map +0 -1
  184. package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-change-listener.test.ts +0 -121
  185. package/node_modules/@mariozechner/pi-tui/src/__tests__/editor-ghost-text.test.ts +0 -112
  186. package/node_modules/@mariozechner/pi-tui/src/__tests__/mouse-events.test.ts +0 -134
  187. package/node_modules/@mariozechner/pi-tui/src/__tests__/settings-list.test.ts +0 -81
  188. package/node_modules/@mariozechner/pi-tui/src/__tests__/tui-diff-regression.test.ts +0 -555
  189. package/node_modules/@mariozechner/pi-tui/src/border-styles.ts +0 -60
  190. package/node_modules/@mariozechner/pi-tui/src/components/bordered-box.ts +0 -113
  191. package/node_modules/@mariozechner/pi-tui/src/test-utils/capability-env.ts +0 -56
  192. package/packages/tallow-tui/node_modules/marked/lib/marked.cjs +0 -2211
  193. package/packages/tallow-tui/node_modules/marked/lib/marked.cjs.map +0 -7
  194. package/packages/tallow-tui/node_modules/marked/lib/marked.d.cts +0 -728
  195. package/packages/tallow-tui/node_modules/marked/marked.min.js +0 -69
@@ -1,112 +0,0 @@
1
- /**
2
- * Tests for Editor ghost text (inline suggestion) functionality.
3
- *
4
- * Uses a minimal TUI mock since Editor requires a TUI instance.
5
- */
6
- import { describe, expect, test } from "bun:test";
7
- import { Editor, type EditorTheme } from "../components/editor.js";
8
- import type { TUI } from "../tui.js";
9
-
10
- /** Minimal TUI mock providing only what Editor needs. */
11
- function createMockTUI(): TUI {
12
- return {
13
- requestRender: () => {},
14
- terminal: { rows: 40, cols: 80 },
15
- } as unknown as TUI;
16
- }
17
-
18
- const theme: EditorTheme = {
19
- borderColor: (s: string) => s,
20
- selectList: {
21
- selectedBg: (s: string) => s,
22
- selectedFg: (s: string) => s,
23
- normalBg: (s: string) => s,
24
- normalFg: (s: string) => s,
25
- matchHighlight: (s: string) => s,
26
- descriptionFg: (s: string) => s,
27
- },
28
- };
29
-
30
- describe("Editor ghost text", () => {
31
- test("setGhostText stores and getGhostText retrieves", () => {
32
- const editor = new Editor(createMockTUI(), theme);
33
- expect(editor.getGhostText()).toBeNull();
34
- editor.setGhostText("hello world");
35
- expect(editor.getGhostText()).toBe("hello world");
36
- });
37
-
38
- test("setGhostText(null) clears ghost text", () => {
39
- const editor = new Editor(createMockTUI(), theme);
40
- editor.setGhostText("suggestion");
41
- editor.setGhostText(null);
42
- expect(editor.getGhostText()).toBeNull();
43
- });
44
-
45
- test("ghost text renders as dim ANSI after cursor", () => {
46
- const editor = new Editor(createMockTUI(), theme);
47
- editor.setGhostText("complete me");
48
- const lines = editor.render(80);
49
- // Ghost text should appear as muted gray (256-color 242) in the output
50
- const joined = lines.join("\n");
51
- expect(joined).toContain("\x1b[38;5;242m");
52
- expect(joined).toContain("complete me");
53
- });
54
-
55
- test("ghost text cleared when character is typed", () => {
56
- const editor = new Editor(createMockTUI(), theme);
57
- editor.setGhostText("suggestion");
58
- editor.handleInput("a");
59
- expect(editor.getGhostText()).toBeNull();
60
- });
61
-
62
- test("ghost text cleared on backspace", () => {
63
- const editor = new Editor(createMockTUI(), theme);
64
- editor.setText("hello");
65
- editor.setGhostText("world");
66
- // Backspace (DEL character)
67
- editor.handleInput("\x7f");
68
- expect(editor.getGhostText()).toBeNull();
69
- });
70
-
71
- test("Tab accepts ghost text into buffer", () => {
72
- const editor = new Editor(createMockTUI(), theme);
73
- editor.setGhostText("complete me");
74
- // Tab
75
- editor.handleInput("\t");
76
- expect(editor.getGhostText()).toBeNull();
77
- expect(editor.getText()).toBe("complete me");
78
- });
79
-
80
- test("Enter on empty input accepts ghost text and submits", () => {
81
- const editor = new Editor(createMockTUI(), theme);
82
- let submitted = "";
83
- editor.onSubmit = (text: string) => {
84
- submitted = text;
85
- };
86
- editor.setGhostText("suggested prompt");
87
- // Enter (carriage return)
88
- editor.handleInput("\r");
89
- expect(submitted).toBe("suggested prompt");
90
- expect(editor.getGhostText()).toBeNull();
91
- });
92
-
93
- test("Enter on non-empty input submits typed text, not ghost text", () => {
94
- const editor = new Editor(createMockTUI(), theme);
95
- let submitted = "";
96
- editor.onSubmit = (text: string) => {
97
- submitted = text;
98
- };
99
- editor.setText("my input");
100
- editor.setGhostText("ghost suggestion");
101
- editor.handleInput("\r");
102
- expect(submitted).toBe("my input");
103
- });
104
-
105
- test("Escape dismisses ghost text", () => {
106
- const editor = new Editor(createMockTUI(), theme);
107
- editor.setGhostText("suggestion");
108
- // Escape
109
- editor.handleInput("\x1b");
110
- expect(editor.getGhostText()).toBeNull();
111
- });
112
- });
@@ -1,134 +0,0 @@
1
- /**
2
- * Tests for SGR mouse event parsing: parseMouseEvent and isMouseEvent.
3
- */
4
- import { describe, expect, it } from "bun:test";
5
- import { isMouseEvent, parseMouseEvent } from "../keys.js";
6
-
7
- // ── parseMouseEvent ──────────────────────────────────────────────────────────
8
-
9
- describe("parseMouseEvent", () => {
10
- it("parses scroll-up event", () => {
11
- // SGR: \x1b[<64;10;5M — code 64 = scroll up, col 10, row 5, press
12
- expect(parseMouseEvent("\x1b[<64;10;5M")).toEqual({
13
- type: "scroll-up",
14
- button: 0,
15
- x: 10,
16
- y: 5,
17
- });
18
- });
19
-
20
- it("parses scroll-down event", () => {
21
- // SGR: \x1b[<65;20;15M — code 65 = scroll down, col 20, row 15, press
22
- expect(parseMouseEvent("\x1b[<65;20;15M")).toEqual({
23
- type: "scroll-down",
24
- button: 0,
25
- x: 20,
26
- y: 15,
27
- });
28
- });
29
-
30
- it("parses left button press", () => {
31
- // SGR: \x1b[<0;5;3M — code 0 = left button, col 5, row 3, M = press
32
- expect(parseMouseEvent("\x1b[<0;5;3M")).toEqual({
33
- type: "press",
34
- button: 0,
35
- x: 5,
36
- y: 3,
37
- });
38
- });
39
-
40
- it("parses left button release", () => {
41
- // SGR: \x1b[<0;5;3m — code 0, lowercase m = release
42
- expect(parseMouseEvent("\x1b[<0;5;3m")).toEqual({
43
- type: "release",
44
- button: 0,
45
- x: 5,
46
- y: 3,
47
- });
48
- });
49
-
50
- it("parses middle button press", () => {
51
- // SGR: \x1b[<1;12;8M — code 1 = middle button
52
- expect(parseMouseEvent("\x1b[<1;12;8M")).toEqual({
53
- type: "press",
54
- button: 1,
55
- x: 12,
56
- y: 8,
57
- });
58
- });
59
-
60
- it("parses right button press", () => {
61
- // SGR: \x1b[<2;30;20M — code 2 = right button
62
- expect(parseMouseEvent("\x1b[<2;30;20M")).toEqual({
63
- type: "press",
64
- button: 2,
65
- x: 30,
66
- y: 20,
67
- });
68
- });
69
-
70
- it("parses drag event (bit 5 set)", () => {
71
- // SGR: \x1b[<32;15;10M — code 32 = motion + left button
72
- expect(parseMouseEvent("\x1b[<32;15;10M")).toEqual({
73
- type: "drag",
74
- button: 0,
75
- x: 15,
76
- y: 10,
77
- });
78
- });
79
-
80
- it("parses drag with right button", () => {
81
- // SGR: \x1b[<34;15;10M — code 34 = 32 (motion) + 2 (right)
82
- expect(parseMouseEvent("\x1b[<34;15;10M")).toEqual({
83
- type: "drag",
84
- button: 2,
85
- x: 15,
86
- y: 10,
87
- });
88
- });
89
-
90
- it("handles large coordinates (beyond 223-column limit)", () => {
91
- // SGR format supports arbitrary coordinates — this is why we use mode 1006
92
- expect(parseMouseEvent("\x1b[<0;300;150M")).toEqual({
93
- type: "press",
94
- button: 0,
95
- x: 300,
96
- y: 150,
97
- });
98
- });
99
-
100
- it("returns null for non-mouse input", () => {
101
- expect(parseMouseEvent("a")).toBeNull();
102
- expect(parseMouseEvent("\x1b[A")).toBeNull(); // arrow up
103
- expect(parseMouseEvent("\x1b[1;2H")).toBeNull(); // cursor position
104
- expect(parseMouseEvent("")).toBeNull();
105
- });
106
-
107
- it("returns null for malformed SGR sequences", () => {
108
- expect(parseMouseEvent("\x1b[<0;5M")).toBeNull(); // missing y
109
- expect(parseMouseEvent("\x1b[<0;5;3")).toBeNull(); // missing M/m terminator
110
- expect(parseMouseEvent("\x1b[<;5;3M")).toBeNull(); // missing code
111
- });
112
- });
113
-
114
- // ── isMouseEvent ─────────────────────────────────────────────────────────────
115
-
116
- describe("isMouseEvent", () => {
117
- it("returns true for SGR mouse sequences", () => {
118
- expect(isMouseEvent("\x1b[<0;5;3M")).toBe(true);
119
- expect(isMouseEvent("\x1b[<64;10;5M")).toBe(true);
120
- expect(isMouseEvent("\x1b[<0;300;150m")).toBe(true);
121
- });
122
-
123
- it("returns false for non-mouse input", () => {
124
- expect(isMouseEvent("a")).toBe(false);
125
- expect(isMouseEvent("\x1b[A")).toBe(false);
126
- expect(isMouseEvent("\x1b[1")).toBe(false);
127
- expect(isMouseEvent("")).toBe(false);
128
- });
129
-
130
- it("returns false for strings shorter than minimum mouse sequence", () => {
131
- // Minimum: \x1b[<N;N;NM = 9 chars
132
- expect(isMouseEvent("\x1b[<0;5;")).toBe(false);
133
- });
134
- });
@@ -1,81 +0,0 @@
1
- import { describe, expect, it } from "bun:test";
2
- import { SettingsList, type SettingsListTheme } from "../components/settings-list.js";
3
-
4
- const theme: SettingsListTheme = {
5
- cursor: "> ",
6
- description: (text) => text,
7
- hint: (text) => text,
8
- label: (text) => text,
9
- value: (text) => text,
10
- };
11
-
12
- describe("SettingsList submenu transitions", () => {
13
- it("preserves submenu height for one frame when closing back to the main list", () => {
14
- let changedValue: string | undefined;
15
- const list = new SettingsList(
16
- [
17
- {
18
- id: "thinking",
19
- label: "Thinking level",
20
- currentValue: "medium",
21
- description: "Reasoning depth",
22
- submenu: (_currentValue, done) => ({
23
- handleInput: () => done("high"),
24
- invalidate: () => {},
25
- render: () => ["submenu", "", "one", "two", "three", "four", "five", "six"],
26
- }),
27
- },
28
- ],
29
- 10,
30
- theme,
31
- (_id, newValue) => {
32
- changedValue = newValue;
33
- },
34
- () => {}
35
- );
36
-
37
- const initialLines = list.render(80);
38
- list.handleInput(" ");
39
- const submenuLines = list.render(80);
40
- list.handleInput("x");
41
- const firstFrameAfterClose = list.render(80);
42
- const secondFrameAfterClose = list.render(80);
43
-
44
- expect(changedValue).toBe("high");
45
- expect(submenuLines.length).toBeGreaterThan(initialLines.length);
46
- expect(firstFrameAfterClose.length).toBe(submenuLines.length);
47
- expect(secondFrameAfterClose.length).toBe(initialLines.length);
48
- });
49
-
50
- it("fires the layout transition callback when opening and closing a submenu", () => {
51
- const list = new SettingsList(
52
- [
53
- {
54
- id: "thinking",
55
- label: "Thinking level",
56
- currentValue: "medium",
57
- submenu: (_currentValue, done) => ({
58
- handleInput: () => done("high"),
59
- invalidate: () => {},
60
- render: () => ["submenu", "one", "two"],
61
- }),
62
- },
63
- ],
64
- 10,
65
- theme,
66
- () => {},
67
- () => {}
68
- );
69
- const transitions: string[] = [];
70
- list.setLayoutTransitionCallback(() => {
71
- transitions.push("transition");
72
- });
73
-
74
- list.render(80);
75
- list.handleInput(" ");
76
- list.render(80);
77
- list.handleInput("x");
78
-
79
- expect(transitions).toEqual(["transition", "transition"]);
80
- });
81
- });