@ai-matrx/office 0.8.48 → 0.8.49

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.
package/dist/pdf.d.cts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ComponentType, ReactNode } from 'react';
3
3
  import { ComingSoonEntry } from '@ai-matrx/kit/coming-soon';
4
4
 
5
5
  /**
@@ -62,6 +62,8 @@ interface PdfViewerState {
62
62
  rotations: Record<number, number>;
63
63
  /** Changes when the file changed on the server: the viewer must load it again. */
64
64
  reloadKey: number;
65
+ /** The page the person is on (1-based), passed only while a host tool with `followsPage` is open; otherwise 1. */
66
+ currentPage: number;
65
67
  /** The document parsed with this many pages. */
66
68
  onDocumentLoad(pageCount: number): void;
67
69
  /** A page was measured, in PDF points (crop and fit-page need it). */
@@ -119,6 +121,38 @@ type PdfRunResult =
119
121
  rows: string[][];
120
122
  }>;
121
123
  };
124
+ /** What the shell tells a host tool's panel about the session it sits in. */
125
+ interface PdfHostToolContext {
126
+ currentPage: number;
127
+ pageCount: number;
128
+ /** Original page numbers selected in the page panel (empty when none). */
129
+ selected: number[];
130
+ goToPage(n: number): void;
131
+ /** The file changed under the same id: draw the viewer and thumbnails again. */
132
+ reload(): void;
133
+ }
134
+ /**
135
+ * A tool the host brings to the rail. The shell gives it a rail button, a place in "All tools", the
136
+ * tool search and the right panel; the host owns what is inside (its own server calls and state).
137
+ * This is how an app folds its older studios into the workspace without the package knowing them.
138
+ */
139
+ interface PdfHostTool {
140
+ /** Unique among the host's tools. */
141
+ id: string;
142
+ label: string;
143
+ /** One short line under the panel title. */
144
+ hint?: string;
145
+ icon: ComponentType<{
146
+ className?: string;
147
+ }>;
148
+ /** The viewer receives `currentPage` while this tool is open (a one-page-at-a-time canvas needs it). */
149
+ followsPage?: boolean;
150
+ /** A wide panel (28rem) instead of the standard one (18rem). */
151
+ wide?: boolean;
152
+ /** Rail group: 1 (default) sits with the document tools. */
153
+ group?: 0 | 1 | 2;
154
+ render(context: PdfHostToolContext): ReactNode;
155
+ }
122
156
  interface PdfWorkspaceHost {
123
157
  file: {
124
158
  id: string;
@@ -155,6 +189,8 @@ interface PdfWorkspaceHost {
155
189
  id: string;
156
190
  label: string;
157
191
  }>>;
192
+ /** Extra tools the host brings (see `PdfHostTool`). */
193
+ tools?: PdfHostTool[];
158
194
  /** False while the device is offline: the save pill says so and edits are not queued. */
159
195
  online?: boolean;
160
196
  /** Show a failure to the person (the host's toast). Defaults to an inline banner. */
@@ -252,4 +288,4 @@ declare const canRedo: (h: History<unknown>) => boolean;
252
288
  declare const undoLabel: (h: History<unknown>) => string;
253
289
  declare const redoLabel: (h: History<unknown>) => string;
254
290
 
255
- export { HISTORY_LIMIT, type History, type KeyLike, PDF_COMING_SOON, PDF_SHORTCUTS, PDF_TOOLS, type PageDecisions, type PageOp, type PdfActionId, type PdfRunRequest, type PdfRunResult, type PdfShortcut, type PdfToolDef, type PdfToolId, type PdfViewerState, PdfWorkspace, type PdfWorkspaceHost, type PdfWorkspaceProps, type Turn, canRedo, canUndo, comingSoonIdOf, compilePageOps, deletePages, formatKeys, freshDecisions, isDirty, keptOrder, matchShortcut, pdfTool, pushStep, redo, redoLabel, reorderPages, restorePages, startHistory, turnPages, undo, undoLabel };
291
+ export { HISTORY_LIMIT, type History, type KeyLike, PDF_COMING_SOON, PDF_SHORTCUTS, PDF_TOOLS, type PageDecisions, type PageOp, type PdfActionId, type PdfHostTool, type PdfHostToolContext, type PdfRunRequest, type PdfRunResult, type PdfShortcut, type PdfToolDef, type PdfToolId, type PdfViewerState, PdfWorkspace, type PdfWorkspaceHost, type PdfWorkspaceProps, type Turn, canRedo, canUndo, comingSoonIdOf, compilePageOps, deletePages, formatKeys, freshDecisions, isDirty, keptOrder, matchShortcut, pdfTool, pushStep, redo, redoLabel, reorderPages, restorePages, startHistory, turnPages, undo, undoLabel };
package/dist/pdf.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ReactNode } from 'react';
2
+ import { ComponentType, ReactNode } from 'react';
3
3
  import { ComingSoonEntry } from '@ai-matrx/kit/coming-soon';
4
4
 
5
5
  /**
@@ -62,6 +62,8 @@ interface PdfViewerState {
62
62
  rotations: Record<number, number>;
63
63
  /** Changes when the file changed on the server: the viewer must load it again. */
64
64
  reloadKey: number;
65
+ /** The page the person is on (1-based), passed only while a host tool with `followsPage` is open; otherwise 1. */
66
+ currentPage: number;
65
67
  /** The document parsed with this many pages. */
66
68
  onDocumentLoad(pageCount: number): void;
67
69
  /** A page was measured, in PDF points (crop and fit-page need it). */
@@ -119,6 +121,38 @@ type PdfRunResult =
119
121
  rows: string[][];
120
122
  }>;
121
123
  };
124
+ /** What the shell tells a host tool's panel about the session it sits in. */
125
+ interface PdfHostToolContext {
126
+ currentPage: number;
127
+ pageCount: number;
128
+ /** Original page numbers selected in the page panel (empty when none). */
129
+ selected: number[];
130
+ goToPage(n: number): void;
131
+ /** The file changed under the same id: draw the viewer and thumbnails again. */
132
+ reload(): void;
133
+ }
134
+ /**
135
+ * A tool the host brings to the rail. The shell gives it a rail button, a place in "All tools", the
136
+ * tool search and the right panel; the host owns what is inside (its own server calls and state).
137
+ * This is how an app folds its older studios into the workspace without the package knowing them.
138
+ */
139
+ interface PdfHostTool {
140
+ /** Unique among the host's tools. */
141
+ id: string;
142
+ label: string;
143
+ /** One short line under the panel title. */
144
+ hint?: string;
145
+ icon: ComponentType<{
146
+ className?: string;
147
+ }>;
148
+ /** The viewer receives `currentPage` while this tool is open (a one-page-at-a-time canvas needs it). */
149
+ followsPage?: boolean;
150
+ /** A wide panel (28rem) instead of the standard one (18rem). */
151
+ wide?: boolean;
152
+ /** Rail group: 1 (default) sits with the document tools. */
153
+ group?: 0 | 1 | 2;
154
+ render(context: PdfHostToolContext): ReactNode;
155
+ }
122
156
  interface PdfWorkspaceHost {
123
157
  file: {
124
158
  id: string;
@@ -155,6 +189,8 @@ interface PdfWorkspaceHost {
155
189
  id: string;
156
190
  label: string;
157
191
  }>>;
192
+ /** Extra tools the host brings (see `PdfHostTool`). */
193
+ tools?: PdfHostTool[];
158
194
  /** False while the device is offline: the save pill says so and edits are not queued. */
159
195
  online?: boolean;
160
196
  /** Show a failure to the person (the host's toast). Defaults to an inline banner. */
@@ -252,4 +288,4 @@ declare const canRedo: (h: History<unknown>) => boolean;
252
288
  declare const undoLabel: (h: History<unknown>) => string;
253
289
  declare const redoLabel: (h: History<unknown>) => string;
254
290
 
255
- export { HISTORY_LIMIT, type History, type KeyLike, PDF_COMING_SOON, PDF_SHORTCUTS, PDF_TOOLS, type PageDecisions, type PageOp, type PdfActionId, type PdfRunRequest, type PdfRunResult, type PdfShortcut, type PdfToolDef, type PdfToolId, type PdfViewerState, PdfWorkspace, type PdfWorkspaceHost, type PdfWorkspaceProps, type Turn, canRedo, canUndo, comingSoonIdOf, compilePageOps, deletePages, formatKeys, freshDecisions, isDirty, keptOrder, matchShortcut, pdfTool, pushStep, redo, redoLabel, reorderPages, restorePages, startHistory, turnPages, undo, undoLabel };
291
+ export { HISTORY_LIMIT, type History, type KeyLike, PDF_COMING_SOON, PDF_SHORTCUTS, PDF_TOOLS, type PageDecisions, type PageOp, type PdfActionId, type PdfHostTool, type PdfHostToolContext, type PdfRunRequest, type PdfRunResult, type PdfShortcut, type PdfToolDef, type PdfToolId, type PdfViewerState, PdfWorkspace, type PdfWorkspaceHost, type PdfWorkspaceProps, type Turn, canRedo, canUndo, comingSoonIdOf, compilePageOps, deletePages, formatKeys, freshDecisions, isDirty, keptOrder, matchShortcut, pdfTool, pushStep, redo, redoLabel, reorderPages, restorePages, startHistory, turnPages, undo, undoLabel };
package/dist/pdf.js CHANGED
@@ -564,25 +564,41 @@ function useWidth(ref) {
564
564
  }, [ref]);
565
565
  return size;
566
566
  }
567
- function ToolRows({ tool, onPick }) {
568
- return /* @__PURE__ */ jsx3(Fragment3, { children: PDF_TOOLS.filter((t) => t.id !== "browse").map((t) => {
569
- const Icon = PDF_TOOL_ICONS[t.id];
570
- return /* @__PURE__ */ jsx3("li", { role: "none", children: /* @__PURE__ */ jsxs3(
567
+ function ToolRows({ tool, hostTools, onPick }) {
568
+ return /* @__PURE__ */ jsxs3(Fragment3, { children: [
569
+ hostTools.map((t) => /* @__PURE__ */ jsx3("li", { role: "none", children: /* @__PURE__ */ jsxs3(
571
570
  "button",
572
571
  {
573
572
  type: "button",
574
573
  role: "menuitem",
575
- "aria-current": t.id === tool ? "true" : void 0,
576
- className: cn("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", t.id === tool && "bg-accent"),
577
- onClick: () => onPick(t.id),
574
+ "aria-current": tool === `host:${t.id}` ? "true" : void 0,
575
+ className: cn("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", tool === `host:${t.id}` && "bg-accent"),
576
+ onClick: () => onPick(`host:${t.id}`),
578
577
  children: [
579
- /* @__PURE__ */ jsx3(Icon, { className: "size-4 shrink-0" }),
580
- /* @__PURE__ */ jsx3("span", { className: "flex-1 whitespace-nowrap", children: t.label }),
581
- t.status === "soon" ? /* @__PURE__ */ jsx3("span", { className: "text-muted-foreground", children: "Coming soon" }) : null
578
+ /* @__PURE__ */ jsx3(t.icon, { className: "size-4 shrink-0" }),
579
+ /* @__PURE__ */ jsx3("span", { className: "flex-1 whitespace-nowrap", children: t.label })
582
580
  ]
583
581
  }
584
- ) }, t.id);
585
- }) });
582
+ ) }, `host:${t.id}`)),
583
+ PDF_TOOLS.filter((t) => t.id !== "browse").map((t) => {
584
+ const Icon = PDF_TOOL_ICONS[t.id];
585
+ return /* @__PURE__ */ jsx3("li", { role: "none", children: /* @__PURE__ */ jsxs3(
586
+ "button",
587
+ {
588
+ type: "button",
589
+ role: "menuitem",
590
+ "aria-current": t.id === tool ? "true" : void 0,
591
+ className: cn("flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-xs hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", t.id === tool && "bg-accent"),
592
+ onClick: () => onPick(t.id),
593
+ children: [
594
+ /* @__PURE__ */ jsx3(Icon, { className: "size-4 shrink-0" }),
595
+ /* @__PURE__ */ jsx3("span", { className: "flex-1 whitespace-nowrap", children: t.label }),
596
+ t.status === "soon" ? /* @__PURE__ */ jsx3("span", { className: "text-muted-foreground", children: "Coming soon" }) : null
597
+ ]
598
+ }
599
+ ) }, t.id);
600
+ })
601
+ ] });
586
602
  }
587
603
  function PdfWorkspace({ host, className }) {
588
604
  const rootRef = useRef2(null);
@@ -596,6 +612,10 @@ function PdfWorkspace({ host, className }) {
596
612
  const decisions = history.present.value;
597
613
  const dirty = isDirty(decisions);
598
614
  const [tool, setTool] = useState3("browse");
615
+ const [hostToolId, setHostToolId] = useState3(null);
616
+ const hostTools = useMemo2(() => host.tools ?? [], [host.tools]);
617
+ const hostTool = hostToolId ? hostTools.find((t) => t.id === hostToolId) ?? null : null;
618
+ const activeToolKey = hostTool ? `host:${hostTool.id}` : tool;
599
619
  const [leftOpen, setLeftOpen] = useState3(true);
600
620
  const [rightOpen, setRightOpen] = useState3(true);
601
621
  const [leftTab, setLeftTab] = useState3("pages");
@@ -748,8 +768,17 @@ function PdfWorkspace({ host, className }) {
748
768
  const discard = useCallback(() => setHistory(startHistory(freshDecisions(pageCount))), [pageCount]);
749
769
  const chooseTool = useCallback(
750
770
  (id) => {
771
+ if (id.startsWith("host:")) {
772
+ setHostToolId(id.slice(5));
773
+ setResult(null);
774
+ setError(null);
775
+ setRightOpen(true);
776
+ if (compact) setSheet("tools");
777
+ return;
778
+ }
751
779
  const def = pdfTool(id);
752
780
  if (!def) return;
781
+ setHostToolId(null);
753
782
  if (def.status === "soon") {
754
783
  announceSoon(comingSoonIdOf(def.id)).catch(fail);
755
784
  return;
@@ -772,9 +801,10 @@ function PdfWorkspace({ host, className }) {
772
801
  if (t.status !== "ready") continue;
773
802
  groups[t.group].push({ id: t.id, label: t.label, icon: PDF_TOOL_ICONS[t.id], ...t.key ? { shortcut: t.key.toUpperCase() } : null });
774
803
  }
804
+ for (const t of hostTools) groups[t.group ?? 1].push({ id: `host:${t.id}`, label: t.label, icon: t.icon });
775
805
  groups[2].push({ id: ALL_TOOLS, label: "All tools", icon: MoreHorizontalIcon });
776
806
  return groups.filter((g) => g.length);
777
- }, []);
807
+ }, [hostTools]);
778
808
  const runAction = useCallback(
779
809
  (action) => {
780
810
  if (action.startsWith("tool:")) return chooseTool(action.slice(5));
@@ -862,7 +892,10 @@ function PdfWorkspace({ host, className }) {
862
892
  }
863
893
  );
864
894
  const iconBtn = (label, icon, onClick, opts) => /* @__PURE__ */ jsx3(Button2, { variant: "quiet", icon, "aria-label": label, title: label, onClick, ...opts?.disabled !== void 0 ? { disabled: opts.disabled } : null, ...opts?.pressed !== void 0 ? { pressed: opts.pressed } : null });
865
- const toolHits = toolQuery.trim() ? PDF_TOOLS.filter((t) => t.label.toLowerCase().includes(toolQuery.trim().toLowerCase())) : [];
895
+ const toolHits = toolQuery.trim() ? [
896
+ ...hostTools.map((t) => ({ id: `host:${t.id}`, label: t.label, status: "ready" })),
897
+ ...PDF_TOOLS
898
+ ].filter((t) => t.label.toLowerCase().includes(toolQuery.trim().toLowerCase())) : [];
866
899
  const nameNode = editingName && host.rename ? /* @__PURE__ */ jsx3(
867
900
  Field2,
868
901
  {
@@ -893,7 +926,13 @@ function PdfWorkspace({ host, className }) {
893
926
  children: host.file.name
894
927
  }
895
928
  );
896
- const rightPanel = /* @__PURE__ */ jsxs3("div", { className: "flex h-full min-h-0 flex-col", children: [
929
+ const rightPanel = hostTool ? /* @__PURE__ */ jsxs3("div", { className: "flex h-full min-h-0 flex-col", "data-pdf-host-tool": hostTool.id, children: [
930
+ /* @__PURE__ */ jsxs3("div", { className: "shrink-0 border-b border-border px-3 py-2", children: [
931
+ /* @__PURE__ */ jsx3("div", { className: "text-sm font-medium", children: hostTool.label }),
932
+ hostTool.hint ? /* @__PURE__ */ jsx3("div", { className: "text-xs text-muted-foreground", children: hostTool.hint }) : null
933
+ ] }),
934
+ /* @__PURE__ */ jsx3("div", { className: "min-h-0 flex-1 overflow-hidden", children: hostTool.render({ currentPage, pageCount, selected: selectedPages, goToPage, reload: () => setReloadKey((k) => k + 1) }) })
935
+ ] }) : /* @__PURE__ */ jsxs3("div", { className: "flex h-full min-h-0 flex-col", children: [
897
936
  /* @__PURE__ */ jsxs3("div", { className: "shrink-0 border-b border-border px-3 py-2", children: [
898
937
  /* @__PURE__ */ jsx3("div", { className: "text-sm font-medium", children: toolDef.label }),
899
938
  toolDef.hint ? /* @__PURE__ */ jsx3("div", { className: "text-xs text-muted-foreground", children: toolDef.hint }) : null
@@ -940,9 +979,10 @@ function PdfWorkspace({ host, className }) {
940
979
  onLayersSoon: () => void announceSoon("pdf.layers").catch(fail)
941
980
  }
942
981
  );
982
+ const viewerPage = hostTool?.followsPage ? currentPage : 1;
943
983
  const viewer = useMemo2(
944
- () => /* @__PURE__ */ jsx3(Fragment2, { children: host.renderViewer({ zoom, spread, rotations: decisions.turns, reloadKey, onDocumentLoad, onPageSize }) }, reloadKey),
945
- [host, reloadKey, zoom, spread, decisions.turns, onDocumentLoad, onPageSize]
984
+ () => /* @__PURE__ */ jsx3(Fragment2, { children: host.renderViewer({ zoom, spread, rotations: decisions.turns, reloadKey, currentPage: viewerPage, onDocumentLoad, onPageSize }) }, reloadKey),
985
+ [host, reloadKey, zoom, spread, decisions.turns, viewerPage, onDocumentLoad, onPageSize]
946
986
  );
947
987
  const showChrome = !read;
948
988
  const popCard = "absolute right-2 top-11 z-30 rounded-lg border border-border bg-popover p-3 text-popover-foreground shadow-lg";
@@ -1055,15 +1095,15 @@ function PdfWorkspace({ host, className }) {
1055
1095
  iconBtn("Reading mode", /* @__PURE__ */ jsx3(ExpandIcon, {}), () => setRead(true))
1056
1096
  ] }) : null,
1057
1097
  /* @__PURE__ */ jsxs3("div", { className: "relative flex min-h-0 flex-1", children: [
1058
- showChrome && !compact ? /* @__PURE__ */ jsx3("div", { className: "flex w-10 shrink-0 flex-col items-center border-r border-border bg-background py-2", "data-pdf-rail": "", children: /* @__PURE__ */ jsx3(ToolRail, { groups: railGroups, value: pop === "all-tools" ? ALL_TOOLS : tool, onValueChange: (id) => id === ALL_TOOLS ? setPop((p) => p === "all-tools" ? null : "all-tools") : id && chooseTool(id), "aria-label": "PDF tools" }) }) : null,
1098
+ showChrome && !compact ? /* @__PURE__ */ jsx3("div", { className: "flex w-10 shrink-0 flex-col items-center border-r border-border bg-background py-2", "data-pdf-rail": "", children: /* @__PURE__ */ jsx3(ToolRail, { groups: railGroups, value: pop === "all-tools" ? ALL_TOOLS : activeToolKey, onValueChange: (id) => id === ALL_TOOLS ? setPop((p) => p === "all-tools" ? null : "all-tools") : id && chooseTool(id), "aria-label": "PDF tools" }) }) : null,
1059
1099
  showChrome && !compact && leftOpen ? /* @__PURE__ */ jsx3("aside", { className: "w-56 shrink-0 border-r border-border bg-background", "aria-label": "Pages", "data-pdf-left": "", children: leftPanel }) : null,
1060
1100
  /* @__PURE__ */ jsxs3("main", { className: "relative flex min-w-0 flex-1 flex-col", children: [
1061
1101
  findOpen ? /* @__PURE__ */ jsx3("div", { className: "absolute right-4 top-2 z-20", children: /* @__PURE__ */ jsx3(RenderedFindBar, { rootRef: scrollerRef, onClose: () => setFindOpen(false), label: "Find in document", focusRequest: findFocus, compact: true }) }) : null,
1062
1102
  /* @__PURE__ */ jsx3("div", { ref: scrollerRef, tabIndex: 0, "data-pdf-scroller": "", className: "min-h-0 flex-1 overflow-auto bg-muted outline-none", children: viewer }),
1063
1103
  read ? /* @__PURE__ */ jsx3("div", { className: "absolute right-3 top-3 z-20", children: /* @__PURE__ */ jsx3(Button2, { variant: "outline", icon: /* @__PURE__ */ jsx3(XIcon, {}), onClick: () => setRead(false), children: "Exit reading mode" }) }) : null
1064
1104
  ] }),
1065
- showChrome && !compact && rightOpen ? /* @__PURE__ */ jsx3("aside", { className: "w-72 shrink-0 border-l border-border bg-background", "aria-label": "Properties", "data-pdf-right": "", children: rightPanel }) : null,
1066
- pop === "all-tools" ? /* @__PURE__ */ jsx3("ul", { role: "menu", "aria-label": "All tools", className: "absolute left-12 top-2 z-30 w-72 rounded-lg border border-border bg-popover p-1 shadow-lg", "data-pdf-all-tools": "", children: /* @__PURE__ */ jsx3(ToolRows, { tool, onPick: (id) => {
1105
+ showChrome && !compact && rightOpen ? /* @__PURE__ */ jsx3("aside", { className: cn("shrink-0 border-l border-border bg-background", hostTool?.wide ? "w-[28rem]" : "w-72"), "aria-label": "Properties", "data-pdf-right": "", children: rightPanel }) : null,
1106
+ pop === "all-tools" ? /* @__PURE__ */ jsx3("ul", { role: "menu", "aria-label": "All tools", className: "absolute left-12 top-2 z-30 w-72 rounded-lg border border-border bg-popover p-1 shadow-lg", "data-pdf-all-tools": "", children: /* @__PURE__ */ jsx3(ToolRows, { tool: activeToolKey, hostTools, onPick: (id) => {
1067
1107
  setPop(null);
1068
1108
  chooseTool(id);
1069
1109
  } }) }) : null,
@@ -1094,7 +1134,7 @@ function PdfWorkspace({ host, className }) {
1094
1134
  compact && sheet ? /* @__PURE__ */ jsxs3(Fragment3, { children: [
1095
1135
  /* @__PURE__ */ jsx3("button", { type: "button", "aria-label": "Close", className: "absolute inset-0 z-30 bg-background/60", onClick: () => setSheet(null) }),
1096
1136
  /* @__PURE__ */ jsx3("div", { className: "absolute inset-x-0 bottom-0 z-40 flex max-h-[75%] flex-col rounded-t-xl border-t border-border bg-background", role: "dialog", "aria-label": sheet === "pages" ? "Pages" : "Tools", children: sheet === "pages" ? /* @__PURE__ */ jsx3("div", { className: "h-[60vh] min-h-0", children: leftPanel }) : /* @__PURE__ */ jsxs3("div", { className: "flex min-h-0 flex-col overflow-y-auto", children: [
1097
- /* @__PURE__ */ jsx3("ul", { className: "p-2", role: "menu", "aria-label": "Tools", children: /* @__PURE__ */ jsx3(ToolRows, { tool, onPick: chooseTool }) }),
1137
+ /* @__PURE__ */ jsx3("ul", { className: "p-2", role: "menu", "aria-label": "Tools", children: /* @__PURE__ */ jsx3(ToolRows, { tool: activeToolKey, hostTools, onPick: chooseTool }) }),
1098
1138
  /* @__PURE__ */ jsx3("div", { className: "border-t border-border", children: rightPanel })
1099
1139
  ] }) })
1100
1140
  ] }) : null