@doriandev/devcc 0.1.2

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 (284) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +659 -0
  3. package/bin/devcc.mjs +66 -0
  4. package/dist/devcc/app/App.d.ts +178 -0
  5. package/dist/devcc/app/App.d.ts.map +1 -0
  6. package/dist/devcc/app/App.js +1255 -0
  7. package/dist/devcc/app/App.js.map +1 -0
  8. package/dist/devcc/app/builtinCommands.d.ts +17 -0
  9. package/dist/devcc/app/builtinCommands.d.ts.map +1 -0
  10. package/dist/devcc/app/builtinCommands.js +389 -0
  11. package/dist/devcc/app/builtinCommands.js.map +1 -0
  12. package/dist/devcc/app/keymap.d.ts +21 -0
  13. package/dist/devcc/app/keymap.d.ts.map +1 -0
  14. package/dist/devcc/app/keymap.js +162 -0
  15. package/dist/devcc/app/keymap.js.map +1 -0
  16. package/dist/devcc/app/theme.d.ts +49 -0
  17. package/dist/devcc/app/theme.d.ts.map +1 -0
  18. package/dist/devcc/app/theme.js +68 -0
  19. package/dist/devcc/app/theme.js.map +1 -0
  20. package/dist/devcc/cli.d.ts +3 -0
  21. package/dist/devcc/cli.d.ts.map +1 -0
  22. package/dist/devcc/cli.js +113 -0
  23. package/dist/devcc/cli.js.map +1 -0
  24. package/dist/devcc/components/CommandPalette.d.ts +26 -0
  25. package/dist/devcc/components/CommandPalette.d.ts.map +1 -0
  26. package/dist/devcc/components/CommandPalette.js +113 -0
  27. package/dist/devcc/components/CommandPalette.js.map +1 -0
  28. package/dist/devcc/components/ConfirmDialog.d.ts +31 -0
  29. package/dist/devcc/components/ConfirmDialog.d.ts.map +1 -0
  30. package/dist/devcc/components/ConfirmDialog.js +147 -0
  31. package/dist/devcc/components/ConfirmDialog.js.map +1 -0
  32. package/dist/devcc/components/Footer.d.ts +22 -0
  33. package/dist/devcc/components/Footer.d.ts.map +1 -0
  34. package/dist/devcc/components/Footer.js +72 -0
  35. package/dist/devcc/components/Footer.js.map +1 -0
  36. package/dist/devcc/components/Header.d.ts +12 -0
  37. package/dist/devcc/components/Header.d.ts.map +1 -0
  38. package/dist/devcc/components/Header.js +84 -0
  39. package/dist/devcc/components/Header.js.map +1 -0
  40. package/dist/devcc/components/HelpOverlay.d.ts +18 -0
  41. package/dist/devcc/components/HelpOverlay.d.ts.map +1 -0
  42. package/dist/devcc/components/HelpOverlay.js +48 -0
  43. package/dist/devcc/components/HelpOverlay.js.map +1 -0
  44. package/dist/devcc/components/Overlay.d.ts +31 -0
  45. package/dist/devcc/components/Overlay.d.ts.map +1 -0
  46. package/dist/devcc/components/Overlay.js +60 -0
  47. package/dist/devcc/components/Overlay.js.map +1 -0
  48. package/dist/devcc/components/ProjectPicker.d.ts +26 -0
  49. package/dist/devcc/components/ProjectPicker.d.ts.map +1 -0
  50. package/dist/devcc/components/ProjectPicker.js +114 -0
  51. package/dist/devcc/components/ProjectPicker.js.map +1 -0
  52. package/dist/devcc/components/Sidebar.d.ts +42 -0
  53. package/dist/devcc/components/Sidebar.d.ts.map +1 -0
  54. package/dist/devcc/components/Sidebar.js +127 -0
  55. package/dist/devcc/components/Sidebar.js.map +1 -0
  56. package/dist/devcc/components/StatusBadge.d.ts +16 -0
  57. package/dist/devcc/components/StatusBadge.d.ts.map +1 -0
  58. package/dist/devcc/components/StatusBadge.js +30 -0
  59. package/dist/devcc/components/StatusBadge.js.map +1 -0
  60. package/dist/devcc/components/primitives.d.ts +62 -0
  61. package/dist/devcc/components/primitives.d.ts.map +1 -0
  62. package/dist/devcc/components/primitives.js +169 -0
  63. package/dist/devcc/components/primitives.js.map +1 -0
  64. package/dist/devcc/components/styled.d.ts +16 -0
  65. package/dist/devcc/components/styled.d.ts.map +1 -0
  66. package/dist/devcc/components/styled.js +35 -0
  67. package/dist/devcc/components/styled.js.map +1 -0
  68. package/dist/devcc/core/commands.d.ts +89 -0
  69. package/dist/devcc/core/commands.d.ts.map +1 -0
  70. package/dist/devcc/core/commands.js +68 -0
  71. package/dist/devcc/core/commands.js.map +1 -0
  72. package/dist/devcc/core/config.d.ts +81 -0
  73. package/dist/devcc/core/config.d.ts.map +1 -0
  74. package/dist/devcc/core/config.js +313 -0
  75. package/dist/devcc/core/config.js.map +1 -0
  76. package/dist/devcc/core/events.d.ts +21 -0
  77. package/dist/devcc/core/events.d.ts.map +1 -0
  78. package/dist/devcc/core/events.js +27 -0
  79. package/dist/devcc/core/events.js.map +1 -0
  80. package/dist/devcc/core/state.d.ts +104 -0
  81. package/dist/devcc/core/state.d.ts.map +1 -0
  82. package/dist/devcc/core/state.js +139 -0
  83. package/dist/devcc/core/state.js.map +1 -0
  84. package/dist/devcc/deps/DependencyService.d.ts +50 -0
  85. package/dist/devcc/deps/DependencyService.d.ts.map +1 -0
  86. package/dist/devcc/deps/DependencyService.js +109 -0
  87. package/dist/devcc/deps/DependencyService.js.map +1 -0
  88. package/dist/devcc/deps/parse.d.ts +49 -0
  89. package/dist/devcc/deps/parse.d.ts.map +1 -0
  90. package/dist/devcc/deps/parse.js +158 -0
  91. package/dist/devcc/deps/parse.js.map +1 -0
  92. package/dist/devcc/git/GitService.d.ts +60 -0
  93. package/dist/devcc/git/GitService.d.ts.map +1 -0
  94. package/dist/devcc/git/GitService.js +160 -0
  95. package/dist/devcc/git/GitService.js.map +1 -0
  96. package/dist/devcc/git/parse.d.ts +57 -0
  97. package/dist/devcc/git/parse.d.ts.map +1 -0
  98. package/dist/devcc/git/parse.js +174 -0
  99. package/dist/devcc/git/parse.js.map +1 -0
  100. package/dist/devcc/index.d.ts +37 -0
  101. package/dist/devcc/index.d.ts.map +1 -0
  102. package/dist/devcc/index.js +36 -0
  103. package/dist/devcc/index.js.map +1 -0
  104. package/dist/devcc/logs/LogBuffer.d.ts +86 -0
  105. package/dist/devcc/logs/LogBuffer.d.ts.map +1 -0
  106. package/dist/devcc/logs/LogBuffer.js +200 -0
  107. package/dist/devcc/logs/LogBuffer.js.map +1 -0
  108. package/dist/devcc/logs/merge.d.ts +36 -0
  109. package/dist/devcc/logs/merge.d.ts.map +1 -0
  110. package/dist/devcc/logs/merge.js +71 -0
  111. package/dist/devcc/logs/merge.js.map +1 -0
  112. package/dist/devcc/processes/ManagedProcess.d.ts +129 -0
  113. package/dist/devcc/processes/ManagedProcess.d.ts.map +1 -0
  114. package/dist/devcc/processes/ManagedProcess.js +80 -0
  115. package/dist/devcc/processes/ManagedProcess.js.map +1 -0
  116. package/dist/devcc/processes/ProcessManager.d.ts +112 -0
  117. package/dist/devcc/processes/ProcessManager.d.ts.map +1 -0
  118. package/dist/devcc/processes/ProcessManager.js +525 -0
  119. package/dist/devcc/processes/ProcessManager.js.map +1 -0
  120. package/dist/devcc/processes/graph.d.ts +35 -0
  121. package/dist/devcc/processes/graph.d.ts.map +1 -0
  122. package/dist/devcc/processes/graph.js +68 -0
  123. package/dist/devcc/processes/graph.js.map +1 -0
  124. package/dist/devcc/projects/ProjectRegistry.d.ts +52 -0
  125. package/dist/devcc/projects/ProjectRegistry.d.ts.map +1 -0
  126. package/dist/devcc/projects/ProjectRegistry.js +177 -0
  127. package/dist/devcc/projects/ProjectRegistry.js.map +1 -0
  128. package/dist/devcc/services/ServiceManager.d.ts +48 -0
  129. package/dist/devcc/services/ServiceManager.d.ts.map +1 -0
  130. package/dist/devcc/services/ServiceManager.js +146 -0
  131. package/dist/devcc/services/ServiceManager.js.map +1 -0
  132. package/dist/devcc/services/docker.d.ts +37 -0
  133. package/dist/devcc/services/docker.d.ts.map +1 -0
  134. package/dist/devcc/services/docker.js +179 -0
  135. package/dist/devcc/services/docker.js.map +1 -0
  136. package/dist/devcc/services/node.d.ts +40 -0
  137. package/dist/devcc/services/node.d.ts.map +1 -0
  138. package/dist/devcc/services/node.js +107 -0
  139. package/dist/devcc/services/node.js.map +1 -0
  140. package/dist/devcc/services/ollama.d.ts +27 -0
  141. package/dist/devcc/services/ollama.d.ts.map +1 -0
  142. package/dist/devcc/services/ollama.js +66 -0
  143. package/dist/devcc/services/ollama.js.map +1 -0
  144. package/dist/devcc/services/postgres.d.ts +30 -0
  145. package/dist/devcc/services/postgres.d.ts.map +1 -0
  146. package/dist/devcc/services/postgres.js +47 -0
  147. package/dist/devcc/services/postgres.js.map +1 -0
  148. package/dist/devcc/services/redis.d.ts +20 -0
  149. package/dist/devcc/services/redis.d.ts.map +1 -0
  150. package/dist/devcc/services/redis.js +39 -0
  151. package/dist/devcc/services/redis.js.map +1 -0
  152. package/dist/devcc/services/types.d.ts +51 -0
  153. package/dist/devcc/services/types.d.ts.map +1 -0
  154. package/dist/devcc/services/types.js +10 -0
  155. package/dist/devcc/services/types.js.map +1 -0
  156. package/dist/devcc/system/SystemMonitor.d.ts +87 -0
  157. package/dist/devcc/system/SystemMonitor.d.ts.map +1 -0
  158. package/dist/devcc/system/SystemMonitor.js +142 -0
  159. package/dist/devcc/system/SystemMonitor.js.map +1 -0
  160. package/dist/devcc/utils/errors.d.ts +31 -0
  161. package/dist/devcc/utils/errors.d.ts.map +1 -0
  162. package/dist/devcc/utils/errors.js +52 -0
  163. package/dist/devcc/utils/errors.js.map +1 -0
  164. package/dist/devcc/utils/exec.d.ts +41 -0
  165. package/dist/devcc/utils/exec.d.ts.map +1 -0
  166. package/dist/devcc/utils/exec.js +112 -0
  167. package/dist/devcc/utils/exec.js.map +1 -0
  168. package/dist/devcc/utils/format.d.ts +18 -0
  169. package/dist/devcc/utils/format.d.ts.map +1 -0
  170. package/dist/devcc/utils/format.js +85 -0
  171. package/dist/devcc/utils/format.js.map +1 -0
  172. package/dist/devcc/utils/fuzzy.d.ts +12 -0
  173. package/dist/devcc/utils/fuzzy.d.ts.map +1 -0
  174. package/dist/devcc/utils/fuzzy.js +20 -0
  175. package/dist/devcc/utils/fuzzy.js.map +1 -0
  176. package/dist/devcc/utils/logger.d.ts +41 -0
  177. package/dist/devcc/utils/logger.d.ts.map +1 -0
  178. package/dist/devcc/utils/logger.js +117 -0
  179. package/dist/devcc/utils/logger.js.map +1 -0
  180. package/dist/devcc/utils/packageManager.d.ts +39 -0
  181. package/dist/devcc/utils/packageManager.d.ts.map +1 -0
  182. package/dist/devcc/utils/packageManager.js +85 -0
  183. package/dist/devcc/utils/packageManager.js.map +1 -0
  184. package/dist/devcc/utils/paths.d.ts +12 -0
  185. package/dist/devcc/utils/paths.d.ts.map +1 -0
  186. package/dist/devcc/utils/paths.js +39 -0
  187. package/dist/devcc/utils/paths.js.map +1 -0
  188. package/dist/devcc/views/DependenciesView.d.ts +34 -0
  189. package/dist/devcc/views/DependenciesView.d.ts.map +1 -0
  190. package/dist/devcc/views/DependenciesView.js +170 -0
  191. package/dist/devcc/views/DependenciesView.js.map +1 -0
  192. package/dist/devcc/views/GitView.d.ts +29 -0
  193. package/dist/devcc/views/GitView.d.ts.map +1 -0
  194. package/dist/devcc/views/GitView.js +226 -0
  195. package/dist/devcc/views/GitView.js.map +1 -0
  196. package/dist/devcc/views/LogsView.d.ts +39 -0
  197. package/dist/devcc/views/LogsView.d.ts.map +1 -0
  198. package/dist/devcc/views/LogsView.js +249 -0
  199. package/dist/devcc/views/LogsView.js.map +1 -0
  200. package/dist/devcc/views/OverviewView.d.ts +16 -0
  201. package/dist/devcc/views/OverviewView.d.ts.map +1 -0
  202. package/dist/devcc/views/OverviewView.js +135 -0
  203. package/dist/devcc/views/OverviewView.js.map +1 -0
  204. package/dist/devcc/views/ProcessesView.d.ts +26 -0
  205. package/dist/devcc/views/ProcessesView.d.ts.map +1 -0
  206. package/dist/devcc/views/ProcessesView.js +161 -0
  207. package/dist/devcc/views/ProcessesView.js.map +1 -0
  208. package/dist/devcc/views/ScriptsView.d.ts +30 -0
  209. package/dist/devcc/views/ScriptsView.d.ts.map +1 -0
  210. package/dist/devcc/views/ScriptsView.js +168 -0
  211. package/dist/devcc/views/ScriptsView.js.map +1 -0
  212. package/dist/devcc/views/ServicesView.d.ts +28 -0
  213. package/dist/devcc/views/ServicesView.d.ts.map +1 -0
  214. package/dist/devcc/views/ServicesView.js +153 -0
  215. package/dist/devcc/views/ServicesView.js.map +1 -0
  216. package/dist/devcc/views/SettingsView.d.ts +20 -0
  217. package/dist/devcc/views/SettingsView.d.ts.map +1 -0
  218. package/dist/devcc/views/SettingsView.js +114 -0
  219. package/dist/devcc/views/SettingsView.js.map +1 -0
  220. package/dist/devcc/views/SystemView.d.ts +13 -0
  221. package/dist/devcc/views/SystemView.d.ts.map +1 -0
  222. package/dist/devcc/views/SystemView.js +82 -0
  223. package/dist/devcc/views/SystemView.js.map +1 -0
  224. package/dist/devcc/views/View.d.ts +35 -0
  225. package/dist/devcc/views/View.d.ts.map +1 -0
  226. package/dist/devcc/views/View.js +42 -0
  227. package/dist/devcc/views/View.js.map +1 -0
  228. package/package.json +79 -0
  229. package/src/devcc/app/App.ts +1463 -0
  230. package/src/devcc/app/builtinCommands.ts +429 -0
  231. package/src/devcc/app/keymap.ts +167 -0
  232. package/src/devcc/app/theme.ts +83 -0
  233. package/src/devcc/cli.ts +122 -0
  234. package/src/devcc/components/CommandPalette.ts +136 -0
  235. package/src/devcc/components/ConfirmDialog.ts +174 -0
  236. package/src/devcc/components/Footer.ts +85 -0
  237. package/src/devcc/components/Header.ts +93 -0
  238. package/src/devcc/components/HelpOverlay.ts +62 -0
  239. package/src/devcc/components/Overlay.ts +91 -0
  240. package/src/devcc/components/ProjectPicker.ts +138 -0
  241. package/src/devcc/components/Sidebar.ts +163 -0
  242. package/src/devcc/components/StatusBadge.ts +36 -0
  243. package/src/devcc/components/primitives.ts +213 -0
  244. package/src/devcc/components/styled.ts +44 -0
  245. package/src/devcc/core/commands.ts +140 -0
  246. package/src/devcc/core/config.ts +405 -0
  247. package/src/devcc/core/events.ts +41 -0
  248. package/src/devcc/core/state.ts +236 -0
  249. package/src/devcc/deps/DependencyService.ts +152 -0
  250. package/src/devcc/deps/parse.ts +210 -0
  251. package/src/devcc/git/GitService.ts +205 -0
  252. package/src/devcc/git/parse.ts +203 -0
  253. package/src/devcc/index.ts +115 -0
  254. package/src/devcc/logs/LogBuffer.ts +237 -0
  255. package/src/devcc/logs/merge.ts +87 -0
  256. package/src/devcc/processes/ManagedProcess.ts +195 -0
  257. package/src/devcc/processes/ProcessManager.ts +625 -0
  258. package/src/devcc/processes/graph.ts +98 -0
  259. package/src/devcc/projects/ProjectRegistry.ts +219 -0
  260. package/src/devcc/services/ServiceManager.ts +180 -0
  261. package/src/devcc/services/docker.ts +220 -0
  262. package/src/devcc/services/node.ts +137 -0
  263. package/src/devcc/services/ollama.ts +80 -0
  264. package/src/devcc/services/postgres.ts +57 -0
  265. package/src/devcc/services/redis.ts +47 -0
  266. package/src/devcc/services/types.ts +59 -0
  267. package/src/devcc/system/SystemMonitor.ts +207 -0
  268. package/src/devcc/utils/errors.ts +64 -0
  269. package/src/devcc/utils/exec.ts +165 -0
  270. package/src/devcc/utils/format.ts +83 -0
  271. package/src/devcc/utils/fuzzy.ts +44 -0
  272. package/src/devcc/utils/logger.ts +140 -0
  273. package/src/devcc/utils/packageManager.ts +112 -0
  274. package/src/devcc/utils/paths.ts +39 -0
  275. package/src/devcc/views/DependenciesView.ts +206 -0
  276. package/src/devcc/views/GitView.ts +259 -0
  277. package/src/devcc/views/LogsView.ts +300 -0
  278. package/src/devcc/views/OverviewView.ts +187 -0
  279. package/src/devcc/views/ProcessesView.ts +177 -0
  280. package/src/devcc/views/ScriptsView.ts +187 -0
  281. package/src/devcc/views/ServicesView.ts +188 -0
  282. package/src/devcc/views/SettingsView.ts +146 -0
  283. package/src/devcc/views/SystemView.ts +110 -0
  284. package/src/devcc/views/View.ts +63 -0
@@ -0,0 +1,114 @@
1
+ import { BoxRenderable, InputRenderable, TextRenderable } from "@opentui/core";
2
+ import { theme } from "../app/theme.js";
3
+ import { fit } from "../utils/format.js";
4
+ import { tildify, truncatePath } from "../utils/paths.js";
5
+ import { Overlay } from "./Overlay.js";
6
+ import { RowList } from "./primitives.js";
7
+ import { chunk, dim, styled } from "./styled.js";
8
+ /**
9
+ * Project switcher (`ctrl+p`).
10
+ *
11
+ * Reattaches the whole dashboard to another checkout: the current project,
12
+ * recently opened ones, anything named in config, and sibling directories.
13
+ */
14
+ export class ProjectPicker extends Overlay {
15
+ input;
16
+ list;
17
+ footer;
18
+ results = [];
19
+ selectedIndex = 0;
20
+ currentPath = "";
21
+ constructor(ctx) {
22
+ super(ctx, {
23
+ title: " Switch project ",
24
+ widthRatio: 0.7,
25
+ minWidth: 44,
26
+ maxWidth: 100,
27
+ heightRatio: 0.6,
28
+ minHeight: 9,
29
+ maxHeight: 24,
30
+ });
31
+ const inputWrapper = new BoxRenderable(ctx, {
32
+ height: 1,
33
+ flexShrink: 0,
34
+ flexDirection: "row",
35
+ marginTop: 1,
36
+ backgroundColor: theme.panelAlt,
37
+ paddingLeft: 1,
38
+ paddingRight: 1,
39
+ });
40
+ inputWrapper.add(new TextRenderable(ctx, { content: "› ", fg: theme.accent, width: 2, selectable: false }));
41
+ this.input = new InputRenderable(ctx, {
42
+ flexGrow: 1,
43
+ backgroundColor: theme.panelAlt,
44
+ textColor: theme.textBright,
45
+ placeholder: "Filter projects…",
46
+ placeholderColor: theme.textDim,
47
+ });
48
+ inputWrapper.add(this.input);
49
+ // Column widths depend on the overlay width, which is only known after
50
+ // layout, so recompute the rows when the viewport changes.
51
+ this.list = new RowList(ctx, { marginTop: 1, flexGrow: 1, onViewportChange: () => this.paint() });
52
+ this.footer = new TextRenderable(ctx, {
53
+ content: "",
54
+ fg: theme.textDim,
55
+ height: 1,
56
+ flexShrink: 0,
57
+ selectable: false,
58
+ truncate: true,
59
+ });
60
+ this.box.add(inputWrapper);
61
+ this.box.add(this.list.box);
62
+ this.box.add(this.footer);
63
+ }
64
+ open(currentPath) {
65
+ this.currentPath = currentPath;
66
+ this.input.value = "";
67
+ this.selectedIndex = 0;
68
+ this.show();
69
+ this.input.focus();
70
+ }
71
+ close() {
72
+ this.input.blur();
73
+ this.hide();
74
+ }
75
+ get query() {
76
+ return this.input.value;
77
+ }
78
+ setResults(results) {
79
+ this.results = results;
80
+ this.selectedIndex = Math.min(this.selectedIndex, Math.max(0, results.length - 1));
81
+ this.paint();
82
+ }
83
+ move(delta) {
84
+ if (this.results.length === 0)
85
+ return;
86
+ const next = this.selectedIndex + delta;
87
+ this.selectedIndex = ((next % this.results.length) + this.results.length) % this.results.length;
88
+ this.paint();
89
+ }
90
+ get selected() {
91
+ return this.results[this.selectedIndex];
92
+ }
93
+ paint() {
94
+ const width = Math.max(24, this.box.width - 4);
95
+ const nameWidth = Math.min(28, Math.max(12, Math.floor(width * 0.3)));
96
+ const rows = this.results.map((entry) => {
97
+ const isCurrent = entry.path === this.currentPath;
98
+ const markers = [entry.hasGit ? "git" : null, entry.hasPackageJson ? "pkg" : null]
99
+ .filter(Boolean)
100
+ .join(" ");
101
+ const pathWidth = Math.max(12, width - nameWidth - 12);
102
+ return {
103
+ key: entry.path,
104
+ content: styled(chunk(isCurrent ? "● " : " ", theme.accent), chunk(fit(entry.name, nameWidth), isCurrent ? theme.accent : theme.textBright), dim(fit(truncatePath(tildify(entry.path), pathWidth - 1), pathWidth)), dim(fit(markers, 8))),
105
+ };
106
+ });
107
+ if (rows.length === 0) {
108
+ rows.push({ key: "__empty", disabled: true, content: styled(dim("No matching projects")) });
109
+ }
110
+ this.list.setRows(rows, this.selectedIndex);
111
+ this.footer.content = styled(dim(`${this.results.length} project${this.results.length === 1 ? "" : "s"}`), dim(" ↑↓ move enter switch esc cancel"));
112
+ }
113
+ }
114
+ //# sourceMappingURL=ProjectPicker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProjectPicker.js","sourceRoot":"","sources":["../../../src/devcc/components/ProjectPicker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { BoxRenderable, type RenderContext } from "@opentui/core";
2
+ import type { ViewId } from "../core/state.js";
3
+ export interface SidebarItem {
4
+ id: ViewId;
5
+ label: string;
6
+ }
7
+ export declare const SIDEBAR_ITEMS: readonly SidebarItem[];
8
+ /** What the rail needs to know about an open project. */
9
+ export interface SidebarProject {
10
+ path: string;
11
+ name: string;
12
+ /** Processes currently active in that project. */
13
+ running: number;
14
+ /** True when a process there has failed or exhausted its restarts. */
15
+ attention: boolean;
16
+ }
17
+ export declare const SIDEBAR_WIDTH = 23;
18
+ /**
19
+ * Left navigation rail.
20
+ *
21
+ * With one project open it is the plain section list. Once a second project is
22
+ * opened a PROJECTS block appears above it - progressive disclosure, so the
23
+ * single-project case looks exactly as it always did.
24
+ */
25
+ export declare class Sidebar {
26
+ private readonly ctx;
27
+ readonly box: BoxRenderable;
28
+ private readonly projectsBlock;
29
+ private readonly projectRows;
30
+ private readonly sectionHeading;
31
+ private readonly rows;
32
+ private activeView;
33
+ constructor(ctx: RenderContext);
34
+ setActive(view: ViewId): void;
35
+ /**
36
+ * Show the open projects. The block hides itself with a single project, and
37
+ * the section heading switches from "PROJECT" to "SECTIONS" when it shows.
38
+ */
39
+ setProjects(projects: readonly SidebarProject[], activePath: string): void;
40
+ get active(): ViewId;
41
+ }
42
+ //# sourceMappingURL=Sidebar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/devcc/components/Sidebar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAkB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAGjF,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAI9C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;CACd;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,WAAW,EAU/C,CAAA;AAED,yDAAyD;AACzD,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,kDAAkD;IAClD,OAAO,EAAE,MAAM,CAAA;IACf,sEAAsE;IACtE,SAAS,EAAE,OAAO,CAAA;CACnB;AAED,eAAO,MAAM,aAAa,KAAK,CAAA;AAS/B;;;;;;GAMG;AACH,qBAAa,OAAO;IAQN,OAAO,CAAC,QAAQ,CAAC,GAAG;IAPhC,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAA;IAC3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAe;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAuB;IACnD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAgB;IAC/C,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAoC;IACzD,OAAO,CAAC,UAAU,CAAqB;gBAEV,GAAG,EAAE,aAAa;IA0C/C,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAiB7B;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,SAAS,cAAc,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI;IAsC1E,IAAI,MAAM,IAAI,MAAM,CAEnB;CACF"}
@@ -0,0 +1,127 @@
1
+ import { BoxRenderable, TextRenderable } from "@opentui/core";
2
+ import { shortcutHintFor } from "../app/keymap.js";
3
+ import { theme } from "../app/theme.js";
4
+ import { fit } from "../utils/format.js";
5
+ import { chunk, dim, styled } from "./styled.js";
6
+ export const SIDEBAR_ITEMS = [
7
+ { id: "overview", label: "Overview" },
8
+ { id: "processes", label: "Processes" },
9
+ { id: "services", label: "Services" },
10
+ { id: "scripts", label: "Scripts" },
11
+ { id: "git", label: "Git" },
12
+ { id: "logs", label: "Logs" },
13
+ { id: "dependencies", label: "Dependencies" },
14
+ { id: "system", label: "System" },
15
+ { id: "settings", label: "Settings" },
16
+ ];
17
+ export const SIDEBAR_WIDTH = 23;
18
+ /** Widest label ("Dependencies") plus a space before the shortcut column. */
19
+ const LABEL_WIDTH = 13;
20
+ /** Room for the project name; a space and a 3-column badge follow it. */
21
+ const PROJECT_WIDTH = 14;
22
+ /** Keep the rail readable on short terminals. */
23
+ const MAX_PROJECT_ROWS = 6;
24
+ /**
25
+ * Left navigation rail.
26
+ *
27
+ * With one project open it is the plain section list. Once a second project is
28
+ * opened a PROJECTS block appears above it - progressive disclosure, so the
29
+ * single-project case looks exactly as it always did.
30
+ */
31
+ export class Sidebar {
32
+ ctx;
33
+ box;
34
+ projectsBlock;
35
+ projectRows = [];
36
+ sectionHeading;
37
+ rows = new Map();
38
+ activeView = "overview";
39
+ constructor(ctx) {
40
+ this.ctx = ctx;
41
+ this.box = new BoxRenderable(ctx, {
42
+ width: SIDEBAR_WIDTH,
43
+ flexShrink: 0,
44
+ flexDirection: "column",
45
+ paddingLeft: 1,
46
+ paddingRight: 1,
47
+ paddingTop: 1,
48
+ border: ["right"],
49
+ borderColor: theme.border,
50
+ backgroundColor: theme.panel,
51
+ });
52
+ this.projectsBlock = new BoxRenderable(ctx, {
53
+ flexDirection: "column",
54
+ flexShrink: 0,
55
+ visible: false,
56
+ backgroundColor: "transparent",
57
+ });
58
+ this.projectsBlock.add(new TextRenderable(ctx, { content: "PROJECTS", fg: theme.textDim, height: 1, selectable: false }));
59
+ this.box.add(this.projectsBlock);
60
+ this.sectionHeading = new TextRenderable(ctx, {
61
+ content: "PROJECT",
62
+ fg: theme.textDim,
63
+ height: 1,
64
+ selectable: false,
65
+ });
66
+ this.box.add(this.sectionHeading);
67
+ this.box.add(new BoxRenderable(ctx, { height: 1, backgroundColor: "transparent" }));
68
+ for (const item of SIDEBAR_ITEMS) {
69
+ const row = new TextRenderable(ctx, { content: "", height: 1, selectable: false, truncate: true });
70
+ this.rows.set(item.id, row);
71
+ this.box.add(row);
72
+ }
73
+ this.setActive("overview");
74
+ }
75
+ setActive(view) {
76
+ this.activeView = view;
77
+ for (const item of SIDEBAR_ITEMS) {
78
+ const row = this.rows.get(item.id);
79
+ if (!row)
80
+ continue;
81
+ const active = item.id === view;
82
+ // Shortcut hints are derived from the keymap, never hand-written here.
83
+ const hint = shortcutHintFor(item.id);
84
+ row.content = styled(chunk(active ? "● " : "○ ", active ? theme.accent : theme.textDim), chunk(fit(item.label, LABEL_WIDTH), active ? theme.textBright : theme.text), dim(hint));
85
+ row.bg = active ? theme.selectionBackground : "transparent";
86
+ }
87
+ }
88
+ /**
89
+ * Show the open projects. The block hides itself with a single project, and
90
+ * the section heading switches from "PROJECT" to "SECTIONS" when it shows.
91
+ */
92
+ setProjects(projects, activePath) {
93
+ const multi = projects.length > 1;
94
+ this.projectsBlock.visible = multi;
95
+ this.sectionHeading.content = multi ? "SECTIONS" : "PROJECT";
96
+ if (!multi)
97
+ return;
98
+ const visible = projects.slice(0, MAX_PROJECT_ROWS);
99
+ while (this.projectRows.length < visible.length + 1) {
100
+ const row = new TextRenderable(this.ctx, { content: "", height: 1, selectable: false, truncate: true });
101
+ this.projectRows.push(row);
102
+ this.projectsBlock.add(row);
103
+ }
104
+ for (const [index, row] of this.projectRows.entries()) {
105
+ const project = visible[index];
106
+ if (!project) {
107
+ // The last pooled row doubles as the spacer under the block.
108
+ row.visible = index === visible.length;
109
+ row.content =
110
+ index === visible.length && projects.length > visible.length
111
+ ? styled(dim(` +${projects.length - visible.length} more`))
112
+ : "";
113
+ row.bg = "transparent";
114
+ continue;
115
+ }
116
+ row.visible = true;
117
+ const active = project.path === activePath;
118
+ const badge = project.running > 0 ? `${project.running}▸` : "";
119
+ row.content = styled(chunk(active ? "● " : "○ ", active ? theme.accent : theme.textDim), chunk(fit(project.name, PROJECT_WIDTH), active ? theme.textBright : theme.text), " ", project.attention ? chunk(fit("!", 3), theme.danger) : chunk(fit(badge, 3), theme.success));
120
+ row.bg = active ? theme.selectionBackground : "transparent";
121
+ }
122
+ }
123
+ get active() {
124
+ return this.activeView;
125
+ }
126
+ }
127
+ //# sourceMappingURL=Sidebar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sidebar.js","sourceRoot":"","sources":["../../../src/devcc/components/Sidebar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { type StyledText } from "@opentui/core";
2
+ import type { ProcessStatus } from "../processes/ManagedProcess.js";
3
+ import type { ServiceState } from "../services/types.js";
4
+ /**
5
+ * Status indicators.
6
+ *
7
+ * A single glyph plus a colour is enough to scan a column at a glance; the
8
+ * word is included at a fixed width so the columns after it stay aligned.
9
+ */
10
+ export declare function processBadge(status: ProcessStatus, width?: number): StyledText;
11
+ export declare function serviceBadge(state: ServiceState, width?: number): StyledText;
12
+ export declare function processGlyph(status: ProcessStatus): StyledText;
13
+ export declare function serviceGlyph(state: ServiceState): StyledText;
14
+ /** `label value` pair with a dim label, aligned to `labelWidth`. */
15
+ export declare function keyValue(label: string, value: string, labelWidth?: number): StyledText;
16
+ //# sourceMappingURL=StatusBadge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusBadge.d.ts","sourceRoot":"","sources":["../../../src/devcc/components/StatusBadge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,eAAe,CAAA;AAEtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,EAAE,KAAK,SAAI,GAAG,UAAU,CAGzE;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,EAAE,KAAK,SAAK,GAAG,UAAU,CAGxE;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,UAAU,CAG9D;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,YAAY,GAAG,UAAU,CAG5D;AAED,qEAAqE;AACrE,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,SAAK,GAAG,UAAU,CAElF"}
@@ -0,0 +1,30 @@
1
+ import { fg, t } from "@opentui/core";
2
+ import { processStatusStyle, serviceStateStyle, theme } from "../app/theme.js";
3
+ import { fit } from "../utils/format.js";
4
+ /**
5
+ * Status indicators.
6
+ *
7
+ * A single glyph plus a colour is enough to scan a column at a glance; the
8
+ * word is included at a fixed width so the columns after it stay aligned.
9
+ */
10
+ export function processBadge(status, width = 9) {
11
+ const style = processStatusStyle(status);
12
+ return t `${fg(style.color)(style.glyph)} ${fg(style.color)(fit(style.label, width))}`;
13
+ }
14
+ export function serviceBadge(state, width = 12) {
15
+ const style = serviceStateStyle(state);
16
+ return t `${fg(style.color)(style.glyph)} ${fg(style.color)(fit(style.label, width))}`;
17
+ }
18
+ export function processGlyph(status) {
19
+ const style = processStatusStyle(status);
20
+ return t `${fg(style.color)(style.glyph)}`;
21
+ }
22
+ export function serviceGlyph(state) {
23
+ const style = serviceStateStyle(state);
24
+ return t `${fg(style.color)(style.glyph)}`;
25
+ }
26
+ /** `label value` pair with a dim label, aligned to `labelWidth`. */
27
+ export function keyValue(label, value, labelWidth = 16) {
28
+ return t `${fg(theme.textDim)(fit(label, labelWidth))}${fg(theme.text)(value)}`;
29
+ }
30
+ //# sourceMappingURL=StatusBadge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusBadge.js","sourceRoot":"","sources":["../../../src/devcc/components/StatusBadge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,CAAC,EAAmB,MAAM,eAAe,CAAA;AACtD,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AAG9E,OAAO,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAA;AAExC;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,MAAqB,EAAE,KAAK,GAAG,CAAC;IAC3D,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;IACxC,OAAO,CAAC,CAAA,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,CAAA;AACvF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAmB,EAAE,KAAK,GAAG,EAAE;IAC1D,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;IACtC,OAAO,CAAC,CAAA,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,EAAE,CAAA;AACvF,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAA;IACxC,OAAO,CAAC,CAAA,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAA;AAC3C,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAmB;IAC9C,MAAM,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAA;IACtC,OAAO,CAAC,CAAA,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAA;AAC3C,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,QAAQ,CAAC,KAAa,EAAE,KAAa,EAAE,UAAU,GAAG,EAAE;IACpE,OAAO,CAAC,CAAA,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAA;AAChF,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { BoxRenderable, TextRenderable, type BoxOptions, type RenderContext, type StyledText } from "@opentui/core";
2
+ /** Shorthand for a plain text row. */
3
+ export declare function createText(ctx: RenderContext, content: StyledText | string, options?: {
4
+ fg?: string;
5
+ bg?: string;
6
+ height?: number;
7
+ }): TextRenderable;
8
+ /** A section heading inside a panel. */
9
+ export declare function createHeading(ctx: RenderContext, label: string): TextRenderable;
10
+ export declare function createBox(ctx: RenderContext, options?: BoxOptions): BoxRenderable;
11
+ /** A vertical spacer. */
12
+ export declare function createSpacer(ctx: RenderContext, height?: number): BoxRenderable;
13
+ export interface ListRow {
14
+ /** Stable identity, used to preserve selection across refreshes. */
15
+ key: string;
16
+ content: StyledText | string;
17
+ /** Rendered as a non-selectable row (group headings, empty states). */
18
+ disabled?: boolean;
19
+ }
20
+ export interface RowListOptions extends BoxOptions {
21
+ /** Rows kept visible above/below the selection while scrolling. */
22
+ scrollPadding?: number;
23
+ /**
24
+ * Called when the viewport height changes. Views that window their own data
25
+ * (the log viewer) use this to recompute the slice they hand over.
26
+ */
27
+ onViewportChange?: () => void;
28
+ }
29
+ /**
30
+ * A scrolling, selectable list of single-line rows.
31
+ *
32
+ * Renderables are recycled: refreshing the data updates existing
33
+ * `TextRenderable` contents instead of rebuilding the subtree, and only the rows
34
+ * that fit the current viewport are materialised.
35
+ */
36
+ export declare class RowList {
37
+ private readonly ctx;
38
+ readonly box: BoxRenderable;
39
+ private readonly rowRenderables;
40
+ private rows;
41
+ private selectedIndex;
42
+ private scrollOffset;
43
+ private focused;
44
+ private readonly scrollPadding;
45
+ private readonly onViewportChange;
46
+ private lastVisibleCount;
47
+ constructor(ctx: RenderContext, options?: RowListOptions);
48
+ get length(): number;
49
+ get visibleCount(): number;
50
+ get offset(): number;
51
+ setFocused(focused: boolean): void;
52
+ setRows(rows: ListRow[], selectedIndex: number): void;
53
+ setSelectedIndex(index: number): void;
54
+ scrollBy(delta: number): void;
55
+ scrollToEnd(): void;
56
+ private ensureVisible;
57
+ private paint;
58
+ private ensurePool;
59
+ destroy(): void;
60
+ }
61
+ export declare function clamp(value: number, min: number, max: number): number;
62
+ //# sourceMappingURL=primitives.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.d.ts","sourceRoot":"","sources":["../../../src/devcc/components/primitives.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,cAAc,EACd,KAAK,UAAU,EACf,KAAK,aAAa,EAClB,KAAK,UAAU,EAChB,MAAM,eAAe,CAAA;AAGtB,sCAAsC;AACtC,wBAAgB,UAAU,CACxB,GAAG,EAAE,aAAa,EAClB,OAAO,EAAE,UAAU,GAAG,MAAM,EAC5B,OAAO,GAAE;IAAE,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC1D,cAAc,CAShB;AAED,wCAAwC;AACxC,wBAAgB,aAAa,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,CAQ/E;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,GAAE,UAAe,GAAG,aAAa,CAKrF;AAED,yBAAyB;AACzB,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,EAAE,MAAM,SAAI,GAAG,aAAa,CAE1E;AAED,MAAM,WAAW,OAAO;IACtB,oEAAoE;IACpE,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,UAAU,GAAG,MAAM,CAAA;IAC5B,uEAAuE;IACvE,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,MAAM,WAAW,cAAe,SAAQ,UAAU;IAChD,mEAAmE;IACnE,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,MAAM,IAAI,CAAA;CAC9B;AAED;;;;;;GAMG;AACH,qBAAa,OAAO;IAYhB,OAAO,CAAC,QAAQ,CAAC,GAAG;IAXtB,QAAQ,CAAC,GAAG,EAAE,aAAa,CAAA;IAC3B,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAuB;IACtD,OAAO,CAAC,IAAI,CAAgB;IAC5B,OAAO,CAAC,aAAa,CAAI;IACzB,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAQ;IACtC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA0B;IAC3D,OAAO,CAAC,gBAAgB,CAAI;gBAGT,GAAG,EAAE,aAAa,EACnC,OAAO,GAAE,cAAmB;IAsB9B,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,IAAI,MAAM,IAAI,MAAM,CAEnB;IAED,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAMlC,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,MAAM,GAAG,IAAI;IAOrD,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAQrC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAM7B,WAAW,IAAI,IAAI;IAKnB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,KAAK;IAkBb,OAAO,CAAC,UAAU;IAqBlB,OAAO,IAAI,IAAI;CAGhB;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAGrE"}
@@ -0,0 +1,169 @@
1
+ import { BoxRenderable, TextRenderable, } from "@opentui/core";
2
+ import { theme } from "../app/theme.js";
3
+ /** Shorthand for a plain text row. */
4
+ export function createText(ctx, content, options = {}) {
5
+ return new TextRenderable(ctx, {
6
+ content,
7
+ fg: options.fg ?? theme.text,
8
+ bg: options.bg ?? "transparent",
9
+ height: options.height ?? 1,
10
+ truncate: true,
11
+ selectable: false,
12
+ });
13
+ }
14
+ /** A section heading inside a panel. */
15
+ export function createHeading(ctx, label) {
16
+ return new TextRenderable(ctx, {
17
+ content: label.toUpperCase(),
18
+ fg: theme.accent,
19
+ height: 1,
20
+ selectable: false,
21
+ truncate: true,
22
+ });
23
+ }
24
+ export function createBox(ctx, options = {}) {
25
+ return new BoxRenderable(ctx, {
26
+ backgroundColor: "transparent",
27
+ ...options,
28
+ });
29
+ }
30
+ /** A vertical spacer. */
31
+ export function createSpacer(ctx, height = 1) {
32
+ return new BoxRenderable(ctx, { height, backgroundColor: "transparent" });
33
+ }
34
+ /**
35
+ * A scrolling, selectable list of single-line rows.
36
+ *
37
+ * Renderables are recycled: refreshing the data updates existing
38
+ * `TextRenderable` contents instead of rebuilding the subtree, and only the rows
39
+ * that fit the current viewport are materialised.
40
+ */
41
+ export class RowList {
42
+ ctx;
43
+ box;
44
+ rowRenderables = [];
45
+ rows = [];
46
+ selectedIndex = 0;
47
+ scrollOffset = 0;
48
+ focused = true;
49
+ scrollPadding;
50
+ onViewportChange;
51
+ lastVisibleCount = 0;
52
+ constructor(ctx, options = {}) {
53
+ this.ctx = ctx;
54
+ const { scrollPadding, onViewportChange, ...boxOptions } = options;
55
+ this.scrollPadding = scrollPadding ?? 1;
56
+ this.onViewportChange = onViewportChange;
57
+ this.box = new BoxRenderable(ctx, {
58
+ flexDirection: "column",
59
+ flexGrow: 1,
60
+ overflow: "hidden",
61
+ backgroundColor: "transparent",
62
+ ...boxOptions,
63
+ });
64
+ this.box.onSizeChange = () => {
65
+ const visible = this.visibleCount;
66
+ this.paint();
67
+ if (visible !== this.lastVisibleCount) {
68
+ this.lastVisibleCount = visible;
69
+ this.onViewportChange?.();
70
+ }
71
+ };
72
+ }
73
+ get length() {
74
+ return this.rows.length;
75
+ }
76
+ get visibleCount() {
77
+ return Math.max(1, this.box.height);
78
+ }
79
+ get offset() {
80
+ return this.scrollOffset;
81
+ }
82
+ setFocused(focused) {
83
+ if (this.focused === focused)
84
+ return;
85
+ this.focused = focused;
86
+ this.paint();
87
+ }
88
+ setRows(rows, selectedIndex) {
89
+ this.rows = rows;
90
+ this.selectedIndex = clamp(selectedIndex, 0, Math.max(0, rows.length - 1));
91
+ this.ensureVisible();
92
+ this.paint();
93
+ }
94
+ setSelectedIndex(index) {
95
+ const next = clamp(index, 0, Math.max(0, this.rows.length - 1));
96
+ if (next === this.selectedIndex)
97
+ return;
98
+ this.selectedIndex = next;
99
+ this.ensureVisible();
100
+ this.paint();
101
+ }
102
+ scrollBy(delta) {
103
+ const maxOffset = Math.max(0, this.rows.length - this.visibleCount);
104
+ this.scrollOffset = clamp(this.scrollOffset + delta, 0, maxOffset);
105
+ this.paint();
106
+ }
107
+ scrollToEnd() {
108
+ this.scrollOffset = Math.max(0, this.rows.length - this.visibleCount);
109
+ this.paint();
110
+ }
111
+ ensureVisible() {
112
+ const visible = this.visibleCount;
113
+ const padding = Math.min(this.scrollPadding, Math.floor((visible - 1) / 2));
114
+ const maxOffset = Math.max(0, this.rows.length - visible);
115
+ if (this.selectedIndex < this.scrollOffset + padding) {
116
+ this.scrollOffset = this.selectedIndex - padding;
117
+ }
118
+ else if (this.selectedIndex > this.scrollOffset + visible - 1 - padding) {
119
+ this.scrollOffset = this.selectedIndex - visible + 1 + padding;
120
+ }
121
+ this.scrollOffset = clamp(this.scrollOffset, 0, maxOffset);
122
+ }
123
+ paint() {
124
+ const visible = this.visibleCount;
125
+ this.ensurePool(Math.min(visible, Math.max(this.rows.length, 1)));
126
+ for (const [index, renderable] of this.rowRenderables.entries()) {
127
+ const rowIndex = this.scrollOffset + index;
128
+ const row = this.rows[rowIndex];
129
+ if (!row) {
130
+ renderable.visible = false;
131
+ continue;
132
+ }
133
+ renderable.visible = true;
134
+ renderable.content = row.content;
135
+ const selected = rowIndex === this.selectedIndex && !row.disabled;
136
+ renderable.bg = selected ? (this.focused ? theme.selectionBackground : theme.panelAlt) : "transparent";
137
+ }
138
+ }
139
+ ensurePool(size) {
140
+ while (this.rowRenderables.length < size) {
141
+ const renderable = new TextRenderable(this.ctx, {
142
+ content: "",
143
+ fg: theme.text,
144
+ height: 1,
145
+ flexShrink: 0,
146
+ truncate: true,
147
+ selectable: false,
148
+ });
149
+ this.rowRenderables.push(renderable);
150
+ this.box.add(renderable);
151
+ }
152
+ while (this.rowRenderables.length > size) {
153
+ const renderable = this.rowRenderables.pop();
154
+ if (!renderable)
155
+ break;
156
+ this.box.remove(renderable);
157
+ renderable.destroy();
158
+ }
159
+ }
160
+ destroy() {
161
+ this.box.destroyRecursively();
162
+ }
163
+ }
164
+ export function clamp(value, min, max) {
165
+ if (max < min)
166
+ return min;
167
+ return Math.max(min, Math.min(max, value));
168
+ }
169
+ //# sourceMappingURL=primitives.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"primitives.js","sourceRoot":"","sources":["../../../src/devcc/components/primitives.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { StyledText, type TextChunk } from "@opentui/core";
2
+ /**
3
+ * Helpers for composing `StyledText` programmatically.
4
+ *
5
+ * The `t` template literal is convenient for fixed strings; these helpers cover
6
+ * the dynamic case (variable numbers of coloured segments) without fighting the
7
+ * template syntax.
8
+ */
9
+ export declare function chunk(text: string, color?: string): TextChunk;
10
+ export declare function bold(text: string, color?: string): TextChunk;
11
+ export declare function dim(text: string): TextChunk;
12
+ export declare function styled(...parts: (TextChunk | string)[]): StyledText;
13
+ export declare function joinStyled(parts: StyledText[], separator: string, separatorColor?: "#6b7885"): StyledText;
14
+ /** Total display length of a styled line, for right-alignment maths. */
15
+ export declare function styledLength(text: StyledText): number;
16
+ //# sourceMappingURL=styled.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"styled.d.ts","sourceRoot":"","sources":["../../../src/devcc/components/styled.ts"],"names":[],"mappings":"AAAA,OAAO,EAA0C,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,eAAe,CAAA;AAGlG;;;;;;GAMG;AAEH,wBAAgB,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAmB,GAAG,SAAS,CAEzE;AAED,wBAAgB,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAyB,GAAG,SAAS,CAE9E;AAED,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAE3C;AAED,wBAAgB,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC,SAAS,GAAG,MAAM,CAAC,EAAE,GAAG,UAAU,CAEnE;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,UAAU,EAAE,EACnB,SAAS,EAAE,MAAM,EACjB,cAAc,YAAgB,GAC7B,UAAU,CAOZ;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAErD"}