@arbidocs/blocks 0.5.118 → 0.5.120

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 (145) hide show
  1. package/dist/{ConnectedCallDock-E7RMQMMT.cjs → ConnectedCallDock-WER7R222.cjs} +12 -12
  2. package/dist/{ConnectedCallDock-E7RMQMMT.cjs.map → ConnectedCallDock-WER7R222.cjs.map} +1 -1
  3. package/dist/{ConnectedCallRoom-FF7X6LQ2.cjs → ConnectedCallRoom-T7OBQTYP.cjs} +12 -12
  4. package/dist/{ConnectedCallRoom-FF7X6LQ2.cjs.map → ConnectedCallRoom-T7OBQTYP.cjs.map} +1 -1
  5. package/dist/{ConnectedNativeDocxComparison-PB2LXT5U.cjs → ConnectedNativeDocxComparison-SGE4R3M4.cjs} +11 -11
  6. package/dist/{ConnectedNativeDocxComparison-PB2LXT5U.cjs.map → ConnectedNativeDocxComparison-SGE4R3M4.cjs.map} +1 -1
  7. package/dist/{ConnectedStreamedWordArtifact-S7ICDK5T.cjs → ConnectedStreamedWordArtifact-6MCLJRIT.cjs} +11 -11
  8. package/dist/{ConnectedStreamedWordArtifact-S7ICDK5T.cjs.map → ConnectedStreamedWordArtifact-6MCLJRIT.cjs.map} +1 -1
  9. package/dist/{DocumentReviewCard-L472OMQS.cjs → DocumentReviewCard-BPIAJJED.cjs} +17 -17
  10. package/dist/{DocumentReviewCard-L472OMQS.cjs.map → DocumentReviewCard-BPIAJJED.cjs.map} +1 -1
  11. package/dist/{FilesViewerDialog-JK25HKKF.cjs → FilesViewerDialog-67WK3TZC.cjs} +26 -26
  12. package/dist/{FilesViewerDialog-JK25HKKF.cjs.map → FilesViewerDialog-67WK3TZC.cjs.map} +1 -1
  13. package/dist/{WorkspaceTableView-JCTDEMIL.cjs → WorkspaceTableView-J3C6VH4T.cjs} +8 -8
  14. package/dist/{WorkspaceTableView-JCTDEMIL.cjs.map → WorkspaceTableView-J3C6VH4T.cjs.map} +1 -1
  15. package/dist/agents/index.cjs +187 -187
  16. package/dist/agents/tasks/ConversationListView.js +10 -2
  17. package/dist/agents/tasks/ConversationListView.js.map +2 -2
  18. package/dist/agents/tasks/TaskTable.js +5 -4
  19. package/dist/agents/tasks/TaskTable.js.map +2 -2
  20. package/dist/agents/tasks/WorkflowsTable.js +4 -5
  21. package/dist/agents/tasks/WorkflowsTable.js.map +2 -2
  22. package/dist/agents/tasks/taskColumns.js +1 -1
  23. package/dist/agents/tasks/taskColumns.js.map +1 -1
  24. package/dist/agents/tasks/taskTableLabels.js +1 -1
  25. package/dist/agents/tasks/taskTableLabels.js.map +1 -1
  26. package/dist/agents/tasks/workflowTableLabels.js +1 -1
  27. package/dist/agents/tasks/workflowTableLabels.js.map +1 -1
  28. package/dist/{ai-OBS67QV4.cjs → ai-IM4A23YT.cjs} +16 -16
  29. package/dist/ai-IM4A23YT.cjs.map +1 -0
  30. package/dist/calls/index.cjs +2 -2
  31. package/dist/{chunk-P77YTTJ3.cjs → chunk-3GWWOYGS.cjs} +4 -4
  32. package/dist/{chunk-P77YTTJ3.cjs.map → chunk-3GWWOYGS.cjs.map} +1 -1
  33. package/dist/{chunk-QOXK5O6M.cjs → chunk-557MJ4IH.cjs} +12 -12
  34. package/dist/{chunk-QOXK5O6M.cjs.map → chunk-557MJ4IH.cjs.map} +1 -1
  35. package/dist/{chunk-YDPLSXHB.cjs → chunk-5IZFSAEZ.cjs} +4 -4
  36. package/dist/{chunk-YDPLSXHB.cjs.map → chunk-5IZFSAEZ.cjs.map} +1 -1
  37. package/dist/{chunk-JSQQV23D.cjs → chunk-6UTKM5AB.cjs} +3 -3
  38. package/dist/{chunk-JSQQV23D.cjs.map → chunk-6UTKM5AB.cjs.map} +1 -1
  39. package/dist/{chunk-PVPRVI54.cjs → chunk-775S43W7.cjs} +21 -12
  40. package/dist/chunk-775S43W7.cjs.map +1 -0
  41. package/dist/{chunk-3LNUQYAF.cjs → chunk-B3LZITVF.cjs} +3 -3
  42. package/dist/{chunk-3LNUQYAF.cjs.map → chunk-B3LZITVF.cjs.map} +1 -1
  43. package/dist/{chunk-SUYPXUE6.cjs → chunk-BP3IJ34D.cjs} +6 -6
  44. package/dist/{chunk-SUYPXUE6.cjs.map → chunk-BP3IJ34D.cjs.map} +1 -1
  45. package/dist/{chunk-TT4IF52H.cjs → chunk-BUVIBHFU.cjs} +37 -38
  46. package/dist/chunk-BUVIBHFU.cjs.map +1 -0
  47. package/dist/{chunk-OPH4UZQN.cjs → chunk-CKCG4NDB.cjs} +33 -33
  48. package/dist/{chunk-OPH4UZQN.cjs.map → chunk-CKCG4NDB.cjs.map} +1 -1
  49. package/dist/{chunk-7IPIKMCY.cjs → chunk-CPR6EHG7.cjs} +3 -3
  50. package/dist/{chunk-7IPIKMCY.cjs.map → chunk-CPR6EHG7.cjs.map} +1 -1
  51. package/dist/{chunk-YGXOKB5Z.cjs → chunk-DFBDQKGE.cjs} +4 -4
  52. package/dist/{chunk-YGXOKB5Z.cjs.map → chunk-DFBDQKGE.cjs.map} +1 -1
  53. package/dist/{chunk-K6AUKKUN.cjs → chunk-ECLUFKYR.cjs} +6 -6
  54. package/dist/{chunk-K6AUKKUN.cjs.map → chunk-ECLUFKYR.cjs.map} +1 -1
  55. package/dist/{chunk-CPG7II4E.cjs → chunk-HA66DHW6.cjs} +28 -28
  56. package/dist/{chunk-CPG7II4E.cjs.map → chunk-HA66DHW6.cjs.map} +1 -1
  57. package/dist/{chunk-P2MOLUFO.cjs → chunk-KTQOGT2L.cjs} +6 -6
  58. package/dist/{chunk-P2MOLUFO.cjs.map → chunk-KTQOGT2L.cjs.map} +1 -1
  59. package/dist/{chunk-57NHXEU2.cjs → chunk-MXBXZXXQ.cjs} +5 -5
  60. package/dist/{chunk-57NHXEU2.cjs.map → chunk-MXBXZXXQ.cjs.map} +1 -1
  61. package/dist/{chunk-L6APDO3Y.cjs → chunk-NJCK6V6U.cjs} +3 -3
  62. package/dist/{chunk-L6APDO3Y.cjs.map → chunk-NJCK6V6U.cjs.map} +1 -1
  63. package/dist/{chunk-NNUK5ZM7.cjs → chunk-NLSWDP42.cjs} +9 -17
  64. package/dist/chunk-NLSWDP42.cjs.map +1 -0
  65. package/dist/{chunk-ZCIQBHH5.cjs → chunk-Q6CLWOP2.cjs} +36 -36
  66. package/dist/{chunk-ZCIQBHH5.cjs.map → chunk-Q6CLWOP2.cjs.map} +1 -1
  67. package/dist/{chunk-XZYIS2JZ.cjs → chunk-QQWHG3KF.cjs} +6 -7
  68. package/dist/chunk-QQWHG3KF.cjs.map +1 -0
  69. package/dist/{chunk-KHAO7ZTO.cjs → chunk-T23UTIRI.cjs} +5 -5
  70. package/dist/{chunk-KHAO7ZTO.cjs.map → chunk-T23UTIRI.cjs.map} +1 -1
  71. package/dist/{chunk-O4F77VSO.cjs → chunk-TDO5UWXF.cjs} +5 -5
  72. package/dist/{chunk-O4F77VSO.cjs.map → chunk-TDO5UWXF.cjs.map} +1 -1
  73. package/dist/{chunk-VLCY46K6.cjs → chunk-TG2GM7WJ.cjs} +4 -3
  74. package/dist/chunk-TG2GM7WJ.cjs.map +1 -0
  75. package/dist/{chunk-5XAJ4N2S.cjs → chunk-VZCPMXWC.cjs} +4 -4
  76. package/dist/{chunk-5XAJ4N2S.cjs.map → chunk-VZCPMXWC.cjs.map} +1 -1
  77. package/dist/{chunk-MMVDVHKE.cjs → chunk-W6INT5GS.cjs} +5 -5
  78. package/dist/{chunk-MMVDVHKE.cjs.map → chunk-W6INT5GS.cjs.map} +1 -1
  79. package/dist/{chunk-ZPPMAL5P.cjs → chunk-WQMR3O2D.cjs} +6 -10
  80. package/dist/chunk-WQMR3O2D.cjs.map +1 -0
  81. package/dist/{chunk-CB3YYZAU.cjs → chunk-X36UR4A7.cjs} +175 -58
  82. package/dist/chunk-X36UR4A7.cjs.map +1 -0
  83. package/dist/{chunk-6ULADDBW.cjs → chunk-YYSBWMDJ.cjs} +4 -4
  84. package/dist/{chunk-6ULADDBW.cjs.map → chunk-YYSBWMDJ.cjs.map} +1 -1
  85. package/dist/collaboration/index.cjs +3 -3
  86. package/dist/collaboration/sharing/ShareControl.js +10 -2
  87. package/dist/collaboration/sharing/ShareControl.js.map +2 -2
  88. package/dist/components/SharedCell.d.ts +2 -4
  89. package/dist/components/SharedCell.js +4 -8
  90. package/dist/components/SharedCell.js.map +2 -2
  91. package/dist/connect/docx.cjs +14 -14
  92. package/dist/connect/index.cjs +965 -937
  93. package/dist/connect/index.cjs.map +1 -1
  94. package/dist/connect/viewer.cjs +16 -16
  95. package/dist/connection/facts/factPageColumns.js +3 -9
  96. package/dist/connection/facts/factPageColumns.js.map +2 -2
  97. package/dist/connection/files/grid/cells.js +1 -3
  98. package/dist/connection/files/grid/cells.js.map +2 -2
  99. package/dist/connection/files/grid/documentColumns.js +3 -2
  100. package/dist/connection/files/grid/documentColumns.js.map +2 -2
  101. package/dist/connection/sharing/WorkspaceMembersList.d.ts +4 -0
  102. package/dist/connection/sharing/WorkspaceMembersList.js +34 -0
  103. package/dist/connection/sharing/WorkspaceMembersList.js.map +7 -0
  104. package/dist/connection/shell/ConnectedAppShell.js +4 -0
  105. package/dist/connection/shell/ConnectedAppShell.js.map +2 -2
  106. package/dist/connection/viewer/ConnectedDocumentViewer.js +3 -2
  107. package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
  108. package/dist/connection/viewer/ViewerPdfPane.js +20 -2
  109. package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
  110. package/dist/connection/viewer/pdf/PdfPassageHighlights.d.ts +12 -0
  111. package/dist/connection/viewer/pdf/PdfPassageHighlights.js +36 -0
  112. package/dist/connection/viewer/pdf/PdfPassageHighlights.js.map +7 -0
  113. package/dist/connection/viewer/pdf/passageHighlights.d.ts +26 -0
  114. package/dist/connection/viewer/pdf/passageHighlights.js +40 -0
  115. package/dist/connection/viewer/pdf/passageHighlights.js.map +7 -0
  116. package/dist/connection/viewer/pdf/usePdfPassageHighlights.d.ts +9 -0
  117. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +47 -0
  118. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +7 -0
  119. package/dist/connection/workflows/workflowsPageLabels.js +1 -1
  120. package/dist/connection/workflows/workflowsPageLabels.js.map +1 -1
  121. package/dist/dashboards/index.cjs +1 -1
  122. package/dist/embed/index.cjs +26 -26
  123. package/dist/facts/factColumns.js +3 -3
  124. package/dist/facts/factColumns.js.map +1 -1
  125. package/dist/facts/index.cjs +42 -42
  126. package/dist/files/HtmlViewerParts.js +7 -15
  127. package/dist/files/HtmlViewerParts.js.map +2 -2
  128. package/dist/files/index.cjs +223 -223
  129. package/dist/index.cjs +321 -321
  130. package/dist/settings/index.cjs +147 -147
  131. package/dist/shell/index.cjs +35 -35
  132. package/dist/studio/index.cjs +8 -8
  133. package/dist/styles.css +1 -1
  134. package/dist/workflow-canvas/index.cjs +36 -36
  135. package/dist/workflow-canvas/index.cjs.map +1 -1
  136. package/node_modules/@arbidocs/coedit/package.json +1 -1
  137. package/package.json +5 -5
  138. package/dist/ai-OBS67QV4.cjs.map +0 -1
  139. package/dist/chunk-CB3YYZAU.cjs.map +0 -1
  140. package/dist/chunk-NNUK5ZM7.cjs.map +0 -1
  141. package/dist/chunk-PVPRVI54.cjs.map +0 -1
  142. package/dist/chunk-TT4IF52H.cjs.map +0 -1
  143. package/dist/chunk-VLCY46K6.cjs.map +0 -1
  144. package/dist/chunk-XZYIS2JZ.cjs.map +0 -1
  145. package/dist/chunk-ZPPMAL5P.cjs.map +0 -1
@@ -0,0 +1,36 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { cn } from "@arbidocs/react/ui";
4
+ function PdfPassageHighlights({
5
+ boxes,
6
+ activeId,
7
+ onActiveDrawn
8
+ }) {
9
+ return /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0", "data-testid": "pdf-passage-highlights", children: boxes.map(({ chunkId, box: [x0, y0, x1, y1], highlight }) => /* @__PURE__ */ jsx(
10
+ "div",
11
+ {
12
+ ref: chunkId === activeId ? (element) => {
13
+ if (element) onActiveDrawn(element);
14
+ } : void 0,
15
+ "data-testid": "pdf-passage-highlight",
16
+ "data-chunk-id": chunkId,
17
+ "data-highlight": highlight,
18
+ className: cn(
19
+ // multiplied, so the page's text stays as dark as it was under the wash
20
+ "absolute rounded-sm mix-blend-multiply",
21
+ highlight === "strong" ? "bg-ai-soft ring-1 ring-ai-accent/50" : "bg-ai-soft/60"
22
+ ),
23
+ style: {
24
+ left: `${x0 * 100}%`,
25
+ top: `${y0 * 100}%`,
26
+ width: `${(x1 - x0) * 100}%`,
27
+ height: `${(y1 - y0) * 100}%`
28
+ }
29
+ },
30
+ chunkId
31
+ )) });
32
+ }
33
+ export {
34
+ PdfPassageHighlights
35
+ };
36
+ //# sourceMappingURL=PdfPassageHighlights.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/connection/viewer/pdf/PdfPassageHighlights.tsx"],
4
+ "sourcesContent": ["/**\n * The lit passages of one PDF page, drawn over it. The boxes are fractions of the page, so the layer\n * fills the page area and scales with it; it takes no pointer events, so the PDF stays selectable.\n */\n\nimport { cn } from '@arbidocs/react/ui'\nimport type { PdfPassageBox } from './passageHighlights'\n\nexport interface PdfPassageHighlightsProps {\n boxes: readonly PdfPassageBox[]\n /** The passage being read: its box is told to the host once it is drawn, to bring it into view. */\n activeId: string | null\n onActiveDrawn: (element: HTMLElement) => void\n}\n\nexport function PdfPassageHighlights({\n boxes,\n activeId,\n onActiveDrawn,\n}: PdfPassageHighlightsProps) {\n return (\n <div className=\"pointer-events-none absolute inset-0\" data-testid=\"pdf-passage-highlights\">\n {boxes.map(({ chunkId, box: [x0, y0, x1, y1], highlight }) => (\n <div\n key={chunkId}\n ref={\n chunkId === activeId\n ? (element) => {\n if (element) onActiveDrawn(element)\n }\n : undefined\n }\n data-testid=\"pdf-passage-highlight\"\n data-chunk-id={chunkId}\n data-highlight={highlight}\n className={cn(\n // multiplied, so the page's text stays as dark as it was under the wash\n 'absolute rounded-sm mix-blend-multiply',\n highlight === 'strong' ? 'bg-ai-soft ring-1 ring-ai-accent/50' : 'bg-ai-soft/60'\n )}\n style={{\n left: `${x0 * 100}%`,\n top: `${y0 * 100}%`,\n width: `${(x1 - x0) * 100}%`,\n height: `${(y1 - y0) * 100}%`,\n }}\n />\n ))}\n </div>\n )\n}\n"],
5
+ "mappings": ";AAuBQ;AAlBR,SAAS,UAAU;AAUZ,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAA8B;AAC5B,SACE,oBAAC,SAAI,WAAU,wCAAuC,eAAY,0BAC/D,gBAAM,IAAI,CAAC,EAAE,SAAS,KAAK,CAAC,IAAI,IAAI,IAAI,EAAE,GAAG,UAAU,MACtD;AAAA,IAAC;AAAA;AAAA,MAEC,KACE,YAAY,WACR,CAAC,YAAY;AACX,YAAI,QAAS,eAAc,OAAO;AAAA,MACpC,IACA;AAAA,MAEN,eAAY;AAAA,MACZ,iBAAe;AAAA,MACf,kBAAgB;AAAA,MAChB,WAAW;AAAA;AAAA,QAET;AAAA,QACA,cAAc,WAAW,wCAAwC;AAAA,MACnE;AAAA,MACA,OAAO;AAAA,QACL,MAAM,GAAG,KAAK,GAAG;AAAA,QACjB,KAAK,GAAG,KAAK,GAAG;AAAA,QAChB,OAAO,IAAI,KAAK,MAAM,GAAG;AAAA,QACzB,QAAQ,IAAI,KAAK,MAAM,GAAG;AAAA,MAC5B;AAAA;AAAA,IArBK;AAAA,EAsBP,CACD,GACH;AAEJ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Which passages light up on the PDF, and where. The rules are the parsed view's (`ParsedPassage`):
3
+ * while a fact's Citation popover is open its cited passages are light and the one being read is
4
+ * strong; otherwise the passage a citation opened the document at is the one lit. A passage's box
5
+ * is the parser's (`page_bbox`: fractions of its page, top-left origin), so it lands on the page
6
+ * at any zoom.
7
+ */
8
+ import type { ProcessedPage } from '@arbidocs/react/viewers';
9
+ import type { PassageHighlight } from '../../../files';
10
+ /** [x0, y0, x1, y1] as fractions of the page. */
11
+ export type PageBox = readonly [number, number, number, number];
12
+ export interface PdfPassageBox {
13
+ chunkId: string;
14
+ box: PageBox;
15
+ highlight: PassageHighlight;
16
+ }
17
+ export interface PassageHighlightState {
18
+ /** A fact's cited passages (its Citation popover is open); empty when none is. */
19
+ cited: ReadonlySet<string>;
20
+ /** The passage being read: the one a citation opened the document at. */
21
+ active: string | null;
22
+ }
23
+ /** How a passage is lit, or null when it is not. */
24
+ export declare function passageHighlight(chunkId: string, { cited, active }: PassageHighlightState): PassageHighlight | null;
25
+ /** The lit passages' boxes, by page number. Passages without a usable box are left out. */
26
+ export declare function passageBoxesByPage(pages: readonly ProcessedPage[], state: PassageHighlightState): Map<number, PdfPassageBox[]>;
@@ -0,0 +1,40 @@
1
+ "use client";
2
+ function passageHighlight(chunkId, { cited, active }) {
3
+ if (cited.size > 0) {
4
+ if (!cited.has(chunkId)) return null;
5
+ return chunkId === active ? "strong" : "light";
6
+ }
7
+ return chunkId === active ? "light" : null;
8
+ }
9
+ function asBox(bbox) {
10
+ if (!bbox || bbox.length !== 4 || !bbox.every(Number.isFinite)) return null;
11
+ const [x0, y0, x1, y1] = bbox;
12
+ if (x1 <= x0 || y1 <= y0) return null;
13
+ return [x0, y0, x1, y1];
14
+ }
15
+ function isWholePage([x0, y0, x1, y1]) {
16
+ return x0 <= 0 && y0 <= 0 && x1 >= 1 && y1 >= 1;
17
+ }
18
+ function passageBoxesByPage(pages, state) {
19
+ const byPage = /* @__PURE__ */ new Map();
20
+ if (state.cited.size === 0 && !state.active) return byPage;
21
+ for (const page of pages) {
22
+ if (page.pageNumber === null) continue;
23
+ for (const chunk of page.chunks) {
24
+ const chunkId = chunk.chunkExtId;
25
+ if (!chunkId) continue;
26
+ const highlight = passageHighlight(chunkId, state);
27
+ const box = highlight && asBox(chunk.pageBbox);
28
+ if (!highlight || !box || isWholePage(box)) continue;
29
+ const boxes = byPage.get(page.pageNumber) ?? [];
30
+ boxes.push({ chunkId, box, highlight });
31
+ byPage.set(page.pageNumber, boxes);
32
+ }
33
+ }
34
+ return byPage;
35
+ }
36
+ export {
37
+ passageBoxesByPage,
38
+ passageHighlight
39
+ };
40
+ //# sourceMappingURL=passageHighlights.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/connection/viewer/pdf/passageHighlights.ts"],
4
+ "sourcesContent": ["/**\n * Which passages light up on the PDF, and where. The rules are the parsed view's (`ParsedPassage`):\n * while a fact's Citation popover is open its cited passages are light and the one being read is\n * strong; otherwise the passage a citation opened the document at is the one lit. A passage's box\n * is the parser's (`page_bbox`: fractions of its page, top-left origin), so it lands on the page\n * at any zoom.\n */\n\nimport type { ProcessedPage } from '@arbidocs/react/viewers'\nimport type { PassageHighlight } from '../../../files'\n\n/** [x0, y0, x1, y1] as fractions of the page. */\nexport type PageBox = readonly [number, number, number, number]\n\nexport interface PdfPassageBox {\n chunkId: string\n box: PageBox\n highlight: PassageHighlight\n}\n\nexport interface PassageHighlightState {\n /** A fact's cited passages (its Citation popover is open); empty when none is. */\n cited: ReadonlySet<string>\n /** The passage being read: the one a citation opened the document at. */\n active: string | null\n}\n\n/** How a passage is lit, or null when it is not. */\nexport function passageHighlight(\n chunkId: string,\n { cited, active }: PassageHighlightState\n): PassageHighlight | null {\n if (cited.size > 0) {\n if (!cited.has(chunkId)) return null\n return chunkId === active ? 'strong' : 'light'\n }\n return chunkId === active ? 'light' : null\n}\n\n/** A drawable box: four finite fractions with area. */\nfunction asBox(bbox: readonly number[] | undefined): PageBox | null {\n if (!bbox || bbox.length !== 4 || !bbox.every(Number.isFinite)) return null\n const [x0, y0, x1, y1] = bbox\n if (x1 <= x0 || y1 <= y0) return null\n return [x0, y0, x1, y1]\n}\n\n/**\n * The page's whole area: what the parser gives a chunk on a page where it recognized no block to\n * place it by. It says \"this page\", and a rectangle over the whole page would say nothing more.\n */\nfunction isWholePage([x0, y0, x1, y1]: PageBox): boolean {\n return x0 <= 0 && y0 <= 0 && x1 >= 1 && y1 >= 1\n}\n\n/** The lit passages' boxes, by page number. Passages without a usable box are left out. */\nexport function passageBoxesByPage(\n pages: readonly ProcessedPage[],\n state: PassageHighlightState\n): Map<number, PdfPassageBox[]> {\n const byPage = new Map<number, PdfPassageBox[]>()\n if (state.cited.size === 0 && !state.active) return byPage\n for (const page of pages) {\n if (page.pageNumber === null) continue\n for (const chunk of page.chunks) {\n const chunkId = chunk.chunkExtId\n if (!chunkId) continue\n const highlight = passageHighlight(chunkId, state)\n const box = highlight && asBox(chunk.pageBbox)\n if (!highlight || !box || isWholePage(box)) continue\n const boxes = byPage.get(page.pageNumber) ?? []\n boxes.push({ chunkId, box, highlight })\n byPage.set(page.pageNumber, boxes)\n }\n }\n return byPage\n}\n"],
5
+ "mappings": ";AA4BO,SAAS,iBACd,SACA,EAAE,OAAO,OAAO,GACS;AACzB,MAAI,MAAM,OAAO,GAAG;AAClB,QAAI,CAAC,MAAM,IAAI,OAAO,EAAG,QAAO;AAChC,WAAO,YAAY,SAAS,WAAW;AAAA,EACzC;AACA,SAAO,YAAY,SAAS,UAAU;AACxC;AAGA,SAAS,MAAM,MAAqD;AAClE,MAAI,CAAC,QAAQ,KAAK,WAAW,KAAK,CAAC,KAAK,MAAM,OAAO,QAAQ,EAAG,QAAO;AACvE,QAAM,CAAC,IAAI,IAAI,IAAI,EAAE,IAAI;AACzB,MAAI,MAAM,MAAM,MAAM,GAAI,QAAO;AACjC,SAAO,CAAC,IAAI,IAAI,IAAI,EAAE;AACxB;AAMA,SAAS,YAAY,CAAC,IAAI,IAAI,IAAI,EAAE,GAAqB;AACvD,SAAO,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM;AAChD;AAGO,SAAS,mBACd,OACA,OAC8B;AAC9B,QAAM,SAAS,oBAAI,IAA6B;AAChD,MAAI,MAAM,MAAM,SAAS,KAAK,CAAC,MAAM,OAAQ,QAAO;AACpD,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,eAAe,KAAM;AAC9B,eAAW,SAAS,KAAK,QAAQ;AAC/B,YAAM,UAAU,MAAM;AACtB,UAAI,CAAC,QAAS;AACd,YAAM,YAAY,iBAAiB,SAAS,KAAK;AACjD,YAAM,MAAM,aAAa,MAAM,MAAM,QAAQ;AAC7C,UAAI,CAAC,aAAa,CAAC,OAAO,YAAY,GAAG,EAAG;AAC5C,YAAM,QAAQ,OAAO,IAAI,KAAK,UAAU,KAAK,CAAC;AAC9C,YAAM,KAAK,EAAE,SAAS,KAAK,UAAU,CAAC;AACtC,aAAO,IAAI,KAAK,YAAY,KAAK;AAAA,IACnC;AAAA,EACF;AACA,SAAO;AACT;",
6
+ "names": []
7
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The passages a citation lights, drawn over the PDF page by page: a fact's cited passages (its
3
+ * Citation popover is open) and the passage a citation opened the document at, as the parsed view
4
+ * lights them. Nothing is fetched until one is lit; the parsed chunks are the parsed view's own
5
+ * query, so opening that tab afterwards costs nothing more.
6
+ */
7
+ import { type ReactNode } from 'react';
8
+ /** A PDF viewer's page overlay for the document being viewed: `(page) => highlights | null`. */
9
+ export declare function usePdfPassageHighlights(documentId: string | undefined): (pageNumber: number) => ReactNode;
@@ -0,0 +1,47 @@
1
+ "use client";
2
+ import { jsx } from "react/jsx-runtime";
3
+ import { useCallback, useEffect, useMemo, useRef } from "react";
4
+ import { useArbiSessionState, useParsedDocument } from "@arbidocs/react";
5
+ import { useProcessedChunks } from "@arbidocs/react/viewers";
6
+ import { useViewerPassageCitation } from "../support.js";
7
+ import { PdfPassageHighlights } from "./PdfPassageHighlights.js";
8
+ import { passageBoxesByPage } from "./passageHighlights.js";
9
+ const NONE = [];
10
+ const NO_FOOTNOTES = {};
11
+ function usePdfPassageHighlights(documentId) {
12
+ const citedIds = useViewerPassageCitation()?.highlighted ?? NONE;
13
+ const cited = useMemo(() => new Set(citedIds), [citedIds]);
14
+ const active = useArbiSessionState((s) => s.viewingDocument?.passageId ?? null);
15
+ const { data: parsed } = useParsedDocument(documentId, "final", {
16
+ enabled: cited.size > 0 || !!active
17
+ });
18
+ const { processedChunks } = useProcessedChunks(parsed?.chunks, NO_FOOTNOTES);
19
+ const boxesByPage = useMemo(
20
+ () => passageBoxesByPage(processedChunks, { cited, active }),
21
+ [processedChunks, cited, active]
22
+ );
23
+ const centredFor = useRef(null);
24
+ const activeKey = active ? `${documentId}:${active}` : null;
25
+ useEffect(() => {
26
+ if (!activeKey) centredFor.current = null;
27
+ }, [activeKey]);
28
+ const centre = useCallback(
29
+ (element) => {
30
+ if (!activeKey || centredFor.current === activeKey) return;
31
+ centredFor.current = activeKey;
32
+ element.scrollIntoView?.({ block: "center", behavior: "smooth" });
33
+ },
34
+ [activeKey]
35
+ );
36
+ return useCallback(
37
+ (pageNumber) => {
38
+ const boxes = boxesByPage.get(pageNumber);
39
+ return boxes ? /* @__PURE__ */ jsx(PdfPassageHighlights, { boxes, activeId: active, onActiveDrawn: centre }) : null;
40
+ },
41
+ [boxesByPage, active, centre]
42
+ );
43
+ }
44
+ export {
45
+ usePdfPassageHighlights
46
+ };
47
+ //# sourceMappingURL=usePdfPassageHighlights.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/connection/viewer/pdf/usePdfPassageHighlights.tsx"],
4
+ "sourcesContent": ["/**\n * The passages a citation lights, drawn over the PDF page by page: a fact's cited passages (its\n * Citation popover is open) and the passage a citation opened the document at, as the parsed view\n * lights them. Nothing is fetched until one is lit; the parsed chunks are the parsed view's own\n * query, so opening that tab afterwards costs nothing more.\n */\n\nimport { useCallback, useEffect, useMemo, useRef, type ReactNode } from 'react'\nimport { useArbiSessionState, useParsedDocument } from '@arbidocs/react'\nimport { useProcessedChunks } from '@arbidocs/react/viewers'\nimport { useViewerPassageCitation } from '../support'\nimport { PdfPassageHighlights } from './PdfPassageHighlights'\nimport { passageBoxesByPage } from './passageHighlights'\n\nconst NONE: readonly string[] = []\nconst NO_FOOTNOTES: Record<string, string> = {}\n\n/** A PDF viewer's page overlay for the document being viewed: `(page) => highlights | null`. */\nexport function usePdfPassageHighlights(\n documentId: string | undefined\n): (pageNumber: number) => ReactNode {\n const citedIds = useViewerPassageCitation()?.highlighted ?? NONE\n const cited = useMemo(() => new Set(citedIds), [citedIds])\n const active = useArbiSessionState((s) => s.viewingDocument?.passageId ?? null)\n\n const { data: parsed } = useParsedDocument(documentId, 'final', {\n enabled: cited.size > 0 || !!active,\n })\n const { processedChunks } = useProcessedChunks(parsed?.chunks, NO_FOOTNOTES)\n const boxesByPage = useMemo(\n () => passageBoxesByPage(processedChunks, { cited, active }),\n [processedChunks, cited, active]\n )\n\n // The passage being read is brought into view once, when its page first draws it: the viewer\n // opens the page, this centres the passage on it, and scrolling away is then left alone.\n const centredFor = useRef<string | null>(null)\n const activeKey = active ? `${documentId}:${active}` : null\n useEffect(() => {\n if (!activeKey) centredFor.current = null\n }, [activeKey])\n const centre = useCallback(\n (element: HTMLElement) => {\n if (!activeKey || centredFor.current === activeKey) return\n centredFor.current = activeKey\n element.scrollIntoView?.({ block: 'center', behavior: 'smooth' })\n },\n [activeKey]\n )\n\n return useCallback(\n (pageNumber: number) => {\n const boxes = boxesByPage.get(pageNumber)\n return boxes ? (\n <PdfPassageHighlights boxes={boxes} activeId={active} onActiveDrawn={centre} />\n ) : null\n },\n [boxesByPage, active, centre]\n )\n}\n"],
5
+ "mappings": ";AAsDQ;AA/CR,SAAS,aAAa,WAAW,SAAS,cAA8B;AACxE,SAAS,qBAAqB,yBAAyB;AACvD,SAAS,0BAA0B;AACnC,SAAS,gCAAgC;AACzC,SAAS,4BAA4B;AACrC,SAAS,0BAA0B;AAEnC,MAAM,OAA0B,CAAC;AACjC,MAAM,eAAuC,CAAC;AAGvC,SAAS,wBACd,YACmC;AACnC,QAAM,WAAW,yBAAyB,GAAG,eAAe;AAC5D,QAAM,QAAQ,QAAQ,MAAM,IAAI,IAAI,QAAQ,GAAG,CAAC,QAAQ,CAAC;AACzD,QAAM,SAAS,oBAAoB,CAAC,MAAM,EAAE,iBAAiB,aAAa,IAAI;AAE9E,QAAM,EAAE,MAAM,OAAO,IAAI,kBAAkB,YAAY,SAAS;AAAA,IAC9D,SAAS,MAAM,OAAO,KAAK,CAAC,CAAC;AAAA,EAC/B,CAAC;AACD,QAAM,EAAE,gBAAgB,IAAI,mBAAmB,QAAQ,QAAQ,YAAY;AAC3E,QAAM,cAAc;AAAA,IAClB,MAAM,mBAAmB,iBAAiB,EAAE,OAAO,OAAO,CAAC;AAAA,IAC3D,CAAC,iBAAiB,OAAO,MAAM;AAAA,EACjC;AAIA,QAAM,aAAa,OAAsB,IAAI;AAC7C,QAAM,YAAY,SAAS,GAAG,UAAU,IAAI,MAAM,KAAK;AACvD,YAAU,MAAM;AACd,QAAI,CAAC,UAAW,YAAW,UAAU;AAAA,EACvC,GAAG,CAAC,SAAS,CAAC;AACd,QAAM,SAAS;AAAA,IACb,CAAC,YAAyB;AACxB,UAAI,CAAC,aAAa,WAAW,YAAY,UAAW;AACpD,iBAAW,UAAU;AACrB,cAAQ,iBAAiB,EAAE,OAAO,UAAU,UAAU,SAAS,CAAC;AAAA,IAClE;AAAA,IACA,CAAC,SAAS;AAAA,EACZ;AAEA,SAAO;AAAA,IACL,CAAC,eAAuB;AACtB,YAAM,QAAQ,YAAY,IAAI,UAAU;AACxC,aAAO,QACL,oBAAC,wBAAqB,OAAc,UAAU,QAAQ,eAAe,QAAQ,IAC3E;AAAA,IACN;AAAA,IACA,CAAC,aAAa,QAAQ,MAAM;AAAA,EAC9B;AACF;",
6
+ "names": []
7
+ }
@@ -9,7 +9,7 @@ const DEFAULT_CONNECTED_WORKFLOWS_PAGE_LABELS = {
9
9
  };
10
10
  const DEFAULT_WORKFLOWS_PAGE_TABLE_LABELS = {
11
11
  colName: "Workflow",
12
- colShared: "Visibility",
12
+ colShared: "Sharing",
13
13
  searchLabel: "Filter workflows",
14
14
  searchPlaceholder: "Filter\u2026",
15
15
  emptyTitle: "No workflows yet",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/connection/workflows/workflowsPageLabels.ts"],
4
- "sourcesContent": ["/** The Workflows page's words (`ConnectedWorkflowsPage`), and its table's. */\nimport type { TaskTriggerChipLabels } from '../../agents/tasks/TaskTriggerChip'\nimport type { WorkflowListLabels } from '../../agents/tasks/workflowTableLabels'\n\nexport interface ConnectedWorkflowsPageLabels {\n newWorkflow: string\n /** Opens the workflow whose history is shown. */\n edit: string\n editAria: string\n /** The builder's way back to the list. */\n back: string\n /** Runs the catalogue entry open in the builder. */\n runTemplate: string\n /** When a workflow with no trigger of its own starts. */\n manualTrigger: string\n}\n\nexport const DEFAULT_CONNECTED_WORKFLOWS_PAGE_LABELS: ConnectedWorkflowsPageLabels = {\n newWorkflow: 'New workflow',\n edit: 'Edit',\n editAria: 'Edit workflow',\n back: 'Workflows',\n runTemplate: 'Run',\n manualTrigger: 'When started manually',\n}\n\n/** The table's words on this page. */\nexport const DEFAULT_WORKFLOWS_PAGE_TABLE_LABELS: Partial<WorkflowListLabels> = {\n colName: 'Workflow',\n colShared: 'Visibility',\n searchLabel: 'Filter workflows',\n searchPlaceholder: 'Filter\u2026',\n emptyTitle: 'No workflows yet',\n emptyMessage:\n 'Build a workflow of steps for people and agents. Start it by hand, on a schedule, when something happens, or after a thread is marked done.',\n openLastRun: 'Open the latest thread',\n runs: 'History',\n run: 'Start now',\n moreActions: 'Workflow options',\n filterWorkflows: 'Workflows',\n}\n\n/** How the trigger chips say an \"after\" or a manual start on this page. */\nexport const WORKFLOWS_PAGE_TRIGGER_CHIP_LABELS: Partial<TaskTriggerChipLabels> = {\n after: (name) => `After \u201C${name}\u201D is marked done`,\n afterUnknown: 'After a thread is marked done',\n onDemand: 'Manual',\n}\n"],
4
+ "sourcesContent": ["/** The Workflows page's words (`ConnectedWorkflowsPage`), and its table's. */\nimport type { TaskTriggerChipLabels } from '../../agents/tasks/TaskTriggerChip'\nimport type { WorkflowListLabels } from '../../agents/tasks/workflowTableLabels'\n\nexport interface ConnectedWorkflowsPageLabels {\n newWorkflow: string\n /** Opens the workflow whose history is shown. */\n edit: string\n editAria: string\n /** The builder's way back to the list. */\n back: string\n /** Runs the catalogue entry open in the builder. */\n runTemplate: string\n /** When a workflow with no trigger of its own starts. */\n manualTrigger: string\n}\n\nexport const DEFAULT_CONNECTED_WORKFLOWS_PAGE_LABELS: ConnectedWorkflowsPageLabels = {\n newWorkflow: 'New workflow',\n edit: 'Edit',\n editAria: 'Edit workflow',\n back: 'Workflows',\n runTemplate: 'Run',\n manualTrigger: 'When started manually',\n}\n\n/** The table's words on this page. */\nexport const DEFAULT_WORKFLOWS_PAGE_TABLE_LABELS: Partial<WorkflowListLabels> = {\n colName: 'Workflow',\n colShared: 'Sharing',\n searchLabel: 'Filter workflows',\n searchPlaceholder: 'Filter\u2026',\n emptyTitle: 'No workflows yet',\n emptyMessage:\n 'Build a workflow of steps for people and agents. Start it by hand, on a schedule, when something happens, or after a thread is marked done.',\n openLastRun: 'Open the latest thread',\n runs: 'History',\n run: 'Start now',\n moreActions: 'Workflow options',\n filterWorkflows: 'Workflows',\n}\n\n/** How the trigger chips say an \"after\" or a manual start on this page. */\nexport const WORKFLOWS_PAGE_TRIGGER_CHIP_LABELS: Partial<TaskTriggerChipLabels> = {\n after: (name) => `After \u201C${name}\u201D is marked done`,\n afterUnknown: 'After a thread is marked done',\n onDemand: 'Manual',\n}\n"],
5
5
  "mappings": ";AAiBO,MAAM,0CAAwE;AAAA,EACnF,aAAa;AAAA,EACb,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,aAAa;AAAA,EACb,eAAe;AACjB;AAGO,MAAM,sCAAmE;AAAA,EAC9E,SAAS;AAAA,EACT,WAAW;AAAA,EACX,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,YAAY;AAAA,EACZ,cACE;AAAA,EACF,aAAa;AAAA,EACb,MAAM;AAAA,EACN,KAAK;AAAA,EACL,aAAa;AAAA,EACb,iBAAiB;AACnB;AAGO,MAAM,qCAAqE;AAAA,EAChF,OAAO,CAAC,SAAS,eAAU,IAAI;AAAA,EAC/B,cAAc;AAAA,EACd,UAAU;AACZ;",
6
6
  "names": []
7
7
  }
@@ -10,8 +10,8 @@ require('../chunk-ZU2B2RZK.cjs');
10
10
  var chunkNSD37OF5_cjs = require('../chunk-NSD37OF5.cjs');
11
11
  var chunkOEJQFPWO_cjs = require('../chunk-OEJQFPWO.cjs');
12
12
  require('../chunk-JV5TVUOU.cjs');
13
- require('../chunk-IPSHAMO2.cjs');
14
13
  var chunkZW6FPIFC_cjs = require('../chunk-ZW6FPIFC.cjs');
14
+ require('../chunk-IPSHAMO2.cjs');
15
15
  var chunkTKHCIHE2_cjs = require('../chunk-TKHCIHE2.cjs');
16
16
  require('../chunk-JDFBEGQO.cjs');
17
17
  require('../chunk-ULWRNGGE.cjs');
@@ -1,17 +1,17 @@
1
1
  "use client";
2
2
  'use strict';
3
3
 
4
- var chunkOPH4UZQN_cjs = require('../chunk-OPH4UZQN.cjs');
5
- require('../chunk-QOXK5O6M.cjs');
6
- require('../chunk-SUYPXUE6.cjs');
7
- require('../chunk-P77YTTJ3.cjs');
8
- require('../chunk-JSQQV23D.cjs');
4
+ var chunkCKCG4NDB_cjs = require('../chunk-CKCG4NDB.cjs');
5
+ require('../chunk-557MJ4IH.cjs');
6
+ require('../chunk-BP3IJ34D.cjs');
7
+ require('../chunk-3GWWOYGS.cjs');
8
+ require('../chunk-6UTKM5AB.cjs');
9
9
  require('../chunk-TJY7XPDE.cjs');
10
10
  require('../chunk-XNW62J54.cjs');
11
11
  require('../chunk-KXIRVKCJ.cjs');
12
- require('../chunk-TT4IF52H.cjs');
13
- require('../chunk-L6APDO3Y.cjs');
14
- require('../chunk-NNUK5ZM7.cjs');
12
+ require('../chunk-BUVIBHFU.cjs');
13
+ require('../chunk-NJCK6V6U.cjs');
14
+ require('../chunk-NLSWDP42.cjs');
15
15
  require('../chunk-223D4727.cjs');
16
16
  require('../chunk-SNUBQMIS.cjs');
17
17
  require('../chunk-P5AQYC4D.cjs');
@@ -22,12 +22,12 @@ require('../chunk-4B6HYQTW.cjs');
22
22
  require('../chunk-MZZ3SBQL.cjs');
23
23
  require('../chunk-NY3YUCOW.cjs');
24
24
  require('../chunk-325GVZE6.cjs');
25
- require('../chunk-ZPPMAL5P.cjs');
25
+ require('../chunk-WQMR3O2D.cjs');
26
26
  require('../chunk-ORELHENJ.cjs');
27
27
  require('../chunk-NWNVWO6L.cjs');
28
28
  require('../chunk-SK6HQ46Q.cjs');
29
29
  require('../chunk-E3Y7RI3J.cjs');
30
- require('../chunk-VLCY46K6.cjs');
30
+ require('../chunk-TG2GM7WJ.cjs');
31
31
  require('../chunk-OEJQFPWO.cjs');
32
32
  require('../chunk-TP5PGWIO.cjs');
33
33
  require('../chunk-I4IS6ST6.cjs');
@@ -49,6 +49,16 @@ require('../chunk-V6C2MBFY.cjs');
49
49
  require('../chunk-M74FWYNL.cjs');
50
50
  require('../chunk-QUMUAJ2P.cjs');
51
51
  require('../chunk-VZOOGA47.cjs');
52
+ require('../chunk-VJCSEMXT.cjs');
53
+ require('../chunk-SBWIA4PL.cjs');
54
+ require('../chunk-QMIHLJMH.cjs');
55
+ require('../chunk-HQDR43JC.cjs');
56
+ var chunkJR2YSBD5_cjs = require('../chunk-JR2YSBD5.cjs');
57
+ require('../chunk-TMX7YFVM.cjs');
58
+ require('../chunk-3YZKDCWY.cjs');
59
+ require('../chunk-SJSGSHIT.cjs');
60
+ require('../chunk-ZW6FPIFC.cjs');
61
+ require('../chunk-ZT5MIFLC.cjs');
52
62
  require('../chunk-JHDCDEXY.cjs');
53
63
  require('../chunk-M2FOXGJU.cjs');
54
64
  require('../chunk-5F4DCIHS.cjs');
@@ -62,16 +72,6 @@ require('../chunk-QGVOT7E4.cjs');
62
72
  require('../chunk-QRAQZTJE.cjs');
63
73
  require('../chunk-UDSHVNU3.cjs');
64
74
  require('../chunk-IPSHAMO2.cjs');
65
- require('../chunk-VJCSEMXT.cjs');
66
- require('../chunk-SBWIA4PL.cjs');
67
- require('../chunk-QMIHLJMH.cjs');
68
- require('../chunk-HQDR43JC.cjs');
69
- var chunkJR2YSBD5_cjs = require('../chunk-JR2YSBD5.cjs');
70
- require('../chunk-TMX7YFVM.cjs');
71
- require('../chunk-3YZKDCWY.cjs');
72
- require('../chunk-SJSGSHIT.cjs');
73
- require('../chunk-ZW6FPIFC.cjs');
74
- require('../chunk-ZT5MIFLC.cjs');
75
75
  require('../chunk-ZBP4ZSAJ.cjs');
76
76
  require('../chunk-PPCATBOY.cjs');
77
77
  require('../chunk-TKHCIHE2.cjs');
@@ -84,27 +84,27 @@ require('../chunk-PLIF5CUV.cjs');
84
84
 
85
85
  Object.defineProperty(exports, "ArbiChat", {
86
86
  enumerable: true,
87
- get: function () { return chunkOPH4UZQN_cjs.ArbiChat; }
87
+ get: function () { return chunkCKCG4NDB_cjs.ArbiChat; }
88
88
  });
89
89
  Object.defineProperty(exports, "ConnectedCompactLogin", {
90
90
  enumerable: true,
91
- get: function () { return chunkOPH4UZQN_cjs.ConnectedCompactLogin; }
91
+ get: function () { return chunkCKCG4NDB_cjs.ConnectedCompactLogin; }
92
92
  });
93
93
  Object.defineProperty(exports, "ConnectedEmbeddedChat", {
94
94
  enumerable: true,
95
- get: function () { return chunkOPH4UZQN_cjs.ConnectedEmbeddedChat; }
95
+ get: function () { return chunkCKCG4NDB_cjs.ConnectedEmbeddedChat; }
96
96
  });
97
97
  Object.defineProperty(exports, "ConnectedLoginPage", {
98
98
  enumerable: true,
99
- get: function () { return chunkOPH4UZQN_cjs.ConnectedLoginPage; }
99
+ get: function () { return chunkCKCG4NDB_cjs.ConnectedLoginPage; }
100
100
  });
101
101
  Object.defineProperty(exports, "EmbeddedChatPanel", {
102
102
  enumerable: true,
103
- get: function () { return chunkOPH4UZQN_cjs.EmbeddedChatPanel; }
103
+ get: function () { return chunkCKCG4NDB_cjs.EmbeddedChatPanel; }
104
104
  });
105
105
  Object.defineProperty(exports, "defaultHost", {
106
106
  enumerable: true,
107
- get: function () { return chunkOPH4UZQN_cjs.defaultHost; }
107
+ get: function () { return chunkCKCG4NDB_cjs.defaultHost; }
108
108
  });
109
109
  Object.defineProperty(exports, "useConnection", {
110
110
  enumerable: true,
@@ -17,7 +17,7 @@ const DEFAULT_FACT_COLUMN_LABELS = {
17
17
  labels: "Labels",
18
18
  verified: "Verified",
19
19
  verifiedTooltip: "Verified by a human",
20
- shared: "Shared",
20
+ shared: "Sharing",
21
21
  sharedTooltip: "Shared with the workspace, or private to you & your agents",
22
22
  createdBy: "Created by",
23
23
  sources: "Sources",
@@ -240,8 +240,8 @@ function createFactColumns(slots) {
240
240
  headerTooltip: l.sharedTooltip,
241
241
  field: fieldOf("shared"),
242
242
  // minWidth (not just width) is raised too: AG Grid clamps any persisted width up to it.
243
- width: 110,
244
- minWidth: 110,
243
+ width: 124,
244
+ minWidth: 124,
245
245
  sortable: true,
246
246
  headerClass: "header-hcenter",
247
247
  cellDataType: "boolean",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/facts/factColumns.tsx"],
4
- "sourcesContent": ["/**\n * Column definitions for the Facts grid. Every column has an explicit `colId` (AG Grid persists\n * column state by id: see CLAUDE.md). The app supplies behaviour and app-specific cells through\n * slots; the structure, widths, sorting, filters and presentational cells live here.\n */\nimport type { CSSProperties, ReactNode } from 'react'\nimport type {\n ColDef,\n ICellRendererParams,\n IHeaderParams,\n ValueGetterParams,\n} from 'ag-grid-community'\nimport { CalendarDays, Paperclip, Quote } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { formatSpan } from '../timeline/span'\nimport { decodeWhitespaceEntities } from './fact-text'\nimport { testIdOr } from '../chat/test-id'\n\nexport interface FactColumnLabels {\n inChatHeaderTooltip: string\n inChatTitle: string\n notInChatTitle: string\n removeFromChat: string\n addToChat: string\n fact: string\n dates: string\n dateTitle: string\n labels: string\n verified: string\n verifiedTooltip: string\n shared: string\n sharedTooltip: string\n createdBy: string\n sources: string\n /** Tooltip of the Sources cell for `count` cited documents. */\n sourcedFrom: (count: number) => string\n createdAt: string\n updated: string\n id: string\n}\n\nexport const DEFAULT_FACT_COLUMN_LABELS: FactColumnLabels = {\n inChatHeaderTooltip: 'Facts added to this chat are always in context for this chat',\n inChatTitle: 'In this chat \u2014 always in context for it. Click to remove from chat.',\n notInChatTitle: 'Add to chat \u2014 always in context for this chat',\n removeFromChat: 'Remove from chat',\n addToChat: 'Add to chat',\n fact: 'Fact',\n dates: 'Dates',\n dateTitle: 'Date of the fact itself, not when this was saved',\n labels: 'Labels',\n verified: 'Verified',\n verifiedTooltip: 'Verified by a human',\n shared: 'Shared',\n sharedTooltip: 'Shared with the workspace, or private to you & your agents',\n createdBy: 'Created by',\n sources: 'Sources',\n sourcedFrom: (n) => `Sourced from ${n} document${n === 1 ? '' : 's'} \u2014 open the fact to see them`,\n createdAt: 'Created at',\n updated: 'Updated',\n id: 'ID',\n}\n\nexport interface FactColumnTestIds {\n inChat: (factId: string) => string\n text: (factId: string) => string\n date: (factId: string) => string\n}\n\n/** The fields of a fact the grid reads. Callers' richer types are accepted as-is. */\nexport interface FactRowView {\n external_id: string\n text: string\n confirmed: boolean\n shared: boolean\n date_start?: string | null\n date_end?: string | null\n timezone?: string | null\n tags?: Array<{ name: string }> | null\n citations?: unknown[] | null\n created_by_ext_id?: string | null\n created_at?: string | null\n updated_at?: string | null\n}\n\nexport interface FactColumnSlots<T extends FactRowView> {\n /** Whether the fact is in the host's current chat. With `onToggleInChat`, adds the In chat\n * column; a host without chats leaves both out. Read at render time: the host refreshes the\n * column when its chat changes. */\n isInChat?: (fact: T) => boolean\n /** Add the fact to the current chat, or take it out. */\n onToggleInChat?: (fact: T) => void\n /** Custom header (persistent filter button) for the columns that use one. */\n renderHeader: (params: IHeaderParams, colId: string) => ReactNode\n /** Row action menu, shown at the right edge of the Fact cell. */\n renderRowActions: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** Inline label picker for the Labels cell. */\n renderLabels: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** The Verified switch. */\n renderVerified: (fact: T) => ReactNode\n /** The Shared switch. */\n renderShared: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** The creator avatar. */\n renderCreator: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** Sort/filter value for the Created by column (the creator's display name). */\n getCreatorName: (params: ValueGetterParams<T>) => string\n /** Friendly display of an ISO timestamp (Created at / Updated). */\n formatDate: (iso: string) => string\n labels?: Partial<FactColumnLabels>\n testIds?: Partial<FactColumnTestIds>\n}\n\n/**\n * Date-filter params for a column whose value is an ISO string. AG Grid hands the comparator a JS\n * `Date` from the picker and the raw cell value; this compares UTC day components so a filter\n * never shifts a date by a day for viewers west of UTC.\n */\nexport const ISO_DATE_FILTER_PARAMS = {\n browserDatePicker: true,\n comparator: (filterDate: Date, cellValue: unknown): number => {\n if (!cellValue || typeof cellValue !== 'string') return -1\n const cell = new Date(cellValue)\n if (Number.isNaN(cell.getTime())) return -1\n const cellDay = Date.UTC(cell.getUTCFullYear(), cell.getUTCMonth(), cell.getUTCDate())\n const filterDay = Date.UTC(\n filterDate.getFullYear(),\n filterDate.getMonth(),\n filterDate.getDate()\n )\n return cellDay < filterDay ? -1 : cellDay > filterDay ? 1 : 0\n },\n}\n\n/** How many source documents a fact cites (the Sources column counts documents, not passages). */\nexport function sourceDocCount(fact: Pick<FactRowView, 'citations'> | undefined): number {\n return fact?.citations?.length ?? 0\n}\n\n/** Default left-to-right order; default-hidden columns trail. Every colId must be listed. */\nexport const DEFAULT_FACT_COLUMN_ORDER = [\n 'in_chat',\n 'text',\n 'sources',\n 'tags',\n 'date',\n 'confirmed',\n 'shared',\n 'created_by',\n 'created_at',\n 'updated_at',\n 'note_id',\n] as const\n\nexport function createFactColumns<T extends FactRowView>(slots: FactColumnSlots<T>): ColDef<T>[] {\n // AG Grid's `field` is a path type over the row; for a generic row we assert the known keys.\n const fieldOf = (name: keyof FactRowView) => name as ColDef<T>['field']\n const l = { ...DEFAULT_FACT_COLUMN_LABELS, ...slots.labels }\n const ids = slots.testIds\n\n const { isInChat, onToggleInChat } = slots\n const inChatColumn: ColDef<T>[] =\n isInChat && onToggleInChat\n ? [\n {\n colId: 'in_chat',\n headerName: '',\n headerComponent: () => (\n <span className=\"flex size-full items-center justify-center\">\n <Paperclip className=\"size-3.5 text-muted-foreground\" />\n </span>\n ),\n valueGetter: (params: ValueGetterParams<T>) =>\n params.data ? isInChat(params.data) : false,\n width: 44,\n minWidth: 44,\n maxWidth: 44,\n sortable: true,\n resizable: false,\n headerTooltip: l.inChatHeaderTooltip,\n cellClass: 'cell-hcenter',\n // A toggle, not a readout: a fact in the chat rides every message of it, so it flips\n // in place.\n cellRenderer: (params: ICellRendererParams<T>) => {\n if (!params.data) return null\n const fact = params.data\n const inChat = isInChat(fact)\n return (\n <button\n type=\"button\"\n onClick={() => onToggleInChat(fact)}\n title={inChat ? l.inChatTitle : l.notInChatTitle}\n aria-label={inChat ? l.removeFromChat : l.addToChat}\n aria-pressed={inChat}\n data-testid={testIdOr(ids?.inChat?.(fact.external_id), {\n testId: `facts-grid-in-chat-${fact.external_id}`,\n })}\n className=\"flex h-full items-center\"\n >\n <Paperclip\n className={cn(\n 'size-3.5',\n inChat\n ? 'text-primary'\n : 'text-muted-foreground/30 transition-colors hover:text-muted-foreground'\n )}\n />\n </button>\n )\n },\n },\n ]\n : []\n\n const columns: ColDef<T>[] = [\n ...inChatColumn,\n {\n colId: 'text',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'text'),\n headerName: l.fact,\n field: fieldOf('text'),\n flex: 3,\n minWidth: 280,\n sortable: true,\n filter: 'agTextColumnFilter',\n // Decode the editor's whitespace entities (`&#x20;` for a trailing space) so the tooltip\n // reads as typed, not as raw markdown references.\n tooltipValueGetter: (p) => decodeWhitespaceEntities(p.data?.text),\n // Editable only via the grid api (Rename in the row's menu); clicks never open the editor\n // (suppressClickEdit on the grid).\n editable: true,\n cellEditor: 'agLargeTextCellEditor',\n cellEditorPopup: true,\n cellEditorParams: { rows: 8, cols: 60 },\n valueSetter: (params) => {\n if (!params.data) return false\n params.data.text = params.newValue\n return true\n },\n // NOT `cell-multiline`: this cell has its OWN clamp (the `.fact-clamp` span below, sized\n // from the row height). A second clamp cut the text in half at the minimum row height.\n cellClass: 'relative',\n cellRenderer: (params: ICellRendererParams<T>) => {\n if (!params.data) return null\n const fact = params.data\n // Clamp to however many WHOLE lines fit the row height (leading-snug ~ 20px/line),\n // top-aligned so the BEGINNING of the fact is always shown. No overflow clip here: the\n // wrapper is the cell's content box, shorter than a line at the density floor.\n const rowH = params.node.rowHeight ?? 52\n const clampLines = Math.max(1, Math.floor(rowH / 20))\n return (\n <div className=\"relative flex size-full items-start pr-6\">\n <span\n className=\"fact-clamp whitespace-normal break-words text-sm leading-snug text-foreground\"\n style={{ ['--fact-clamp-lines' as string]: clampLines } as CSSProperties}\n data-testid={testIdOr(ids?.text?.(fact.external_id), {\n testId: `facts-grid-text-${fact.external_id}`,\n })}\n >\n {decodeWhitespaceEntities(fact.text)}\n </span>\n {/* `facts-row-kebab` (app CSS) keeps the menu always visible: touch has no hover. */}\n <div className=\"facts-row-kebab absolute right-0.5 top-1/2 -translate-y-1/2\">\n {slots.renderRowActions(fact, params)}\n </div>\n </div>\n )\n },\n },\n {\n colId: 'date',\n // AG Grid's DEFAULT header, so the sort arrow and filter button are the native ones,\n // identical to the Files table's Date columns.\n headerName: l.dates,\n // Sort on the raw bound rather than the rendered string (\"Oct 2019\" sorts April first).\n field: fieldOf('date_start'),\n flex: 0.8,\n minWidth: 132,\n sortable: true,\n filter: 'agDateColumnFilter',\n filterParams: ISO_DATE_FILTER_PARAMS,\n // The edit value is the date-only slice: a lexical sort matches a chronological one, and\n // the inline editor shows \"2024-03-12\" rather than a full ISO timestamp. Inline typing\n // accepts YYYY, YYYY-MM or YYYY-MM-DD; clearing the cell undates the fact.\n editable: true,\n singleClickEdit: true,\n valueGetter: (params: ValueGetterParams<T>) =>\n params.data?.date_start ? params.data.date_start.slice(0, 10) : null,\n valueSetter: (params) => {\n if (!params.data) return false\n params.data.date_start = params.newValue\n return true\n },\n cellClass: 'relative cell-tnum',\n cellRenderer: (params: ICellRendererParams<T>) => {\n const when = formatSpan(\n params.data?.date_start,\n params.data?.date_end,\n params.data?.timezone\n )\n if (!when) return <span className=\"text-muted-foreground/50\">\u2014</span>\n return (\n <span\n className=\"inline-flex items-center gap-1\"\n data-testid={testIdOr(ids?.date?.(params.data?.external_id ?? ''), {\n testId: `facts-grid-date-${params.data?.external_id}`,\n })}\n title={l.dateTitle}\n >\n <CalendarDays className=\"size-3 opacity-70\" />\n {when}\n </span>\n )\n },\n },\n {\n colId: 'tags',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'tags'),\n headerName: l.labels,\n flex: 0.9,\n // Never narrower than its own header, even with the filter button and sort indicator.\n minWidth: 160,\n sortable: true,\n filter: 'agTextColumnFilter',\n cellClass: 'overflow-visible',\n valueGetter: (params: ValueGetterParams<T>) =>\n (params.data?.tags ?? []).map((t) => t.name).join(', '),\n // Editable in place: toggling a label persists immediately, no dialog round-trip.\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? slots.renderLabels(params.data, params) : null,\n },\n {\n colId: 'confirmed',\n headerName: l.verified,\n headerTooltip: l.verifiedTooltip,\n field: fieldOf('confirmed'),\n // minWidth matches width so the header can't be clamped narrow enough to ellipsize.\n width: 116,\n minWidth: 116,\n sortable: true,\n cellDataType: 'boolean',\n valueGetter: (params) => params.data?.confirmed ?? false,\n cellClass: 'cell-hcenter',\n headerClass: 'header-hcenter',\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? (\n <div className=\"flex h-full items-center justify-center\">\n {slots.renderVerified(params.data)}\n </div>\n ) : null,\n },\n {\n colId: 'shared',\n headerName: l.shared,\n headerTooltip: l.sharedTooltip,\n field: fieldOf('shared'),\n // minWidth (not just width) is raised too: AG Grid clamps any persisted width up to it.\n width: 110,\n minWidth: 110,\n sortable: true,\n headerClass: 'header-hcenter',\n cellDataType: 'boolean',\n valueGetter: (params) => params.data?.shared ?? false,\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? (\n <div className=\"flex h-full items-center justify-center\">\n {slots.renderShared(params.data, params)}\n </div>\n ) : null,\n },\n {\n colId: 'created_by',\n headerName: l.createdBy,\n headerTooltip: l.createdBy,\n width: 138,\n minWidth: 138,\n sortable: true,\n valueGetter: (params) => slots.getCreatorName(params),\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? (\n <div className=\"flex h-full items-center justify-center\">\n {slots.renderCreator(params.data, params)}\n </div>\n ) : null,\n },\n {\n colId: 'sources',\n headerName: l.sources,\n width: 112,\n minWidth: 104,\n sortable: true,\n // A hand-written fact has no sources, which is information rather than a gap: it reads as\n // an em dash instead of a zero.\n valueGetter: (params) => sourceDocCount(params.data),\n cellRenderer: (params: ICellRendererParams<T>) => {\n const n = sourceDocCount(params.data)\n if (n === 0) return <span className=\"text-muted-foreground/40\">\u2014</span>\n return (\n <span\n className=\"inline-flex items-center gap-1 text-xs text-muted-foreground\"\n title={l.sourcedFrom(n)}\n >\n <Quote className=\"size-3 opacity-70\" />\n {n}\n </span>\n )\n },\n },\n {\n colId: 'created_at',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'created_at'),\n headerName: l.createdAt,\n field: fieldOf('created_at'),\n width: 162,\n minWidth: 154,\n sortable: true,\n filter: 'agDateColumnFilter',\n filterParams: ISO_DATE_FILTER_PARAMS,\n // Display-only: a valueFormatter avoids mounting a React component per row.\n cellClass: 'text-muted-foreground',\n valueFormatter: (params) => (params.value ? slots.formatDate(params.value) : ''),\n },\n {\n colId: 'updated_at',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'updated_at'),\n headerName: l.updated,\n field: fieldOf('updated_at'),\n width: 140,\n minWidth: 140,\n // Hidden by default: a column-menu opt-in like the documents grid's long tail.\n hide: true,\n sortable: true,\n filter: 'agDateColumnFilter',\n filterParams: ISO_DATE_FILTER_PARAMS,\n valueFormatter: (params) => (params.value ? slots.formatDate(params.value) : ''),\n },\n {\n colId: 'note_id',\n headerName: l.id,\n field: fieldOf('external_id'),\n width: 120,\n minWidth: 100,\n sortable: true,\n filter: 'agTextColumnFilter',\n // Hidden by default like the documents ID column: needed when quoting a fact to support.\n hide: true,\n cellClass: 'font-mono text-xs text-muted-foreground',\n },\n ]\n\n // Persisted per-user column order still wins once set; bump the grid id to apply a new default.\n return DEFAULT_FACT_COLUMN_ORDER.map((id) => columns.find((c) => c.colId === id)).filter(\n (c): c is ColDef<T> => c !== undefined\n )\n}\n"],
4
+ "sourcesContent": ["/**\n * Column definitions for the Facts grid. Every column has an explicit `colId` (AG Grid persists\n * column state by id: see CLAUDE.md). The app supplies behaviour and app-specific cells through\n * slots; the structure, widths, sorting, filters and presentational cells live here.\n */\nimport type { CSSProperties, ReactNode } from 'react'\nimport type {\n ColDef,\n ICellRendererParams,\n IHeaderParams,\n ValueGetterParams,\n} from 'ag-grid-community'\nimport { CalendarDays, Paperclip, Quote } from 'lucide-react'\nimport { cn } from '@arbidocs/react/ui'\nimport { formatSpan } from '../timeline/span'\nimport { decodeWhitespaceEntities } from './fact-text'\nimport { testIdOr } from '../chat/test-id'\n\nexport interface FactColumnLabels {\n inChatHeaderTooltip: string\n inChatTitle: string\n notInChatTitle: string\n removeFromChat: string\n addToChat: string\n fact: string\n dates: string\n dateTitle: string\n labels: string\n verified: string\n verifiedTooltip: string\n shared: string\n sharedTooltip: string\n createdBy: string\n sources: string\n /** Tooltip of the Sources cell for `count` cited documents. */\n sourcedFrom: (count: number) => string\n createdAt: string\n updated: string\n id: string\n}\n\nexport const DEFAULT_FACT_COLUMN_LABELS: FactColumnLabels = {\n inChatHeaderTooltip: 'Facts added to this chat are always in context for this chat',\n inChatTitle: 'In this chat \u2014 always in context for it. Click to remove from chat.',\n notInChatTitle: 'Add to chat \u2014 always in context for this chat',\n removeFromChat: 'Remove from chat',\n addToChat: 'Add to chat',\n fact: 'Fact',\n dates: 'Dates',\n dateTitle: 'Date of the fact itself, not when this was saved',\n labels: 'Labels',\n verified: 'Verified',\n verifiedTooltip: 'Verified by a human',\n shared: 'Sharing',\n sharedTooltip: 'Shared with the workspace, or private to you & your agents',\n createdBy: 'Created by',\n sources: 'Sources',\n sourcedFrom: (n) => `Sourced from ${n} document${n === 1 ? '' : 's'} \u2014 open the fact to see them`,\n createdAt: 'Created at',\n updated: 'Updated',\n id: 'ID',\n}\n\nexport interface FactColumnTestIds {\n inChat: (factId: string) => string\n text: (factId: string) => string\n date: (factId: string) => string\n}\n\n/** The fields of a fact the grid reads. Callers' richer types are accepted as-is. */\nexport interface FactRowView {\n external_id: string\n text: string\n confirmed: boolean\n shared: boolean\n date_start?: string | null\n date_end?: string | null\n timezone?: string | null\n tags?: Array<{ name: string }> | null\n citations?: unknown[] | null\n created_by_ext_id?: string | null\n created_at?: string | null\n updated_at?: string | null\n}\n\nexport interface FactColumnSlots<T extends FactRowView> {\n /** Whether the fact is in the host's current chat. With `onToggleInChat`, adds the In chat\n * column; a host without chats leaves both out. Read at render time: the host refreshes the\n * column when its chat changes. */\n isInChat?: (fact: T) => boolean\n /** Add the fact to the current chat, or take it out. */\n onToggleInChat?: (fact: T) => void\n /** Custom header (persistent filter button) for the columns that use one. */\n renderHeader: (params: IHeaderParams, colId: string) => ReactNode\n /** Row action menu, shown at the right edge of the Fact cell. */\n renderRowActions: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** Inline label picker for the Labels cell. */\n renderLabels: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** The Verified switch. */\n renderVerified: (fact: T) => ReactNode\n /** The Shared switch. */\n renderShared: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** The creator avatar. */\n renderCreator: (fact: T, params: ICellRendererParams<T>) => ReactNode\n /** Sort/filter value for the Created by column (the creator's display name). */\n getCreatorName: (params: ValueGetterParams<T>) => string\n /** Friendly display of an ISO timestamp (Created at / Updated). */\n formatDate: (iso: string) => string\n labels?: Partial<FactColumnLabels>\n testIds?: Partial<FactColumnTestIds>\n}\n\n/**\n * Date-filter params for a column whose value is an ISO string. AG Grid hands the comparator a JS\n * `Date` from the picker and the raw cell value; this compares UTC day components so a filter\n * never shifts a date by a day for viewers west of UTC.\n */\nexport const ISO_DATE_FILTER_PARAMS = {\n browserDatePicker: true,\n comparator: (filterDate: Date, cellValue: unknown): number => {\n if (!cellValue || typeof cellValue !== 'string') return -1\n const cell = new Date(cellValue)\n if (Number.isNaN(cell.getTime())) return -1\n const cellDay = Date.UTC(cell.getUTCFullYear(), cell.getUTCMonth(), cell.getUTCDate())\n const filterDay = Date.UTC(\n filterDate.getFullYear(),\n filterDate.getMonth(),\n filterDate.getDate()\n )\n return cellDay < filterDay ? -1 : cellDay > filterDay ? 1 : 0\n },\n}\n\n/** How many source documents a fact cites (the Sources column counts documents, not passages). */\nexport function sourceDocCount(fact: Pick<FactRowView, 'citations'> | undefined): number {\n return fact?.citations?.length ?? 0\n}\n\n/** Default left-to-right order; default-hidden columns trail. Every colId must be listed. */\nexport const DEFAULT_FACT_COLUMN_ORDER = [\n 'in_chat',\n 'text',\n 'sources',\n 'tags',\n 'date',\n 'confirmed',\n 'shared',\n 'created_by',\n 'created_at',\n 'updated_at',\n 'note_id',\n] as const\n\nexport function createFactColumns<T extends FactRowView>(slots: FactColumnSlots<T>): ColDef<T>[] {\n // AG Grid's `field` is a path type over the row; for a generic row we assert the known keys.\n const fieldOf = (name: keyof FactRowView) => name as ColDef<T>['field']\n const l = { ...DEFAULT_FACT_COLUMN_LABELS, ...slots.labels }\n const ids = slots.testIds\n\n const { isInChat, onToggleInChat } = slots\n const inChatColumn: ColDef<T>[] =\n isInChat && onToggleInChat\n ? [\n {\n colId: 'in_chat',\n headerName: '',\n headerComponent: () => (\n <span className=\"flex size-full items-center justify-center\">\n <Paperclip className=\"size-3.5 text-muted-foreground\" />\n </span>\n ),\n valueGetter: (params: ValueGetterParams<T>) =>\n params.data ? isInChat(params.data) : false,\n width: 44,\n minWidth: 44,\n maxWidth: 44,\n sortable: true,\n resizable: false,\n headerTooltip: l.inChatHeaderTooltip,\n cellClass: 'cell-hcenter',\n // A toggle, not a readout: a fact in the chat rides every message of it, so it flips\n // in place.\n cellRenderer: (params: ICellRendererParams<T>) => {\n if (!params.data) return null\n const fact = params.data\n const inChat = isInChat(fact)\n return (\n <button\n type=\"button\"\n onClick={() => onToggleInChat(fact)}\n title={inChat ? l.inChatTitle : l.notInChatTitle}\n aria-label={inChat ? l.removeFromChat : l.addToChat}\n aria-pressed={inChat}\n data-testid={testIdOr(ids?.inChat?.(fact.external_id), {\n testId: `facts-grid-in-chat-${fact.external_id}`,\n })}\n className=\"flex h-full items-center\"\n >\n <Paperclip\n className={cn(\n 'size-3.5',\n inChat\n ? 'text-primary'\n : 'text-muted-foreground/30 transition-colors hover:text-muted-foreground'\n )}\n />\n </button>\n )\n },\n },\n ]\n : []\n\n const columns: ColDef<T>[] = [\n ...inChatColumn,\n {\n colId: 'text',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'text'),\n headerName: l.fact,\n field: fieldOf('text'),\n flex: 3,\n minWidth: 280,\n sortable: true,\n filter: 'agTextColumnFilter',\n // Decode the editor's whitespace entities (`&#x20;` for a trailing space) so the tooltip\n // reads as typed, not as raw markdown references.\n tooltipValueGetter: (p) => decodeWhitespaceEntities(p.data?.text),\n // Editable only via the grid api (Rename in the row's menu); clicks never open the editor\n // (suppressClickEdit on the grid).\n editable: true,\n cellEditor: 'agLargeTextCellEditor',\n cellEditorPopup: true,\n cellEditorParams: { rows: 8, cols: 60 },\n valueSetter: (params) => {\n if (!params.data) return false\n params.data.text = params.newValue\n return true\n },\n // NOT `cell-multiline`: this cell has its OWN clamp (the `.fact-clamp` span below, sized\n // from the row height). A second clamp cut the text in half at the minimum row height.\n cellClass: 'relative',\n cellRenderer: (params: ICellRendererParams<T>) => {\n if (!params.data) return null\n const fact = params.data\n // Clamp to however many WHOLE lines fit the row height (leading-snug ~ 20px/line),\n // top-aligned so the BEGINNING of the fact is always shown. No overflow clip here: the\n // wrapper is the cell's content box, shorter than a line at the density floor.\n const rowH = params.node.rowHeight ?? 52\n const clampLines = Math.max(1, Math.floor(rowH / 20))\n return (\n <div className=\"relative flex size-full items-start pr-6\">\n <span\n className=\"fact-clamp whitespace-normal break-words text-sm leading-snug text-foreground\"\n style={{ ['--fact-clamp-lines' as string]: clampLines } as CSSProperties}\n data-testid={testIdOr(ids?.text?.(fact.external_id), {\n testId: `facts-grid-text-${fact.external_id}`,\n })}\n >\n {decodeWhitespaceEntities(fact.text)}\n </span>\n {/* `facts-row-kebab` (app CSS) keeps the menu always visible: touch has no hover. */}\n <div className=\"facts-row-kebab absolute right-0.5 top-1/2 -translate-y-1/2\">\n {slots.renderRowActions(fact, params)}\n </div>\n </div>\n )\n },\n },\n {\n colId: 'date',\n // AG Grid's DEFAULT header, so the sort arrow and filter button are the native ones,\n // identical to the Files table's Date columns.\n headerName: l.dates,\n // Sort on the raw bound rather than the rendered string (\"Oct 2019\" sorts April first).\n field: fieldOf('date_start'),\n flex: 0.8,\n minWidth: 132,\n sortable: true,\n filter: 'agDateColumnFilter',\n filterParams: ISO_DATE_FILTER_PARAMS,\n // The edit value is the date-only slice: a lexical sort matches a chronological one, and\n // the inline editor shows \"2024-03-12\" rather than a full ISO timestamp. Inline typing\n // accepts YYYY, YYYY-MM or YYYY-MM-DD; clearing the cell undates the fact.\n editable: true,\n singleClickEdit: true,\n valueGetter: (params: ValueGetterParams<T>) =>\n params.data?.date_start ? params.data.date_start.slice(0, 10) : null,\n valueSetter: (params) => {\n if (!params.data) return false\n params.data.date_start = params.newValue\n return true\n },\n cellClass: 'relative cell-tnum',\n cellRenderer: (params: ICellRendererParams<T>) => {\n const when = formatSpan(\n params.data?.date_start,\n params.data?.date_end,\n params.data?.timezone\n )\n if (!when) return <span className=\"text-muted-foreground/50\">\u2014</span>\n return (\n <span\n className=\"inline-flex items-center gap-1\"\n data-testid={testIdOr(ids?.date?.(params.data?.external_id ?? ''), {\n testId: `facts-grid-date-${params.data?.external_id}`,\n })}\n title={l.dateTitle}\n >\n <CalendarDays className=\"size-3 opacity-70\" />\n {when}\n </span>\n )\n },\n },\n {\n colId: 'tags',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'tags'),\n headerName: l.labels,\n flex: 0.9,\n // Never narrower than its own header, even with the filter button and sort indicator.\n minWidth: 160,\n sortable: true,\n filter: 'agTextColumnFilter',\n cellClass: 'overflow-visible',\n valueGetter: (params: ValueGetterParams<T>) =>\n (params.data?.tags ?? []).map((t) => t.name).join(', '),\n // Editable in place: toggling a label persists immediately, no dialog round-trip.\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? slots.renderLabels(params.data, params) : null,\n },\n {\n colId: 'confirmed',\n headerName: l.verified,\n headerTooltip: l.verifiedTooltip,\n field: fieldOf('confirmed'),\n // minWidth matches width so the header can't be clamped narrow enough to ellipsize.\n width: 116,\n minWidth: 116,\n sortable: true,\n cellDataType: 'boolean',\n valueGetter: (params) => params.data?.confirmed ?? false,\n cellClass: 'cell-hcenter',\n headerClass: 'header-hcenter',\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? (\n <div className=\"flex h-full items-center justify-center\">\n {slots.renderVerified(params.data)}\n </div>\n ) : null,\n },\n {\n colId: 'shared',\n headerName: l.shared,\n headerTooltip: l.sharedTooltip,\n field: fieldOf('shared'),\n // minWidth (not just width) is raised too: AG Grid clamps any persisted width up to it.\n width: 124,\n minWidth: 124,\n sortable: true,\n headerClass: 'header-hcenter',\n cellDataType: 'boolean',\n valueGetter: (params) => params.data?.shared ?? false,\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? (\n <div className=\"flex h-full items-center justify-center\">\n {slots.renderShared(params.data, params)}\n </div>\n ) : null,\n },\n {\n colId: 'created_by',\n headerName: l.createdBy,\n headerTooltip: l.createdBy,\n width: 138,\n minWidth: 138,\n sortable: true,\n valueGetter: (params) => slots.getCreatorName(params),\n cellRenderer: (params: ICellRendererParams<T>) =>\n params.data ? (\n <div className=\"flex h-full items-center justify-center\">\n {slots.renderCreator(params.data, params)}\n </div>\n ) : null,\n },\n {\n colId: 'sources',\n headerName: l.sources,\n width: 112,\n minWidth: 104,\n sortable: true,\n // A hand-written fact has no sources, which is information rather than a gap: it reads as\n // an em dash instead of a zero.\n valueGetter: (params) => sourceDocCount(params.data),\n cellRenderer: (params: ICellRendererParams<T>) => {\n const n = sourceDocCount(params.data)\n if (n === 0) return <span className=\"text-muted-foreground/40\">\u2014</span>\n return (\n <span\n className=\"inline-flex items-center gap-1 text-xs text-muted-foreground\"\n title={l.sourcedFrom(n)}\n >\n <Quote className=\"size-3 opacity-70\" />\n {n}\n </span>\n )\n },\n },\n {\n colId: 'created_at',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'created_at'),\n headerName: l.createdAt,\n field: fieldOf('created_at'),\n width: 162,\n minWidth: 154,\n sortable: true,\n filter: 'agDateColumnFilter',\n filterParams: ISO_DATE_FILTER_PARAMS,\n // Display-only: a valueFormatter avoids mounting a React component per row.\n cellClass: 'text-muted-foreground',\n valueFormatter: (params) => (params.value ? slots.formatDate(params.value) : ''),\n },\n {\n colId: 'updated_at',\n suppressHeaderFilterButton: true,\n headerComponent: (p: IHeaderParams) => slots.renderHeader(p, 'updated_at'),\n headerName: l.updated,\n field: fieldOf('updated_at'),\n width: 140,\n minWidth: 140,\n // Hidden by default: a column-menu opt-in like the documents grid's long tail.\n hide: true,\n sortable: true,\n filter: 'agDateColumnFilter',\n filterParams: ISO_DATE_FILTER_PARAMS,\n valueFormatter: (params) => (params.value ? slots.formatDate(params.value) : ''),\n },\n {\n colId: 'note_id',\n headerName: l.id,\n field: fieldOf('external_id'),\n width: 120,\n minWidth: 100,\n sortable: true,\n filter: 'agTextColumnFilter',\n // Hidden by default like the documents ID column: needed when quoting a fact to support.\n hide: true,\n cellClass: 'font-mono text-xs text-muted-foreground',\n },\n ]\n\n // Persisted per-user column order still wins once set; bump the grid id to apply a new default.\n return DEFAULT_FACT_COLUMN_ORDER.map((id) => columns.find((c) => c.colId === id)).filter(\n (c): c is ColDef<T> => c !== undefined\n )\n}\n"],
5
5
  "mappings": "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",
6
6
  "names": []
7
7
  }