pilotswarm 0.5.71 → 0.5.72

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 (68) hide show
  1. package/package.json +2 -2
  2. package/ui/react/src/web-app.js +99 -39
  3. package/web/dist/assets/{abnfDiagram-VRR7QNED-C1caNr4U.js → abnfDiagram-VRR7QNED-D__RWhK7.js} +1 -1
  4. package/web/dist/assets/{arc-BufdFJYK.js → arc-CjtcEiTR.js} +1 -1
  5. package/web/dist/assets/{architectureDiagram-ZJ3FMSHR-C0vQblUK.js → architectureDiagram-ZJ3FMSHR-BDI8FioV.js} +1 -1
  6. package/web/dist/assets/{blockDiagram-677ZJIJ3-B6PYWI9u.js → blockDiagram-677ZJIJ3-D62iIbEl.js} +1 -1
  7. package/web/dist/assets/{c4Diagram-LMCZKHZV-DFoaVeMm.js → c4Diagram-LMCZKHZV-BlJ596a2.js} +1 -1
  8. package/web/dist/assets/channel-CF_IY6bX.js +1 -0
  9. package/web/dist/assets/{chunk-2Q5K7J3B-CxFBb-8y.js → chunk-2Q5K7J3B-CnVtHjtN.js} +1 -1
  10. package/web/dist/assets/{chunk-32BRIVSS-DO1G8AVc.js → chunk-32BRIVSS-g8IU-e70.js} +1 -1
  11. package/web/dist/assets/{chunk-5VM5RSS4-spE4bKSd.js → chunk-5VM5RSS4-KKxfFv2y.js} +1 -1
  12. package/web/dist/assets/{chunk-EX3LRPZG-Bc_eUP5F.js → chunk-EX3LRPZG-C0eEpQtc.js} +1 -1
  13. package/web/dist/assets/{chunk-JWPE2WC7-CGM2GAMX.js → chunk-JWPE2WC7-ZfmDblU2.js} +1 -1
  14. package/web/dist/assets/{chunk-MOJQB5TN-CHdrVT1z.js → chunk-MOJQB5TN-BOfHzBMe.js} +1 -1
  15. package/web/dist/assets/{chunk-RYQCIY6F-BWJK7-AW.js → chunk-RYQCIY6F-GvY7zGfa.js} +1 -1
  16. package/web/dist/assets/{chunk-V7JOEXUC-D8tgpQwK.js → chunk-V7JOEXUC-Bi28CvqE.js} +1 -1
  17. package/web/dist/assets/{chunk-VR4S4FIN-BP86JfVu.js → chunk-VR4S4FIN-H1DY3Xw7.js} +1 -1
  18. package/web/dist/assets/{chunk-XXDRQBXY-Ctq_LUrs.js → chunk-XXDRQBXY-JMwCi2he.js} +1 -1
  19. package/web/dist/assets/classDiagram-OUVF2IWQ-BoTycRRp.js +1 -0
  20. package/web/dist/assets/classDiagram-v2-EOCWNBFH-BoTycRRp.js +1 -0
  21. package/web/dist/assets/{cose-bilkent-JH36ORCC-DNvC4thT.js → cose-bilkent-JH36ORCC-DfFOvDA3.js} +1 -1
  22. package/web/dist/assets/{cynefin-VYW2F7L2-3zVj2GvI.js → cynefin-VYW2F7L2-CD5a_UMt.js} +1 -1
  23. package/web/dist/assets/{cynefinDiagram-TSTJHNR4-DQbITfsJ.js → cynefinDiagram-TSTJHNR4-CRsYXGC9.js} +1 -1
  24. package/web/dist/assets/{dagre-VKFMJZFB-BkGAcDyj.js → dagre-VKFMJZFB-BuPdi3xA.js} +1 -1
  25. package/web/dist/assets/{diagram-FQU43EPY-D3lsgelm.js → diagram-FQU43EPY-MIVIpIBC.js} +1 -1
  26. package/web/dist/assets/{diagram-G47NLZAW-C2rO9e3d.js → diagram-G47NLZAW-D7-s_wbT.js} +1 -1
  27. package/web/dist/assets/{diagram-NH7WQ7WH-DJBwtT8q.js → diagram-NH7WQ7WH-fmSlDjpy.js} +1 -1
  28. package/web/dist/assets/{diagram-OA4YK3LP-C-SAwEHZ.js → diagram-OA4YK3LP-DwEwWIum.js} +1 -1
  29. package/web/dist/assets/{diagram-WEI45ONY-BpXMlmKz.js → diagram-WEI45ONY-Gvb_KdCz.js} +1 -1
  30. package/web/dist/assets/{ebnfDiagram-CCIWWBDH-DwxUgEmE.js → ebnfDiagram-CCIWWBDH-BOWGc2OC.js} +1 -1
  31. package/web/dist/assets/{erDiagram-Q63AITRT-DNZMCmYz.js → erDiagram-Q63AITRT-CrigFfDY.js} +1 -1
  32. package/web/dist/assets/{flowDiagram-23GEKE2U-CUlGtnWV.js → flowDiagram-23GEKE2U-618PQgNe.js} +1 -1
  33. package/web/dist/assets/{ganttDiagram-NO4QXBWP-DCj6zkyt.js → ganttDiagram-NO4QXBWP-lHe8_OHE.js} +1 -1
  34. package/web/dist/assets/{gitGraphDiagram-IHSO6WYX-Q6UP_dgi.js → gitGraphDiagram-IHSO6WYX-CM3Jo1NF.js} +1 -1
  35. package/web/dist/assets/index-DHFBzAwY.css +1 -0
  36. package/web/dist/assets/{index-23y0f1it.js → index-G-9aAxKP.js} +2 -2
  37. package/web/dist/assets/{infoDiagram-FWYZ7A6U-Cwn8XNQT.js → infoDiagram-FWYZ7A6U-CtDt5Yg1.js} +1 -1
  38. package/web/dist/assets/{ishikawaDiagram-FXEZZL3T-BaMvGBAo.js → ishikawaDiagram-FXEZZL3T-DMDXe5yy.js} +1 -1
  39. package/web/dist/assets/{journeyDiagram-5HDEW3XC-DK95FJ0t.js → journeyDiagram-5HDEW3XC-BxUjwmwF.js} +1 -1
  40. package/web/dist/assets/{kanban-definition-HUTT4EX6-C6W6RJLm.js → kanban-definition-HUTT4EX6-Cey1IRnt.js} +1 -1
  41. package/web/dist/assets/{linear-Un37Oyxr.js → linear-BAaF8u7Q.js} +1 -1
  42. package/web/dist/assets/{mermaid.core-i8uqvLPa.js → mermaid.core-D7ywN4EU.js} +4 -4
  43. package/web/dist/assets/{mindmap-definition-LN4V7U3C-d_cgq1KW.js → mindmap-definition-LN4V7U3C-BTSESh2V.js} +1 -1
  44. package/web/dist/assets/{papaparse.min-BiJEkQ8f.js → papaparse.min-BhnWt-zK.js} +1 -1
  45. package/web/dist/assets/{pegDiagram-2B236MQR-5QRWM5AP.js → pegDiagram-2B236MQR-BTWzwmna.js} +1 -1
  46. package/web/dist/assets/{pieDiagram-ENE6RG2P-VIZXsjFV.js → pieDiagram-ENE6RG2P-qI9jL2eV.js} +1 -1
  47. package/web/dist/assets/{pilotswarm-D7Q48waO.js → pilotswarm-Dccv5YRO.js} +73 -73
  48. package/web/dist/assets/{quadrantDiagram-ABIIQ3AL-DMOx841b.js → quadrantDiagram-ABIIQ3AL-B54Va5N3.js} +1 -1
  49. package/web/dist/assets/{railroadDiagram-RFXS5EU6-lTWzjdcd.js → railroadDiagram-RFXS5EU6-CVXDflXo.js} +1 -1
  50. package/web/dist/assets/{requirementDiagram-TGXJPOKE-BE5SpiNy.js → requirementDiagram-TGXJPOKE-C7abNeEc.js} +1 -1
  51. package/web/dist/assets/{sankeyDiagram-HTMAVEWB-C3LYWQTA.js → sankeyDiagram-HTMAVEWB-ND6Feq2w.js} +1 -1
  52. package/web/dist/assets/{sequenceDiagram-DBY2YBRQ-BTCp88tQ.js → sequenceDiagram-DBY2YBRQ-DXGwvQdf.js} +1 -1
  53. package/web/dist/assets/{sizeCapture-X5ZJPWSS-Ppzj8n5l.js → sizeCapture-X5ZJPWSS-CrXKKsBI.js} +1 -1
  54. package/web/dist/assets/{stateDiagram-2N3HPSRC-Ch_iZ_cQ.js → stateDiagram-2N3HPSRC-BJWpN6s6.js} +1 -1
  55. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-BQY9l8FM.js +1 -0
  56. package/web/dist/assets/{swimlanes-5IMT3BWC-BX4-Oeby.js → swimlanes-5IMT3BWC-Cy67JyBd.js} +2 -2
  57. package/web/dist/assets/swimlanesDiagram-G3AALYLV-DZ0Jn4Gp.js +8 -0
  58. package/web/dist/assets/{timeline-definition-FHXFAJF6-B1l-6l6u.js → timeline-definition-FHXFAJF6-CeDd4R0u.js} +1 -1
  59. package/web/dist/assets/{vennDiagram-L72KCM5P-Grpa6wFZ.js → vennDiagram-L72KCM5P-BDrPrK0B.js} +1 -1
  60. package/web/dist/assets/{wardleyDiagram-EHGQE667-B5bXnFlL.js → wardleyDiagram-EHGQE667-Bp9PEqNv.js} +1 -1
  61. package/web/dist/assets/{xychartDiagram-FW5EYKEG-BkELQtgc.js → xychartDiagram-FW5EYKEG-DI_8u8T1.js} +1 -1
  62. package/web/dist/index.html +3 -3
  63. package/web/dist/assets/channel-CDzPwSI9.js +0 -1
  64. package/web/dist/assets/classDiagram-OUVF2IWQ-DdcABn-U.js +0 -1
  65. package/web/dist/assets/classDiagram-v2-EOCWNBFH-DdcABn-U.js +0 -1
  66. package/web/dist/assets/index-BXR-II2L.css +0 -1
  67. package/web/dist/assets/stateDiagram-v2-6OUMAXLB-BbJN7t8_.js +0 -1
  68. package/web/dist/assets/swimlanesDiagram-G3AALYLV-0UA1VebA.js +0 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pilotswarm",
3
- "version": "0.5.71",
3
+ "version": "0.5.72",
4
4
  "description": "PilotSwarm application package: terminal UI, browser portal + Web API server, and MCP server — one install, three bins.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -81,7 +81,7 @@
81
81
  "ink": "^6.8.0",
82
82
  "jose": "^6.2.2",
83
83
  "mermaid": "^11.16.0",
84
- "pilotswarm-sdk": "0.5.71",
84
+ "pilotswarm-sdk": "0.5.72",
85
85
  "react": "^19.2.4",
86
86
  "react-dom": "^19.2.4",
87
87
  "ws": "^8.18.2"
@@ -4558,28 +4558,26 @@ function SessionDetailBox({ session, childCount = 0, pause = null, controller =
4558
4558
  * fleet. That only holds while every prop is referentially stable — hence the
4559
4559
  * hoisted click handler and ref setter rather than closures built per row.
4560
4560
  */
4561
- /**
4562
- * True when the primary input is a finger. Drag-to-folder is armed on
4563
- * pointerdown and needs `touch-action: none` to receive a move stream — which
4564
- * on a touch screen also means the list can no longer be scrolled by dragging
4565
- * it, so the gesture is withheld there entirely.
4566
- */
4567
- function useCoarsePointer() {
4568
- const query = "(pointer: coarse)";
4561
+ /** Subscribe to viewport or input changes without remounting the pane. */
4562
+ function useMediaQuery(query) {
4569
4563
  const read = () => (typeof window !== "undefined" && typeof window.matchMedia === "function"
4570
4564
  ? window.matchMedia(query).matches
4571
4565
  : false);
4572
- const [coarse, setCoarse] = React.useState(read);
4566
+ const [matches, setMatches] = React.useState(read);
4573
4567
  React.useEffect(() => {
4574
4568
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return undefined;
4575
4569
  const media = window.matchMedia(query);
4576
- const onChange = (event) => setCoarse(event.matches);
4570
+ const onChange = (event) => setMatches(event.matches);
4571
+ setMatches(media.matches);
4577
4572
  media.addEventListener?.("change", onChange);
4578
4573
  return () => media.removeEventListener?.("change", onChange);
4579
- }, []);
4580
- return coarse;
4574
+ }, [query]);
4575
+ return matches;
4581
4576
  }
4582
4577
 
4578
+ // Withhold drag-to-folder on touch screens so finger drags can scroll the list.
4579
+ function useCoarsePointer() { return useMediaQuery("(pointer: coarse)"); }
4580
+
4583
4581
  const RAIL_ORIGIN_PX = 13;
4584
4582
  const RAIL_STEP_PX = 11;
4585
4583
  const RAIL_WIDTH_PX = 1.5;
@@ -5052,11 +5050,10 @@ function useAxisLockedPan(ref, enabled = true) {
5052
5050
  }, [ref, enabled]);
5053
5051
  }
5054
5052
 
5055
- const SessionSearchControl = React.memo(function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = false, listRef = null }) {
5053
+ const SessionSearchControl = React.memo(function SessionSearchControl({ query = "", onQuery, matchCount = 0, mobile = false, expanded = false, onOpen, onClose, triggerRef, listRef = null }) {
5056
5054
  // Keep typing local: expensive list filtering and external-store updates
5057
5055
  // must never be part of the input's immediate render path.
5058
5056
  const [draft, setDraft] = React.useState(query);
5059
- const [mobileOpen, setMobileOpen] = React.useState(Boolean(query));
5060
5057
  const timer = React.useRef(null);
5061
5058
  const published = React.useRef(query);
5062
5059
  const composing = React.useRef(false);
@@ -5075,29 +5072,24 @@ const SessionSearchControl = React.memo(function SessionSearchControl({ query =
5075
5072
  cancel(); published.current = query; setDraft(query);
5076
5073
  }, [query]);
5077
5074
  const inputRef = React.useRef(null);
5078
- React.useEffect(() => {
5079
- if (query) setMobileOpen(true);
5080
- }, [query]);
5081
- const open = () => {
5082
- setMobileOpen(true);
5083
- requestAnimationFrame(() => inputRef.current?.focus({ preventScroll: true }));
5084
- };
5085
5075
  const closeOrClear = () => {
5086
5076
  if (draft || query) { setDraft(""); publish(""); }
5087
- else setMobileOpen(false);
5077
+ else onClose?.();
5088
5078
  };
5089
5079
  const resultLabel = draft !== query ? "Searching…" : draft
5090
5080
  ? `${matchCount} ${matchCount === 1 ? "match" : "matches"}` : "";
5091
5081
  return React.createElement("div", {
5092
- className: `ps-session-search${mobileOpen ? " is-open" : ""}`,
5082
+ className: `ps-session-search${expanded ? " is-open" : ""}`,
5093
5083
  "data-session-search": "true",
5094
5084
  },
5095
5085
  mobile ? React.createElement("button", {
5096
5086
  type: "button",
5097
5087
  className: "ps-session-search-trigger",
5088
+ ref: triggerRef,
5089
+ "aria-expanded": expanded,
5098
5090
  "aria-label": "Search sessions",
5099
5091
  title: "Search sessions",
5100
- onClick: open,
5092
+ onClick: onOpen,
5101
5093
  }, React.createElement(SearchGlyph)) : null,
5102
5094
  React.createElement("div", { className: "ps-session-search-fields" },
5103
5095
  React.createElement(SearchGlyph),
@@ -5128,7 +5120,7 @@ const SessionSearchControl = React.memo(function SessionSearchControl({ query =
5128
5120
  role: "status",
5129
5121
  "aria-live": "polite",
5130
5122
  }, resultLabel) : null,
5131
- (draft || mobile) ? React.createElement("button", {
5123
+ draft ? React.createElement("button", {
5132
5124
  type: "button",
5133
5125
  className: "ps-session-search-clear",
5134
5126
  "aria-label": draft ? "Clear session search" : "Close session search",
@@ -5145,6 +5137,11 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5145
5137
  // sessions-ONLY layout is the exception: it has the whole screen and the
5146
5138
  // detail box is the point of asking for it.
5147
5139
  const isMobilePane = String(panelClassName).includes("ps-mobile-session-pane");
5140
+ const compactSearch = useMediaQuery("(max-width: 920px)");
5141
+ const [searchOpen, setSearchOpen] = React.useState(false);
5142
+ const searchOverlay = compactSearch && searchOpen;
5143
+ const searchDialogRef = React.useRef(null);
5144
+ const searchTriggerRef = React.useRef(null);
5148
5145
  // Vertical is the primary scroll axis; sideways takes a deliberate swipe.
5149
5146
  const sessionListRef = React.useRef(null);
5150
5147
  // Selection reverts to plain taps wherever the primary input is a finger:
@@ -5253,6 +5250,35 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5253
5250
  }
5254
5251
  searchEnvRef.current?.setQuery?.(next);
5255
5252
  }, []);
5253
+ const closeSearch = React.useCallback(() => {
5254
+ setSearchOpen(false);
5255
+ setSearchQuery("");
5256
+ requestAnimationFrame(() => searchTriggerRef.current?.focus({ preventScroll: true }));
5257
+ }, [setSearchQuery]);
5258
+ React.useLayoutEffect(() => {
5259
+ const dialog = searchDialogRef.current;
5260
+ if (!searchOverlay || !dialog) return undefined;
5261
+ const viewport = window.visualViewport;
5262
+ const resize = () => {
5263
+ dialog.style.top = `${(viewport?.offsetTop || 0) + 8}px`;
5264
+ dialog.style.left = `${(viewport?.offsetLeft || 0) + 8}px`;
5265
+ dialog.style.width = `${(viewport?.width || window.innerWidth) - 16}px`;
5266
+ dialog.style.height = `${(viewport?.height || window.innerHeight) - 16}px`;
5267
+ };
5268
+ resize();
5269
+ dialog.showModal();
5270
+ dialog.querySelector("input")?.focus({ preventScroll: true });
5271
+ viewport?.addEventListener("resize", resize);
5272
+ viewport?.addEventListener("scroll", resize);
5273
+ window.addEventListener("resize", resize);
5274
+ return () => {
5275
+ viewport?.removeEventListener("resize", resize);
5276
+ viewport?.removeEventListener("scroll", resize);
5277
+ window.removeEventListener("resize", resize);
5278
+ dialog.close();
5279
+ };
5280
+ }, [searchOverlay]);
5281
+ React.useEffect(() => { if (!compactSearch) setSearchOpen(false); }, [compactSearch]);
5256
5282
  React.useLayoutEffect(() => {
5257
5283
  if (viewState.filterQuery || !searchScrollRef.current.restore || !sessionListRef.current) return;
5258
5284
  sessionListRef.current.scrollTop = searchScrollRef.current.top;
@@ -5386,7 +5412,7 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5386
5412
  // rows/viewState from a ref that is refreshed on every render instead of
5387
5413
  // closing over them.
5388
5414
  const clickEnv = React.useRef(null);
5389
- clickEnv.current = { rows, viewState, controller, selection };
5415
+ clickEnv.current = { rows, viewState, controller, selection, searchOverlay, closeSearch };
5390
5416
  // ── Drag sessions into / out of groups ────────────────────────────
5391
5417
  // Pointer-driven so it works from <button> rows, can render a collection
5392
5418
  // ghost for a multi-selection, and can highlight the destination folder.
@@ -5712,6 +5738,15 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5712
5738
 
5713
5739
  const handleRowClick = React.useCallback((event, row) => {
5714
5740
  const { rows: currentRows, viewState: current, controller: ctl, selection: pick } = clickEnv.current;
5741
+ if (clickEnv.current.searchOverlay && !row.isGroup) {
5742
+ if (pick) pick.onSelect(row.sessionId);
5743
+ else {
5744
+ ctl.setFocus("sessions");
5745
+ ctl.loadSession(row.sessionId).catch(() => {});
5746
+ }
5747
+ clickEnv.current.closeSearch();
5748
+ return;
5749
+ }
5715
5750
  if (pick) {
5716
5751
  if (row.isGroup || (row.hasChildren && row.active)) ctl.dispatch({ type: row.collapsed ? "sessions/expand" : "sessions/collapse", sessionId: row.sessionId });
5717
5752
  if (!row.isGroup) pick.onSelect(row.sessionId);
@@ -5955,14 +5990,12 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
5955
5990
  : "Release to cancel"))
5956
5991
  : null;
5957
5992
 
5958
- return React.createElement(React.Fragment, null,
5959
- dragGhost,
5960
- actionsOnly ? (actionsHost ? createPortal(React.createElement("div", { className: "ps-moa-control-actions", onClick: onAction }, panelActions), actionsHost) : null) : React.createElement(Panel, {
5961
- title: [{ text: "Sessions", color: "yellow", bold: true }],
5993
+ const sessionPanel = actionsOnly ? (actionsHost ? createPortal(React.createElement("div", { className: "ps-moa-control-actions", onClick: onAction }, panelActions), actionsHost) : null) : React.createElement(Panel, {
5994
+ title: [{ text: searchOverlay ? "Find a session" : "Sessions", color: "yellow", bold: true }],
5962
5995
  color: "yellow",
5963
5996
  focused: viewState.focused,
5964
5997
  theme,
5965
- actions: selection ? React.createElement(React.Fragment, null,
5998
+ actions: searchOverlay ? React.createElement(IconButton, { label: "Close session search", icon: "×", onClick: closeSearch }) : selection ? React.createElement(React.Fragment, null,
5966
5999
  selection.onCreate ? React.createElement(IconButton, {
5967
6000
  className: "ps-mini-button", icon: React.createElement(PlusGlyph),
5968
6001
  label: "Create New Session", onClick: selection.onCreate,
@@ -6010,7 +6043,16 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
6010
6043
  // touch hijacks the finger that should be scrolling the list.
6011
6044
  drag: selection || touchInput || viewState.sortMode !== "saved" ? null : dragHandlers,
6012
6045
  }))),
6013
- React.createElement("div", { className: "ps-session-find-controls" },
6046
+ React.createElement("div", {
6047
+ className: "ps-session-find-controls",
6048
+ onPointerDown: (event) => {
6049
+ // Keep the search keyboard open while tapping sort, refresh, or clear.
6050
+ // Safari otherwise blurs the field without focusing the button.
6051
+ if (compactSearch && event.button === 0 && event.target.closest?.("button")
6052
+ && event.currentTarget.contains(document.activeElement)
6053
+ && document.activeElement?.matches("input")) event.preventDefault();
6054
+ },
6055
+ },
6014
6056
  React.createElement("div", { className: "ps-session-sort-controls" },
6015
6057
  React.createElement("div", { className: "ps-session-sort-modes", role: "group", "aria-label": "Session sort order" },
6016
6058
  ...[["used", "Recently used", "M12 8v4l3 2", true], ["updated", "Recently updated", "M3 12h4l3-7 4 14 3-7h4"], ["saved", "Saved order", "M6 3h12v18l-6-4-6 4Z"]].map(([mode, label, path, clock]) => React.createElement(IconButton, {
@@ -6030,10 +6072,14 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
6030
6072
  query: viewState.filterQuery,
6031
6073
  onQuery: setSearchQuery,
6032
6074
  matchCount: searchMatchCount,
6033
- mobile: isMobilePane,
6075
+ mobile: compactSearch,
6076
+ expanded: searchOverlay,
6077
+ onOpen: () => setSearchOpen(true),
6078
+ onClose: closeSearch,
6079
+ triggerRef: searchTriggerRef,
6034
6080
  listRef: sessionListRef,
6035
6081
  })),
6036
- (showDetailBox === null ? !isMobilePane : showDetailBox)
6082
+ !searchOverlay && (showDetailBox === null ? !isMobilePane : showDetailBox)
6037
6083
  ? React.createElement(SessionDetailBox, {
6038
6084
  session: activeSession,
6039
6085
  childCount: activeRow?.childCount || 0,
@@ -6047,7 +6093,21 @@ function SessionPane({ controller, actions = null, panelClassName = "", structur
6047
6093
  collapsed: !detailCollapsed,
6048
6094
  }),
6049
6095
  })
6050
- : null),
6096
+ : null);
6097
+
6098
+ return React.createElement(React.Fragment, null,
6099
+ dragGhost,
6100
+ !searchOverlay ? sessionPanel : null,
6101
+ React.createElement("dialog", {
6102
+ ref: searchDialogRef,
6103
+ className: "ps-session-search-overlay",
6104
+ "aria-label": "Find a session",
6105
+ onCancel: event => { event.preventDefault(); closeSearch(); },
6106
+ onKeyDownCapture: event => {
6107
+ if (event.key === "Escape") { event.preventDefault(); event.stopPropagation(); closeSearch(); }
6108
+ },
6109
+ onClick: event => { if (event.target === event.currentTarget) closeSearch(); },
6110
+ }, searchOverlay ? sessionPanel : null),
6051
6111
  (manageOpen && activeSession && !activeSession.isGroup)
6052
6112
  ? React.createElement(SessionModifyModal, {
6053
6113
  controller,
@@ -7225,14 +7285,14 @@ export function evaluateKeyboardTakeover(baseline, viewportWidth, viewportHeight
7225
7285
  }
7226
7286
 
7227
7287
  /**
7228
- * True while the on-screen keyboard is up AND the chat composer summoned it.
7288
+ * True while the on-screen keyboard is up AND a matching control has focus.
7229
7289
  * Both conditions matter: height alone would fire for a modal's text field
7230
7290
  * and collapse the workspace behind the modal; focus alone would fire for
7231
7291
  * hardware keyboards that shrink nothing. State-driven on the keyboard
7232
7292
  * itself, so it reverts the moment the keyboard goes away — including the
7233
7293
  * iOS swipe-dismiss that closes the keyboard without blurring the input.
7234
7294
  */
7235
- function useKeyboardTakeover(enabled) {
7295
+ function useKeyboardTakeover(enabled, focusSelector = ".ps-prompt-input") {
7236
7296
  const [takeover, setTakeover] = React.useState(false);
7237
7297
  React.useEffect(() => {
7238
7298
  if (!enabled || typeof window === "undefined" || !window.visualViewport) {
@@ -7244,7 +7304,7 @@ function useKeyboardTakeover(enabled) {
7244
7304
  let frame = 0;
7245
7305
  const evaluate = () => {
7246
7306
  frame = 0;
7247
- const composerFocused = Boolean(document.activeElement?.classList?.contains("ps-prompt-input"));
7307
+ const composerFocused = Boolean(document.activeElement?.matches?.(focusSelector));
7248
7308
  const next = evaluateKeyboardTakeover(baseline, viewport.width, viewport.height, composerFocused);
7249
7309
  baseline = next.baseline;
7250
7310
  setTakeover(next.takeover);
@@ -7262,7 +7322,7 @@ function useKeyboardTakeover(enabled) {
7262
7322
  window.removeEventListener("focusin", schedule);
7263
7323
  window.removeEventListener("focusout", schedule);
7264
7324
  };
7265
- }, [enabled]);
7325
+ }, [enabled, focusSelector]);
7266
7326
  return enabled ? takeover : false;
7267
7327
  }
7268
7328
 
@@ -1 +1 @@
1
- import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-CHdrVT1z.js";import{p as f}from"./chunk-JWPE2WC7-CGM2GAMX.js";import{_ as n,l as o}from"./mermaid.core-i8uqvLPa.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-3zVj2GvI.js";import"./pilotswarm-D7Q48waO.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
1
+ import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-BOfHzBMe.js";import{p as f}from"./chunk-JWPE2WC7-ZfmDblU2.js";import{_ as n,l as o}from"./mermaid.core-D7ywN4EU.js";import{M as c,b as d}from"./cynefin-VYW2F7L2-CD5a_UMt.js";import"./pilotswarm-Dccv5YRO.js";var v=d().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),l=t?parseInt(t,10):0,m=s?parseInt(s,10):1/0;return{min:l,max:m}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new c(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},B={parser:R,db:a,renderer:u,styles:p};export{B as diagram};
@@ -1 +1 @@
1
- import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-i8uqvLPa.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
1
+ import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as on,ab as sn,ac as fn}from"./mermaid.core-D7ywN4EU.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};