@openspecui/web 2.1.0 → 2.1.1

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 (56) hide show
  1. package/dist/assets/{BufferResource-WPSrP4iZ.js → BufferResource-CSbEbiLP.js} +1 -1
  2. package/dist/assets/{CanvasRenderer-yL0hHLLA.js → CanvasRenderer-CvpAMPzA.js} +1 -1
  3. package/dist/assets/{Filter-MPAI5-Oj.js → Filter-BqwVCa6B.js} +1 -1
  4. package/dist/assets/{RenderTargetSystem-D4qtRaUW.js → RenderTargetSystem-mD_Y2dUA.js} +1 -1
  5. package/dist/assets/{WebGLRenderer-BHfrXEBc.js → WebGLRenderer-DsvDwXyL.js} +1 -1
  6. package/dist/assets/{WebGPURenderer-DE5Q1Ilu.js → WebGPURenderer-YcBYXAol.js} +1 -1
  7. package/dist/assets/{browserAll-qg0ACMg1.js → browserAll-MbWxSnea.js} +1 -1
  8. package/dist/assets/{ghostty-web-D1cPLYOq.js → ghostty-web-cM8zjOdb.js} +1 -1
  9. package/dist/assets/{index-BQWvXpvf.js → index-B0lABsCj.js} +1 -1
  10. package/dist/assets/{index-D7oe-Hg-.js → index-B1J3yPM2.js} +1 -1
  11. package/dist/assets/{index-BEpMDdcu.js → index-BCMJS8eq.js} +1 -1
  12. package/dist/assets/{index-C8igR5_C.js → index-BMKX_bGe.js} +1 -1
  13. package/dist/assets/{index-BTEmB46j.js → index-BY40EQxT.js} +1 -1
  14. package/dist/assets/{index-BLmH2_gh.js → index-Cq4njHD4.js} +183 -182
  15. package/dist/assets/{index-DlK0frtF.js → index-Cr4OFm9E.js} +1 -1
  16. package/dist/assets/{index-DBI0U-_m.js → index-CskIUxS-.js} +1 -1
  17. package/dist/assets/{index-B2AIdjev.js → index-D0sXMPhu.js} +1 -1
  18. package/dist/assets/{index-D1IhiEyy.css → index-DHeR2UYq.css} +1 -1
  19. package/dist/assets/{index-DfNI0fNY.js → index-DijRYB99.js} +1 -1
  20. package/dist/assets/{index-Gknjn7E7.js → index-DuZDcW_P.js} +1 -1
  21. package/dist/assets/{index-DYz8XhtF.js → index-DyZwNTgF.js} +1 -1
  22. package/dist/assets/{index-BM_5Tg9c.js → index-JHrsE4PU.js} +1 -1
  23. package/dist/assets/{index-CQRaC2Gn.js → index-KaodXPu0.js} +1 -1
  24. package/dist/assets/{index-DMpt0Kcu.js → index-TGQYcfbH.js} +1 -1
  25. package/dist/assets/{index-CSledjj-.js → index-kjHuAdn9.js} +1 -1
  26. package/dist/assets/{webworkerAll-iHUuedbL.js → webworkerAll-BE_Ec3Rk.js} +1 -1
  27. package/dist/index.html +2 -2
  28. package/dist-ssg/client/.vite/ssr-manifest.json +194 -191
  29. package/dist-ssg/client/assets/{BufferResource-D81lYMLT.js → BufferResource-BXAwYrfZ.js} +1 -1
  30. package/dist-ssg/client/assets/{CanvasRenderer-BYIOuB-u.js → CanvasRenderer-C-_Ei4Lx.js} +1 -1
  31. package/dist-ssg/client/assets/{Filter-CeoA-Hyu.js → Filter-ClWz3L4e.js} +1 -1
  32. package/dist-ssg/client/assets/{RenderTargetSystem-DXG3rON5.js → RenderTargetSystem-mkoEDW34.js} +1 -1
  33. package/dist-ssg/client/assets/{WebGLRenderer-C8QtcPPE.js → WebGLRenderer-D-p2Wvph.js} +1 -1
  34. package/dist-ssg/client/assets/{WebGPURenderer-TSulBBlS.js → WebGPURenderer-CnUVPIau.js} +1 -1
  35. package/dist-ssg/client/assets/{browserAll-wG5chgko.js → browserAll-DIrSCRrR.js} +1 -1
  36. package/dist-ssg/client/assets/{index-BGCX0p5r.js → index-4SYwcH9o.js} +1 -1
  37. package/dist-ssg/client/assets/{index-C8IGL6vM.js → index-9dzaV4-3.js} +1 -1
  38. package/dist-ssg/client/assets/{index-CjyblKoL.css → index-Brg9wIKi.css} +1 -1
  39. package/dist-ssg/client/assets/{index-bGllGkV0.js → index-BxqwPwCo.js} +1 -1
  40. package/dist-ssg/client/assets/{index-rbH3brrb.js → index-C3Zu70mc.js} +1 -1
  41. package/dist-ssg/client/assets/{index-DK_U1_Lh.js → index-CGYcF9cy.js} +1 -1
  42. package/dist-ssg/client/assets/{index-BW2CaBe9.js → index-D9vFOR1x.js} +1 -1
  43. package/dist-ssg/client/assets/{index-DuZ0AKLC.js → index-DGZY9q7K.js} +1 -1
  44. package/dist-ssg/client/assets/{index-DqMkjeUD.js → index-DH_3Uwqw.js} +1 -1
  45. package/dist-ssg/client/assets/{index-BPcWtlCR.js → index-DM-IE6Il.js} +1 -1
  46. package/dist-ssg/client/assets/{index-DMCE4Kkm.js → index-DMf28vE-.js} +1 -1
  47. package/dist-ssg/client/assets/{index-CtoDt3iY.js → index-I6EcgPnl.js} +1 -1
  48. package/dist-ssg/client/assets/{index-D4YbeFcQ.js → index-R53t0sC8.js} +1 -1
  49. package/dist-ssg/client/assets/{index-BRKO5Axs.js → index-fIJERjSL.js} +1 -1
  50. package/dist-ssg/client/assets/{index-DRGqIcc0.js → index-geNCH0rZ.js} +1 -1
  51. package/dist-ssg/client/assets/{index-Cj5wOcC4.js → index-zKBrZAkn.js} +1 -1
  52. package/dist-ssg/client/assets/{index.ssg-BCAZPCWG.js → index.ssg-7hLvM_9r.js} +190 -189
  53. package/dist-ssg/client/assets/{webworkerAll-DisB_v8s.js → webworkerAll-CysFfo0u.js} +1 -1
  54. package/dist-ssg/client/index.ssg.html +2 -2
  55. package/dist-ssg/server/entry-server.js +356 -84
  56. package/package.json +1 -1
@@ -1,4 +1,4 @@
1
- import{G as R,u as S,T as b,R as P,af as I,ab as B,aq as T,V as _,aJ as O,a1 as A,y as C,ap as E,a2 as k}from"./index.ssg-BCAZPCWG.js";import{F as z}from"./Filter-CeoA-Hyu.js";var U=`in vec2 aPosition;
1
+ import{G as R,u as S,T as b,R as P,af as I,ab as B,aq as T,V as _,aJ as O,a1 as A,y as C,ap as E,a2 as k}from"./index.ssg-7hLvM_9r.js";import{F as z}from"./Filter-ClWz3L4e.js";var U=`in vec2 aPosition;
2
2
  out vec2 vTextureCoord;
3
3
 
4
4
  uniform vec4 uInputSize;
@@ -35,8 +35,8 @@
35
35
  document.head.append(preconnectApi, preconnectStatic, stylesheet)
36
36
  })()
37
37
  </script>
38
- <script type="module" crossorigin src="/assets/index.ssg-BCAZPCWG.js"></script>
39
- <link rel="stylesheet" crossorigin href="/assets/index-CjyblKoL.css">
38
+ <script type="module" crossorigin src="/assets/index.ssg-7hLvM_9r.js"></script>
39
+ <link rel="stylesheet" crossorigin href="/assets/index-Brg9wIKi.css">
40
40
  </head>
41
41
  <body>
42
42
  <div id="root"><!--app-html--></div>
@@ -37033,23 +37033,23 @@ const createLucideIcon = (iconName, iconNode) => {
37033
37033
  Component.displayName = `${iconName}`;
37034
37034
  return Component;
37035
37035
  };
37036
- const __iconNode$R = [
37036
+ const __iconNode$S = [
37037
37037
  ["rect", { width: "20", height: "5", x: "2", y: "3", rx: "1", key: "1wp1u1" }],
37038
37038
  ["path", { d: "M4 8v11a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8", key: "1s80jp" }],
37039
37039
  ["path", { d: "M10 12h4", key: "a56b0p" }]
37040
37040
  ];
37041
- const Archive = createLucideIcon("Archive", __iconNode$R);
37042
- const __iconNode$Q = [
37041
+ const Archive = createLucideIcon("Archive", __iconNode$S);
37042
+ const __iconNode$R = [
37043
37043
  ["path", { d: "m12 19-7-7 7-7", key: "1l729n" }],
37044
37044
  ["path", { d: "M19 12H5", key: "x3x0zl" }]
37045
37045
  ];
37046
- const ArrowLeft = createLucideIcon("ArrowLeft", __iconNode$Q);
37047
- const __iconNode$P = [
37046
+ const ArrowLeft = createLucideIcon("ArrowLeft", __iconNode$R);
37047
+ const __iconNode$Q = [
37048
37048
  ["path", { d: "M5 12h14", key: "1ays0h" }],
37049
37049
  ["path", { d: "m12 5 7 7-7 7", key: "xquz4c" }]
37050
37050
  ];
37051
- const ArrowRight = createLucideIcon("ArrowRight", __iconNode$P);
37052
- const __iconNode$O = [
37051
+ const ArrowRight = createLucideIcon("ArrowRight", __iconNode$Q);
37052
+ const __iconNode$P = [
37053
37053
  [
37054
37054
  "path",
37055
37055
  {
@@ -37059,68 +37059,79 @@ const __iconNode$O = [
37059
37059
  ],
37060
37060
  ["circle", { cx: "12", cy: "13", r: "3", key: "1vg3eu" }]
37061
37061
  ];
37062
- const Camera = createLucideIcon("Camera", __iconNode$O);
37063
- const __iconNode$N = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
37064
- const Check = createLucideIcon("Check", __iconNode$N);
37065
- const __iconNode$M = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
37066
- const ChevronDown = createLucideIcon("ChevronDown", __iconNode$M);
37067
- const __iconNode$L = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
37068
- const ChevronRight = createLucideIcon("ChevronRight", __iconNode$L);
37069
- const __iconNode$K = [
37062
+ const Camera = createLucideIcon("Camera", __iconNode$P);
37063
+ const __iconNode$O = [["path", { d: "M20 6 9 17l-5-5", key: "1gmf2c" }]];
37064
+ const Check = createLucideIcon("Check", __iconNode$O);
37065
+ const __iconNode$N = [["path", { d: "m6 9 6 6 6-6", key: "qrunsl" }]];
37066
+ const ChevronDown = createLucideIcon("ChevronDown", __iconNode$N);
37067
+ const __iconNode$M = [["path", { d: "m9 18 6-6-6-6", key: "mthhwq" }]];
37068
+ const ChevronRight = createLucideIcon("ChevronRight", __iconNode$M);
37069
+ const __iconNode$L = [
37070
37070
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
37071
37071
  ["line", { x1: "12", x2: "12", y1: "8", y2: "12", key: "1pkeuh" }],
37072
37072
  ["line", { x1: "12", x2: "12.01", y1: "16", y2: "16", key: "4dfq90" }]
37073
37073
  ];
37074
- const CircleAlert = createLucideIcon("CircleAlert", __iconNode$K);
37075
- const __iconNode$J = [
37074
+ const CircleAlert = createLucideIcon("CircleAlert", __iconNode$L);
37075
+ const __iconNode$K = [
37076
37076
  ["path", { d: "M21.801 10A10 10 0 1 1 17 3.335", key: "yps3ct" }],
37077
37077
  ["path", { d: "m9 11 3 3L22 4", key: "1pflzl" }]
37078
37078
  ];
37079
- const CircleCheckBig = createLucideIcon("CircleCheckBig", __iconNode$J);
37080
- const __iconNode$I = [
37079
+ const CircleCheckBig = createLucideIcon("CircleCheckBig", __iconNode$K);
37080
+ const __iconNode$J = [
37081
37081
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
37082
37082
  ["path", { d: "m9 12 2 2 4-4", key: "dzmm74" }]
37083
37083
  ];
37084
- const CircleCheck = createLucideIcon("CircleCheck", __iconNode$I);
37085
- const __iconNode$H = [
37084
+ const CircleCheck = createLucideIcon("CircleCheck", __iconNode$J);
37085
+ const __iconNode$I = [
37086
37086
  ["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }],
37087
37087
  ["path", { d: "m15 9-6 6", key: "1uzhvr" }],
37088
37088
  ["path", { d: "m9 9 6 6", key: "z0biqf" }]
37089
37089
  ];
37090
- const CircleX = createLucideIcon("CircleX", __iconNode$H);
37091
- const __iconNode$G = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
37092
- const Circle$1 = createLucideIcon("Circle", __iconNode$G);
37093
- const __iconNode$F = [
37090
+ const CircleX = createLucideIcon("CircleX", __iconNode$I);
37091
+ const __iconNode$H = [["circle", { cx: "12", cy: "12", r: "10", key: "1mglay" }]];
37092
+ const Circle$1 = createLucideIcon("Circle", __iconNode$H);
37093
+ const __iconNode$G = [
37094
37094
  ["rect", { width: "14", height: "14", x: "8", y: "8", rx: "2", ry: "2", key: "17jyea" }],
37095
37095
  ["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" }]
37096
37096
  ];
37097
- const Copy = createLucideIcon("Copy", __iconNode$F);
37098
- const __iconNode$E = [
37097
+ const Copy = createLucideIcon("Copy", __iconNode$G);
37098
+ const __iconNode$F = [
37099
37099
  ["circle", { cx: "12", cy: "12", r: "1", key: "41hilf" }],
37100
37100
  ["circle", { cx: "12", cy: "5", r: "1", key: "gxeob9" }],
37101
37101
  ["circle", { cx: "12", cy: "19", r: "1", key: "lyex9k" }]
37102
37102
  ];
37103
- const EllipsisVertical = createLucideIcon("EllipsisVertical", __iconNode$E);
37104
- const __iconNode$D = [
37103
+ const EllipsisVertical = createLucideIcon("EllipsisVertical", __iconNode$F);
37104
+ const __iconNode$E = [
37105
37105
  ["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
37106
37106
  ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
37107
37107
  ["path", { d: "M9 15h6", key: "cctwl0" }],
37108
37108
  ["path", { d: "M12 18v-6", key: "17g6i2" }]
37109
37109
  ];
37110
- const FilePlus = createLucideIcon("FilePlus", __iconNode$D);
37111
- const __iconNode$C = [
37110
+ const FilePlus = createLucideIcon("FilePlus", __iconNode$E);
37111
+ const __iconNode$D = [
37112
37112
  ["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
37113
37113
  ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }],
37114
37114
  ["path", { d: "M10 9H8", key: "b1mrlr" }],
37115
37115
  ["path", { d: "M16 13H8", key: "t4e002" }],
37116
37116
  ["path", { d: "M16 17H8", key: "z1uh3a" }]
37117
37117
  ];
37118
- const FileText = createLucideIcon("FileText", __iconNode$C);
37119
- const __iconNode$B = [
37118
+ const FileText = createLucideIcon("FileText", __iconNode$D);
37119
+ const __iconNode$C = [
37120
37120
  ["path", { d: "M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z", key: "1rqfz7" }],
37121
37121
  ["path", { d: "M14 2v4a2 2 0 0 0 2 2h4", key: "tnqrlb" }]
37122
37122
  ];
37123
- const File = createLucideIcon("File", __iconNode$B);
37123
+ const File = createLucideIcon("File", __iconNode$C);
37124
+ const __iconNode$B = [
37125
+ [
37126
+ "path",
37127
+ {
37128
+ d: "m6 14 1.45-2.9A2 2 0 0 1 9.24 10H20a2 2 0 0 1 1.94 2.5l-1.55 6a2 2 0 0 1-1.94 1.5H4a2 2 0 0 1-2-2V5c0-1.1.9-2 2-2h3.93a2 2 0 0 1 1.66.9l.82 1.2a2 2 0 0 0 1.66.9H18a2 2 0 0 1 2 2v2",
37129
+ key: "1nmvlm"
37130
+ }
37131
+ ],
37132
+ ["circle", { cx: "14", cy: "15", r: "1", key: "1gm4qj" }]
37133
+ ];
37134
+ const FolderOpenDot = createLucideIcon("FolderOpenDot", __iconNode$B);
37124
37135
  const __iconNode$A = [
37125
37136
  [
37126
37137
  "path",
@@ -37459,7 +37470,7 @@ const navItems = allNavItems.filter(
37459
37470
  );
37460
37471
  const mobileNavItems = allNavItems.filter((i3) => i3.to !== "/settings");
37461
37472
  const settingsItem = allNavItems.find((i3) => i3.to === "/settings");
37462
- let _draggedTabId = null;
37473
+ let _draggedTabId$1 = null;
37463
37474
  function AreaNav({ area: area2, tabs, className, useLinks, onNavigate }) {
37464
37475
  const [dragOverArea, setDragOverArea] = reactExports.useState(false);
37465
37476
  const [dropIndicator, setDropIndicator] = reactExports.useState(null);
@@ -37477,12 +37488,12 @@ function AreaNav({ area: area2, tabs, className, useLinks, onNavigate }) {
37477
37488
  );
37478
37489
  const handleDragStart = reactExports.useCallback((e2, tabId) => {
37479
37490
  if (!e2.dataTransfer) return;
37480
- _draggedTabId = tabId;
37491
+ _draggedTabId$1 = tabId;
37481
37492
  e2.dataTransfer.setData("text/plain", tabId);
37482
37493
  e2.dataTransfer.effectAllowed = "move";
37483
37494
  }, []);
37484
37495
  const handleDragEnd = reactExports.useCallback(() => {
37485
- _draggedTabId = null;
37496
+ _draggedTabId$1 = null;
37486
37497
  }, []);
37487
37498
  const handleAreaDragOver = reactExports.useCallback((e2) => {
37488
37499
  e2.preventDefault();
@@ -37503,7 +37514,7 @@ function AreaNav({ area: area2, tabs, className, useLinks, onNavigate }) {
37503
37514
  e2.preventDefault();
37504
37515
  e2.stopPropagation();
37505
37516
  e2.dataTransfer.dropEffect = "move";
37506
- if (tabs[index2] === _draggedTabId) {
37517
+ if (tabs[index2] === _draggedTabId$1) {
37507
37518
  updateIndicator(null);
37508
37519
  return;
37509
37520
  }
@@ -37522,7 +37533,7 @@ function AreaNav({ area: area2, tabs, className, useLinks, onNavigate }) {
37522
37533
  const indicator = dropIndicatorRef.current;
37523
37534
  setDragOverArea(false);
37524
37535
  updateIndicator(null);
37525
- _draggedTabId = null;
37536
+ _draggedTabId$1 = null;
37526
37537
  if (!tabId) return;
37527
37538
  const isFromThisArea = tabs.includes(tabId);
37528
37539
  const targetTab = indicator != null ? tabs[indicator.index] : void 0;
@@ -47961,6 +47972,7 @@ function buildStaticGitSnapshot(snapshot) {
47961
47972
  path: repositoryUrl ?? "Repository URL unavailable",
47962
47973
  relativePath: "repo",
47963
47974
  branchName: "(snapshot)",
47975
+ detached: false,
47964
47976
  isCurrent: true,
47965
47977
  ahead: 0,
47966
47978
  behind: 0,
@@ -72445,6 +72457,7 @@ const viewerStyles = css$2`
72445
72457
  }
72446
72458
  }
72447
72459
  `;
72460
+ let _draggedTabId = null;
72448
72461
  const tabsStyle = (id2) => {
72449
72462
  const css2 = String.raw;
72450
72463
  const anchorName = `--tabs-button-${id2}`;
@@ -72518,37 +72531,164 @@ const tabsStyle = (id2) => {
72518
72531
  }
72519
72532
  ` });
72520
72533
  };
72534
+ function buildReorderedTabIds(currentTabIds, draggedTabId, targetTabId, position2) {
72535
+ if (draggedTabId === targetTabId) {
72536
+ return [...currentTabIds];
72537
+ }
72538
+ const remaining = currentTabIds.filter((tabId) => tabId !== draggedTabId);
72539
+ const targetIndex = remaining.indexOf(targetTabId);
72540
+ if (targetIndex < 0) {
72541
+ return [...currentTabIds];
72542
+ }
72543
+ const insertIndex = position2 === "before" ? targetIndex : targetIndex + 1;
72544
+ remaining.splice(insertIndex, 0, draggedTabId);
72545
+ return remaining;
72546
+ }
72547
+ function buildStableContentTabIds(previousTabIds, currentTabIds) {
72548
+ const currentTabIdSet = new Set(currentTabIds);
72549
+ const retained = previousTabIds.filter((tabId) => currentTabIdSet.has(tabId));
72550
+ const additions = currentTabIds.filter((tabId) => !retained.includes(tabId));
72551
+ return [...retained, ...additions];
72552
+ }
72521
72553
  function Tabs({
72522
72554
  tabs,
72523
72555
  selectedTab: controlled,
72524
72556
  onTabChange,
72525
72557
  onTabClose,
72558
+ onTabOrderChange,
72526
72559
  actions,
72527
72560
  onTabBarDoubleClick,
72528
72561
  className = "",
72529
72562
  variant = "default"
72530
72563
  }) {
72531
72564
  const [uncontrolled, setUncontrolled] = reactExports.useState(tabs[0]?.id ?? "");
72565
+ const [dropIndicator, setDropIndicator] = reactExports.useState(null);
72566
+ const dropIndicatorRef = reactExports.useRef(null);
72567
+ const contentOrderRef = reactExports.useRef(tabs.map((tab2) => tab2.id));
72532
72568
  const activeTab = controlled ?? uncontrolled;
72569
+ const reorderable = typeof onTabOrderChange === "function" && tabs.length > 1;
72570
+ const tabIds = tabs.map((tab2) => tab2.id);
72571
+ const tabsById = reactExports.useMemo(() => new Map(tabs.map((tab2) => [tab2.id, tab2])), [tabs]);
72572
+ const contentTabIds = reactExports.useMemo(() => {
72573
+ const nextOrder = buildStableContentTabIds(contentOrderRef.current, tabIds);
72574
+ contentOrderRef.current = nextOrder;
72575
+ return nextOrder;
72576
+ }, [tabIds]);
72577
+ const contentTabs = contentTabIds.map((tabId) => tabsById.get(tabId)).filter((tab2) => tab2 !== void 0);
72578
+ const id2 = reactExports.useId();
72579
+ const style = reactExports.useMemo(() => tabsStyle(id2), [id2]);
72533
72580
  const handleChange = (id22) => {
72534
72581
  if (!controlled) {
72535
72582
  setUncontrolled(id22);
72536
72583
  }
72537
72584
  onTabChange?.(id22);
72538
72585
  };
72586
+ const updateIndicator = reactExports.useCallback((indicator) => {
72587
+ dropIndicatorRef.current = indicator;
72588
+ setDropIndicator(indicator);
72589
+ }, []);
72590
+ const resetDragState = reactExports.useCallback(() => {
72591
+ _draggedTabId = null;
72592
+ updateIndicator(null);
72593
+ }, [updateIndicator]);
72594
+ const commitReorder = reactExports.useCallback(
72595
+ (targetTabId, position2) => {
72596
+ if (!reorderable || !_draggedTabId) {
72597
+ return;
72598
+ }
72599
+ const nextTabIds = buildReorderedTabIds(tabIds, _draggedTabId, targetTabId, position2);
72600
+ const changed = nextTabIds.some((tabId, index2) => tabId !== tabIds[index2]);
72601
+ if (changed) {
72602
+ onTabOrderChange?.(nextTabIds);
72603
+ }
72604
+ },
72605
+ [onTabOrderChange, reorderable, tabIds]
72606
+ );
72607
+ const handleDragStart = reactExports.useCallback(
72608
+ (event, tabId) => {
72609
+ if (!reorderable || !event.dataTransfer) {
72610
+ return;
72611
+ }
72612
+ _draggedTabId = tabId;
72613
+ event.dataTransfer.setData("text/plain", tabId);
72614
+ event.dataTransfer.effectAllowed = "move";
72615
+ },
72616
+ [reorderable]
72617
+ );
72618
+ const handleDragEnd = reactExports.useCallback(() => {
72619
+ resetDragState();
72620
+ }, [resetDragState]);
72621
+ const handleItemDragOver = reactExports.useCallback(
72622
+ (event, tabId) => {
72623
+ if (!reorderable || !_draggedTabId) {
72624
+ return;
72625
+ }
72626
+ event.preventDefault();
72627
+ event.stopPropagation();
72628
+ event.dataTransfer.dropEffect = "move";
72629
+ if (tabId === _draggedTabId) {
72630
+ updateIndicator(null);
72631
+ return;
72632
+ }
72633
+ const rect = event.currentTarget.getBoundingClientRect();
72634
+ const midX = rect.left + rect.width / 2;
72635
+ const position2 = event.clientX < midX ? "before" : "after";
72636
+ updateIndicator({ tabId, position: position2 });
72637
+ },
72638
+ [reorderable, updateIndicator]
72639
+ );
72640
+ const handleItemDrop = reactExports.useCallback(
72641
+ (event, tabId) => {
72642
+ if (!reorderable) {
72643
+ return;
72644
+ }
72645
+ event.preventDefault();
72646
+ event.stopPropagation();
72647
+ const indicator = dropIndicatorRef.current;
72648
+ commitReorder(tabId, indicator?.tabId === tabId ? indicator.position : "after");
72649
+ resetDragState();
72650
+ },
72651
+ [commitReorder, reorderable, resetDragState]
72652
+ );
72653
+ const handleListDrop = reactExports.useCallback(
72654
+ (event) => {
72655
+ if (!reorderable) {
72656
+ return;
72657
+ }
72658
+ event.preventDefault();
72659
+ if (_draggedTabId && dropIndicatorRef.current === null) {
72660
+ const remaining = tabIds.filter((tabId) => tabId !== _draggedTabId);
72661
+ remaining.push(_draggedTabId);
72662
+ const changed = remaining.some((tabId, index2) => tabId !== tabIds[index2]);
72663
+ if (changed) {
72664
+ onTabOrderChange?.(remaining);
72665
+ }
72666
+ }
72667
+ resetDragState();
72668
+ },
72669
+ [onTabOrderChange, reorderable, resetDragState, tabIds]
72670
+ );
72671
+ const handleListDragOver = reactExports.useCallback(
72672
+ (event) => {
72673
+ if (!reorderable || !_draggedTabId) {
72674
+ return;
72675
+ }
72676
+ event.preventDefault();
72677
+ event.dataTransfer.dropEffect = "move";
72678
+ },
72679
+ [reorderable]
72680
+ );
72539
72681
  if (tabs.length === 0) return null;
72540
- const id2 = reactExports.useId();
72541
- const style = reactExports.useMemo(() => tabsStyle(id2), [id2]);
72542
72682
  const headerClassName = variant === "terminal" ? "tabs-header z-2 bg-terminal text-terminal-foreground sticky top-0 flex min-w-0 items-stretch" : "tabs-header z-2 bg-background sticky top-0 flex min-w-0 items-stretch";
72543
72683
  const stripClassName = variant === "terminal" ? "tabs-strip min-w-0 flex-1 bg-terminal px-4" : "tabs-strip min-w-0 flex-1 px-4";
72544
- const listClassName = "tabs-button scrollbar-none flex min-w-0 gap-1 overflow-x-auto";
72545
- const buttonBaseClassName = `m-0 flex h-full shrink-0 items-center gap-2 px-2 py-2 text-sm font-medium transition-colors ${variant === "terminal" ? "rounded-t-[8px]" : ""}`;
72684
+ const listClassName = variant === "terminal" ? "tabs-button scrollbar-none flex min-w-0 gap-1 overflow-x-auto pt-2" : "tabs-button scrollbar-none flex min-w-0 gap-1 overflow-x-auto";
72685
+ const buttonBaseClassName = `group relative m-0 flex h-full shrink-0 items-center gap-2 px-2 text-sm font-medium transition-colors ${variant === "terminal" ? "rounded-t-[8px] py-1" : "py-2"}`;
72546
72686
  const activeButtonClassName = variant === "terminal" ? "tab-selected bg-background text-foreground" : "tab-selected text-foreground";
72547
- const inactiveButtonClassName = variant === "terminal" ? "bg-terminal text-terminal-foreground hover:bg-background hover:text-foreground" : "text-muted-foreground hover:text-foreground";
72687
+ const inactiveButtonClassName = variant === "terminal" ? "bg-terminal text-terminal-foreground/80 hover:bg-terminal hover:text-terminal-foreground" : "text-muted-foreground hover:text-foreground";
72548
72688
  const actionsClassName = variant === "terminal" ? "tabs-actions border-border bg-terminal text-terminal-foreground flex shrink-0 items-center border-b px-1" : "tabs-actions border-border bg-background flex shrink-0 items-center border-b px-1";
72549
- const handleTabBarDoubleClick = (e2) => {
72689
+ const handleTabBarDoubleClick = (event) => {
72550
72690
  if (!onTabBarDoubleClick) return;
72551
- if (e2.target.closest('[data-tab-item="true"]')) return;
72691
+ if (event.target.closest('[data-tab-item="true"]')) return;
72552
72692
  onTabBarDoubleClick();
72553
72693
  };
72554
72694
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(
@@ -72560,41 +72700,62 @@ function Tabs({
72560
72700
  children: [
72561
72701
  style,
72562
72702
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: headerClassName, children: [
72563
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: stripClassName, children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: listClassName, onDoubleClick: handleTabBarDoubleClick, children: tabs.map((tab2) => /* @__PURE__ */ jsxRuntimeExports.jsxs(
72564
- "button",
72703
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: stripClassName, children: /* @__PURE__ */ jsxRuntimeExports.jsx(
72704
+ "div",
72565
72705
  {
72566
- "data-tab-item": "true",
72567
- onClick: () => handleChange(tab2.id),
72568
- className: `${buttonBaseClassName} ${activeTab === tab2.id ? activeButtonClassName : inactiveButtonClassName}`,
72569
- children: [
72570
- tab2.icon,
72571
- tab2.label,
72572
- tab2.closable && onTabClose && /* @__PURE__ */ jsxRuntimeExports.jsx(
72573
- "span",
72706
+ className: listClassName,
72707
+ onDoubleClick: handleTabBarDoubleClick,
72708
+ onDragOver: handleListDragOver,
72709
+ onDrop: handleListDrop,
72710
+ children: tabs.map((tab2) => {
72711
+ const dragIndicatorStyle = dropIndicator?.tabId === tab2.id ? {
72712
+ boxShadow: dropIndicator.position === "before" ? "inset 2px 0 0 var(--border)" : "inset -2px 0 0 var(--border)"
72713
+ } : void 0;
72714
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs(
72715
+ "button",
72574
72716
  {
72575
- role: "button",
72576
- tabIndex: 0,
72577
- onClick: (e2) => {
72578
- e2.stopPropagation();
72579
- onTabClose(tab2.id);
72580
- },
72581
- onKeyDown: (e2) => {
72582
- if (e2.key === "Enter" || e2.key === " ") {
72583
- e2.stopPropagation();
72584
- onTabClose(tab2.id);
72585
- }
72586
- },
72587
- className: `hover:text-foreground -mr-1 rounded p-0.5 transition ${tab2.closeButtonVisibility === "always" ? "opacity-100" : "opacity-0 group-hover:opacity-100 [button:hover>&]:opacity-100"} ${activeTab === tab2.id ? "text-current/80" : "text-muted-foreground"}`,
72588
- children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$2, { className: "h-3 w-3" })
72589
- }
72590
- )
72591
- ]
72592
- },
72593
- tab2.id
72594
- )) }) }),
72717
+ "data-tab-item": "true",
72718
+ draggable: reorderable,
72719
+ onClick: () => handleChange(tab2.id),
72720
+ onDragStart: (event) => handleDragStart(event, tab2.id),
72721
+ onDragEnd: handleDragEnd,
72722
+ onDragOver: (event) => handleItemDragOver(event, tab2.id),
72723
+ onDrop: (event) => handleItemDrop(event, tab2.id),
72724
+ className: `${buttonBaseClassName} ${activeTab === tab2.id ? activeButtonClassName : inactiveButtonClassName} ${reorderable ? "cursor-grab active:cursor-grabbing" : ""}`,
72725
+ style: dragIndicatorStyle,
72726
+ children: [
72727
+ tab2.icon,
72728
+ tab2.label,
72729
+ tab2.closable && onTabClose && /* @__PURE__ */ jsxRuntimeExports.jsx(
72730
+ "span",
72731
+ {
72732
+ role: "button",
72733
+ tabIndex: 0,
72734
+ onClick: (event) => {
72735
+ event.stopPropagation();
72736
+ onTabClose(tab2.id);
72737
+ },
72738
+ onKeyDown: (event) => {
72739
+ if (event.key === "Enter" || event.key === " ") {
72740
+ event.stopPropagation();
72741
+ onTabClose(tab2.id);
72742
+ }
72743
+ },
72744
+ draggable: false,
72745
+ className: `hover:text-foreground -mr-1 rounded p-0.5 transition ${tab2.closeButtonVisibility === "always" ? "opacity-100" : "opacity-0 group-hover:opacity-100 [button:hover>&]:opacity-100"} ${activeTab === tab2.id ? "text-current/80" : "text-muted-foreground"}`,
72746
+ children: /* @__PURE__ */ jsxRuntimeExports.jsx(X$2, { className: "h-3 w-3" })
72747
+ }
72748
+ )
72749
+ ]
72750
+ },
72751
+ tab2.id
72752
+ );
72753
+ })
72754
+ }
72755
+ ) }),
72595
72756
  actions && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { "data-tabs-actions": "true", className: actionsClassName, children: actions })
72596
72757
  ] }),
72597
- tabs.map(
72758
+ contentTabs.map(
72598
72759
  (tab2) => tab2.unmountOnHide ? activeTab === tab2.id && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: tab2.content }, tab2.id) : /* @__PURE__ */ jsxRuntimeExports.jsx(reactExports.Activity, { mode: activeTab === tab2.id ? "visible" : "hidden", children: /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: tab2.content }) }, tab2.id)
72599
72760
  )
72600
72761
  ]
@@ -152133,6 +152294,10 @@ async function refreshDashboardGitSnapshot(reason) {
152133
152294
  if (isStaticMode()) return;
152134
152295
  await trpcClient.dashboard.refreshGitSnapshot.mutate({ reason });
152135
152296
  }
152297
+ async function removeDetachedDashboardWorktree(path2) {
152298
+ if (isStaticMode()) return;
152299
+ await trpcClient.dashboard.removeDetachedWorktree.mutate({ path: path2 });
152300
+ }
152136
152301
  const SPEC_DRIVEN_ORDER = ["proposal", "design", "specs", "tasks"];
152137
152302
  const GIT_WORKTREE_BORDER_CLASS = "border-zinc-400/50";
152138
152303
  const GIT_WORKTREE_BG_CLASS = "bg-zinc-500/8";
@@ -152171,6 +152336,9 @@ function formatArtifactLabel(id2) {
152171
152336
  function isHttpUrl(value) {
152172
152337
  return /^https?:\/\//.test(value);
152173
152338
  }
152339
+ async function copyText(value) {
152340
+ await navigator.clipboard.writeText(value);
152341
+ }
152174
152342
  function sortArtifactIdsForSchema(schemaName, artifactIds) {
152175
152343
  if (schemaName !== "spec-driven") return artifactIds;
152176
152344
  const rank = /* @__PURE__ */ new Map();
@@ -152311,6 +152479,31 @@ function Dashboard() {
152311
152479
  }
152312
152480
  }, []);
152313
152481
  const focusRefreshAtRef = reactExports.useRef(0);
152482
+ const [removingWorktreePath, setRemovingWorktreePath] = reactExports.useState(null);
152483
+ const handleRemoveDetachedWorktree = reactExports.useCallback(async (worktree) => {
152484
+ if (isStaticMode() || worktree.isCurrent || !worktree.detached || isHttpUrl(worktree.path)) {
152485
+ return;
152486
+ }
152487
+ const confirmed = window.confirm(
152488
+ [
152489
+ "Remove detached worktree?",
152490
+ "",
152491
+ worktree.path,
152492
+ "",
152493
+ "This runs git worktree remove --force."
152494
+ ].join("\n")
152495
+ );
152496
+ if (!confirmed) return;
152497
+ setRemovingWorktreePath(worktree.path);
152498
+ try {
152499
+ await removeDetachedDashboardWorktree(worktree.path);
152500
+ } catch (error2) {
152501
+ console.error("[Dashboard] Failed to remove detached worktree:", error2);
152502
+ window.alert(error2 instanceof Error ? error2.message : "Failed to remove detached worktree.");
152503
+ } finally {
152504
+ setRemovingWorktreePath((current) => current === worktree.path ? null : current);
152505
+ }
152506
+ }, []);
152314
152507
  reactExports.useEffect(() => {
152315
152508
  if (isStaticMode()) return;
152316
152509
  const triggerOnce = (reason) => {
@@ -152535,7 +152728,15 @@ function Dashboard() {
152535
152728
  ] })
152536
152729
  ] }),
152537
152730
  currentWorktree ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "space-y-0", children: [
152538
- /* @__PURE__ */ jsxRuntimeExports.jsx(WorktreeRow, { worktree: currentWorktree, emphasize: true }),
152731
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
152732
+ WorktreeRow,
152733
+ {
152734
+ worktree: currentWorktree,
152735
+ emphasize: true,
152736
+ removing: removingWorktreePath === currentWorktree.path,
152737
+ onRemoveDetachedWorktree: handleRemoveDetachedWorktree
152738
+ }
152739
+ ),
152539
152740
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: `-mt-px space-y-1 border-l pl-3 pt-2 ${GIT_WORKTREE_LINE_CLASS}`, children: currentWorktree.entries.map((entry) => /* @__PURE__ */ jsxRuntimeExports.jsx(
152540
152741
  GitEntryRow,
152541
152742
  {
@@ -152546,7 +152747,16 @@ function Dashboard() {
152546
152747
  ] }) : /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground rounded-md border border-dashed px-2.5 py-2 text-xs", children: "No worktree snapshot available." }),
152547
152748
  otherWorktrees.length > 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-border/70 mt-3 space-y-1 border-t pt-2", children: [
152548
152749
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground text-xs uppercase tracking-wide", children: "Other Worktrees" }),
152549
- otherWorktrees.map((worktree) => /* @__PURE__ */ jsxRuntimeExports.jsx(WorktreeRow, { worktree, emphasize: false }, worktree.path))
152750
+ otherWorktrees.map((worktree) => /* @__PURE__ */ jsxRuntimeExports.jsx(
152751
+ WorktreeRow,
152752
+ {
152753
+ worktree,
152754
+ emphasize: false,
152755
+ removing: removingWorktreePath === worktree.path,
152756
+ onRemoveDetachedWorktree: handleRemoveDetachedWorktree
152757
+ },
152758
+ worktree.path
152759
+ ))
152550
152760
  ] })
152551
152761
  ] })
152552
152762
  ] }) : null
@@ -152723,22 +152933,84 @@ function Dashboard() {
152723
152933
  }
152724
152934
  function WorktreeRow({
152725
152935
  worktree,
152726
- emphasize
152936
+ emphasize,
152937
+ removing = false,
152938
+ onRemoveDetachedWorktree
152727
152939
  }) {
152728
- const pathLabel = isHttpUrl(worktree.path) ? worktree.path : `${worktree.relativePath} | ${worktree.path}`;
152940
+ const isRemotePath = isHttpUrl(worktree.path);
152941
+ const canToggleRelativePath = !isRemotePath;
152942
+ const canRemoveDetached = !isRemotePath && worktree.detached && !worktree.isCurrent;
152943
+ const [showRelativePath, setShowRelativePath] = reactExports.useState(false);
152944
+ const [copied, setCopied] = reactExports.useState(false);
152945
+ const displayPath = isRemotePath ? worktree.path : showRelativePath ? worktree.relativePath : worktree.path;
152946
+ const handleCopyPath = reactExports.useCallback(async () => {
152947
+ try {
152948
+ await copyText(displayPath);
152949
+ setCopied(true);
152950
+ window.setTimeout(() => setCopied(false), 1200);
152951
+ } catch (error) {
152952
+ console.error("[Dashboard] Failed to copy worktree path:", error);
152953
+ }
152954
+ }, [displayPath]);
152729
152955
  return /* @__PURE__ */ jsxRuntimeExports.jsx(
152730
152956
  "div",
152731
152957
  {
152732
152958
  className: `min-w-0 rounded-e-md rounded-t-md border px-2.5 py-2 ${emphasize ? `${GIT_WORKTREE_BORDER_CLASS} ${GIT_WORKTREE_BG_CLASS}` : "border-border/70 bg-muted/15"}`,
152733
152959
  children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-start justify-between gap-2", children: [
152734
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0", children: [
152960
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "min-w-0 flex-1", children: [
152735
152961
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-1.5 text-sm font-medium", children: [
152736
- /* @__PURE__ */ jsxRuntimeExports.jsx(GitBranch, { className: "h-3.5 w-3.5" }),
152962
+ /* @__PURE__ */ jsxRuntimeExports.jsx(GitBranch, { className: "h-3.5 w-3.5 shrink-0" }),
152737
152963
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: worktree.branchName })
152738
152964
  ] }),
152739
- /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground truncate text-xs", children: pathLabel })
152965
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-0.5 flex min-w-0 items-center gap-1", children: [
152966
+ canToggleRelativePath ? /* @__PURE__ */ jsxRuntimeExports.jsx(
152967
+ "button",
152968
+ {
152969
+ type: "button",
152970
+ onClick: () => setShowRelativePath((current) => !current),
152971
+ className: "text-muted-foreground hover:text-foreground inline-flex h-5 w-5 shrink-0 items-center justify-center rounded border border-transparent",
152972
+ title: showRelativePath ? "Show absolute path" : "Show relative path",
152973
+ "aria-label": showRelativePath ? "Show absolute path" : "Show relative path",
152974
+ children: showRelativePath ? /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpenDot, { className: "h-3.5 w-3.5" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(FolderOpen, { className: "h-3.5 w-3.5" })
152975
+ }
152976
+ ) : null,
152977
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
152978
+ "button",
152979
+ {
152980
+ type: "button",
152981
+ onClick: () => {
152982
+ void handleCopyPath();
152983
+ },
152984
+ onDoubleClick: () => {
152985
+ if (!canToggleRelativePath) return;
152986
+ setShowRelativePath((current) => !current);
152987
+ },
152988
+ className: "text-muted-foreground hover:text-foreground inline-flex min-w-0 flex-1 items-center gap-1 truncate text-left text-xs",
152989
+ title: displayPath,
152990
+ "aria-label": `Copy ${showRelativePath && canToggleRelativePath ? "relative" : "absolute"} path for ${worktree.branchName}`,
152991
+ children: [
152992
+ /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "truncate", children: displayPath }),
152993
+ copied ? /* @__PURE__ */ jsxRuntimeExports.jsx(Check, { className: "h-3 w-3 shrink-0" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Copy, { className: "h-3 w-3 shrink-0" })
152994
+ ]
152995
+ }
152996
+ )
152997
+ ] })
152740
152998
  ] }),
152741
152999
  /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "shrink-0 text-right", children: /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center justify-end gap-1", children: [
153000
+ canRemoveDetached ? /* @__PURE__ */ jsxRuntimeExports.jsx(
153001
+ "button",
153002
+ {
153003
+ type: "button",
153004
+ onClick: () => {
153005
+ void onRemoveDetachedWorktree?.(worktree);
153006
+ },
153007
+ disabled: removing,
153008
+ className: "text-muted-foreground hover:text-destructive inline-flex h-5 w-5 items-center justify-center rounded border border-transparent disabled:cursor-not-allowed disabled:opacity-60",
153009
+ title: "Remove detached worktree",
153010
+ "aria-label": "Remove detached worktree",
153011
+ children: removing ? /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "h-3.5 w-3.5 animate-spin" }) : /* @__PURE__ */ jsxRuntimeExports.jsx(Trash2, { className: "h-3.5 w-3.5" })
153012
+ }
153013
+ ) : null,
152742
153014
  /* @__PURE__ */ jsxRuntimeExports.jsx(GitAheadBehindBadge, { ahead: worktree.ahead, behind: worktree.behind }),
152743
153015
  /* @__PURE__ */ jsxRuntimeExports.jsx(GitFilesBadge, { files: worktree.diff.files }),
152744
153016
  /* @__PURE__ */ jsxRuntimeExports.jsx(DiffStat, { diff: worktree.diff, className: "justify-end" })