tuiboard 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.
Files changed (41) hide show
  1. package/.tuiboard/config.example.yaml +32 -0
  2. package/LICENSE +21 -0
  3. package/README.md +208 -0
  4. package/bin/tuiboard.ts +28 -0
  5. package/package.json +62 -0
  6. package/src/app.tsx +129 -0
  7. package/src/cli/args.test.ts +40 -0
  8. package/src/cli/args.ts +41 -0
  9. package/src/config/loader.ts +169 -0
  10. package/src/input/handleKey.ts +733 -0
  11. package/src/io/watcher.ts +85 -0
  12. package/src/io/writer.ts +92 -0
  13. package/src/parser/markdown.ts +351 -0
  14. package/src/parser/serialize.ts +97 -0
  15. package/src/scripts/agents-check.ts +24 -0
  16. package/src/scripts/parse-check.ts +124 -0
  17. package/src/scripts/roundtrip-check.ts +79 -0
  18. package/src/store/agents.test.ts +181 -0
  19. package/src/store/agents.ts +435 -0
  20. package/src/store/index.test.ts +110 -0
  21. package/src/store/index.ts +972 -0
  22. package/src/store/parsers.ts +243 -0
  23. package/src/store/timeline.test.ts +279 -0
  24. package/src/store/timeline.ts +279 -0
  25. package/src/store/virtual-panel.ts +0 -0
  26. package/src/types.ts +116 -0
  27. package/src/ui/AgentRow.tsx +79 -0
  28. package/src/ui/AgentsBar.tsx +102 -0
  29. package/src/ui/BoardView.tsx +333 -0
  30. package/src/ui/Chrome.tsx +122 -0
  31. package/src/ui/Modal.tsx +613 -0
  32. package/src/ui/TaskRow.tsx +240 -0
  33. package/src/ui/TimelineView.tsx +643 -0
  34. package/src/ui/VirtualPanel.tsx +237 -0
  35. package/src/ui/board-scroll.test.ts +63 -0
  36. package/src/ui/board-scroll.ts +49 -0
  37. package/src/ui/glyphs.ts +129 -0
  38. package/src/views/AgentsOnly.tsx +103 -0
  39. package/src/views/BoardOnly.tsx +35 -0
  40. package/src/views/Dashboard.tsx +106 -0
  41. package/src/views/TimelineOnly.tsx +12 -0
@@ -0,0 +1,106 @@
1
+ /**
2
+ * The default tuiboard view: a 4-zone dashboard.
3
+ *
4
+ * ┌─Virtual─┬─Board────────┬─Timeline─┐
5
+ * │ │ │ │
6
+ * │ │ │ │
7
+ * │ ├──────────────┤ │
8
+ * │ │ Agents │ │
9
+ * └─────────┴──────────────┴──────────┘
10
+ *
11
+ * Zone visibility is governed by store.state.ui.visibleZones (F1/F2/F3
12
+ * keys). The cursor lives in store.state.ui.activeZone and is cycled
13
+ * by Shift+Tab via store.cycleActiveZone().
14
+ *
15
+ * Zoom (`z`): when ui.zoomed is true, only the active zone is rendered,
16
+ * full-screen, by reusing the standalone --view=X wrapper for that zone.
17
+ * For the board zone, ui.zoomed also propagates down to BoardView and
18
+ * collapses the masonry to the active column (the legacy Python kanban
19
+ * behavior — "zoom inside the zoom").
20
+ */
21
+
22
+ import { Show, createMemo } from "solid-js";
23
+
24
+ import { AgentsBar } from "~/ui/AgentsBar";
25
+ import { BoardView } from "~/ui/BoardView";
26
+ import { TimelineView } from "~/ui/TimelineView";
27
+ import { VirtualPanel } from "~/ui/VirtualPanel";
28
+ import { AgentsOnly } from "~/views/AgentsOnly";
29
+ import { BoardOnly } from "~/views/BoardOnly";
30
+ import { TimelineOnly } from "~/views/TimelineOnly";
31
+ import type { TuiStore } from "~/store/index";
32
+
33
+ /** Width (in cells) for the right-column Timeline panel on a wide terminal. */
34
+ const TIMELINE_WIDTH = 50;
35
+ /** Row height for the bottom Agents strip — enough for ~5 sessions. */
36
+ const AGENTS_HEIGHT = 7;
37
+
38
+ export function Dashboard(props: { store: TuiStore }) {
39
+ const ui = () => props.store.state.ui;
40
+
41
+ return (
42
+ <Show
43
+ when={ui().zoomed}
44
+ fallback={<FourZoneLayout store={props.store} />}
45
+ >
46
+ <ZoomedLayout store={props.store} />
47
+ </Show>
48
+ );
49
+ }
50
+
51
+ /**
52
+ * Zoomed mode: full-screen the active zone. We reuse the existing
53
+ * standalone view wrappers so a `z` press in the dashboard produces
54
+ * the same visual as launching `tuiboard --view=<zone>`.
55
+ *
56
+ * Board + virtual share BoardOnly because both live in the top-left
57
+ * zone of the normal layout and BoardOnly already respects ui.zoomed
58
+ * to render only the active panel between them.
59
+ */
60
+ function ZoomedLayout(props: { store: TuiStore }) {
61
+ const zone = () => props.store.state.ui.activeZone;
62
+
63
+ return (
64
+ <Show when={zone() === "timeline"} fallback={
65
+ <Show when={zone() === "agents"} fallback={<BoardOnly store={props.store} />}>
66
+ <AgentsOnly store={props.store} />
67
+ </Show>
68
+ }>
69
+ <TimelineOnly store={props.store} />
70
+ </Show>
71
+ );
72
+ }
73
+
74
+ function FourZoneLayout(props: { store: TuiStore }) {
75
+ const ui = () => props.store.state.ui;
76
+ const visible = () => ui().visibleZones;
77
+ const activeBoard = createMemo(
78
+ () => props.store.state.boards[ui().activeBoardIndex]?.board,
79
+ );
80
+
81
+ return (
82
+ <box style={{ flexDirection: "row", flexGrow: 1 }}>
83
+ {/* Left column: virtual + board on top, agents on bottom */}
84
+ <box style={{ flexDirection: "column", flexGrow: 1 }}>
85
+ {/* Top zone */}
86
+ <box style={{ flexDirection: "row", flexGrow: 1 }}>
87
+ <Show when={visible().virtual}>
88
+ <VirtualPanel store={props.store} />
89
+ </Show>
90
+ <Show when={visible().board && activeBoard()}>
91
+ <BoardView store={props.store} board={activeBoard()!} />
92
+ </Show>
93
+ </box>
94
+ {/* Bottom zone */}
95
+ <Show when={visible().agents}>
96
+ <AgentsBar store={props.store} height={AGENTS_HEIGHT} />
97
+ </Show>
98
+ </box>
99
+ {/* Right column: timeline (full height) */}
100
+ <Show when={visible().timeline}>
101
+ <TimelineView store={props.store} width={TIMELINE_WIDTH} />
102
+ </Show>
103
+ {/* ModalLayer rendered at App level so it can sit beside any view */}
104
+ </box>
105
+ );
106
+ }
@@ -0,0 +1,12 @@
1
+ /** Standalone fullscreen view for the timeline. `tuiboard --view=timeline`. */
2
+
3
+ import { TimelineView } from "~/ui/TimelineView";
4
+ import type { TuiStore } from "~/store/index";
5
+
6
+ export function TimelineOnly(props: { store: TuiStore }) {
7
+ return (
8
+ <box style={{ flexDirection: "row", flexGrow: 1 }}>
9
+ <TimelineView store={props.store} />
10
+ </box>
11
+ );
12
+ }