@tomkapa/tayto 0.5.4 → 0.7.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.
- package/dist/{chunk-74Q55TOV.js → chunk-5V4TBQ5S.js} +38 -4
- package/dist/chunk-5V4TBQ5S.js.map +1 -0
- package/dist/index.js +262 -30
- package/dist/index.js.map +1 -1
- package/dist/{tui-24ZW56Q6.js → tui-NCL4RFFD.js} +579 -215
- package/dist/tui-NCL4RFFD.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-74Q55TOV.js.map +0 -1
- package/dist/tui-24ZW56Q6.js.map +0 -1
|
@@ -8,14 +8,14 @@ import {
|
|
|
8
8
|
detectGitRemote,
|
|
9
9
|
isTerminalStatus,
|
|
10
10
|
logger
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-5V4TBQ5S.js";
|
|
12
12
|
|
|
13
13
|
// src/tui/index.tsx
|
|
14
14
|
import { render } from "ink";
|
|
15
15
|
|
|
16
16
|
// src/tui/components/App.tsx
|
|
17
|
-
import { useReducer, useEffect as
|
|
18
|
-
import { Box as
|
|
17
|
+
import { useReducer, useEffect as useEffect4, useCallback as useCallback2, useMemo as useMemo2, useState as useState7, useRef as useRef5 } from "react";
|
|
18
|
+
import { Box as Box19, Text as Text19, useInput as useInput7, useApp, useStdout as useStdout4 } from "ink";
|
|
19
19
|
|
|
20
20
|
// src/tui/types.ts
|
|
21
21
|
var ViewType = {
|
|
@@ -25,6 +25,7 @@ var ViewType = {
|
|
|
25
25
|
TaskEdit: "task-edit",
|
|
26
26
|
ProjectSelector: "project-selector",
|
|
27
27
|
ProjectCreate: "project-create",
|
|
28
|
+
ProjectEdit: "project-edit",
|
|
28
29
|
DependencyList: "dependency-list",
|
|
29
30
|
EpicPicker: "epic-picker",
|
|
30
31
|
ProjectLink: "project-link",
|
|
@@ -177,8 +178,10 @@ var initialState = {
|
|
|
177
178
|
epicSelectedIndex: 0,
|
|
178
179
|
selectedEpicIds: /* @__PURE__ */ new Set(),
|
|
179
180
|
linkingProject: null,
|
|
181
|
+
editingProject: null,
|
|
180
182
|
isEpicReordering: false,
|
|
181
|
-
epicReorderSnapshot: null
|
|
183
|
+
epicReorderSnapshot: null,
|
|
184
|
+
detectedGitRemote: null
|
|
182
185
|
};
|
|
183
186
|
function appReducer(state, action) {
|
|
184
187
|
switch (action.type) {
|
|
@@ -200,6 +203,8 @@ function appReducer(state, action) {
|
|
|
200
203
|
isSearchActive: false,
|
|
201
204
|
formData: null,
|
|
202
205
|
linkingProject: null,
|
|
206
|
+
editingProject: null,
|
|
207
|
+
detectedGitRemote: null,
|
|
203
208
|
focusedPanel: "list"
|
|
204
209
|
};
|
|
205
210
|
}
|
|
@@ -384,6 +389,10 @@ function appReducer(state, action) {
|
|
|
384
389
|
}
|
|
385
390
|
case "SET_LINKING_PROJECT":
|
|
386
391
|
return { ...state, linkingProject: action.project };
|
|
392
|
+
case "SET_EDITING_PROJECT":
|
|
393
|
+
return { ...state, editingProject: action.project };
|
|
394
|
+
case "SET_DETECTED_GIT_REMOTE":
|
|
395
|
+
return { ...state, detectedGitRemote: action.remote };
|
|
387
396
|
}
|
|
388
397
|
}
|
|
389
398
|
|
|
@@ -425,53 +434,116 @@ var Logo = React.memo(function Logo2() {
|
|
|
425
434
|
|
|
426
435
|
// src/tui/components/Header.tsx
|
|
427
436
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
428
|
-
function getKeyHints(
|
|
437
|
+
function getKeyHints(state) {
|
|
438
|
+
const { activeView, isSearchActive, isReordering, isEpicReordering, isAddingDep, focusedPanel } = state;
|
|
439
|
+
if (isAddingDep) {
|
|
440
|
+
return [
|
|
441
|
+
{ key: "type", desc: "search" },
|
|
442
|
+
{ key: "enter", desc: "confirm" },
|
|
443
|
+
{ key: "esc", desc: "cancel" }
|
|
444
|
+
];
|
|
445
|
+
}
|
|
446
|
+
const REORDER_SUFFIX = [
|
|
447
|
+
{ key: "\u2192", desc: "save" },
|
|
448
|
+
{ key: "t", desc: "top" },
|
|
449
|
+
{ key: "b", desc: "bottom" },
|
|
450
|
+
{ key: "esc/\u2190", desc: "cancel" }
|
|
451
|
+
];
|
|
452
|
+
if (isReordering) return [{ key: "\u2191/\u2193", desc: "move" }, ...REORDER_SUFFIX];
|
|
453
|
+
if (isEpicReordering) return [{ key: "\u2191/\u2193", desc: "move epic" }, ...REORDER_SUFFIX];
|
|
429
454
|
if (isSearchActive) {
|
|
430
455
|
return [
|
|
456
|
+
{ key: "type", desc: "query" },
|
|
431
457
|
{ key: "enter", desc: "apply" },
|
|
432
458
|
{ key: "esc", desc: "cancel" }
|
|
433
459
|
];
|
|
434
460
|
}
|
|
435
|
-
if (
|
|
461
|
+
if (activeView === ViewType.TaskList && focusedPanel === "epic") {
|
|
436
462
|
return [
|
|
437
463
|
{ key: "j/k", desc: "nav" },
|
|
438
464
|
{ key: "space", desc: "toggle" },
|
|
439
|
-
{ key: "\u2190", desc: "reorder" },
|
|
440
465
|
{ key: "0", desc: "clear" },
|
|
441
|
-
{ key: "
|
|
466
|
+
{ key: "\u2190", desc: "reorder" },
|
|
467
|
+
{ key: "tab/S-tab", desc: "panel" },
|
|
442
468
|
{ key: "?", desc: "help" },
|
|
443
469
|
{ key: "q", desc: "quit" }
|
|
444
470
|
];
|
|
445
471
|
}
|
|
446
|
-
if (
|
|
472
|
+
if (activeView === ViewType.TaskList && focusedPanel === "detail") {
|
|
473
|
+
return [
|
|
474
|
+
{ key: "j/k", desc: "scroll" },
|
|
475
|
+
{ key: "e", desc: "edit" },
|
|
476
|
+
{ key: "s", desc: "status" },
|
|
477
|
+
{ key: "d", desc: "del" },
|
|
478
|
+
{ key: "m", desc: "mermaid" },
|
|
479
|
+
{ key: "D", desc: "deps" },
|
|
480
|
+
{ key: "tab/S-tab", desc: "panel" },
|
|
481
|
+
{ key: "?", desc: "help" }
|
|
482
|
+
];
|
|
483
|
+
}
|
|
484
|
+
if (activeView === ViewType.TaskList) {
|
|
447
485
|
return [
|
|
448
486
|
{ key: "enter", desc: "view" },
|
|
449
487
|
{ key: "c", desc: "create" },
|
|
450
488
|
{ key: "e", desc: "edit" },
|
|
451
489
|
{ key: "d", desc: "del" },
|
|
452
490
|
{ key: "s", desc: "status" },
|
|
453
|
-
{ key: "a", desc: "assign" },
|
|
454
|
-
{ key: "A", desc: "unassign" },
|
|
491
|
+
{ key: "a/A", desc: "assign" },
|
|
455
492
|
{ key: "\u2190", desc: "reorder" },
|
|
456
493
|
{ key: "/", desc: "search" },
|
|
457
494
|
{ key: "p", desc: "project" },
|
|
458
|
-
{ key: "f", desc: "
|
|
459
|
-
{ key: "t", desc: "type-f" },
|
|
495
|
+
{ key: "f/t", desc: "filter" },
|
|
460
496
|
{ key: "PgDn/Up", desc: "page" },
|
|
461
|
-
{ key: "tab", desc: "panel" },
|
|
497
|
+
{ key: "tab/S-tab", desc: "panel" },
|
|
462
498
|
{ key: "?", desc: "help" },
|
|
463
499
|
{ key: "q", desc: "quit" }
|
|
464
500
|
];
|
|
465
501
|
}
|
|
466
|
-
if (
|
|
502
|
+
if (activeView === ViewType.TaskDetail) {
|
|
467
503
|
return [
|
|
468
504
|
{ key: "e", desc: "edit" },
|
|
469
505
|
{ key: "s", desc: "status" },
|
|
470
506
|
{ key: "d", desc: "del" },
|
|
471
507
|
{ key: "m", desc: "mermaid" },
|
|
508
|
+
{ key: "D", desc: "deps" },
|
|
509
|
+
{ key: "j/k", desc: "scroll" },
|
|
472
510
|
{ key: "esc", desc: "back" },
|
|
473
|
-
{ key: "?", desc: "help" }
|
|
474
|
-
|
|
511
|
+
{ key: "?", desc: "help" }
|
|
512
|
+
];
|
|
513
|
+
}
|
|
514
|
+
if (activeView === ViewType.DependencyList) {
|
|
515
|
+
return [
|
|
516
|
+
{ key: "a", desc: "add blocker" },
|
|
517
|
+
{ key: "x", desc: "remove" },
|
|
518
|
+
{ key: "enter", desc: "goto task" },
|
|
519
|
+
{ key: "esc", desc: "back" },
|
|
520
|
+
{ key: "?", desc: "help" }
|
|
521
|
+
];
|
|
522
|
+
}
|
|
523
|
+
if (activeView === ViewType.TaskCreate || activeView === ViewType.TaskEdit) {
|
|
524
|
+
return [
|
|
525
|
+
{ key: "\u2191\u2193/tab", desc: "navigate" },
|
|
526
|
+
{ key: "\u2190\u2192", desc: "cursor" },
|
|
527
|
+
{ key: "ctrl+s", desc: "save" },
|
|
528
|
+
{ key: "esc", desc: "cancel" }
|
|
529
|
+
];
|
|
530
|
+
}
|
|
531
|
+
if (activeView === ViewType.ProjectSelector) {
|
|
532
|
+
return [
|
|
533
|
+
{ key: "j/k", desc: "nav" },
|
|
534
|
+
{ key: "enter", desc: "select" },
|
|
535
|
+
{ key: "e", desc: "edit" },
|
|
536
|
+
{ key: "c", desc: "create" },
|
|
537
|
+
{ key: "l", desc: "link" },
|
|
538
|
+
{ key: "d", desc: "default" },
|
|
539
|
+
{ key: "esc", desc: "back" }
|
|
540
|
+
];
|
|
541
|
+
}
|
|
542
|
+
if (activeView === ViewType.EpicPicker) {
|
|
543
|
+
return [
|
|
544
|
+
{ key: "j/k", desc: "nav" },
|
|
545
|
+
{ key: "enter", desc: "select" },
|
|
546
|
+
{ key: "esc", desc: "cancel" }
|
|
475
547
|
];
|
|
476
548
|
}
|
|
477
549
|
return [
|
|
@@ -488,10 +560,10 @@ function chunkHints(hints, cols) {
|
|
|
488
560
|
}
|
|
489
561
|
return result;
|
|
490
562
|
}
|
|
491
|
-
function Header({ state }) {
|
|
563
|
+
function Header({ state, latestVersion }) {
|
|
492
564
|
const projectName = state.activeProject?.name ?? "none";
|
|
493
565
|
const taskCount = state.tasks.length;
|
|
494
|
-
const hints = getKeyHints(state
|
|
566
|
+
const hints = getKeyHints(state);
|
|
495
567
|
const hintCols = hints.length <= 7 ? 2 : hints.length <= 12 ? 3 : 4;
|
|
496
568
|
const columns = chunkHints(hints, hintCols);
|
|
497
569
|
return /* @__PURE__ */ jsxs(Box2, { flexDirection: "row", gap: 1, children: [
|
|
@@ -505,6 +577,13 @@ function Header({ state }) {
|
|
|
505
577
|
/* @__PURE__ */ jsxs(Box2, { gap: 1, children: [
|
|
506
578
|
/* @__PURE__ */ jsx2(Text2, { color: theme.fg, children: "Tasks:" }),
|
|
507
579
|
/* @__PURE__ */ jsx2(Text2, { color: theme.titleCounter, bold: true, children: taskCount })
|
|
580
|
+
] }),
|
|
581
|
+
latestVersion && /* @__PURE__ */ jsxs(Box2, { gap: 1, children: [
|
|
582
|
+
/* @__PURE__ */ jsxs(Text2, { color: theme.flash.warn, children: [
|
|
583
|
+
"Update ",
|
|
584
|
+
latestVersion
|
|
585
|
+
] }),
|
|
586
|
+
/* @__PURE__ */ jsx2(Text2, { color: theme.fg, children: "\u2014 tayto upgrade" })
|
|
508
587
|
] })
|
|
509
588
|
] }),
|
|
510
589
|
/* @__PURE__ */ jsx2(Box2, { flexGrow: 1, justifyContent: "flex-end", children: /* @__PURE__ */ jsx2(Box2, { flexDirection: "row", gap: 2, children: columns.map((col, ci) => /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", children: col.map((h) => /* @__PURE__ */ jsxs(Box2, { children: [
|
|
@@ -514,7 +593,7 @@ function Header({ state }) {
|
|
|
514
593
|
">"
|
|
515
594
|
] }),
|
|
516
595
|
/* @__PURE__ */ jsx2(Text2, { color: theme.menu.desc, children: h.desc })
|
|
517
|
-
] }, h.key)) }, ci)) }) })
|
|
596
|
+
] }, h.key)) }, col[0]?.key ?? String(ci))) }) })
|
|
518
597
|
] });
|
|
519
598
|
}
|
|
520
599
|
|
|
@@ -918,8 +997,8 @@ ${task.additionalRequirements}`;
|
|
|
918
997
|
}
|
|
919
998
|
|
|
920
999
|
// src/tui/components/TaskForm.tsx
|
|
921
|
-
import { useState as useState2, useCallback } from "react";
|
|
922
|
-
import { Box as Box9, Text as Text9, useInput as useInput2 } from "ink";
|
|
1000
|
+
import { useState as useState2, useCallback, useEffect, useRef } from "react";
|
|
1001
|
+
import { Box as Box9, Text as Text9, useInput as useInput2, useStdin } from "ink";
|
|
923
1002
|
|
|
924
1003
|
// src/tui/editor.ts
|
|
925
1004
|
import { writeFileSync as writeFileSync2, readFileSync, unlinkSync, mkdtempSync as mkdtempSync2 } from "fs";
|
|
@@ -929,15 +1008,17 @@ import { spawnSync } from "child_process";
|
|
|
929
1008
|
function getEditor() {
|
|
930
1009
|
return process.env["EDITOR"] ?? process.env["VISUAL"] ?? "vi";
|
|
931
1010
|
}
|
|
932
|
-
function openInEditor(content, filename) {
|
|
1011
|
+
function openInEditor(content, filename, options) {
|
|
933
1012
|
const dir = mkdtempSync2(join2(tmpdir2(), "task-"));
|
|
934
1013
|
const filepath = join2(dir, filename);
|
|
935
1014
|
writeFileSync2(filepath, content, "utf-8");
|
|
936
1015
|
const editor = getEditor();
|
|
1016
|
+
options?.beforeOpen?.();
|
|
937
1017
|
const result = spawnSync(editor, [filepath], {
|
|
938
1018
|
stdio: "inherit",
|
|
939
1019
|
shell: true
|
|
940
1020
|
});
|
|
1021
|
+
options?.afterOpen?.();
|
|
941
1022
|
if (result.status !== 0) {
|
|
942
1023
|
try {
|
|
943
1024
|
unlinkSync(filepath);
|
|
@@ -1154,7 +1235,7 @@ function TaskPicker({ tasks, excludeIds, initialSelection, onConfirm, onCancel }
|
|
|
1154
1235
|
}
|
|
1155
1236
|
|
|
1156
1237
|
// src/tui/components/TaskForm.tsx
|
|
1157
|
-
import { jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1238
|
+
import { Fragment as Fragment2, jsx as jsx9, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1158
1239
|
var FIELDS = [
|
|
1159
1240
|
{ label: "Name", key: "name", type: "inline" },
|
|
1160
1241
|
{ label: "Type", key: "type", type: "select", options: TYPE_VALUES },
|
|
@@ -1184,23 +1265,42 @@ function TaskForm({ editingTask, allTasks, initialDeps, onSave, onCancel }) {
|
|
|
1184
1265
|
technicalNotes: editingTask?.technicalNotes ?? "",
|
|
1185
1266
|
additionalRequirements: editingTask?.additionalRequirements ?? ""
|
|
1186
1267
|
});
|
|
1268
|
+
const [cursorPos, setCursorPos] = useState2(() => (editingTask?.name ?? "").length);
|
|
1269
|
+
const cursorRef = useRef(cursorPos);
|
|
1270
|
+
cursorRef.current = cursorPos;
|
|
1187
1271
|
const [editorActive, setEditorActive] = useState2(false);
|
|
1188
1272
|
const [pickerActive, setPickerActive] = useState2(false);
|
|
1189
1273
|
const [pickedDeps, setPickedDeps] = useState2(initialDeps ?? []);
|
|
1274
|
+
const { setRawMode } = useStdin();
|
|
1275
|
+
useEffect(() => {
|
|
1276
|
+
const field2 = FIELDS[focusIndex];
|
|
1277
|
+
if (field2?.type === "inline") {
|
|
1278
|
+
const pos = values[field2.key]?.length ?? 0;
|
|
1279
|
+
setCursorPos(pos);
|
|
1280
|
+
cursorRef.current = pos;
|
|
1281
|
+
}
|
|
1282
|
+
}, [focusIndex]);
|
|
1190
1283
|
const currentField = FIELDS[focusIndex];
|
|
1191
1284
|
const launchEditor = useCallback(
|
|
1192
1285
|
(field2) => {
|
|
1193
1286
|
setEditorActive(true);
|
|
1194
1287
|
setTimeout(() => {
|
|
1195
1288
|
const content = values[field2.key] ?? "";
|
|
1196
|
-
const result = openInEditor(content, field2.editorFilename ?? `${field2.key}.md
|
|
1289
|
+
const result = openInEditor(content, field2.editorFilename ?? `${field2.key}.md`, {
|
|
1290
|
+
beforeOpen: () => {
|
|
1291
|
+
setRawMode(false);
|
|
1292
|
+
},
|
|
1293
|
+
afterOpen: () => {
|
|
1294
|
+
setRawMode(true);
|
|
1295
|
+
}
|
|
1296
|
+
});
|
|
1197
1297
|
if (result !== null) {
|
|
1198
1298
|
setValues((v) => ({ ...v, [field2.key]: result }));
|
|
1199
1299
|
}
|
|
1200
1300
|
setEditorActive(false);
|
|
1201
1301
|
}, 50);
|
|
1202
1302
|
},
|
|
1203
|
-
[values]
|
|
1303
|
+
[values, setRawMode]
|
|
1204
1304
|
);
|
|
1205
1305
|
const handlePickerConfirm = useCallback((selected) => {
|
|
1206
1306
|
setPickedDeps(selected);
|
|
@@ -1240,32 +1340,49 @@ function TaskForm({ editingTask, allTasks, initialDeps, onSave, onCancel }) {
|
|
|
1240
1340
|
}
|
|
1241
1341
|
return;
|
|
1242
1342
|
}
|
|
1343
|
+
if (key.upArrow) {
|
|
1344
|
+
setFocusIndex((i) => Math.max(0, i - 1));
|
|
1345
|
+
return;
|
|
1346
|
+
}
|
|
1347
|
+
if (key.downArrow) {
|
|
1348
|
+
setFocusIndex((i) => Math.min(FIELDS.length - 1, i + 1));
|
|
1349
|
+
return;
|
|
1350
|
+
}
|
|
1243
1351
|
if (currentField.type === "inline") {
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1352
|
+
if (key.leftArrow) {
|
|
1353
|
+
setCursorPos((p) => Math.max(0, p - 1));
|
|
1354
|
+
} else if (key.rightArrow) {
|
|
1355
|
+
setCursorPos((p) => Math.min((values[currentField.key] ?? "").length, p + 1));
|
|
1356
|
+
} else if (key.backspace || key.delete) {
|
|
1357
|
+
const pos = cursorRef.current;
|
|
1358
|
+
if (pos > 0) {
|
|
1359
|
+
setValues((v) => {
|
|
1360
|
+
const cur = v[currentField.key] ?? "";
|
|
1361
|
+
return { ...v, [currentField.key]: cur.slice(0, pos - 1) + cur.slice(pos) };
|
|
1362
|
+
});
|
|
1363
|
+
cursorRef.current = pos - 1;
|
|
1364
|
+
setCursorPos(pos - 1);
|
|
1365
|
+
}
|
|
1247
1366
|
} else if (key.return) {
|
|
1248
1367
|
setFocusIndex((i) => Math.min(FIELDS.length - 1, i + 1));
|
|
1249
1368
|
} else if (input && !key.ctrl && !key.meta) {
|
|
1250
|
-
|
|
1369
|
+
const pos = cursorRef.current;
|
|
1370
|
+
setValues((v) => {
|
|
1371
|
+
const cur = v[currentField.key] ?? "";
|
|
1372
|
+
return { ...v, [currentField.key]: cur.slice(0, pos) + input + cur.slice(pos) };
|
|
1373
|
+
});
|
|
1374
|
+
cursorRef.current = pos + input.length;
|
|
1375
|
+
setCursorPos(pos + input.length);
|
|
1251
1376
|
}
|
|
1252
1377
|
}
|
|
1253
1378
|
if (currentField.type === "picker") {
|
|
1254
1379
|
if (key.return) {
|
|
1255
1380
|
setPickerActive(true);
|
|
1256
|
-
} else if (key.downArrow) {
|
|
1257
|
-
setFocusIndex((i) => Math.min(FIELDS.length - 1, i + 1));
|
|
1258
|
-
} else if (key.upArrow) {
|
|
1259
|
-
setFocusIndex((i) => Math.max(0, i - 1));
|
|
1260
1381
|
}
|
|
1261
1382
|
}
|
|
1262
1383
|
if (currentField.type === "editor") {
|
|
1263
1384
|
if (key.return) {
|
|
1264
1385
|
launchEditor(currentField);
|
|
1265
|
-
} else if (key.downArrow) {
|
|
1266
|
-
setFocusIndex((i) => Math.min(FIELDS.length - 1, i + 1));
|
|
1267
|
-
} else if (key.upArrow) {
|
|
1268
|
-
setFocusIndex((i) => Math.max(0, i - 1));
|
|
1269
1386
|
}
|
|
1270
1387
|
}
|
|
1271
1388
|
if (currentField.type === "select") {
|
|
@@ -1306,37 +1423,37 @@ function TaskForm({ editingTask, allTasks, initialDeps, onSave, onCancel }) {
|
|
|
1306
1423
|
/* @__PURE__ */ jsx9(Box9, { flexDirection: "column", paddingX: 1, paddingY: 0, children: FIELDS.map((field2, i) => {
|
|
1307
1424
|
const isFocused = i === focusIndex;
|
|
1308
1425
|
const value = field2.key === "dependsOn" ? depSummary : values[field2.key] ?? "";
|
|
1309
|
-
const displayValue = value;
|
|
1310
1426
|
return /* @__PURE__ */ jsxs6(Box9, { gap: 1, children: [
|
|
1311
1427
|
/* @__PURE__ */ jsxs6(Text9, { color: isFocused ? theme.dialog.label : theme.yaml.key, bold: isFocused, children: [
|
|
1312
1428
|
isFocused ? ">" : " ",
|
|
1313
1429
|
" ",
|
|
1314
1430
|
field2.label.padEnd(14)
|
|
1315
1431
|
] }),
|
|
1316
|
-
field2.type === "inline" && /* @__PURE__ */
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1432
|
+
field2.type === "inline" && /* @__PURE__ */ jsx9(Text9, { color: isFocused ? theme.yaml.value : theme.table.fg, children: isFocused ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
1433
|
+
value.slice(0, cursorPos),
|
|
1434
|
+
/* @__PURE__ */ jsx9(Text9, { color: theme.titleHighlight, children: "_" }),
|
|
1435
|
+
value.slice(cursorPos)
|
|
1436
|
+
] }) : value }),
|
|
1320
1437
|
field2.type === "picker" && /* @__PURE__ */ jsxs6(Text9, { children: [
|
|
1321
|
-
|
|
1438
|
+
value ? /* @__PURE__ */ jsx9(Text9, { color: theme.status.added, children: value.length > 60 ? value.slice(0, 60) + "..." : value }) : /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: isFocused ? "press enter to select" : "none" }),
|
|
1322
1439
|
isFocused && /* @__PURE__ */ jsx9(Text9, { color: theme.menu.key, children: " [enter: open picker]" })
|
|
1323
1440
|
] }),
|
|
1324
1441
|
field2.type === "editor" && /* @__PURE__ */ jsxs6(Text9, { children: [
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1442
|
+
value ? /* @__PURE__ */ jsxs6(Text9, { color: theme.status.added, children: [
|
|
1443
|
+
value.split("\n")[0]?.slice(0, 50),
|
|
1444
|
+
value.length > 50 || value.includes("\n") ? "..." : ""
|
|
1328
1445
|
] }) : /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: isFocused ? "press enter" : "empty" }),
|
|
1329
1446
|
isFocused && /* @__PURE__ */ jsx9(Text9, { color: theme.menu.key, children: " [enter: $EDITOR]" })
|
|
1330
1447
|
] }),
|
|
1331
1448
|
field2.type === "select" && /* @__PURE__ */ jsxs6(Text9, { color: isFocused ? theme.yaml.value : theme.table.fg, children: [
|
|
1332
1449
|
isFocused ? "< " : " ",
|
|
1333
|
-
|
|
1450
|
+
value,
|
|
1334
1451
|
isFocused ? " >" : ""
|
|
1335
1452
|
] })
|
|
1336
1453
|
] }, field2.key);
|
|
1337
1454
|
}) }),
|
|
1338
1455
|
/* @__PURE__ */ jsx9(Box9, { flexGrow: 1 }),
|
|
1339
|
-
/* @__PURE__ */ jsx9(Box9, { paddingX: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "tab:
|
|
1456
|
+
/* @__PURE__ */ jsx9(Box9, { paddingX: 1, children: /* @__PURE__ */ jsx9(Text9, { dimColor: true, children: "\u2191\u2193/tab: navigate | \u2190\u2192: cursor | ctrl+s: save | esc: cancel" }) }),
|
|
1340
1457
|
editorActive && /* @__PURE__ */ jsx9(Box9, { paddingX: 1, children: /* @__PURE__ */ jsx9(Text9, { color: theme.flash.warn, bold: true, children: "Editor open... save and close to return" }) })
|
|
1341
1458
|
] });
|
|
1342
1459
|
}
|
|
@@ -1350,6 +1467,7 @@ function ProjectSelector({
|
|
|
1350
1467
|
activeProject,
|
|
1351
1468
|
onSelect,
|
|
1352
1469
|
onCreate,
|
|
1470
|
+
onEdit,
|
|
1353
1471
|
onSetDefault,
|
|
1354
1472
|
onLink,
|
|
1355
1473
|
onCancel
|
|
@@ -1375,6 +1493,13 @@ function ProjectSelector({
|
|
|
1375
1493
|
onCreate();
|
|
1376
1494
|
return;
|
|
1377
1495
|
}
|
|
1496
|
+
if (input === "e") {
|
|
1497
|
+
const project = projects[selectedIndex];
|
|
1498
|
+
if (project) {
|
|
1499
|
+
onEdit(project);
|
|
1500
|
+
}
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1378
1503
|
if (input === "d") {
|
|
1379
1504
|
const project = projects[selectedIndex];
|
|
1380
1505
|
if (project) {
|
|
@@ -1419,7 +1544,7 @@ function ProjectSelector({
|
|
|
1419
1544
|
const activeMarker = isActive ? "*" : " ";
|
|
1420
1545
|
const defaultMarker = project.isDefault ? "D" : " ";
|
|
1421
1546
|
const marker = `${activeMarker}${defaultMarker}`;
|
|
1422
|
-
const remoteDisplay = (project.gitRemote ?? "").slice(0, 38).padEnd(40);
|
|
1547
|
+
const remoteDisplay = (project.gitRemote?.value ?? "").slice(0, 38).padEnd(40);
|
|
1423
1548
|
if (isSelected) {
|
|
1424
1549
|
return /* @__PURE__ */ jsx10(Box10, { paddingX: 1, children: /* @__PURE__ */ jsxs7(Text10, { backgroundColor: theme.table.cursorBg, color: theme.table.cursorFg, bold: true, children: [
|
|
1425
1550
|
marker,
|
|
@@ -1440,28 +1565,53 @@ function ProjectSelector({
|
|
|
1440
1565
|
] }, project.id);
|
|
1441
1566
|
}),
|
|
1442
1567
|
/* @__PURE__ */ jsx10(Box10, { flexGrow: 1 }),
|
|
1443
|
-
/* @__PURE__ */ jsx10(Box10, { paddingX: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "enter: select | d: set default | l: link git | c: create | esc: back" }) })
|
|
1568
|
+
/* @__PURE__ */ jsx10(Box10, { paddingX: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "enter: select | e: edit | d: set default | l: link git | c: create | esc: back" }) })
|
|
1444
1569
|
] });
|
|
1445
1570
|
}
|
|
1446
1571
|
|
|
1447
1572
|
// src/tui/components/ProjectForm.tsx
|
|
1448
|
-
import { useState as useState4 } from "react";
|
|
1573
|
+
import { useState as useState4, useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
1449
1574
|
import { Box as Box11, Text as Text11, useInput as useInput4 } from "ink";
|
|
1450
|
-
import { jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1575
|
+
import { Fragment as Fragment3, jsx as jsx11, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1451
1576
|
var FIELDS2 = [
|
|
1452
1577
|
{ label: "Name", key: "name", type: "inline" },
|
|
1453
1578
|
{ label: "Key", key: "key", type: "inline" },
|
|
1454
1579
|
{ label: "Description", key: "description", type: "inline" },
|
|
1580
|
+
{ label: "Git Remote", key: "gitRemote", type: "inline" },
|
|
1455
1581
|
{ label: "Default", key: "isDefault", type: "toggle" }
|
|
1456
1582
|
];
|
|
1457
|
-
function ProjectForm({ onSave, onCancel }) {
|
|
1583
|
+
function ProjectForm({ editingProject, initialGitRemote, onSave, onCancel }) {
|
|
1584
|
+
const isEditing = !!editingProject;
|
|
1458
1585
|
const [focusIndex, setFocusIndex] = useState4(0);
|
|
1459
|
-
const [values, setValues] = useState4({
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1586
|
+
const [values, setValues] = useState4(() => {
|
|
1587
|
+
if (editingProject) {
|
|
1588
|
+
return {
|
|
1589
|
+
name: editingProject.name,
|
|
1590
|
+
key: editingProject.key,
|
|
1591
|
+
description: editingProject.description,
|
|
1592
|
+
gitRemote: editingProject.gitRemote?.value ?? "",
|
|
1593
|
+
isDefault: editingProject.isDefault ? "yes" : "no"
|
|
1594
|
+
};
|
|
1595
|
+
}
|
|
1596
|
+
return {
|
|
1597
|
+
name: "",
|
|
1598
|
+
key: "",
|
|
1599
|
+
description: "",
|
|
1600
|
+
gitRemote: initialGitRemote?.value ?? "",
|
|
1601
|
+
isDefault: "no"
|
|
1602
|
+
};
|
|
1464
1603
|
});
|
|
1604
|
+
const [cursorPos, setCursorPos] = useState4(0);
|
|
1605
|
+
const cursorRef = useRef2(cursorPos);
|
|
1606
|
+
cursorRef.current = cursorPos;
|
|
1607
|
+
useEffect2(() => {
|
|
1608
|
+
const field2 = FIELDS2[focusIndex];
|
|
1609
|
+
if (field2?.type === "inline") {
|
|
1610
|
+
const pos = values[field2.key]?.length ?? 0;
|
|
1611
|
+
setCursorPos(pos);
|
|
1612
|
+
cursorRef.current = pos;
|
|
1613
|
+
}
|
|
1614
|
+
}, [focusIndex]);
|
|
1465
1615
|
const currentField = FIELDS2[focusIndex];
|
|
1466
1616
|
useInput4((input, key) => {
|
|
1467
1617
|
if (key.escape) {
|
|
@@ -1484,19 +1634,46 @@ function ProjectForm({ onSave, onCancel }) {
|
|
|
1484
1634
|
name: nameVal,
|
|
1485
1635
|
key: values["key"] ?? "",
|
|
1486
1636
|
description: values["description"] ?? "",
|
|
1637
|
+
gitRemote: values["gitRemote"] ?? "",
|
|
1487
1638
|
isDefault: values["isDefault"] === "yes"
|
|
1488
1639
|
});
|
|
1489
1640
|
}
|
|
1490
1641
|
return;
|
|
1491
1642
|
}
|
|
1492
|
-
if (
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1643
|
+
if (key.upArrow) {
|
|
1644
|
+
setFocusIndex((i) => Math.max(0, i - 1));
|
|
1645
|
+
return;
|
|
1646
|
+
}
|
|
1647
|
+
if (key.downArrow) {
|
|
1648
|
+
setFocusIndex((i) => Math.min(FIELDS2.length - 1, i + 1));
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
const isReadOnly = isEditing && currentField.key === "key";
|
|
1652
|
+
if (currentField.type === "inline" && !isReadOnly) {
|
|
1653
|
+
if (key.leftArrow) {
|
|
1654
|
+
setCursorPos((p) => Math.max(0, p - 1));
|
|
1655
|
+
} else if (key.rightArrow) {
|
|
1656
|
+
setCursorPos((p) => Math.min((values[currentField.key] ?? "").length, p + 1));
|
|
1657
|
+
} else if (key.backspace || key.delete) {
|
|
1658
|
+
const pos = cursorRef.current;
|
|
1659
|
+
if (pos > 0) {
|
|
1660
|
+
setValues((v) => {
|
|
1661
|
+
const cur = v[currentField.key] ?? "";
|
|
1662
|
+
return { ...v, [currentField.key]: cur.slice(0, pos - 1) + cur.slice(pos) };
|
|
1663
|
+
});
|
|
1664
|
+
cursorRef.current = pos - 1;
|
|
1665
|
+
setCursorPos(pos - 1);
|
|
1666
|
+
}
|
|
1496
1667
|
} else if (key.return) {
|
|
1497
1668
|
setFocusIndex((i) => Math.min(FIELDS2.length - 1, i + 1));
|
|
1498
1669
|
} else if (input && !key.ctrl && !key.meta) {
|
|
1499
|
-
|
|
1670
|
+
const pos = cursorRef.current;
|
|
1671
|
+
setValues((v) => {
|
|
1672
|
+
const cur = v[currentField.key] ?? "";
|
|
1673
|
+
return { ...v, [currentField.key]: cur.slice(0, pos) + input + cur.slice(pos) };
|
|
1674
|
+
});
|
|
1675
|
+
cursorRef.current = pos + input.length;
|
|
1676
|
+
setCursorPos(pos + input.length);
|
|
1500
1677
|
}
|
|
1501
1678
|
}
|
|
1502
1679
|
if (currentField.type === "toggle") {
|
|
@@ -1511,7 +1688,7 @@ function ProjectForm({ onSave, onCancel }) {
|
|
|
1511
1688
|
return /* @__PURE__ */ jsxs8(Box11, { flexDirection: "column", flexGrow: 1, borderStyle: "bold", borderColor: theme.borderFocus, children: [
|
|
1512
1689
|
/* @__PURE__ */ jsx11(Box11, { gap: 0, children: /* @__PURE__ */ jsxs8(Text11, { color: theme.title, bold: true, children: [
|
|
1513
1690
|
" ",
|
|
1514
|
-
"new project"
|
|
1691
|
+
isEditing ? "edit project" : "new project"
|
|
1515
1692
|
] }) }),
|
|
1516
1693
|
/* @__PURE__ */ jsx11(Box11, { flexDirection: "column", paddingX: 1, paddingY: 0, children: FIELDS2.map((field2, i) => {
|
|
1517
1694
|
const isFocused = i === focusIndex;
|
|
@@ -1523,9 +1700,13 @@ function ProjectForm({ onSave, onCancel }) {
|
|
|
1523
1700
|
field2.label.padEnd(14)
|
|
1524
1701
|
] }),
|
|
1525
1702
|
field2.type === "inline" && /* @__PURE__ */ jsxs8(Text11, { color: isFocused ? theme.yaml.value : theme.table.fg, children: [
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1703
|
+
isFocused ? /* @__PURE__ */ jsxs8(Fragment3, { children: [
|
|
1704
|
+
value.slice(0, cursorPos),
|
|
1705
|
+
/* @__PURE__ */ jsx11(Text11, { color: theme.titleHighlight, children: "_" }),
|
|
1706
|
+
value.slice(cursorPos)
|
|
1707
|
+
] }) : value,
|
|
1708
|
+
field2.key === "key" && !value && !isEditing && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: isFocused ? " (auto from name)" : "" }),
|
|
1709
|
+
field2.key === "key" && isEditing && isFocused && /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: " (read-only)" })
|
|
1529
1710
|
] }),
|
|
1530
1711
|
field2.type === "toggle" && /* @__PURE__ */ jsxs8(Text11, { color: isFocused ? theme.yaml.value : theme.table.fg, children: [
|
|
1531
1712
|
isFocused ? "< " : " ",
|
|
@@ -1535,16 +1716,19 @@ function ProjectForm({ onSave, onCancel }) {
|
|
|
1535
1716
|
] }, field2.key);
|
|
1536
1717
|
}) }),
|
|
1537
1718
|
/* @__PURE__ */ jsx11(Box11, { flexGrow: 1 }),
|
|
1538
|
-
/* @__PURE__ */ jsx11(Box11, { paddingX: 1, children: /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "tab:
|
|
1719
|
+
/* @__PURE__ */ jsx11(Box11, { paddingX: 1, children: /* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "\u2191\u2193/tab: navigate | \u2190\u2192: cursor | ctrl+s: save | esc: cancel" }) })
|
|
1539
1720
|
] });
|
|
1540
1721
|
}
|
|
1541
1722
|
|
|
1542
1723
|
// src/tui/components/ProjectLinkForm.tsx
|
|
1543
|
-
import { useState as useState5 } from "react";
|
|
1724
|
+
import { useState as useState5, useRef as useRef3 } from "react";
|
|
1544
1725
|
import { Box as Box12, Text as Text12, useInput as useInput5 } from "ink";
|
|
1545
1726
|
import { jsx as jsx12, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1546
1727
|
function ProjectLinkForm({ project, onSave, onUnlink, onDetect, onCancel }) {
|
|
1547
|
-
const [remoteUrl, setRemoteUrl] = useState5(project.gitRemote ?? "");
|
|
1728
|
+
const [remoteUrl, setRemoteUrl] = useState5(project.gitRemote?.value ?? "");
|
|
1729
|
+
const [cursorPos, setCursorPos] = useState5(() => (project.gitRemote?.value ?? "").length);
|
|
1730
|
+
const cursorRef = useRef3(cursorPos);
|
|
1731
|
+
cursorRef.current = cursorPos;
|
|
1548
1732
|
useInput5((input, key) => {
|
|
1549
1733
|
if (key.escape) {
|
|
1550
1734
|
onCancel();
|
|
@@ -1561,6 +1745,8 @@ function ProjectLinkForm({ project, onSave, onUnlink, onDetect, onCancel }) {
|
|
|
1561
1745
|
const detected = onDetect();
|
|
1562
1746
|
if (detected) {
|
|
1563
1747
|
setRemoteUrl(detected);
|
|
1748
|
+
cursorRef.current = detected.length;
|
|
1749
|
+
setCursorPos(detected.length);
|
|
1564
1750
|
}
|
|
1565
1751
|
return;
|
|
1566
1752
|
}
|
|
@@ -1570,12 +1756,28 @@ function ProjectLinkForm({ project, onSave, onUnlink, onDetect, onCancel }) {
|
|
|
1570
1756
|
}
|
|
1571
1757
|
return;
|
|
1572
1758
|
}
|
|
1759
|
+
if (key.leftArrow) {
|
|
1760
|
+
setCursorPos((p) => Math.max(0, p - 1));
|
|
1761
|
+
return;
|
|
1762
|
+
}
|
|
1763
|
+
if (key.rightArrow) {
|
|
1764
|
+
setCursorPos((p) => Math.min(remoteUrl.length, p + 1));
|
|
1765
|
+
return;
|
|
1766
|
+
}
|
|
1573
1767
|
if (key.backspace || key.delete) {
|
|
1574
|
-
|
|
1768
|
+
const pos = cursorRef.current;
|
|
1769
|
+
if (pos > 0) {
|
|
1770
|
+
setRemoteUrl((v) => v.slice(0, pos - 1) + v.slice(pos));
|
|
1771
|
+
cursorRef.current = pos - 1;
|
|
1772
|
+
setCursorPos(pos - 1);
|
|
1773
|
+
}
|
|
1575
1774
|
return;
|
|
1576
1775
|
}
|
|
1577
1776
|
if (input && !key.ctrl && !key.meta) {
|
|
1578
|
-
|
|
1777
|
+
const pos = cursorRef.current;
|
|
1778
|
+
setRemoteUrl((v) => v.slice(0, pos) + input + v.slice(pos));
|
|
1779
|
+
cursorRef.current = pos + input.length;
|
|
1780
|
+
setCursorPos(pos + input.length);
|
|
1579
1781
|
}
|
|
1580
1782
|
});
|
|
1581
1783
|
return /* @__PURE__ */ jsxs9(Box12, { flexDirection: "column", flexGrow: 1, borderStyle: "bold", borderColor: theme.borderFocus, children: [
|
|
@@ -1599,15 +1801,16 @@ function ProjectLinkForm({ project, onSave, onUnlink, onDetect, onCancel }) {
|
|
|
1599
1801
|
{
|
|
1600
1802
|
color: project.gitRemote ? theme.yaml.value : theme.table.fg,
|
|
1601
1803
|
dimColor: !project.gitRemote,
|
|
1602
|
-
children: project.gitRemote ?? "(none)"
|
|
1804
|
+
children: project.gitRemote?.value ?? "(none)"
|
|
1603
1805
|
}
|
|
1604
1806
|
)
|
|
1605
1807
|
] }),
|
|
1606
1808
|
/* @__PURE__ */ jsxs9(Box12, { gap: 1, marginTop: 1, children: [
|
|
1607
1809
|
/* @__PURE__ */ jsx12(Text12, { color: theme.dialog.label, bold: true, children: "Remote URL: " }),
|
|
1608
1810
|
/* @__PURE__ */ jsxs9(Text12, { color: theme.yaml.value, children: [
|
|
1609
|
-
remoteUrl,
|
|
1610
|
-
/* @__PURE__ */ jsx12(Text12, { color: theme.titleHighlight, children: "_" })
|
|
1811
|
+
remoteUrl.slice(0, cursorPos),
|
|
1812
|
+
/* @__PURE__ */ jsx12(Text12, { color: theme.titleHighlight, children: "_" }),
|
|
1813
|
+
remoteUrl.slice(cursorPos)
|
|
1611
1814
|
] })
|
|
1612
1815
|
] })
|
|
1613
1816
|
] }),
|
|
@@ -1616,18 +1819,51 @@ function ProjectLinkForm({ project, onSave, onUnlink, onDetect, onCancel }) {
|
|
|
1616
1819
|
] });
|
|
1617
1820
|
}
|
|
1618
1821
|
|
|
1822
|
+
// src/utils/dismissed-remotes.ts
|
|
1823
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
|
|
1824
|
+
function isDismissedRemote(filePath, remote) {
|
|
1825
|
+
try {
|
|
1826
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1827
|
+
const list = JSON.parse(content);
|
|
1828
|
+
if (!Array.isArray(list)) return false;
|
|
1829
|
+
return list.includes(remote.value);
|
|
1830
|
+
} catch {
|
|
1831
|
+
return false;
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
function dismissRemote(filePath, remote) {
|
|
1835
|
+
let list = [];
|
|
1836
|
+
try {
|
|
1837
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1838
|
+
const parsed = JSON.parse(content);
|
|
1839
|
+
if (Array.isArray(parsed)) {
|
|
1840
|
+
list = parsed.filter((v) => typeof v === "string");
|
|
1841
|
+
}
|
|
1842
|
+
} catch {
|
|
1843
|
+
}
|
|
1844
|
+
if (list.includes(remote.value)) return;
|
|
1845
|
+
list.push(remote.value);
|
|
1846
|
+
try {
|
|
1847
|
+
writeFileSync3(filePath, JSON.stringify(list), "utf-8");
|
|
1848
|
+
logger.info(`dismissRemote: persisted ${remote.value} to ${filePath}`);
|
|
1849
|
+
} catch (e) {
|
|
1850
|
+
logger.error(`dismissRemote: failed to write ${filePath}`, e instanceof Error ? e : new Error(String(e)));
|
|
1851
|
+
}
|
|
1852
|
+
}
|
|
1853
|
+
|
|
1619
1854
|
// src/tui/components/HelpOverlay.tsx
|
|
1620
1855
|
import { Box as Box13, Text as Text13 } from "ink";
|
|
1621
1856
|
import { jsx as jsx13, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1622
|
-
var
|
|
1857
|
+
var ROW1 = [
|
|
1623
1858
|
{
|
|
1624
1859
|
title: "NAVIGATION",
|
|
1625
1860
|
keys: [
|
|
1626
1861
|
["j/k", "Up/Down"],
|
|
1627
1862
|
["g/G", "Top/Bottom"],
|
|
1628
|
-
["PgDn", "Page
|
|
1629
|
-
["
|
|
1630
|
-
["
|
|
1863
|
+
["PgDn/Up", "Page"],
|
|
1864
|
+
["tab", "Next panel"],
|
|
1865
|
+
["S-tab", "Prev panel"],
|
|
1866
|
+
["enter", "View/select"],
|
|
1631
1867
|
["esc", "Back"]
|
|
1632
1868
|
]
|
|
1633
1869
|
},
|
|
@@ -1638,14 +1874,16 @@ var SECTIONS = [
|
|
|
1638
1874
|
["e", "Edit"],
|
|
1639
1875
|
["d", "Delete"],
|
|
1640
1876
|
["s", "Status cycle"],
|
|
1641
|
-
["
|
|
1877
|
+
["a/A", "Assign/unassign"],
|
|
1878
|
+
["D", "Dependencies"],
|
|
1879
|
+
["m", "Mermaid"]
|
|
1642
1880
|
]
|
|
1643
1881
|
},
|
|
1644
1882
|
{
|
|
1645
1883
|
title: "REORDER",
|
|
1646
1884
|
keys: [
|
|
1647
1885
|
["\u2190", "Enter reorder"],
|
|
1648
|
-
["\u2191\u2193", "Move
|
|
1886
|
+
["\u2191\u2193", "Move item"],
|
|
1649
1887
|
["t", "Jump to top"],
|
|
1650
1888
|
["b", "Jump to bottom"],
|
|
1651
1889
|
["\u2192", "Save position"],
|
|
@@ -1660,6 +1898,17 @@ var SECTIONS = [
|
|
|
1660
1898
|
["t", "Type filter"],
|
|
1661
1899
|
["0", "Clear filters"]
|
|
1662
1900
|
]
|
|
1901
|
+
}
|
|
1902
|
+
];
|
|
1903
|
+
var ROW2 = [
|
|
1904
|
+
{
|
|
1905
|
+
title: "EPIC PANEL",
|
|
1906
|
+
keys: [
|
|
1907
|
+
["j/k", "Navigate"],
|
|
1908
|
+
["space", "Toggle filter"],
|
|
1909
|
+
["0", "Clear filter"],
|
|
1910
|
+
["\u2190", "Reorder epics"]
|
|
1911
|
+
]
|
|
1663
1912
|
},
|
|
1664
1913
|
{
|
|
1665
1914
|
title: "DEPS VIEW",
|
|
@@ -1670,6 +1919,16 @@ var SECTIONS = [
|
|
|
1670
1919
|
["esc", "Back"]
|
|
1671
1920
|
]
|
|
1672
1921
|
},
|
|
1922
|
+
{
|
|
1923
|
+
title: "FORMS",
|
|
1924
|
+
keys: [
|
|
1925
|
+
["\u2191\u2193/tab", "Navigate fields"],
|
|
1926
|
+
["\u2190\u2192", "Move cursor"],
|
|
1927
|
+
["ctrl+s", "Save"],
|
|
1928
|
+
["enter", "Open editor / next"],
|
|
1929
|
+
["esc", "Cancel"]
|
|
1930
|
+
]
|
|
1931
|
+
},
|
|
1673
1932
|
{
|
|
1674
1933
|
title: "GENERAL",
|
|
1675
1934
|
keys: [
|
|
@@ -1679,6 +1938,19 @@ var SECTIONS = [
|
|
|
1679
1938
|
]
|
|
1680
1939
|
}
|
|
1681
1940
|
];
|
|
1941
|
+
function SectionRow({ sections }) {
|
|
1942
|
+
return /* @__PURE__ */ jsx13(Box13, { flexDirection: "row", gap: 4, children: sections.map((section) => /* @__PURE__ */ jsxs10(Box13, { flexDirection: "column", children: [
|
|
1943
|
+
/* @__PURE__ */ jsx13(Text13, { color: theme.table.headerFg, bold: true, children: section.title }),
|
|
1944
|
+
section.keys.map(([key, desc]) => /* @__PURE__ */ jsxs10(Box13, { gap: 1, children: [
|
|
1945
|
+
/* @__PURE__ */ jsxs10(Text13, { color: theme.menu.key, bold: true, children: [
|
|
1946
|
+
"<",
|
|
1947
|
+
key.padEnd(5),
|
|
1948
|
+
">"
|
|
1949
|
+
] }),
|
|
1950
|
+
/* @__PURE__ */ jsx13(Text13, { dimColor: true, children: desc })
|
|
1951
|
+
] }, key))
|
|
1952
|
+
] }, section.title)) });
|
|
1953
|
+
}
|
|
1682
1954
|
function HelpOverlay() {
|
|
1683
1955
|
return /* @__PURE__ */ jsxs10(
|
|
1684
1956
|
Box13,
|
|
@@ -1694,17 +1966,10 @@ function HelpOverlay() {
|
|
|
1694
1966
|
"Help"
|
|
1695
1967
|
] }),
|
|
1696
1968
|
/* @__PURE__ */ jsx13(Text13, { children: " " }),
|
|
1697
|
-
/* @__PURE__ */
|
|
1698
|
-
/* @__PURE__ */ jsx13(
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
"<",
|
|
1702
|
-
(key ?? "").padEnd(5),
|
|
1703
|
-
">"
|
|
1704
|
-
] }),
|
|
1705
|
-
/* @__PURE__ */ jsx13(Text13, { dimColor: true, children: desc })
|
|
1706
|
-
] }, key))
|
|
1707
|
-
] }, section.title)) }),
|
|
1969
|
+
/* @__PURE__ */ jsxs10(Box13, { flexDirection: "column", gap: 1, children: [
|
|
1970
|
+
/* @__PURE__ */ jsx13(SectionRow, { sections: ROW1 }),
|
|
1971
|
+
/* @__PURE__ */ jsx13(SectionRow, { sections: ROW2 })
|
|
1972
|
+
] }),
|
|
1708
1973
|
/* @__PURE__ */ jsx13(Text13, { children: " " }),
|
|
1709
1974
|
/* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Press any key to close" })
|
|
1710
1975
|
]
|
|
@@ -1751,9 +2016,41 @@ function ConfirmDialog({ task }) {
|
|
|
1751
2016
|
);
|
|
1752
2017
|
}
|
|
1753
2018
|
|
|
1754
|
-
// src/tui/components/
|
|
2019
|
+
// src/tui/components/DetectedProjectDialog.tsx
|
|
1755
2020
|
import { Box as Box15, Text as Text15 } from "ink";
|
|
1756
|
-
import {
|
|
2021
|
+
import { jsx as jsx15, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2022
|
+
function DetectedProjectDialog({ remote }) {
|
|
2023
|
+
return /* @__PURE__ */ jsxs12(
|
|
2024
|
+
Box15,
|
|
2025
|
+
{
|
|
2026
|
+
flexDirection: "column",
|
|
2027
|
+
borderStyle: "bold",
|
|
2028
|
+
borderColor: theme.borderFocus,
|
|
2029
|
+
paddingX: 3,
|
|
2030
|
+
paddingY: 1,
|
|
2031
|
+
alignSelf: "center",
|
|
2032
|
+
children: [
|
|
2033
|
+
/* @__PURE__ */ jsx15(Text15, { color: theme.dialog.label, bold: true, children: "<New Repo Detected>" }),
|
|
2034
|
+
/* @__PURE__ */ jsx15(Text15, { children: " " }),
|
|
2035
|
+
/* @__PURE__ */ jsxs12(Text15, { color: theme.dialog.fg, children: [
|
|
2036
|
+
"Git remote: ",
|
|
2037
|
+
/* @__PURE__ */ jsx15(Text15, { bold: true, children: remote.value })
|
|
2038
|
+
] }),
|
|
2039
|
+
/* @__PURE__ */ jsx15(Text15, { color: theme.dialog.fg, children: "No project is linked to this repo yet." }),
|
|
2040
|
+
/* @__PURE__ */ jsx15(Text15, { color: theme.dialog.fg, children: "Would you like to create one and link it?" }),
|
|
2041
|
+
/* @__PURE__ */ jsx15(Text15, { children: " " }),
|
|
2042
|
+
/* @__PURE__ */ jsxs12(Box15, { gap: 3, children: [
|
|
2043
|
+
/* @__PURE__ */ jsx15(Text15, { backgroundColor: theme.dialog.buttonFocusBg, color: theme.dialog.buttonFocusFg, bold: true, children: " y: Create " }),
|
|
2044
|
+
/* @__PURE__ */ jsx15(Text15, { backgroundColor: theme.dialog.buttonBg, color: theme.dialog.buttonFg, children: " n: Skip " })
|
|
2045
|
+
] })
|
|
2046
|
+
]
|
|
2047
|
+
}
|
|
2048
|
+
);
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
// src/tui/components/DependencyList.tsx
|
|
2052
|
+
import { Box as Box16, Text as Text16 } from "ink";
|
|
2053
|
+
import { Fragment as Fragment4, jsx as jsx16, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1757
2054
|
function TaskRow({
|
|
1758
2055
|
task,
|
|
1759
2056
|
globalIndex,
|
|
@@ -1761,16 +2058,16 @@ function TaskRow({
|
|
|
1761
2058
|
}) {
|
|
1762
2059
|
const isSelected = globalIndex === selectedIndex;
|
|
1763
2060
|
const statusColor = STATUS_COLOR[task.status] ?? theme.table.fg;
|
|
1764
|
-
return /* @__PURE__ */
|
|
2061
|
+
return /* @__PURE__ */ jsx16(Box16, { children: isSelected ? /* @__PURE__ */ jsxs13(Text16, { backgroundColor: theme.table.cursorBg, color: theme.table.cursorFg, bold: true, children: [
|
|
1765
2062
|
"> ",
|
|
1766
2063
|
task.id.padEnd(12),
|
|
1767
2064
|
task.status.padEnd(14),
|
|
1768
2065
|
task.name
|
|
1769
|
-
] }) : /* @__PURE__ */
|
|
1770
|
-
/* @__PURE__ */
|
|
1771
|
-
/* @__PURE__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
1773
|
-
/* @__PURE__ */
|
|
2066
|
+
] }) : /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
2067
|
+
/* @__PURE__ */ jsx16(Text16, { children: " " }),
|
|
2068
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.yaml.value, children: task.id.padEnd(12) }),
|
|
2069
|
+
/* @__PURE__ */ jsx16(Text16, { color: statusColor, children: task.status.padEnd(14) }),
|
|
2070
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.table.fg, children: task.name })
|
|
1774
2071
|
] }) }, task.id);
|
|
1775
2072
|
}
|
|
1776
2073
|
function DependencyList({
|
|
@@ -1791,23 +2088,23 @@ function DependencyList({
|
|
|
1791
2088
|
const relatedOffset = offset;
|
|
1792
2089
|
offset += related.length;
|
|
1793
2090
|
const duplicatesOffset = offset;
|
|
1794
|
-
return /* @__PURE__ */
|
|
1795
|
-
/* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
2091
|
+
return /* @__PURE__ */ jsxs13(Box16, { flexDirection: "column", flexGrow: 1, borderStyle: "bold", borderColor: theme.borderFocus, children: [
|
|
2092
|
+
/* @__PURE__ */ jsxs13(Box16, { gap: 0, children: [
|
|
2093
|
+
/* @__PURE__ */ jsxs13(Text16, { color: theme.title, bold: true, children: [
|
|
1797
2094
|
" ",
|
|
1798
2095
|
"dependencies"
|
|
1799
2096
|
] }),
|
|
1800
|
-
/* @__PURE__ */
|
|
1801
|
-
/* @__PURE__ */
|
|
1802
|
-
/* @__PURE__ */
|
|
2097
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.fg, children: "(" }),
|
|
2098
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.titleHighlight, bold: true, children: task.name }),
|
|
2099
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.fg, children: ")" })
|
|
1803
2100
|
] }),
|
|
1804
|
-
/* @__PURE__ */
|
|
1805
|
-
/* @__PURE__ */
|
|
2101
|
+
/* @__PURE__ */ jsxs13(Box16, { flexDirection: "column", paddingX: 1, paddingTop: 1, children: [
|
|
2102
|
+
/* @__PURE__ */ jsxs13(Text16, { color: theme.table.headerFg, bold: true, children: [
|
|
1806
2103
|
"BLOCKED BY (",
|
|
1807
2104
|
blockers.length,
|
|
1808
2105
|
")"
|
|
1809
2106
|
] }),
|
|
1810
|
-
blockers.length === 0 ? /* @__PURE__ */
|
|
2107
|
+
blockers.length === 0 ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: " No blockers" }) : blockers.map((t, i) => /* @__PURE__ */ jsx16(
|
|
1811
2108
|
TaskRow,
|
|
1812
2109
|
{
|
|
1813
2110
|
task: t,
|
|
@@ -1817,13 +2114,13 @@ function DependencyList({
|
|
|
1817
2114
|
t.id
|
|
1818
2115
|
))
|
|
1819
2116
|
] }),
|
|
1820
|
-
/* @__PURE__ */
|
|
1821
|
-
/* @__PURE__ */
|
|
2117
|
+
/* @__PURE__ */ jsxs13(Box16, { flexDirection: "column", paddingX: 1, paddingTop: 1, children: [
|
|
2118
|
+
/* @__PURE__ */ jsxs13(Text16, { color: theme.table.headerFg, bold: true, children: [
|
|
1822
2119
|
"BLOCKS (",
|
|
1823
2120
|
dependents.length,
|
|
1824
2121
|
")"
|
|
1825
2122
|
] }),
|
|
1826
|
-
dependents.length === 0 ? /* @__PURE__ */
|
|
2123
|
+
dependents.length === 0 ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: " No dependents" }) : dependents.map((t, i) => /* @__PURE__ */ jsx16(
|
|
1827
2124
|
TaskRow,
|
|
1828
2125
|
{
|
|
1829
2126
|
task: t,
|
|
@@ -1833,13 +2130,13 @@ function DependencyList({
|
|
|
1833
2130
|
t.id
|
|
1834
2131
|
))
|
|
1835
2132
|
] }),
|
|
1836
|
-
/* @__PURE__ */
|
|
1837
|
-
/* @__PURE__ */
|
|
2133
|
+
/* @__PURE__ */ jsxs13(Box16, { flexDirection: "column", paddingX: 1, paddingTop: 1, children: [
|
|
2134
|
+
/* @__PURE__ */ jsxs13(Text16, { color: theme.table.headerFg, bold: true, children: [
|
|
1838
2135
|
"RELATES TO (",
|
|
1839
2136
|
related.length,
|
|
1840
2137
|
")"
|
|
1841
2138
|
] }),
|
|
1842
|
-
related.length === 0 ? /* @__PURE__ */
|
|
2139
|
+
related.length === 0 ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: " No related tasks" }) : related.map((t, i) => /* @__PURE__ */ jsx16(
|
|
1843
2140
|
TaskRow,
|
|
1844
2141
|
{
|
|
1845
2142
|
task: t,
|
|
@@ -1849,13 +2146,13 @@ function DependencyList({
|
|
|
1849
2146
|
t.id
|
|
1850
2147
|
))
|
|
1851
2148
|
] }),
|
|
1852
|
-
/* @__PURE__ */
|
|
1853
|
-
/* @__PURE__ */
|
|
2149
|
+
/* @__PURE__ */ jsxs13(Box16, { flexDirection: "column", paddingX: 1, paddingTop: 1, children: [
|
|
2150
|
+
/* @__PURE__ */ jsxs13(Text16, { color: theme.table.headerFg, bold: true, children: [
|
|
1854
2151
|
"DUPLICATES (",
|
|
1855
2152
|
duplicates.length,
|
|
1856
2153
|
")"
|
|
1857
2154
|
] }),
|
|
1858
|
-
duplicates.length === 0 ? /* @__PURE__ */
|
|
2155
|
+
duplicates.length === 0 ? /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: " No duplicate tasks" }) : duplicates.map((t, i) => /* @__PURE__ */ jsx16(
|
|
1859
2156
|
TaskRow,
|
|
1860
2157
|
{
|
|
1861
2158
|
task: t,
|
|
@@ -1865,19 +2162,19 @@ function DependencyList({
|
|
|
1865
2162
|
t.id
|
|
1866
2163
|
))
|
|
1867
2164
|
] }),
|
|
1868
|
-
/* @__PURE__ */
|
|
1869
|
-
isAddingDep && /* @__PURE__ */
|
|
1870
|
-
/* @__PURE__ */
|
|
1871
|
-
/* @__PURE__ */
|
|
1872
|
-
/* @__PURE__ */
|
|
2165
|
+
/* @__PURE__ */ jsx16(Box16, { flexGrow: 1 }),
|
|
2166
|
+
isAddingDep && /* @__PURE__ */ jsxs13(Box16, { borderStyle: "round", borderColor: theme.prompt, paddingX: 1, children: [
|
|
2167
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.prompt, children: "depends on (id or id:type): " }),
|
|
2168
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.prompt, children: addDepInput }),
|
|
2169
|
+
/* @__PURE__ */ jsx16(Text16, { color: theme.promptSuggest, children: "_" })
|
|
1873
2170
|
] }),
|
|
1874
|
-
/* @__PURE__ */
|
|
2171
|
+
/* @__PURE__ */ jsx16(Box16, { paddingX: 1, children: /* @__PURE__ */ jsx16(Text16, { dimColor: true, children: "a: add dep (id or id:relates-to) | x: remove selected | enter: go to task | esc: back" }) })
|
|
1875
2172
|
] });
|
|
1876
2173
|
}
|
|
1877
2174
|
|
|
1878
2175
|
// src/tui/components/EpicPanel.tsx
|
|
1879
|
-
import { Box as
|
|
1880
|
-
import { jsx as
|
|
2176
|
+
import { Box as Box17, Text as Text17 } from "ink";
|
|
2177
|
+
import { jsx as jsx17, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1881
2178
|
var PAGE_SIZE2 = 20;
|
|
1882
2179
|
function EpicPanel({
|
|
1883
2180
|
epics,
|
|
@@ -1890,34 +2187,34 @@ function EpicPanel({
|
|
|
1890
2187
|
const currentPage = Math.floor(selectedIndex / PAGE_SIZE2);
|
|
1891
2188
|
const viewStart = currentPage * PAGE_SIZE2;
|
|
1892
2189
|
const visibleEpics = epics.slice(viewStart, viewStart + PAGE_SIZE2);
|
|
1893
|
-
return /* @__PURE__ */
|
|
1894
|
-
|
|
2190
|
+
return /* @__PURE__ */ jsxs14(
|
|
2191
|
+
Box17,
|
|
1895
2192
|
{
|
|
1896
2193
|
flexDirection: "column",
|
|
1897
2194
|
width: 48,
|
|
1898
2195
|
borderStyle: "bold",
|
|
1899
2196
|
borderColor: isFocused ? theme.borderFocus : theme.border,
|
|
1900
2197
|
children: [
|
|
1901
|
-
/* @__PURE__ */
|
|
1902
|
-
/* @__PURE__ */
|
|
2198
|
+
/* @__PURE__ */ jsxs14(Box17, { children: [
|
|
2199
|
+
/* @__PURE__ */ jsxs14(Text17, { color: theme.title, bold: true, children: [
|
|
1903
2200
|
" ",
|
|
1904
2201
|
"epics"
|
|
1905
2202
|
] }),
|
|
1906
|
-
/* @__PURE__ */
|
|
2203
|
+
/* @__PURE__ */ jsxs14(Text17, { color: theme.titleCounter, bold: true, children: [
|
|
1907
2204
|
"[",
|
|
1908
2205
|
epics.length,
|
|
1909
2206
|
"]"
|
|
1910
2207
|
] }),
|
|
1911
|
-
isReordering && /* @__PURE__ */
|
|
2208
|
+
isReordering && /* @__PURE__ */ jsxs14(Text17, { color: theme.flash.warn, bold: true, children: [
|
|
1912
2209
|
" ",
|
|
1913
2210
|
"REORDER"
|
|
1914
2211
|
] }),
|
|
1915
|
-
filterActive && /* @__PURE__ */
|
|
2212
|
+
filterActive && /* @__PURE__ */ jsxs14(Text17, { color: theme.titleFilter, children: [
|
|
1916
2213
|
" *",
|
|
1917
2214
|
selectedEpicIds.size
|
|
1918
2215
|
] })
|
|
1919
2216
|
] }),
|
|
1920
|
-
/* @__PURE__ */
|
|
2217
|
+
/* @__PURE__ */ jsx17(Box17, { flexDirection: "column", flexGrow: 1, overflowY: "hidden", children: epics.length === 0 ? /* @__PURE__ */ jsx17(Box17, { paddingX: 1, children: /* @__PURE__ */ jsx17(Text17, { dimColor: true, children: "No epics" }) }) : visibleEpics.map((epic, i) => {
|
|
1921
2218
|
const actualIndex = viewStart + i;
|
|
1922
2219
|
const isSelected = actualIndex === selectedIndex && isFocused;
|
|
1923
2220
|
const isChecked = selectedEpicIds.has(epic.id);
|
|
@@ -1925,21 +2222,21 @@ function EpicPanel({
|
|
|
1925
2222
|
const statusColor = STATUS_COLOR[epic.status] ?? theme.table.fg;
|
|
1926
2223
|
if (isSelected) {
|
|
1927
2224
|
const cursorBg = isReordering ? theme.flash.warn : theme.table.cursorBg;
|
|
1928
|
-
return /* @__PURE__ */
|
|
2225
|
+
return /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsxs14(Text17, { backgroundColor: cursorBg, color: theme.table.cursorFg, bold: true, children: [
|
|
1929
2226
|
isReordering ? "~ " : " ",
|
|
1930
2227
|
marker,
|
|
1931
2228
|
" ",
|
|
1932
2229
|
epic.name
|
|
1933
2230
|
] }) }, epic.id);
|
|
1934
2231
|
}
|
|
1935
|
-
return /* @__PURE__ */
|
|
2232
|
+
return /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsxs14(Text17, { color: isChecked ? theme.titleHighlight : statusColor, children: [
|
|
1936
2233
|
" ",
|
|
1937
2234
|
marker,
|
|
1938
2235
|
" ",
|
|
1939
2236
|
epic.name
|
|
1940
2237
|
] }) }, epic.id);
|
|
1941
2238
|
}) }),
|
|
1942
|
-
epics.length > PAGE_SIZE2 && /* @__PURE__ */
|
|
2239
|
+
epics.length > PAGE_SIZE2 && /* @__PURE__ */ jsx17(Box17, { justifyContent: "flex-end", paddingRight: 1, children: /* @__PURE__ */ jsxs14(Text17, { dimColor: true, children: [
|
|
1943
2240
|
"[",
|
|
1944
2241
|
viewStart + 1,
|
|
1945
2242
|
"-",
|
|
@@ -1955,8 +2252,8 @@ function EpicPanel({
|
|
|
1955
2252
|
|
|
1956
2253
|
// src/tui/components/EpicPicker.tsx
|
|
1957
2254
|
import { useState as useState6 } from "react";
|
|
1958
|
-
import { Box as
|
|
1959
|
-
import { Fragment as
|
|
2255
|
+
import { Box as Box18, Text as Text18, useInput as useInput6, useStdout as useStdout3 } from "ink";
|
|
2256
|
+
import { Fragment as Fragment5, jsx as jsx18, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1960
2257
|
function EpicPicker({ epics, currentEpicId, onSelect, onCancel }) {
|
|
1961
2258
|
const { stdout } = useStdout3();
|
|
1962
2259
|
const termHeight = stdout.rows > 0 ? stdout.rows : 24;
|
|
@@ -2029,53 +2326,53 @@ function EpicPicker({ epics, currentEpicId, onSelect, onCancel }) {
|
|
|
2029
2326
|
return;
|
|
2030
2327
|
}
|
|
2031
2328
|
});
|
|
2032
|
-
return /* @__PURE__ */
|
|
2033
|
-
/* @__PURE__ */
|
|
2034
|
-
/* @__PURE__ */
|
|
2329
|
+
return /* @__PURE__ */ jsxs15(Box18, { flexDirection: "column", borderStyle: "bold", borderColor: theme.borderFocus, flexGrow: 1, children: [
|
|
2330
|
+
/* @__PURE__ */ jsxs15(Box18, { gap: 0, children: [
|
|
2331
|
+
/* @__PURE__ */ jsxs15(Text18, { color: theme.title, bold: true, children: [
|
|
2035
2332
|
" ",
|
|
2036
2333
|
"assign to epic"
|
|
2037
2334
|
] }),
|
|
2038
|
-
/* @__PURE__ */
|
|
2335
|
+
/* @__PURE__ */ jsxs15(Text18, { color: theme.titleCounter, bold: true, children: [
|
|
2039
2336
|
" ",
|
|
2040
2337
|
"[",
|
|
2041
2338
|
epics.length,
|
|
2042
2339
|
"]"
|
|
2043
2340
|
] })
|
|
2044
2341
|
] }),
|
|
2045
|
-
isSearching ? /* @__PURE__ */
|
|
2046
|
-
/* @__PURE__ */
|
|
2047
|
-
/* @__PURE__ */
|
|
2048
|
-
/* @__PURE__ */
|
|
2049
|
-
] }) : searchQuery ? /* @__PURE__ */
|
|
2342
|
+
isSearching ? /* @__PURE__ */ jsxs15(Box18, { borderStyle: "round", borderColor: theme.prompt, paddingX: 1, children: [
|
|
2343
|
+
/* @__PURE__ */ jsx18(Text18, { color: theme.prompt, children: "/" }),
|
|
2344
|
+
/* @__PURE__ */ jsx18(Text18, { color: theme.prompt, children: searchQuery }),
|
|
2345
|
+
/* @__PURE__ */ jsx18(Text18, { color: theme.promptSuggest, children: "_" })
|
|
2346
|
+
] }) : searchQuery ? /* @__PURE__ */ jsx18(Box18, { paddingX: 1, children: /* @__PURE__ */ jsxs15(Text18, { color: theme.titleFilter, children: [
|
|
2050
2347
|
"/",
|
|
2051
2348
|
searchQuery
|
|
2052
2349
|
] }) }) : null,
|
|
2053
|
-
/* @__PURE__ */
|
|
2350
|
+
/* @__PURE__ */ jsx18(Box18, { paddingX: 1, children: /* @__PURE__ */ jsxs15(Text18, { color: theme.table.headerFg, bold: true, children: [
|
|
2054
2351
|
" ",
|
|
2055
2352
|
"ID".padEnd(14),
|
|
2056
2353
|
"STATUS".padEnd(14),
|
|
2057
2354
|
"NAME"
|
|
2058
2355
|
] }) }),
|
|
2059
|
-
filtered.length === 0 ? /* @__PURE__ */
|
|
2356
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx18(Box18, { paddingX: 2, paddingY: 1, children: /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "No epics match the filter" }) }) : visible.map((epic, i) => {
|
|
2060
2357
|
const actualIndex = viewStart + i;
|
|
2061
2358
|
const isCursor = actualIndex === cursorIndex;
|
|
2062
2359
|
const isCurrent = epic.id === currentEpicId;
|
|
2063
2360
|
const marker = isCurrent ? "* " : " ";
|
|
2064
2361
|
const statusColor = STATUS_COLOR[epic.status] ?? theme.table.fg;
|
|
2065
|
-
return /* @__PURE__ */
|
|
2362
|
+
return /* @__PURE__ */ jsx18(Box18, { paddingX: 1, children: isCursor ? /* @__PURE__ */ jsxs15(Text18, { backgroundColor: theme.table.cursorBg, color: theme.table.cursorFg, bold: true, children: [
|
|
2066
2363
|
"> ",
|
|
2067
2364
|
epic.id.padEnd(14),
|
|
2068
2365
|
epic.status.padEnd(14),
|
|
2069
2366
|
epic.name
|
|
2070
|
-
] }) : /* @__PURE__ */
|
|
2071
|
-
/* @__PURE__ */
|
|
2072
|
-
/* @__PURE__ */
|
|
2073
|
-
/* @__PURE__ */
|
|
2074
|
-
/* @__PURE__ */
|
|
2367
|
+
] }) : /* @__PURE__ */ jsxs15(Fragment5, { children: [
|
|
2368
|
+
/* @__PURE__ */ jsx18(Text18, { color: isCurrent ? theme.titleHighlight : theme.table.fg, children: marker }),
|
|
2369
|
+
/* @__PURE__ */ jsx18(Text18, { color: theme.yaml.value, children: epic.id.padEnd(14) }),
|
|
2370
|
+
/* @__PURE__ */ jsx18(Text18, { color: statusColor, children: epic.status.padEnd(14) }),
|
|
2371
|
+
/* @__PURE__ */ jsx18(Text18, { color: isCurrent ? theme.titleHighlight : theme.table.fg, children: epic.name })
|
|
2075
2372
|
] }) }, epic.id);
|
|
2076
2373
|
}),
|
|
2077
|
-
/* @__PURE__ */
|
|
2078
|
-
filtered.length > maxVisible && /* @__PURE__ */
|
|
2374
|
+
/* @__PURE__ */ jsx18(Box18, { flexGrow: 1 }),
|
|
2375
|
+
filtered.length > maxVisible && /* @__PURE__ */ jsx18(Box18, { justifyContent: "flex-end", paddingRight: 1, children: /* @__PURE__ */ jsxs15(Text18, { dimColor: true, children: [
|
|
2079
2376
|
"[",
|
|
2080
2377
|
viewStart + 1,
|
|
2081
2378
|
"-",
|
|
@@ -2084,19 +2381,19 @@ function EpicPicker({ epics, currentEpicId, onSelect, onCancel }) {
|
|
|
2084
2381
|
filtered.length,
|
|
2085
2382
|
"]"
|
|
2086
2383
|
] }) }),
|
|
2087
|
-
/* @__PURE__ */
|
|
2384
|
+
/* @__PURE__ */ jsx18(Box18, { paddingX: 1, children: /* @__PURE__ */ jsx18(Text18, { dimColor: true, children: "enter: assign | x: unassign | /: search | esc: cancel" }) })
|
|
2088
2385
|
] });
|
|
2089
2386
|
}
|
|
2090
2387
|
|
|
2091
2388
|
// src/tui/useAutoRefetch.ts
|
|
2092
|
-
import { useEffect, useRef } from "react";
|
|
2389
|
+
import { useEffect as useEffect3, useRef as useRef4 } from "react";
|
|
2093
2390
|
import { watchFile, unwatchFile } from "fs";
|
|
2094
2391
|
var POLL_INTERVAL_MS = 1e3;
|
|
2095
2392
|
var DEBOUNCE_MS = 200;
|
|
2096
2393
|
function useAutoRefetch(dbPath, onRefetch) {
|
|
2097
|
-
const callbackRef =
|
|
2394
|
+
const callbackRef = useRef4(onRefetch);
|
|
2098
2395
|
callbackRef.current = onRefetch;
|
|
2099
|
-
|
|
2396
|
+
useEffect3(() => {
|
|
2100
2397
|
let debounceTimer = null;
|
|
2101
2398
|
const handleChange = () => {
|
|
2102
2399
|
if (debounceTimer) clearTimeout(debounceTimer);
|
|
@@ -2124,7 +2421,7 @@ function useAutoRefetch(dbPath, onRefetch) {
|
|
|
2124
2421
|
}
|
|
2125
2422
|
|
|
2126
2423
|
// src/tui/components/App.tsx
|
|
2127
|
-
import { jsx as
|
|
2424
|
+
import { jsx as jsx19, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2128
2425
|
var STATUS_CYCLE = [
|
|
2129
2426
|
TaskStatus.Backlog,
|
|
2130
2427
|
TaskStatus.Todo,
|
|
@@ -2133,12 +2430,12 @@ var STATUS_CYCLE = [
|
|
|
2133
2430
|
TaskStatus.Done
|
|
2134
2431
|
];
|
|
2135
2432
|
var EPIC_PANEL_WIDTH = 48;
|
|
2136
|
-
function App({ container, initialProject }) {
|
|
2433
|
+
function App({ container, initialProject, latestVersion }) {
|
|
2137
2434
|
const { exit } = useApp();
|
|
2138
2435
|
const { stdout } = useStdout4();
|
|
2139
2436
|
const [state, dispatch] = useReducer(appReducer, initialState);
|
|
2140
2437
|
const [, setResizeTick] = useState7(0);
|
|
2141
|
-
|
|
2438
|
+
useEffect4(() => {
|
|
2142
2439
|
const onResize = () => {
|
|
2143
2440
|
setResizeTick((n) => n + 1);
|
|
2144
2441
|
};
|
|
@@ -2303,10 +2600,10 @@ function App({ container, initialProject }) {
|
|
|
2303
2600
|
loadEpics();
|
|
2304
2601
|
}, [loadProjects, loadTasks, loadEpics]);
|
|
2305
2602
|
useAutoRefetch(container.dbPath, refetchAll);
|
|
2306
|
-
|
|
2603
|
+
useEffect4(() => {
|
|
2307
2604
|
loadProjects();
|
|
2308
2605
|
}, [loadProjects]);
|
|
2309
|
-
|
|
2606
|
+
useEffect4(() => {
|
|
2310
2607
|
if (state.projects.length > 0 && !state.activeProject) {
|
|
2311
2608
|
logger.info(`TUI.resolveProject: resolving initialProject=${initialProject ?? "(default)"}`);
|
|
2312
2609
|
const result = container.projectService.resolveProject(initialProject);
|
|
@@ -2323,13 +2620,29 @@ function App({ container, initialProject }) {
|
|
|
2323
2620
|
}
|
|
2324
2621
|
}
|
|
2325
2622
|
}, [state.projects, state.activeProject, initialProject, container]);
|
|
2326
|
-
|
|
2623
|
+
const gitRemoteCheckedRef = useRef5(false);
|
|
2624
|
+
useEffect4(() => {
|
|
2625
|
+
if (state.projects.length > 0 && !gitRemoteCheckedRef.current && !initialProject) {
|
|
2626
|
+
gitRemoteCheckedRef.current = true;
|
|
2627
|
+
const remoteResult = detectGitRemote();
|
|
2628
|
+
if (remoteResult.ok && remoteResult.value) {
|
|
2629
|
+
const remote = remoteResult.value;
|
|
2630
|
+
const alreadyLinked = state.projects.some((p) => p.gitRemote?.equals(remote));
|
|
2631
|
+
const dismissed = isDismissedRemote(container.dismissedGitRemotesPath, remote);
|
|
2632
|
+
if (!alreadyLinked && !dismissed) {
|
|
2633
|
+
logger.info(`TUI.detectGitRemote: unlinked remote detected: ${remote.value}`);
|
|
2634
|
+
dispatch({ type: "SET_DETECTED_GIT_REMOTE", remote });
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2638
|
+
}, [state.projects, initialProject]);
|
|
2639
|
+
useEffect4(() => {
|
|
2327
2640
|
if (state.activeProject) {
|
|
2328
2641
|
loadTasks();
|
|
2329
2642
|
loadEpics();
|
|
2330
2643
|
}
|
|
2331
2644
|
}, [state.activeProject, state.filter, loadTasks, loadEpics]);
|
|
2332
|
-
|
|
2645
|
+
useEffect4(() => {
|
|
2333
2646
|
if (state.flash) {
|
|
2334
2647
|
const timer = setTimeout(() => {
|
|
2335
2648
|
dispatch({ type: "CLEAR_FLASH" });
|
|
@@ -2361,11 +2674,20 @@ function App({ container, initialProject }) {
|
|
|
2361
2674
|
}
|
|
2362
2675
|
return;
|
|
2363
2676
|
}
|
|
2677
|
+
if (state.detectedGitRemote && state.activeView === ViewType.TaskList) {
|
|
2678
|
+
if (input === "y") {
|
|
2679
|
+
dispatch({ type: "NAVIGATE_TO", view: ViewType.ProjectCreate });
|
|
2680
|
+
} else if (input === "n" || key.escape) {
|
|
2681
|
+
dismissRemote(container.dismissedGitRemotesPath, state.detectedGitRemote);
|
|
2682
|
+
dispatch({ type: "SET_DETECTED_GIT_REMOTE", remote: null });
|
|
2683
|
+
}
|
|
2684
|
+
return;
|
|
2685
|
+
}
|
|
2364
2686
|
if (state.activeView === ViewType.Help) {
|
|
2365
2687
|
dispatch({ type: "GO_BACK" });
|
|
2366
2688
|
return;
|
|
2367
2689
|
}
|
|
2368
|
-
if (state.activeView === ViewType.TaskCreate || state.activeView === ViewType.TaskEdit || state.activeView === ViewType.ProjectSelector || state.activeView === ViewType.ProjectCreate || state.activeView === ViewType.ProjectLink || state.activeView === ViewType.EpicPicker) {
|
|
2690
|
+
if (state.activeView === ViewType.TaskCreate || state.activeView === ViewType.TaskEdit || state.activeView === ViewType.ProjectSelector || state.activeView === ViewType.ProjectCreate || state.activeView === ViewType.ProjectEdit || state.activeView === ViewType.ProjectLink || state.activeView === ViewType.EpicPicker) {
|
|
2369
2691
|
return;
|
|
2370
2692
|
}
|
|
2371
2693
|
if (state.activeView === ViewType.DependencyList && state.isAddingDep) {
|
|
@@ -2511,7 +2833,8 @@ function App({ container, initialProject }) {
|
|
|
2511
2833
|
if (key.tab && state.activeView === ViewType.TaskList) {
|
|
2512
2834
|
const panels = previewTask ? ["epic", "list", "detail"] : ["epic", "list"];
|
|
2513
2835
|
const curIdx = panels.indexOf(state.focusedPanel);
|
|
2514
|
-
const
|
|
2836
|
+
const delta = key.shift ? -1 : 1;
|
|
2837
|
+
const nextPanel = panels[(curIdx + delta + panels.length) % panels.length] ?? "list";
|
|
2515
2838
|
dispatch({ type: "SET_PANEL_FOCUS", panel: nextPanel });
|
|
2516
2839
|
return;
|
|
2517
2840
|
}
|
|
@@ -2938,35 +3261,57 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
2938
3261
|
const handleProjectCreate = useCallback2(() => {
|
|
2939
3262
|
dispatch({ type: "NAVIGATE_TO", view: ViewType.ProjectCreate });
|
|
2940
3263
|
}, []);
|
|
3264
|
+
const handleProjectEdit = useCallback2((project) => {
|
|
3265
|
+
dispatch({ type: "SET_EDITING_PROJECT", project });
|
|
3266
|
+
dispatch({ type: "NAVIGATE_TO", view: ViewType.ProjectEdit });
|
|
3267
|
+
}, []);
|
|
2941
3268
|
const handleProjectFormSave = useCallback2(
|
|
2942
3269
|
(data) => {
|
|
2943
|
-
const
|
|
3270
|
+
const editing = state.activeView === ViewType.ProjectEdit ? state.editingProject : null;
|
|
3271
|
+
const result = editing ? container.projectService.updateProject(editing.id, {
|
|
3272
|
+
name: data.name,
|
|
3273
|
+
description: data.description,
|
|
3274
|
+
isDefault: data.isDefault,
|
|
3275
|
+
gitRemote: data.gitRemote || null
|
|
3276
|
+
}) : container.projectService.createProject({
|
|
2944
3277
|
name: data.name,
|
|
2945
3278
|
key: data.key || void 0,
|
|
2946
3279
|
description: data.description || void 0,
|
|
2947
|
-
isDefault: data.isDefault
|
|
3280
|
+
isDefault: data.isDefault,
|
|
3281
|
+
gitRemote: data.gitRemote || void 0
|
|
2948
3282
|
});
|
|
2949
3283
|
if (result.ok) {
|
|
2950
|
-
|
|
3284
|
+
const verb = editing ? "updated" : "created";
|
|
3285
|
+
logger.info(
|
|
3286
|
+
`TUI.${editing ? "editProject" : "createProject"}: ${verb} key=${result.value.key} name=${result.value.name}`
|
|
3287
|
+
);
|
|
2951
3288
|
dispatch({
|
|
2952
3289
|
type: "FLASH",
|
|
2953
|
-
message: `Project
|
|
3290
|
+
message: `Project ${verb}: ${result.value.name}`,
|
|
2954
3291
|
level: "info"
|
|
2955
3292
|
});
|
|
2956
|
-
|
|
2957
|
-
|
|
3293
|
+
if (editing && state.activeProject?.id === result.value.id) {
|
|
3294
|
+
dispatch({ type: "SET_ACTIVE_PROJECT", project: result.value });
|
|
3295
|
+
}
|
|
3296
|
+
if (!editing) {
|
|
3297
|
+
dispatch({ type: "SET_ACTIVE_PROJECT", project: result.value });
|
|
3298
|
+
dispatch({ type: "GO_BACK" });
|
|
3299
|
+
}
|
|
2958
3300
|
dispatch({ type: "GO_BACK" });
|
|
2959
3301
|
loadProjects();
|
|
2960
3302
|
} else {
|
|
2961
|
-
logger.error("
|
|
3303
|
+
logger.error(`TUI.${editing ? "editProject" : "createProject"}: failed`, result.error);
|
|
2962
3304
|
dispatch({ type: "FLASH", message: result.error.message, level: "error" });
|
|
2963
3305
|
}
|
|
2964
3306
|
},
|
|
2965
|
-
[container, loadProjects]
|
|
3307
|
+
[container, state.activeView, state.editingProject, state.activeProject, loadProjects]
|
|
2966
3308
|
);
|
|
2967
3309
|
const handleProjectFormCancel = useCallback2(() => {
|
|
3310
|
+
if (state.activeView === ViewType.ProjectCreate && state.detectedGitRemote) {
|
|
3311
|
+
dismissRemote(container.dismissedGitRemotesPath, state.detectedGitRemote);
|
|
3312
|
+
}
|
|
2968
3313
|
dispatch({ type: "GO_BACK" });
|
|
2969
|
-
}, []);
|
|
3314
|
+
}, [state.activeView, state.detectedGitRemote, container]);
|
|
2970
3315
|
const handleProjectLink = useCallback2((project) => {
|
|
2971
3316
|
dispatch({ type: "SET_LINKING_PROJECT", project });
|
|
2972
3317
|
dispatch({ type: "NAVIGATE_TO", view: ViewType.ProjectLink });
|
|
@@ -2977,11 +3322,11 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
2977
3322
|
const result = container.projectService.linkGitRemote(state.linkingProject.id, remote);
|
|
2978
3323
|
if (result.ok) {
|
|
2979
3324
|
logger.info(
|
|
2980
|
-
`TUI.linkGitRemote: linked project=${state.linkingProject.id} remote=${result.value.gitRemote}`
|
|
3325
|
+
`TUI.linkGitRemote: linked project=${state.linkingProject.id} remote=${result.value.gitRemote?.value}`
|
|
2981
3326
|
);
|
|
2982
3327
|
dispatch({
|
|
2983
3328
|
type: "FLASH",
|
|
2984
|
-
message: `Linked to: ${result.value.gitRemote}`,
|
|
3329
|
+
message: `Linked to: ${result.value.gitRemote?.value}`,
|
|
2985
3330
|
level: "info"
|
|
2986
3331
|
});
|
|
2987
3332
|
dispatch({ type: "GO_BACK" });
|
|
@@ -3009,8 +3354,8 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3009
3354
|
const handleLinkDetect = useCallback2(() => {
|
|
3010
3355
|
const result = detectGitRemote();
|
|
3011
3356
|
if (result.ok && result.value) {
|
|
3012
|
-
dispatch({ type: "FLASH", message: `Detected: ${result.value}`, level: "info" });
|
|
3013
|
-
return result.value;
|
|
3357
|
+
dispatch({ type: "FLASH", message: `Detected: ${result.value.value}`, level: "info" });
|
|
3358
|
+
return result.value.value;
|
|
3014
3359
|
}
|
|
3015
3360
|
dispatch({ type: "FLASH", message: "No git remote detected in cwd", level: "warn" });
|
|
3016
3361
|
return null;
|
|
@@ -3039,17 +3384,17 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3039
3384
|
return result.ok ? result.value : [];
|
|
3040
3385
|
}, [container, state.activeProject, state.tasks]);
|
|
3041
3386
|
const previewTaskId = previewTask?.id ?? null;
|
|
3042
|
-
|
|
3387
|
+
useEffect4(() => {
|
|
3043
3388
|
if (state.activeView === ViewType.TaskList && previewTaskId) {
|
|
3044
3389
|
loadDeps(previewTaskId);
|
|
3045
3390
|
}
|
|
3046
3391
|
}, [state.activeView, previewTaskId, loadDeps]);
|
|
3047
|
-
return /* @__PURE__ */
|
|
3048
|
-
/* @__PURE__ */
|
|
3049
|
-
/* @__PURE__ */
|
|
3050
|
-
state.confirmDelete && /* @__PURE__ */
|
|
3051
|
-
!state.confirmDelete && state.activeView === ViewType.TaskList && /* @__PURE__ */
|
|
3052
|
-
/* @__PURE__ */
|
|
3392
|
+
return /* @__PURE__ */ jsxs16(Box19, { flexDirection: "column", height: stdout.rows, children: [
|
|
3393
|
+
/* @__PURE__ */ jsx19(Header, { state, latestVersion }),
|
|
3394
|
+
/* @__PURE__ */ jsxs16(Box19, { flexDirection: "column", flexGrow: 1, overflowY: "hidden", children: [
|
|
3395
|
+
state.confirmDelete && /* @__PURE__ */ jsx19(ConfirmDialog, { task: state.confirmDelete }),
|
|
3396
|
+
!state.confirmDelete && state.activeView === ViewType.TaskList && (state.detectedGitRemote ? /* @__PURE__ */ jsx19(DetectedProjectDialog, { remote: state.detectedGitRemote }) : /* @__PURE__ */ jsxs16(Box19, { flexDirection: "row", flexGrow: 1, children: [
|
|
3397
|
+
/* @__PURE__ */ jsx19(
|
|
3053
3398
|
EpicPanel,
|
|
3054
3399
|
{
|
|
3055
3400
|
epics: state.epics,
|
|
@@ -3059,7 +3404,7 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3059
3404
|
isReordering: state.isEpicReordering
|
|
3060
3405
|
}
|
|
3061
3406
|
),
|
|
3062
|
-
/* @__PURE__ */
|
|
3407
|
+
/* @__PURE__ */ jsx19(Box19, { width: taskListWidth, children: /* @__PURE__ */ jsx19(
|
|
3063
3408
|
TaskList,
|
|
3064
3409
|
{
|
|
3065
3410
|
tasks: state.tasks,
|
|
@@ -3080,7 +3425,7 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3080
3425
|
epicFilterActive: state.selectedEpicIds.size > 0
|
|
3081
3426
|
}
|
|
3082
3427
|
) }),
|
|
3083
|
-
/* @__PURE__ */
|
|
3428
|
+
/* @__PURE__ */ jsx19(Box19, { width: taskDetailWidth, children: previewTask ? /* @__PURE__ */ jsx19(
|
|
3084
3429
|
TaskDetail,
|
|
3085
3430
|
{
|
|
3086
3431
|
task: previewTask,
|
|
@@ -3091,24 +3436,24 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3091
3436
|
isFocused: state.focusedPanel === "detail",
|
|
3092
3437
|
scrollOffset: state.detailScrollOffset
|
|
3093
3438
|
}
|
|
3094
|
-
) : /* @__PURE__ */
|
|
3095
|
-
|
|
3439
|
+
) : /* @__PURE__ */ jsxs16(
|
|
3440
|
+
Box19,
|
|
3096
3441
|
{
|
|
3097
3442
|
flexDirection: "column",
|
|
3098
3443
|
flexGrow: 1,
|
|
3099
3444
|
borderStyle: "bold",
|
|
3100
3445
|
borderColor: theme.border,
|
|
3101
3446
|
children: [
|
|
3102
|
-
/* @__PURE__ */
|
|
3447
|
+
/* @__PURE__ */ jsx19(Box19, { children: /* @__PURE__ */ jsxs16(Text19, { color: theme.title, bold: true, children: [
|
|
3103
3448
|
" ",
|
|
3104
3449
|
"detail"
|
|
3105
3450
|
] }) }),
|
|
3106
|
-
/* @__PURE__ */
|
|
3451
|
+
/* @__PURE__ */ jsx19(Box19, { flexGrow: 1, justifyContent: "center", alignItems: "center", children: /* @__PURE__ */ jsx19(Text19, { dimColor: true, children: "No task selected" }) })
|
|
3107
3452
|
]
|
|
3108
3453
|
}
|
|
3109
3454
|
) })
|
|
3110
|
-
] }),
|
|
3111
|
-
!state.confirmDelete && state.activeView === ViewType.TaskDetail && state.selectedTask && /* @__PURE__ */
|
|
3455
|
+
] })),
|
|
3456
|
+
!state.confirmDelete && state.activeView === ViewType.TaskDetail && state.selectedTask && /* @__PURE__ */ jsx19(
|
|
3112
3457
|
TaskDetail,
|
|
3113
3458
|
{
|
|
3114
3459
|
task: state.selectedTask,
|
|
@@ -3119,7 +3464,7 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3119
3464
|
scrollOffset: state.detailScrollOffset
|
|
3120
3465
|
}
|
|
3121
3466
|
),
|
|
3122
|
-
!state.confirmDelete && state.activeView === ViewType.DependencyList && state.selectedTask && /* @__PURE__ */
|
|
3467
|
+
!state.confirmDelete && state.activeView === ViewType.DependencyList && state.selectedTask && /* @__PURE__ */ jsx19(
|
|
3123
3468
|
DependencyList,
|
|
3124
3469
|
{
|
|
3125
3470
|
task: state.selectedTask,
|
|
@@ -3132,7 +3477,7 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3132
3477
|
addDepInput: state.addDepInput
|
|
3133
3478
|
}
|
|
3134
3479
|
),
|
|
3135
|
-
!state.confirmDelete && (state.activeView === ViewType.TaskCreate || state.activeView === ViewType.TaskEdit) && /* @__PURE__ */
|
|
3480
|
+
!state.confirmDelete && (state.activeView === ViewType.TaskCreate || state.activeView === ViewType.TaskEdit) && /* @__PURE__ */ jsx19(
|
|
3136
3481
|
TaskForm,
|
|
3137
3482
|
{
|
|
3138
3483
|
editingTask: state.activeView === ViewType.TaskEdit ? state.selectedTask : null,
|
|
@@ -3142,7 +3487,7 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3142
3487
|
onCancel: handleFormCancel
|
|
3143
3488
|
}
|
|
3144
3489
|
),
|
|
3145
|
-
!state.confirmDelete && state.activeView === ViewType.EpicPicker && state.selectedTask && /* @__PURE__ */
|
|
3490
|
+
!state.confirmDelete && state.activeView === ViewType.EpicPicker && state.selectedTask && /* @__PURE__ */ jsx19(
|
|
3146
3491
|
EpicPicker,
|
|
3147
3492
|
{
|
|
3148
3493
|
epics: state.epics,
|
|
@@ -3151,20 +3496,36 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3151
3496
|
onCancel: handleEpicPickerCancel
|
|
3152
3497
|
}
|
|
3153
3498
|
),
|
|
3154
|
-
!state.confirmDelete && state.activeView === ViewType.ProjectSelector && /* @__PURE__ */
|
|
3499
|
+
!state.confirmDelete && state.activeView === ViewType.ProjectSelector && /* @__PURE__ */ jsx19(
|
|
3155
3500
|
ProjectSelector,
|
|
3156
3501
|
{
|
|
3157
3502
|
projects: state.projects,
|
|
3158
3503
|
activeProject: state.activeProject,
|
|
3159
3504
|
onSelect: handleProjectSelect,
|
|
3160
3505
|
onCreate: handleProjectCreate,
|
|
3506
|
+
onEdit: handleProjectEdit,
|
|
3161
3507
|
onSetDefault: handleSetDefault,
|
|
3162
3508
|
onLink: handleProjectLink,
|
|
3163
3509
|
onCancel: handleProjectCancel
|
|
3164
3510
|
}
|
|
3165
3511
|
),
|
|
3166
|
-
!state.confirmDelete && state.activeView === ViewType.ProjectCreate && /* @__PURE__ */
|
|
3167
|
-
|
|
3512
|
+
!state.confirmDelete && state.activeView === ViewType.ProjectCreate && /* @__PURE__ */ jsx19(
|
|
3513
|
+
ProjectForm,
|
|
3514
|
+
{
|
|
3515
|
+
initialGitRemote: state.detectedGitRemote ?? void 0,
|
|
3516
|
+
onSave: handleProjectFormSave,
|
|
3517
|
+
onCancel: handleProjectFormCancel
|
|
3518
|
+
}
|
|
3519
|
+
),
|
|
3520
|
+
!state.confirmDelete && state.activeView === ViewType.ProjectEdit && state.editingProject && /* @__PURE__ */ jsx19(
|
|
3521
|
+
ProjectForm,
|
|
3522
|
+
{
|
|
3523
|
+
editingProject: state.editingProject,
|
|
3524
|
+
onSave: handleProjectFormSave,
|
|
3525
|
+
onCancel: handleProjectFormCancel
|
|
3526
|
+
}
|
|
3527
|
+
),
|
|
3528
|
+
!state.confirmDelete && state.activeView === ViewType.ProjectLink && state.linkingProject && /* @__PURE__ */ jsx19(
|
|
3168
3529
|
ProjectLinkForm,
|
|
3169
3530
|
{
|
|
3170
3531
|
project: state.linkingProject,
|
|
@@ -3174,22 +3535,25 @@ ${state.selectedTask.additionalRequirements}`;
|
|
|
3174
3535
|
onCancel: handleLinkCancel
|
|
3175
3536
|
}
|
|
3176
3537
|
),
|
|
3177
|
-
!state.confirmDelete && state.activeView === ViewType.Help && /* @__PURE__ */
|
|
3538
|
+
!state.confirmDelete && state.activeView === ViewType.Help && /* @__PURE__ */ jsx19(HelpOverlay, {})
|
|
3178
3539
|
] }),
|
|
3179
|
-
/* @__PURE__ */
|
|
3180
|
-
state.flash && /* @__PURE__ */
|
|
3540
|
+
/* @__PURE__ */ jsx19(Crumbs, { breadcrumbs: state.breadcrumbs }),
|
|
3541
|
+
state.flash && /* @__PURE__ */ jsx19(FlashMessage, { message: state.flash.message, level: state.flash.level })
|
|
3181
3542
|
] });
|
|
3182
3543
|
}
|
|
3183
3544
|
|
|
3184
3545
|
// src/tui/index.tsx
|
|
3185
|
-
import { jsx as
|
|
3186
|
-
async function launchTUI(container, initialProject) {
|
|
3187
|
-
const instance = render(
|
|
3188
|
-
|
|
3189
|
-
|
|
3546
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
3547
|
+
async function launchTUI(container, initialProject, latestVersion) {
|
|
3548
|
+
const instance = render(
|
|
3549
|
+
/* @__PURE__ */ jsx20(App, { container, initialProject, latestVersion }),
|
|
3550
|
+
{
|
|
3551
|
+
exitOnCtrlC: true
|
|
3552
|
+
}
|
|
3553
|
+
);
|
|
3190
3554
|
await instance.waitUntilExit();
|
|
3191
3555
|
}
|
|
3192
3556
|
export {
|
|
3193
3557
|
launchTUI
|
|
3194
3558
|
};
|
|
3195
|
-
//# sourceMappingURL=tui-
|
|
3559
|
+
//# sourceMappingURL=tui-NCL4RFFD.js.map
|