@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/CHANGELOG.md CHANGED
@@ -1,10 +1,15 @@
1
1
  # Changelog
2
2
 
3
- ## 0.8.48
3
+ ## 0.8.49
4
4
 
5
5
  UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
6
6
  Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/office/src`.
7
7
 
8
+ ## 0.8.48
9
+
10
+ Automatic changed-only republish (docs/metadata drift since the last published version; verified: `git diff 5da59424ae 184cfc8959 -- apps/shared/office/src`
11
+ has no shipped-source changes outside tests, fixtures and docs). No consumer action required.
12
+
8
13
  ## 0.8.47
9
14
 
10
15
  - `EditorBridgeLike` / `FilterServiceLike` accept Univer's own `IEditorBridgeService` and `SheetsFilterService` types (their `Nullable<…>` returns, `IRange`): a host passing `injector.get(IEditorBridgeService)` to `editorBridgeCell`, or the filter service to `filterServiceRange`, type-checks. New `FilterRangeLike`. Consumer action: none.
@@ -305,6 +310,7 @@ Changed shipped source files (8):
305
310
 
306
311
  ### Unreleased
307
312
 
313
+ - `./pdf`: `PdfWorkspaceHost.tools` lets the host bring its own rail tools (`PdfHostTool`: id, label, icon, `render(context)`, optional `wide` and `followsPage`); the shell gives each a rail button, an All-tools row, tool-search hit and the right panel, and tells it the page, page count, selection, `goToPage` and `reload`. `PdfViewerState.currentPage` is passed while a `followsPage` tool is open. Consumer action: none (optional).
308
314
  - **US spelling: the British spelling of "color" no longer exists in this package (Arman, 2026-10-21).** Every label, template string, comment, identifier, CSS class/variable and test name that spelled it the British way now says color. Guard: `design-system/src/us-spelling.test.ts` scans all of `apps/` for the word. Consumer action: none for imports; if you matched on a British-spelled identifier, class or CSS variable from this package, use the `color` spelling; update the package.
309
315
  - **Sheets co-editing on the ordered log (C6).** `@ai-matrx/office/univer/collab` adds the Sheets room: `openSheetsOtRoom` (the C2 session over the C5a/C5b group transform, saves at a quiet point with a matching hash, restore through `collab_replace`, undo items rebased over every remote op), `univerSheetsOtPort` (capture: onlyLocal/fromCollab filtered, grouped by outermost command with a try/finally depth guard on both execute paths, params allowlist, completeCellContent, exact merge removals, style objects never ids, whole-style overrides restated as merges, annotateFormulas, inverses from the applied params against a pre-state copy; a barrier or unknown id is `not_shared` and rolls the seat back), `sheetsStateHash` / `canonicalSheet` (merges as a set, defined names by id; the transform fuzz now hashes through it), and `startWorkbookOtRoom` / `workbookUsesOrderedRoom` (the `udt_workbook_snapshots` store, the C1 doors, presence). A remote row/column insert, remove or move carries this seat's selection along and never leaves it past the sheet's edge (the port's `selections` option; a stale whole-row selection after a peer's column delete crashed the editor in the live run). Remote applies run with `{ fromCollab: true }` only (not `onlyLocal`): Univer's formula engine skips onlyLocal value writes, so a peer's formula showed blank on every other seat in the live run. Flip is per room exactly like Docs. Consumer action: matrx-frontend's WorkbookEditor opens it when the workbook's room exists or `collab.ot_rooms` says so (shipped with this release); every other consumer: none.
310
316
 
@@ -1,5 +1,5 @@
1
1
  import { ComingSoonEntry } from '@ai-matrx/kit/coming-soon';
2
- import { ReactNode } from 'react';
2
+ import { ComponentType, ReactNode } from 'react';
3
3
 
4
4
  /**
5
5
  * The PDF workspace's tool rail, as data. Pure (no React, no icons): the host registers the
@@ -146,6 +146,8 @@ interface PdfViewerState {
146
146
  rotations: Record<number, number>;
147
147
  /** Changes when the file changed on the server: the viewer must load it again. */
148
148
  reloadKey: number;
149
+ /** The page the person is on (1-based), passed only while a host tool with `followsPage` is open; otherwise 1. */
150
+ currentPage: number;
149
151
  /** The document parsed with this many pages. */
150
152
  onDocumentLoad(pageCount: number): void;
151
153
  /** A page was measured, in PDF points (crop and fit-page need it). */
@@ -203,6 +205,38 @@ type PdfRunResult =
203
205
  rows: string[][];
204
206
  }>;
205
207
  };
208
+ /** What the shell tells a host tool's panel about the session it sits in. */
209
+ interface PdfHostToolContext {
210
+ currentPage: number;
211
+ pageCount: number;
212
+ /** Original page numbers selected in the page panel (empty when none). */
213
+ selected: number[];
214
+ goToPage(n: number): void;
215
+ /** The file changed under the same id: draw the viewer and thumbnails again. */
216
+ reload(): void;
217
+ }
218
+ /**
219
+ * A tool the host brings to the rail. The shell gives it a rail button, a place in "All tools", the
220
+ * tool search and the right panel; the host owns what is inside (its own server calls and state).
221
+ * This is how an app folds its older studios into the workspace without the package knowing them.
222
+ */
223
+ interface PdfHostTool {
224
+ /** Unique among the host's tools. */
225
+ id: string;
226
+ label: string;
227
+ /** One short line under the panel title. */
228
+ hint?: string;
229
+ icon: ComponentType<{
230
+ className?: string;
231
+ }>;
232
+ /** The viewer receives `currentPage` while this tool is open (a one-page-at-a-time canvas needs it). */
233
+ followsPage?: boolean;
234
+ /** A wide panel (28rem) instead of the standard one (18rem). */
235
+ wide?: boolean;
236
+ /** Rail group: 1 (default) sits with the document tools. */
237
+ group?: 0 | 1 | 2;
238
+ render(context: PdfHostToolContext): ReactNode;
239
+ }
206
240
  interface PdfWorkspaceHost {
207
241
  file: {
208
242
  id: string;
@@ -239,10 +273,12 @@ interface PdfWorkspaceHost {
239
273
  id: string;
240
274
  label: string;
241
275
  }>>;
276
+ /** Extra tools the host brings (see `PdfHostTool`). */
277
+ tools?: PdfHostTool[];
242
278
  /** False while the device is offline: the save pill says so and edits are not queued. */
243
279
  online?: boolean;
244
280
  /** Show a failure to the person (the host's toast). Defaults to an inline banner. */
245
281
  notify?(message: string, tone: "error" | "info"): void;
246
282
  }
247
283
 
248
- 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, type PdfWorkspaceHost, type Turn, canRedo, canUndo, comingSoonIdOf, compilePageOps, deletePages, formatKeys, freshDecisions, isDirty, keptOrder, matchShortcut, pdfTool, pushStep, redo, redoLabel, reorderPages, restorePages, startHistory, turnPages, undo, undoLabel };
284
+ 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, type PdfWorkspaceHost, type Turn, canRedo, canUndo, comingSoonIdOf, compilePageOps, deletePages, formatKeys, freshDecisions, isDirty, keptOrder, matchShortcut, pdfTool, pushStep, redo, redoLabel, reorderPages, restorePages, startHistory, turnPages, undo, undoLabel };
@@ -1,5 +1,5 @@
1
1
  import { ComingSoonEntry } from '@ai-matrx/kit/coming-soon';
2
- import { ReactNode } from 'react';
2
+ import { ComponentType, ReactNode } from 'react';
3
3
 
4
4
  /**
5
5
  * The PDF workspace's tool rail, as data. Pure (no React, no icons): the host registers the
@@ -146,6 +146,8 @@ interface PdfViewerState {
146
146
  rotations: Record<number, number>;
147
147
  /** Changes when the file changed on the server: the viewer must load it again. */
148
148
  reloadKey: number;
149
+ /** The page the person is on (1-based), passed only while a host tool with `followsPage` is open; otherwise 1. */
150
+ currentPage: number;
149
151
  /** The document parsed with this many pages. */
150
152
  onDocumentLoad(pageCount: number): void;
151
153
  /** A page was measured, in PDF points (crop and fit-page need it). */
@@ -203,6 +205,38 @@ type PdfRunResult =
203
205
  rows: string[][];
204
206
  }>;
205
207
  };
208
+ /** What the shell tells a host tool's panel about the session it sits in. */
209
+ interface PdfHostToolContext {
210
+ currentPage: number;
211
+ pageCount: number;
212
+ /** Original page numbers selected in the page panel (empty when none). */
213
+ selected: number[];
214
+ goToPage(n: number): void;
215
+ /** The file changed under the same id: draw the viewer and thumbnails again. */
216
+ reload(): void;
217
+ }
218
+ /**
219
+ * A tool the host brings to the rail. The shell gives it a rail button, a place in "All tools", the
220
+ * tool search and the right panel; the host owns what is inside (its own server calls and state).
221
+ * This is how an app folds its older studios into the workspace without the package knowing them.
222
+ */
223
+ interface PdfHostTool {
224
+ /** Unique among the host's tools. */
225
+ id: string;
226
+ label: string;
227
+ /** One short line under the panel title. */
228
+ hint?: string;
229
+ icon: ComponentType<{
230
+ className?: string;
231
+ }>;
232
+ /** The viewer receives `currentPage` while this tool is open (a one-page-at-a-time canvas needs it). */
233
+ followsPage?: boolean;
234
+ /** A wide panel (28rem) instead of the standard one (18rem). */
235
+ wide?: boolean;
236
+ /** Rail group: 1 (default) sits with the document tools. */
237
+ group?: 0 | 1 | 2;
238
+ render(context: PdfHostToolContext): ReactNode;
239
+ }
206
240
  interface PdfWorkspaceHost {
207
241
  file: {
208
242
  id: string;
@@ -239,10 +273,12 @@ interface PdfWorkspaceHost {
239
273
  id: string;
240
274
  label: string;
241
275
  }>>;
276
+ /** Extra tools the host brings (see `PdfHostTool`). */
277
+ tools?: PdfHostTool[];
242
278
  /** False while the device is offline: the save pill says so and edits are not queued. */
243
279
  online?: boolean;
244
280
  /** Show a failure to the person (the host's toast). Defaults to an inline banner. */
245
281
  notify?(message: string, tone: "error" | "info"): void;
246
282
  }
247
283
 
248
- 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, type PdfWorkspaceHost, type Turn, canRedo, canUndo, comingSoonIdOf, compilePageOps, deletePages, formatKeys, freshDecisions, isDirty, keptOrder, matchShortcut, pdfTool, pushStep, redo, redoLabel, reorderPages, restorePages, startHistory, turnPages, undo, undoLabel };
284
+ 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, type PdfWorkspaceHost, 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.cjs CHANGED
@@ -585,25 +585,41 @@ function useWidth(ref) {
585
585
  }, [ref]);
586
586
  return size;
587
587
  }
588
- function ToolRows({ tool, onPick }) {
589
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_jsx_runtime3.Fragment, { children: PDF_TOOLS.filter((t) => t.id !== "browse").map((t) => {
590
- const Icon = PDF_TOOL_ICONS[t.id];
591
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
588
+ function ToolRows({ tool, hostTools, onPick }) {
589
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
590
+ hostTools.map((t) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
592
591
  "button",
593
592
  {
594
593
  type: "button",
595
594
  role: "menuitem",
596
- "aria-current": t.id === tool ? "true" : void 0,
597
- className: (0, import_cn.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"),
598
- onClick: () => onPick(t.id),
595
+ "aria-current": tool === `host:${t.id}` ? "true" : void 0,
596
+ className: (0, import_cn.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"),
597
+ onClick: () => onPick(`host:${t.id}`),
599
598
  children: [
600
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { className: "size-4 shrink-0" }),
601
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "flex-1 whitespace-nowrap", children: t.label }),
602
- t.status === "soon" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-muted-foreground", children: "Coming soon" }) : null
599
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(t.icon, { className: "size-4 shrink-0" }),
600
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "flex-1 whitespace-nowrap", children: t.label })
603
601
  ]
604
602
  }
605
- ) }, t.id);
606
- }) });
603
+ ) }, `host:${t.id}`)),
604
+ PDF_TOOLS.filter((t) => t.id !== "browse").map((t) => {
605
+ const Icon = PDF_TOOL_ICONS[t.id];
606
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("li", { role: "none", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
607
+ "button",
608
+ {
609
+ type: "button",
610
+ role: "menuitem",
611
+ "aria-current": t.id === tool ? "true" : void 0,
612
+ className: (0, import_cn.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"),
613
+ onClick: () => onPick(t.id),
614
+ children: [
615
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(Icon, { className: "size-4 shrink-0" }),
616
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "flex-1 whitespace-nowrap", children: t.label }),
617
+ t.status === "soon" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-muted-foreground", children: "Coming soon" }) : null
618
+ ]
619
+ }
620
+ ) }, t.id);
621
+ })
622
+ ] });
607
623
  }
608
624
  function PdfWorkspace({ host, className }) {
609
625
  const rootRef = (0, import_react3.useRef)(null);
@@ -617,6 +633,10 @@ function PdfWorkspace({ host, className }) {
617
633
  const decisions = history.present.value;
618
634
  const dirty = isDirty(decisions);
619
635
  const [tool, setTool] = (0, import_react3.useState)("browse");
636
+ const [hostToolId, setHostToolId] = (0, import_react3.useState)(null);
637
+ const hostTools = (0, import_react3.useMemo)(() => host.tools ?? [], [host.tools]);
638
+ const hostTool = hostToolId ? hostTools.find((t) => t.id === hostToolId) ?? null : null;
639
+ const activeToolKey = hostTool ? `host:${hostTool.id}` : tool;
620
640
  const [leftOpen, setLeftOpen] = (0, import_react3.useState)(true);
621
641
  const [rightOpen, setRightOpen] = (0, import_react3.useState)(true);
622
642
  const [leftTab, setLeftTab] = (0, import_react3.useState)("pages");
@@ -769,8 +789,17 @@ function PdfWorkspace({ host, className }) {
769
789
  const discard = (0, import_react3.useCallback)(() => setHistory(startHistory(freshDecisions(pageCount))), [pageCount]);
770
790
  const chooseTool = (0, import_react3.useCallback)(
771
791
  (id) => {
792
+ if (id.startsWith("host:")) {
793
+ setHostToolId(id.slice(5));
794
+ setResult(null);
795
+ setError(null);
796
+ setRightOpen(true);
797
+ if (compact) setSheet("tools");
798
+ return;
799
+ }
772
800
  const def = pdfTool(id);
773
801
  if (!def) return;
802
+ setHostToolId(null);
774
803
  if (def.status === "soon") {
775
804
  announceSoon(comingSoonIdOf(def.id)).catch(fail);
776
805
  return;
@@ -793,9 +822,10 @@ function PdfWorkspace({ host, className }) {
793
822
  if (t.status !== "ready") continue;
794
823
  groups[t.group].push({ id: t.id, label: t.label, icon: PDF_TOOL_ICONS[t.id], ...t.key ? { shortcut: t.key.toUpperCase() } : null });
795
824
  }
825
+ for (const t of hostTools) groups[t.group ?? 1].push({ id: `host:${t.id}`, label: t.label, icon: t.icon });
796
826
  groups[2].push({ id: ALL_TOOLS, label: "All tools", icon: import_icons2.MoreHorizontalIcon });
797
827
  return groups.filter((g) => g.length);
798
- }, []);
828
+ }, [hostTools]);
799
829
  const runAction = (0, import_react3.useCallback)(
800
830
  (action) => {
801
831
  if (action.startsWith("tool:")) return chooseTool(action.slice(5));
@@ -883,7 +913,10 @@ function PdfWorkspace({ host, className }) {
883
913
  }
884
914
  );
885
915
  const iconBtn = (label, icon, onClick, opts) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_controls4.Button, { 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 });
886
- const toolHits = toolQuery.trim() ? PDF_TOOLS.filter((t) => t.label.toLowerCase().includes(toolQuery.trim().toLowerCase())) : [];
916
+ const toolHits = toolQuery.trim() ? [
917
+ ...hostTools.map((t) => ({ id: `host:${t.id}`, label: t.label, status: "ready" })),
918
+ ...PDF_TOOLS
919
+ ].filter((t) => t.label.toLowerCase().includes(toolQuery.trim().toLowerCase())) : [];
887
920
  const nameNode = editingName && host.rename ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
888
921
  import_controls4.Field,
889
922
  {
@@ -914,7 +947,13 @@ function PdfWorkspace({ host, className }) {
914
947
  children: host.file.name
915
948
  }
916
949
  );
917
- const rightPanel = /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex h-full min-h-0 flex-col", children: [
950
+ const rightPanel = hostTool ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex h-full min-h-0 flex-col", "data-pdf-host-tool": hostTool.id, children: [
951
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "shrink-0 border-b border-border px-3 py-2", children: [
952
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "text-sm font-medium", children: hostTool.label }),
953
+ hostTool.hint ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "text-xs text-muted-foreground", children: hostTool.hint }) : null
954
+ ] }),
955
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "min-h-0 flex-1 overflow-hidden", children: hostTool.render({ currentPage, pageCount, selected: selectedPages, goToPage, reload: () => setReloadKey((k) => k + 1) }) })
956
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex h-full min-h-0 flex-col", children: [
918
957
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "shrink-0 border-b border-border px-3 py-2", children: [
919
958
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "text-sm font-medium", children: toolDef.label }),
920
959
  toolDef.hint ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "text-xs text-muted-foreground", children: toolDef.hint }) : null
@@ -961,9 +1000,10 @@ function PdfWorkspace({ host, className }) {
961
1000
  onLayersSoon: () => void announceSoon("pdf.layers").catch(fail)
962
1001
  }
963
1002
  );
1003
+ const viewerPage = hostTool?.followsPage ? currentPage : 1;
964
1004
  const viewer = (0, import_react3.useMemo)(
965
- () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react3.Fragment, { children: host.renderViewer({ zoom, spread, rotations: decisions.turns, reloadKey, onDocumentLoad, onPageSize }) }, reloadKey),
966
- [host, reloadKey, zoom, spread, decisions.turns, onDocumentLoad, onPageSize]
1005
+ () => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_react3.Fragment, { children: host.renderViewer({ zoom, spread, rotations: decisions.turns, reloadKey, currentPage: viewerPage, onDocumentLoad, onPageSize }) }, reloadKey),
1006
+ [host, reloadKey, zoom, spread, decisions.turns, viewerPage, onDocumentLoad, onPageSize]
967
1007
  );
968
1008
  const showChrome = !read;
969
1009
  const popCard = "absolute right-2 top-11 z-30 rounded-lg border border-border bg-popover p-3 text-popover-foreground shadow-lg";
@@ -1076,15 +1116,15 @@ function PdfWorkspace({ host, className }) {
1076
1116
  iconBtn("Reading mode", /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.ExpandIcon, {}), () => setRead(true))
1077
1117
  ] }) : null,
1078
1118
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "relative flex min-h-0 flex-1", children: [
1079
- showChrome && !compact ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex w-10 shrink-0 flex-col items-center border-r border-border bg-background py-2", "data-pdf-rail": "", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_controls4.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,
1119
+ showChrome && !compact ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "flex w-10 shrink-0 flex-col items-center border-r border-border bg-background py-2", "data-pdf-rail": "", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_controls4.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,
1080
1120
  showChrome && !compact && leftOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("aside", { className: "w-56 shrink-0 border-r border-border bg-background", "aria-label": "Pages", "data-pdf-left": "", children: leftPanel }) : null,
1081
1121
  /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("main", { className: "relative flex min-w-0 flex-1 flex-col", children: [
1082
1122
  findOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "absolute right-4 top-2 z-20", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_RenderedFindBar.RenderedFindBar, { rootRef: scrollerRef, onClose: () => setFindOpen(false), label: "Find in document", focusRequest: findFocus, compact: true }) }) : null,
1083
1123
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { ref: scrollerRef, tabIndex: 0, "data-pdf-scroller": "", className: "min-h-0 flex-1 overflow-auto bg-muted outline-none", children: viewer }),
1084
1124
  read ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "absolute right-3 top-3 z-20", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_controls4.Button, { variant: "outline", icon: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_icons2.XIcon, {}), onClick: () => setRead(false), children: "Exit reading mode" }) }) : null
1085
1125
  ] }),
1086
- showChrome && !compact && rightOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("aside", { className: "w-72 shrink-0 border-l border-border bg-background", "aria-label": "Properties", "data-pdf-right": "", children: rightPanel }) : null,
1087
- pop === "all-tools" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("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__ */ (0, import_jsx_runtime3.jsx)(ToolRows, { tool, onPick: (id) => {
1126
+ showChrome && !compact && rightOpen ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("aside", { className: (0, import_cn.cn)("shrink-0 border-l border-border bg-background", hostTool?.wide ? "w-[28rem]" : "w-72"), "aria-label": "Properties", "data-pdf-right": "", children: rightPanel }) : null,
1127
+ pop === "all-tools" ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("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__ */ (0, import_jsx_runtime3.jsx)(ToolRows, { tool: activeToolKey, hostTools, onPick: (id) => {
1088
1128
  setPop(null);
1089
1129
  chooseTool(id);
1090
1130
  } }) }) : null,
@@ -1115,7 +1155,7 @@ function PdfWorkspace({ host, className }) {
1115
1155
  compact && sheet ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
1116
1156
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", "aria-label": "Close", className: "absolute inset-0 z-30 bg-background/60", onClick: () => setSheet(null) }),
1117
1157
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("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__ */ (0, import_jsx_runtime3.jsx)("div", { className: "h-[60vh] min-h-0", children: leftPanel }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex min-h-0 flex-col overflow-y-auto", children: [
1118
- /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "p-2", role: "menu", "aria-label": "Tools", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToolRows, { tool, onPick: chooseTool }) }),
1158
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("ul", { className: "p-2", role: "menu", "aria-label": "Tools", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ToolRows, { tool: activeToolKey, hostTools, onPick: chooseTool }) }),
1119
1159
  /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "border-t border-border", children: rightPanel })
1120
1160
  ] }) })
1121
1161
  ] }) : null