epoch-tui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/dist/App.d.ts +3 -0
  2. package/dist/App.js +38 -0
  3. package/dist/components/calendar/CalendarPane.d.ts +2 -0
  4. package/dist/components/calendar/CalendarPane.js +91 -0
  5. package/dist/components/calendar/DayCell.d.ts +7 -0
  6. package/dist/components/calendar/DayCell.js +26 -0
  7. package/dist/components/calendar/MonthView.d.ts +7 -0
  8. package/dist/components/calendar/MonthView.js +10 -0
  9. package/dist/components/common/BorderedBox.d.ts +18 -0
  10. package/dist/components/common/BorderedBox.js +29 -0
  11. package/dist/components/common/ClearTimelineDialog.d.ts +2 -0
  12. package/dist/components/common/ClearTimelineDialog.js +33 -0
  13. package/dist/components/common/FullscreenBackground.d.ts +11 -0
  14. package/dist/components/common/FullscreenBackground.js +12 -0
  15. package/dist/components/common/HelpDialog.d.ts +2 -0
  16. package/dist/components/common/HelpDialog.js +40 -0
  17. package/dist/components/common/Modal.d.ts +10 -0
  18. package/dist/components/common/Modal.js +15 -0
  19. package/dist/components/common/Separator.d.ts +8 -0
  20. package/dist/components/common/Separator.js +10 -0
  21. package/dist/components/common/ThemeDialog.d.ts +2 -0
  22. package/dist/components/common/ThemeDialog.js +117 -0
  23. package/dist/components/common/ThemedScreen.d.ts +22 -0
  24. package/dist/components/common/ThemedScreen.js +36 -0
  25. package/dist/components/common/ThemedText.d.ts +11 -0
  26. package/dist/components/common/ThemedText.js +20 -0
  27. package/dist/components/layout/Pane.d.ts +12 -0
  28. package/dist/components/layout/Pane.js +10 -0
  29. package/dist/components/layout/ThreeColumnLayout.d.ts +13 -0
  30. package/dist/components/layout/ThreeColumnLayout.js +22 -0
  31. package/dist/components/overview/OverviewScreen.d.ts +2 -0
  32. package/dist/components/overview/OverviewScreen.js +138 -0
  33. package/dist/components/tasks/TaskHeader.d.ts +7 -0
  34. package/dist/components/tasks/TaskHeader.js +8 -0
  35. package/dist/components/tasks/TaskItem.d.ts +10 -0
  36. package/dist/components/tasks/TaskItem.js +25 -0
  37. package/dist/components/tasks/TaskList.d.ts +11 -0
  38. package/dist/components/tasks/TaskList.js +11 -0
  39. package/dist/components/tasks/TasksPane.d.ts +2 -0
  40. package/dist/components/tasks/TasksPane.js +410 -0
  41. package/dist/components/timeline/TimelineEntry.d.ts +9 -0
  42. package/dist/components/timeline/TimelineEntry.js +26 -0
  43. package/dist/components/timeline/TimelinePane.d.ts +2 -0
  44. package/dist/components/timeline/TimelinePane.js +78 -0
  45. package/dist/contexts/AppContext.d.ts +47 -0
  46. package/dist/contexts/AppContext.js +104 -0
  47. package/dist/contexts/StorageContext.d.ts +15 -0
  48. package/dist/contexts/StorageContext.js +83 -0
  49. package/dist/contexts/ThemeContext.d.ts +15 -0
  50. package/dist/contexts/ThemeContext.js +44 -0
  51. package/dist/hooks/useKeyboardNav.d.ts +1 -0
  52. package/dist/hooks/useKeyboardNav.js +89 -0
  53. package/dist/hooks/useTerminalSize.d.ts +9 -0
  54. package/dist/hooks/useTerminalSize.js +34 -0
  55. package/dist/index.d.ts +2 -0
  56. package/dist/index.js +8 -0
  57. package/dist/services/calendarService.d.ts +18 -0
  58. package/dist/services/calendarService.js +57 -0
  59. package/dist/services/storage.d.ts +14 -0
  60. package/dist/services/storage.js +130 -0
  61. package/dist/services/taskService.d.ts +17 -0
  62. package/dist/services/taskService.js +106 -0
  63. package/dist/services/timelineService.d.ts +25 -0
  64. package/dist/services/timelineService.js +78 -0
  65. package/dist/themes/amazon.d.ts +2 -0
  66. package/dist/themes/amazon.js +37 -0
  67. package/dist/themes/amazonLight.d.ts +2 -0
  68. package/dist/themes/amazonLight.js +38 -0
  69. package/dist/themes/apple.d.ts +2 -0
  70. package/dist/themes/apple.js +38 -0
  71. package/dist/themes/appleLight.d.ts +2 -0
  72. package/dist/themes/appleLight.js +38 -0
  73. package/dist/themes/atomOneDark.d.ts +2 -0
  74. package/dist/themes/atomOneDark.js +37 -0
  75. package/dist/themes/atomOneLight.d.ts +2 -0
  76. package/dist/themes/atomOneLight.js +38 -0
  77. package/dist/themes/batman.d.ts +2 -0
  78. package/dist/themes/batman.js +37 -0
  79. package/dist/themes/catppuccin.d.ts +2 -0
  80. package/dist/themes/catppuccin.js +37 -0
  81. package/dist/themes/catppuccinLatte.d.ts +2 -0
  82. package/dist/themes/catppuccinLatte.js +38 -0
  83. package/dist/themes/claude.d.ts +2 -0
  84. package/dist/themes/claude.js +48 -0
  85. package/dist/themes/claudeCode.d.ts +2 -0
  86. package/dist/themes/claudeCode.js +47 -0
  87. package/dist/themes/cursor.d.ts +2 -0
  88. package/dist/themes/cursor.js +38 -0
  89. package/dist/themes/cursorLight.d.ts +2 -0
  90. package/dist/themes/cursorLight.js +38 -0
  91. package/dist/themes/dark.d.ts +2 -0
  92. package/dist/themes/dark.js +38 -0
  93. package/dist/themes/githubDark.d.ts +2 -0
  94. package/dist/themes/githubDark.js +37 -0
  95. package/dist/themes/githubLight.d.ts +2 -0
  96. package/dist/themes/githubLight.js +38 -0
  97. package/dist/themes/index.d.ts +9 -0
  98. package/dist/themes/index.js +83 -0
  99. package/dist/themes/instagram.d.ts +2 -0
  100. package/dist/themes/instagram.js +37 -0
  101. package/dist/themes/instagramLight.d.ts +2 -0
  102. package/dist/themes/instagramLight.js +38 -0
  103. package/dist/themes/intellij.d.ts +2 -0
  104. package/dist/themes/intellij.js +37 -0
  105. package/dist/themes/intellijLight.d.ts +2 -0
  106. package/dist/themes/intellijLight.js +38 -0
  107. package/dist/themes/light.d.ts +2 -0
  108. package/dist/themes/light.js +38 -0
  109. package/dist/themes/nord.d.ts +2 -0
  110. package/dist/themes/nord.js +37 -0
  111. package/dist/themes/nordLight.d.ts +2 -0
  112. package/dist/themes/nordLight.js +38 -0
  113. package/dist/themes/postman.d.ts +2 -0
  114. package/dist/themes/postman.js +37 -0
  115. package/dist/themes/postmanLight.d.ts +2 -0
  116. package/dist/themes/postmanLight.js +38 -0
  117. package/dist/themes/spiderman.d.ts +2 -0
  118. package/dist/themes/spiderman.js +37 -0
  119. package/dist/themes/terminal.d.ts +2 -0
  120. package/dist/themes/terminal.js +37 -0
  121. package/dist/themes/ubuntu.d.ts +2 -0
  122. package/dist/themes/ubuntu.js +37 -0
  123. package/dist/themes/ubuntuLight.d.ts +2 -0
  124. package/dist/themes/ubuntuLight.js +38 -0
  125. package/dist/themes/x.d.ts +2 -0
  126. package/dist/themes/x.js +38 -0
  127. package/dist/themes/xLight.d.ts +2 -0
  128. package/dist/themes/xLight.js +38 -0
  129. package/dist/types/calendar.d.ts +19 -0
  130. package/dist/types/calendar.js +1 -0
  131. package/dist/types/storage.d.ts +21 -0
  132. package/dist/types/storage.js +1 -0
  133. package/dist/types/task.d.ts +21 -0
  134. package/dist/types/task.js +1 -0
  135. package/dist/types/theme.d.ts +38 -0
  136. package/dist/types/theme.js +1 -0
  137. package/dist/types/timeline.d.ts +23 -0
  138. package/dist/types/timeline.js +9 -0
  139. package/dist/utils/date.d.ts +7 -0
  140. package/dist/utils/date.js +37 -0
  141. package/dist/utils/logger.d.ts +3 -0
  142. package/dist/utils/logger.js +39 -0
  143. package/dist/utils/tree.d.ts +11 -0
  144. package/dist/utils/tree.js +64 -0
  145. package/dist/utils/validation.d.ts +7 -0
  146. package/dist/utils/validation.js +35 -0
  147. package/package.json +44 -0
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box } from "ink";
3
+ import { Text } from "../common/ThemedText";
4
+ import { useTheme } from "../../contexts/ThemeContext";
5
+ export const Pane = ({ children, title, isFocused = false, width, height, center = false, }) => {
6
+ const { theme } = useTheme();
7
+ // Allow height to be controlled by content or parent, don't force full screen
8
+ const paneHeight = height;
9
+ return (_jsxs(Box, { flexDirection: "column", width: width, height: paneHeight, paddingRight: 1, paddingX: 2, alignItems: center ? "center" : "flex-start", children: [title && (_jsx(Box, { marginBottom: 1, children: _jsx(Text, { backgroundColor: isFocused ? theme.colors.focusIndicator : undefined, color: isFocused ? theme.colors.background : theme.colors.taskHeader, bold: true, children: isFocused ? ` ${title.toUpperCase()} ` : title }) })), _jsx(Box, { flexDirection: "column", flexGrow: 1, overflowY: "hidden", alignItems: center ? "center" : "flex-start", children: children })] }));
10
+ };
@@ -0,0 +1,13 @@
1
+ import React from "react";
2
+ import type { ReactNode } from "react";
3
+ interface ThreeColumnLayoutProps {
4
+ leftPane: ReactNode;
5
+ centerPane: ReactNode;
6
+ rightPane: ReactNode;
7
+ leftWidth?: number | string;
8
+ rightWidth?: number | string;
9
+ height?: number;
10
+ activePane?: "calendar" | "tasks" | "timeline";
11
+ }
12
+ export declare const ThreeColumnLayout: React.FC<ThreeColumnLayoutProps>;
13
+ export {};
@@ -0,0 +1,22 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { useTheme } from "../../contexts/ThemeContext";
4
+ // Vertical separator component that fills height with proper background
5
+ const VerticalSeparator = ({ color, backgroundColor, height, isFocused }) => {
6
+ // Create a column of characters - use heavy vertical line if focused
7
+ const char = isFocused ? "┃" : "│";
8
+ const lines = height ? Array(height).fill(char) : [char];
9
+ return (_jsx(Box, { flexDirection: "column", backgroundColor: backgroundColor, children: lines.map((c, i) => (_jsx(Text, { color: color, backgroundColor: backgroundColor, children: c }, i))) }));
10
+ };
11
+ export const ThreeColumnLayout = ({ leftPane, centerPane, rightPane, leftWidth = "15%", rightWidth = "25%", height, activePane, }) => {
12
+ const { theme } = useTheme();
13
+ const focusedColor = theme.colors.focusIndicator;
14
+ const normalColor = theme.colors.border;
15
+ // Apply background color for non-terminal themes
16
+ const bgColor = theme.name !== "terminal" ? theme.colors.background : undefined;
17
+ return (_jsxs(Box, { flexDirection: "row", width: "100%", height: height, backgroundColor: bgColor, children: [_jsx(Box, { width: leftWidth, flexShrink: 0, flexDirection: "column", backgroundColor: bgColor, children: leftPane }), _jsx(VerticalSeparator, { isFocused: activePane === "calendar" || activePane === "tasks", color: activePane === "calendar" || activePane === "tasks"
18
+ ? focusedColor
19
+ : normalColor, backgroundColor: bgColor, height: height }), _jsx(Box, { flexGrow: 1, flexShrink: 1, flexDirection: "column", backgroundColor: bgColor, children: centerPane }), _jsx(VerticalSeparator, { isFocused: activePane === "tasks" || activePane === "timeline", color: activePane === "tasks" || activePane === "timeline"
20
+ ? focusedColor
21
+ : normalColor, backgroundColor: bgColor, height: height }), _jsx(Box, { width: rightWidth, flexShrink: 0.3, flexDirection: "column", backgroundColor: bgColor, children: rightPane })] }));
22
+ };
@@ -0,0 +1,2 @@
1
+ import React from "react";
2
+ export declare const OverviewScreen: React.FC;
@@ -0,0 +1,138 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { useMemo } from "react";
3
+ import { Box, Text, useInput } from "ink";
4
+ import { useTheme } from "../../contexts/ThemeContext";
5
+ import { useApp } from "../../contexts/AppContext";
6
+ import { getDateString, formatDate } from "../../utils/date";
7
+ import { startOfMonth, endOfMonth, eachDayOfInterval } from "date-fns";
8
+ import { useTerminalSize } from "../../hooks/useTerminalSize";
9
+ export const OverviewScreen = () => {
10
+ const { theme } = useTheme();
11
+ const { tasks, overviewMonth, setOverviewMonth, setShowOverview } = useApp();
12
+ const [scrollOffset, setScrollOffset] = React.useState(0);
13
+ const { height: terminalHeight } = useTerminalSize();
14
+ // Calculate visible rows based on terminal height to avoid wasting space
15
+ // Header (~3) + Footer (~2) + Padding (~2) + Indicators (~2) = ~9 lines fixed
16
+ // Minimum row height is 3 lines (Date + "No tasks" + margin)
17
+ const visibleRows = useMemo(() => {
18
+ return Math.max(2, Math.floor((terminalHeight - 9) / 3));
19
+ }, [terminalHeight]);
20
+ const monthDates = useMemo(() => {
21
+ const monthStart = startOfMonth(new Date(overviewMonth.year, overviewMonth.month, 1));
22
+ const monthEnd = endOfMonth(monthStart);
23
+ return eachDayOfInterval({ start: monthStart, end: monthEnd });
24
+ }, [overviewMonth]);
25
+ // Get tasks grouped by date
26
+ const tasksByDate = useMemo(() => {
27
+ const grouped = {};
28
+ monthDates.forEach((date) => {
29
+ const dateStr = getDateString(date);
30
+ grouped[dateStr] = tasks[dateStr] || [];
31
+ });
32
+ return grouped;
33
+ }, [monthDates, tasks]);
34
+ // Month navigation
35
+ const handlePrevMonth = () => {
36
+ const newMonth = overviewMonth.month - 1;
37
+ if (newMonth < 0) {
38
+ setOverviewMonth({ year: overviewMonth.year - 1, month: 11 });
39
+ }
40
+ else {
41
+ setOverviewMonth({ ...overviewMonth, month: newMonth });
42
+ }
43
+ };
44
+ const handleNextMonth = () => {
45
+ const newMonth = overviewMonth.month + 1;
46
+ if (newMonth > 11) {
47
+ setOverviewMonth({ year: overviewMonth.year + 1, month: 0 });
48
+ }
49
+ else {
50
+ setOverviewMonth({ ...overviewMonth, month: newMonth });
51
+ }
52
+ };
53
+ // Reset scroll when month changes
54
+ React.useEffect(() => {
55
+ setScrollOffset(0);
56
+ }, [overviewMonth]);
57
+ useInput((input, key) => {
58
+ if (key.escape) {
59
+ setShowOverview(false);
60
+ return;
61
+ }
62
+ if (input === "n" || key.rightArrow) {
63
+ handleNextMonth();
64
+ return;
65
+ }
66
+ if (input === "p" || key.leftArrow) {
67
+ handlePrevMonth();
68
+ return;
69
+ }
70
+ if (input === "j" || key.downArrow) {
71
+ setScrollOffset((prev) => Math.min(prev + 1, Math.max(0, rows - visibleRows)));
72
+ return;
73
+ }
74
+ if (input === "k" || key.upArrow) {
75
+ setScrollOffset((prev) => Math.max(prev - 1, 0));
76
+ return;
77
+ }
78
+ });
79
+ const monthName = formatDate(new Date(overviewMonth.year, overviewMonth.month, 1), "MMMM yyyy");
80
+ // Calculate grid layout - 4 columns
81
+ const columns = 4;
82
+ const rows = Math.ceil(monthDates.length / columns);
83
+ const visibleRowData = Array.from({ length: rows }).slice(scrollOffset, scrollOffset + visibleRows);
84
+ const canScrollUp = scrollOffset > 0;
85
+ const canScrollDown = scrollOffset + visibleRows < rows;
86
+ return (_jsxs(Box, { flexDirection: "column", padding: 1, width: "100%", height: "100%", children: [_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { bold: true, color: theme.colors.focusIndicator, children: "Overview" }), _jsx(Text, { color: theme.colors.foreground, children: monthName })] }), _jsxs(Box, { flexDirection: "column", flexGrow: 1, children: [canScrollUp && (_jsx(Box, { justifyContent: "center", marginBottom: 1, children: _jsx(Text, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more above --" }) })), visibleRowData.map((_, index) => {
87
+ const rowIndex = scrollOffset + index;
88
+ return (_jsx(Box, { flexDirection: "row", marginBottom: 1, children: Array.from({ length: columns }).map((_, colIndex) => {
89
+ const dateIndex = rowIndex * columns + colIndex;
90
+ const date = monthDates[dateIndex];
91
+ if (!date) {
92
+ return (_jsx(Box, { flexDirection: "column", flexGrow: 1, flexBasis: 0, marginRight: colIndex === columns - 1 ? 0 : 2 }, `empty-${colIndex}`));
93
+ }
94
+ const dateStr = getDateString(date);
95
+ const dayTasks = tasksByDate[dateStr] || [];
96
+ // Flatten tasks with depth info for indentation
97
+ const flatTasksWithDepth = [];
98
+ const traverse = (taskList, depth) => {
99
+ for (const task of taskList) {
100
+ flatTasksWithDepth.push({ task, depth });
101
+ traverse(task.children, depth + 1);
102
+ }
103
+ };
104
+ traverse(dayTasks, 0);
105
+ return (_jsxs(Box, { flexDirection: "column", flexGrow: 1, flexBasis: 0, marginRight: colIndex === columns - 1 ? 0 : 2, children: [_jsx(Text, { bold: true, color: theme.colors.calendarSelected, children: formatDate(date, "do MMM") }), _jsxs(Box, { flexDirection: "column", children: [flatTasksWithDepth.length === 0 ? (_jsx(Text, { dimColor: true, color: theme.colors.keyboardHint, children: "No tasks" })) : (flatTasksWithDepth
106
+ .slice(0, 10)
107
+ .map(({ task, depth }) => (_jsx(TaskItem, { task: task, theme: theme, depth: depth }, task.id)))), flatTasksWithDepth.length > 10 && (_jsxs(Text, { dimColor: true, color: theme.colors.keyboardHint, children: ["+", flatTasksWithDepth.length - 10, " more..."] }))] })] }, dateStr));
108
+ }) }, rowIndex));
109
+ }), canScrollDown && (_jsx(Box, { justifyContent: "center", marginTop: 1, children: _jsx(Text, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more below --" }) }))] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: theme.colors.keyboardHint, dimColor: true, children: "n/p or \u2190/\u2192: month | j/k or \u2193/\u2191: scroll | Esc: close | Shift+;: toggle" }) })] }));
110
+ };
111
+ const TaskItem = ({ task, theme, depth }) => {
112
+ const checkbox = getCheckbox(task.state);
113
+ const color = getStateColor(task.state, theme);
114
+ // Note: We don't recurse here anymore because the parent component (OverviewScreen)
115
+ // already uses flattenTasks() to get a flat list of all tasks including children.
116
+ return (_jsxs(Box, { children: [_jsxs(Text, { color: color, children: [checkbox, " "] }), depth > 0 && _jsx(Text, { children: " ".repeat(depth) }), _jsx(Text, { color: color, strikethrough: task.state === "completed", dimColor: task.state === "delayed", children: task.title.length > 35 ? task.title.slice(0, 32) + "..." : task.title })] }));
117
+ };
118
+ function getCheckbox(state) {
119
+ switch (state) {
120
+ case "completed":
121
+ return "[✓]";
122
+ case "delegated":
123
+ return "[→]";
124
+ case "delayed":
125
+ return "[‖]";
126
+ default:
127
+ return "[ ]";
128
+ }
129
+ }
130
+ function getStateColor(state, theme) {
131
+ const colors = {
132
+ todo: theme.colors.taskStateTodo,
133
+ completed: theme.colors.taskStateCompleted,
134
+ delegated: theme.colors.taskStateDelegated,
135
+ delayed: theme.colors.taskStateDelayed,
136
+ };
137
+ return colors[state] || theme.colors.foreground;
138
+ }
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ interface TaskHeaderProps {
3
+ selectedDate: Date;
4
+ completionPercentage: number;
5
+ }
6
+ export declare const TaskHeader: React.FC<TaskHeaderProps>;
7
+ export {};
@@ -0,0 +1,8 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { useTheme } from "../../contexts/ThemeContext";
4
+ import { formatDate } from "../../utils/date";
5
+ export const TaskHeader = ({ selectedDate, completionPercentage, }) => {
6
+ const { theme } = useTheme();
7
+ return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Text, { color: theme.colors.taskHeader, children: formatDate(selectedDate, "EEEE, MMMM d, yyyy") }), _jsxs(Text, { color: theme.colors.taskHeader, children: [completionPercentage, "% completed"] })] }));
8
+ };
@@ -0,0 +1,10 @@
1
+ import React from "react";
2
+ import type { Task } from "../../types/task";
3
+ interface TaskItemProps {
4
+ task: Task;
5
+ depth: number;
6
+ isSelected: boolean;
7
+ isExpanded: boolean;
8
+ }
9
+ export declare const TaskItem: React.FC<TaskItemProps>;
10
+ export {};
@@ -0,0 +1,25 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from "ink";
3
+ import { useTheme } from "../../contexts/ThemeContext";
4
+ export const TaskItem = ({ task, depth, isSelected, isExpanded, }) => {
5
+ const { theme } = useTheme();
6
+ const stateColors = {
7
+ todo: theme.colors.taskStateTodo,
8
+ completed: theme.colors.taskStateCompleted,
9
+ delegated: theme.colors.taskStateDelegated,
10
+ delayed: theme.colors.taskStateDelayed,
11
+ };
12
+ const checkbox = task.state === "completed"
13
+ ? "☑"
14
+ : task.state === "delegated"
15
+ ? "↦"
16
+ : task.state === "delayed"
17
+ ? "⏸"
18
+ : "☐";
19
+ const expandIcon = task.children.length > 0 ? (isExpanded ? "▼ " : "▶ ") : " ";
20
+ const indent = " ".repeat(depth);
21
+ const selector = isSelected ? ">" : " ";
22
+ const textColor = stateColors[task.state] || theme.colors.foreground;
23
+ const strikethrough = task.state === "completed";
24
+ return (_jsxs(Box, { children: [_jsx(Text, { color: isSelected ? theme.colors.focusIndicator : theme.colors.foreground, children: selector }), _jsx(Text, { children: " " }), _jsx(Text, { color: textColor, children: checkbox }), _jsx(Text, { children: " " }), _jsx(Text, { children: expandIcon }), _jsx(Text, { children: indent }), _jsx(Text, { color: textColor, strikethrough: strikethrough, dimColor: task.state === "delayed", children: task.title }), task.startTime && !task.endTime && (_jsx(Text, { color: theme.colors.timelineEventStarted, children: " \u25B6" }))] }));
25
+ };
@@ -0,0 +1,11 @@
1
+ import React from "react";
2
+ import type { Task } from "../../types/task";
3
+ interface TaskListProps {
4
+ tasks: Task[];
5
+ depth?: number;
6
+ selectedId?: string;
7
+ expandedIds?: Set<string>;
8
+ onToggleExpand?: (id: string) => void;
9
+ }
10
+ export declare const TaskList: React.FC<TaskListProps>;
11
+ export {};
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box } from "ink";
3
+ import { TaskItem } from "./TaskItem";
4
+ export const TaskList = ({ tasks, depth = 0, selectedId, expandedIds = new Set(), onToggleExpand, }) => {
5
+ return (_jsx(Box, { flexDirection: "column", children: tasks.map((task) => {
6
+ const isSelected = task.id === selectedId;
7
+ const isExpanded = expandedIds.has(task.id);
8
+ const hasChildren = task.children.length > 0;
9
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(TaskItem, { task: task, depth: depth, isSelected: isSelected, isExpanded: isExpanded }), hasChildren && isExpanded && (_jsx(TaskList, { tasks: task.children, depth: depth + 1, selectedId: selectedId, expandedIds: expandedIds, onToggleExpand: onToggleExpand }))] }, task.id));
10
+ }) }));
11
+ };
@@ -0,0 +1,2 @@
1
+ import React from "react";
2
+ export declare const TasksPane: React.FC;