revspec 0.3.0 → 0.5.0

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.
@@ -0,0 +1,49 @@
1
+ export const theme = {
2
+ // Surfaces
3
+ base: "#1e1e2e",
4
+ backgroundPanel: "#313244",
5
+ backgroundElement: "#45475a",
6
+
7
+ // Text hierarchy
8
+ text: "#cdd6f4",
9
+ textMuted: "#a6adc8",
10
+ textDim: "#6c7086",
11
+
12
+ // Semantic accents
13
+ blue: "#89b4fa",
14
+ green: "#a6e3a1",
15
+ red: "#f38ba8",
16
+ yellow: "#f9e2af",
17
+ mauve: "#cba6f7",
18
+
19
+ // Borders
20
+ border: "#45475a",
21
+ borderAccent: "#89b4fa",
22
+
23
+ // Status
24
+ success: "#a6e3a1",
25
+ warning: "#f9e2af",
26
+ error: "#f38ba8",
27
+ info: "#89b4fa",
28
+ } as const;
29
+
30
+ export const STATUS_ICONS: Record<string, string> = {
31
+ open: "\u258c", // ▌ half block
32
+ pending: "\u25cb", // ○ circle
33
+ resolved: "\u2713", // ✓ checkmark
34
+ outdated: "\u223c", // ∼ tilde
35
+ };
36
+
37
+ export const SPLIT_BORDER = {
38
+ topLeft: " ",
39
+ topRight: " ",
40
+ bottomLeft: " ",
41
+ bottomRight: " ",
42
+ horizontal: " ",
43
+ vertical: "\u2503",
44
+ topT: " ",
45
+ bottomT: " ",
46
+ leftT: "\u2503",
47
+ rightT: " ",
48
+ cross: " ",
49
+ } as const;
@@ -0,0 +1,71 @@
1
+ import { describe, expect, it } from "bun:test";
2
+ import { createKeybindRegistry } from "../../../src/tui/ui/keybinds";
3
+
4
+ function makeKey(name: string, opts: { ctrl?: boolean; shift?: boolean; sequence?: string } = {}): any {
5
+ return { name, ctrl: opts.ctrl ?? false, shift: opts.shift ?? false, sequence: opts.sequence ?? name };
6
+ }
7
+
8
+ describe("createKeybindRegistry", () => {
9
+ it("matches single keys", () => {
10
+ const reg = createKeybindRegistry([
11
+ { key: "j", action: "down" },
12
+ { key: "k", action: "up" },
13
+ ]);
14
+ expect(reg.match(makeKey("j"))).toBe("down");
15
+ expect(reg.match(makeKey("k"))).toBe("up");
16
+ expect(reg.match(makeKey("x"))).toBeNull();
17
+ reg.destroy();
18
+ });
19
+
20
+ it("matches ctrl keys", () => {
21
+ const reg = createKeybindRegistry([
22
+ { key: "C-d", action: "half-page-down" },
23
+ ]);
24
+ expect(reg.match(makeKey("d", { ctrl: true }))).toBe("half-page-down");
25
+ expect(reg.match(makeKey("d"))).toBeNull();
26
+ reg.destroy();
27
+ });
28
+
29
+ it("matches shift keys", () => {
30
+ const reg = createKeybindRegistry([
31
+ { key: "G", action: "goto-bottom" },
32
+ { key: "R", action: "resolve-all" },
33
+ ]);
34
+ expect(reg.match(makeKey("g", { shift: true }))).toBe("goto-bottom");
35
+ expect(reg.match(makeKey("r", { shift: true }))).toBe("resolve-all");
36
+ reg.destroy();
37
+ });
38
+
39
+ it("matches two-key sequences", () => {
40
+ const reg = createKeybindRegistry([
41
+ { key: "gg", action: "goto-top" },
42
+ { key: "dd", action: "delete" },
43
+ ]);
44
+ expect(reg.match(makeKey("g"))).toBeNull();
45
+ expect(reg.pending()).toBe("g...");
46
+ expect(reg.match(makeKey("g"))).toBe("goto-top");
47
+ expect(reg.pending()).toBeNull();
48
+ reg.destroy();
49
+ });
50
+
51
+ it("clears sequence on invalid second key", () => {
52
+ const reg = createKeybindRegistry([
53
+ { key: "gg", action: "goto-top" },
54
+ { key: "j", action: "down" },
55
+ ]);
56
+ expect(reg.match(makeKey("g"))).toBeNull();
57
+ expect(reg.match(makeKey("x"))).toBeNull();
58
+ expect(reg.match(makeKey("j"))).toBe("down");
59
+ reg.destroy();
60
+ });
61
+
62
+ it("handles bracket sequences", () => {
63
+ const reg = createKeybindRegistry([
64
+ { key: "]t", action: "next-thread" },
65
+ { key: "[t", action: "prev-thread" },
66
+ ]);
67
+ expect(reg.match(makeKey("]", { sequence: "]" }))).toBeNull();
68
+ expect(reg.match(makeKey("t"))).toBe("next-thread");
69
+ reg.destroy();
70
+ });
71
+ });
package/src/tui/theme.ts DELETED
@@ -1,34 +0,0 @@
1
- export const theme = {
2
- // Base surfaces
3
- base: "#1e1e2e",
4
- surface0: "#313244",
5
- surface1: "#45475a",
6
-
7
- // Text hierarchy
8
- text: "#cdd6f4",
9
- subtext: "#a6adc8",
10
- overlay: "#6c7086",
11
-
12
- // Semantic accents
13
- blue: "#89b4fa",
14
- green: "#a6e3a1",
15
- red: "#f38ba8",
16
- yellow: "#f9e2af",
17
- mauve: "#cba6f7",
18
-
19
- // Derived roles
20
- borderComment: "#89b4fa",
21
- borderThread: "#f9e2af", // yellow for informational view
22
- borderList: "#cba6f7",
23
- borderConfirm: "#f38ba8",
24
- borderSearch: "#89b4fa",
25
- hintFg: "#6c7086",
26
- hintBg: "#313244",
27
- } as const;
28
-
29
- export const STATUS_ICONS: Record<string, string> = {
30
- open: "\u258c", // ▌ half block
31
- pending: "\u258c", // ▌ half block
32
- resolved: "\u2713", // ✓ checkmark
33
- outdated: "\u258c", // ▌ half block
34
- };