epoch-tui 0.1.2 → 0.1.3

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 (2) hide show
  1. package/dist/index.js +379 -233
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { render } from "ink";
5
5
 
6
6
  // src/App.tsx
7
- import { Box as Box16, Text as Text12 } from "ink";
7
+ import { Box as Box17, Text as Text14 } from "ink";
8
8
 
9
9
  // src/contexts/ThemeContext.tsx
10
10
  import { createContext as createContext2, useContext as useContext2, useState as useState2, useEffect as useEffect2 } from "react";
@@ -1915,8 +1915,8 @@ var ThreeColumnLayout = ({
1915
1915
  leftPane,
1916
1916
  centerPane,
1917
1917
  rightPane,
1918
- leftWidth = "15%",
1919
- rightWidth = "25%",
1918
+ leftWidth = "20%",
1919
+ rightWidth = "30%",
1920
1920
  height,
1921
1921
  activePane
1922
1922
  }) => {
@@ -1987,7 +1987,7 @@ var ThreeColumnLayout = ({
1987
1987
 
1988
1988
  // src/components/calendar/CalendarPane.tsx
1989
1989
  import { useState as useState5, useEffect as useEffect6 } from "react";
1990
- import { Box as Box5, Text as Text3, useInput as useInput2 } from "ink";
1990
+ import { Box as Box6, useInput as useInput2 } from "ink";
1991
1991
  import { addDays, addWeeks, subDays, subWeeks } from "date-fns";
1992
1992
 
1993
1993
  // src/components/layout/Pane.tsx
@@ -2092,6 +2092,30 @@ var MonthView = ({ calendarView }) => {
2092
2092
  ] });
2093
2093
  };
2094
2094
 
2095
+ // src/components/common/KeyboardHints.tsx
2096
+ import { Box as Box5, Text as Text3 } from "ink";
2097
+ import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
2098
+ var KeyboardHints = ({ hints }) => {
2099
+ const { theme } = useTheme();
2100
+ return /* @__PURE__ */ jsx9(
2101
+ Box5,
2102
+ {
2103
+ marginTop: 1,
2104
+ flexDirection: "row",
2105
+ flexWrap: "wrap",
2106
+ columnGap: 2,
2107
+ width: "100%",
2108
+ children: hints.map((hint, index) => /* @__PURE__ */ jsxs5(Box5, { children: [
2109
+ /* @__PURE__ */ jsx9(Text3, { color: theme.colors.focusIndicator, bold: true, children: hint.key }),
2110
+ /* @__PURE__ */ jsxs5(Text3, { color: theme.colors.keyboardHint, children: [
2111
+ " ",
2112
+ hint.description
2113
+ ] })
2114
+ ] }, index))
2115
+ }
2116
+ );
2117
+ };
2118
+
2095
2119
  // src/utils/date.ts
2096
2120
  import { format, startOfMonth, endOfMonth, eachDayOfInterval, startOfWeek, endOfWeek } from "date-fns";
2097
2121
  var formatDate = (date, formatStr = "MMM d, yyyy") => {
@@ -2186,10 +2210,17 @@ var CalendarService = class {
2186
2210
  var calendarService = new CalendarService();
2187
2211
 
2188
2212
  // src/components/calendar/CalendarPane.tsx
2189
- import { jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
2213
+ import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
2190
2214
  var CalendarPane = () => {
2191
2215
  const { theme } = useTheme();
2192
- const { selectedDate, setSelectedDate, tasks, activePane, isModalOpen, isInputMode } = useApp();
2216
+ const {
2217
+ selectedDate,
2218
+ setSelectedDate,
2219
+ tasks,
2220
+ activePane,
2221
+ isModalOpen,
2222
+ isInputMode
2223
+ } = useApp();
2193
2224
  const [currentMonth, setCurrentMonth] = useState5({
2194
2225
  year: selectedDate.year,
2195
2226
  month: selectedDate.month
@@ -2276,39 +2307,115 @@ var CalendarPane = () => {
2276
2307
  { isActive: isFocused && !isInputMode }
2277
2308
  );
2278
2309
  const monthName = calendarService.getMonthName(currentMonth.month);
2279
- return /* @__PURE__ */ jsx9(
2310
+ return /* @__PURE__ */ jsx10(
2280
2311
  Pane,
2281
2312
  {
2282
2313
  title: `${monthName} ${currentMonth.year}`,
2283
2314
  isFocused,
2284
2315
  center: true,
2285
- children: /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", alignItems: "center", children: [
2286
- /* @__PURE__ */ jsx9(MonthView, { calendarView }),
2287
- /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", alignItems: "center", children: [
2288
- /* @__PURE__ */ jsx9(Text3, { color: theme.colors.keyboardHint, dimColor: true, children: "h/l: days j/k: weeks" }),
2289
- /* @__PURE__ */ jsx9(Text3, { color: theme.colors.keyboardHint, dimColor: true, children: "n/p: month T: today" })
2290
- ] })
2316
+ children: /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", alignItems: "center", children: [
2317
+ /* @__PURE__ */ jsx10(MonthView, { calendarView }),
2318
+ /* @__PURE__ */ jsx10(
2319
+ KeyboardHints,
2320
+ {
2321
+ hints: [
2322
+ { key: "h/l", description: "days" },
2323
+ { key: "j/k", description: "weeks" },
2324
+ { key: "n/p", description: "month" },
2325
+ { key: "T", description: "today" }
2326
+ ]
2327
+ }
2328
+ )
2291
2329
  ] })
2292
2330
  }
2293
2331
  );
2294
2332
  };
2295
2333
 
2296
2334
  // src/components/tasks/TasksPane.tsx
2297
- import { useState as useState6, useEffect as useEffect7, useMemo, useRef as useRef3 } from "react";
2298
- import { Box as Box7, Text as Text5, useInput as useInput3 } from "ink";
2299
- import { TextInput } from "@inkjs/ui";
2335
+ import { useState as useState6, useEffect as useEffect8, useMemo } from "react";
2336
+ import { Box as Box8, Text as Text7, useInput as useInput4 } from "ink";
2337
+
2338
+ // src/components/common/ControlledTextInput.tsx
2339
+ import { useRef as useRef3, useEffect as useEffect7 } from "react";
2340
+ import { Text as Text5, useInput as useInput3 } from "ink";
2341
+ import { jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2342
+ var ControlledTextInput = ({
2343
+ value,
2344
+ onChange,
2345
+ onSubmit,
2346
+ onCancel,
2347
+ placeholder,
2348
+ focus = true,
2349
+ placeholderColor,
2350
+ cursorColor = "white",
2351
+ color,
2352
+ maxLength
2353
+ }) => {
2354
+ const pendingValueRef = useRef3(value);
2355
+ const sentValuesRef = useRef3(/* @__PURE__ */ new Set([value]));
2356
+ useEffect7(() => {
2357
+ if (value === pendingValueRef.current) {
2358
+ return;
2359
+ }
2360
+ if (sentValuesRef.current.has(value)) {
2361
+ return;
2362
+ }
2363
+ pendingValueRef.current = value;
2364
+ sentValuesRef.current.clear();
2365
+ sentValuesRef.current.add(value);
2366
+ }, [value]);
2367
+ useInput3(
2368
+ (input, key) => {
2369
+ const currentValue = pendingValueRef.current;
2370
+ if (key.escape) {
2371
+ onCancel?.();
2372
+ return;
2373
+ }
2374
+ if (key.return) {
2375
+ onSubmit(currentValue);
2376
+ return;
2377
+ }
2378
+ if (input === "\r" || input === "\n") return;
2379
+ let nextValue = currentValue;
2380
+ if (key.backspace || key.delete) {
2381
+ nextValue = currentValue.slice(0, -1);
2382
+ } else if (!key.ctrl && !key.meta && input.length > 0) {
2383
+ const filtered = input.replace(/[\x00-\x1F\x7F]/g, "");
2384
+ if (filtered) {
2385
+ const possibleValue = currentValue + filtered;
2386
+ if (maxLength && possibleValue.length > maxLength) {
2387
+ return;
2388
+ }
2389
+ nextValue = possibleValue;
2390
+ }
2391
+ }
2392
+ if (nextValue !== currentValue) {
2393
+ pendingValueRef.current = nextValue;
2394
+ sentValuesRef.current.add(nextValue);
2395
+ onChange(nextValue);
2396
+ }
2397
+ },
2398
+ { isActive: focus }
2399
+ );
2400
+ const displayValue = pendingValueRef.current || "";
2401
+ const showPlaceholder = !displayValue && placeholder;
2402
+ return /* @__PURE__ */ jsxs7(Text5, { children: [
2403
+ showPlaceholder ? /* @__PURE__ */ jsx11(Text5, { dimColor: true, color: placeholderColor, children: placeholder }) : /* @__PURE__ */ jsx11(Text5, { color, children: displayValue }),
2404
+ focus && /* @__PURE__ */ jsx11(Text5, { backgroundColor: cursorColor, children: " " })
2405
+ ] });
2406
+ };
2300
2407
 
2301
2408
  // src/components/tasks/TaskHeader.tsx
2302
- import { Box as Box6, Text as Text4 } from "ink";
2303
- import { jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
2409
+ import { Box as Box7, Text as Text6 } from "ink";
2410
+ import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
2304
2411
  var TaskHeader = ({
2305
2412
  selectedDate,
2306
2413
  completionPercentage
2307
2414
  }) => {
2308
2415
  const { theme } = useTheme();
2309
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
2310
- /* @__PURE__ */ jsx10(Text4, { color: theme.colors.taskHeader, children: formatDate(selectedDate, "EEEE, MMMM d, yyyy") }),
2311
- /* @__PURE__ */ jsxs6(Text4, { color: theme.colors.taskHeader, children: [
2416
+ return /* @__PURE__ */ jsxs8(Box7, { flexDirection: "column", marginBottom: 1, children: [
2417
+ /* @__PURE__ */ jsx12(Text6, { color: theme.colors.taskHeader, children: formatDate(selectedDate, "EEEE, MMMM d, yyyy") }),
2418
+ /* @__PURE__ */ jsxs8(Text6, { color: theme.colors.taskHeader, children: [
2312
2419
  completionPercentage,
2313
2420
  "% completed"
2314
2421
  ] })
@@ -2595,7 +2702,7 @@ var TimelineService = class {
2595
2702
  var timelineService = new TimelineService();
2596
2703
 
2597
2704
  // src/components/tasks/TasksPane.tsx
2598
- import { Fragment, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
2705
+ import { Fragment, jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
2599
2706
  var TasksPane = () => {
2600
2707
  const {
2601
2708
  tasks,
@@ -2614,8 +2721,6 @@ var TasksPane = () => {
2614
2721
  const [editMode, setEditMode] = useState6("none");
2615
2722
  const [editValue, setEditValue] = useState6("");
2616
2723
  const [parentTaskId, setParentTaskId] = useState6(null);
2617
- const inputValueRef = useRef3("");
2618
- const [inputKey, setInputKey] = useState6(0);
2619
2724
  const [scrollOffset, setScrollOffset] = useState6(0);
2620
2725
  const { height: terminalHeight } = useTerminalSize();
2621
2726
  const visibleRows = useMemo(() => {
@@ -2642,48 +2747,55 @@ var TasksPane = () => {
2642
2747
  }, [dayTasks, expandedIds]);
2643
2748
  const selectedTask = flatTasks[selectedIndex]?.task;
2644
2749
  const selectedTaskId = selectedTask?.id;
2645
- useEffect7(() => {
2750
+ useEffect8(() => {
2751
+ const allParentIds = /* @__PURE__ */ new Set();
2752
+ const collectParents = (taskList) => {
2753
+ for (const task of taskList) {
2754
+ if (task.children.length > 0) {
2755
+ allParentIds.add(task.id);
2756
+ collectParents(task.children);
2757
+ }
2758
+ }
2759
+ };
2760
+ collectParents(dayTasks);
2761
+ setExpandedIds(allParentIds);
2762
+ }, [dayTasks]);
2763
+ useEffect8(() => {
2646
2764
  setSelectedIndex(0);
2647
2765
  setEditMode("none");
2648
2766
  }, [dateStr]);
2649
- useEffect7(() => {
2767
+ useEffect8(() => {
2650
2768
  if (selectedIndex >= flatTasks.length && flatTasks.length > 0) {
2651
2769
  setSelectedIndex(flatTasks.length - 1);
2652
2770
  }
2653
2771
  }, [flatTasks.length, selectedIndex]);
2654
- useEffect7(() => {
2772
+ useEffect8(() => {
2655
2773
  if (selectedIndex < scrollOffset) {
2656
2774
  setScrollOffset(selectedIndex);
2657
2775
  } else if (selectedIndex >= scrollOffset + visibleRows) {
2658
2776
  setScrollOffset(selectedIndex - visibleRows + 1);
2659
2777
  }
2660
2778
  }, [selectedIndex, visibleRows, scrollOffset]);
2661
- useEffect7(() => {
2779
+ useEffect8(() => {
2662
2780
  setScrollOffset(0);
2663
2781
  }, [dateStr]);
2664
2782
  const handleAddTask = () => {
2665
- inputValueRef.current = "";
2666
2783
  setEditMode("add");
2667
2784
  setEditValue("");
2668
- setInputKey((k) => k + 1);
2669
2785
  setIsInputMode(true);
2670
2786
  };
2671
2787
  const handleEditTask = () => {
2672
2788
  if (selectedTask) {
2673
- inputValueRef.current = selectedTask.title;
2674
2789
  setEditMode("edit");
2675
2790
  setEditValue(selectedTask.title);
2676
- setInputKey((k) => k + 1);
2677
2791
  setIsInputMode(true);
2678
2792
  }
2679
2793
  };
2680
2794
  const handleAddSubtask = () => {
2681
2795
  if (selectedTask) {
2682
- inputValueRef.current = "";
2683
2796
  setEditMode("addSubtask");
2684
2797
  setEditValue("");
2685
2798
  setParentTaskId(selectedTask.id);
2686
- setInputKey((k) => k + 1);
2687
2799
  setIsInputMode(true);
2688
2800
  setExpandedIds((prev) => new Set(prev).add(selectedTask.id));
2689
2801
  }
@@ -2847,15 +2959,7 @@ var TasksPane = () => {
2847
2959
  const handleCollapseAll = () => {
2848
2960
  setExpandedIds(/* @__PURE__ */ new Set());
2849
2961
  };
2850
- useInput3(
2851
- (_input, key) => {
2852
- if (key.escape) {
2853
- handleCancelEdit();
2854
- }
2855
- },
2856
- { isActive: isFocused && editMode !== "none" }
2857
- );
2858
- useInput3(
2962
+ useInput4(
2859
2963
  (input, key) => {
2860
2964
  if ((key.meta || key.ctrl) && (input === "a" || key.leftArrow)) {
2861
2965
  handleCollapseAll();
@@ -2950,92 +3054,95 @@ var TasksPane = () => {
2950
3054
  },
2951
3055
  { isActive: isFocused && editMode === "none" }
2952
3056
  );
2953
- return /* @__PURE__ */ jsx11(Pane, { title: "Tasks", isFocused, children: /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", flexGrow: 1, children: [
2954
- /* @__PURE__ */ jsx11(
3057
+ return /* @__PURE__ */ jsx13(Pane, { title: "Tasks", isFocused, children: /* @__PURE__ */ jsxs9(Box8, { flexDirection: "column", flexGrow: 1, width: "100%", children: [
3058
+ /* @__PURE__ */ jsx13(
2955
3059
  TaskHeader,
2956
3060
  {
2957
3061
  selectedDate: new Date(selectedDate.year, selectedDate.month, selectedDate.day),
2958
3062
  completionPercentage: stats.percentage
2959
3063
  }
2960
3064
  ),
2961
- editMode === "add" && /* @__PURE__ */ jsxs7(Box7, { marginY: 1, children: [
2962
- /* @__PURE__ */ jsx11(Text5, { color: theme.colors.focusIndicator, children: "> " }),
2963
- /* @__PURE__ */ jsx11(
2964
- TextInput,
3065
+ editMode === "add" && /* @__PURE__ */ jsxs9(Box8, { marginY: 1, children: [
3066
+ /* @__PURE__ */ jsx13(Text7, { color: theme.colors.focusIndicator, children: "> " }),
3067
+ /* @__PURE__ */ jsx13(
3068
+ ControlledTextInput,
2965
3069
  {
2966
- defaultValue: "",
3070
+ value: editValue,
2967
3071
  placeholder: "Enter task name...",
2968
- onChange: (val) => {
2969
- inputValueRef.current = val;
2970
- },
2971
- onSubmit: handleSubmitEdit
2972
- },
2973
- `add-${inputKey}`
3072
+ onChange: setEditValue,
3073
+ onSubmit: handleSubmitEdit,
3074
+ onCancel: handleCancelEdit,
3075
+ color: theme.colors.foreground,
3076
+ placeholderColor: theme.colors.foreground,
3077
+ maxLength: 60
3078
+ }
2974
3079
  )
2975
3080
  ] }),
2976
- editMode === "addSubtask" && /* @__PURE__ */ jsxs7(Box7, { marginY: 1, children: [
2977
- /* @__PURE__ */ jsx11(Text5, { color: theme.colors.focusIndicator, children: "> " }),
2978
- /* @__PURE__ */ jsx11(Text5, { color: theme.colors.keyboardHint, children: " " }),
2979
- /* @__PURE__ */ jsx11(
2980
- TextInput,
3081
+ editMode === "addSubtask" && /* @__PURE__ */ jsxs9(Box8, { marginY: 1, children: [
3082
+ /* @__PURE__ */ jsx13(Text7, { color: theme.colors.focusIndicator, children: "> " }),
3083
+ /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, children: " " }),
3084
+ /* @__PURE__ */ jsx13(
3085
+ ControlledTextInput,
2981
3086
  {
2982
- defaultValue: "",
3087
+ value: editValue,
2983
3088
  placeholder: "Enter subtask name...",
2984
- onChange: (val) => {
2985
- inputValueRef.current = val;
2986
- },
2987
- onSubmit: handleSubmitEdit
2988
- },
2989
- `subtask-${inputKey}`
3089
+ onChange: setEditValue,
3090
+ onSubmit: handleSubmitEdit,
3091
+ onCancel: handleCancelEdit,
3092
+ color: theme.colors.foreground,
3093
+ placeholderColor: theme.colors.foreground,
3094
+ maxLength: 60
3095
+ }
2990
3096
  )
2991
3097
  ] }),
2992
- dayTasks.length === 0 && editMode !== "add" && editMode !== "addSubtask" ? /* @__PURE__ */ jsx11(Box7, { marginY: 1, children: /* @__PURE__ */ jsx11(Text5, { color: theme.colors.keyboardHint, dimColor: true, children: "No tasks. Press 'a' to add one." }) }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", marginY: 1, paddingRight: 2, children: [
2993
- scrollOffset > 0 && /* @__PURE__ */ jsx11(Box7, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx11(Text5, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more above --" }) }),
3098
+ dayTasks.length === 0 && editMode !== "add" && editMode !== "addSubtask" ? /* @__PURE__ */ jsx13(Box8, { marginY: 1, children: /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "No tasks. Press 'a' to add one." }) }) : /* @__PURE__ */ jsxs9(Box8, { flexDirection: "column", marginY: 1, paddingRight: 2, children: [
3099
+ scrollOffset > 0 && /* @__PURE__ */ jsx13(Box8, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more above --" }) }),
2994
3100
  flatTasks.slice(scrollOffset, scrollOffset + visibleRows).map(({ task, depth }, sliceIndex) => {
2995
3101
  const index = scrollOffset + sliceIndex;
2996
3102
  const isSelected = index === selectedIndex;
2997
3103
  const isExpanded = expandedIds.has(task.id);
2998
3104
  const isEditing = editMode === "edit" && isSelected;
2999
3105
  if (isEditing) {
3000
- return /* @__PURE__ */ jsxs7(Box7, { children: [
3001
- /* @__PURE__ */ jsx11(Text5, { color: theme.colors.focusIndicator, children: "> " }),
3002
- /* @__PURE__ */ jsx11(
3003
- TextInput,
3106
+ return /* @__PURE__ */ jsxs9(Box8, { children: [
3107
+ /* @__PURE__ */ jsx13(Text7, { color: theme.colors.focusIndicator, children: "> " }),
3108
+ /* @__PURE__ */ jsx13(
3109
+ ControlledTextInput,
3004
3110
  {
3005
- defaultValue: editValue,
3006
- onChange: (val) => {
3007
- inputValueRef.current = val;
3008
- },
3009
- onSubmit: handleSubmitEdit
3010
- },
3011
- `edit-${inputKey}`
3111
+ value: editValue,
3112
+ onChange: setEditValue,
3113
+ onSubmit: handleSubmitEdit,
3114
+ onCancel: handleCancelEdit,
3115
+ color: theme.colors.foreground,
3116
+ placeholderColor: theme.colors.foreground,
3117
+ maxLength: 60
3118
+ }
3012
3119
  )
3013
3120
  ] }, task.id);
3014
3121
  }
3015
- return /* @__PURE__ */ jsxs7(Box7, { children: [
3016
- /* @__PURE__ */ jsx11(
3017
- Text5,
3122
+ return /* @__PURE__ */ jsxs9(Box8, { children: [
3123
+ /* @__PURE__ */ jsx13(
3124
+ Text7,
3018
3125
  {
3019
3126
  color: isSelected ? theme.colors.focusIndicator : theme.colors.foreground,
3020
3127
  children: isSelected ? ">" : " "
3021
3128
  }
3022
3129
  ),
3023
- /* @__PURE__ */ jsx11(Text5, { children: " " }),
3024
- /* @__PURE__ */ jsx11(Text5, { children: " ".repeat(depth) }),
3025
- /* @__PURE__ */ jsx11(
3026
- Text5,
3130
+ /* @__PURE__ */ jsx13(Text7, { children: " " }),
3131
+ /* @__PURE__ */ jsx13(Text7, { children: " ".repeat(depth) }),
3132
+ /* @__PURE__ */ jsx13(
3133
+ Text7,
3027
3134
  {
3028
3135
  color: isSelected ? theme.colors.focusIndicator : getStateColor(task.state, theme),
3029
3136
  children: getCheckbox(task.state)
3030
3137
  }
3031
3138
  ),
3032
- /* @__PURE__ */ jsx11(Text5, { children: " " }),
3033
- task.children.length > 0 && /* @__PURE__ */ jsxs7(Fragment, { children: [
3034
- /* @__PURE__ */ jsx11(Text5, { children: isExpanded ? "\u25BC" : "\u25B6" }),
3035
- /* @__PURE__ */ jsx11(Text5, { children: " " })
3139
+ /* @__PURE__ */ jsx13(Text7, { children: " " }),
3140
+ task.children.length > 0 && /* @__PURE__ */ jsxs9(Fragment, { children: [
3141
+ /* @__PURE__ */ jsx13(Text7, { children: isExpanded ? "\u25BC" : "\u25B6" }),
3142
+ /* @__PURE__ */ jsx13(Text7, { children: " " })
3036
3143
  ] }),
3037
- /* @__PURE__ */ jsx11(
3038
- Text5,
3144
+ /* @__PURE__ */ jsx13(
3145
+ Text7,
3039
3146
  {
3040
3147
  color: isSelected ? theme.colors.focusIndicator : getStateColor(task.state, theme),
3041
3148
  strikethrough: task.state === "completed",
@@ -3043,8 +3150,8 @@ var TasksPane = () => {
3043
3150
  children: task.title
3044
3151
  }
3045
3152
  ),
3046
- task.startTime && !task.endTime && /* @__PURE__ */ jsxs7(
3047
- Text5,
3153
+ task.startTime && !task.endTime && /* @__PURE__ */ jsxs9(
3154
+ Text7,
3048
3155
  {
3049
3156
  color: isSelected ? theme.colors.focusIndicator : theme.colors.timelineEventStarted,
3050
3157
  children: [
@@ -3055,13 +3162,26 @@ var TasksPane = () => {
3055
3162
  )
3056
3163
  ] }, task.id);
3057
3164
  }),
3058
- scrollOffset + visibleRows < flatTasks.length && /* @__PURE__ */ jsx11(Box7, { justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx11(Text5, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more below --" }) })
3165
+ scrollOffset + visibleRows < flatTasks.length && /* @__PURE__ */ jsx13(Box8, { justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more below --" }) })
3059
3166
  ] }),
3060
- /* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
3061
- /* @__PURE__ */ jsx11(Text5, { color: theme.colors.keyboardHint, dimColor: true, children: "j/k: navigate a: add Tab: add subtask e: edit d: delete" }),
3062
- /* @__PURE__ */ jsx11(Text5, { color: theme.colors.keyboardHint, dimColor: true, children: "Space: complete D: delegate x: delay s: start" }),
3063
- /* @__PURE__ */ jsx11(Text5, { color: theme.colors.keyboardHint, dimColor: true, children: "\u2190/\u2192: collapse/expand Cmd+\u2190/\u2192: collapse/expand all" })
3064
- ] })
3167
+ /* @__PURE__ */ jsx13(
3168
+ KeyboardHints,
3169
+ {
3170
+ hints: [
3171
+ { key: "j/k", description: "navigate" },
3172
+ { key: "a", description: "add" },
3173
+ { key: "Tab", description: "add subtask" },
3174
+ { key: "e", description: "edit" },
3175
+ { key: "d", description: "delete" },
3176
+ { key: "Space", description: "complete" },
3177
+ { key: "D", description: "delegate" },
3178
+ { key: "x", description: "delay" },
3179
+ { key: "s", description: "start" },
3180
+ { key: "\u2190/\u2192", description: "collapse/expand" },
3181
+ { key: "Cmd+\u2190/\u2192", description: "all" }
3182
+ ]
3183
+ }
3184
+ )
3065
3185
  ] }) });
3066
3186
  };
3067
3187
  function getCheckbox(state) {
@@ -3087,12 +3207,12 @@ function getStateColor(state, theme) {
3087
3207
  }
3088
3208
 
3089
3209
  // src/components/timeline/TimelinePane.tsx
3090
- import { useState as useState7, useEffect as useEffect8, useMemo as useMemo2 } from "react";
3091
- import { Box as Box9, Text as Text7, useInput as useInput4 } from "ink";
3210
+ import { useState as useState7, useEffect as useEffect9, useMemo as useMemo2 } from "react";
3211
+ import { Box as Box10, Text as Text9, useInput as useInput5 } from "ink";
3092
3212
 
3093
3213
  // src/components/timeline/TimelineEntry.tsx
3094
- import { Box as Box8, Text as Text6 } from "ink";
3095
- import { jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
3214
+ import { Box as Box9, Text as Text8 } from "ink";
3215
+ import { jsx as jsx14, jsxs as jsxs10 } from "react/jsx-runtime";
3096
3216
  var TimelineEntry = ({
3097
3217
  event,
3098
3218
  isLast,
@@ -3117,32 +3237,39 @@ var TimelineEntry = ({
3117
3237
  const isFilledCircle = ["completed", "delegated", "delayed"].includes(
3118
3238
  event.type
3119
3239
  );
3120
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
3121
- /* @__PURE__ */ jsxs8(Box8, { children: [
3122
- /* @__PURE__ */ jsx12(Box8, { width: 3, justifyContent: "center", children: /* @__PURE__ */ jsx12(Text6, { color, children: isFilledCircle ? "\u25CF" : "\u25CB" }) }),
3123
- /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", flexGrow: 1, children: [
3124
- /* @__PURE__ */ jsx12(Box8, { children: /* @__PURE__ */ jsxs8(Text6, { children: [
3125
- /* @__PURE__ */ jsxs8(Text6, { color, bold: true, children: [
3240
+ return /* @__PURE__ */ jsxs10(Box9, { flexDirection: "column", children: [
3241
+ /* @__PURE__ */ jsxs10(Box9, { children: [
3242
+ /* @__PURE__ */ jsx14(Box9, { width: 3, justifyContent: "center", children: /* @__PURE__ */ jsx14(Text8, { color, children: isFilledCircle ? "\u25CF" : "\u25CB" }) }),
3243
+ /* @__PURE__ */ jsxs10(Box9, { flexDirection: "column", flexGrow: 1, children: [
3244
+ /* @__PURE__ */ jsx14(Box9, { children: /* @__PURE__ */ jsxs10(Text8, { children: [
3245
+ /* @__PURE__ */ jsxs10(Text8, { color, bold: true, children: [
3126
3246
  typeStr,
3127
3247
  ":"
3128
3248
  ] }),
3129
- /* @__PURE__ */ jsxs8(Text6, { color: theme.colors.foreground, children: [
3249
+ /* @__PURE__ */ jsxs10(Text8, { color: theme.colors.foreground, children: [
3130
3250
  " ",
3131
3251
  event.taskTitle
3132
3252
  ] })
3133
3253
  ] }) }),
3134
- /* @__PURE__ */ jsx12(Box8, { children: /* @__PURE__ */ jsx12(Text6, { color: theme.colors.keyboardHint, dimColor: true, children: timeStr }) })
3254
+ /* @__PURE__ */ jsx14(Box9, { children: /* @__PURE__ */ jsx14(Text8, { color: theme.colors.keyboardHint, dimColor: true, children: timeStr }) })
3135
3255
  ] })
3136
3256
  ] }),
3137
- !isLast && /* @__PURE__ */ jsx12(Box8, { children: /* @__PURE__ */ jsx12(Box8, { width: 3, justifyContent: "center", children: /* @__PURE__ */ jsx12(Text6, { color: hasNextSameTask ? color : theme.colors.border, children: "\u2502" }) }) })
3257
+ !isLast && /* @__PURE__ */ jsx14(Box9, { children: /* @__PURE__ */ jsx14(Box9, { width: 3, justifyContent: "center", children: /* @__PURE__ */ jsx14(Text8, { color: hasNextSameTask ? color : theme.colors.border, children: "\u2502" }) }) })
3138
3258
  ] });
3139
3259
  };
3140
3260
 
3141
3261
  // src/components/timeline/TimelinePane.tsx
3142
- import { jsx as jsx13, jsxs as jsxs9 } from "react/jsx-runtime";
3262
+ import { jsx as jsx15, jsxs as jsxs11 } from "react/jsx-runtime";
3143
3263
  var TimelinePane = () => {
3144
3264
  const { theme } = useTheme();
3145
- const { selectedDate, timeline, activePane, isModalOpen, isInputMode } = useApp();
3265
+ const {
3266
+ selectedDate,
3267
+ timeline,
3268
+ setTimeline,
3269
+ activePane,
3270
+ isModalOpen,
3271
+ isInputMode
3272
+ } = useApp();
3146
3273
  const isFocused = activePane === "timeline" && !isModalOpen;
3147
3274
  const [scrollOffset, setScrollOffset] = useState7(0);
3148
3275
  const { height: terminalHeight } = useTerminalSize();
@@ -3172,10 +3299,10 @@ var TimelinePane = () => {
3172
3299
  );
3173
3300
  return taskGroups.flatMap(([, events]) => events);
3174
3301
  }, [dayEvents]);
3175
- useEffect8(() => {
3302
+ useEffect9(() => {
3176
3303
  setScrollOffset(0);
3177
3304
  }, [dateStr]);
3178
- useInput4(
3305
+ useInput5(
3179
3306
  (input, key) => {
3180
3307
  if (!isFocused) return;
3181
3308
  if (input === "j" || key.downArrow) {
@@ -3199,6 +3326,12 @@ var TimelinePane = () => {
3199
3326
  (prev) => Math.max(prev - Math.floor(visibleRows / 2), 0)
3200
3327
  );
3201
3328
  }
3329
+ if (input === "C") {
3330
+ setTimeline({
3331
+ ...timeline,
3332
+ [dateStr]: []
3333
+ });
3334
+ }
3202
3335
  },
3203
3336
  { isActive: isFocused && !isInputMode }
3204
3337
  );
@@ -3208,18 +3341,18 @@ var TimelinePane = () => {
3208
3341
  );
3209
3342
  const canScrollUp = scrollOffset > 0;
3210
3343
  const canScrollDown = scrollOffset + visibleRows < sortedEvents.length;
3211
- return /* @__PURE__ */ jsx13(Pane, { title: "Timeline", isFocused, children: /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", flexGrow: 1, children: [
3212
- sortedEvents.length === 0 ? /* @__PURE__ */ jsxs9(Box9, { marginY: 1, flexDirection: "column", paddingX: 1, children: [
3213
- /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "No activities yet." }),
3214
- /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "Press 's' to start a task." })
3215
- ] }) : /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
3216
- canScrollUp && /* @__PURE__ */ jsx13(Box9, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more above --" }) }),
3217
- /* @__PURE__ */ jsx13(Box9, { flexDirection: "column", children: visibleEvents.map((event, index) => {
3344
+ return /* @__PURE__ */ jsx15(Pane, { title: "Timeline", isFocused, children: /* @__PURE__ */ jsxs11(Box10, { flexDirection: "column", flexGrow: 1, width: "100%", children: [
3345
+ sortedEvents.length === 0 ? /* @__PURE__ */ jsxs11(Box10, { marginY: 1, flexDirection: "column", children: [
3346
+ /* @__PURE__ */ jsx15(Text9, { color: theme.colors.keyboardHint, dimColor: true, children: "No activities yet." }),
3347
+ /* @__PURE__ */ jsx15(Text9, { color: theme.colors.keyboardHint, dimColor: true, children: "Press 's' to start a task." })
3348
+ ] }) : /* @__PURE__ */ jsxs11(Box10, { flexDirection: "column", children: [
3349
+ canScrollUp && /* @__PURE__ */ jsx15(Box10, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx15(Text9, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more above --" }) }),
3350
+ /* @__PURE__ */ jsx15(Box10, { flexDirection: "column", children: visibleEvents.map((event, index) => {
3218
3351
  const globalIndex = scrollOffset + index;
3219
3352
  const isLast = globalIndex === sortedEvents.length - 1;
3220
3353
  const nextEvent = sortedEvents[globalIndex + 1];
3221
3354
  const hasNextSameTask = nextEvent && nextEvent.taskId === event.taskId;
3222
- return /* @__PURE__ */ jsx13(
3355
+ return /* @__PURE__ */ jsx15(
3223
3356
  TimelineEntry,
3224
3357
  {
3225
3358
  event,
@@ -3229,21 +3362,29 @@ var TimelinePane = () => {
3229
3362
  event.id
3230
3363
  );
3231
3364
  }) }),
3232
- canScrollDown && /* @__PURE__ */ jsx13(Box9, { justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more below --" }) })
3365
+ canScrollDown && /* @__PURE__ */ jsx15(Box10, { justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx15(Text9, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more below --" }) })
3233
3366
  ] }),
3234
- /* @__PURE__ */ jsx13(Box9, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text7, { color: theme.colors.keyboardHint, dimColor: true, children: "j/k: scroll" }) })
3367
+ /* @__PURE__ */ jsx15(
3368
+ KeyboardHints,
3369
+ {
3370
+ hints: [
3371
+ { key: "j/k", description: "scroll" },
3372
+ { key: "Shift+C", description: "clear" }
3373
+ ]
3374
+ }
3375
+ )
3235
3376
  ] }) });
3236
3377
  };
3237
3378
 
3238
3379
  // src/components/common/HelpDialog.tsx
3239
- import { Box as Box12, Text as Text8 } from "ink";
3380
+ import { Box as Box13, Text as Text10 } from "ink";
3240
3381
 
3241
3382
  // src/components/common/Modal.tsx
3242
- import { Box as Box11, useStdout as useStdout3 } from "ink";
3383
+ import { Box as Box12, useStdout as useStdout3 } from "ink";
3243
3384
 
3244
3385
  // src/components/common/FullscreenBackground.tsx
3245
- import { Box as Box10, useStdout as useStdout2 } from "ink";
3246
- import { jsx as jsx14 } from "react/jsx-runtime";
3386
+ import { Box as Box11, useStdout as useStdout2 } from "ink";
3387
+ import { jsx as jsx16 } from "react/jsx-runtime";
3247
3388
  var FullscreenBackground = ({
3248
3389
  children,
3249
3390
  backgroundColor
@@ -3251,8 +3392,8 @@ var FullscreenBackground = ({
3251
3392
  const { stdout } = useStdout2();
3252
3393
  const width = stdout?.columns || 100;
3253
3394
  const height = stdout?.rows || 30;
3254
- return /* @__PURE__ */ jsx14(
3255
- Box10,
3395
+ return /* @__PURE__ */ jsx16(
3396
+ Box11,
3256
3397
  {
3257
3398
  flexDirection: "column",
3258
3399
  width,
@@ -3264,18 +3405,18 @@ var FullscreenBackground = ({
3264
3405
  };
3265
3406
 
3266
3407
  // src/components/common/Modal.tsx
3267
- import { jsx as jsx15 } from "react/jsx-runtime";
3408
+ import { jsx as jsx17 } from "react/jsx-runtime";
3268
3409
  var Modal = ({ children }) => {
3269
3410
  const { theme } = useTheme();
3270
3411
  const { stdout } = useStdout3();
3271
3412
  const width = stdout?.columns || 100;
3272
3413
  const height = stdout?.rows || 30;
3273
- return /* @__PURE__ */ jsx15(
3414
+ return /* @__PURE__ */ jsx17(
3274
3415
  FullscreenBackground,
3275
3416
  {
3276
3417
  backgroundColor: theme.colors.modalOverlay || "black",
3277
- children: /* @__PURE__ */ jsx15(
3278
- Box11,
3418
+ children: /* @__PURE__ */ jsx17(
3419
+ Box12,
3279
3420
  {
3280
3421
  flexDirection: "column",
3281
3422
  width,
@@ -3290,7 +3431,7 @@ var Modal = ({ children }) => {
3290
3431
  };
3291
3432
 
3292
3433
  // src/components/common/HelpDialog.tsx
3293
- import { Fragment as Fragment2, jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
3434
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
3294
3435
  var HelpDialog = () => {
3295
3436
  const { theme } = useTheme();
3296
3437
  const shortcuts = [
@@ -3323,8 +3464,8 @@ var HelpDialog = () => {
3323
3464
  { key: "j/k", action: "Scroll timeline" },
3324
3465
  { key: "Shift+C", action: "Clear timeline" }
3325
3466
  ];
3326
- return /* @__PURE__ */ jsx16(Modal, { children: /* @__PURE__ */ jsxs10(
3327
- Box12,
3467
+ return /* @__PURE__ */ jsx18(Modal, { children: /* @__PURE__ */ jsxs12(
3468
+ Box13,
3328
3469
  {
3329
3470
  flexDirection: "column",
3330
3471
  borderStyle: "double",
@@ -3333,22 +3474,21 @@ var HelpDialog = () => {
3333
3474
  paddingY: 1,
3334
3475
  backgroundColor: theme.colors.modalBackground || theme.colors.background,
3335
3476
  children: [
3336
- /* @__PURE__ */ jsx16(Text8, { bold: true, color: theme.colors.calendarHeader, children: "Keyboard Shortcuts" }),
3337
- /* @__PURE__ */ jsx16(Box12, { flexDirection: "column", marginTop: 1, children: shortcuts.map((item, idx) => /* @__PURE__ */ jsx16(Box12, { marginY: 0, children: item.key ? /* @__PURE__ */ jsxs10(Fragment2, { children: [
3338
- /* @__PURE__ */ jsx16(Box12, { width: 20, children: /* @__PURE__ */ jsx16(Text8, { color: theme.colors.timelineEventStarted, children: item.key }) }),
3339
- /* @__PURE__ */ jsx16(Text8, { color: theme.colors.foreground, children: item.action })
3340
- ] }) : /* @__PURE__ */ jsx16(Text8, { color: theme.colors.separator, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) }, idx)) }),
3341
- /* @__PURE__ */ jsx16(Box12, { marginY: 1, children: /* @__PURE__ */ jsx16(Text8, { color: theme.colors.keyboardHint, dimColor: true, children: "Press '?' to close" }) })
3477
+ /* @__PURE__ */ jsx18(Text10, { bold: true, color: theme.colors.calendarHeader, children: "Keyboard Shortcuts" }),
3478
+ /* @__PURE__ */ jsx18(Box13, { flexDirection: "column", marginTop: 1, children: shortcuts.map((item, idx) => /* @__PURE__ */ jsx18(Box13, { marginY: 0, children: item.key ? /* @__PURE__ */ jsxs12(Fragment2, { children: [
3479
+ /* @__PURE__ */ jsx18(Box13, { width: 20, children: /* @__PURE__ */ jsx18(Text10, { color: theme.colors.timelineEventStarted, children: item.key }) }),
3480
+ /* @__PURE__ */ jsx18(Text10, { color: theme.colors.foreground, children: item.action })
3481
+ ] }) : /* @__PURE__ */ jsx18(Text10, { color: theme.colors.separator, children: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500" }) }, idx)) }),
3482
+ /* @__PURE__ */ jsx18(Box13, { marginY: 1, children: /* @__PURE__ */ jsx18(Text10, { color: theme.colors.keyboardHint, dimColor: true, children: "Press '?' to close" }) })
3342
3483
  ]
3343
3484
  }
3344
3485
  ) });
3345
3486
  };
3346
3487
 
3347
3488
  // src/components/common/ThemeDialog.tsx
3348
- import { useState as useState8, useMemo as useMemo3, useEffect as useEffect9 } from "react";
3349
- import { Box as Box13, Text as Text9, useInput as useInput5 } from "ink";
3350
- import TextInput2 from "ink-text-input";
3351
- import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
3489
+ import { useState as useState8, useMemo as useMemo3, useEffect as useEffect10 } from "react";
3490
+ import { Box as Box14, Text as Text11, useInput as useInput6 } from "ink";
3491
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
3352
3492
  var ThemeDialog = () => {
3353
3493
  const { theme, setTheme, themeName } = useTheme();
3354
3494
  const { setShowThemeDialog } = useApp();
@@ -3388,21 +3528,19 @@ var ThemeDialog = () => {
3388
3528
  return idx >= 0 ? idx : 0;
3389
3529
  }, [themeItems, themeName]);
3390
3530
  const [selectedIndex, setSelectedIndex] = useState8(initialIndex);
3391
- useEffect9(() => {
3531
+ useEffect10(() => {
3392
3532
  setSelectedIndex(0);
3393
3533
  }, [searchQuery]);
3394
- useInput5(
3534
+ useInput6(
3395
3535
  (input, key) => {
3396
3536
  if (key.escape) {
3397
3537
  setShowThemeDialog(false);
3398
3538
  return;
3399
3539
  }
3540
+ if ((input === "\r" || input === "\n") && !key.return) {
3541
+ return;
3542
+ }
3400
3543
  if (focusMode === "search") {
3401
- if (key.return && themeItems.length > 0) {
3402
- setTheme(themeItems[0].value);
3403
- setShowThemeDialog(false);
3404
- return;
3405
- }
3406
3544
  if (key.downArrow && themeItems.length > 0) {
3407
3545
  setFocusMode("list");
3408
3546
  setSelectedIndex(0);
@@ -3436,8 +3574,8 @@ var ThemeDialog = () => {
3436
3574
  const formatThemeName = (name) => {
3437
3575
  return name.split("-").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3438
3576
  };
3439
- return /* @__PURE__ */ jsx17(Modal, { children: /* @__PURE__ */ jsxs11(
3440
- Box13,
3577
+ return /* @__PURE__ */ jsx19(Modal, { children: /* @__PURE__ */ jsxs13(
3578
+ Box14,
3441
3579
  {
3442
3580
  flexDirection: "column",
3443
3581
  borderStyle: "double",
@@ -3447,38 +3585,46 @@ var ThemeDialog = () => {
3447
3585
  width: 44,
3448
3586
  backgroundColor: theme.colors.modalBackground || theme.colors.background,
3449
3587
  children: [
3450
- /* @__PURE__ */ jsx17(Text9, { bold: true, color: theme.colors.calendarHeader, underline: true, children: "Select Theme" }),
3451
- /* @__PURE__ */ jsxs11(Box13, { marginTop: 1, flexDirection: "row", alignItems: "center", children: [
3452
- /* @__PURE__ */ jsxs11(Text9, { color: theme.colors.foreground, dimColor: true, children: [
3588
+ /* @__PURE__ */ jsx19(Text11, { bold: true, color: theme.colors.calendarHeader, underline: true, children: "Select Theme" }),
3589
+ /* @__PURE__ */ jsxs13(Box14, { marginTop: 1, flexDirection: "row", alignItems: "center", children: [
3590
+ /* @__PURE__ */ jsxs13(Text11, { color: theme.colors.foreground, dimColor: true, children: [
3453
3591
  "Search:",
3454
3592
  " "
3455
3593
  ] }),
3456
- /* @__PURE__ */ jsx17(Text9, { color: theme.colors.foreground, children: /* @__PURE__ */ jsx17(
3457
- TextInput2,
3594
+ /* @__PURE__ */ jsx19(
3595
+ ControlledTextInput,
3458
3596
  {
3459
3597
  value: searchQuery,
3460
3598
  onChange: setSearchQuery,
3599
+ onSubmit: () => {
3600
+ if (themeItems.length > 0) {
3601
+ setTheme(themeItems[0].value);
3602
+ setShowThemeDialog(false);
3603
+ }
3604
+ },
3461
3605
  focus: focusMode === "search",
3462
- placeholder: "Type to filter..."
3606
+ placeholder: "Type to filter...",
3607
+ placeholderColor: theme.colors.foreground,
3608
+ color: theme.colors.foreground
3463
3609
  }
3464
- ) })
3610
+ )
3465
3611
  ] }),
3466
- /* @__PURE__ */ jsx17(Box13, { flexDirection: "column", marginTop: 1, children: allThemes.map((item, idx) => {
3612
+ /* @__PURE__ */ jsx19(Box14, { flexDirection: "column", marginTop: 1, children: allThemes.map((item, idx) => {
3467
3613
  if (item.type === "separator") {
3468
- return /* @__PURE__ */ jsx17(
3469
- Box13,
3614
+ return /* @__PURE__ */ jsx19(
3615
+ Box14,
3470
3616
  {
3471
3617
  marginTop: idx > 0 ? 1 : 0,
3472
3618
  marginBottom: 0,
3473
- children: /* @__PURE__ */ jsx17(Text9, { bold: true, color: theme.colors.calendarHeader, dimColor: true, children: item.value })
3619
+ children: /* @__PURE__ */ jsx19(Text11, { bold: true, color: theme.colors.calendarHeader, dimColor: true, children: item.value })
3474
3620
  },
3475
3621
  `sep-${idx}`
3476
3622
  );
3477
3623
  }
3478
3624
  const isSelected = item.value === selectedThemeName;
3479
3625
  const isCurrent = item.value === themeName;
3480
- return /* @__PURE__ */ jsx17(Box13, { paddingLeft: 1, children: /* @__PURE__ */ jsxs11(
3481
- Text9,
3626
+ return /* @__PURE__ */ jsx19(Box14, { paddingLeft: 1, children: /* @__PURE__ */ jsxs13(
3627
+ Text11,
3482
3628
  {
3483
3629
  color: isSelected ? theme.colors.focusIndicator : theme.colors.foreground,
3484
3630
  bold: isSelected,
@@ -3490,16 +3636,16 @@ var ThemeDialog = () => {
3490
3636
  }
3491
3637
  ) }, item.value);
3492
3638
  }) }),
3493
- /* @__PURE__ */ jsx17(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text9, { color: theme.colors.keyboardHint, dimColor: true, children: focusMode === "search" ? "Type to search \u2022 \u2193 to navigate list \u2022 Esc to close" : "\u2191/\u2193 or k/j to navigate \u2022 Enter to select \u2022 Esc to close" }) })
3639
+ /* @__PURE__ */ jsx19(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text11, { color: theme.colors.keyboardHint, dimColor: true, children: focusMode === "search" ? "Type to search \u2022 \u2193 to navigate list \u2022 Esc to close" : "\u2191/\u2193 or k/j to navigate \u2022 Enter to select \u2022 Esc to close" }) })
3494
3640
  ]
3495
3641
  }
3496
3642
  ) });
3497
3643
  };
3498
3644
 
3499
3645
  // src/components/common/ClearTimelineDialog.tsx
3500
- import { Box as Box14, Text as Text10, useInput as useInput6 } from "ink";
3646
+ import { Box as Box15, Text as Text12, useInput as useInput7 } from "ink";
3501
3647
  import { format as format2 } from "date-fns";
3502
- import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
3648
+ import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
3503
3649
  var ClearTimelineDialog = () => {
3504
3650
  const { theme } = useTheme();
3505
3651
  const {
@@ -3519,15 +3665,15 @@ var ClearTimelineDialog = () => {
3519
3665
  const handleCancel = () => {
3520
3666
  setShowClearTimelineDialog(false);
3521
3667
  };
3522
- useInput6((input, key) => {
3668
+ useInput7((input, key) => {
3523
3669
  if (input.toLowerCase() === "y" || key.return) {
3524
3670
  handleConfirm();
3525
3671
  } else if (input.toLowerCase() === "n" || key.escape) {
3526
3672
  handleCancel();
3527
3673
  }
3528
3674
  });
3529
- return /* @__PURE__ */ jsx18(Modal, { children: /* @__PURE__ */ jsxs12(
3530
- Box14,
3675
+ return /* @__PURE__ */ jsx20(Modal, { children: /* @__PURE__ */ jsxs14(
3676
+ Box15,
3531
3677
  {
3532
3678
  flexDirection: "column",
3533
3679
  borderStyle: "double",
@@ -3536,39 +3682,39 @@ var ClearTimelineDialog = () => {
3536
3682
  paddingY: 2,
3537
3683
  backgroundColor: theme.colors.modalBackground || theme.colors.background,
3538
3684
  children: [
3539
- /* @__PURE__ */ jsx18(Box14, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx18(Text10, { bold: true, color: theme.colors.taskStateDelayed, children: "Clear Timeline" }) }),
3540
- /* @__PURE__ */ jsxs12(Box14, { flexDirection: "column", marginY: 1, children: [
3541
- /* @__PURE__ */ jsx18(Text10, { color: theme.colors.foreground, children: "You are about to clear the timeline for" }),
3542
- /* @__PURE__ */ jsx18(Box14, { justifyContent: "center", marginY: 1, children: /* @__PURE__ */ jsx18(Text10, { bold: true, color: theme.colors.calendarHeader, children: formattedDate }) }),
3543
- eventCount > 0 ? /* @__PURE__ */ jsxs12(Text10, { color: theme.colors.keyboardHint, children: [
3685
+ /* @__PURE__ */ jsx20(Box15, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx20(Text12, { bold: true, color: theme.colors.taskStateDelayed, children: "Clear Timeline" }) }),
3686
+ /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", marginY: 1, children: [
3687
+ /* @__PURE__ */ jsx20(Text12, { color: theme.colors.foreground, children: "You are about to clear the timeline for" }),
3688
+ /* @__PURE__ */ jsx20(Box15, { justifyContent: "center", marginY: 1, children: /* @__PURE__ */ jsx20(Text12, { bold: true, color: theme.colors.calendarHeader, children: formattedDate }) }),
3689
+ eventCount > 0 ? /* @__PURE__ */ jsxs14(Text12, { color: theme.colors.keyboardHint, children: [
3544
3690
  "This will remove ",
3545
3691
  eventCount,
3546
3692
  " event",
3547
3693
  eventCount !== 1 ? "s" : "",
3548
3694
  " from the timeline."
3549
- ] }) : /* @__PURE__ */ jsx18(Text10, { color: theme.colors.keyboardHint, dimColor: true, children: "The timeline is already empty." })
3695
+ ] }) : /* @__PURE__ */ jsx20(Text12, { color: theme.colors.keyboardHint, dimColor: true, children: "The timeline is already empty." })
3550
3696
  ] }),
3551
- /* @__PURE__ */ jsxs12(Box14, { marginTop: 2, justifyContent: "center", children: [
3552
- /* @__PURE__ */ jsx18(Text10, { color: theme.colors.foreground, children: "Are you sure? " }),
3553
- /* @__PURE__ */ jsx18(Text10, { color: theme.colors.taskStateCompleted, bold: true, children: "[Y]es" }),
3554
- /* @__PURE__ */ jsx18(Text10, { color: theme.colors.foreground, children: " / " }),
3555
- /* @__PURE__ */ jsx18(Text10, { color: theme.colors.taskStateDelayed, bold: true, children: "[N]o" })
3697
+ /* @__PURE__ */ jsxs14(Box15, { marginTop: 2, justifyContent: "center", children: [
3698
+ /* @__PURE__ */ jsx20(Text12, { color: theme.colors.foreground, children: "Are you sure? " }),
3699
+ /* @__PURE__ */ jsx20(Text12, { color: theme.colors.taskStateCompleted, bold: true, children: "[Y]es" }),
3700
+ /* @__PURE__ */ jsx20(Text12, { color: theme.colors.foreground, children: " / " }),
3701
+ /* @__PURE__ */ jsx20(Text12, { color: theme.colors.taskStateDelayed, bold: true, children: "[N]o" })
3556
3702
  ] }),
3557
- /* @__PURE__ */ jsx18(Box14, { marginTop: 2, justifyContent: "center", children: /* @__PURE__ */ jsx18(Text10, { color: theme.colors.keyboardHint, dimColor: true, children: "Press Y to confirm, N or Esc to cancel" }) })
3703
+ /* @__PURE__ */ jsx20(Box15, { marginTop: 2, justifyContent: "center", children: /* @__PURE__ */ jsx20(Text12, { color: theme.colors.keyboardHint, dimColor: true, children: "Press Y to confirm, N or Esc to cancel" }) })
3558
3704
  ]
3559
3705
  }
3560
3706
  ) });
3561
3707
  };
3562
3708
 
3563
3709
  // src/components/overview/OverviewScreen.tsx
3564
- import React8, { useMemo as useMemo4 } from "react";
3565
- import { Box as Box15, Text as Text11, useInput as useInput7 } from "ink";
3710
+ import React9, { useMemo as useMemo4 } from "react";
3711
+ import { Box as Box16, Text as Text13, useInput as useInput8 } from "ink";
3566
3712
  import { startOfMonth as startOfMonth2, endOfMonth as endOfMonth2, eachDayOfInterval as eachDayOfInterval2 } from "date-fns";
3567
- import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
3713
+ import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
3568
3714
  var OverviewScreen = () => {
3569
3715
  const { theme } = useTheme();
3570
3716
  const { tasks, overviewMonth, setOverviewMonth, setShowOverview } = useApp();
3571
- const [scrollOffset, setScrollOffset] = React8.useState(0);
3717
+ const [scrollOffset, setScrollOffset] = React9.useState(0);
3572
3718
  const { height: terminalHeight } = useTerminalSize();
3573
3719
  const visibleRows = useMemo4(() => {
3574
3720
  return Math.max(2, Math.floor((terminalHeight - 9) / 3));
@@ -3604,10 +3750,10 @@ var OverviewScreen = () => {
3604
3750
  setOverviewMonth({ ...overviewMonth, month: newMonth });
3605
3751
  }
3606
3752
  };
3607
- React8.useEffect(() => {
3753
+ React9.useEffect(() => {
3608
3754
  setScrollOffset(0);
3609
3755
  }, [overviewMonth]);
3610
- useInput7((input, key) => {
3756
+ useInput8((input, key) => {
3611
3757
  if (key.escape) {
3612
3758
  setShowOverview(false);
3613
3759
  return;
@@ -3643,21 +3789,21 @@ var OverviewScreen = () => {
3643
3789
  );
3644
3790
  const canScrollUp = scrollOffset > 0;
3645
3791
  const canScrollDown = scrollOffset + visibleRows < rows;
3646
- return /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", padding: 1, width: "100%", height: "100%", children: [
3647
- /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", marginBottom: 1, children: [
3648
- /* @__PURE__ */ jsx19(Text11, { bold: true, color: theme.colors.focusIndicator, children: "Overview" }),
3649
- /* @__PURE__ */ jsx19(Text11, { color: theme.colors.foreground, children: monthName })
3792
+ return /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", padding: 1, width: "100%", height: "100%", children: [
3793
+ /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", marginBottom: 1, children: [
3794
+ /* @__PURE__ */ jsx21(Text13, { bold: true, color: theme.colors.focusIndicator, children: "Overview" }),
3795
+ /* @__PURE__ */ jsx21(Text13, { color: theme.colors.foreground, children: monthName })
3650
3796
  ] }),
3651
- /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", flexGrow: 1, children: [
3652
- canScrollUp && /* @__PURE__ */ jsx19(Box15, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx19(Text11, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more above --" }) }),
3797
+ /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", flexGrow: 1, children: [
3798
+ canScrollUp && /* @__PURE__ */ jsx21(Box16, { justifyContent: "center", marginBottom: 1, children: /* @__PURE__ */ jsx21(Text13, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more above --" }) }),
3653
3799
  visibleRowData.map((_, index) => {
3654
3800
  const rowIndex = scrollOffset + index;
3655
- return /* @__PURE__ */ jsx19(Box15, { flexDirection: "row", marginBottom: 1, children: Array.from({ length: columns }).map((_2, colIndex) => {
3801
+ return /* @__PURE__ */ jsx21(Box16, { flexDirection: "row", marginBottom: 1, children: Array.from({ length: columns }).map((_2, colIndex) => {
3656
3802
  const dateIndex = rowIndex * columns + colIndex;
3657
3803
  const date = monthDates[dateIndex];
3658
3804
  if (!date) {
3659
- return /* @__PURE__ */ jsx19(
3660
- Box15,
3805
+ return /* @__PURE__ */ jsx21(
3806
+ Box16,
3661
3807
  {
3662
3808
  flexDirection: "column",
3663
3809
  flexGrow: 1,
@@ -3677,17 +3823,17 @@ var OverviewScreen = () => {
3677
3823
  }
3678
3824
  };
3679
3825
  traverse(dayTasks, 0);
3680
- return /* @__PURE__ */ jsxs13(
3681
- Box15,
3826
+ return /* @__PURE__ */ jsxs15(
3827
+ Box16,
3682
3828
  {
3683
3829
  flexDirection: "column",
3684
3830
  flexGrow: 1,
3685
3831
  flexBasis: 0,
3686
3832
  marginRight: colIndex === columns - 1 ? 0 : 2,
3687
3833
  children: [
3688
- /* @__PURE__ */ jsx19(Text11, { bold: true, color: theme.colors.calendarSelected, children: formatDate(date, "do MMM") }),
3689
- /* @__PURE__ */ jsxs13(Box15, { flexDirection: "column", children: [
3690
- flatTasksWithDepth.length === 0 ? /* @__PURE__ */ jsx19(Text11, { dimColor: true, color: theme.colors.keyboardHint, children: "No tasks" }) : flatTasksWithDepth.slice(0, 10).map(({ task, depth }) => /* @__PURE__ */ jsx19(
3834
+ /* @__PURE__ */ jsx21(Text13, { bold: true, color: theme.colors.calendarSelected, children: formatDate(date, "do MMM") }),
3835
+ /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", children: [
3836
+ flatTasksWithDepth.length === 0 ? /* @__PURE__ */ jsx21(Text13, { dimColor: true, color: theme.colors.keyboardHint, children: "No tasks" }) : flatTasksWithDepth.slice(0, 10).map(({ task, depth }) => /* @__PURE__ */ jsx21(
3691
3837
  TaskItem,
3692
3838
  {
3693
3839
  task,
@@ -3696,7 +3842,7 @@ var OverviewScreen = () => {
3696
3842
  },
3697
3843
  task.id
3698
3844
  )),
3699
- flatTasksWithDepth.length > 10 && /* @__PURE__ */ jsxs13(Text11, { dimColor: true, color: theme.colors.keyboardHint, children: [
3845
+ flatTasksWithDepth.length > 10 && /* @__PURE__ */ jsxs15(Text13, { dimColor: true, color: theme.colors.keyboardHint, children: [
3700
3846
  "+",
3701
3847
  flatTasksWithDepth.length - 10,
3702
3848
  " more..."
@@ -3708,22 +3854,22 @@ var OverviewScreen = () => {
3708
3854
  );
3709
3855
  }) }, rowIndex);
3710
3856
  }),
3711
- canScrollDown && /* @__PURE__ */ jsx19(Box15, { justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx19(Text11, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more below --" }) })
3857
+ canScrollDown && /* @__PURE__ */ jsx21(Box16, { justifyContent: "center", marginTop: 1, children: /* @__PURE__ */ jsx21(Text13, { color: theme.colors.keyboardHint, dimColor: true, children: "-- more below --" }) })
3712
3858
  ] }),
3713
- /* @__PURE__ */ jsx19(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx19(Text11, { color: theme.colors.keyboardHint, dimColor: true, children: "n/p or \u2190/\u2192: month | j/k or \u2193/\u2191: scroll | Esc: close | Shift+;: toggle" }) })
3859
+ /* @__PURE__ */ jsx21(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text13, { color: theme.colors.keyboardHint, dimColor: true, children: "n/p or \u2190/\u2192: month | j/k or \u2193/\u2191: scroll | Esc: close | Shift+;: toggle" }) })
3714
3860
  ] });
3715
3861
  };
3716
3862
  var TaskItem = ({ task, theme, depth }) => {
3717
3863
  const checkbox = getCheckbox2(task.state);
3718
3864
  const color = getStateColor2(task.state, theme);
3719
- return /* @__PURE__ */ jsxs13(Box15, { children: [
3720
- /* @__PURE__ */ jsxs13(Text11, { color, children: [
3865
+ return /* @__PURE__ */ jsxs15(Box16, { children: [
3866
+ /* @__PURE__ */ jsxs15(Text13, { color, children: [
3721
3867
  checkbox,
3722
3868
  " "
3723
3869
  ] }),
3724
- depth > 0 && /* @__PURE__ */ jsx19(Text11, { children: " ".repeat(depth) }),
3725
- /* @__PURE__ */ jsx19(
3726
- Text11,
3870
+ depth > 0 && /* @__PURE__ */ jsx21(Text13, { children: " ".repeat(depth) }),
3871
+ /* @__PURE__ */ jsx21(
3872
+ Text13,
3727
3873
  {
3728
3874
  color,
3729
3875
  strikethrough: task.state === "completed",
@@ -3756,7 +3902,7 @@ function getStateColor2(state, theme) {
3756
3902
  }
3757
3903
 
3758
3904
  // src/App.tsx
3759
- import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
3905
+ import { jsx as jsx22, jsxs as jsxs16 } from "react/jsx-runtime";
3760
3906
  var AppContent = () => {
3761
3907
  const {
3762
3908
  showHelp,
@@ -3770,26 +3916,26 @@ var AppContent = () => {
3770
3916
  useKeyboardNav();
3771
3917
  const { width, height } = useTerminalSize();
3772
3918
  if (showThemeDialog) {
3773
- return /* @__PURE__ */ jsx20(ThemeDialog, {});
3919
+ return /* @__PURE__ */ jsx22(ThemeDialog, {});
3774
3920
  }
3775
3921
  if (showHelp) {
3776
- return /* @__PURE__ */ jsx20(HelpDialog, {});
3922
+ return /* @__PURE__ */ jsx22(HelpDialog, {});
3777
3923
  }
3778
3924
  if (showClearTimelineDialog) {
3779
- return /* @__PURE__ */ jsx20(ClearTimelineDialog, {});
3925
+ return /* @__PURE__ */ jsx22(ClearTimelineDialog, {});
3780
3926
  }
3781
- return /* @__PURE__ */ jsx20(FullscreenBackground, { backgroundColor: theme.colors.background || "black", children: /* @__PURE__ */ jsxs14(Box16, { flexDirection: "column", width, height, padding: 1, backgroundColor: theme.colors.background, children: [
3782
- showOverview ? /* @__PURE__ */ jsx20(OverviewScreen, {}) : /* @__PURE__ */ jsx20(
3927
+ return /* @__PURE__ */ jsx22(FullscreenBackground, { backgroundColor: theme.colors.background || "black", children: /* @__PURE__ */ jsxs16(Box17, { flexDirection: "column", width, height, padding: 1, backgroundColor: theme.colors.background, children: [
3928
+ showOverview ? /* @__PURE__ */ jsx22(OverviewScreen, {}) : /* @__PURE__ */ jsx22(
3783
3929
  ThreeColumnLayout,
3784
3930
  {
3785
- leftPane: /* @__PURE__ */ jsx20(CalendarPane, {}),
3786
- centerPane: /* @__PURE__ */ jsx20(TasksPane, {}),
3787
- rightPane: /* @__PURE__ */ jsx20(TimelinePane, {}),
3931
+ leftPane: /* @__PURE__ */ jsx22(CalendarPane, {}),
3932
+ centerPane: /* @__PURE__ */ jsx22(TasksPane, {}),
3933
+ rightPane: /* @__PURE__ */ jsx22(TimelinePane, {}),
3788
3934
  activePane,
3789
3935
  height: height - 2
3790
3936
  }
3791
3937
  ),
3792
- exitConfirmation && /* @__PURE__ */ jsx20(Box16, { width: "100%", justifyContent: "center", paddingY: 1, children: /* @__PURE__ */ jsxs14(Text12, { backgroundColor: "red", color: "white", bold: true, children: [
3938
+ exitConfirmation && /* @__PURE__ */ jsx22(Box17, { width: "100%", justifyContent: "center", paddingY: 1, children: /* @__PURE__ */ jsxs16(Text14, { backgroundColor: "red", color: "white", bold: true, children: [
3793
3939
  " ",
3794
3940
  "Press Ctrl+C again to exit Epoch",
3795
3941
  " "
@@ -3797,12 +3943,12 @@ var AppContent = () => {
3797
3943
  ] }) });
3798
3944
  };
3799
3945
  var App = () => {
3800
- return /* @__PURE__ */ jsx20(StorageProvider, { children: /* @__PURE__ */ jsx20(ThemeProvider, { initialTheme: "dark", children: /* @__PURE__ */ jsx20(AppProvider, { children: /* @__PURE__ */ jsx20(AppContent, {}) }) }) });
3946
+ return /* @__PURE__ */ jsx22(StorageProvider, { children: /* @__PURE__ */ jsx22(ThemeProvider, { initialTheme: "dark", children: /* @__PURE__ */ jsx22(AppProvider, { children: /* @__PURE__ */ jsx22(AppContent, {}) }) }) });
3801
3947
  };
3802
3948
  var App_default = App;
3803
3949
 
3804
3950
  // src/index.tsx
3805
- import { jsx as jsx21 } from "react/jsx-runtime";
3951
+ import { jsx as jsx23 } from "react/jsx-runtime";
3806
3952
  console.clear();
3807
- var app = render(/* @__PURE__ */ jsx21(App_default, {}), { exitOnCtrlC: false });
3953
+ var app = render(/* @__PURE__ */ jsx23(App_default, {}), { exitOnCtrlC: false });
3808
3954
  global.__inkApp = app;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "epoch-tui",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "A TUI app for daily task logging and time tracking",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",