@kaban-board/tui 0.2.6 → 0.2.9

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 +389 -132
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -120,7 +120,7 @@ async function refreshBoard(state) {
120
120
  }
121
121
  state.columns = await boardService.getColumns();
122
122
  state.taskSelects = new Map;
123
- const tasks = await taskService.listTasks();
123
+ const tasks = state.archiveViewMode ? (await taskService.listTasks({ includeArchived: true })).filter((t2) => t2.archived) : await taskService.listTasks();
124
124
  const mainContainer = new BoxRenderable2(renderer, {
125
125
  id: "main",
126
126
  width: "100%",
@@ -139,9 +139,10 @@ async function refreshBoard(state) {
139
139
  justifyContent: "center",
140
140
  alignItems: "center"
141
141
  });
142
+ const modeIndicator = state.archiveViewMode ? " [ARCHIVE]" : "";
142
143
  const headerText = new TextRenderable2(renderer, {
143
144
  id: "header-text",
144
- content: t`${fg(COLORS.warning)(LOGO)} ${fg(COLORS.accent)(state.boardName)}`
145
+ content: t`${fg(COLORS.warning)(LOGO)} ${fg(COLORS.accent)(state.boardName)}${fg(COLORS.textMuted)(modeIndicator)}`
145
146
  });
146
147
  header.add(headerText);
147
148
  mainContainer.add(header);
@@ -231,9 +232,11 @@ async function refreshBoard(state) {
231
232
  justifyContent: "center",
232
233
  alignItems: "center"
233
234
  });
235
+ const hasTasksInView = tasks.length > 0;
236
+ const footerContent = state.archiveViewMode ? hasTasksInView ? "[r]estore [Tab]Back [?] [q]" : "[Tab]Back [?] [q]" : "[a]dd [m]ove [u] [d]el [x]arch [Tab]Arch [?] [q]";
234
237
  const footerText = new TextRenderable2(renderer, {
235
238
  id: "footer-text",
236
- content: "[a]dd [m]ove [u]ser [d]el [?]Help [q]uit",
239
+ content: footerContent,
237
240
  fg: COLORS.textMuted
238
241
  });
239
242
  footer.add(footerText);
@@ -468,13 +471,8 @@ function showAddTaskModal(state, onTaskCreated) {
468
471
  state.activeModal = "addTask";
469
472
  input.on(InputRenderableEvents.ENTER, doCreate);
470
473
  }
471
- // src/components/modals/assign-task.ts
472
- import {
473
- BoxRenderable as BoxRenderable6,
474
- InputRenderable as InputRenderable2,
475
- InputRenderableEvents as InputRenderableEvents2,
476
- TextRenderable as TextRenderable5
477
- } from "@opentui/core";
474
+ // src/components/modals/archive-task.ts
475
+ import { BoxRenderable as BoxRenderable6, TextRenderable as TextRenderable5 } from "@opentui/core";
478
476
 
479
477
  // src/lib/types.ts
480
478
  function getSelectedTaskId(state) {
@@ -489,7 +487,97 @@ function getSelectedTaskId(state) {
489
487
  return typeof value === "string" ? value : null;
490
488
  }
491
489
 
490
+ // src/components/modals/archive-task.ts
491
+ async function showArchiveTaskModal(state, onArchived) {
492
+ const { renderer } = state;
493
+ const taskId = getSelectedTaskId(state);
494
+ if (!taskId) {
495
+ return;
496
+ }
497
+ const task = await state.taskService.getTask(taskId);
498
+ if (!task) {
499
+ return;
500
+ }
501
+ if (task.archived) {
502
+ return;
503
+ }
504
+ state.selectedTask = task;
505
+ const { overlay, dialog } = createModalOverlay(renderer, {
506
+ id: "archive-task-dialog",
507
+ width: 45,
508
+ height: 10,
509
+ borderColor: COLORS.warning
510
+ });
511
+ const titleRow = new BoxRenderable6(renderer, {
512
+ id: "archive-title-row",
513
+ width: "100%",
514
+ height: 1,
515
+ justifyContent: "center"
516
+ });
517
+ const title = new TextRenderable5(renderer, {
518
+ id: "archive-title",
519
+ content: "Archive Task?",
520
+ fg: COLORS.warning
521
+ });
522
+ titleRow.add(title);
523
+ const spacer1 = new BoxRenderable6(renderer, { id: "archive-spacer1", width: "100%", height: 1 });
524
+ const taskRow = new BoxRenderable6(renderer, {
525
+ id: "archive-task-row",
526
+ width: "100%",
527
+ height: 1
528
+ });
529
+ const taskText = new TextRenderable5(renderer, {
530
+ id: "archive-task-text",
531
+ content: task.title.slice(0, 40),
532
+ fg: COLORS.text
533
+ });
534
+ taskRow.add(taskText);
535
+ const infoRow = new BoxRenderable6(renderer, {
536
+ id: "archive-info-row",
537
+ width: "100%",
538
+ height: 1
539
+ });
540
+ const info = new TextRenderable5(renderer, {
541
+ id: "archive-info",
542
+ content: "Task will be moved to archive.",
543
+ fg: COLORS.textMuted
544
+ });
545
+ infoRow.add(info);
546
+ const spacer2 = new BoxRenderable6(renderer, { id: "archive-spacer2", width: "100%", height: 2 });
547
+ const hintRow = new BoxRenderable6(renderer, {
548
+ id: "archive-hint-row",
549
+ width: "100%",
550
+ height: 1,
551
+ justifyContent: "center"
552
+ });
553
+ const hint = new TextRenderable5(renderer, {
554
+ id: "archive-hint",
555
+ content: "[y] Archive [n/Esc] Cancel",
556
+ fg: COLORS.textMuted
557
+ });
558
+ hintRow.add(hint);
559
+ dialog.add(titleRow);
560
+ dialog.add(spacer1);
561
+ dialog.add(taskRow);
562
+ dialog.add(infoRow);
563
+ dialog.add(spacer2);
564
+ dialog.add(hintRow);
565
+ renderer.root.add(overlay);
566
+ state.modalOverlay = overlay;
567
+ state.activeModal = "archiveTask";
568
+ state.onModalConfirm = async () => {
569
+ await state.taskService.archiveTasks({ taskIds: [taskId] });
570
+ closeModal(state);
571
+ await onArchived();
572
+ };
573
+ }
492
574
  // src/components/modals/assign-task.ts
575
+ import {
576
+ BoxRenderable as BoxRenderable7,
577
+ InputRenderable as InputRenderable2,
578
+ InputRenderableEvents as InputRenderableEvents2,
579
+ TextRenderable as TextRenderable6
580
+ } from "@opentui/core";
493
581
  async function showAssignTaskModal(state, onAssigned) {
494
582
  const { renderer } = state;
495
583
  const taskId = getSelectedTaskId(state);
@@ -505,36 +593,36 @@ async function showAssignTaskModal(state, onAssigned) {
505
593
  width: 45,
506
594
  height: 12
507
595
  });
508
- const titleRow = new BoxRenderable6(renderer, {
596
+ const titleRow = new BoxRenderable7(renderer, {
509
597
  id: "assign-title-row",
510
598
  width: "100%",
511
599
  height: 1
512
600
  });
513
- const title = new TextRenderable5(renderer, {
601
+ const title = new TextRenderable6(renderer, {
514
602
  id: "assign-title",
515
603
  content: "Assign Task",
516
604
  fg: COLORS.accent
517
605
  });
518
606
  titleRow.add(title);
519
- const taskRow = new BoxRenderable6(renderer, {
607
+ const taskRow = new BoxRenderable7(renderer, {
520
608
  id: "assign-task-row",
521
609
  width: "100%",
522
610
  height: 1
523
611
  });
524
- const taskText = new TextRenderable5(renderer, {
612
+ const taskText = new TextRenderable6(renderer, {
525
613
  id: "assign-task-text",
526
614
  content: task.title.slice(0, 40),
527
615
  fg: COLORS.textMuted
528
616
  });
529
617
  taskRow.add(taskText);
530
- const spacer1 = new BoxRenderable6(renderer, { id: "assign-spacer1", width: "100%", height: 1 });
531
- const labelRow = new BoxRenderable6(renderer, {
618
+ const spacer1 = new BoxRenderable7(renderer, { id: "assign-spacer1", width: "100%", height: 1 });
619
+ const labelRow = new BoxRenderable7(renderer, {
532
620
  id: "assign-label-row",
533
621
  width: "100%",
534
622
  height: 1
535
623
  });
536
624
  const currentAssignee = task.assignedTo ?? "(unassigned)";
537
- const label = new TextRenderable5(renderer, {
625
+ const label = new TextRenderable6(renderer, {
538
626
  id: "assign-label",
539
627
  content: `Current: ${currentAssignee}`,
540
628
  fg: COLORS.text
@@ -551,7 +639,7 @@ async function showAssignTaskModal(state, onAssigned) {
551
639
  focusedBackgroundColor: COLORS.inputBg,
552
640
  cursorColor: COLORS.cursor
553
641
  });
554
- const spacer2 = new BoxRenderable6(renderer, { id: "assign-spacer2", width: "100%", height: 1 });
642
+ const spacer2 = new BoxRenderable7(renderer, { id: "assign-spacer2", width: "100%", height: 1 });
555
643
  const doAssign = async () => {
556
644
  const assignee = input.value.trim();
557
645
  await state.taskService.updateTask(taskId, {
@@ -586,7 +674,7 @@ async function showAssignTaskModal(state, onAssigned) {
586
674
  input.on(InputRenderableEvents2.ENTER, doAssign);
587
675
  }
588
676
  // src/components/modals/delete-task.ts
589
- import { BoxRenderable as BoxRenderable7, TextRenderable as TextRenderable6 } from "@opentui/core";
677
+ import { BoxRenderable as BoxRenderable8, TextRenderable as TextRenderable7 } from "@opentui/core";
590
678
  async function showDeleteTaskModal(state, onDeleted) {
591
679
  const { renderer } = state;
592
680
  const taskId = getSelectedTaskId(state);
@@ -604,49 +692,49 @@ async function showDeleteTaskModal(state, onDeleted) {
604
692
  height: 10,
605
693
  borderColor: COLORS.danger
606
694
  });
607
- const titleRow = new BoxRenderable7(renderer, {
695
+ const titleRow = new BoxRenderable8(renderer, {
608
696
  id: "delete-title-row",
609
697
  width: "100%",
610
698
  height: 1,
611
699
  justifyContent: "center"
612
700
  });
613
- const title = new TextRenderable6(renderer, {
701
+ const title = new TextRenderable7(renderer, {
614
702
  id: "delete-title",
615
703
  content: "Delete Task?",
616
704
  fg: COLORS.danger
617
705
  });
618
706
  titleRow.add(title);
619
- const spacer1 = new BoxRenderable7(renderer, { id: "delete-spacer1", width: "100%", height: 1 });
620
- const taskRow = new BoxRenderable7(renderer, {
707
+ const spacer1 = new BoxRenderable8(renderer, { id: "delete-spacer1", width: "100%", height: 1 });
708
+ const taskRow = new BoxRenderable8(renderer, {
621
709
  id: "delete-task-row",
622
710
  width: "100%",
623
711
  height: 1
624
712
  });
625
- const taskText = new TextRenderable6(renderer, {
713
+ const taskText = new TextRenderable7(renderer, {
626
714
  id: "delete-task-text",
627
715
  content: task.title.slice(0, 40),
628
716
  fg: COLORS.text
629
717
  });
630
718
  taskRow.add(taskText);
631
- const warningRow = new BoxRenderable7(renderer, {
719
+ const warningRow = new BoxRenderable8(renderer, {
632
720
  id: "delete-warning-row",
633
721
  width: "100%",
634
722
  height: 1
635
723
  });
636
- const warning = new TextRenderable6(renderer, {
724
+ const warning = new TextRenderable7(renderer, {
637
725
  id: "delete-warning",
638
726
  content: "This action cannot be undone.",
639
727
  fg: COLORS.warning
640
728
  });
641
729
  warningRow.add(warning);
642
- const spacer2 = new BoxRenderable7(renderer, { id: "delete-spacer2", width: "100%", height: 2 });
643
- const hintRow = new BoxRenderable7(renderer, {
730
+ const spacer2 = new BoxRenderable8(renderer, { id: "delete-spacer2", width: "100%", height: 2 });
731
+ const hintRow = new BoxRenderable8(renderer, {
644
732
  id: "delete-hint-row",
645
733
  width: "100%",
646
734
  height: 1,
647
735
  justifyContent: "center"
648
736
  });
649
- const hint = new TextRenderable6(renderer, {
737
+ const hint = new TextRenderable7(renderer, {
650
738
  id: "delete-hint",
651
739
  content: "[y] Delete [n/Esc] Cancel",
652
740
  fg: COLORS.textMuted
@@ -667,12 +755,97 @@ async function showDeleteTaskModal(state, onDeleted) {
667
755
  await onDeleted();
668
756
  };
669
757
  }
758
+ // src/components/modals/restore-task.ts
759
+ import { BoxRenderable as BoxRenderable9, TextRenderable as TextRenderable8 } from "@opentui/core";
760
+ async function showRestoreTaskModal(state, onRestored) {
761
+ const { renderer } = state;
762
+ const taskId = getSelectedTaskId(state);
763
+ if (!taskId) {
764
+ return;
765
+ }
766
+ const task = await state.taskService.getTask(taskId);
767
+ if (!task) {
768
+ return;
769
+ }
770
+ if (!task.archived) {
771
+ return;
772
+ }
773
+ state.selectedTask = task;
774
+ const { overlay, dialog } = createModalOverlay(renderer, {
775
+ id: "restore-task-dialog",
776
+ width: 45,
777
+ height: 10,
778
+ borderColor: COLORS.success
779
+ });
780
+ const titleRow = new BoxRenderable9(renderer, {
781
+ id: "restore-title-row",
782
+ width: "100%",
783
+ height: 1,
784
+ justifyContent: "center"
785
+ });
786
+ const title = new TextRenderable8(renderer, {
787
+ id: "restore-title",
788
+ content: "Restore Task?",
789
+ fg: COLORS.success
790
+ });
791
+ titleRow.add(title);
792
+ const spacer1 = new BoxRenderable9(renderer, { id: "restore-spacer1", width: "100%", height: 1 });
793
+ const taskRow = new BoxRenderable9(renderer, {
794
+ id: "restore-task-row",
795
+ width: "100%",
796
+ height: 1
797
+ });
798
+ const taskText = new TextRenderable8(renderer, {
799
+ id: "restore-task-text",
800
+ content: task.title.slice(0, 40),
801
+ fg: COLORS.text
802
+ });
803
+ taskRow.add(taskText);
804
+ const infoRow = new BoxRenderable9(renderer, {
805
+ id: "restore-info-row",
806
+ width: "100%",
807
+ height: 1
808
+ });
809
+ const info = new TextRenderable8(renderer, {
810
+ id: "restore-info",
811
+ content: "Task will be restored to its original column.",
812
+ fg: COLORS.textMuted
813
+ });
814
+ infoRow.add(info);
815
+ const spacer2 = new BoxRenderable9(renderer, { id: "restore-spacer2", width: "100%", height: 2 });
816
+ const hintRow = new BoxRenderable9(renderer, {
817
+ id: "restore-hint-row",
818
+ width: "100%",
819
+ height: 1,
820
+ justifyContent: "center"
821
+ });
822
+ const hint = new TextRenderable8(renderer, {
823
+ id: "restore-hint",
824
+ content: "[y] Restore [n/Esc] Cancel",
825
+ fg: COLORS.textMuted
826
+ });
827
+ hintRow.add(hint);
828
+ dialog.add(titleRow);
829
+ dialog.add(spacer1);
830
+ dialog.add(taskRow);
831
+ dialog.add(infoRow);
832
+ dialog.add(spacer2);
833
+ dialog.add(hintRow);
834
+ renderer.root.add(overlay);
835
+ state.modalOverlay = overlay;
836
+ state.activeModal = "restoreTask";
837
+ state.onModalConfirm = async () => {
838
+ await state.taskService.restoreTask(taskId);
839
+ closeModal(state);
840
+ await onRestored();
841
+ };
842
+ }
670
843
  // src/components/modals/edit-task.ts
671
844
  import {
672
- BoxRenderable as BoxRenderable8,
845
+ BoxRenderable as BoxRenderable10,
673
846
  InputRenderable as InputRenderable3,
674
847
  InputRenderableEvents as InputRenderableEvents3,
675
- TextRenderable as TextRenderable7
848
+ TextRenderable as TextRenderable9
676
849
  } from "@opentui/core";
677
850
  var DIALOG_WIDTH = 60;
678
851
  var DESC_INPUT_HEIGHT = 6;
@@ -693,28 +866,28 @@ async function showEditTaskModal(state, callbacks) {
693
866
  width: DIALOG_WIDTH,
694
867
  height: dialogHeight
695
868
  });
696
- const headerRow = new BoxRenderable8(renderer, {
869
+ const headerRow = new BoxRenderable10(renderer, {
697
870
  id: "edit-header-row",
698
871
  width: "100%",
699
872
  height: 1
700
873
  });
701
- const headerText = new TextRenderable7(renderer, {
874
+ const headerText = new TextRenderable9(renderer, {
702
875
  id: "edit-header-text",
703
876
  content: `Edit Task: ${truncate(task.title, DIALOG_WIDTH - 20)}`,
704
877
  fg: COLORS.accent
705
878
  });
706
879
  headerRow.add(headerText);
707
- const spacer1 = new BoxRenderable8(renderer, {
880
+ const spacer1 = new BoxRenderable10(renderer, {
708
881
  id: "edit-spacer1",
709
882
  width: "100%",
710
883
  height: 1
711
884
  });
712
- const titleLabelRow = new BoxRenderable8(renderer, {
885
+ const titleLabelRow = new BoxRenderable10(renderer, {
713
886
  id: "edit-title-label-row",
714
887
  width: "100%",
715
888
  height: 1
716
889
  });
717
- const titleLabel = new TextRenderable7(renderer, {
890
+ const titleLabel = new TextRenderable9(renderer, {
718
891
  id: "edit-title-label",
719
892
  content: "Title",
720
893
  fg: COLORS.textMuted
@@ -732,17 +905,17 @@ async function showEditTaskModal(state, callbacks) {
732
905
  cursorColor: COLORS.cursor
733
906
  });
734
907
  titleInput.value = task.title;
735
- const spacer2 = new BoxRenderable8(renderer, {
908
+ const spacer2 = new BoxRenderable10(renderer, {
736
909
  id: "edit-spacer2",
737
910
  width: "100%",
738
911
  height: 1
739
912
  });
740
- const descLabelRow = new BoxRenderable8(renderer, {
913
+ const descLabelRow = new BoxRenderable10(renderer, {
741
914
  id: "edit-desc-label-row",
742
915
  width: "100%",
743
916
  height: 1
744
917
  });
745
- const descLabel = new TextRenderable7(renderer, {
918
+ const descLabel = new TextRenderable9(renderer, {
746
919
  id: "edit-desc-label",
747
920
  content: "Description",
748
921
  fg: COLORS.textMuted
@@ -760,7 +933,7 @@ async function showEditTaskModal(state, callbacks) {
760
933
  cursorColor: COLORS.cursor
761
934
  });
762
935
  descInput.value = task.description ?? "";
763
- const spacer3 = new BoxRenderable8(renderer, {
936
+ const spacer3 = new BoxRenderable10(renderer, {
764
937
  id: "edit-spacer3",
765
938
  width: "100%",
766
939
  height: 1
@@ -791,13 +964,13 @@ async function showEditTaskModal(state, callbacks) {
791
964
  { label: "Save", action: doSave, color: COLORS.success },
792
965
  { label: "Cancel", action: doCancel }
793
966
  ]);
794
- const hintRow = new BoxRenderable8(renderer, {
967
+ const hintRow = new BoxRenderable10(renderer, {
795
968
  id: "edit-hint-row",
796
969
  width: "100%",
797
970
  height: 1,
798
971
  justifyContent: "center"
799
972
  });
800
- const hint = new TextRenderable7(renderer, {
973
+ const hint = new TextRenderable9(renderer, {
801
974
  id: "edit-hint",
802
975
  content: "[Tab] Next [Enter] Save [Esc] Cancel",
803
976
  fg: COLORS.textDim
@@ -861,7 +1034,7 @@ function cancelEditTask(state) {
861
1034
  state.editTaskRuntime.doCancel();
862
1035
  }
863
1036
  // src/components/modals/help.ts
864
- import { BoxRenderable as BoxRenderable9, TextRenderable as TextRenderable8 } from "@opentui/core";
1037
+ import { BoxRenderable as BoxRenderable11, TextRenderable as TextRenderable10 } from "@opentui/core";
865
1038
  var SHORTCUTS = [
866
1039
  ["<-/-> h/l", "Switch column"],
867
1040
  ["up/dn j/k", "Navigate tasks"],
@@ -870,6 +1043,9 @@ var SHORTCUTS = [
870
1043
  ["m", "Move task (change status)"],
871
1044
  ["u", "Assign user to task"],
872
1045
  ["d", "Delete task"],
1046
+ ["x", "Archive task"],
1047
+ ["r", "Restore task (archive view)"],
1048
+ ["Tab", "Toggle archive view"],
873
1049
  ["?", "Show/hide help"],
874
1050
  ["q", "Quit"]
875
1051
  ];
@@ -878,36 +1054,36 @@ function showHelpModal(state) {
878
1054
  const { overlay, dialog } = createModalOverlay(renderer, {
879
1055
  id: "help-dialog",
880
1056
  width: 45,
881
- height: 17,
1057
+ height: 20,
882
1058
  padding: 2
883
1059
  });
884
- const titleRow = new BoxRenderable9(renderer, {
1060
+ const titleRow = new BoxRenderable11(renderer, {
885
1061
  id: "help-title-row",
886
1062
  width: "100%",
887
1063
  height: 1
888
1064
  });
889
- const title = new TextRenderable8(renderer, {
1065
+ const title = new TextRenderable10(renderer, {
890
1066
  id: "help-title",
891
1067
  content: "Keyboard Shortcuts",
892
1068
  fg: COLORS.accent
893
1069
  });
894
1070
  titleRow.add(title);
895
- const spacer = new BoxRenderable9(renderer, { id: "help-spacer", width: "100%", height: 1 });
1071
+ const spacer = new BoxRenderable11(renderer, { id: "help-spacer", width: "100%", height: 1 });
896
1072
  dialog.add(titleRow);
897
1073
  dialog.add(spacer);
898
1074
  for (const [key, desc] of SHORTCUTS) {
899
- const row = new BoxRenderable9(renderer, {
1075
+ const row = new BoxRenderable11(renderer, {
900
1076
  id: `help-row-${key}`,
901
1077
  width: "100%",
902
1078
  height: 1,
903
1079
  flexDirection: "row"
904
1080
  });
905
- const keyText = new TextRenderable8(renderer, {
1081
+ const keyText = new TextRenderable10(renderer, {
906
1082
  id: `help-key-${key}`,
907
1083
  content: key.padEnd(12),
908
1084
  fg: COLORS.accentBright
909
1085
  });
910
- const descText = new TextRenderable8(renderer, {
1086
+ const descText = new TextRenderable10(renderer, {
911
1087
  id: `help-desc-${key}`,
912
1088
  content: desc,
913
1089
  fg: COLORS.text
@@ -916,17 +1092,17 @@ function showHelpModal(state) {
916
1092
  row.add(descText);
917
1093
  dialog.add(row);
918
1094
  }
919
- const hintSpacer = new BoxRenderable9(renderer, {
1095
+ const hintSpacer = new BoxRenderable11(renderer, {
920
1096
  id: "help-hint-spacer",
921
1097
  width: "100%",
922
1098
  height: 1
923
1099
  });
924
- const hintRow = new BoxRenderable9(renderer, {
1100
+ const hintRow = new BoxRenderable11(renderer, {
925
1101
  id: "help-hint-row",
926
1102
  width: "100%",
927
1103
  height: 1
928
1104
  });
929
- const hint = new TextRenderable8(renderer, {
1105
+ const hint = new TextRenderable10(renderer, {
930
1106
  id: "help-hint",
931
1107
  content: "[Esc] or any key to close",
932
1108
  fg: COLORS.textDim
@@ -940,10 +1116,10 @@ function showHelpModal(state) {
940
1116
  }
941
1117
  // src/components/modals/move-task.ts
942
1118
  import {
943
- BoxRenderable as BoxRenderable10,
1119
+ BoxRenderable as BoxRenderable12,
944
1120
  SelectRenderable as SelectRenderable2,
945
1121
  SelectRenderableEvents,
946
- TextRenderable as TextRenderable9
1122
+ TextRenderable as TextRenderable11
947
1123
  } from "@opentui/core";
948
1124
  async function showMoveTaskModal(state, onMoved) {
949
1125
  const { renderer, columns } = state;
@@ -966,35 +1142,35 @@ async function showMoveTaskModal(state, onMoved) {
966
1142
  width: 40,
967
1143
  height: dialogHeight
968
1144
  });
969
- const titleRow = new BoxRenderable10(renderer, {
1145
+ const titleRow = new BoxRenderable12(renderer, {
970
1146
  id: "move-title-row",
971
1147
  width: "100%",
972
1148
  height: 1
973
1149
  });
974
- const title = new TextRenderable9(renderer, {
1150
+ const title = new TextRenderable11(renderer, {
975
1151
  id: "move-title",
976
1152
  content: "Move Task",
977
1153
  fg: COLORS.accent
978
1154
  });
979
1155
  titleRow.add(title);
980
- const taskRow = new BoxRenderable10(renderer, {
1156
+ const taskRow = new BoxRenderable12(renderer, {
981
1157
  id: "move-task-row",
982
1158
  width: "100%",
983
1159
  height: 1
984
1160
  });
985
- const taskText = new TextRenderable9(renderer, {
1161
+ const taskText = new TextRenderable11(renderer, {
986
1162
  id: "move-task-text",
987
1163
  content: task.title.slice(0, 35),
988
1164
  fg: COLORS.textMuted
989
1165
  });
990
1166
  taskRow.add(taskText);
991
- const spacer1 = new BoxRenderable10(renderer, { id: "move-spacer1", width: "100%", height: 1 });
992
- const labelRow = new BoxRenderable10(renderer, {
1167
+ const spacer1 = new BoxRenderable12(renderer, { id: "move-spacer1", width: "100%", height: 1 });
1168
+ const labelRow = new BoxRenderable12(renderer, {
993
1169
  id: "move-label-row",
994
1170
  width: "100%",
995
1171
  height: 1
996
1172
  });
997
- const label = new TextRenderable9(renderer, {
1173
+ const label = new TextRenderable11(renderer, {
998
1174
  id: "move-label",
999
1175
  content: "Select column:",
1000
1176
  fg: COLORS.text
@@ -1015,13 +1191,13 @@ async function showMoveTaskModal(state, onMoved) {
1015
1191
  selectedBackgroundColor: COLORS.inputBg,
1016
1192
  selectedTextColor: COLORS.accentBright
1017
1193
  });
1018
- const spacer2 = new BoxRenderable10(renderer, { id: "move-spacer2", width: "100%", height: 1 });
1019
- const hintRow = new BoxRenderable10(renderer, {
1194
+ const spacer2 = new BoxRenderable12(renderer, { id: "move-spacer2", width: "100%", height: 1 });
1195
+ const hintRow = new BoxRenderable12(renderer, {
1020
1196
  id: "move-hint-row",
1021
1197
  width: "100%",
1022
1198
  height: 1
1023
1199
  });
1024
- const hint = new TextRenderable9(renderer, {
1200
+ const hint = new TextRenderable11(renderer, {
1025
1201
  id: "move-hint",
1026
1202
  content: "[Enter] Move [Esc] Cancel",
1027
1203
  fg: COLORS.textDim
@@ -1049,14 +1225,14 @@ async function showMoveTaskModal(state, onMoved) {
1049
1225
  }
1050
1226
  // src/components/modals/onboarding.ts
1051
1227
  import {
1052
- BoxRenderable as BoxRenderable11,
1228
+ BoxRenderable as BoxRenderable13,
1053
1229
  InputRenderable as InputRenderable4,
1054
1230
  InputRenderableEvents as InputRenderableEvents4,
1055
- TextRenderable as TextRenderable10
1231
+ TextRenderable as TextRenderable12
1056
1232
  } from "@opentui/core";
1057
1233
  async function showOnboarding(renderer) {
1058
1234
  return new Promise((resolvePromise) => {
1059
- const container = new BoxRenderable11(renderer, {
1235
+ const container = new BoxRenderable13(renderer, {
1060
1236
  id: "onboarding",
1061
1237
  width: "100%",
1062
1238
  height: "100%",
@@ -1065,7 +1241,7 @@ async function showOnboarding(renderer) {
1065
1241
  alignItems: "center",
1066
1242
  backgroundColor: COLORS.bg
1067
1243
  });
1068
- const card = new BoxRenderable11(renderer, {
1244
+ const card = new BoxRenderable13(renderer, {
1069
1245
  id: "card",
1070
1246
  width: 52,
1071
1247
  height: 13,
@@ -1079,35 +1255,35 @@ async function showOnboarding(renderer) {
1079
1255
  paddingLeft: 2,
1080
1256
  paddingRight: 2
1081
1257
  });
1082
- const titleRow = new BoxRenderable11(renderer, {
1258
+ const titleRow = new BoxRenderable13(renderer, {
1083
1259
  id: "title-row",
1084
1260
  width: "100%",
1085
1261
  height: 1
1086
1262
  });
1087
- const title = new TextRenderable10(renderer, {
1263
+ const title = new TextRenderable12(renderer, {
1088
1264
  id: "title",
1089
1265
  content: "Welcome to Kaban",
1090
1266
  fg: COLORS.accent
1091
1267
  });
1092
1268
  titleRow.add(title);
1093
- const subtitleRow = new BoxRenderable11(renderer, {
1269
+ const subtitleRow = new BoxRenderable13(renderer, {
1094
1270
  id: "subtitle-row",
1095
1271
  width: "100%",
1096
1272
  height: 1
1097
1273
  });
1098
- const subtitle = new TextRenderable10(renderer, {
1274
+ const subtitle = new TextRenderable12(renderer, {
1099
1275
  id: "subtitle",
1100
1276
  content: "No board found. Let's create one!",
1101
1277
  fg: COLORS.textMuted
1102
1278
  });
1103
1279
  subtitleRow.add(subtitle);
1104
- const spacer1 = new BoxRenderable11(renderer, { id: "spacer1", width: "100%", height: 1 });
1105
- const labelRow = new BoxRenderable11(renderer, {
1280
+ const spacer1 = new BoxRenderable13(renderer, { id: "spacer1", width: "100%", height: 1 });
1281
+ const labelRow = new BoxRenderable13(renderer, {
1106
1282
  id: "label-row",
1107
1283
  width: "100%",
1108
1284
  height: 1
1109
1285
  });
1110
- const label = new TextRenderable10(renderer, {
1286
+ const label = new TextRenderable12(renderer, {
1111
1287
  id: "label",
1112
1288
  content: "Board name:",
1113
1289
  fg: COLORS.text
@@ -1124,15 +1300,16 @@ async function showOnboarding(renderer) {
1124
1300
  focusedBackgroundColor: COLORS.inputBg,
1125
1301
  cursorColor: COLORS.cursor
1126
1302
  });
1127
- const spacer2 = new BoxRenderable11(renderer, { id: "spacer2", width: "100%", height: 1 });
1303
+ const spacer2 = new BoxRenderable13(renderer, { id: "spacer2", width: "100%", height: 1 });
1304
+ const keyEmitter = renderer.keyInput;
1128
1305
  const doCreate = () => {
1129
- renderer.keyInput.off("keypress", keyHandler);
1306
+ keyEmitter.off("keypress", keyHandler);
1130
1307
  const boardName = input.value.trim() || "Kaban Board";
1131
1308
  container.destroy();
1132
1309
  resolvePromise(boardName);
1133
1310
  };
1134
1311
  const doQuit = () => {
1135
- renderer.keyInput.off("keypress", keyHandler);
1312
+ keyEmitter.off("keypress", keyHandler);
1136
1313
  renderer.destroy();
1137
1314
  process.exit(0);
1138
1315
  };
@@ -1175,11 +1352,11 @@ async function showOnboarding(renderer) {
1175
1352
  const keyHandler = (key) => {
1176
1353
  keyBindings[key.name]?.();
1177
1354
  };
1178
- renderer.keyInput.on("keypress", keyHandler);
1355
+ keyEmitter.on("keypress", keyHandler);
1179
1356
  });
1180
1357
  }
1181
1358
  // src/components/modals/quit.ts
1182
- import { BoxRenderable as BoxRenderable12, TextRenderable as TextRenderable11 } from "@opentui/core";
1359
+ import { BoxRenderable as BoxRenderable14, TextRenderable as TextRenderable13 } from "@opentui/core";
1183
1360
  function showQuitModal(state) {
1184
1361
  const { renderer } = state;
1185
1362
  const { overlay, dialog } = createModalOverlay(renderer, {
@@ -1188,26 +1365,26 @@ function showQuitModal(state) {
1188
1365
  height: 8,
1189
1366
  borderColor: COLORS.danger
1190
1367
  });
1191
- const titleRow = new BoxRenderable12(renderer, {
1368
+ const titleRow = new BoxRenderable14(renderer, {
1192
1369
  id: "quit-title-row",
1193
1370
  width: "100%",
1194
1371
  height: 1,
1195
1372
  justifyContent: "center"
1196
1373
  });
1197
- const title = new TextRenderable11(renderer, {
1374
+ const title = new TextRenderable13(renderer, {
1198
1375
  id: "quit-title",
1199
1376
  content: "Quit Kaban?",
1200
1377
  fg: COLORS.danger
1201
1378
  });
1202
1379
  titleRow.add(title);
1203
- const spacer = new BoxRenderable12(renderer, { id: "quit-spacer", width: "100%", height: 2 });
1204
- const hintRow = new BoxRenderable12(renderer, {
1380
+ const spacer = new BoxRenderable14(renderer, { id: "quit-spacer", width: "100%", height: 2 });
1381
+ const hintRow = new BoxRenderable14(renderer, {
1205
1382
  id: "quit-hint-row",
1206
1383
  width: "100%",
1207
1384
  height: 1,
1208
1385
  justifyContent: "center"
1209
1386
  });
1210
- const hint = new TextRenderable11(renderer, {
1387
+ const hint = new TextRenderable13(renderer, {
1211
1388
  id: "quit-hint",
1212
1389
  content: "[y] Yes [n/Esc] No",
1213
1390
  fg: COLORS.textMuted
@@ -1221,7 +1398,7 @@ function showQuitModal(state) {
1221
1398
  state.activeModal = "quit";
1222
1399
  }
1223
1400
  // src/components/modals/view-task.ts
1224
- import { BoxRenderable as BoxRenderable13, TextRenderable as TextRenderable12 } from "@opentui/core";
1401
+ import { BoxRenderable as BoxRenderable15, TextRenderable as TextRenderable14 } from "@opentui/core";
1225
1402
  var DIALOG_WIDTH2 = 60;
1226
1403
  var DESC_VISIBLE_LINES = 4;
1227
1404
  var LABEL_WIDTH = 12;
@@ -1272,43 +1449,43 @@ async function showViewTaskModal(state, actions, taskIdOverride) {
1272
1449
  width: DIALOG_WIDTH2 - 4,
1273
1450
  id: "view-header"
1274
1451
  });
1275
- const spacerHeader = new BoxRenderable13(renderer, {
1452
+ const spacerHeader = new BoxRenderable15(renderer, {
1276
1453
  id: "view-spacer-header",
1277
1454
  width: "100%",
1278
1455
  height: 1
1279
1456
  });
1280
- const titleRow = new BoxRenderable13(renderer, {
1457
+ const titleRow = new BoxRenderable15(renderer, {
1281
1458
  id: "view-title-row",
1282
1459
  width: "100%",
1283
1460
  height: 1,
1284
1461
  flexDirection: "row",
1285
1462
  justifyContent: "space-between"
1286
1463
  });
1287
- const taskTitle = new TextRenderable12(renderer, {
1464
+ const taskTitle = new TextRenderable14(renderer, {
1288
1465
  id: "view-task-title",
1289
1466
  content: truncate(task.title, DIALOG_WIDTH2 - 14),
1290
1467
  fg: COLORS.text
1291
1468
  });
1292
- const editHint = new TextRenderable12(renderer, {
1469
+ const editHint = new TextRenderable14(renderer, {
1293
1470
  id: "view-edit-hint",
1294
1471
  content: "[e]dit",
1295
1472
  fg: COLORS.textDim
1296
1473
  });
1297
1474
  titleRow.add(taskTitle);
1298
1475
  titleRow.add(editHint);
1299
- const idRow = new BoxRenderable13(renderer, {
1476
+ const idRow = new BoxRenderable15(renderer, {
1300
1477
  id: "view-id-row",
1301
1478
  width: "100%",
1302
1479
  height: 1,
1303
1480
  flexDirection: "row",
1304
1481
  justifyContent: "space-between"
1305
1482
  });
1306
- const idValue = new TextRenderable12(renderer, {
1483
+ const idValue = new TextRenderable14(renderer, {
1307
1484
  id: "view-id-value",
1308
1485
  content: truncateMiddle(task.id, DIALOG_WIDTH2 - 14),
1309
1486
  fg: COLORS.textDim
1310
1487
  });
1311
- const copyHint = new TextRenderable12(renderer, {
1488
+ const copyHint = new TextRenderable14(renderer, {
1312
1489
  id: "view-copy-hint",
1313
1490
  content: "[c]opy",
1314
1491
  fg: COLORS.textDim
@@ -1320,23 +1497,23 @@ async function showViewTaskModal(state, actions, taskIdOverride) {
1320
1497
  width: DIALOG_WIDTH2 - 4,
1321
1498
  id: "view-status"
1322
1499
  });
1323
- const columnRow = new BoxRenderable13(renderer, {
1500
+ const columnRow = new BoxRenderable15(renderer, {
1324
1501
  id: "view-column-row",
1325
1502
  width: "100%",
1326
1503
  height: 1,
1327
1504
  flexDirection: "row"
1328
1505
  });
1329
- const columnLabel = new TextRenderable12(renderer, {
1506
+ const columnLabel = new TextRenderable14(renderer, {
1330
1507
  id: "view-column-label",
1331
1508
  content: padLabel("Column"),
1332
1509
  fg: COLORS.textMuted
1333
1510
  });
1334
- const columnBullet = new TextRenderable12(renderer, {
1511
+ const columnBullet = new TextRenderable14(renderer, {
1335
1512
  id: "view-column-bullet",
1336
1513
  content: "\u25CF ",
1337
1514
  fg: statusColor
1338
1515
  });
1339
- const columnValue = new TextRenderable12(renderer, {
1516
+ const columnValue = new TextRenderable14(renderer, {
1340
1517
  id: "view-column-value",
1341
1518
  content: columnName,
1342
1519
  fg: COLORS.text
@@ -1344,54 +1521,54 @@ async function showViewTaskModal(state, actions, taskIdOverride) {
1344
1521
  columnRow.add(columnLabel);
1345
1522
  columnRow.add(columnBullet);
1346
1523
  columnRow.add(columnValue);
1347
- const assigneeRow = new BoxRenderable13(renderer, {
1524
+ const assigneeRow = new BoxRenderable15(renderer, {
1348
1525
  id: "view-assignee-row",
1349
1526
  width: "100%",
1350
1527
  height: 1,
1351
1528
  flexDirection: "row"
1352
1529
  });
1353
- const assigneeLabel = new TextRenderable12(renderer, {
1530
+ const assigneeLabel = new TextRenderable14(renderer, {
1354
1531
  id: "view-assignee-label",
1355
1532
  content: padLabel("Assignee"),
1356
1533
  fg: COLORS.textMuted
1357
1534
  });
1358
- const assigneeValue = new TextRenderable12(renderer, {
1535
+ const assigneeValue = new TextRenderable14(renderer, {
1359
1536
  id: "view-assignee-value",
1360
1537
  content: task.assignedTo ?? "\u2014 unassigned",
1361
1538
  fg: task.assignedTo ? COLORS.success : COLORS.textDim
1362
1539
  });
1363
1540
  assigneeRow.add(assigneeLabel);
1364
1541
  assigneeRow.add(assigneeValue);
1365
- const creatorRow = new BoxRenderable13(renderer, {
1542
+ const creatorRow = new BoxRenderable15(renderer, {
1366
1543
  id: "view-creator-row",
1367
1544
  width: "100%",
1368
1545
  height: 1,
1369
1546
  flexDirection: "row"
1370
1547
  });
1371
- const creatorLabel = new TextRenderable12(renderer, {
1548
+ const creatorLabel = new TextRenderable14(renderer, {
1372
1549
  id: "view-creator-label",
1373
1550
  content: padLabel("Creator"),
1374
1551
  fg: COLORS.textMuted
1375
1552
  });
1376
- const creatorValue = new TextRenderable12(renderer, {
1553
+ const creatorValue = new TextRenderable14(renderer, {
1377
1554
  id: "view-creator-value",
1378
1555
  content: task.createdBy,
1379
1556
  fg: COLORS.text
1380
1557
  });
1381
1558
  creatorRow.add(creatorLabel);
1382
1559
  creatorRow.add(creatorValue);
1383
- const labelsRow = new BoxRenderable13(renderer, {
1560
+ const labelsRow = new BoxRenderable15(renderer, {
1384
1561
  id: "view-labels-row",
1385
1562
  width: "100%",
1386
1563
  height: 1,
1387
1564
  flexDirection: "row"
1388
1565
  });
1389
- const labelsLabel = new TextRenderable12(renderer, {
1566
+ const labelsLabel = new TextRenderable14(renderer, {
1390
1567
  id: "view-labels-label",
1391
1568
  content: padLabel("Labels"),
1392
1569
  fg: COLORS.textMuted
1393
1570
  });
1394
- const labelsValue = new TextRenderable12(renderer, {
1571
+ const labelsValue = new TextRenderable14(renderer, {
1395
1572
  id: "view-labels-value",
1396
1573
  content: "\u2014 none",
1397
1574
  fg: COLORS.textDim
@@ -1403,49 +1580,49 @@ async function showViewTaskModal(state, actions, taskIdOverride) {
1403
1580
  width: DIALOG_WIDTH2 - 4,
1404
1581
  id: "view-timeline"
1405
1582
  });
1406
- const createdRow = new BoxRenderable13(renderer, {
1583
+ const createdRow = new BoxRenderable15(renderer, {
1407
1584
  id: "view-created-row",
1408
1585
  width: "100%",
1409
1586
  height: 1,
1410
1587
  flexDirection: "row"
1411
1588
  });
1412
- const createdLabel = new TextRenderable12(renderer, {
1589
+ const createdLabel = new TextRenderable14(renderer, {
1413
1590
  id: "view-created-label",
1414
1591
  content: padLabel("Created"),
1415
1592
  fg: COLORS.textMuted
1416
1593
  });
1417
- const createdValue = new TextRenderable12(renderer, {
1594
+ const createdValue = new TextRenderable14(renderer, {
1418
1595
  id: "view-created-value",
1419
1596
  content: formatDate(task.createdAt),
1420
1597
  fg: COLORS.textDim
1421
1598
  });
1422
1599
  createdRow.add(createdLabel);
1423
1600
  createdRow.add(createdValue);
1424
- const updatedRow = new BoxRenderable13(renderer, {
1601
+ const updatedRow = new BoxRenderable15(renderer, {
1425
1602
  id: "view-updated-row",
1426
1603
  width: "100%",
1427
1604
  height: 1,
1428
1605
  flexDirection: "row",
1429
1606
  justifyContent: "space-between"
1430
1607
  });
1431
- const updatedLeft = new BoxRenderable13(renderer, {
1608
+ const updatedLeft = new BoxRenderable15(renderer, {
1432
1609
  id: "view-updated-left",
1433
1610
  height: 1,
1434
1611
  flexDirection: "row"
1435
1612
  });
1436
- const updatedLabel = new TextRenderable12(renderer, {
1613
+ const updatedLabel = new TextRenderable14(renderer, {
1437
1614
  id: "view-updated-label",
1438
1615
  content: padLabel("Updated"),
1439
1616
  fg: COLORS.textMuted
1440
1617
  });
1441
- const updatedValue = new TextRenderable12(renderer, {
1618
+ const updatedValue = new TextRenderable14(renderer, {
1442
1619
  id: "view-updated-value",
1443
1620
  content: formatDate(task.updatedAt),
1444
1621
  fg: COLORS.textDim
1445
1622
  });
1446
1623
  updatedLeft.add(updatedLabel);
1447
1624
  updatedLeft.add(updatedValue);
1448
- const relativeTime = new TextRenderable12(renderer, {
1625
+ const relativeTime = new TextRenderable14(renderer, {
1449
1626
  id: "view-relative-time",
1450
1627
  content: `(${formatRelativeTime(task.updatedAt)})`,
1451
1628
  fg: COLORS.textDim
@@ -1457,7 +1634,7 @@ async function showViewTaskModal(state, actions, taskIdOverride) {
1457
1634
  width: DIALOG_WIDTH2 - 4,
1458
1635
  id: "view-desc"
1459
1636
  });
1460
- const descContainer = new BoxRenderable13(renderer, {
1637
+ const descContainer = new BoxRenderable15(renderer, {
1461
1638
  id: "view-desc-container",
1462
1639
  width: "100%",
1463
1640
  height: DESC_VISIBLE_LINES,
@@ -1465,7 +1642,7 @@ async function showViewTaskModal(state, actions, taskIdOverride) {
1465
1642
  });
1466
1643
  const descLineRenderables = [];
1467
1644
  for (let i = 0;i < DESC_VISIBLE_LINES; i++) {
1468
- const line = new TextRenderable12(renderer, {
1645
+ const line = new TextRenderable14(renderer, {
1469
1646
  id: `view-desc-line-${i}`,
1470
1647
  content: " ",
1471
1648
  fg: COLORS.text
@@ -1501,55 +1678,61 @@ async function showViewTaskModal(state, actions, taskIdOverride) {
1501
1678
  }
1502
1679
  }
1503
1680
  updateDescriptionContent(0);
1504
- const footerDivider = new BoxRenderable13(renderer, {
1681
+ const footerDivider = new BoxRenderable15(renderer, {
1505
1682
  id: "view-footer-divider",
1506
1683
  width: "100%",
1507
1684
  height: 1
1508
1685
  });
1509
- const footerLine = new TextRenderable12(renderer, {
1686
+ const footerLine = new TextRenderable14(renderer, {
1510
1687
  id: "view-footer-line",
1511
1688
  content: "\u2500".repeat(DIALOG_WIDTH2 - 4),
1512
1689
  fg: COLORS.border
1513
1690
  });
1514
1691
  footerDivider.add(footerLine);
1515
- const actionsRow = new BoxRenderable13(renderer, {
1692
+ const actionsRow = new BoxRenderable15(renderer, {
1516
1693
  id: "view-actions-row",
1517
1694
  width: "100%",
1518
1695
  height: 1,
1519
1696
  flexDirection: "row",
1520
1697
  justifyContent: "space-between"
1521
1698
  });
1522
- const actionsLeft = new BoxRenderable13(renderer, {
1699
+ const actionsLeft = new BoxRenderable15(renderer, {
1523
1700
  id: "view-actions-left",
1524
1701
  height: 1,
1525
1702
  flexDirection: "row",
1526
1703
  gap: 2
1527
1704
  });
1528
- const moveAction = new TextRenderable12(renderer, {
1705
+ const moveAction = new TextRenderable14(renderer, {
1529
1706
  id: "view-action-move",
1530
1707
  content: "[m] Move",
1531
1708
  fg: COLORS.textMuted
1532
1709
  });
1533
- const assignAction = new TextRenderable12(renderer, {
1710
+ const assignAction = new TextRenderable14(renderer, {
1534
1711
  id: "view-action-assign",
1535
1712
  content: "[u] Assign",
1536
1713
  fg: COLORS.textMuted
1537
1714
  });
1538
- const editAction = new TextRenderable12(renderer, {
1715
+ const editAction = new TextRenderable14(renderer, {
1539
1716
  id: "view-action-edit",
1540
1717
  content: "[e] Edit",
1541
1718
  fg: COLORS.textMuted
1542
1719
  });
1543
- const deleteAction = new TextRenderable12(renderer, {
1720
+ const deleteAction = new TextRenderable14(renderer, {
1544
1721
  id: "view-action-delete",
1545
1722
  content: "[d] Delete",
1546
1723
  fg: COLORS.danger
1547
1724
  });
1725
+ const archiveRestoreAction = new TextRenderable14(renderer, {
1726
+ id: "view-action-archive-restore",
1727
+ content: task.archived ? "[r] Restore" : "[x] Archive",
1728
+ fg: task.archived ? COLORS.success : COLORS.warning
1729
+ });
1548
1730
  actionsLeft.add(moveAction);
1549
1731
  actionsLeft.add(assignAction);
1550
1732
  actionsLeft.add(editAction);
1733
+ actionsLeft.add(archiveRestoreAction);
1551
1734
  actionsLeft.add(deleteAction);
1552
- const escAction = new TextRenderable12(renderer, {
1735
+ const escAction = new TextRenderable14(renderer, {
1553
1736
  id: "view-action-esc",
1554
1737
  content: "[Esc]",
1555
1738
  fg: COLORS.textDim
@@ -1677,6 +1860,21 @@ var openDeleteModal = async (state) => {
1677
1860
  await showDeleteTaskModal(state, () => refreshBoard(state));
1678
1861
  }
1679
1862
  };
1863
+ var openArchiveModal = async (state) => {
1864
+ const taskId = getSelectedTaskId(state);
1865
+ if (taskId) {
1866
+ if (state.archiveViewMode) {
1867
+ await showRestoreTaskModal(state, () => refreshBoard(state));
1868
+ } else {
1869
+ await showArchiveTaskModal(state, () => refreshBoard(state));
1870
+ }
1871
+ }
1872
+ };
1873
+ var toggleArchiveView = async (state) => {
1874
+ state.archiveViewMode = !state.archiveViewMode;
1875
+ state.currentColumnIndex = 0;
1876
+ await refreshBoard(state);
1877
+ };
1680
1878
  var openEditModal = async (state) => {
1681
1879
  const task = state.selectedTask;
1682
1880
  if (!task)
@@ -1709,6 +1907,14 @@ async function openViewModalForTask(state, taskIdOverride) {
1709
1907
  },
1710
1908
  onEdit: async () => {
1711
1909
  await openEditModal(state);
1910
+ },
1911
+ onArchive: async () => {
1912
+ closeModal(state);
1913
+ await openArchiveModal(state);
1914
+ },
1915
+ onRestore: async () => {
1916
+ closeModal(state);
1917
+ await showRestoreTaskModal(state, () => refreshBoard(state));
1712
1918
  }
1713
1919
  }, taskIdOverride);
1714
1920
  }
@@ -1761,10 +1967,37 @@ var modalBindings = {
1761
1967
  h: navigateLeft,
1762
1968
  right: navigateRight,
1763
1969
  l: navigateRight,
1764
- a: (state) => showAddTaskModal(state, () => refreshBoard(state)),
1765
- m: openMoveModal,
1766
- u: openAssignModal,
1767
- d: openDeleteModal,
1970
+ a: (state) => {
1971
+ if (!state.archiveViewMode) {
1972
+ return showAddTaskModal(state, () => refreshBoard(state));
1973
+ }
1974
+ },
1975
+ m: (state) => {
1976
+ if (!state.archiveViewMode) {
1977
+ return openMoveModal(state);
1978
+ }
1979
+ },
1980
+ u: (state) => {
1981
+ if (!state.archiveViewMode) {
1982
+ return openAssignModal(state);
1983
+ }
1984
+ },
1985
+ d: (state) => {
1986
+ if (!state.archiveViewMode) {
1987
+ return openDeleteModal(state);
1988
+ }
1989
+ },
1990
+ x: (state) => {
1991
+ if (!state.archiveViewMode) {
1992
+ return openArchiveModal(state);
1993
+ }
1994
+ },
1995
+ r: (state) => {
1996
+ if (state.archiveViewMode) {
1997
+ return openArchiveModal(state);
1998
+ }
1999
+ },
2000
+ tab: toggleArchiveView,
1768
2001
  return: openViewModal,
1769
2002
  "?": showHelpModal
1770
2003
  },
@@ -1794,6 +2027,16 @@ var modalBindings = {
1794
2027
  n: closeModal,
1795
2028
  escape: closeModal
1796
2029
  },
2030
+ archiveTask: {
2031
+ y: confirmModal,
2032
+ n: closeModal,
2033
+ escape: closeModal
2034
+ },
2035
+ restoreTask: {
2036
+ y: confirmModal,
2037
+ n: closeModal,
2038
+ escape: closeModal
2039
+ },
1797
2040
  viewTask: {
1798
2041
  escape: closeModal,
1799
2042
  left: buttonSelectPrev,
@@ -1812,6 +2055,18 @@ var modalBindings = {
1812
2055
  closeModal(state);
1813
2056
  await openDeleteModal(state);
1814
2057
  },
2058
+ x: async (state) => {
2059
+ if (!state.selectedTask?.archived) {
2060
+ closeModal(state);
2061
+ await openArchiveModal(state);
2062
+ }
2063
+ },
2064
+ r: async (state) => {
2065
+ if (state.selectedTask?.archived) {
2066
+ closeModal(state);
2067
+ await showRestoreTaskModal(state, () => refreshBoard(state));
2068
+ }
2069
+ },
1815
2070
  e: openEditModal,
1816
2071
  c: copyTaskId,
1817
2072
  j: (state) => scrollViewTaskDescription(state, "down"),
@@ -1931,7 +2186,8 @@ async function main() {
1931
2186
  viewTaskState: null,
1932
2187
  editTaskState: null,
1933
2188
  viewTaskRuntime: null,
1934
- editTaskRuntime: null
2189
+ editTaskRuntime: null,
2190
+ archiveViewMode: false
1935
2191
  };
1936
2192
  await refreshBoard(state);
1937
2193
  let lastDataVersion = null;
@@ -1953,7 +2209,8 @@ async function main() {
1953
2209
  process.on("exit", cleanup);
1954
2210
  process.on("SIGINT", cleanup);
1955
2211
  process.on("SIGTERM", cleanup);
1956
- renderer.keyInput.on("keypress", (key) => {
2212
+ const keyEmitter = renderer.keyInput;
2213
+ keyEmitter.on("keypress", (key) => {
1957
2214
  handleKeypress(state, key);
1958
2215
  });
1959
2216
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kaban-board/tui",
3
- "version": "0.2.6",
3
+ "version": "0.2.9",
4
4
  "description": "Terminal User Interface for Kaban - Kanban for AI Agents",
5
5
  "type": "module",
6
6
  "bin": {
@@ -18,7 +18,7 @@
18
18
  "prepublishOnly": "npm run build"
19
19
  },
20
20
  "dependencies": {
21
- "@kaban-board/core": "0.2.4",
21
+ "@kaban-board/core": "0.2.5",
22
22
  "@opentui/core": "^0.1.69"
23
23
  },
24
24
  "devDependencies": {