kandown 0.4.0 → 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/README.md +1 -1
- package/bin/kandown.js +189 -40
- package/bin/tui.js +547 -80
- package/dist/index.html +217 -217
- package/package.json +1 -1
package/bin/tui.js
CHANGED
|
@@ -27895,7 +27895,7 @@ var require_backend = __commonJS({
|
|
|
27895
27895
|
});
|
|
27896
27896
|
return value;
|
|
27897
27897
|
},
|
|
27898
|
-
useEffect: function
|
|
27898
|
+
useEffect: function useEffect10(create3) {
|
|
27899
27899
|
nextHook();
|
|
27900
27900
|
hookLog.push({
|
|
27901
27901
|
displayName: null,
|
|
@@ -27968,7 +27968,7 @@ var require_backend = __commonJS({
|
|
|
27968
27968
|
return [initialArg, function() {
|
|
27969
27969
|
}];
|
|
27970
27970
|
},
|
|
27971
|
-
useRef: function
|
|
27971
|
+
useRef: function useRef6(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 useState10(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_react38 = __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";
|
|
@@ -56755,8 +56755,224 @@ function AgentPicker({ agents, taskId, onSelect, onCancel }) {
|
|
|
56755
56755
|
);
|
|
56756
56756
|
}
|
|
56757
56757
|
|
|
56758
|
-
// src/cli/
|
|
56758
|
+
// src/cli/hooks/use-mouse.ts
|
|
56759
|
+
var import_react36 = __toESM(require_react(), 1);
|
|
56760
|
+
var MOUSE_ENABLE_X10 = "\x1B[?1000h";
|
|
56761
|
+
var MOUSE_DISABLE_X10 = "\x1B[?1000l";
|
|
56762
|
+
var MOUSE_ENABLE_SGR = "\x1B[?1006h";
|
|
56763
|
+
var MOUSE_DISABLE_SGR = "\x1B[?1006l";
|
|
56764
|
+
function parseSGRMouse(buffer) {
|
|
56765
|
+
const sgrRegex = /^\x1b\[<(\d+);(\d+);(\d+)([Mm])/;
|
|
56766
|
+
const match = buffer.match(sgrRegex);
|
|
56767
|
+
if (!match) return null;
|
|
56768
|
+
const cb = parseInt(match[1], 10);
|
|
56769
|
+
const cx = parseInt(match[2], 10);
|
|
56770
|
+
const cy = parseInt(match[3], 10);
|
|
56771
|
+
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
|
+
return {
|
|
56777
|
+
event: {
|
|
56778
|
+
x: cx,
|
|
56779
|
+
y: cy,
|
|
56780
|
+
button,
|
|
56781
|
+
action: isPress ? "press" : "release",
|
|
56782
|
+
shift,
|
|
56783
|
+
meta,
|
|
56784
|
+
ctrl
|
|
56785
|
+
},
|
|
56786
|
+
endIndex: match[0].length
|
|
56787
|
+
};
|
|
56788
|
+
}
|
|
56789
|
+
function parseX10Mouse(buffer) {
|
|
56790
|
+
if (!buffer.startsWith("\x1B[M")) return null;
|
|
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
|
+
};
|
|
56813
|
+
}
|
|
56814
|
+
function useMouse(handler, options = {}) {
|
|
56815
|
+
const { enabled = true, pressOnly = true } = options;
|
|
56816
|
+
const handlerRef = (0, import_react36.useRef)(handler);
|
|
56817
|
+
handlerRef.current = handler;
|
|
56818
|
+
(0, import_react36.useEffect)(() => {
|
|
56819
|
+
if (!enabled) return;
|
|
56820
|
+
const stdin = process.stdin;
|
|
56821
|
+
if (!stdin.isTTY) return;
|
|
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);
|
|
56871
|
+
const cleanup = () => {
|
|
56872
|
+
process.stdout.write(MOUSE_DISABLE_SGR + MOUSE_DISABLE_X10);
|
|
56873
|
+
};
|
|
56874
|
+
process.on("exit", cleanup);
|
|
56875
|
+
return () => {
|
|
56876
|
+
stdin.removeListener("data", onData);
|
|
56877
|
+
process.removeListener("exit", cleanup);
|
|
56878
|
+
process.stdout.write(MOUSE_DISABLE_SGR + MOUSE_DISABLE_X10);
|
|
56879
|
+
};
|
|
56880
|
+
}, [enabled, pressOnly]);
|
|
56881
|
+
}
|
|
56882
|
+
|
|
56883
|
+
// src/cli/components/task-context-menu.tsx
|
|
56884
|
+
var import_react37 = __toESM(require_react(), 1);
|
|
56759
56885
|
var import_jsx_runtime3 = __toESM(require_jsx_runtime(), 1);
|
|
56886
|
+
function TaskContextMenu({
|
|
56887
|
+
taskId,
|
|
56888
|
+
options,
|
|
56889
|
+
onSelect,
|
|
56890
|
+
onCancel,
|
|
56891
|
+
mouseX,
|
|
56892
|
+
mouseY,
|
|
56893
|
+
onMouseClick,
|
|
56894
|
+
menuStartRow
|
|
56895
|
+
}) {
|
|
56896
|
+
const [cursor, setCursor] = (0, import_react37.useState)(0);
|
|
56897
|
+
use_input_default((input, key) => {
|
|
56898
|
+
if (key.escape || input === "q") {
|
|
56899
|
+
onCancel();
|
|
56900
|
+
return;
|
|
56901
|
+
}
|
|
56902
|
+
if (key.downArrow || input === "j") {
|
|
56903
|
+
setCursor((c) => Math.min(c + 1, options.length - 1));
|
|
56904
|
+
return;
|
|
56905
|
+
}
|
|
56906
|
+
if (key.upArrow || input === "k") {
|
|
56907
|
+
setCursor((c) => Math.max(c - 1, 0));
|
|
56908
|
+
return;
|
|
56909
|
+
}
|
|
56910
|
+
if (key.return) {
|
|
56911
|
+
const opt = options[cursor];
|
|
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
|
+
);
|
|
56971
|
+
}
|
|
56972
|
+
|
|
56973
|
+
// src/cli/screens/board.tsx
|
|
56974
|
+
var import_jsx_runtime4 = __toESM(require_jsx_runtime(), 1);
|
|
56975
|
+
var HEADER_LINES = 4;
|
|
56760
56976
|
function truncate(str, maxLen) {
|
|
56761
56977
|
if (str.length <= maxLen) return str;
|
|
56762
56978
|
return str.slice(0, maxLen - 1) + "\u2026";
|
|
@@ -56791,44 +57007,65 @@ function TaskRow({
|
|
|
56791
57007
|
const tagChars = tag ? tag.length + 1 : 0;
|
|
56792
57008
|
const available = colWidth - fixedChars - tagChars;
|
|
56793
57009
|
const titleStr = truncate(titleWithoutTag, Math.max(4, available));
|
|
56794
|
-
return /* @__PURE__ */ (0,
|
|
56795
|
-
/* @__PURE__ */ (0,
|
|
57010
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { children: [
|
|
57011
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: focused ? "cyan" : void 0, bold: focused, children: [
|
|
56796
57012
|
cursor,
|
|
56797
57013
|
" "
|
|
56798
57014
|
] }),
|
|
56799
|
-
/* @__PURE__ */ (0,
|
|
57015
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: task.checked ? "green" : focused ? "white" : "gray", children: [
|
|
56800
57016
|
check2,
|
|
56801
57017
|
" "
|
|
56802
57018
|
] }),
|
|
56803
|
-
/* @__PURE__ */ (0,
|
|
56804
|
-
tag && /* @__PURE__ */ (0,
|
|
57019
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: focused ? "cyan" : "yellow", bold: focused, children: idStr }),
|
|
57020
|
+
tag && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: focused ? "white" : "magenta", bold: true, children: [
|
|
56805
57021
|
" ",
|
|
56806
57022
|
tag
|
|
56807
57023
|
] }),
|
|
56808
|
-
/* @__PURE__ */ (0,
|
|
57024
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: focused ? "white" : "gray", children: [
|
|
56809
57025
|
" ",
|
|
56810
57026
|
titleStr
|
|
56811
57027
|
] })
|
|
56812
57028
|
] });
|
|
56813
57029
|
}
|
|
57030
|
+
function MovePlaceholder({
|
|
57031
|
+
name,
|
|
57032
|
+
focused,
|
|
57033
|
+
colWidth
|
|
57034
|
+
}) {
|
|
57035
|
+
const label = `\u2193 ${name}`;
|
|
57036
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
57037
|
+
Text,
|
|
57038
|
+
{
|
|
57039
|
+
color: focused ? "black" : "yellow",
|
|
57040
|
+
backgroundColor: focused ? "yellow" : void 0,
|
|
57041
|
+
bold: focused,
|
|
57042
|
+
children: [
|
|
57043
|
+
" ",
|
|
57044
|
+
pad(label, colWidth - 2)
|
|
57045
|
+
]
|
|
57046
|
+
}
|
|
57047
|
+
) });
|
|
57048
|
+
}
|
|
56814
57049
|
function KanbanColumn({
|
|
56815
57050
|
name,
|
|
56816
57051
|
tasks,
|
|
56817
57052
|
focusedRow,
|
|
56818
57053
|
isFocused,
|
|
56819
|
-
colWidth
|
|
57054
|
+
colWidth,
|
|
57055
|
+
showMoveTarget,
|
|
57056
|
+
isMoveFocused
|
|
56820
57057
|
}) {
|
|
56821
57058
|
const headerBg = isFocused ? "cyan" : void 0;
|
|
56822
57059
|
const headerColor = isFocused ? "black" : "cyan";
|
|
56823
57060
|
const countStr = tasks.length > 0 ? ` (${tasks.length})` : "";
|
|
56824
57061
|
const headerText = truncate(`${name}${countStr}`, colWidth);
|
|
56825
|
-
return /* @__PURE__ */ (0,
|
|
56826
|
-
/* @__PURE__ */ (0,
|
|
56827
|
-
/* @__PURE__ */ (0,
|
|
56828
|
-
tasks.length === 0 ? /* @__PURE__ */ (0,
|
|
57062
|
+
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(headerText, colWidth) }) }),
|
|
57064
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: isFocused ? "cyan" : "gray", children: "\u2500".repeat(colWidth) }),
|
|
57065
|
+
tasks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
56829
57066
|
" ".repeat(2),
|
|
56830
57067
|
"(empty)"
|
|
56831
|
-
] }) : tasks.map((task, idx) => /* @__PURE__ */ (0,
|
|
57068
|
+
] }) : tasks.map((task, idx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
56832
57069
|
TaskRow,
|
|
56833
57070
|
{
|
|
56834
57071
|
task,
|
|
@@ -56836,28 +57073,32 @@ function KanbanColumn({
|
|
|
56836
57073
|
colWidth
|
|
56837
57074
|
},
|
|
56838
57075
|
task.id
|
|
56839
|
-
))
|
|
57076
|
+
)),
|
|
57077
|
+
showMoveTarget && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(MovePlaceholder, { name, focused: !!isMoveFocused, colWidth })
|
|
56840
57078
|
] });
|
|
56841
57079
|
}
|
|
56842
|
-
function BoardHeader({ title, inTmux }) {
|
|
57080
|
+
function BoardHeader({ title, inTmux, modeHint, version }) {
|
|
56843
57081
|
const tmuxHint = inTmux ? " tmux" : "";
|
|
56844
|
-
|
|
56845
|
-
|
|
57082
|
+
const hint = modeHint || "h/l cols j/k tasks Enter detail a agent r reload q quit";
|
|
57083
|
+
const versionTag = version ? ` v${version}` : "";
|
|
57084
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { marginBottom: 1, justifyContent: "space-between", children: [
|
|
57085
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { bold: true, color: "cyan", children: [
|
|
56846
57086
|
" ",
|
|
56847
57087
|
"KANDOWN",
|
|
56848
57088
|
tmuxHint,
|
|
57089
|
+
versionTag,
|
|
56849
57090
|
" ",
|
|
56850
57091
|
title
|
|
56851
57092
|
] }),
|
|
56852
|
-
/* @__PURE__ */ (0,
|
|
57093
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", dimColor: true, children: hint })
|
|
56853
57094
|
] });
|
|
56854
57095
|
}
|
|
56855
57096
|
function StatusBar({ message, task }) {
|
|
56856
57097
|
if (message) {
|
|
56857
|
-
return /* @__PURE__ */ (0,
|
|
57098
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "yellow", children: message }) });
|
|
56858
57099
|
}
|
|
56859
|
-
if (!task) return /* @__PURE__ */ (0,
|
|
56860
|
-
return /* @__PURE__ */ (0,
|
|
57100
|
+
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
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", children: [
|
|
56861
57102
|
task.id.replace(/^t/, ""),
|
|
56862
57103
|
task.progress ? ` (${task.progress.done}/${task.progress.total})` : "",
|
|
56863
57104
|
" ",
|
|
@@ -56873,27 +57114,27 @@ function TaskDetail({
|
|
|
56873
57114
|
const bodyLines = task.body.split("\n");
|
|
56874
57115
|
const maxVisible = (process.stdout.rows || 24) - 10;
|
|
56875
57116
|
const visibleLines = bodyLines.slice(scrollOffset, scrollOffset + maxVisible);
|
|
56876
|
-
return /* @__PURE__ */ (0,
|
|
56877
|
-
/* @__PURE__ */ (0,
|
|
56878
|
-
/* @__PURE__ */ (0,
|
|
56879
|
-
/* @__PURE__ */ (0,
|
|
57117
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", paddingX: 2, children: [
|
|
57118
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { marginBottom: 1, children: [
|
|
57119
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { bold: true, color: "cyan", children: taskId }),
|
|
57120
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "white", bold: true, children: [
|
|
56880
57121
|
" ",
|
|
56881
57122
|
fm.title
|
|
56882
57123
|
] })
|
|
56883
57124
|
] }),
|
|
56884
|
-
/* @__PURE__ */ (0,
|
|
57125
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginBottom: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", children: [
|
|
56885
57126
|
"status: ",
|
|
56886
|
-
/* @__PURE__ */ (0,
|
|
57127
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "yellow", children: fm.status ?? "\u2014" }),
|
|
56887
57128
|
fm.priority ? ` priority: ${fm.priority}` : "",
|
|
56888
57129
|
fm.assignee ? ` assignee: ${fm.assignee}` : "",
|
|
56889
57130
|
fm.due ? ` due: ${fm.due}` : ""
|
|
56890
57131
|
] }) }),
|
|
56891
|
-
/* @__PURE__ */ (0,
|
|
57132
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: "\u2500".repeat(termWidth() - 4) }),
|
|
56892
57133
|
visibleLines.map((line, idx) => {
|
|
56893
57134
|
const isHeader = RE_HEADER.test(line);
|
|
56894
57135
|
const isSubtask = RE_SUBTASK.test(line);
|
|
56895
57136
|
const isDone = RE_DONE_SUBTASK.test(line);
|
|
56896
|
-
return /* @__PURE__ */ (0,
|
|
57137
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
56897
57138
|
Text,
|
|
56898
57139
|
{
|
|
56899
57140
|
color: isHeader ? "cyan" : isDone ? "green" : isSubtask ? "white" : "gray",
|
|
@@ -56903,7 +57144,7 @@ function TaskDetail({
|
|
|
56903
57144
|
scrollOffset + idx
|
|
56904
57145
|
);
|
|
56905
57146
|
}),
|
|
56906
|
-
bodyLines.length > maxVisible && /* @__PURE__ */ (0,
|
|
57147
|
+
bodyLines.length > maxVisible && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
56907
57148
|
" ",
|
|
56908
57149
|
"\u2191\u2193 scroll (",
|
|
56909
57150
|
scrollOffset + 1,
|
|
@@ -56915,66 +57156,92 @@ function TaskDetail({
|
|
|
56915
57156
|
] })
|
|
56916
57157
|
] });
|
|
56917
57158
|
}
|
|
56918
|
-
function Board({ kandownDir }) {
|
|
57159
|
+
function Board({ kandownDir, version }) {
|
|
56919
57160
|
const { exit } = use_app_default();
|
|
56920
|
-
const [board, setBoard] = (0,
|
|
56921
|
-
const [colIndex, setColIndex] = (0,
|
|
56922
|
-
const [rowIndex, setRowIndex] = (0,
|
|
56923
|
-
const [mode, setMode] = (0,
|
|
56924
|
-
const [detailTask, setDetailTask] = (0,
|
|
56925
|
-
const [detailTaskId, setDetailTaskId] = (0,
|
|
56926
|
-
const [detailScroll, setDetailScroll] = (0,
|
|
56927
|
-
const [installedAgents, setInstalledAgents] = (0,
|
|
56928
|
-
const [statusMsg, setStatusMsg] = (0,
|
|
57161
|
+
const [board, setBoard] = (0, import_react38.useState)(null);
|
|
57162
|
+
const [colIndex, setColIndex] = (0, import_react38.useState)(0);
|
|
57163
|
+
const [rowIndex, setRowIndex] = (0, import_react38.useState)(0);
|
|
57164
|
+
const [mode, setMode] = (0, import_react38.useState)("browse");
|
|
57165
|
+
const [detailTask, setDetailTask] = (0, import_react38.useState)(null);
|
|
57166
|
+
const [detailTaskId, setDetailTaskId] = (0, import_react38.useState)("");
|
|
57167
|
+
const [detailScroll, setDetailScroll] = (0, import_react38.useState)(0);
|
|
57168
|
+
const [installedAgents, setInstalledAgents] = (0, import_react38.useState)([]);
|
|
57169
|
+
const [statusMsg, setStatusMsg] = (0, import_react38.useState)("");
|
|
57170
|
+
const [contextTaskId, setContextTaskId] = (0, import_react38.useState)(null);
|
|
57171
|
+
const [moveTaskId, setMoveTaskId] = (0, import_react38.useState)(null);
|
|
57172
|
+
const [moveTargetCol, setMoveTargetCol] = (0, import_react38.useState)(0);
|
|
56929
57173
|
const inTmux = isInTmux();
|
|
56930
|
-
(0,
|
|
57174
|
+
const layoutRef = (0, import_react38.useRef)({
|
|
57175
|
+
colStarts: [],
|
|
57176
|
+
colWidth: 0,
|
|
57177
|
+
colTaskCounts: []
|
|
57178
|
+
});
|
|
57179
|
+
const updateLayout = (0, import_react38.useCallback)((b) => {
|
|
57180
|
+
if (!b) return;
|
|
57181
|
+
const cw = calcColWidth(b.columns.length);
|
|
57182
|
+
const starts = [];
|
|
57183
|
+
let x = 1;
|
|
57184
|
+
for (let i = 0; i < b.columns.length; i++) {
|
|
57185
|
+
starts.push(x);
|
|
57186
|
+
x += cw + 1;
|
|
57187
|
+
}
|
|
57188
|
+
layoutRef.current = {
|
|
57189
|
+
colStarts: starts,
|
|
57190
|
+
colWidth: cw,
|
|
57191
|
+
colTaskCounts: b.columns.map((c) => c.tasks.length)
|
|
57192
|
+
};
|
|
57193
|
+
}, []);
|
|
57194
|
+
(0, import_react38.useEffect)(() => {
|
|
56931
57195
|
const loaded = readBoard(kandownDir);
|
|
56932
57196
|
setBoard(loaded);
|
|
57197
|
+
updateLayout(loaded);
|
|
56933
57198
|
setInstalledAgents(detectInstalledAgents());
|
|
56934
|
-
}, [kandownDir]);
|
|
56935
|
-
|
|
56936
|
-
const rowIndexRef = (0, import_react36.useRef)(0);
|
|
56937
|
-
(0, import_react36.useEffect)(() => {
|
|
57199
|
+
}, [kandownDir, updateLayout]);
|
|
57200
|
+
(0, import_react38.useEffect)(() => {
|
|
56938
57201
|
const watcher = createWatcher();
|
|
56939
57202
|
watcher.on("taskChanged", () => {
|
|
56940
57203
|
const loaded = readBoard(kandownDir);
|
|
56941
57204
|
setBoard(loaded);
|
|
57205
|
+
updateLayout(loaded);
|
|
56942
57206
|
});
|
|
56943
57207
|
watcher.on("newTaskDetected", (taskId) => {
|
|
56944
57208
|
const loaded = readBoard(kandownDir);
|
|
56945
57209
|
setBoard(loaded);
|
|
57210
|
+
updateLayout(loaded);
|
|
56946
57211
|
setStatusMsg(`New task: ${taskId}`);
|
|
56947
57212
|
setTimeout(() => setStatusMsg(""), 2e3);
|
|
56948
57213
|
});
|
|
56949
57214
|
watcher.on("configChanged", () => {
|
|
56950
57215
|
const loaded = readBoard(kandownDir);
|
|
56951
57216
|
setBoard(loaded);
|
|
57217
|
+
updateLayout(loaded);
|
|
56952
57218
|
});
|
|
56953
57219
|
watcher.start(kandownDir);
|
|
56954
57220
|
return () => {
|
|
56955
57221
|
watcher.stop();
|
|
56956
57222
|
};
|
|
56957
|
-
}, [kandownDir]);
|
|
56958
|
-
const reloadBoard = (0,
|
|
57223
|
+
}, [kandownDir, updateLayout]);
|
|
57224
|
+
const reloadBoard = (0, import_react38.useCallback)(() => {
|
|
56959
57225
|
const loaded = readBoard(kandownDir);
|
|
56960
57226
|
setBoard(loaded);
|
|
57227
|
+
updateLayout(loaded);
|
|
56961
57228
|
setStatusMsg("Board reloaded");
|
|
56962
57229
|
setTimeout(() => setStatusMsg(""), 1500);
|
|
56963
|
-
}, [kandownDir]);
|
|
56964
|
-
const getFocusedTask = (0,
|
|
57230
|
+
}, [kandownDir, updateLayout]);
|
|
57231
|
+
const getFocusedTask = (0, import_react38.useCallback)(() => {
|
|
56965
57232
|
if (!board) return null;
|
|
56966
57233
|
const col = board.columns[colIndex];
|
|
56967
57234
|
if (!col || col.tasks.length === 0) return null;
|
|
56968
57235
|
return col.tasks[Math.min(rowIndex, col.tasks.length - 1)] ?? null;
|
|
56969
57236
|
}, [board, colIndex, rowIndex]);
|
|
56970
|
-
const openDetail = (0,
|
|
57237
|
+
const openDetail = (0, import_react38.useCallback)((taskId) => {
|
|
56971
57238
|
const task = readTask(kandownDir, taskId);
|
|
56972
57239
|
setDetailTask(task);
|
|
56973
57240
|
setDetailTaskId(taskId);
|
|
56974
57241
|
setDetailScroll(0);
|
|
56975
57242
|
setMode("detail");
|
|
56976
57243
|
}, [kandownDir]);
|
|
56977
|
-
const handleAgentSelect = (0,
|
|
57244
|
+
const handleAgentSelect = (0, import_react38.useCallback)((agentId) => {
|
|
56978
57245
|
const task = getFocusedTask();
|
|
56979
57246
|
const taskId = mode === "detail" ? detailTaskId : task?.id;
|
|
56980
57247
|
if (!taskId) return;
|
|
@@ -56997,6 +57264,121 @@ function Board({ kandownDir }) {
|
|
|
56997
57264
|
}
|
|
56998
57265
|
}, 50);
|
|
56999
57266
|
}, [mode, detailTaskId, getFocusedTask, kandownDir, exit, reloadBoard]);
|
|
57267
|
+
const handleMouseClick = (0, import_react38.useCallback)((evt) => {
|
|
57268
|
+
if (evt.button !== 0) return;
|
|
57269
|
+
if (!board) return;
|
|
57270
|
+
const { x, y } = evt;
|
|
57271
|
+
const layout = layoutRef.current;
|
|
57272
|
+
if (mode === "browse") {
|
|
57273
|
+
for (let c = 0; c < board.columns.length; c++) {
|
|
57274
|
+
const colStart = layout.colStarts[c] || 0;
|
|
57275
|
+
const colEnd = colStart + layout.colWidth;
|
|
57276
|
+
if (x >= colStart && x <= colEnd) {
|
|
57277
|
+
const taskRow = y - HEADER_LINES;
|
|
57278
|
+
if (taskRow >= 0 && taskRow < board.columns[c].tasks.length) {
|
|
57279
|
+
setColIndex(c);
|
|
57280
|
+
setRowIndex(taskRow);
|
|
57281
|
+
const task = board.columns[c].tasks[taskRow];
|
|
57282
|
+
if (task) {
|
|
57283
|
+
setContextTaskId(task.id);
|
|
57284
|
+
setMode("context-menu");
|
|
57285
|
+
}
|
|
57286
|
+
return;
|
|
57287
|
+
}
|
|
57288
|
+
}
|
|
57289
|
+
}
|
|
57290
|
+
return;
|
|
57291
|
+
}
|
|
57292
|
+
if (mode === "context-menu") {
|
|
57293
|
+
const maxTasks = Math.max(...board.columns.map((c) => c.tasks.length), 0);
|
|
57294
|
+
const menuStartY = HEADER_LINES + maxTasks + 1;
|
|
57295
|
+
const menuRow = y - menuStartY;
|
|
57296
|
+
if (menuRow === 1) {
|
|
57297
|
+
if (contextTaskId) {
|
|
57298
|
+
setContextTaskId(null);
|
|
57299
|
+
openDetail(contextTaskId);
|
|
57300
|
+
}
|
|
57301
|
+
return;
|
|
57302
|
+
}
|
|
57303
|
+
if (menuRow === 2) {
|
|
57304
|
+
if (contextTaskId) {
|
|
57305
|
+
const taskId = contextTaskId;
|
|
57306
|
+
setContextTaskId(null);
|
|
57307
|
+
setMoveTaskId(taskId);
|
|
57308
|
+
const target = colIndex === 0 ? Math.min(1, board.columns.length - 1) : 0;
|
|
57309
|
+
setMoveTargetCol(target);
|
|
57310
|
+
setMode("move-target");
|
|
57311
|
+
}
|
|
57312
|
+
return;
|
|
57313
|
+
}
|
|
57314
|
+
if (menuRow < 0 || menuRow > 3) {
|
|
57315
|
+
for (let c = 0; c < board.columns.length; c++) {
|
|
57316
|
+
const colStart = layout.colStarts[c] || 0;
|
|
57317
|
+
const colEnd = colStart + layout.colWidth;
|
|
57318
|
+
if (x >= colStart && x <= colEnd) {
|
|
57319
|
+
const taskRow = y - HEADER_LINES;
|
|
57320
|
+
if (taskRow >= 0 && taskRow < board.columns[c].tasks.length) {
|
|
57321
|
+
setColIndex(c);
|
|
57322
|
+
setRowIndex(taskRow);
|
|
57323
|
+
const task = board.columns[c].tasks[taskRow];
|
|
57324
|
+
if (task) {
|
|
57325
|
+
setContextTaskId(task.id);
|
|
57326
|
+
}
|
|
57327
|
+
return;
|
|
57328
|
+
}
|
|
57329
|
+
}
|
|
57330
|
+
}
|
|
57331
|
+
setContextTaskId(null);
|
|
57332
|
+
setMode("browse");
|
|
57333
|
+
}
|
|
57334
|
+
return;
|
|
57335
|
+
}
|
|
57336
|
+
if (mode === "move-target") {
|
|
57337
|
+
let clickedPlaceholder = false;
|
|
57338
|
+
for (let c = 0; c < board.columns.length; c++) {
|
|
57339
|
+
if (c === colIndex) continue;
|
|
57340
|
+
const colStart = layout.colStarts[c] || 0;
|
|
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
|
+
}
|
|
57359
|
+
}
|
|
57360
|
+
if (!clickedPlaceholder) {
|
|
57361
|
+
let clickedTask = false;
|
|
57362
|
+
for (let c = 0; c < board.columns.length; c++) {
|
|
57363
|
+
const colStart = layout.colStarts[c] || 0;
|
|
57364
|
+
const colEnd = colStart + layout.colWidth;
|
|
57365
|
+
if (x >= colStart && x <= colEnd) {
|
|
57366
|
+
const taskRow = y - HEADER_LINES;
|
|
57367
|
+
if (taskRow >= 0 && taskRow < board.columns[c].tasks.length) {
|
|
57368
|
+
clickedTask = true;
|
|
57369
|
+
break;
|
|
57370
|
+
}
|
|
57371
|
+
}
|
|
57372
|
+
}
|
|
57373
|
+
if (!clickedTask) {
|
|
57374
|
+
setMoveTaskId(null);
|
|
57375
|
+
setMode("browse");
|
|
57376
|
+
}
|
|
57377
|
+
}
|
|
57378
|
+
return;
|
|
57379
|
+
}
|
|
57380
|
+
}, [board, mode, colIndex, contextTaskId, moveTaskId, kandownDir, updateLayout, openDetail]);
|
|
57381
|
+
useMouse(handleMouseClick, { enabled: mode !== "agent-picker" });
|
|
57000
57382
|
use_input_default((input, key) => {
|
|
57001
57383
|
if (mode === "browse") {
|
|
57002
57384
|
if (input === "q" || key.escape) {
|
|
@@ -57045,6 +57427,47 @@ function Board({ kandownDir }) {
|
|
|
57045
57427
|
return;
|
|
57046
57428
|
}
|
|
57047
57429
|
}
|
|
57430
|
+
if (mode === "context-menu") {
|
|
57431
|
+
return;
|
|
57432
|
+
}
|
|
57433
|
+
if (mode === "move-target") {
|
|
57434
|
+
if (key.escape || input === "q") {
|
|
57435
|
+
setMoveTaskId(null);
|
|
57436
|
+
setMode("browse");
|
|
57437
|
+
return;
|
|
57438
|
+
}
|
|
57439
|
+
if (input === "l" || key.rightArrow) {
|
|
57440
|
+
if (!board) return;
|
|
57441
|
+
const otherCols = board.columns.map((_, i) => i).filter((i) => i !== colIndex);
|
|
57442
|
+
const currentIdx = otherCols.indexOf(moveTargetCol);
|
|
57443
|
+
const nextIdx = Math.min(currentIdx + 1, otherCols.length - 1);
|
|
57444
|
+
setMoveTargetCol(otherCols[nextIdx] ?? 0);
|
|
57445
|
+
return;
|
|
57446
|
+
}
|
|
57447
|
+
if (input === "h" || key.leftArrow) {
|
|
57448
|
+
if (!board) return;
|
|
57449
|
+
const otherCols = board.columns.map((_, i) => i).filter((i) => i !== colIndex);
|
|
57450
|
+
const currentIdx = otherCols.indexOf(moveTargetCol);
|
|
57451
|
+
const prevIdx = Math.max(currentIdx - 1, 0);
|
|
57452
|
+
setMoveTargetCol(otherCols[prevIdx] ?? 0);
|
|
57453
|
+
return;
|
|
57454
|
+
}
|
|
57455
|
+
if (key.return) {
|
|
57456
|
+
if (!board || !moveTaskId) return;
|
|
57457
|
+
const targetColName = board.columns[moveTargetCol]?.name;
|
|
57458
|
+
if (targetColName) {
|
|
57459
|
+
moveTaskToColumn(kandownDir, moveTaskId, targetColName);
|
|
57460
|
+
const loaded = readBoard(kandownDir);
|
|
57461
|
+
setBoard(loaded);
|
|
57462
|
+
updateLayout(loaded);
|
|
57463
|
+
setStatusMsg(`Moved ${moveTaskId} \u2192 ${targetColName}`);
|
|
57464
|
+
setTimeout(() => setStatusMsg(""), 2e3);
|
|
57465
|
+
}
|
|
57466
|
+
setMoveTaskId(null);
|
|
57467
|
+
setMode("browse");
|
|
57468
|
+
return;
|
|
57469
|
+
}
|
|
57470
|
+
}
|
|
57048
57471
|
if (mode === "detail") {
|
|
57049
57472
|
if (key.escape || input === "q") {
|
|
57050
57473
|
setMode("browse");
|
|
@@ -57070,17 +57493,17 @@ function Board({ kandownDir }) {
|
|
|
57070
57493
|
}
|
|
57071
57494
|
});
|
|
57072
57495
|
if (!board) {
|
|
57073
|
-
return /* @__PURE__ */ (0,
|
|
57496
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { padding: 2, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: "Loading board\u2026" }) });
|
|
57074
57497
|
}
|
|
57075
57498
|
if (board.columns.length === 0) {
|
|
57076
|
-
return /* @__PURE__ */ (0,
|
|
57077
|
-
/* @__PURE__ */ (0,
|
|
57499
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", padding: 2, children: [
|
|
57500
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "red", bold: true, children: [
|
|
57078
57501
|
"No board found at ",
|
|
57079
57502
|
kandownDir
|
|
57080
57503
|
] }),
|
|
57081
|
-
/* @__PURE__ */ (0,
|
|
57504
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", children: [
|
|
57082
57505
|
"Run ",
|
|
57083
|
-
/* @__PURE__ */ (0,
|
|
57506
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: "kandown init" }),
|
|
57084
57507
|
" to set up kandown in this project."
|
|
57085
57508
|
] })
|
|
57086
57509
|
] });
|
|
@@ -57089,9 +57512,9 @@ function Board({ kandownDir }) {
|
|
|
57089
57512
|
const focusedTask = getFocusedTask();
|
|
57090
57513
|
if (mode === "agent-picker") {
|
|
57091
57514
|
const taskId = detailTaskId || focusedTask?.id || "";
|
|
57092
|
-
return /* @__PURE__ */ (0,
|
|
57093
|
-
/* @__PURE__ */ (0,
|
|
57094
|
-
/* @__PURE__ */ (0,
|
|
57515
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
57516
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BoardHeader, { title: board.title, inTmux, version }),
|
|
57517
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
57095
57518
|
AgentPicker,
|
|
57096
57519
|
{
|
|
57097
57520
|
agents: installedAgents,
|
|
@@ -57103,45 +57526,89 @@ function Board({ kandownDir }) {
|
|
|
57103
57526
|
] });
|
|
57104
57527
|
}
|
|
57105
57528
|
if (mode === "detail" && detailTask) {
|
|
57106
|
-
return /* @__PURE__ */ (0,
|
|
57107
|
-
/* @__PURE__ */ (0,
|
|
57108
|
-
/* @__PURE__ */ (0,
|
|
57109
|
-
/* @__PURE__ */ (0,
|
|
57529
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
57530
|
+
/* @__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 a launch agent j/k scroll" }),
|
|
57532
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Text, { color: "gray", dimColor: true, children: [
|
|
57110
57533
|
"KANDOWN ",
|
|
57111
57534
|
board.title
|
|
57112
57535
|
] })
|
|
57113
57536
|
] }),
|
|
57114
|
-
/* @__PURE__ */ (0,
|
|
57115
|
-
statusMsg && /* @__PURE__ */ (0,
|
|
57537
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(TaskDetail, { task: detailTask, taskId: detailTaskId, scrollOffset: detailScroll }),
|
|
57538
|
+
statusMsg && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { marginTop: 1, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "yellow", children: statusMsg }) })
|
|
57116
57539
|
] });
|
|
57117
57540
|
}
|
|
57118
|
-
|
|
57119
|
-
|
|
57120
|
-
|
|
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
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(Box_default, { flexDirection: "column", children: [
|
|
57552
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(BoardHeader, { title: board.title, inTmux, modeHint, version }),
|
|
57553
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Box_default, { flexDirection: "row", children: board.columns.map((col, cIdx) => /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
57121
57554
|
KanbanColumn,
|
|
57122
57555
|
{
|
|
57123
57556
|
name: col.name,
|
|
57124
57557
|
tasks: col.tasks,
|
|
57125
57558
|
focusedRow: cIdx === colIndex ? rowIndex : -1,
|
|
57126
57559
|
isFocused: cIdx === colIndex,
|
|
57127
|
-
colWidth
|
|
57560
|
+
colWidth,
|
|
57561
|
+
showMoveTarget: mode === "move-target" && cIdx !== colIndex,
|
|
57562
|
+
isMoveFocused: mode === "move-target" && cIdx === moveTargetCol
|
|
57128
57563
|
},
|
|
57129
57564
|
col.name
|
|
57130
57565
|
)) }),
|
|
57131
|
-
/* @__PURE__ */ (0,
|
|
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
|
+
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
|
+
"Moving ",
|
|
57593
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "cyan", children: moveTaskId }),
|
|
57594
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: " \u2014 click a " }),
|
|
57595
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "yellow", bold: true, children: "\u2193" }),
|
|
57596
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(Text, { color: "gray", children: " placeholder or use \u2190/\u2192 + Enter" })
|
|
57597
|
+
] }) }),
|
|
57598
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(StatusBar, { message: statusMsg, task: focusedTask })
|
|
57132
57599
|
] });
|
|
57133
57600
|
}
|
|
57134
57601
|
|
|
57135
57602
|
// src/cli/app.tsx
|
|
57136
|
-
var
|
|
57603
|
+
var import_jsx_runtime5 = __toESM(require_jsx_runtime(), 1);
|
|
57137
57604
|
function App2({ screen, kandownDir, version }) {
|
|
57138
57605
|
switch (screen) {
|
|
57139
57606
|
case "settings":
|
|
57140
|
-
return /* @__PURE__ */ (0,
|
|
57607
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Settings, { kandownDir, version });
|
|
57141
57608
|
case "board":
|
|
57142
|
-
return /* @__PURE__ */ (0,
|
|
57609
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Board, { kandownDir, version });
|
|
57143
57610
|
default:
|
|
57144
|
-
return /* @__PURE__ */ (0,
|
|
57611
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Box_default, { padding: 2, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(Text, { color: "red", bold: true, children: [
|
|
57145
57612
|
"Unknown screen: ",
|
|
57146
57613
|
screen
|
|
57147
57614
|
] }) });
|
|
@@ -57149,7 +57616,7 @@ function App2({ screen, kandownDir, version }) {
|
|
|
57149
57616
|
}
|
|
57150
57617
|
|
|
57151
57618
|
// src/cli/tui.tsx
|
|
57152
|
-
var
|
|
57619
|
+
var import_jsx_runtime6 = __toESM(require_jsx_runtime(), 1);
|
|
57153
57620
|
async function run(screen, kandownDir, version) {
|
|
57154
57621
|
if (!process.stdin.isTTY) {
|
|
57155
57622
|
throw new Error(
|
|
@@ -57157,7 +57624,7 @@ async function run(screen, kandownDir, version) {
|
|
|
57157
57624
|
);
|
|
57158
57625
|
}
|
|
57159
57626
|
process.stdout.write("\x1B[?1049h\x1B[H");
|
|
57160
|
-
const instance = render_default(/* @__PURE__ */ (0,
|
|
57627
|
+
const instance = render_default(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(App2, { screen, kandownDir, version }), {
|
|
57161
57628
|
exitOnCtrlC: true
|
|
57162
57629
|
});
|
|
57163
57630
|
try {
|