kandown 0.7.0 → 0.7.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.
- package/bin/tui.js +293 -417
- package/dist/index.html +259 -259
- package/package.json +1 -1
package/bin/tui.js
CHANGED
|
@@ -27968,7 +27968,7 @@ var require_backend = __commonJS({
|
|
|
27968
27968
|
return [initialArg, function() {
|
|
27969
27969
|
}];
|
|
27970
27970
|
},
|
|
27971
|
-
useRef: function
|
|
27971
|
+
useRef: function useRef5(initialValue) {
|
|
27972
27972
|
var hook = nextHook();
|
|
27973
27973
|
initialValue = null !== hook ? hook.memoizedState : {
|
|
27974
27974
|
current: initialValue
|
|
@@ -27983,7 +27983,7 @@ var require_backend = __commonJS({
|
|
|
27983
27983
|
});
|
|
27984
27984
|
return initialValue;
|
|
27985
27985
|
},
|
|
27986
|
-
useState: function
|
|
27986
|
+
useState: function useState9(initialState) {
|
|
27987
27987
|
var hook = nextHook();
|
|
27988
27988
|
initialState = null !== hook ? hook.memoizedState : "function" === typeof initialState ? initialState() : initialState;
|
|
27989
27989
|
hookLog.push({
|
|
@@ -54326,7 +54326,7 @@ function ValueDisplay({ setting, value, focused }) {
|
|
|
54326
54326
|
}
|
|
54327
54327
|
|
|
54328
54328
|
// src/cli/screens/board.tsx
|
|
54329
|
-
var
|
|
54329
|
+
var import_react37 = __toESM(require_react(), 1);
|
|
54330
54330
|
|
|
54331
54331
|
// src/cli/lib/board-reader.ts
|
|
54332
54332
|
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -56299,8 +56299,8 @@ var FileWatcher = class {
|
|
|
56299
56299
|
knownTaskIds = /* @__PURE__ */ new Set();
|
|
56300
56300
|
listeners = /* @__PURE__ */ new Map();
|
|
56301
56301
|
debounceTimers = /* @__PURE__ */ new Map();
|
|
56302
|
-
debounceDelay =
|
|
56303
|
-
watchDebounceDelay =
|
|
56302
|
+
debounceDelay = 30;
|
|
56303
|
+
watchDebounceDelay = 75;
|
|
56304
56304
|
pollInterval = null;
|
|
56305
56305
|
stopped = false;
|
|
56306
56306
|
/**
|
|
@@ -56321,16 +56321,16 @@ var FileWatcher = class {
|
|
|
56321
56321
|
}
|
|
56322
56322
|
}
|
|
56323
56323
|
this.watcher = watch([join5(tasksDir, "*.md"), configPath], {
|
|
56324
|
-
persistent: true,
|
|
56325
56324
|
ignoreInitial: true,
|
|
56326
|
-
awaitWriteFinish: { stabilityThreshold:
|
|
56325
|
+
awaitWriteFinish: { stabilityThreshold: 25, pollInterval: 25 },
|
|
56326
|
+
alwaysStat: true
|
|
56327
56327
|
});
|
|
56328
56328
|
this.watcher.on("all", (event, path) => {
|
|
56329
56329
|
this.handleFsEvent(event, path, kandownDir);
|
|
56330
56330
|
});
|
|
56331
56331
|
this.pollInterval = setInterval(() => {
|
|
56332
56332
|
this.pollHashes(kandownDir);
|
|
56333
|
-
},
|
|
56333
|
+
}, 300);
|
|
56334
56334
|
}
|
|
56335
56335
|
/**
|
|
56336
56336
|
* 📖 Stop watching and clean up all resources.
|
|
@@ -56757,222 +56757,76 @@ function AgentPicker({ agents, taskId, onSelect, onCancel }) {
|
|
|
56757
56757
|
|
|
56758
56758
|
// src/cli/hooks/use-mouse.ts
|
|
56759
56759
|
var import_react36 = __toESM(require_react(), 1);
|
|
56760
|
-
var
|
|
56761
|
-
var
|
|
56762
|
-
var
|
|
56763
|
-
|
|
56764
|
-
|
|
56765
|
-
const sgrRegex = /^\x1b\[<(\d+);(\d+);(\d+)([Mm])/;
|
|
56766
|
-
const match = buffer.match(sgrRegex);
|
|
56760
|
+
var MOUSE_ENABLE = "\x1B[?1000h\x1B[?1006h";
|
|
56761
|
+
var MOUSE_DISABLE = "\x1B[?1006l\x1B[?1000l";
|
|
56762
|
+
var RE_SGR_MOUSE = /^\[<(\d+);(\d+);(\d+)([Mm])/;
|
|
56763
|
+
function parseMouseInput(input) {
|
|
56764
|
+
const match = input.match(RE_SGR_MOUSE);
|
|
56767
56765
|
if (!match) return null;
|
|
56768
56766
|
const cb = parseInt(match[1], 10);
|
|
56769
56767
|
const cx = parseInt(match[2], 10);
|
|
56770
56768
|
const cy = parseInt(match[3], 10);
|
|
56771
56769
|
const isPress = match[4] === "M";
|
|
56772
|
-
const button = cb & 3;
|
|
56773
|
-
const shift = (cb & 4) !== 0;
|
|
56774
|
-
const meta = (cb & 8) !== 0;
|
|
56775
|
-
const ctrl = (cb & 16) !== 0;
|
|
56776
56770
|
return {
|
|
56777
|
-
|
|
56778
|
-
|
|
56779
|
-
|
|
56780
|
-
|
|
56781
|
-
action: isPress ? "press" : "release",
|
|
56782
|
-
shift,
|
|
56783
|
-
meta,
|
|
56784
|
-
ctrl
|
|
56785
|
-
},
|
|
56786
|
-
endIndex: match[0].length
|
|
56771
|
+
x: cx,
|
|
56772
|
+
y: cy,
|
|
56773
|
+
button: cb & 3,
|
|
56774
|
+
action: isPress ? "press" : "release"
|
|
56787
56775
|
};
|
|
56788
56776
|
}
|
|
56789
|
-
function
|
|
56790
|
-
|
|
56791
|
-
if (buffer.length < 6) return null;
|
|
56792
|
-
const cb = buffer.charCodeAt(3) - 32;
|
|
56793
|
-
const cx = buffer.charCodeAt(4) - 32;
|
|
56794
|
-
const cy = buffer.charCodeAt(5) - 32;
|
|
56795
|
-
if (cb < 0 || cx < 0 || cy < 0) return null;
|
|
56796
|
-
const button = cb & 3;
|
|
56797
|
-
const shift = (cb & 4) !== 0;
|
|
56798
|
-
const meta = (cb & 8) !== 0;
|
|
56799
|
-
const ctrl = (cb & 16) !== 0;
|
|
56800
|
-
return {
|
|
56801
|
-
event: {
|
|
56802
|
-
x: cx,
|
|
56803
|
-
y: cy,
|
|
56804
|
-
button,
|
|
56805
|
-
action: "press",
|
|
56806
|
-
// X10 only reports press
|
|
56807
|
-
shift,
|
|
56808
|
-
meta,
|
|
56809
|
-
ctrl
|
|
56810
|
-
},
|
|
56811
|
-
endIndex: 6
|
|
56812
|
-
};
|
|
56777
|
+
function isMouseInput(input) {
|
|
56778
|
+
return input.startsWith("[<") || input.startsWith("[M");
|
|
56813
56779
|
}
|
|
56814
|
-
function
|
|
56815
|
-
const { enabled = true, pressOnly = true } = options;
|
|
56816
|
-
const handlerRef = (0, import_react36.useRef)(handler);
|
|
56817
|
-
handlerRef.current = handler;
|
|
56780
|
+
function useMouseMode(enabled = true) {
|
|
56818
56781
|
(0, import_react36.useEffect)(() => {
|
|
56819
56782
|
if (!enabled) return;
|
|
56820
|
-
|
|
56821
|
-
|
|
56822
|
-
process.stdout.write(MOUSE_ENABLE_SGR + MOUSE_ENABLE_X10);
|
|
56823
|
-
let buffer = "";
|
|
56824
|
-
const onData = (data) => {
|
|
56825
|
-
buffer += data.toString("utf8");
|
|
56826
|
-
while (buffer.length > 0) {
|
|
56827
|
-
let parsed = parseSGRMouse(buffer);
|
|
56828
|
-
if (!parsed) {
|
|
56829
|
-
parsed = parseX10Mouse(buffer);
|
|
56830
|
-
}
|
|
56831
|
-
if (parsed) {
|
|
56832
|
-
const { event, endIndex } = parsed;
|
|
56833
|
-
buffer = buffer.slice(endIndex);
|
|
56834
|
-
if (pressOnly && event.action === "release") continue;
|
|
56835
|
-
if (event.button === 3 && event.action === "press") continue;
|
|
56836
|
-
handlerRef.current(event);
|
|
56837
|
-
} else if (buffer.startsWith("\x1B[")) {
|
|
56838
|
-
if (buffer.length >= 3 && buffer[2] !== "<" && buffer[2] !== "M") {
|
|
56839
|
-
const leftover = buffer;
|
|
56840
|
-
buffer = "";
|
|
56841
|
-
stdin.unshift(Buffer.from(leftover, "utf8"));
|
|
56842
|
-
break;
|
|
56843
|
-
}
|
|
56844
|
-
if (buffer.length > 32) {
|
|
56845
|
-
const leftover = buffer;
|
|
56846
|
-
buffer = "";
|
|
56847
|
-
stdin.unshift(Buffer.from(leftover, "utf8"));
|
|
56848
|
-
}
|
|
56849
|
-
break;
|
|
56850
|
-
} else if (buffer.startsWith("\x1B") && buffer.length > 1 && buffer[1] !== "[") {
|
|
56851
|
-
const leftover = buffer;
|
|
56852
|
-
buffer = "";
|
|
56853
|
-
stdin.unshift(Buffer.from(leftover, "utf8"));
|
|
56854
|
-
break;
|
|
56855
|
-
} else if (buffer.startsWith("\x1B") && buffer.length === 1) {
|
|
56856
|
-
break;
|
|
56857
|
-
} else {
|
|
56858
|
-
const leftover = buffer;
|
|
56859
|
-
buffer = "";
|
|
56860
|
-
stdin.unshift(Buffer.from(leftover, "utf8"));
|
|
56861
|
-
break;
|
|
56862
|
-
}
|
|
56863
|
-
}
|
|
56864
|
-
if (buffer.length > 256) {
|
|
56865
|
-
const leftover = buffer;
|
|
56866
|
-
buffer = "";
|
|
56867
|
-
stdin.unshift(Buffer.from(leftover, "utf8"));
|
|
56868
|
-
}
|
|
56869
|
-
};
|
|
56870
|
-
stdin.prependListener("data", onData);
|
|
56783
|
+
if (!process.stdin.isTTY) return;
|
|
56784
|
+
process.stdout.write(MOUSE_ENABLE);
|
|
56871
56785
|
const cleanup = () => {
|
|
56872
|
-
process.stdout.write(
|
|
56786
|
+
process.stdout.write(MOUSE_DISABLE);
|
|
56873
56787
|
};
|
|
56874
56788
|
process.on("exit", cleanup);
|
|
56875
56789
|
return () => {
|
|
56876
|
-
stdin.removeListener("data", onData);
|
|
56877
56790
|
process.removeListener("exit", cleanup);
|
|
56878
|
-
process.stdout.write(
|
|
56791
|
+
process.stdout.write(MOUSE_DISABLE);
|
|
56879
56792
|
};
|
|
56880
|
-
}, [enabled
|
|
56793
|
+
}, [enabled]);
|
|
56881
56794
|
}
|
|
56882
56795
|
|
|
56883
56796
|
// src/cli/components/task-context-menu.tsx
|
|
56884
|
-
var import_react37 = __toESM(require_react(), 1);
|
|
56885
56797
|
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
56886
|
-
function
|
|
56887
|
-
|
|
56888
|
-
|
|
56889
|
-
|
|
56890
|
-
|
|
56891
|
-
|
|
56892
|
-
|
|
56893
|
-
|
|
56894
|
-
|
|
56895
|
-
|
|
56896
|
-
|
|
56897
|
-
|
|
56898
|
-
|
|
56899
|
-
|
|
56900
|
-
|
|
56901
|
-
|
|
56902
|
-
|
|
56903
|
-
|
|
56904
|
-
|
|
56905
|
-
|
|
56906
|
-
|
|
56907
|
-
|
|
56908
|
-
|
|
56909
|
-
|
|
56910
|
-
|
|
56911
|
-
|
|
56912
|
-
if (opt) onSelect(opt.id);
|
|
56913
|
-
return;
|
|
56914
|
-
}
|
|
56915
|
-
});
|
|
56916
|
-
const maxLabelLen = Math.max(...options.map((o) => o.label.length));
|
|
56917
|
-
const menuWidth = Math.max(24, maxLabelLen + 8);
|
|
56918
|
-
const lines = [];
|
|
56919
|
-
const startRow = menuStartRow ?? 0;
|
|
56920
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
56921
|
-
Box_default,
|
|
56922
|
-
{
|
|
56923
|
-
flexDirection: "column",
|
|
56924
|
-
paddingLeft: 2,
|
|
56925
|
-
marginTop: 0,
|
|
56926
|
-
children: [
|
|
56927
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { children: [
|
|
56928
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "gray", dimColor: true, children: "\u250C\u2500 " }),
|
|
56929
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "cyan", bold: true, children: taskId }),
|
|
56930
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "gray", dimColor: true, children: " \u2500\u2510" })
|
|
56931
|
-
] }),
|
|
56932
|
-
options.map((opt, idx) => {
|
|
56933
|
-
const focused = idx === cursor;
|
|
56934
|
-
const lineY = startRow + 1 + idx;
|
|
56935
|
-
lines.push({ optionId: opt.id, y: lineY });
|
|
56936
|
-
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { children: [
|
|
56937
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "gray", dimColor: true, children: "\u2502 " }),
|
|
56938
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
56939
|
-
Text,
|
|
56940
|
-
{
|
|
56941
|
-
color: focused ? "black" : "gray",
|
|
56942
|
-
backgroundColor: focused ? "cyan" : void 0,
|
|
56943
|
-
bold: focused,
|
|
56944
|
-
children: [
|
|
56945
|
-
focused ? "\u25B8" : " ",
|
|
56946
|
-
" ",
|
|
56947
|
-
opt.icon,
|
|
56948
|
-
" ",
|
|
56949
|
-
opt.label
|
|
56950
|
-
]
|
|
56951
|
-
}
|
|
56952
|
-
),
|
|
56953
|
-
!focused && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
56954
|
-
" ".repeat(Math.max(0, menuWidth - opt.label.length - 4)),
|
|
56955
|
-
"\u2502"
|
|
56956
|
-
] }),
|
|
56957
|
-
focused && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
56958
|
-
" ".repeat(Math.max(0, menuWidth - opt.label.length - 4)),
|
|
56959
|
-
"\u2502"
|
|
56960
|
-
] })
|
|
56961
|
-
] }, opt.id);
|
|
56962
|
-
}),
|
|
56963
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
56964
|
-
"\u2514",
|
|
56965
|
-
"\u2500".repeat(menuWidth),
|
|
56966
|
-
"\u2518"
|
|
56967
|
-
] }) })
|
|
56968
|
-
]
|
|
56969
|
-
}
|
|
56970
|
-
);
|
|
56798
|
+
function InlineContextMenu({ cursor, colWidth }) {
|
|
56799
|
+
const options = [
|
|
56800
|
+
{ label: "Open task", icon: "\u{1F4D6}" },
|
|
56801
|
+
{ label: "Move task", icon: "\u2197" }
|
|
56802
|
+
];
|
|
56803
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Box_default, { flexDirection: "column", children: options.map((opt, idx) => {
|
|
56804
|
+
const focused = idx === cursor;
|
|
56805
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(Box_default, { children: [
|
|
56806
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Text, { color: "gray", dimColor: true, children: " " }),
|
|
56807
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
56808
|
+
Text,
|
|
56809
|
+
{
|
|
56810
|
+
color: focused ? "black" : "gray",
|
|
56811
|
+
backgroundColor: focused ? "cyan" : void 0,
|
|
56812
|
+
bold: focused,
|
|
56813
|
+
children: [
|
|
56814
|
+
focused ? "\u25B8" : " ",
|
|
56815
|
+
" ",
|
|
56816
|
+
opt.icon,
|
|
56817
|
+
" ",
|
|
56818
|
+
opt.label
|
|
56819
|
+
]
|
|
56820
|
+
}
|
|
56821
|
+
)
|
|
56822
|
+
] }, opt.label);
|
|
56823
|
+
}) });
|
|
56971
56824
|
}
|
|
56825
|
+
var MENU_HEIGHT = 2;
|
|
56972
56826
|
|
|
56973
56827
|
// src/cli/screens/board.tsx
|
|
56974
56828
|
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
|
56975
|
-
var
|
|
56829
|
+
var TASKS_START_Y = 5;
|
|
56976
56830
|
function truncate(str, maxLen) {
|
|
56977
56831
|
if (str.length <= maxLen) return str;
|
|
56978
56832
|
return str.slice(0, maxLen - 1) + "\u2026";
|
|
@@ -56990,23 +56844,18 @@ function calcColWidth(numCols) {
|
|
|
56990
56844
|
}
|
|
56991
56845
|
var RE_HEADER = /^#{1,3}\s/;
|
|
56992
56846
|
var RE_SUBTASK = /^\s*-\s+\[([ xX])\]/;
|
|
56993
|
-
var
|
|
56847
|
+
var RE_DONE = /^\s*-\s+\[x\]/i;
|
|
56994
56848
|
var RE_BRACKET_TAG = /^\[([^\]]+)\]\s*/;
|
|
56995
|
-
function TaskRow({
|
|
56996
|
-
task,
|
|
56997
|
-
focused,
|
|
56998
|
-
colWidth
|
|
56999
|
-
}) {
|
|
56849
|
+
function TaskRow({ task, focused, colWidth }) {
|
|
57000
56850
|
const cursor = focused ? "\u25B8" : " ";
|
|
57001
56851
|
const check2 = task.checked ? "\u2713" : "\u25CB";
|
|
57002
56852
|
const idStr = task.id;
|
|
57003
56853
|
const tagMatch = task.title.match(RE_BRACKET_TAG);
|
|
57004
56854
|
const tag = tagMatch ? `[${tagMatch[1]}]` : "";
|
|
57005
|
-
const
|
|
56855
|
+
const titleClean = tagMatch ? task.title.slice(tagMatch[0].length) : task.title;
|
|
57006
56856
|
const fixedChars = 4 + idStr.length + 1;
|
|
57007
56857
|
const tagChars = tag ? tag.length + 1 : 0;
|
|
57008
|
-
const
|
|
57009
|
-
const titleStr = truncate(titleWithoutTag, Math.max(4, available));
|
|
56858
|
+
const titleStr = truncate(titleClean, Math.max(4, colWidth - fixedChars - tagChars));
|
|
57010
56859
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { children: [
|
|
57011
56860
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: focused ? "cyan" : void 0, bold: focused, children: [
|
|
57012
56861
|
cursor,
|
|
@@ -57027,12 +56876,7 @@ function TaskRow({
|
|
|
57027
56876
|
] })
|
|
57028
56877
|
] });
|
|
57029
56878
|
}
|
|
57030
|
-
function MovePlaceholder({
|
|
57031
|
-
name,
|
|
57032
|
-
focused,
|
|
57033
|
-
colWidth
|
|
57034
|
-
}) {
|
|
57035
|
-
const label = `\u2193 ${name}`;
|
|
56879
|
+
function MovePlaceholder({ name, focused, colWidth }) {
|
|
57036
56880
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
57037
56881
|
Text,
|
|
57038
56882
|
{
|
|
@@ -57041,7 +56885,7 @@ function MovePlaceholder({
|
|
|
57041
56885
|
bold: focused,
|
|
57042
56886
|
children: [
|
|
57043
56887
|
" ",
|
|
57044
|
-
pad(
|
|
56888
|
+
pad(`\u2193 ${name}`, colWidth - 2)
|
|
57045
56889
|
]
|
|
57046
56890
|
}
|
|
57047
56891
|
) });
|
|
@@ -57052,35 +56896,54 @@ function KanbanColumn({
|
|
|
57052
56896
|
focusedRow,
|
|
57053
56897
|
isFocused,
|
|
57054
56898
|
colWidth,
|
|
56899
|
+
contextMenuRow,
|
|
56900
|
+
contextMenuCursor,
|
|
57055
56901
|
showMoveTarget,
|
|
57056
56902
|
isMoveFocused
|
|
57057
56903
|
}) {
|
|
57058
56904
|
const headerBg = isFocused ? "cyan" : void 0;
|
|
57059
56905
|
const headerColor = isFocused ? "black" : "cyan";
|
|
57060
56906
|
const countStr = tasks.length > 0 ? ` (${tasks.length})` : "";
|
|
57061
|
-
const
|
|
56907
|
+
const rows = [];
|
|
56908
|
+
tasks.forEach((task, idx) => {
|
|
56909
|
+
rows.push(
|
|
56910
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
56911
|
+
TaskRow,
|
|
56912
|
+
{
|
|
56913
|
+
task,
|
|
56914
|
+
focused: isFocused && idx === focusedRow,
|
|
56915
|
+
colWidth
|
|
56916
|
+
},
|
|
56917
|
+
task.id
|
|
56918
|
+
)
|
|
56919
|
+
);
|
|
56920
|
+
if (contextMenuRow === idx) {
|
|
56921
|
+
rows.push(
|
|
56922
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
56923
|
+
InlineContextMenu,
|
|
56924
|
+
{
|
|
56925
|
+
cursor: contextMenuCursor ?? 0,
|
|
56926
|
+
colWidth
|
|
56927
|
+
},
|
|
56928
|
+
"ctx-menu"
|
|
56929
|
+
)
|
|
56930
|
+
);
|
|
56931
|
+
}
|
|
56932
|
+
});
|
|
57062
56933
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", width: colWidth, marginRight: 1, children: [
|
|
57063
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { backgroundColor: headerBg, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: headerColor, bold: true, children: pad(
|
|
56934
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { backgroundColor: headerBg, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: headerColor, bold: true, children: pad(`${name}${countStr}`, colWidth) }) }),
|
|
57064
56935
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: isFocused ? "cyan" : "gray", children: "\u2500".repeat(colWidth) }),
|
|
57065
56936
|
tasks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
57066
56937
|
" ".repeat(2),
|
|
57067
56938
|
"(empty)"
|
|
57068
|
-
] }) :
|
|
57069
|
-
TaskRow,
|
|
57070
|
-
{
|
|
57071
|
-
task,
|
|
57072
|
-
focused: isFocused && idx === focusedRow,
|
|
57073
|
-
colWidth
|
|
57074
|
-
},
|
|
57075
|
-
task.id
|
|
57076
|
-
)),
|
|
56939
|
+
] }) : rows,
|
|
57077
56940
|
showMoveTarget && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MovePlaceholder, { name, focused: !!isMoveFocused, colWidth })
|
|
57078
56941
|
] });
|
|
57079
56942
|
}
|
|
57080
56943
|
function BoardHeader({ title, inTmux, modeHint, version }) {
|
|
57081
56944
|
const tmuxHint = inTmux ? " tmux" : "";
|
|
57082
|
-
const hint = modeHint || "h/l cols j/k tasks Enter detail a agent r reload q quit";
|
|
57083
56945
|
const versionTag = version ? ` v${version}` : "";
|
|
56946
|
+
const hint = modeHint || "h/l cols \xB7 j/k tasks \xB7 Enter detail \xB7 m menu \xB7 a agent \xB7 r reload \xB7 q quit";
|
|
57084
56947
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { marginBottom: 1, justifyContent: "space-between", children: [
|
|
57085
56948
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { bold: true, color: "cyan", children: [
|
|
57086
56949
|
" ",
|
|
@@ -57099,17 +56962,13 @@ function StatusBar({ message, task }) {
|
|
|
57099
56962
|
}
|
|
57100
56963
|
if (!task) return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: " " }) });
|
|
57101
56964
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", children: [
|
|
57102
|
-
task.id
|
|
56965
|
+
task.id,
|
|
57103
56966
|
task.progress ? ` (${task.progress.done}/${task.progress.total})` : "",
|
|
57104
56967
|
" ",
|
|
57105
56968
|
task.checked ? "\u2713 done" : "\u25CB open"
|
|
57106
56969
|
] }) });
|
|
57107
56970
|
}
|
|
57108
|
-
function TaskDetail({
|
|
57109
|
-
task,
|
|
57110
|
-
taskId,
|
|
57111
|
-
scrollOffset
|
|
57112
|
-
}) {
|
|
56971
|
+
function TaskDetail({ task, taskId, scrollOffset }) {
|
|
57113
56972
|
const fm = task.frontmatter;
|
|
57114
56973
|
const bodyLines = task.body.split("\n");
|
|
57115
56974
|
const maxVisible = (process.stdout.rows || 24) - 10;
|
|
@@ -57131,14 +56990,14 @@ function TaskDetail({
|
|
|
57131
56990
|
] }) }),
|
|
57132
56991
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: "\u2500".repeat(termWidth() - 4) }),
|
|
57133
56992
|
visibleLines.map((line, idx) => {
|
|
57134
|
-
const
|
|
57135
|
-
const
|
|
57136
|
-
const
|
|
56993
|
+
const isH = RE_HEADER.test(line);
|
|
56994
|
+
const isS = RE_SUBTASK.test(line);
|
|
56995
|
+
const isD = RE_DONE.test(line);
|
|
57137
56996
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
57138
56997
|
Text,
|
|
57139
56998
|
{
|
|
57140
|
-
color:
|
|
57141
|
-
bold:
|
|
56999
|
+
color: isH ? "cyan" : isD ? "green" : isS ? "white" : "gray",
|
|
57000
|
+
bold: isH,
|
|
57142
57001
|
children: line || " "
|
|
57143
57002
|
},
|
|
57144
57003
|
scrollOffset + idx
|
|
@@ -57158,25 +57017,25 @@ function TaskDetail({
|
|
|
57158
57017
|
}
|
|
57159
57018
|
function Board({ kandownDir, version }) {
|
|
57160
57019
|
const { exit } = use_app_default();
|
|
57161
|
-
const [board, setBoard] = (0,
|
|
57162
|
-
const [colIndex, setColIndex] = (0,
|
|
57163
|
-
const [rowIndex, setRowIndex] = (0,
|
|
57164
|
-
const [mode, setMode] = (0,
|
|
57165
|
-
const [
|
|
57166
|
-
const [
|
|
57167
|
-
const [
|
|
57168
|
-
const [
|
|
57169
|
-
const [
|
|
57170
|
-
const [
|
|
57171
|
-
const [moveTaskId, setMoveTaskId] = (0,
|
|
57172
|
-
const [moveTargetCol, setMoveTargetCol] = (0,
|
|
57020
|
+
const [board, setBoard] = (0, import_react37.useState)(null);
|
|
57021
|
+
const [colIndex, setColIndex] = (0, import_react37.useState)(0);
|
|
57022
|
+
const [rowIndex, setRowIndex] = (0, import_react37.useState)(0);
|
|
57023
|
+
const [mode, setMode] = (0, import_react37.useState)("browse");
|
|
57024
|
+
const [statusMsg, setStatusMsg] = (0, import_react37.useState)("");
|
|
57025
|
+
const [detailTask, setDetailTask] = (0, import_react37.useState)(null);
|
|
57026
|
+
const [detailTaskId, setDetailTaskId] = (0, import_react37.useState)("");
|
|
57027
|
+
const [detailScroll, setDetailScroll] = (0, import_react37.useState)(0);
|
|
57028
|
+
const [ctxMenuRow, setCtxMenuRow] = (0, import_react37.useState)(-1);
|
|
57029
|
+
const [ctxMenuCursor, setCtxMenuCursor] = (0, import_react37.useState)(0);
|
|
57030
|
+
const [moveTaskId, setMoveTaskId] = (0, import_react37.useState)(null);
|
|
57031
|
+
const [moveTargetCol, setMoveTargetCol] = (0, import_react37.useState)(0);
|
|
57032
|
+
const [installedAgents, setInstalledAgents] = (0, import_react37.useState)([]);
|
|
57173
57033
|
const inTmux = isInTmux();
|
|
57174
|
-
const layoutRef = (0,
|
|
57034
|
+
const layoutRef = (0, import_react37.useRef)({
|
|
57175
57035
|
colStarts: [],
|
|
57176
|
-
colWidth: 0
|
|
57177
|
-
colTaskCounts: []
|
|
57036
|
+
colWidth: 0
|
|
57178
57037
|
});
|
|
57179
|
-
const updateLayout = (0,
|
|
57038
|
+
const updateLayout = (0, import_react37.useCallback)((b) => {
|
|
57180
57039
|
if (!b) return;
|
|
57181
57040
|
const cw = calcColWidth(b.columns.length);
|
|
57182
57041
|
const starts = [];
|
|
@@ -57185,19 +57044,15 @@ function Board({ kandownDir, version }) {
|
|
|
57185
57044
|
starts.push(x);
|
|
57186
57045
|
x += cw + 1;
|
|
57187
57046
|
}
|
|
57188
|
-
layoutRef.current = {
|
|
57189
|
-
colStarts: starts,
|
|
57190
|
-
colWidth: cw,
|
|
57191
|
-
colTaskCounts: b.columns.map((c) => c.tasks.length)
|
|
57192
|
-
};
|
|
57047
|
+
layoutRef.current = { colStarts: starts, colWidth: cw };
|
|
57193
57048
|
}, []);
|
|
57194
|
-
(0,
|
|
57049
|
+
(0, import_react37.useEffect)(() => {
|
|
57195
57050
|
const loaded = readBoard(kandownDir);
|
|
57196
57051
|
setBoard(loaded);
|
|
57197
57052
|
updateLayout(loaded);
|
|
57198
57053
|
setInstalledAgents(detectInstalledAgents());
|
|
57199
57054
|
}, [kandownDir, updateLayout]);
|
|
57200
|
-
(0,
|
|
57055
|
+
(0, import_react37.useEffect)(() => {
|
|
57201
57056
|
const watcher = createWatcher();
|
|
57202
57057
|
watcher.on("taskChanged", () => {
|
|
57203
57058
|
const loaded = readBoard(kandownDir);
|
|
@@ -57221,27 +57076,31 @@ function Board({ kandownDir, version }) {
|
|
|
57221
57076
|
watcher.stop();
|
|
57222
57077
|
};
|
|
57223
57078
|
}, [kandownDir, updateLayout]);
|
|
57224
|
-
const reloadBoard = (0,
|
|
57079
|
+
const reloadBoard = (0, import_react37.useCallback)(() => {
|
|
57225
57080
|
const loaded = readBoard(kandownDir);
|
|
57226
57081
|
setBoard(loaded);
|
|
57227
57082
|
updateLayout(loaded);
|
|
57228
57083
|
setStatusMsg("Board reloaded");
|
|
57229
57084
|
setTimeout(() => setStatusMsg(""), 1500);
|
|
57230
57085
|
}, [kandownDir, updateLayout]);
|
|
57231
|
-
const getFocusedTask = (0,
|
|
57086
|
+
const getFocusedTask = (0, import_react37.useCallback)(() => {
|
|
57232
57087
|
if (!board) return null;
|
|
57233
57088
|
const col = board.columns[colIndex];
|
|
57234
57089
|
if (!col || col.tasks.length === 0) return null;
|
|
57235
57090
|
return col.tasks[Math.min(rowIndex, col.tasks.length - 1)] ?? null;
|
|
57236
57091
|
}, [board, colIndex, rowIndex]);
|
|
57237
|
-
const openDetail = (0,
|
|
57092
|
+
const openDetail = (0, import_react37.useCallback)((taskId) => {
|
|
57238
57093
|
const task = readTask(kandownDir, taskId);
|
|
57239
57094
|
setDetailTask(task);
|
|
57240
57095
|
setDetailTaskId(taskId);
|
|
57241
57096
|
setDetailScroll(0);
|
|
57242
57097
|
setMode("detail");
|
|
57243
57098
|
}, [kandownDir]);
|
|
57244
|
-
const
|
|
57099
|
+
const closeContextMenu = (0, import_react37.useCallback)(() => {
|
|
57100
|
+
setCtxMenuRow(-1);
|
|
57101
|
+
setCtxMenuCursor(0);
|
|
57102
|
+
}, []);
|
|
57103
|
+
const handleAgentSelect = (0, import_react37.useCallback)((agentId) => {
|
|
57245
57104
|
const task = getFocusedTask();
|
|
57246
57105
|
const taskId = mode === "detail" ? detailTaskId : task?.id;
|
|
57247
57106
|
if (!taskId) return;
|
|
@@ -57249,12 +57108,7 @@ function Board({ kandownDir, version }) {
|
|
|
57249
57108
|
setStatusMsg(`Launching ${agentId} for ${taskId}\u2026`);
|
|
57250
57109
|
setTimeout(() => {
|
|
57251
57110
|
try {
|
|
57252
|
-
launchAgent({
|
|
57253
|
-
taskId,
|
|
57254
|
-
agentId,
|
|
57255
|
-
kandownDir,
|
|
57256
|
-
onBeforeExec: () => exit()
|
|
57257
|
-
});
|
|
57111
|
+
launchAgent({ taskId, agentId, kandownDir, onBeforeExec: () => exit() });
|
|
57258
57112
|
reloadBoard();
|
|
57259
57113
|
setStatusMsg(`${agentId} launched in tmux pane`);
|
|
57260
57114
|
setTimeout(() => setStatusMsg(""), 3e3);
|
|
@@ -57264,122 +57118,135 @@ function Board({ kandownDir, version }) {
|
|
|
57264
57118
|
}
|
|
57265
57119
|
}, 50);
|
|
57266
57120
|
}, [mode, detailTaskId, getFocusedTask, kandownDir, exit, reloadBoard]);
|
|
57267
|
-
|
|
57268
|
-
|
|
57121
|
+
useMouseMode(mode !== "agent-picker");
|
|
57122
|
+
const handleMouseClick = (0, import_react37.useCallback)((x, y) => {
|
|
57269
57123
|
if (!board) return;
|
|
57270
|
-
const { x, y } = evt;
|
|
57271
57124
|
const layout = layoutRef.current;
|
|
57125
|
+
let clickedCol = -1;
|
|
57126
|
+
for (let c = 0; c < layout.colStarts.length; c++) {
|
|
57127
|
+
const start = layout.colStarts[c];
|
|
57128
|
+
if (x >= start && x < start + layout.colWidth) {
|
|
57129
|
+
clickedCol = c;
|
|
57130
|
+
break;
|
|
57131
|
+
}
|
|
57132
|
+
}
|
|
57272
57133
|
if (mode === "browse") {
|
|
57273
|
-
|
|
57274
|
-
|
|
57275
|
-
|
|
57276
|
-
|
|
57277
|
-
|
|
57278
|
-
|
|
57279
|
-
|
|
57280
|
-
|
|
57281
|
-
|
|
57282
|
-
if (task) {
|
|
57283
|
-
setContextTaskId(task.id);
|
|
57284
|
-
setMode("context-menu");
|
|
57285
|
-
}
|
|
57286
|
-
return;
|
|
57287
|
-
}
|
|
57288
|
-
}
|
|
57134
|
+
if (clickedCol < 0) return;
|
|
57135
|
+
const col = board.columns[clickedCol];
|
|
57136
|
+
const taskIdx = y - TASKS_START_Y;
|
|
57137
|
+
if (taskIdx >= 0 && taskIdx < col.tasks.length) {
|
|
57138
|
+
setColIndex(clickedCol);
|
|
57139
|
+
setRowIndex(taskIdx);
|
|
57140
|
+
setCtxMenuRow(taskIdx);
|
|
57141
|
+
setCtxMenuCursor(0);
|
|
57142
|
+
setMode("context-menu");
|
|
57289
57143
|
}
|
|
57290
57144
|
return;
|
|
57291
57145
|
}
|
|
57292
57146
|
if (mode === "context-menu") {
|
|
57293
|
-
|
|
57294
|
-
|
|
57295
|
-
|
|
57296
|
-
if (menuRow === 1) {
|
|
57297
|
-
if (contextTaskId) {
|
|
57298
|
-
setContextTaskId(null);
|
|
57299
|
-
openDetail(contextTaskId);
|
|
57300
|
-
}
|
|
57147
|
+
if (clickedCol < 0) {
|
|
57148
|
+
closeContextMenu();
|
|
57149
|
+
setMode("browse");
|
|
57301
57150
|
return;
|
|
57302
57151
|
}
|
|
57303
|
-
|
|
57304
|
-
|
|
57305
|
-
|
|
57306
|
-
|
|
57307
|
-
|
|
57308
|
-
|
|
57309
|
-
|
|
57310
|
-
|
|
57152
|
+
const col = board.columns[clickedCol];
|
|
57153
|
+
const hasMenu = clickedCol === colIndex && ctxMenuRow >= 0;
|
|
57154
|
+
if (hasMenu) {
|
|
57155
|
+
const taskIdx = y - TASKS_START_Y;
|
|
57156
|
+
if (taskIdx >= 0 && taskIdx < ctxMenuRow) {
|
|
57157
|
+
setRowIndex(taskIdx);
|
|
57158
|
+
setCtxMenuRow(taskIdx);
|
|
57159
|
+
setCtxMenuCursor(0);
|
|
57160
|
+
return;
|
|
57311
57161
|
}
|
|
57312
|
-
|
|
57313
|
-
|
|
57314
|
-
|
|
57315
|
-
|
|
57316
|
-
|
|
57317
|
-
|
|
57318
|
-
|
|
57319
|
-
|
|
57320
|
-
|
|
57321
|
-
|
|
57322
|
-
|
|
57323
|
-
|
|
57324
|
-
|
|
57325
|
-
|
|
57326
|
-
|
|
57327
|
-
|
|
57162
|
+
if (taskIdx === ctxMenuRow) {
|
|
57163
|
+
closeContextMenu();
|
|
57164
|
+
setMode("browse");
|
|
57165
|
+
return;
|
|
57166
|
+
}
|
|
57167
|
+
const menuOffset = taskIdx - ctxMenuRow - 1;
|
|
57168
|
+
if (menuOffset >= 0 && menuOffset < MENU_HEIGHT) {
|
|
57169
|
+
if (menuOffset === 0) {
|
|
57170
|
+
const task = col.tasks[ctxMenuRow];
|
|
57171
|
+
if (task) {
|
|
57172
|
+
closeContextMenu();
|
|
57173
|
+
openDetail(task.id);
|
|
57174
|
+
}
|
|
57175
|
+
} else {
|
|
57176
|
+
const task = col.tasks[ctxMenuRow];
|
|
57177
|
+
if (task) {
|
|
57178
|
+
setMoveTaskId(task.id);
|
|
57179
|
+
const target = colIndex === 0 ? Math.min(1, board.columns.length - 1) : 0;
|
|
57180
|
+
setMoveTargetCol(target);
|
|
57181
|
+
closeContextMenu();
|
|
57182
|
+
setMode("move-target");
|
|
57328
57183
|
}
|
|
57329
57184
|
}
|
|
57185
|
+
return;
|
|
57186
|
+
}
|
|
57187
|
+
const belowIdx = taskIdx - MENU_HEIGHT;
|
|
57188
|
+
if (belowIdx >= 0 && belowIdx < col.tasks.length) {
|
|
57189
|
+
setRowIndex(belowIdx);
|
|
57190
|
+
closeContextMenu();
|
|
57191
|
+
setCtxMenuRow(belowIdx);
|
|
57192
|
+
setCtxMenuCursor(0);
|
|
57193
|
+
return;
|
|
57194
|
+
}
|
|
57195
|
+
} else {
|
|
57196
|
+
const taskIdx = y - TASKS_START_Y;
|
|
57197
|
+
if (taskIdx >= 0 && taskIdx < col.tasks.length) {
|
|
57198
|
+
closeContextMenu();
|
|
57199
|
+
setColIndex(clickedCol);
|
|
57200
|
+
setRowIndex(taskIdx);
|
|
57201
|
+
setCtxMenuRow(taskIdx);
|
|
57202
|
+
setCtxMenuCursor(0);
|
|
57203
|
+
return;
|
|
57330
57204
|
}
|
|
57331
|
-
setContextTaskId(null);
|
|
57332
|
-
setMode("browse");
|
|
57333
57205
|
}
|
|
57206
|
+
closeContextMenu();
|
|
57207
|
+
setMode("browse");
|
|
57334
57208
|
return;
|
|
57335
57209
|
}
|
|
57336
57210
|
if (mode === "move-target") {
|
|
57337
|
-
|
|
57338
|
-
|
|
57339
|
-
|
|
57340
|
-
|
|
57341
|
-
const colEnd = colStart + layout.colWidth;
|
|
57342
|
-
const colTaskCount = board.columns[c].tasks.length;
|
|
57343
|
-
const placeholderRow = HEADER_LINES + colTaskCount;
|
|
57344
|
-
if (x >= colStart && x <= colEnd && y === placeholderRow) {
|
|
57345
|
-
const targetColName = board.columns[c].name;
|
|
57346
|
-
if (moveTaskId && targetColName) {
|
|
57347
|
-
moveTaskToColumn(kandownDir, moveTaskId, targetColName);
|
|
57348
|
-
const loaded = readBoard(kandownDir);
|
|
57349
|
-
setBoard(loaded);
|
|
57350
|
-
updateLayout(loaded);
|
|
57351
|
-
setStatusMsg(`Moved ${moveTaskId} \u2192 ${targetColName}`);
|
|
57352
|
-
setTimeout(() => setStatusMsg(""), 2e3);
|
|
57353
|
-
}
|
|
57354
|
-
setMoveTaskId(null);
|
|
57355
|
-
setMode("browse");
|
|
57356
|
-
clickedPlaceholder = true;
|
|
57357
|
-
break;
|
|
57358
|
-
}
|
|
57211
|
+
if (clickedCol < 0) {
|
|
57212
|
+
setMoveTaskId(null);
|
|
57213
|
+
setMode("browse");
|
|
57214
|
+
return;
|
|
57359
57215
|
}
|
|
57360
|
-
if (
|
|
57361
|
-
|
|
57362
|
-
|
|
57363
|
-
|
|
57364
|
-
|
|
57365
|
-
|
|
57366
|
-
|
|
57367
|
-
|
|
57368
|
-
|
|
57369
|
-
|
|
57370
|
-
|
|
57371
|
-
|
|
57372
|
-
|
|
57373
|
-
|
|
57374
|
-
|
|
57375
|
-
|
|
57216
|
+
if (clickedCol === colIndex) {
|
|
57217
|
+
setMoveTaskId(null);
|
|
57218
|
+
setMode("browse");
|
|
57219
|
+
return;
|
|
57220
|
+
}
|
|
57221
|
+
const col = board.columns[clickedCol];
|
|
57222
|
+
const placeholderY = TASKS_START_Y + col.tasks.length;
|
|
57223
|
+
if (y === placeholderY) {
|
|
57224
|
+
const targetColName = col.name;
|
|
57225
|
+
if (moveTaskId) {
|
|
57226
|
+
moveTaskToColumn(kandownDir, moveTaskId, targetColName);
|
|
57227
|
+
const loaded = readBoard(kandownDir);
|
|
57228
|
+
setBoard(loaded);
|
|
57229
|
+
updateLayout(loaded);
|
|
57230
|
+
setStatusMsg(`Moved ${moveTaskId} \u2192 ${targetColName}`);
|
|
57231
|
+
setTimeout(() => setStatusMsg(""), 2e3);
|
|
57376
57232
|
}
|
|
57233
|
+
setMoveTaskId(null);
|
|
57234
|
+
setMode("browse");
|
|
57235
|
+
return;
|
|
57377
57236
|
}
|
|
57237
|
+
setMoveTaskId(null);
|
|
57238
|
+
setMode("browse");
|
|
57378
57239
|
return;
|
|
57379
57240
|
}
|
|
57380
|
-
}, [board, mode, colIndex,
|
|
57381
|
-
useMouse(handleMouseClick, { enabled: mode !== "agent-picker" });
|
|
57241
|
+
}, [board, mode, colIndex, rowIndex, ctxMenuRow, moveTaskId, kandownDir, updateLayout, openDetail, closeContextMenu]);
|
|
57382
57242
|
use_input_default((input, key) => {
|
|
57243
|
+
if (isMouseInput(input)) {
|
|
57244
|
+
const mouse = parseMouseInput(input);
|
|
57245
|
+
if (mouse && mouse.action === "press" && mouse.button === 0) {
|
|
57246
|
+
handleMouseClick(mouse.x, mouse.y);
|
|
57247
|
+
}
|
|
57248
|
+
return;
|
|
57249
|
+
}
|
|
57383
57250
|
if (mode === "browse") {
|
|
57384
57251
|
if (input === "q" || key.escape) {
|
|
57385
57252
|
exit();
|
|
@@ -57415,9 +57282,18 @@ function Board({ kandownDir, version }) {
|
|
|
57415
57282
|
if (task) openDetail(task.id);
|
|
57416
57283
|
return;
|
|
57417
57284
|
}
|
|
57285
|
+
if (input === "m") {
|
|
57286
|
+
const col = board?.columns[colIndex];
|
|
57287
|
+
if (col && col.tasks.length > 0) {
|
|
57288
|
+
setCtxMenuRow(rowIndex);
|
|
57289
|
+
setCtxMenuCursor(0);
|
|
57290
|
+
setMode("context-menu");
|
|
57291
|
+
}
|
|
57292
|
+
return;
|
|
57293
|
+
}
|
|
57418
57294
|
if (input === "a") {
|
|
57419
57295
|
if (installedAgents.length === 0) {
|
|
57420
|
-
setStatusMsg("No AI agents found in PATH
|
|
57296
|
+
setStatusMsg("No AI agents found in PATH");
|
|
57421
57297
|
setTimeout(() => setStatusMsg(""), 3e3);
|
|
57422
57298
|
return;
|
|
57423
57299
|
}
|
|
@@ -57428,7 +57304,36 @@ function Board({ kandownDir, version }) {
|
|
|
57428
57304
|
}
|
|
57429
57305
|
}
|
|
57430
57306
|
if (mode === "context-menu") {
|
|
57431
|
-
|
|
57307
|
+
if (key.escape || input === "q") {
|
|
57308
|
+
closeContextMenu();
|
|
57309
|
+
setMode("browse");
|
|
57310
|
+
return;
|
|
57311
|
+
}
|
|
57312
|
+
if (input === "j" || key.downArrow) {
|
|
57313
|
+
setCtxMenuCursor((c) => Math.min(c + 1, 1));
|
|
57314
|
+
return;
|
|
57315
|
+
}
|
|
57316
|
+
if (input === "k" || key.upArrow) {
|
|
57317
|
+
setCtxMenuCursor((c) => Math.max(c - 1, 0));
|
|
57318
|
+
return;
|
|
57319
|
+
}
|
|
57320
|
+
if (key.return) {
|
|
57321
|
+
const col = board?.columns[colIndex];
|
|
57322
|
+
if (!col) return;
|
|
57323
|
+
const task = col.tasks[ctxMenuRow];
|
|
57324
|
+
if (!task) return;
|
|
57325
|
+
if (ctxMenuCursor === 0) {
|
|
57326
|
+
closeContextMenu();
|
|
57327
|
+
openDetail(task.id);
|
|
57328
|
+
} else {
|
|
57329
|
+
setMoveTaskId(task.id);
|
|
57330
|
+
const target = colIndex === 0 ? Math.min(1, (board?.columns.length ?? 1) - 1) : 0;
|
|
57331
|
+
setMoveTargetCol(target);
|
|
57332
|
+
closeContextMenu();
|
|
57333
|
+
setMode("move-target");
|
|
57334
|
+
}
|
|
57335
|
+
return;
|
|
57336
|
+
}
|
|
57432
57337
|
}
|
|
57433
57338
|
if (mode === "move-target") {
|
|
57434
57339
|
if (key.escape || input === "q") {
|
|
@@ -57438,29 +57343,27 @@ function Board({ kandownDir, version }) {
|
|
|
57438
57343
|
}
|
|
57439
57344
|
if (input === "l" || key.rightArrow) {
|
|
57440
57345
|
if (!board) return;
|
|
57441
|
-
const
|
|
57442
|
-
const
|
|
57443
|
-
|
|
57444
|
-
setMoveTargetCol(otherCols[nextIdx] ?? 0);
|
|
57346
|
+
const others = board.columns.map((_, i) => i).filter((i) => i !== colIndex);
|
|
57347
|
+
const cur = others.indexOf(moveTargetCol);
|
|
57348
|
+
setMoveTargetCol(others[Math.min(cur + 1, others.length - 1)] ?? 0);
|
|
57445
57349
|
return;
|
|
57446
57350
|
}
|
|
57447
57351
|
if (input === "h" || key.leftArrow) {
|
|
57448
57352
|
if (!board) return;
|
|
57449
|
-
const
|
|
57450
|
-
const
|
|
57451
|
-
|
|
57452
|
-
setMoveTargetCol(otherCols[prevIdx] ?? 0);
|
|
57353
|
+
const others = board.columns.map((_, i) => i).filter((i) => i !== colIndex);
|
|
57354
|
+
const cur = others.indexOf(moveTargetCol);
|
|
57355
|
+
setMoveTargetCol(others[Math.max(cur - 1, 0)] ?? 0);
|
|
57453
57356
|
return;
|
|
57454
57357
|
}
|
|
57455
57358
|
if (key.return) {
|
|
57456
57359
|
if (!board || !moveTaskId) return;
|
|
57457
|
-
const
|
|
57458
|
-
if (
|
|
57459
|
-
moveTaskToColumn(kandownDir, moveTaskId,
|
|
57360
|
+
const name = board.columns[moveTargetCol]?.name;
|
|
57361
|
+
if (name) {
|
|
57362
|
+
moveTaskToColumn(kandownDir, moveTaskId, name);
|
|
57460
57363
|
const loaded = readBoard(kandownDir);
|
|
57461
57364
|
setBoard(loaded);
|
|
57462
57365
|
updateLayout(loaded);
|
|
57463
|
-
setStatusMsg(`Moved ${moveTaskId} \u2192 ${
|
|
57366
|
+
setStatusMsg(`Moved ${moveTaskId} \u2192 ${name}`);
|
|
57464
57367
|
setTimeout(() => setStatusMsg(""), 2e3);
|
|
57465
57368
|
}
|
|
57466
57369
|
setMoveTaskId(null);
|
|
@@ -57504,12 +57407,18 @@ function Board({ kandownDir, version }) {
|
|
|
57504
57407
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", children: [
|
|
57505
57408
|
"Run ",
|
|
57506
57409
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "kandown init" }),
|
|
57507
|
-
" to set up
|
|
57410
|
+
" to set up."
|
|
57508
57411
|
] })
|
|
57509
57412
|
] });
|
|
57510
57413
|
}
|
|
57511
57414
|
const colWidth = calcColWidth(board.columns.length);
|
|
57512
57415
|
const focusedTask = getFocusedTask();
|
|
57416
|
+
let modeHint;
|
|
57417
|
+
if (mode === "context-menu") {
|
|
57418
|
+
modeHint = "j/k choose \xB7 Enter confirm \xB7 Esc cancel \xB7 or click";
|
|
57419
|
+
} else if (mode === "move-target") {
|
|
57420
|
+
modeHint = "\u2190/\u2192 pick column \xB7 Enter confirm \xB7 Esc cancel \xB7 or click \u2193";
|
|
57421
|
+
}
|
|
57513
57422
|
if (mode === "agent-picker") {
|
|
57514
57423
|
const taskId = detailTaskId || focusedTask?.id || "";
|
|
57515
57424
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
@@ -57528,7 +57437,7 @@ function Board({ kandownDir, version }) {
|
|
|
57528
57437
|
if (mode === "detail" && detailTask) {
|
|
57529
57438
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
57530
57439
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { marginBottom: 1, justifyContent: "space-between", children: [
|
|
57531
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: "Esc back
|
|
57440
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: "Esc back \xB7 a agent \xB7 j/k scroll" }),
|
|
57532
57441
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
57533
57442
|
"KANDOWN ",
|
|
57534
57443
|
board.title
|
|
@@ -57538,16 +57447,6 @@ function Board({ kandownDir, version }) {
|
|
|
57538
57447
|
statusMsg && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "yellow", children: statusMsg }) })
|
|
57539
57448
|
] });
|
|
57540
57449
|
}
|
|
57541
|
-
const contextMenuOptions = [
|
|
57542
|
-
{ id: "open", label: "Open task", icon: "\u{1F4D6}" },
|
|
57543
|
-
{ id: "move", label: "Move task", icon: "\u2197" }
|
|
57544
|
-
];
|
|
57545
|
-
let modeHint;
|
|
57546
|
-
if (mode === "context-menu") {
|
|
57547
|
-
modeHint = "\u2191/\u2193 navigate Enter confirm Esc cancel (or click)";
|
|
57548
|
-
} else if (mode === "move-target") {
|
|
57549
|
-
modeHint = "\u2190/\u2192 pick column Enter confirm Esc cancel (or click \u2193 placeholder)";
|
|
57550
|
-
}
|
|
57551
57450
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
57552
57451
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BoardHeader, { title: board.title, inTmux, modeHint, version }),
|
|
57553
57452
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { flexDirection: "row", children: board.columns.map((col, cIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -57558,42 +57457,19 @@ function Board({ kandownDir, version }) {
|
|
|
57558
57457
|
focusedRow: cIdx === colIndex ? rowIndex : -1,
|
|
57559
57458
|
isFocused: cIdx === colIndex,
|
|
57560
57459
|
colWidth,
|
|
57460
|
+
contextMenuRow: mode === "context-menu" && cIdx === colIndex ? ctxMenuRow : -1,
|
|
57461
|
+
contextMenuCursor: ctxMenuCursor,
|
|
57561
57462
|
showMoveTarget: mode === "move-target" && cIdx !== colIndex,
|
|
57562
57463
|
isMoveFocused: mode === "move-target" && cIdx === moveTargetCol
|
|
57563
57464
|
},
|
|
57564
57465
|
col.name
|
|
57565
57466
|
)) }),
|
|
57566
|
-
mode === "context-menu" && contextTaskId && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 0, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
57567
|
-
TaskContextMenu,
|
|
57568
|
-
{
|
|
57569
|
-
taskId: contextTaskId,
|
|
57570
|
-
options: contextMenuOptions,
|
|
57571
|
-
onSelect: (optionId) => {
|
|
57572
|
-
if (optionId === "open") {
|
|
57573
|
-
setContextTaskId(null);
|
|
57574
|
-
openDetail(contextTaskId);
|
|
57575
|
-
} else if (optionId === "move") {
|
|
57576
|
-
setContextTaskId(null);
|
|
57577
|
-
setMoveTaskId(contextTaskId);
|
|
57578
|
-
const target = colIndex === 0 ? Math.min(1, board.columns.length - 1) : 0;
|
|
57579
|
-
setMoveTargetCol(target);
|
|
57580
|
-
setMode("move-target");
|
|
57581
|
-
}
|
|
57582
|
-
},
|
|
57583
|
-
onCancel: () => {
|
|
57584
|
-
setContextTaskId(null);
|
|
57585
|
-
setMode("browse");
|
|
57586
|
-
},
|
|
57587
|
-
mouseX: layoutRef.current.colStarts[colIndex],
|
|
57588
|
-
mouseY: HEADER_LINES + rowIndex
|
|
57589
|
-
}
|
|
57590
|
-
) }),
|
|
57591
57467
|
mode === "move-target" && moveTaskId && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "yellow", bold: true, children: [
|
|
57592
57468
|
"Moving ",
|
|
57593
57469
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: moveTaskId }),
|
|
57594
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: " \u2014 click
|
|
57470
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: " \u2014 click " }),
|
|
57595
57471
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "yellow", bold: true, children: "\u2193" }),
|
|
57596
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: "
|
|
57472
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: " or \u2190/\u2192 + Enter" })
|
|
57597
57473
|
] }) }),
|
|
57598
57474
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StatusBar, { message: statusMsg, task: focusedTask })
|
|
57599
57475
|
] });
|