@industry-theme/backlogmd-kanban-panel 1.0.12 → 1.0.14

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.
@@ -3740,89 +3740,89 @@ const createLucideIcon = (iconName, iconNode) => {
3740
3740
  * This source code is licensed under the ISC license.
3741
3741
  * See the LICENSE file in the root directory of this source tree.
3742
3742
  */
3743
- const __iconNode$m = [
3743
+ const __iconNode$o = [
3744
3744
  ["path", { d: "m12 19-7-7 7-7", key: "1l729n" }],
3745
3745
  ["path", { d: "M19 12H5", key: "x3x0zl" }]
3746
3746
  ];
3747
- const ArrowLeft = createLucideIcon("arrow-left", __iconNode$m);
3747
+ const ArrowLeft = createLucideIcon("arrow-left", __iconNode$o);
3748
3748
  /**
3749
3749
  * @license lucide-react v0.552.0 - ISC
3750
3750
  *
3751
3751
  * This source code is licensed under the ISC license.
3752
3752
  * See the LICENSE file in the root directory of this source tree.
3753
3753
  */
3754
- const __iconNode$l = [
3754
+ const __iconNode$n = [
3755
3755
  ["path", { d: "M8 2v4", key: "1cmpym" }],
3756
3756
  ["path", { d: "M16 2v4", key: "4m81vk" }],
3757
3757
  ["rect", { width: "18", height: "18", x: "3", y: "4", rx: "2", key: "1hopcy" }],
3758
3758
  ["path", { d: "M3 10h18", key: "8toen8" }]
3759
3759
  ];
3760
- const Calendar = createLucideIcon("calendar", __iconNode$l);
3760
+ const Calendar = createLucideIcon("calendar", __iconNode$n);
3761
3761
  /**
3762
3762
  * @license lucide-react v0.552.0 - ISC
3763
3763
  *
3764
3764
  * This source code is licensed under the ISC license.
3765
3765
  * See the LICENSE file in the root directory of this source tree.
3766
3766
  */
3767
- const __iconNode$k = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
3768
- const Check = createLucideIcon("check", __iconNode$k);
3767
+ const __iconNode$m = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
3768
+ const Check = createLucideIcon("check", __iconNode$m);
3769
3769
  /**
3770
3770
  * @license lucide-react v0.552.0 - ISC
3771
3771
  *
3772
3772
  * This source code is licensed under the ISC license.
3773
3773
  * See the LICENSE file in the root directory of this source tree.
3774
3774
  */
3775
- const __iconNode$j = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
3776
- const ChevronDown = createLucideIcon("chevron-down", __iconNode$j);
3775
+ const __iconNode$l = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
3776
+ const ChevronDown = createLucideIcon("chevron-down", __iconNode$l);
3777
3777
  /**
3778
3778
  * @license lucide-react v0.552.0 - ISC
3779
3779
  *
3780
3780
  * This source code is licensed under the ISC license.
3781
3781
  * See the LICENSE file in the root directory of this source tree.
3782
3782
  */
3783
- const __iconNode$i = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
3784
- const ChevronRight = createLucideIcon("chevron-right", __iconNode$i);
3783
+ const __iconNode$k = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
3784
+ const ChevronRight = createLucideIcon("chevron-right", __iconNode$k);
3785
3785
  /**
3786
3786
  * @license lucide-react v0.552.0 - ISC
3787
3787
  *
3788
3788
  * This source code is licensed under the ISC license.
3789
3789
  * See the LICENSE file in the root directory of this source tree.
3790
3790
  */
3791
- const __iconNode$h = [
3791
+ const __iconNode$j = [
3792
3792
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
3793
3793
  ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
3794
3794
  ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
3795
3795
  ];
3796
- const CircleAlert = createLucideIcon("circle-alert", __iconNode$h);
3796
+ const CircleAlert = createLucideIcon("circle-alert", __iconNode$j);
3797
3797
  /**
3798
3798
  * @license lucide-react v0.552.0 - ISC
3799
3799
  *
3800
3800
  * This source code is licensed under the ISC license.
3801
3801
  * See the LICENSE file in the root directory of this source tree.
3802
3802
  */
3803
- const __iconNode$g = [
3803
+ const __iconNode$i = [
3804
3804
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
3805
3805
  ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
3806
3806
  ];
3807
- const CircleCheck = createLucideIcon("circle-check", __iconNode$g);
3807
+ const CircleCheck = createLucideIcon("circle-check", __iconNode$i);
3808
3808
  /**
3809
3809
  * @license lucide-react v0.552.0 - ISC
3810
3810
  *
3811
3811
  * This source code is licensed under the ISC license.
3812
3812
  * See the LICENSE file in the root directory of this source tree.
3813
3813
  */
3814
- const __iconNode$f = [
3814
+ const __iconNode$h = [
3815
3815
  ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
3816
3816
  ["path", { d: "M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2", key: "zix9uf" }]
3817
3817
  ];
3818
- const Copy = createLucideIcon("copy", __iconNode$f);
3818
+ const Copy = createLucideIcon("copy", __iconNode$h);
3819
3819
  /**
3820
3820
  * @license lucide-react v0.552.0 - ISC
3821
3821
  *
3822
3822
  * This source code is licensed under the ISC license.
3823
3823
  * See the LICENSE file in the root directory of this source tree.
3824
3824
  */
3825
- const __iconNode$e = [
3825
+ const __iconNode$g = [
3826
3826
  ["path", { d: "m15 15 6 6", key: "1s409w" }],
3827
3827
  ["path", { d: "m15 9 6-6", key: "ko1vev" }],
3828
3828
  ["path", { d: "M21 16v5h-5", key: "1ck2sf" }],
@@ -3832,26 +3832,26 @@ const __iconNode$e = [
3832
3832
  ["path", { d: "M3 8V3h5", key: "1ln10m" }],
3833
3833
  ["path", { d: "M9 9 3 3", key: "v551iv" }]
3834
3834
  ];
3835
- const Expand = createLucideIcon("expand", __iconNode$e);
3835
+ const Expand = createLucideIcon("expand", __iconNode$g);
3836
3836
  /**
3837
3837
  * @license lucide-react v0.552.0 - ISC
3838
3838
  *
3839
3839
  * This source code is licensed under the ISC license.
3840
3840
  * See the LICENSE file in the root directory of this source tree.
3841
3841
  */
3842
- const __iconNode$d = [
3842
+ const __iconNode$f = [
3843
3843
  ["path", { d: "M15 3h6v6", key: "1q9fwt" }],
3844
3844
  ["path", { d: "M10 14 21 3", key: "gplh6r" }],
3845
3845
  ["path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6", key: "a6xqqp" }]
3846
3846
  ];
3847
- const ExternalLink = createLucideIcon("external-link", __iconNode$d);
3847
+ const ExternalLink = createLucideIcon("external-link", __iconNode$f);
3848
3848
  /**
3849
3849
  * @license lucide-react v0.552.0 - ISC
3850
3850
  *
3851
3851
  * This source code is licensed under the ISC license.
3852
3852
  * See the LICENSE file in the root directory of this source tree.
3853
3853
  */
3854
- const __iconNode$c = [
3854
+ const __iconNode$e = [
3855
3855
  [
3856
3856
  "path",
3857
3857
  {
@@ -3864,14 +3864,14 @@ const __iconNode$c = [
3864
3864
  ["path", { d: "M16 13H8", key: "t4e002" }],
3865
3865
  ["path", { d: "M16 17H8", key: "z1uh3a" }]
3866
3866
  ];
3867
- const FileText = createLucideIcon("file-text", __iconNode$c);
3867
+ const FileText = createLucideIcon("file-text", __iconNode$e);
3868
3868
  /**
3869
3869
  * @license lucide-react v0.552.0 - ISC
3870
3870
  *
3871
3871
  * This source code is licensed under the ISC license.
3872
3872
  * See the LICENSE file in the root directory of this source tree.
3873
3873
  */
3874
- const __iconNode$b = [
3874
+ const __iconNode$d = [
3875
3875
  [
3876
3876
  "path",
3877
3877
  {
@@ -3880,14 +3880,14 @@ const __iconNode$b = [
3880
3880
  }
3881
3881
  ]
3882
3882
  ];
3883
- const Flag = createLucideIcon("flag", __iconNode$b);
3883
+ const Flag = createLucideIcon("flag", __iconNode$d);
3884
3884
  /**
3885
3885
  * @license lucide-react v0.552.0 - ISC
3886
3886
  *
3887
3887
  * This source code is licensed under the ISC license.
3888
3888
  * See the LICENSE file in the root directory of this source tree.
3889
3889
  */
3890
- const __iconNode$a = [
3890
+ const __iconNode$c = [
3891
3891
  ["path", { d: "M12 10v6", key: "1bos4e" }],
3892
3892
  ["path", { d: "M9 13h6", key: "1uhe8q" }],
3893
3893
  [
@@ -3898,70 +3898,70 @@ const __iconNode$a = [
3898
3898
  }
3899
3899
  ]
3900
3900
  ];
3901
- const FolderPlus = createLucideIcon("folder-plus", __iconNode$a);
3901
+ const FolderPlus = createLucideIcon("folder-plus", __iconNode$c);
3902
3902
  /**
3903
3903
  * @license lucide-react v0.552.0 - ISC
3904
3904
  *
3905
3905
  * This source code is licensed under the ISC license.
3906
3906
  * See the LICENSE file in the root directory of this source tree.
3907
3907
  */
3908
- const __iconNode$9 = [
3908
+ const __iconNode$b = [
3909
3909
  ["line", { x1: "6", x2: "6", y1: "3", y2: "15", key: "17qcm7" }],
3910
3910
  ["circle", { cx: "18", cy: "6", r: "3", key: "1h7g24" }],
3911
3911
  ["circle", { cx: "6", cy: "18", r: "3", key: "fqmcym" }],
3912
3912
  ["path", { d: "M18 9a9 9 0 0 1-9 9", key: "n2h4wq" }]
3913
3913
  ];
3914
- const GitBranch = createLucideIcon("git-branch", __iconNode$9);
3914
+ const GitBranch = createLucideIcon("git-branch", __iconNode$b);
3915
3915
  /**
3916
3916
  * @license lucide-react v0.552.0 - ISC
3917
3917
  *
3918
3918
  * This source code is licensed under the ISC license.
3919
3919
  * See the LICENSE file in the root directory of this source tree.
3920
3920
  */
3921
- const __iconNode$8 = [
3921
+ const __iconNode$a = [
3922
3922
  ["path", { d: "M5 3v14", key: "9nsxs2" }],
3923
3923
  ["path", { d: "M12 3v8", key: "1h2ygw" }],
3924
3924
  ["path", { d: "M19 3v18", key: "1sk56x" }]
3925
3925
  ];
3926
- const Kanban = createLucideIcon("kanban", __iconNode$8);
3926
+ const Kanban = createLucideIcon("kanban", __iconNode$a);
3927
3927
  /**
3928
3928
  * @license lucide-react v0.552.0 - ISC
3929
3929
  *
3930
3930
  * This source code is licensed under the ISC license.
3931
3931
  * See the LICENSE file in the root directory of this source tree.
3932
3932
  */
3933
- const __iconNode$7 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
3934
- const LoaderCircle = createLucideIcon("loader-circle", __iconNode$7);
3933
+ const __iconNode$9 = [["path", { d: "M21 12a9 9 0 1 1-6.219-8.56", key: "13zald" }]];
3934
+ const LoaderCircle = createLucideIcon("loader-circle", __iconNode$9);
3935
3935
  /**
3936
3936
  * @license lucide-react v0.552.0 - ISC
3937
3937
  *
3938
3938
  * This source code is licensed under the ISC license.
3939
3939
  * See the LICENSE file in the root directory of this source tree.
3940
3940
  */
3941
- const __iconNode$6 = [
3941
+ const __iconNode$8 = [
3942
3942
  ["rect", { width: "20", height: "14", x: "2", y: "3", rx: "2", key: "48i651" }],
3943
3943
  ["line", { x1: "8", x2: "16", y1: "21", y2: "21", key: "1svkeh" }],
3944
3944
  ["line", { x1: "12", x2: "12", y1: "17", y2: "21", key: "vw1qmm" }]
3945
3945
  ];
3946
- const Monitor = createLucideIcon("monitor", __iconNode$6);
3946
+ const Monitor = createLucideIcon("monitor", __iconNode$8);
3947
3947
  /**
3948
3948
  * @license lucide-react v0.552.0 - ISC
3949
3949
  *
3950
3950
  * This source code is licensed under the ISC license.
3951
3951
  * See the LICENSE file in the root directory of this source tree.
3952
3952
  */
3953
- const __iconNode$5 = [
3953
+ const __iconNode$7 = [
3954
3954
  ["path", { d: "M18 8L22 12L18 16", key: "1r0oui" }],
3955
3955
  ["path", { d: "M2 12H22", key: "1m8cig" }]
3956
3956
  ];
3957
- const MoveRight = createLucideIcon("move-right", __iconNode$5);
3957
+ const MoveRight = createLucideIcon("move-right", __iconNode$7);
3958
3958
  /**
3959
3959
  * @license lucide-react v0.552.0 - ISC
3960
3960
  *
3961
3961
  * This source code is licensed under the ISC license.
3962
3962
  * See the LICENSE file in the root directory of this source tree.
3963
3963
  */
3964
- const __iconNode$4 = [
3964
+ const __iconNode$6 = [
3965
3965
  [
3966
3966
  "path",
3967
3967
  {
@@ -3970,27 +3970,38 @@ const __iconNode$4 = [
3970
3970
  }
3971
3971
  ]
3972
3972
  ];
3973
- const Play = createLucideIcon("play", __iconNode$4);
3973
+ const Play = createLucideIcon("play", __iconNode$6);
3974
3974
  /**
3975
3975
  * @license lucide-react v0.552.0 - ISC
3976
3976
  *
3977
3977
  * This source code is licensed under the ISC license.
3978
3978
  * See the LICENSE file in the root directory of this source tree.
3979
3979
  */
3980
- const __iconNode$3 = [
3980
+ const __iconNode$5 = [
3981
+ ["path", { d: "M5 12h14", key: "1ays0h" }],
3982
+ ["path", { d: "M12 5v14", key: "s699le" }]
3983
+ ];
3984
+ const Plus = createLucideIcon("plus", __iconNode$5);
3985
+ /**
3986
+ * @license lucide-react v0.552.0 - ISC
3987
+ *
3988
+ * This source code is licensed under the ISC license.
3989
+ * See the LICENSE file in the root directory of this source tree.
3990
+ */
3991
+ const __iconNode$4 = [
3981
3992
  ["path", { d: "M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8", key: "v9h5vc" }],
3982
3993
  ["path", { d: "M21 3v5h-5", key: "1q7to0" }],
3983
3994
  ["path", { d: "M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16", key: "3uifl3" }],
3984
3995
  ["path", { d: "M8 16H3v5", key: "1cv678" }]
3985
3996
  ];
3986
- const RefreshCw = createLucideIcon("refresh-cw", __iconNode$3);
3997
+ const RefreshCw = createLucideIcon("refresh-cw", __iconNode$4);
3987
3998
  /**
3988
3999
  * @license lucide-react v0.552.0 - ISC
3989
4000
  *
3990
4001
  * This source code is licensed under the ISC license.
3991
4002
  * See the LICENSE file in the root directory of this source tree.
3992
4003
  */
3993
- const __iconNode$2 = [
4004
+ const __iconNode$3 = [
3994
4005
  [
3995
4006
  "path",
3996
4007
  {
@@ -4000,30 +4011,41 @@ const __iconNode$2 = [
4000
4011
  ],
4001
4012
  ["circle", { cx: "7.5", cy: "7.5", r: ".5", fill: "currentColor", key: "kqv944" }]
4002
4013
  ];
4003
- const Tag = createLucideIcon("tag", __iconNode$2);
4014
+ const Tag = createLucideIcon("tag", __iconNode$3);
4004
4015
  /**
4005
4016
  * @license lucide-react v0.552.0 - ISC
4006
4017
  *
4007
4018
  * This source code is licensed under the ISC license.
4008
4019
  * See the LICENSE file in the root directory of this source tree.
4009
4020
  */
4010
- const __iconNode$1 = [
4021
+ const __iconNode$2 = [
4011
4022
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
4012
4023
  ["circle", { cx: "12", cy: "12", r: "6", key: "1vlfrh" }],
4013
4024
  ["circle", { cx: "12", cy: "12", r: "2", key: "1c9p78" }]
4014
4025
  ];
4015
- const Target = createLucideIcon("target", __iconNode$1);
4026
+ const Target = createLucideIcon("target", __iconNode$2);
4016
4027
  /**
4017
4028
  * @license lucide-react v0.552.0 - ISC
4018
4029
  *
4019
4030
  * This source code is licensed under the ISC license.
4020
4031
  * See the LICENSE file in the root directory of this source tree.
4021
4032
  */
4022
- const __iconNode = [
4033
+ const __iconNode$1 = [
4023
4034
  ["path", { d: "M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2", key: "975kel" }],
4024
4035
  ["circle", { cx: "12", cy: "7", r: "4", key: "17ys0d" }]
4025
4036
  ];
4026
- const User = createLucideIcon("user", __iconNode);
4037
+ const User = createLucideIcon("user", __iconNode$1);
4038
+ /**
4039
+ * @license lucide-react v0.552.0 - ISC
4040
+ *
4041
+ * This source code is licensed under the ISC license.
4042
+ * See the LICENSE file in the root directory of this source tree.
4043
+ */
4044
+ const __iconNode = [
4045
+ ["path", { d: "M18 6 6 18", key: "1bl5f8" }],
4046
+ ["path", { d: "m6 6 12 12", key: "d8bk6v" }]
4047
+ ];
4048
+ const X = createLucideIcon("x", __iconNode);
4027
4049
  var terminalTheme$1 = {
4028
4050
  space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
4029
4051
  fonts: {
@@ -5765,6 +5787,7 @@ class PanelFileSystemAdapter {
5765
5787
  constructor(access) {
5766
5788
  this.fetchFile = access.fetchFile;
5767
5789
  this.filePaths = new Set(access.filePaths);
5790
+ this.hostFileSystem = access.hostFileSystem;
5768
5791
  this.directories = /* @__PURE__ */ new Set();
5769
5792
  for (const filePath of access.filePaths) {
5770
5793
  const parts = filePath.split("/");
@@ -5774,6 +5797,13 @@ class PanelFileSystemAdapter {
5774
5797
  }
5775
5798
  this.directories.add("");
5776
5799
  }
5800
+ /**
5801
+ * Check if write operations are available
5802
+ */
5803
+ get canWrite() {
5804
+ var _a, _b;
5805
+ return !!(((_a = this.hostFileSystem) == null ? void 0 : _a.writeFile) && ((_b = this.hostFileSystem) == null ? void 0 : _b.createDir));
5806
+ }
5777
5807
  async exists(path2) {
5778
5808
  const normalized = this.normalizePath(path2);
5779
5809
  return this.filePaths.has(normalized) || this.directories.has(normalized);
@@ -5785,14 +5815,36 @@ class PanelFileSystemAdapter {
5785
5815
  }
5786
5816
  return this.fetchFile(normalized);
5787
5817
  }
5788
- async writeFile(_path, _content) {
5789
- throw new Error("Write operations not supported in panel context");
5818
+ async writeFile(path2, content2) {
5819
+ var _a;
5820
+ if (!((_a = this.hostFileSystem) == null ? void 0 : _a.writeFile)) {
5821
+ throw new Error("Write operations not available - host adapter not configured");
5822
+ }
5823
+ const normalized = this.normalizePath(path2);
5824
+ await this.hostFileSystem.writeFile(normalized, content2);
5825
+ this.filePaths.add(normalized);
5826
+ const parts = normalized.split("/");
5827
+ for (let i = 1; i < parts.length; i++) {
5828
+ this.directories.add(parts.slice(0, i).join("/"));
5829
+ }
5790
5830
  }
5791
- async deleteFile(_path) {
5792
- throw new Error("Delete operations not supported in panel context");
5831
+ async deleteFile(path2) {
5832
+ var _a;
5833
+ if (!((_a = this.hostFileSystem) == null ? void 0 : _a.deleteFile)) {
5834
+ throw new Error("Delete operations not available - host adapter not configured");
5835
+ }
5836
+ const normalized = this.normalizePath(path2);
5837
+ await this.hostFileSystem.deleteFile(normalized);
5838
+ this.filePaths.delete(normalized);
5793
5839
  }
5794
- async createDir(_path, _options) {
5795
- throw new Error("Directory creation not supported in panel context");
5840
+ async createDir(path2, _options) {
5841
+ var _a;
5842
+ if (!((_a = this.hostFileSystem) == null ? void 0 : _a.createDir)) {
5843
+ throw new Error("Directory creation not available - host adapter not configured");
5844
+ }
5845
+ const normalized = this.normalizePath(path2);
5846
+ await this.hostFileSystem.createDir(normalized);
5847
+ this.directories.add(normalized);
5796
5848
  }
5797
5849
  async readDir(path2) {
5798
5850
  const normalized = this.normalizePath(path2);
@@ -5905,6 +5957,7 @@ function useKanbanData(options) {
5905
5957
  const [isLoading, setIsLoading] = useState(true);
5906
5958
  const [error, setError] = useState(null);
5907
5959
  const [isBacklogProject, setIsBacklogProject] = useState(false);
5960
+ const [canWrite, setCanWrite] = useState(false);
5908
5961
  const [tasksBySource, setTasksBySource] = useState(
5909
5962
  /* @__PURE__ */ new Map()
5910
5963
  );
@@ -5950,7 +6003,7 @@ function useKanbanData(options) {
5950
6003
  }, []);
5951
6004
  const fileTreeVersionRef = useRef(null);
5952
6005
  const loadBacklogData = useCallback(async () => {
5953
- var _a, _b;
6006
+ var _a, _b, _c;
5954
6007
  if (!context || !actions) {
5955
6008
  console.log("[useKanbanData] No context provided");
5956
6009
  setIsBacklogProject(false);
@@ -5986,7 +6039,8 @@ function useKanbanData(options) {
5986
6039
  const filePaths = files.map((f) => f.path);
5987
6040
  const fs = new PanelFileSystemAdapter({
5988
6041
  fetchFile: fetchFileContent,
5989
- filePaths
6042
+ filePaths,
6043
+ hostFileSystem: (_c = context.adapters) == null ? void 0 : _c.fileSystem
5990
6044
  });
5991
6045
  const core2 = new Core({
5992
6046
  projectRoot: "",
@@ -6004,6 +6058,7 @@ function useKanbanData(options) {
6004
6058
  }
6005
6059
  console.log("[useKanbanData] Loading Backlog.md data with lazy loading...");
6006
6060
  setIsBacklogProject(true);
6061
+ setCanWrite(fs.canWrite);
6007
6062
  await core2.initializeLazy(filePaths);
6008
6063
  coreRef.current = core2;
6009
6064
  const paginatedResult = await core2.getTasksBySourcePaginated({
@@ -6138,14 +6193,28 @@ function useKanbanData(options) {
6138
6193
  await loadBacklogData();
6139
6194
  }, [loadBacklogData]);
6140
6195
  const updateTaskStatus = useCallback(
6141
- async (_taskId, _newStatus) => {
6196
+ async (taskId, newStatus) => {
6197
+ const core2 = coreRef.current;
6198
+ if (!core2) {
6199
+ console.warn("[useKanbanData] Core not available for updateTaskStatus");
6200
+ setError("Cannot update task - backlog not loaded");
6201
+ return;
6202
+ }
6142
6203
  setError(null);
6143
- console.warn(
6144
- "[useKanbanData] Task status updates not yet implemented for Backlog.md"
6145
- );
6146
- setError("Task editing is not yet supported");
6204
+ try {
6205
+ console.log(`[useKanbanData] Updating task ${taskId} status to "${newStatus}"`);
6206
+ const updatedTask = await core2.updateTask(taskId, { status: newStatus });
6207
+ if (!updatedTask) {
6208
+ throw new Error(`Task ${taskId} not found`);
6209
+ }
6210
+ console.log(`[useKanbanData] Task ${taskId} updated successfully`);
6211
+ await loadBacklogData();
6212
+ } catch (err) {
6213
+ console.error("[useKanbanData] Failed to update task status:", err);
6214
+ setError(err instanceof Error ? err.message : "Failed to update task");
6215
+ }
6147
6216
  },
6148
- []
6217
+ [loadBacklogData]
6149
6218
  );
6150
6219
  const moveTaskOptimistic = useCallback(
6151
6220
  (taskId, toColumn) => {
@@ -6237,7 +6306,10 @@ function useKanbanData(options) {
6237
6306
  loadMoreActive,
6238
6307
  // Drag-and-drop support
6239
6308
  moveTaskOptimistic,
6240
- getTaskById
6309
+ getTaskById,
6310
+ // Write support
6311
+ canWrite,
6312
+ core: coreRef.current
6241
6313
  };
6242
6314
  }
6243
6315
  const TaskCard = ({
@@ -6830,6 +6902,519 @@ const EmptyState = ({
6830
6902
  )
6831
6903
  ] });
6832
6904
  };
6905
+ const TaskModal = ({
6906
+ isOpen,
6907
+ onClose,
6908
+ onSave,
6909
+ task,
6910
+ defaultStatus = "To Do",
6911
+ availableStatuses = ["To Do", "In Progress", "Done"],
6912
+ availableMilestones = []
6913
+ }) => {
6914
+ const { theme: theme2 } = useTheme();
6915
+ const isEditing = !!task;
6916
+ const [title, setTitle] = useState("");
6917
+ const [description, setDescription] = useState("");
6918
+ const [status, setStatus] = useState(defaultStatus);
6919
+ const [priority, setPriority] = useState("medium");
6920
+ const [labels, setLabels] = useState("");
6921
+ const [assignee, setAssignee] = useState("");
6922
+ const [milestone, setMilestone] = useState("");
6923
+ const [isSaving, setIsSaving] = useState(false);
6924
+ const [error, setError] = useState(null);
6925
+ useEffect(() => {
6926
+ var _a, _b;
6927
+ if (isOpen) {
6928
+ if (task) {
6929
+ setTitle(task.title || "");
6930
+ setDescription(task.description || "");
6931
+ setStatus(task.status || defaultStatus);
6932
+ setPriority(task.priority || "medium");
6933
+ setLabels(((_a = task.labels) == null ? void 0 : _a.join(", ")) || "");
6934
+ setAssignee(((_b = task.assignee) == null ? void 0 : _b.join(", ")) || "");
6935
+ setMilestone(task.milestone || "");
6936
+ } else {
6937
+ setTitle("");
6938
+ setDescription("");
6939
+ setStatus(defaultStatus);
6940
+ setPriority("medium");
6941
+ setLabels("");
6942
+ setAssignee("");
6943
+ setMilestone("");
6944
+ }
6945
+ setError(null);
6946
+ }
6947
+ }, [isOpen, task, defaultStatus]);
6948
+ const handleSubmit = async (e) => {
6949
+ e.preventDefault();
6950
+ if (!title.trim()) {
6951
+ setError("Title is required");
6952
+ return;
6953
+ }
6954
+ setIsSaving(true);
6955
+ setError(null);
6956
+ try {
6957
+ const labelsArray = labels.split(",").map((l) => l.trim()).filter(Boolean);
6958
+ const assigneeArray = assignee.split(",").map((a) => a.trim()).filter(Boolean);
6959
+ if (isEditing) {
6960
+ const input = {
6961
+ title: title.trim(),
6962
+ description: description.trim() || void 0,
6963
+ status,
6964
+ priority,
6965
+ labels: labelsArray.length > 0 ? labelsArray : void 0,
6966
+ assignee: assigneeArray.length > 0 ? assigneeArray : void 0,
6967
+ milestone: milestone || void 0
6968
+ };
6969
+ await onSave(input);
6970
+ } else {
6971
+ const input = {
6972
+ title: title.trim(),
6973
+ description: description.trim() || void 0,
6974
+ status,
6975
+ priority,
6976
+ labels: labelsArray.length > 0 ? labelsArray : void 0,
6977
+ assignee: assigneeArray.length > 0 ? assigneeArray : void 0,
6978
+ milestone: milestone || void 0
6979
+ };
6980
+ await onSave(input);
6981
+ }
6982
+ onClose();
6983
+ } catch (err) {
6984
+ setError(err instanceof Error ? err.message : "Failed to save task");
6985
+ } finally {
6986
+ setIsSaving(false);
6987
+ }
6988
+ };
6989
+ if (!isOpen) return null;
6990
+ const modalContent = /* @__PURE__ */ jsxs(
6991
+ "div",
6992
+ {
6993
+ style: {
6994
+ position: "fixed",
6995
+ inset: 0,
6996
+ zIndex: 9999,
6997
+ display: "flex",
6998
+ alignItems: "center",
6999
+ justifyContent: "center",
7000
+ padding: "16px"
7001
+ },
7002
+ children: [
7003
+ /* @__PURE__ */ jsx(
7004
+ "div",
7005
+ {
7006
+ onClick: onClose,
7007
+ style: {
7008
+ position: "absolute",
7009
+ inset: 0,
7010
+ backgroundColor: "rgba(0, 0, 0, 0.5)"
7011
+ }
7012
+ }
7013
+ ),
7014
+ /* @__PURE__ */ jsxs(
7015
+ "div",
7016
+ {
7017
+ style: {
7018
+ position: "relative",
7019
+ width: "100%",
7020
+ maxWidth: "500px",
7021
+ maxHeight: "90vh",
7022
+ overflow: "auto",
7023
+ backgroundColor: theme2.colors.background,
7024
+ borderRadius: theme2.radii[3],
7025
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
7026
+ border: `1px solid ${theme2.colors.border}`
7027
+ },
7028
+ children: [
7029
+ /* @__PURE__ */ jsxs(
7030
+ "div",
7031
+ {
7032
+ style: {
7033
+ display: "flex",
7034
+ alignItems: "center",
7035
+ justifyContent: "space-between",
7036
+ padding: "16px 20px",
7037
+ borderBottom: `1px solid ${theme2.colors.border}`
7038
+ },
7039
+ children: [
7040
+ /* @__PURE__ */ jsx(
7041
+ "h2",
7042
+ {
7043
+ style: {
7044
+ margin: 0,
7045
+ fontSize: theme2.fontSizes[4],
7046
+ fontWeight: 600,
7047
+ color: theme2.colors.text
7048
+ },
7049
+ children: isEditing ? "Edit Task" : "New Task"
7050
+ }
7051
+ ),
7052
+ /* @__PURE__ */ jsx(
7053
+ "button",
7054
+ {
7055
+ onClick: onClose,
7056
+ style: {
7057
+ background: "none",
7058
+ border: "none",
7059
+ cursor: "pointer",
7060
+ padding: "4px",
7061
+ display: "flex",
7062
+ alignItems: "center",
7063
+ justifyContent: "center",
7064
+ borderRadius: theme2.radii[1],
7065
+ color: theme2.colors.textMuted
7066
+ },
7067
+ children: /* @__PURE__ */ jsx(X, { size: 20 })
7068
+ }
7069
+ )
7070
+ ]
7071
+ }
7072
+ ),
7073
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
7074
+ /* @__PURE__ */ jsxs("div", { style: { padding: "20px", display: "flex", flexDirection: "column", gap: "16px" }, children: [
7075
+ /* @__PURE__ */ jsxs("div", { children: [
7076
+ /* @__PURE__ */ jsx(
7077
+ "label",
7078
+ {
7079
+ style: {
7080
+ display: "block",
7081
+ marginBottom: "6px",
7082
+ fontSize: theme2.fontSizes[1],
7083
+ fontWeight: 500,
7084
+ color: theme2.colors.text
7085
+ },
7086
+ children: "Title *"
7087
+ }
7088
+ ),
7089
+ /* @__PURE__ */ jsx(
7090
+ "input",
7091
+ {
7092
+ type: "text",
7093
+ value: title,
7094
+ onChange: (e) => setTitle(e.target.value),
7095
+ placeholder: "Enter task title",
7096
+ autoFocus: true,
7097
+ style: {
7098
+ width: "100%",
7099
+ padding: "10px 12px",
7100
+ fontSize: theme2.fontSizes[2],
7101
+ border: `1px solid ${theme2.colors.border}`,
7102
+ borderRadius: theme2.radii[2],
7103
+ backgroundColor: theme2.colors.backgroundSecondary,
7104
+ color: theme2.colors.text,
7105
+ outline: "none",
7106
+ boxSizing: "border-box"
7107
+ }
7108
+ }
7109
+ )
7110
+ ] }),
7111
+ /* @__PURE__ */ jsxs("div", { children: [
7112
+ /* @__PURE__ */ jsx(
7113
+ "label",
7114
+ {
7115
+ style: {
7116
+ display: "block",
7117
+ marginBottom: "6px",
7118
+ fontSize: theme2.fontSizes[1],
7119
+ fontWeight: 500,
7120
+ color: theme2.colors.text
7121
+ },
7122
+ children: "Description"
7123
+ }
7124
+ ),
7125
+ /* @__PURE__ */ jsx(
7126
+ "textarea",
7127
+ {
7128
+ value: description,
7129
+ onChange: (e) => setDescription(e.target.value),
7130
+ placeholder: "Enter task description (markdown supported)",
7131
+ rows: 4,
7132
+ style: {
7133
+ width: "100%",
7134
+ padding: "10px 12px",
7135
+ fontSize: theme2.fontSizes[2],
7136
+ border: `1px solid ${theme2.colors.border}`,
7137
+ borderRadius: theme2.radii[2],
7138
+ backgroundColor: theme2.colors.backgroundSecondary,
7139
+ color: theme2.colors.text,
7140
+ outline: "none",
7141
+ resize: "vertical",
7142
+ fontFamily: theme2.fonts.body,
7143
+ boxSizing: "border-box"
7144
+ }
7145
+ }
7146
+ )
7147
+ ] }),
7148
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", gap: "12px" }, children: [
7149
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
7150
+ /* @__PURE__ */ jsx(
7151
+ "label",
7152
+ {
7153
+ style: {
7154
+ display: "block",
7155
+ marginBottom: "6px",
7156
+ fontSize: theme2.fontSizes[1],
7157
+ fontWeight: 500,
7158
+ color: theme2.colors.text
7159
+ },
7160
+ children: "Status"
7161
+ }
7162
+ ),
7163
+ /* @__PURE__ */ jsx(
7164
+ "select",
7165
+ {
7166
+ value: status,
7167
+ onChange: (e) => setStatus(e.target.value),
7168
+ style: {
7169
+ width: "100%",
7170
+ padding: "10px 12px",
7171
+ fontSize: theme2.fontSizes[2],
7172
+ border: `1px solid ${theme2.colors.border}`,
7173
+ borderRadius: theme2.radii[2],
7174
+ backgroundColor: theme2.colors.backgroundSecondary,
7175
+ color: theme2.colors.text,
7176
+ outline: "none",
7177
+ cursor: "pointer"
7178
+ },
7179
+ children: availableStatuses.map((s2) => /* @__PURE__ */ jsx("option", { value: s2, children: s2 }, s2))
7180
+ }
7181
+ )
7182
+ ] }),
7183
+ /* @__PURE__ */ jsxs("div", { style: { flex: 1 }, children: [
7184
+ /* @__PURE__ */ jsx(
7185
+ "label",
7186
+ {
7187
+ style: {
7188
+ display: "block",
7189
+ marginBottom: "6px",
7190
+ fontSize: theme2.fontSizes[1],
7191
+ fontWeight: 500,
7192
+ color: theme2.colors.text
7193
+ },
7194
+ children: "Priority"
7195
+ }
7196
+ ),
7197
+ /* @__PURE__ */ jsxs(
7198
+ "select",
7199
+ {
7200
+ value: priority,
7201
+ onChange: (e) => setPriority(e.target.value),
7202
+ style: {
7203
+ width: "100%",
7204
+ padding: "10px 12px",
7205
+ fontSize: theme2.fontSizes[2],
7206
+ border: `1px solid ${theme2.colors.border}`,
7207
+ borderRadius: theme2.radii[2],
7208
+ backgroundColor: theme2.colors.backgroundSecondary,
7209
+ color: theme2.colors.text,
7210
+ outline: "none",
7211
+ cursor: "pointer"
7212
+ },
7213
+ children: [
7214
+ /* @__PURE__ */ jsx("option", { value: "low", children: "Low" }),
7215
+ /* @__PURE__ */ jsx("option", { value: "medium", children: "Medium" }),
7216
+ /* @__PURE__ */ jsx("option", { value: "high", children: "High" })
7217
+ ]
7218
+ }
7219
+ )
7220
+ ] })
7221
+ ] }),
7222
+ /* @__PURE__ */ jsxs("div", { children: [
7223
+ /* @__PURE__ */ jsx(
7224
+ "label",
7225
+ {
7226
+ style: {
7227
+ display: "block",
7228
+ marginBottom: "6px",
7229
+ fontSize: theme2.fontSizes[1],
7230
+ fontWeight: 500,
7231
+ color: theme2.colors.text
7232
+ },
7233
+ children: "Labels"
7234
+ }
7235
+ ),
7236
+ /* @__PURE__ */ jsx(
7237
+ "input",
7238
+ {
7239
+ type: "text",
7240
+ value: labels,
7241
+ onChange: (e) => setLabels(e.target.value),
7242
+ placeholder: "bug, feature, enhancement (comma-separated)",
7243
+ style: {
7244
+ width: "100%",
7245
+ padding: "10px 12px",
7246
+ fontSize: theme2.fontSizes[2],
7247
+ border: `1px solid ${theme2.colors.border}`,
7248
+ borderRadius: theme2.radii[2],
7249
+ backgroundColor: theme2.colors.backgroundSecondary,
7250
+ color: theme2.colors.text,
7251
+ outline: "none",
7252
+ boxSizing: "border-box"
7253
+ }
7254
+ }
7255
+ )
7256
+ ] }),
7257
+ /* @__PURE__ */ jsxs("div", { children: [
7258
+ /* @__PURE__ */ jsx(
7259
+ "label",
7260
+ {
7261
+ style: {
7262
+ display: "block",
7263
+ marginBottom: "6px",
7264
+ fontSize: theme2.fontSizes[1],
7265
+ fontWeight: 500,
7266
+ color: theme2.colors.text
7267
+ },
7268
+ children: "Assignee"
7269
+ }
7270
+ ),
7271
+ /* @__PURE__ */ jsx(
7272
+ "input",
7273
+ {
7274
+ type: "text",
7275
+ value: assignee,
7276
+ onChange: (e) => setAssignee(e.target.value),
7277
+ placeholder: "user@example.com (comma-separated)",
7278
+ style: {
7279
+ width: "100%",
7280
+ padding: "10px 12px",
7281
+ fontSize: theme2.fontSizes[2],
7282
+ border: `1px solid ${theme2.colors.border}`,
7283
+ borderRadius: theme2.radii[2],
7284
+ backgroundColor: theme2.colors.backgroundSecondary,
7285
+ color: theme2.colors.text,
7286
+ outline: "none",
7287
+ boxSizing: "border-box"
7288
+ }
7289
+ }
7290
+ )
7291
+ ] }),
7292
+ availableMilestones.length > 0 && /* @__PURE__ */ jsxs("div", { children: [
7293
+ /* @__PURE__ */ jsx(
7294
+ "label",
7295
+ {
7296
+ style: {
7297
+ display: "block",
7298
+ marginBottom: "6px",
7299
+ fontSize: theme2.fontSizes[1],
7300
+ fontWeight: 500,
7301
+ color: theme2.colors.text
7302
+ },
7303
+ children: "Milestone"
7304
+ }
7305
+ ),
7306
+ /* @__PURE__ */ jsxs(
7307
+ "select",
7308
+ {
7309
+ value: milestone,
7310
+ onChange: (e) => setMilestone(e.target.value),
7311
+ style: {
7312
+ width: "100%",
7313
+ padding: "10px 12px",
7314
+ fontSize: theme2.fontSizes[2],
7315
+ border: `1px solid ${theme2.colors.border}`,
7316
+ borderRadius: theme2.radii[2],
7317
+ backgroundColor: theme2.colors.backgroundSecondary,
7318
+ color: theme2.colors.text,
7319
+ outline: "none",
7320
+ cursor: "pointer"
7321
+ },
7322
+ children: [
7323
+ /* @__PURE__ */ jsx("option", { value: "", children: "None" }),
7324
+ availableMilestones.map((m) => /* @__PURE__ */ jsx("option", { value: m, children: m }, m))
7325
+ ]
7326
+ }
7327
+ )
7328
+ ] }),
7329
+ error && /* @__PURE__ */ jsx(
7330
+ "div",
7331
+ {
7332
+ style: {
7333
+ padding: "10px 12px",
7334
+ backgroundColor: `${theme2.colors.error}15`,
7335
+ border: `1px solid ${theme2.colors.error}`,
7336
+ borderRadius: theme2.radii[2],
7337
+ color: theme2.colors.error,
7338
+ fontSize: theme2.fontSizes[1]
7339
+ },
7340
+ children: error
7341
+ }
7342
+ )
7343
+ ] }),
7344
+ /* @__PURE__ */ jsxs(
7345
+ "div",
7346
+ {
7347
+ style: {
7348
+ display: "flex",
7349
+ justifyContent: "flex-end",
7350
+ gap: "12px",
7351
+ padding: "16px 20px",
7352
+ borderTop: `1px solid ${theme2.colors.border}`
7353
+ },
7354
+ children: [
7355
+ /* @__PURE__ */ jsx(
7356
+ "button",
7357
+ {
7358
+ type: "button",
7359
+ onClick: onClose,
7360
+ disabled: isSaving,
7361
+ style: {
7362
+ padding: "10px 20px",
7363
+ fontSize: theme2.fontSizes[2],
7364
+ fontWeight: 500,
7365
+ border: `1px solid ${theme2.colors.border}`,
7366
+ borderRadius: theme2.radii[2],
7367
+ backgroundColor: "transparent",
7368
+ color: theme2.colors.text,
7369
+ cursor: "pointer"
7370
+ },
7371
+ children: "Cancel"
7372
+ }
7373
+ ),
7374
+ /* @__PURE__ */ jsxs(
7375
+ "button",
7376
+ {
7377
+ type: "submit",
7378
+ disabled: isSaving,
7379
+ style: {
7380
+ display: "flex",
7381
+ alignItems: "center",
7382
+ gap: "8px",
7383
+ padding: "10px 20px",
7384
+ fontSize: theme2.fontSizes[2],
7385
+ fontWeight: 500,
7386
+ border: "none",
7387
+ borderRadius: theme2.radii[2],
7388
+ backgroundColor: theme2.colors.primary,
7389
+ color: "#fff",
7390
+ cursor: isSaving ? "wait" : "pointer",
7391
+ opacity: isSaving ? 0.7 : 1
7392
+ },
7393
+ children: [
7394
+ isSaving && /* @__PURE__ */ jsx(LoaderCircle, { size: 16, style: { animation: "spin 1s linear infinite" } }),
7395
+ isEditing ? "Save Changes" : "Create Task"
7396
+ ]
7397
+ }
7398
+ )
7399
+ ]
7400
+ }
7401
+ )
7402
+ ] })
7403
+ ]
7404
+ }
7405
+ ),
7406
+ /* @__PURE__ */ jsx("style", { children: `
7407
+ @keyframes spin {
7408
+ from { transform: rotate(0deg); }
7409
+ to { transform: rotate(360deg); }
7410
+ }
7411
+ ` })
7412
+ ]
7413
+ }
7414
+ );
7415
+ if (typeof document === "undefined") return null;
7416
+ return createPortal(modalContent, document.body);
7417
+ };
6833
7418
  const KanbanPanelContent = ({
6834
7419
  context,
6835
7420
  actions,
@@ -6842,6 +7427,8 @@ const KanbanPanelContent = ({
6842
7427
  const [isNarrowView, setIsNarrowView] = useState(false);
6843
7428
  const containerRef = useRef(null);
6844
7429
  const [activeTask, setActiveTask] = useState(null);
7430
+ const [isTaskModalOpen, setIsTaskModalOpen] = useState(false);
7431
+ const [editingTask, setEditingTask] = useState(void 0);
6845
7432
  const sensors = useSensors(
6846
7433
  useSensor(PointerSensor, {
6847
7434
  activationConstraint: {
@@ -6877,7 +7464,9 @@ const KanbanPanelContent = ({
6877
7464
  isBacklogProject,
6878
7465
  refreshData,
6879
7466
  moveTaskOptimistic,
6880
- getTaskById
7467
+ getTaskById,
7468
+ canWrite,
7469
+ core: core2
6881
7470
  } = useKanbanData({
6882
7471
  context,
6883
7472
  actions,
@@ -6972,14 +7561,38 @@ const KanbanPanelContent = ({
6972
7561
  normalize: (path2) => path2.replace(/\/+/g, "/"),
6973
7562
  homedir: () => "/"
6974
7563
  };
6975
- const core2 = new Core({
7564
+ const core22 = new Core({
6976
7565
  projectRoot: repoPath,
6977
7566
  adapters: { fs: fsAdapter }
6978
7567
  });
6979
7568
  const projectName = ((_b2 = context.currentScope.repository) == null ? void 0 : _b2.name) || "Backlog";
6980
- await core2.initProject({ projectName });
7569
+ await core22.initProject({ projectName });
6981
7570
  await refreshData();
6982
7571
  }, [fileSystem, context.currentScope.repository, refreshData]);
7572
+ const handleOpenNewTask = useCallback(() => {
7573
+ setEditingTask(void 0);
7574
+ setIsTaskModalOpen(true);
7575
+ }, []);
7576
+ useCallback((task) => {
7577
+ setEditingTask(task);
7578
+ setIsTaskModalOpen(true);
7579
+ }, []);
7580
+ const handleCloseTaskModal = useCallback(() => {
7581
+ setIsTaskModalOpen(false);
7582
+ setEditingTask(void 0);
7583
+ }, []);
7584
+ const handleSaveTask = useCallback(async (input) => {
7585
+ if (!core2) {
7586
+ throw new Error("Backlog not loaded");
7587
+ }
7588
+ if (editingTask) {
7589
+ await core2.updateTask(editingTask.id, input);
7590
+ } else {
7591
+ await core2.createTask(input);
7592
+ }
7593
+ await refreshData();
7594
+ }, [core2, editingTask, refreshData]);
7595
+ const availableStatuses = ["To Do", "In Progress", "Done"];
6983
7596
  return /* @__PURE__ */ jsxs(
6984
7597
  "div",
6985
7598
  {
@@ -7053,12 +7666,14 @@ const KanbanPanelContent = ({
7053
7666
  status
7054
7667
  );
7055
7668
  }) }),
7056
- activeTasksState.hasMore && /* @__PURE__ */ jsx(
7669
+ canWrite && /* @__PURE__ */ jsxs(
7057
7670
  "button",
7058
7671
  {
7059
- onClick: loadMoreActive,
7060
- disabled: activeTasksState.isLoadingMore,
7672
+ onClick: handleOpenNewTask,
7061
7673
  style: {
7674
+ display: "flex",
7675
+ alignItems: "center",
7676
+ gap: "6px",
7062
7677
  background: theme2.colors.primary,
7063
7678
  color: theme2.colors.background,
7064
7679
  border: "none",
@@ -7066,6 +7681,28 @@ const KanbanPanelContent = ({
7066
7681
  padding: "6px 12px",
7067
7682
  fontSize: theme2.fontSizes[1],
7068
7683
  fontWeight: theme2.fontWeights.medium,
7684
+ cursor: "pointer",
7685
+ transition: "opacity 0.2s ease"
7686
+ },
7687
+ children: [
7688
+ /* @__PURE__ */ jsx(Plus, { size: 14 }),
7689
+ "Add Task"
7690
+ ]
7691
+ }
7692
+ ),
7693
+ activeTasksState.hasMore && /* @__PURE__ */ jsx(
7694
+ "button",
7695
+ {
7696
+ onClick: loadMoreActive,
7697
+ disabled: activeTasksState.isLoadingMore,
7698
+ style: {
7699
+ background: theme2.colors.backgroundSecondary,
7700
+ color: theme2.colors.text,
7701
+ border: `1px solid ${theme2.colors.border}`,
7702
+ borderRadius: theme2.radii[2],
7703
+ padding: "6px 12px",
7704
+ fontSize: theme2.fontSizes[1],
7705
+ fontWeight: theme2.fontWeights.medium,
7069
7706
  cursor: activeTasksState.isLoadingMore ? "wait" : "pointer",
7070
7707
  opacity: activeTasksState.isLoadingMore ? 0.7 : 1,
7071
7708
  transition: "opacity 0.2s ease"
@@ -7247,6 +7884,17 @@ const KanbanPanelContent = ({
7247
7884
  )
7248
7885
  ]
7249
7886
  }
7887
+ ),
7888
+ /* @__PURE__ */ jsx(
7889
+ TaskModal,
7890
+ {
7891
+ isOpen: isTaskModalOpen,
7892
+ onClose: handleCloseTaskModal,
7893
+ onSave: handleSaveTask,
7894
+ task: editingTask,
7895
+ defaultStatus: "To Do",
7896
+ availableStatuses
7897
+ }
7250
7898
  )
7251
7899
  ]
7252
7900
  }
@@ -51590,6 +52238,7 @@ function useMilestoneData(options) {
51590
52238
  const [isLoading, setIsLoading] = useState(true);
51591
52239
  const [error, setError] = useState(null);
51592
52240
  const [isBacklogProject, setIsBacklogProject] = useState(false);
52241
+ const [canWrite, setCanWrite] = useState(false);
51593
52242
  const coreRef = useRef(null);
51594
52243
  const activeFilePathRef = useRef(null);
51595
52244
  const contextRef = useRef(context);
@@ -51629,7 +52278,7 @@ function useMilestoneData(options) {
51629
52278
  }, []);
51630
52279
  const fileTreeVersionRef = useRef(null);
51631
52280
  const loadMilestoneData = useCallback(async () => {
51632
- var _a, _b;
52281
+ var _a, _b, _c;
51633
52282
  if (!context || !actions) {
51634
52283
  console.log("[useMilestoneData] No context provided");
51635
52284
  setIsBacklogProject(false);
@@ -51661,7 +52310,8 @@ function useMilestoneData(options) {
51661
52310
  const filePaths = files.map((f) => f.path);
51662
52311
  const fs = new PanelFileSystemAdapter({
51663
52312
  fetchFile: fetchFileContent,
51664
- filePaths
52313
+ filePaths,
52314
+ hostFileSystem: (_c = context.adapters) == null ? void 0 : _c.fileSystem
51665
52315
  });
51666
52316
  const core2 = new Core({
51667
52317
  projectRoot: "",
@@ -51677,6 +52327,7 @@ function useMilestoneData(options) {
51677
52327
  }
51678
52328
  console.log("[useMilestoneData] Loading milestone data...");
51679
52329
  setIsBacklogProject(true);
52330
+ setCanWrite(fs.canWrite);
51680
52331
  await core2.initializeLazy(filePaths);
51681
52332
  coreRef.current = core2;
51682
52333
  console.log("[useMilestoneData] Core instance:", core2);
@@ -51784,7 +52435,10 @@ function useMilestoneData(options) {
51784
52435
  expandMilestone,
51785
52436
  collapseMilestone,
51786
52437
  toggleMilestone,
51787
- refreshData
52438
+ refreshData,
52439
+ // Write support
52440
+ canWrite,
52441
+ core: coreRef.current
51788
52442
  };
51789
52443
  }
51790
52444
  const MilestoneCard = ({
@@ -52137,6 +52791,307 @@ const MilestoneCard = ({
52137
52791
  }
52138
52792
  );
52139
52793
  };
52794
+ const MilestoneModal = ({
52795
+ isOpen,
52796
+ onClose,
52797
+ onSave,
52798
+ milestone
52799
+ }) => {
52800
+ const { theme: theme2 } = useTheme();
52801
+ const isEditing = !!milestone;
52802
+ const [title, setTitle] = useState("");
52803
+ const [description, setDescription] = useState("");
52804
+ const [isSaving, setIsSaving] = useState(false);
52805
+ const [error, setError] = useState(null);
52806
+ useEffect(() => {
52807
+ if (isOpen) {
52808
+ if (milestone) {
52809
+ setTitle(milestone.title || "");
52810
+ setDescription(milestone.description || "");
52811
+ } else {
52812
+ setTitle("");
52813
+ setDescription("");
52814
+ }
52815
+ setError(null);
52816
+ }
52817
+ }, [isOpen, milestone]);
52818
+ const handleSubmit = async (e) => {
52819
+ e.preventDefault();
52820
+ if (!title.trim()) {
52821
+ setError("Title is required");
52822
+ return;
52823
+ }
52824
+ setIsSaving(true);
52825
+ setError(null);
52826
+ try {
52827
+ if (isEditing) {
52828
+ const input = {
52829
+ title: title.trim(),
52830
+ description: description.trim() || void 0
52831
+ };
52832
+ await onSave(input);
52833
+ } else {
52834
+ const input = {
52835
+ title: title.trim(),
52836
+ description: description.trim() || void 0
52837
+ };
52838
+ await onSave(input);
52839
+ }
52840
+ onClose();
52841
+ } catch (err) {
52842
+ setError(err instanceof Error ? err.message : "Failed to save milestone");
52843
+ } finally {
52844
+ setIsSaving(false);
52845
+ }
52846
+ };
52847
+ if (!isOpen) return null;
52848
+ const modalContent = /* @__PURE__ */ jsxs(
52849
+ "div",
52850
+ {
52851
+ style: {
52852
+ position: "fixed",
52853
+ inset: 0,
52854
+ zIndex: 9999,
52855
+ display: "flex",
52856
+ alignItems: "center",
52857
+ justifyContent: "center",
52858
+ padding: "16px"
52859
+ },
52860
+ children: [
52861
+ /* @__PURE__ */ jsx(
52862
+ "div",
52863
+ {
52864
+ onClick: onClose,
52865
+ style: {
52866
+ position: "absolute",
52867
+ inset: 0,
52868
+ backgroundColor: "rgba(0, 0, 0, 0.5)"
52869
+ }
52870
+ }
52871
+ ),
52872
+ /* @__PURE__ */ jsxs(
52873
+ "div",
52874
+ {
52875
+ style: {
52876
+ position: "relative",
52877
+ width: "100%",
52878
+ maxWidth: "500px",
52879
+ maxHeight: "90vh",
52880
+ overflow: "auto",
52881
+ backgroundColor: theme2.colors.background,
52882
+ borderRadius: theme2.radii[3],
52883
+ boxShadow: "0 25px 50px -12px rgba(0, 0, 0, 0.25)",
52884
+ border: `1px solid ${theme2.colors.border}`
52885
+ },
52886
+ children: [
52887
+ /* @__PURE__ */ jsxs(
52888
+ "div",
52889
+ {
52890
+ style: {
52891
+ display: "flex",
52892
+ alignItems: "center",
52893
+ justifyContent: "space-between",
52894
+ padding: "16px 20px",
52895
+ borderBottom: `1px solid ${theme2.colors.border}`
52896
+ },
52897
+ children: [
52898
+ /* @__PURE__ */ jsx(
52899
+ "h2",
52900
+ {
52901
+ style: {
52902
+ margin: 0,
52903
+ fontSize: theme2.fontSizes[4],
52904
+ fontWeight: 600,
52905
+ color: theme2.colors.text
52906
+ },
52907
+ children: isEditing ? "Edit Milestone" : "New Milestone"
52908
+ }
52909
+ ),
52910
+ /* @__PURE__ */ jsx(
52911
+ "button",
52912
+ {
52913
+ onClick: onClose,
52914
+ style: {
52915
+ background: "none",
52916
+ border: "none",
52917
+ cursor: "pointer",
52918
+ padding: "4px",
52919
+ display: "flex",
52920
+ alignItems: "center",
52921
+ justifyContent: "center",
52922
+ borderRadius: theme2.radii[1],
52923
+ color: theme2.colors.textMuted
52924
+ },
52925
+ children: /* @__PURE__ */ jsx(X, { size: 20 })
52926
+ }
52927
+ )
52928
+ ]
52929
+ }
52930
+ ),
52931
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, children: [
52932
+ /* @__PURE__ */ jsxs("div", { style: { padding: "20px", display: "flex", flexDirection: "column", gap: "16px" }, children: [
52933
+ /* @__PURE__ */ jsxs("div", { children: [
52934
+ /* @__PURE__ */ jsx(
52935
+ "label",
52936
+ {
52937
+ style: {
52938
+ display: "block",
52939
+ marginBottom: "6px",
52940
+ fontSize: theme2.fontSizes[1],
52941
+ fontWeight: 500,
52942
+ color: theme2.colors.text
52943
+ },
52944
+ children: "Title *"
52945
+ }
52946
+ ),
52947
+ /* @__PURE__ */ jsx(
52948
+ "input",
52949
+ {
52950
+ type: "text",
52951
+ value: title,
52952
+ onChange: (e) => setTitle(e.target.value),
52953
+ placeholder: "Enter milestone title",
52954
+ autoFocus: true,
52955
+ style: {
52956
+ width: "100%",
52957
+ padding: "10px 12px",
52958
+ fontSize: theme2.fontSizes[2],
52959
+ border: `1px solid ${theme2.colors.border}`,
52960
+ borderRadius: theme2.radii[2],
52961
+ backgroundColor: theme2.colors.backgroundSecondary,
52962
+ color: theme2.colors.text,
52963
+ outline: "none",
52964
+ boxSizing: "border-box"
52965
+ }
52966
+ }
52967
+ )
52968
+ ] }),
52969
+ /* @__PURE__ */ jsxs("div", { children: [
52970
+ /* @__PURE__ */ jsx(
52971
+ "label",
52972
+ {
52973
+ style: {
52974
+ display: "block",
52975
+ marginBottom: "6px",
52976
+ fontSize: theme2.fontSizes[1],
52977
+ fontWeight: 500,
52978
+ color: theme2.colors.text
52979
+ },
52980
+ children: "Description"
52981
+ }
52982
+ ),
52983
+ /* @__PURE__ */ jsx(
52984
+ "textarea",
52985
+ {
52986
+ value: description,
52987
+ onChange: (e) => setDescription(e.target.value),
52988
+ placeholder: "Enter milestone description (markdown supported)",
52989
+ rows: 4,
52990
+ style: {
52991
+ width: "100%",
52992
+ padding: "10px 12px",
52993
+ fontSize: theme2.fontSizes[2],
52994
+ border: `1px solid ${theme2.colors.border}`,
52995
+ borderRadius: theme2.radii[2],
52996
+ backgroundColor: theme2.colors.backgroundSecondary,
52997
+ color: theme2.colors.text,
52998
+ outline: "none",
52999
+ resize: "vertical",
53000
+ fontFamily: theme2.fonts.body,
53001
+ boxSizing: "border-box"
53002
+ }
53003
+ }
53004
+ )
53005
+ ] }),
53006
+ error && /* @__PURE__ */ jsx(
53007
+ "div",
53008
+ {
53009
+ style: {
53010
+ padding: "10px 12px",
53011
+ backgroundColor: `${theme2.colors.error}15`,
53012
+ border: `1px solid ${theme2.colors.error}`,
53013
+ borderRadius: theme2.radii[2],
53014
+ color: theme2.colors.error,
53015
+ fontSize: theme2.fontSizes[1]
53016
+ },
53017
+ children: error
53018
+ }
53019
+ )
53020
+ ] }),
53021
+ /* @__PURE__ */ jsxs(
53022
+ "div",
53023
+ {
53024
+ style: {
53025
+ display: "flex",
53026
+ justifyContent: "flex-end",
53027
+ gap: "12px",
53028
+ padding: "16px 20px",
53029
+ borderTop: `1px solid ${theme2.colors.border}`
53030
+ },
53031
+ children: [
53032
+ /* @__PURE__ */ jsx(
53033
+ "button",
53034
+ {
53035
+ type: "button",
53036
+ onClick: onClose,
53037
+ disabled: isSaving,
53038
+ style: {
53039
+ padding: "10px 20px",
53040
+ fontSize: theme2.fontSizes[2],
53041
+ fontWeight: 500,
53042
+ border: `1px solid ${theme2.colors.border}`,
53043
+ borderRadius: theme2.radii[2],
53044
+ backgroundColor: "transparent",
53045
+ color: theme2.colors.text,
53046
+ cursor: "pointer"
53047
+ },
53048
+ children: "Cancel"
53049
+ }
53050
+ ),
53051
+ /* @__PURE__ */ jsxs(
53052
+ "button",
53053
+ {
53054
+ type: "submit",
53055
+ disabled: isSaving,
53056
+ style: {
53057
+ display: "flex",
53058
+ alignItems: "center",
53059
+ gap: "8px",
53060
+ padding: "10px 20px",
53061
+ fontSize: theme2.fontSizes[2],
53062
+ fontWeight: 500,
53063
+ border: "none",
53064
+ borderRadius: theme2.radii[2],
53065
+ backgroundColor: theme2.colors.primary,
53066
+ color: "#fff",
53067
+ cursor: isSaving ? "wait" : "pointer",
53068
+ opacity: isSaving ? 0.7 : 1
53069
+ },
53070
+ children: [
53071
+ isSaving && /* @__PURE__ */ jsx(LoaderCircle, { size: 16, style: { animation: "spin 1s linear infinite" } }),
53072
+ isEditing ? "Save Changes" : "Create Milestone"
53073
+ ]
53074
+ }
53075
+ )
53076
+ ]
53077
+ }
53078
+ )
53079
+ ] })
53080
+ ]
53081
+ }
53082
+ ),
53083
+ /* @__PURE__ */ jsx("style", { children: `
53084
+ @keyframes spin {
53085
+ from { transform: rotate(0deg); }
53086
+ to { transform: rotate(360deg); }
53087
+ }
53088
+ ` })
53089
+ ]
53090
+ }
53091
+ );
53092
+ if (typeof document === "undefined") return null;
53093
+ return createPortal(modalContent, document.body);
53094
+ };
52140
53095
  const MilestonePanelContent = ({
52141
53096
  context,
52142
53097
  actions,
@@ -52144,13 +53099,17 @@ const MilestonePanelContent = ({
52144
53099
  }) => {
52145
53100
  const { theme: theme2 } = useTheme();
52146
53101
  const [isRefreshing, setIsRefreshing] = useState(false);
53102
+ const [isMilestoneModalOpen, setIsMilestoneModalOpen] = useState(false);
53103
+ const [editingMilestone, setEditingMilestone] = useState(void 0);
52147
53104
  const {
52148
53105
  milestones,
52149
53106
  isLoading,
52150
53107
  error,
52151
53108
  isBacklogProject,
52152
53109
  toggleMilestone,
52153
- refreshData
53110
+ refreshData,
53111
+ canWrite,
53112
+ core: core2
52154
53113
  } = useMilestoneData({
52155
53114
  context,
52156
53115
  actions
@@ -52173,6 +53132,29 @@ const MilestonePanelContent = ({
52173
53132
  setIsRefreshing(false);
52174
53133
  }
52175
53134
  };
53135
+ const handleOpenNewMilestone = useCallback(() => {
53136
+ setEditingMilestone(void 0);
53137
+ setIsMilestoneModalOpen(true);
53138
+ }, []);
53139
+ useCallback((milestone) => {
53140
+ setEditingMilestone(milestone);
53141
+ setIsMilestoneModalOpen(true);
53142
+ }, []);
53143
+ const handleCloseMilestoneModal = useCallback(() => {
53144
+ setIsMilestoneModalOpen(false);
53145
+ setEditingMilestone(void 0);
53146
+ }, []);
53147
+ const handleSaveMilestone = useCallback(async (input) => {
53148
+ if (!core2) {
53149
+ throw new Error("Backlog not loaded");
53150
+ }
53151
+ if (editingMilestone) {
53152
+ await core2.updateMilestone(editingMilestone.id, input);
53153
+ } else {
53154
+ await core2.createMilestone(input);
53155
+ }
53156
+ await refreshData();
53157
+ }, [core2, editingMilestone, refreshData]);
52176
53158
  const totalMilestones = milestones.length;
52177
53159
  const totalTasks = milestones.reduce((sum, m) => sum + m.milestone.tasks.length, 0);
52178
53160
  return /* @__PURE__ */ jsxs(
@@ -52239,6 +53221,30 @@ const MilestonePanelContent = ({
52239
53221
  ]
52240
53222
  }
52241
53223
  ),
53224
+ canWrite && /* @__PURE__ */ jsxs(
53225
+ "button",
53226
+ {
53227
+ onClick: handleOpenNewMilestone,
53228
+ style: {
53229
+ display: "flex",
53230
+ alignItems: "center",
53231
+ gap: "6px",
53232
+ background: theme2.colors.primary,
53233
+ color: theme2.colors.background,
53234
+ border: "none",
53235
+ borderRadius: theme2.radii[2],
53236
+ padding: "6px 12px",
53237
+ fontSize: theme2.fontSizes[1],
53238
+ fontWeight: theme2.fontWeights.medium,
53239
+ cursor: "pointer",
53240
+ transition: "opacity 0.2s ease"
53241
+ },
53242
+ children: [
53243
+ /* @__PURE__ */ jsx(Plus, { size: 14 }),
53244
+ "Add Milestone"
53245
+ ]
53246
+ }
53247
+ ),
52242
53248
  /* @__PURE__ */ jsx(
52243
53249
  "button",
52244
53250
  {
@@ -52373,7 +53379,16 @@ const MilestonePanelContent = ({
52373
53379
  @keyframes spin {
52374
53380
  to { transform: rotate(360deg); }
52375
53381
  }
52376
- ` })
53382
+ ` }),
53383
+ /* @__PURE__ */ jsx(
53384
+ MilestoneModal,
53385
+ {
53386
+ isOpen: isMilestoneModalOpen,
53387
+ onClose: handleCloseMilestoneModal,
53388
+ onSave: handleSaveMilestone,
53389
+ milestone: editingMilestone
53390
+ }
53391
+ )
52377
53392
  ]
52378
53393
  }
52379
53394
  );