@arbidocs/blocks 0.5.124 → 0.5.126

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 (152) hide show
  1. package/dist/{ClippingMediaViewer-ZFEX5A3U.cjs → ClippingMediaViewer-47BAXNLO.cjs} +10 -11
  2. package/dist/ClippingMediaViewer-47BAXNLO.cjs.map +1 -0
  3. package/dist/{ClippingPdfViewer-3LRTEPHV.cjs → ClippingPdfViewer-D5BYHEAH.cjs} +16 -14
  4. package/dist/ClippingPdfViewer-D5BYHEAH.cjs.map +1 -0
  5. package/dist/{ConnectedCallDock-XJOYVVAH.cjs → ConnectedCallDock-733O5M36.cjs} +5 -5
  6. package/dist/{ConnectedCallDock-XJOYVVAH.cjs.map → ConnectedCallDock-733O5M36.cjs.map} +1 -1
  7. package/dist/{ConnectedCallRoom-CUDYAPQK.cjs → ConnectedCallRoom-TAUGSRGV.cjs} +5 -5
  8. package/dist/{ConnectedCallRoom-CUDYAPQK.cjs.map → ConnectedCallRoom-TAUGSRGV.cjs.map} +1 -1
  9. package/dist/{ConnectedNativeDocxComparison-QKHCYD6W.cjs → ConnectedNativeDocxComparison-HDE522YC.cjs} +9 -9
  10. package/dist/{ConnectedNativeDocxComparison-QKHCYD6W.cjs.map → ConnectedNativeDocxComparison-HDE522YC.cjs.map} +1 -1
  11. package/dist/{ConnectedPresentation-OV2KBOLK.cjs → ConnectedPresentation-SI3L77J4.cjs} +33 -34
  12. package/dist/ConnectedPresentation-SI3L77J4.cjs.map +1 -0
  13. package/dist/{ConnectedSlidesTab-LUAGZ6FD.cjs → ConnectedSlidesTab-JSPU6EY5.cjs} +37 -43
  14. package/dist/ConnectedSlidesTab-JSPU6EY5.cjs.map +1 -0
  15. package/dist/{ConnectedStreamedWordArtifact-AG62232A.cjs → ConnectedStreamedWordArtifact-4FHPOAFZ.cjs} +9 -9
  16. package/dist/{ConnectedStreamedWordArtifact-AG62232A.cjs.map → ConnectedStreamedWordArtifact-4FHPOAFZ.cjs.map} +1 -1
  17. package/dist/{DocumentReviewCard-M53XFLI2.cjs → DocumentReviewCard-BDNXP3D4.cjs} +4 -4
  18. package/dist/{DocumentReviewCard-M53XFLI2.cjs.map → DocumentReviewCard-BDNXP3D4.cjs.map} +1 -1
  19. package/dist/{FilesViewerDialog-JWKNJLWG.cjs → FilesViewerDialog-WQRNSKWM.cjs} +10 -11
  20. package/dist/FilesViewerDialog-WQRNSKWM.cjs.map +1 -0
  21. package/dist/{NativeDocxEditor-2LQY2CTV.cjs → NativeDocxEditor-SUDULUN3.cjs} +6 -6
  22. package/dist/{NativeDocxEditor-2LQY2CTV.cjs.map → NativeDocxEditor-SUDULUN3.cjs.map} +1 -1
  23. package/dist/{SpotlightStrip-ED22UYTM.cjs → SpotlightStrip-QQ2WUI32.cjs} +28 -29
  24. package/dist/SpotlightStrip-QQ2WUI32.cjs.map +1 -0
  25. package/dist/WorkspaceTableView-3XYAV4BV.cjs +1 -1
  26. package/dist/agents/index.cjs +1 -1
  27. package/dist/ai-IEIR7SC2.cjs +1 -1
  28. package/dist/calls/index.cjs +2 -2
  29. package/dist/{chunk-ZZZITHGK.cjs → chunk-26SFI2BH.cjs} +16 -3
  30. package/dist/chunk-26SFI2BH.cjs.map +1 -0
  31. package/dist/{chunk-NG2EE7HR.cjs → chunk-463QM764.cjs} +3 -3
  32. package/dist/{chunk-NG2EE7HR.cjs.map → chunk-463QM764.cjs.map} +1 -1
  33. package/dist/{chunk-XGM4VVNV.cjs → chunk-4KEQ62SL.cjs} +6 -6
  34. package/dist/{chunk-XGM4VVNV.cjs.map → chunk-4KEQ62SL.cjs.map} +1 -1
  35. package/dist/{chunk-YGBHY67W.cjs → chunk-6B4CCDDB.cjs} +5 -5
  36. package/dist/{chunk-YGBHY67W.cjs.map → chunk-6B4CCDDB.cjs.map} +1 -1
  37. package/dist/{chunk-JY7UUZQG.cjs → chunk-7Q46YAX4.cjs} +74 -71
  38. package/dist/chunk-7Q46YAX4.cjs.map +1 -0
  39. package/dist/{chunk-3ZZZO4F7.cjs → chunk-BY3QA3S5.cjs} +9 -9
  40. package/dist/{chunk-3ZZZO4F7.cjs.map → chunk-BY3QA3S5.cjs.map} +1 -1
  41. package/dist/{chunk-VKH3BEZE.cjs → chunk-CMPHJRVV.cjs} +3 -3
  42. package/dist/{chunk-VKH3BEZE.cjs.map → chunk-CMPHJRVV.cjs.map} +1 -1
  43. package/dist/{chunk-BX6G2ZCI.cjs → chunk-FB3JXSQT.cjs} +71 -43
  44. package/dist/chunk-FB3JXSQT.cjs.map +1 -0
  45. package/dist/{chunk-EMRY62HS.cjs → chunk-FGOJBOZX.cjs} +4 -4
  46. package/dist/{chunk-EMRY62HS.cjs.map → chunk-FGOJBOZX.cjs.map} +1 -1
  47. package/dist/{chunk-V6MW7B4B.cjs → chunk-I4X72WUT.cjs} +6 -6
  48. package/dist/{chunk-V6MW7B4B.cjs.map → chunk-I4X72WUT.cjs.map} +1 -1
  49. package/dist/{chunk-ORNLCBNE.cjs → chunk-JVEDKKNO.cjs} +43 -4
  50. package/dist/chunk-JVEDKKNO.cjs.map +1 -0
  51. package/dist/{chunk-7557LDAN.cjs → chunk-LOB2ATS5.cjs} +23 -10
  52. package/dist/chunk-LOB2ATS5.cjs.map +1 -0
  53. package/dist/{chunk-MXBXZXXQ.cjs → chunk-LXM5QXII.cjs} +3 -3
  54. package/dist/{chunk-MXBXZXXQ.cjs.map → chunk-LXM5QXII.cjs.map} +1 -1
  55. package/dist/chunk-OALQGO5C.cjs +18 -0
  56. package/dist/{chunk-SDRYSLOX.cjs.map → chunk-OALQGO5C.cjs.map} +1 -1
  57. package/dist/{chunk-2CSLFAGF.cjs → chunk-Q6N5D3R5.cjs} +34 -8
  58. package/dist/chunk-Q6N5D3R5.cjs.map +1 -0
  59. package/dist/{chunk-MVXHTAJ4.cjs → chunk-QWVUBTW3.cjs} +9 -9
  60. package/dist/{chunk-MVXHTAJ4.cjs.map → chunk-QWVUBTW3.cjs.map} +1 -1
  61. package/dist/{chunk-ADPRIBSH.cjs → chunk-X7ALF4MP.cjs} +7 -7
  62. package/dist/{chunk-ADPRIBSH.cjs.map → chunk-X7ALF4MP.cjs.map} +1 -1
  63. package/dist/{chunk-COD5ENHK.cjs → chunk-XNB27POJ.cjs} +4 -4
  64. package/dist/{chunk-COD5ENHK.cjs.map → chunk-XNB27POJ.cjs.map} +1 -1
  65. package/dist/{chunk-H236SNEV.cjs → chunk-ZCU72Q76.cjs} +191 -165
  66. package/dist/chunk-ZCU72Q76.cjs.map +1 -0
  67. package/dist/connect/docx.cjs +13 -13
  68. package/dist/connect/index.cjs +198 -163
  69. package/dist/connect/index.cjs.map +1 -1
  70. package/dist/connect/viewer.cjs +8 -9
  71. package/dist/connection/ai.d.ts +1 -0
  72. package/dist/connection/docx/ConnectedNativeDocxEditor.js +4 -5
  73. package/dist/connection/docx/ConnectedNativeDocxEditor.js.map +2 -2
  74. package/dist/connection/docx/save-native-version.d.ts +3 -0
  75. package/dist/connection/docx/save-native-version.js +19 -0
  76. package/dist/connection/docx/save-native-version.js.map +7 -0
  77. package/dist/connection/presentation/ClippingPdfViewer.js +8 -5
  78. package/dist/connection/presentation/ClippingPdfViewer.js.map +2 -2
  79. package/dist/connection/presentation/ConnectedSlidesTab.js +8 -13
  80. package/dist/connection/presentation/ConnectedSlidesTab.js.map +2 -2
  81. package/dist/connection/presentation/usePresentationController.js +24 -15
  82. package/dist/connection/presentation/usePresentationController.js.map +2 -2
  83. package/dist/connection/presentation/usePresentationFiles.d.ts +2 -1
  84. package/dist/connection/presentation/usePresentationFiles.js +15 -6
  85. package/dist/connection/presentation/usePresentationFiles.js.map +2 -2
  86. package/dist/connection/search/ConnectedSearchPage.d.ts +0 -11
  87. package/dist/connection/search/ConnectedSearchPage.js +3 -0
  88. package/dist/connection/search/ConnectedSearchPage.js.map +2 -2
  89. package/dist/connection/search/SearchResultRows.js +75 -43
  90. package/dist/connection/search/SearchResultRows.js.map +2 -2
  91. package/dist/connection/viewer/CleanViewControl.d.ts +3 -1
  92. package/dist/connection/viewer/CleanViewControl.js +5 -1
  93. package/dist/connection/viewer/CleanViewControl.js.map +2 -2
  94. package/dist/connection/viewer/ConnectedDocumentViewer.js +1 -1
  95. package/dist/connection/viewer/ConnectedDocumentViewer.js.map +2 -2
  96. package/dist/connection/viewer/VersionDropdown.js +1 -1
  97. package/dist/connection/viewer/VersionDropdown.js.map +1 -1
  98. package/dist/connection/viewer/ViewerPdfPane.js +2 -0
  99. package/dist/connection/viewer/ViewerPdfPane.js.map +2 -2
  100. package/dist/connection/viewer/pdf/usePassageTextFallback.d.ts +12 -0
  101. package/dist/connection/viewer/pdf/usePassageTextFallback.js +30 -0
  102. package/dist/connection/viewer/pdf/usePassageTextFallback.js.map +7 -0
  103. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js +2 -11
  104. package/dist/connection/viewer/pdf/usePdfPassageHighlights.js.map +2 -2
  105. package/dist/connection/viewer/useCleanView.d.ts +1 -1
  106. package/dist/connection/viewer/useCleanView.js +2 -2
  107. package/dist/connection/viewer/useCleanView.js.map +2 -2
  108. package/dist/connection/viewer/useViewedDocument.d.ts +1 -0
  109. package/dist/connection/viewer/useViewerTabs.js +13 -1
  110. package/dist/connection/viewer/useViewerTabs.js.map +2 -2
  111. package/dist/docx/DocxCommandMenu.js +2 -1
  112. package/dist/docx/DocxCommandMenu.js.map +2 -2
  113. package/dist/docx/NativeDocxEditor.d.ts +2 -1
  114. package/dist/docx/NativeDocxEditor.js +30 -5
  115. package/dist/docx/NativeDocxEditor.js.map +2 -2
  116. package/dist/docx/index.cjs +38 -38
  117. package/dist/embed/index.cjs +2 -2
  118. package/dist/facts/index.cjs +43 -43
  119. package/dist/index.cjs +73 -73
  120. package/dist/presentation/ClipCaptureOverlay.js +14 -1
  121. package/dist/presentation/ClipCaptureOverlay.js.map +2 -2
  122. package/dist/presentation/ClipImage.js +7 -4
  123. package/dist/presentation/ClipImage.js.map +2 -2
  124. package/dist/presentation/ClipTray.js +11 -7
  125. package/dist/presentation/ClipTray.js.map +2 -2
  126. package/dist/presentation/SlidesEditor.js +6 -2
  127. package/dist/presentation/SlidesEditor.js.map +2 -2
  128. package/dist/presentation/store.d.ts +2 -0
  129. package/dist/presentation/store.js +15 -0
  130. package/dist/presentation/store.js.map +3 -3
  131. package/dist/settings/index.cjs +1 -1
  132. package/dist/studio/index.cjs +1 -1
  133. package/dist/styles.css +1 -1
  134. package/dist/workflow-canvas/index.cjs +12 -12
  135. package/node_modules/@arbidocs/coedit/package.json +1 -1
  136. package/package.json +5 -5
  137. package/dist/ClippingMediaViewer-ZFEX5A3U.cjs.map +0 -1
  138. package/dist/ClippingPdfViewer-3LRTEPHV.cjs.map +0 -1
  139. package/dist/ConnectedPresentation-OV2KBOLK.cjs.map +0 -1
  140. package/dist/ConnectedSlidesTab-LUAGZ6FD.cjs.map +0 -1
  141. package/dist/FilesViewerDialog-JWKNJLWG.cjs.map +0 -1
  142. package/dist/SpotlightStrip-ED22UYTM.cjs.map +0 -1
  143. package/dist/chunk-2CSLFAGF.cjs.map +0 -1
  144. package/dist/chunk-7557LDAN.cjs.map +0 -1
  145. package/dist/chunk-BX6G2ZCI.cjs.map +0 -1
  146. package/dist/chunk-GFUOCGY6.cjs +0 -32
  147. package/dist/chunk-GFUOCGY6.cjs.map +0 -1
  148. package/dist/chunk-H236SNEV.cjs.map +0 -1
  149. package/dist/chunk-JY7UUZQG.cjs.map +0 -1
  150. package/dist/chunk-ORNLCBNE.cjs.map +0 -1
  151. package/dist/chunk-SDRYSLOX.cjs +0 -18
  152. package/dist/chunk-ZZZITHGK.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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, useArbiSessionStore, useParsedDocument } from '@arbidocs/react'\nimport { useProcessedChunks } from '@arbidocs/react/viewers'\nimport { useViewerPassageCitation } from '../support'\nimport { PdfPassageHighlights } from './PdfPassageHighlights'\nimport { passageBoxesByPage, passagePlaced } 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 could not be placed on its page (a document parsed before passages had\n // boxes): the text view marks it instead.\n const session = useArbiSessionStore()\n const fellBackFor = useRef<string | null>(null)\n useEffect(() => {\n if (!active || !parsed || !documentId) return\n const key = `${documentId}:${active}`\n if (fellBackFor.current === key || passagePlaced(processedChunks, active)) return\n fellBackFor.current = key\n session.setDocumentViewer({ tab: 'html' })\n }, [active, parsed, processedChunks, documentId, session])\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": ";AAkEQ;AA3DR,SAAS,aAAa,WAAW,SAAS,cAA8B;AACxE,SAAS,qBAAqB,qBAAqB,yBAAyB;AAC5E,SAAS,0BAA0B;AACnC,SAAS,gCAAgC;AACzC,SAAS,4BAA4B;AACrC,SAAS,oBAAoB,qBAAqB;AAElD,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,UAAU,oBAAoB;AACpC,QAAM,cAAc,OAAsB,IAAI;AAC9C,YAAU,MAAM;AACd,QAAI,CAAC,UAAU,CAAC,UAAU,CAAC,WAAY;AACvC,UAAM,MAAM,GAAG,UAAU,IAAI,MAAM;AACnC,QAAI,YAAY,YAAY,OAAO,cAAc,iBAAiB,MAAM,EAAG;AAC3E,gBAAY,UAAU;AACtB,YAAQ,kBAAkB,EAAE,KAAK,OAAO,CAAC;AAAA,EAC3C,GAAG,CAAC,QAAQ,QAAQ,iBAAiB,YAAY,OAAO,CAAC;AAIzD,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;",
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
6
  "names": []
7
7
  }
@@ -7,7 +7,7 @@
7
7
  import { type ReactNode } from 'react';
8
8
  export declare function useCleanView(
9
9
  /** Over the body in any view (the spotlight's strip). */
10
- extra?: ReactNode): {
10
+ extra?: ReactNode, controls?: ReactNode): {
11
11
  on: boolean;
12
12
  frame: {
13
13
  bare: boolean;
@@ -3,7 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef } from "react";
4
4
  import { useArbiSessionState, useArbiSessionStore } from "@arbidocs/react";
5
5
  import { CleanViewControl } from "./CleanViewControl.js";
6
- function useCleanView(extra) {
6
+ function useCleanView(extra, controls) {
7
7
  const session = useArbiSessionStore();
8
8
  const detached = useArbiSessionState((s) => s.documentViewer.detached);
9
9
  const presenting = useArbiSessionState((s) => s.documentViewer.presenting);
@@ -20,7 +20,7 @@ function useCleanView(extra) {
20
20
  frame: {
21
21
  bare: on,
22
22
  overlay: /* @__PURE__ */ jsxs(Fragment, { children: [
23
- on && /* @__PURE__ */ jsx(CleanViewControl, { onExit: () => session.setDocumentViewer({ presenting: false }) }),
23
+ on && /* @__PURE__ */ jsx(CleanViewControl, { onExit: () => session.setDocumentViewer({ presenting: false }), children: controls }),
24
24
  extra
25
25
  ] })
26
26
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/connection/viewer/useCleanView.tsx"],
4
- "sourcesContent": ["/**\n * The viewer's clean view: popped out with `documentViewer.presenting`, it shows only the document\n * on black (no header, bars or controls), to share in a call or put full screen. Its one control\n * (`CleanViewControl`: full screen, show the controls again) shows while the pointer moves. Popping\n * the viewer back in ends the clean view.\n */\n\nimport { useEffect, useRef, type ReactNode } from 'react'\nimport { useArbiSessionState, useArbiSessionStore } from '@arbidocs/react'\nimport { CleanViewControl } from './CleanViewControl'\n\nexport function useCleanView(\n /** Over the body in any view (the spotlight's strip). */\n extra?: ReactNode\n): { on: boolean; frame: { bare: boolean; overlay: ReactNode } } {\n const session = useArbiSessionStore()\n const detached = useArbiSessionState((s) => s.documentViewer.detached)\n const presenting = useArbiSessionState((s) => s.documentViewer.presenting)\n const on = detached && presenting\n\n // Back in the app's window: the next pop-out shows the controls as usual.\n const wasDetached = useRef(detached)\n useEffect(() => {\n if (wasDetached.current && !detached && presenting) {\n session.setDocumentViewer({ presenting: false })\n }\n wasDetached.current = detached\n }, [detached, presenting, session])\n\n return {\n on,\n frame: {\n bare: on,\n overlay: (\n <>\n {on && (\n <CleanViewControl onExit={() => session.setDocumentViewer({ presenting: false })} />\n )}\n {extra}\n </>\n ),\n },\n }\n}\n"],
5
- "mappings": ";AAkCQ,mBAEI,KAFJ;AA3BR,SAAS,WAAW,cAA8B;AAClD,SAAS,qBAAqB,2BAA2B;AACzD,SAAS,wBAAwB;AAE1B,SAAS,aAEd,OAC+D;AAC/D,QAAM,UAAU,oBAAoB;AACpC,QAAM,WAAW,oBAAoB,CAAC,MAAM,EAAE,eAAe,QAAQ;AACrE,QAAM,aAAa,oBAAoB,CAAC,MAAM,EAAE,eAAe,UAAU;AACzE,QAAM,KAAK,YAAY;AAGvB,QAAM,cAAc,OAAO,QAAQ;AACnC,YAAU,MAAM;AACd,QAAI,YAAY,WAAW,CAAC,YAAY,YAAY;AAClD,cAAQ,kBAAkB,EAAE,YAAY,MAAM,CAAC;AAAA,IACjD;AACA,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,UAAU,YAAY,OAAO,CAAC;AAElC,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SACE,iCACG;AAAA,cACC,oBAAC,oBAAiB,QAAQ,MAAM,QAAQ,kBAAkB,EAAE,YAAY,MAAM,CAAC,GAAG;AAAA,QAEnF;AAAA,SACH;AAAA,IAEJ;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["/**\n * The viewer's clean view: popped out with `documentViewer.presenting`, it shows only the document\n * on black (no header, bars or controls), to share in a call or put full screen. Its one control\n * (`CleanViewControl`: full screen, show the controls again) shows while the pointer moves. Popping\n * the viewer back in ends the clean view.\n */\n\nimport { useEffect, useRef, type ReactNode } from 'react'\nimport { useArbiSessionState, useArbiSessionStore } from '@arbidocs/react'\nimport { CleanViewControl } from './CleanViewControl'\n\nexport function useCleanView(\n /** Over the body in any view (the spotlight's strip). */\n extra?: ReactNode,\n controls?: ReactNode\n): { on: boolean; frame: { bare: boolean; overlay: ReactNode } } {\n const session = useArbiSessionStore()\n const detached = useArbiSessionState((s) => s.documentViewer.detached)\n const presenting = useArbiSessionState((s) => s.documentViewer.presenting)\n const on = detached && presenting\n\n // Back in the app's window: the next pop-out shows the controls as usual.\n const wasDetached = useRef(detached)\n useEffect(() => {\n if (wasDetached.current && !detached && presenting) {\n session.setDocumentViewer({ presenting: false })\n }\n wasDetached.current = detached\n }, [detached, presenting, session])\n\n return {\n on,\n frame: {\n bare: on,\n overlay: (\n <>\n {on && (\n <CleanViewControl onExit={() => session.setDocumentViewer({ presenting: false })}>\n {controls}\n </CleanViewControl>\n )}\n {extra}\n </>\n ),\n },\n }\n}\n"],
5
+ "mappings": ";AAmCQ,mBAEI,KAFJ;AA5BR,SAAS,WAAW,cAA8B;AAClD,SAAS,qBAAqB,2BAA2B;AACzD,SAAS,wBAAwB;AAE1B,SAAS,aAEd,OACA,UAC+D;AAC/D,QAAM,UAAU,oBAAoB;AACpC,QAAM,WAAW,oBAAoB,CAAC,MAAM,EAAE,eAAe,QAAQ;AACrE,QAAM,aAAa,oBAAoB,CAAC,MAAM,EAAE,eAAe,UAAU;AACzE,QAAM,KAAK,YAAY;AAGvB,QAAM,cAAc,OAAO,QAAQ;AACnC,YAAU,MAAM;AACd,QAAI,YAAY,WAAW,CAAC,YAAY,YAAY;AAClD,cAAQ,kBAAkB,EAAE,YAAY,MAAM,CAAC;AAAA,IACjD;AACA,gBAAY,UAAU;AAAA,EACxB,GAAG,CAAC,UAAU,YAAY,OAAO,CAAC;AAElC,SAAO;AAAA,IACL;AAAA,IACA,OAAO;AAAA,MACL,MAAM;AAAA,MACN,SACE,iCACG;AAAA,cACC,oBAAC,oBAAiB,QAAQ,MAAM,QAAQ,kBAAkB,EAAE,YAAY,MAAM,CAAC,GAC5E,oBACH;AAAA,QAED;AAAA,SACH;AAAA,IAEJ;AAAA,EACF;AACF;",
6
6
  "names": []
7
7
  }
@@ -29,6 +29,7 @@ export declare function useViewedDocument(documentId: string): {
29
29
  config_ext_id?: string | null;
30
30
  parent_ext_id?: string | null;
31
31
  current_version: number;
32
+ autosave: boolean;
32
33
  versions: import("@arbidocs/client").components["schemas"]["DocVersion"][];
33
34
  thread_id?: string | null;
34
35
  derived_from: import("@arbidocs/client").components["schemas"]["DerivedFrom"][];
@@ -41,6 +41,7 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
41
41
  phonePdfChosen
42
42
  } = useArbiSessionState((s) => s.documentViewer);
43
43
  const setActiveTab = (tab) => session.setDocumentViewer({ tab });
44
+ const passageId = useArbiSessionState((s) => s.viewingDocument?.passageId ?? null);
44
45
  const isTextFile = friendlyFileType(documentData?.file_type, documentData?.file_name) === "Text";
45
46
  const isPhone = useIsPhone();
46
47
  const phoneDefaultDecidedFor = useRef(null);
@@ -51,6 +52,8 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
51
52
  setActiveTab("slides");
52
53
  } else if (!isPresentation && documentData && activeTab === "slides") {
53
54
  setActiveTab(isDocx ? "docx" : isXlsx ? "xlsx" : "pdf");
55
+ } else if (passageId && activeTab === "pdf" && (isArtifact || isDocx)) {
56
+ setActiveTab("html");
54
57
  } else if (isArtifact && (activeTab === "pdf" || !liveKind && activeTab === "docx")) {
55
58
  setActiveTab(liveKind ? "preview" : "edit");
56
59
  } else if (isDocx && activeTab === "pdf") {
@@ -62,7 +65,16 @@ function useViewerTabs(doc, isCompact, hasHistory = false) {
62
65
  } else if (!isArtifact && !isDocx && !isXlsx && documentData && (activeTab === "docx" || activeTab === "xlsx")) {
63
66
  setActiveTab("pdf");
64
67
  }
65
- }, [hasDocumentData, documentKey, isArtifact, isDocx, isXlsx, liveKind, isPresentation]);
68
+ }, [
69
+ hasDocumentData,
70
+ documentKey,
71
+ isArtifact,
72
+ isDocx,
73
+ isXlsx,
74
+ liveKind,
75
+ isPresentation,
76
+ passageId
77
+ ]);
66
78
  useEffect(() => {
67
79
  if (!tabRequest || !documentKey || tabRequest.documentId !== documentKey) return;
68
80
  phoneDefaultDecidedFor.current = documentKey;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/connection/viewer/useViewerTabs.tsx"],
4
- "sourcesContent": ["/**\n * Tabs of the document viewer: which tabs a document has, the automatic switches when the\n * document's type or parsed content changes, and switching (which ends a comparison when leaving\n * the tab that hosts it). The open tab is the session state's, so whatever opens a document can\n * open it on a tab.\n */\n\nimport { useEffect, useRef } from 'react'\nimport { Code, FileText, History, MonitorPlay, Presentation } from 'lucide-react'\nimport { friendlyFileType } from '@arbidocs/react/ui'\nimport {\n AudIcon,\n DocIcon,\n EmlIcon,\n HtmlIcon,\n ImgIcon,\n PdfIcon,\n VidIcon,\n XlsIcon,\n useArbiSessionState,\n useArbiSessionStore,\n type ArbiViewerTab,\n} from '@arbidocs/react'\nimport type { ViewerTab } from '../../files/ViewerParts'\nimport { useIsPhone } from '../../lib/use-media-query'\nimport type { ViewedDocument } from './useViewedDocument'\n\n/**\n * @param hasHistory The document has earlier versions (a signed copy, a re-upload): PDF and text\n * documents then get a Versions tab too. Artifacts and Word documents always have one.\n */\nexport function useViewerTabs(doc: ViewedDocument, isCompact: boolean, hasHistory = false) {\n const {\n documentData,\n isArtifact,\n isPresentation,\n isDraft,\n isStreaming,\n isDocx,\n isXlsx,\n isEmail,\n isVideo,\n isAudio,\n isImage,\n liveKind,\n hasParsedContent,\n isParsedDocLoading,\n } = doc\n const session = useArbiSessionStore()\n const {\n tab: activeTab,\n compareId,\n tabRequest,\n phonePdfChosen,\n } = useArbiSessionState((s) => s.documentViewer)\n const setActiveTab = (tab: ArbiViewerTab) => session.setDocumentViewer({ tab })\n // A plain-text file is still shown as a generated PDF, but the tab names the file the user\n // opened (\"Text\", as the Fields panel does), not the rendering format.\n const isTextFile = friendlyFileType(documentData?.file_type, documentData?.file_name) === 'Text'\n const isPhone = useIsPhone()\n const phoneDefaultDecidedFor = useRef<string | null>(null)\n\n // Switch to the tab that fits the document type. Only on type changes: never over the user's own\n // choice. Keyed on the document and its kind, not on the record: a refreshed record (a new\n // version finishing processing) must not send a user on the PDF tab of a Word document back to\n // the editor.\n const hasDocumentData = !!documentData\n const documentKey = documentData?.external_id\n useEffect(() => {\n // A presentation opens on its slides; another document never shows that tab.\n if (isPresentation && hasDocumentData && activeTab === 'pdf') {\n setActiveTab('slides')\n } else if (!isPresentation && documentData && activeTab === 'slides') {\n setActiveTab(isDocx ? 'docx' : isXlsx ? 'xlsx' : 'pdf')\n }\n // A Word artifact (an AI draft, stored as .docx) has one Word tab, 'edit', not a DOCX tab.\n else if (isArtifact && (activeTab === 'pdf' || (!liveKind && activeTab === 'docx'))) {\n setActiveTab(liveKind ? 'preview' : 'edit')\n } else if (isDocx && activeTab === 'pdf') {\n setActiveTab('docx')\n } else if (!liveKind && activeTab === 'preview') {\n setActiveTab(isArtifact ? 'edit' : 'pdf')\n } else if (!isArtifact && documentData && activeTab === 'edit') {\n setActiveTab(isDocx ? 'docx' : isXlsx ? 'xlsx' : 'pdf')\n } else if (\n !isArtifact &&\n !isDocx &&\n !isXlsx &&\n documentData &&\n (activeTab === 'docx' || activeTab === 'xlsx')\n ) {\n setActiveTab('pdf')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [hasDocumentData, documentKey, isArtifact, isDocx, isXlsx, liveKind, isPresentation])\n\n // A tab asked for when the document was opened (a signature request opens on the PDF, where it\n // is signed) wins over the type's own tab once that document has loaded, and over the phone's\n // text default. Declared after the type switch above so it has the last word.\n useEffect(() => {\n if (!tabRequest || !documentKey || tabRequest.documentId !== documentKey) return\n phoneDefaultDecidedFor.current = documentKey\n session.setDocumentViewer({ tabRequest: null, tab: tabRequest.tab })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [documentKey, tabRequest])\n\n // Versions of a PDF or text document exist only with history: leave the tab when there is none\n // (another document opened while it was active).\n const hasVersionsTab = isArtifact || isDocx || hasHistory\n useEffect(() => {\n if (activeTab === 'versions' && documentData && !hasVersionsTab) {\n setActiveTab(isXlsx ? 'xlsx' : 'pdf')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeTab, documentData, hasVersionsTab])\n\n // The text tab exists only with parsed content. When it is open without any (a recording with\n // no transcript, a failed parse), fall back to the natural default once the parsed query\n // settles. Not during a comparison, which uses the text tab. Waits for the record: until it is\n // here the parsed query has not started, so it is not loading yet.\n useEffect(() => {\n if (\n activeTab === 'html' &&\n documentData !== undefined &&\n !isParsedDocLoading &&\n !hasParsedContent &&\n !compareId\n ) {\n setActiveTab(isArtifact ? 'edit' : isDocx ? 'docx' : isXlsx ? 'xlsx' : 'pdf')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n activeTab,\n documentData,\n isParsedDocLoading,\n hasParsedContent,\n compareId,\n isArtifact,\n isDocx,\n isXlsx,\n ])\n\n // Phones open a document on the readable reflowed (text) view: a fit-width PDF on a 390px\n // screen is footnote-sized. Decided once per document, after the parsed query settles, and only\n // over the PDF default (Word, sheets, artifacts and media keep their own tab). A PDF the user\n // picked by hand this session wins.\n useEffect(() => {\n if (!isPhone || !documentKey || isParsedDocLoading) return\n if (phoneDefaultDecidedFor.current === documentKey) return\n phoneDefaultDecidedFor.current = documentKey\n const opensOnPdf =\n !isArtifact && !isDocx && !isXlsx && !isVideo && !isAudio && !isImage && !isEmail\n if (opensOnPdf && hasParsedContent && !compareId && !phonePdfChosen && activeTab === 'pdf') {\n setActiveTab('html')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isPhone, documentKey, isParsedDocLoading, hasParsedContent])\n\n const handleTabChange = (tabId: string) => {\n // A comparison is shown on the text tab: leaving it ends the comparison.\n const change: Parameters<typeof session.setDocumentViewer>[0] = { tab: tabId as ArbiViewerTab }\n if (tabId !== 'html' && compareId) change.compareId = null\n // A phone user who goes back to the PDF wants it: stop opening documents on the text view\n // until they pick it again.\n if (isPhone && (tabId === 'pdf' || tabId === 'html')) change.phonePdfChosen = tabId === 'pdf'\n session.setDocumentViewer(change)\n }\n\n const mediaTab = isVideo\n ? { icon: <VidIcon size={20} />, tooltip: 'Video' }\n : isAudio\n ? { icon: <AudIcon size={20} />, tooltip: 'Audio' }\n : isImage\n ? { icon: <ImgIcon size={20} />, tooltip: 'Image' }\n : isEmail\n ? { icon: <EmlIcon size={20} />, tooltip: 'Email' }\n : isTextFile\n ? { icon: <FileText className=\"size-5\" />, tooltip: 'Text' }\n : documentData\n ? { icon: <PdfIcon size={20} />, tooltip: 'PDF' }\n : // The file type is unknown until the record loads: name no guess (a text file\n // would flip from PDF to Text once it arrives).\n { icon: <FileText className=\"size-5\" />, tooltip: 'Document' }\n // Tabs say what they are: in a narrow panel or on a phone only the open tab keeps its name, plus\n // the text view, whose icon is not recognisable. Labelling every tab there would crowd the header.\n const tabLabel = (id: string, label: string) =>\n !isCompact || activeTab === id || id === 'html' ? label : undefined\n\n const versionsTab: ViewerTab = {\n id: 'versions',\n icon: <History className=\"size-5\" />,\n tooltip: 'Versions',\n label: tabLabel('versions', 'Versions'),\n }\n const viewerTabs: ViewerTab[] = [\n // A presentation's slides, edited; then its PDF (the slides as saved), once it has one.\n ...(isPresentation\n ? [\n {\n id: 'slides',\n icon: <Presentation className=\"size-5\" />,\n tooltip: 'Slides',\n label: tabLabel('slides', 'Slides'),\n },\n ]\n : []),\n ...(isArtifact\n ? [\n ...(liveKind\n ? [\n {\n id: 'preview',\n icon: <MonitorPlay className=\"size-5\" />,\n tooltip: 'Preview',\n label: tabLabel('preview', 'Preview'),\n },\n ]\n : []),\n {\n id: 'edit',\n icon: liveKind ? <Code className=\"size-5\" /> : <FileText className=\"size-5\" />,\n tooltip: liveKind ? 'Code' : 'Editor',\n label: tabLabel('edit', liveKind ? 'Code' : 'Document'),\n },\n ...(!liveKind && !isDraft && !isStreaming && isDocx\n ? [\n {\n id: 'pdf',\n icon: <PdfIcon size={20} />,\n tooltip: 'PDF',\n label: tabLabel('pdf', 'PDF'),\n },\n ]\n : []),\n versionsTab,\n ]\n : [\n ...(isDocx\n ? [\n {\n id: 'docx',\n icon: <DocIcon size={20} />,\n tooltip: 'DOCX (with track changes & comments)',\n label: tabLabel('docx', 'DOCX'),\n },\n ]\n : []),\n ...(isXlsx\n ? [\n {\n id: 'xlsx',\n icon: <XlsIcon size={20} />,\n tooltip: 'Spreadsheet',\n label: tabLabel('xlsx', 'Sheet'),\n },\n ]\n : []),\n ...(isPresentation && isDraft\n ? []\n : [{ id: 'pdf', ...mediaTab, label: tabLabel('pdf', mediaTab.tooltip) }]),\n ...(hasVersionsTab ? [versionsTab] : []),\n ]),\n ...((hasParsedContent || compareId) && !liveKind\n ? [\n {\n id: 'html',\n icon: compareId ? <FileText className=\"size-5\" /> : <HtmlIcon size={20} />,\n tooltip: compareId ? 'Word redline' : 'HTML',\n label: tabLabel('html', compareId ? 'Compare' : 'HTML'),\n },\n ]\n : []),\n ]\n\n return { activeTab, handleTabChange, viewerTabs }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["/**\n * Tabs of the document viewer: which tabs a document has, the automatic switches when the\n * document's type or parsed content changes, and switching (which ends a comparison when leaving\n * the tab that hosts it). The open tab is the session state's, so whatever opens a document can\n * open it on a tab.\n */\n\nimport { useEffect, useRef } from 'react'\nimport { Code, FileText, History, MonitorPlay, Presentation } from 'lucide-react'\nimport { friendlyFileType } from '@arbidocs/react/ui'\nimport {\n AudIcon,\n DocIcon,\n EmlIcon,\n HtmlIcon,\n ImgIcon,\n PdfIcon,\n VidIcon,\n XlsIcon,\n useArbiSessionState,\n useArbiSessionStore,\n type ArbiViewerTab,\n} from '@arbidocs/react'\nimport type { ViewerTab } from '../../files/ViewerParts'\nimport { useIsPhone } from '../../lib/use-media-query'\nimport type { ViewedDocument } from './useViewedDocument'\n\n/**\n * @param hasHistory The document has earlier versions (a signed copy, a re-upload): PDF and text\n * documents then get a Versions tab too. Artifacts and Word documents always have one.\n */\nexport function useViewerTabs(doc: ViewedDocument, isCompact: boolean, hasHistory = false) {\n const {\n documentData,\n isArtifact,\n isPresentation,\n isDraft,\n isStreaming,\n isDocx,\n isXlsx,\n isEmail,\n isVideo,\n isAudio,\n isImage,\n liveKind,\n hasParsedContent,\n isParsedDocLoading,\n } = doc\n const session = useArbiSessionStore()\n const {\n tab: activeTab,\n compareId,\n tabRequest,\n phonePdfChosen,\n } = useArbiSessionState((s) => s.documentViewer)\n const setActiveTab = (tab: ArbiViewerTab) => session.setDocumentViewer({ tab })\n // A passage being opened (a citation, a search hit): it is lit on the PDF, else marked on the text\n // view, never in an editor.\n const passageId = useArbiSessionState((s) => s.viewingDocument?.passageId ?? null)\n // A plain-text file is still shown as a generated PDF, but the tab names the file the user\n // opened (\"Text\", as the Fields panel does), not the rendering format.\n const isTextFile = friendlyFileType(documentData?.file_type, documentData?.file_name) === 'Text'\n const isPhone = useIsPhone()\n const phoneDefaultDecidedFor = useRef<string | null>(null)\n\n // Switch to the tab that fits the document type. Only on type changes: never over the user's own\n // choice. Keyed on the document and its kind, not on the record: a refreshed record (a new\n // version finishing processing) must not send a user on the PDF tab of a Word document back to\n // the editor. Also on a passage opened: it asks for the PDF tab whatever the type.\n const hasDocumentData = !!documentData\n const documentKey = documentData?.external_id\n useEffect(() => {\n // A presentation opens on its slides; another document never shows that tab.\n if (isPresentation && hasDocumentData && activeTab === 'pdf') {\n setActiveTab('slides')\n } else if (!isPresentation && documentData && activeTab === 'slides') {\n setActiveTab(isDocx ? 'docx' : isXlsx ? 'xlsx' : 'pdf')\n }\n // A passage opened on a document whose type leaves the PDF tab goes to the text view, where\n // every passage is marked (the PDF pane's own fallback is not there to do it).\n else if (passageId && activeTab === 'pdf' && (isArtifact || isDocx)) {\n setActiveTab('html')\n }\n // A Word artifact (an AI draft, stored as .docx) has one Word tab, 'edit', not a DOCX tab.\n else if (isArtifact && (activeTab === 'pdf' || (!liveKind && activeTab === 'docx'))) {\n setActiveTab(liveKind ? 'preview' : 'edit')\n } else if (isDocx && activeTab === 'pdf') {\n setActiveTab('docx')\n } else if (!liveKind && activeTab === 'preview') {\n setActiveTab(isArtifact ? 'edit' : 'pdf')\n } else if (!isArtifact && documentData && activeTab === 'edit') {\n setActiveTab(isDocx ? 'docx' : isXlsx ? 'xlsx' : 'pdf')\n } else if (\n !isArtifact &&\n !isDocx &&\n !isXlsx &&\n documentData &&\n (activeTab === 'docx' || activeTab === 'xlsx')\n ) {\n setActiveTab('pdf')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n hasDocumentData,\n documentKey,\n isArtifact,\n isDocx,\n isXlsx,\n liveKind,\n isPresentation,\n passageId,\n ])\n\n // A tab asked for when the document was opened (a signature request opens on the PDF, where it\n // is signed) wins over the type's own tab once that document has loaded, and over the phone's\n // text default. Declared after the type switch above so it has the last word.\n useEffect(() => {\n if (!tabRequest || !documentKey || tabRequest.documentId !== documentKey) return\n phoneDefaultDecidedFor.current = documentKey\n session.setDocumentViewer({ tabRequest: null, tab: tabRequest.tab })\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [documentKey, tabRequest])\n\n // Versions of a PDF or text document exist only with history: leave the tab when there is none\n // (another document opened while it was active).\n const hasVersionsTab = isArtifact || isDocx || hasHistory\n useEffect(() => {\n if (activeTab === 'versions' && documentData && !hasVersionsTab) {\n setActiveTab(isXlsx ? 'xlsx' : 'pdf')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [activeTab, documentData, hasVersionsTab])\n\n // The text tab exists only with parsed content. When it is open without any (a recording with\n // no transcript, a failed parse), fall back to the natural default once the parsed query\n // settles. Not during a comparison, which uses the text tab. Waits for the record: until it is\n // here the parsed query has not started, so it is not loading yet.\n useEffect(() => {\n if (\n activeTab === 'html' &&\n documentData !== undefined &&\n !isParsedDocLoading &&\n !hasParsedContent &&\n !compareId\n ) {\n setActiveTab(isArtifact ? 'edit' : isDocx ? 'docx' : isXlsx ? 'xlsx' : 'pdf')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [\n activeTab,\n documentData,\n isParsedDocLoading,\n hasParsedContent,\n compareId,\n isArtifact,\n isDocx,\n isXlsx,\n ])\n\n // Phones open a document on the readable reflowed (text) view: a fit-width PDF on a 390px\n // screen is footnote-sized. Decided once per document, after the parsed query settles, and only\n // over the PDF default (Word, sheets, artifacts and media keep their own tab). A PDF the user\n // picked by hand this session wins.\n useEffect(() => {\n if (!isPhone || !documentKey || isParsedDocLoading) return\n if (phoneDefaultDecidedFor.current === documentKey) return\n phoneDefaultDecidedFor.current = documentKey\n const opensOnPdf =\n !isArtifact && !isDocx && !isXlsx && !isVideo && !isAudio && !isImage && !isEmail\n if (opensOnPdf && hasParsedContent && !compareId && !phonePdfChosen && activeTab === 'pdf') {\n setActiveTab('html')\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isPhone, documentKey, isParsedDocLoading, hasParsedContent])\n\n const handleTabChange = (tabId: string) => {\n // A comparison is shown on the text tab: leaving it ends the comparison.\n const change: Parameters<typeof session.setDocumentViewer>[0] = { tab: tabId as ArbiViewerTab }\n if (tabId !== 'html' && compareId) change.compareId = null\n // A phone user who goes back to the PDF wants it: stop opening documents on the text view\n // until they pick it again.\n if (isPhone && (tabId === 'pdf' || tabId === 'html')) change.phonePdfChosen = tabId === 'pdf'\n session.setDocumentViewer(change)\n }\n\n const mediaTab = isVideo\n ? { icon: <VidIcon size={20} />, tooltip: 'Video' }\n : isAudio\n ? { icon: <AudIcon size={20} />, tooltip: 'Audio' }\n : isImage\n ? { icon: <ImgIcon size={20} />, tooltip: 'Image' }\n : isEmail\n ? { icon: <EmlIcon size={20} />, tooltip: 'Email' }\n : isTextFile\n ? { icon: <FileText className=\"size-5\" />, tooltip: 'Text' }\n : documentData\n ? { icon: <PdfIcon size={20} />, tooltip: 'PDF' }\n : // The file type is unknown until the record loads: name no guess (a text file\n // would flip from PDF to Text once it arrives).\n { icon: <FileText className=\"size-5\" />, tooltip: 'Document' }\n // Tabs say what they are: in a narrow panel or on a phone only the open tab keeps its name, plus\n // the text view, whose icon is not recognisable. Labelling every tab there would crowd the header.\n const tabLabel = (id: string, label: string) =>\n !isCompact || activeTab === id || id === 'html' ? label : undefined\n\n const versionsTab: ViewerTab = {\n id: 'versions',\n icon: <History className=\"size-5\" />,\n tooltip: 'Versions',\n label: tabLabel('versions', 'Versions'),\n }\n const viewerTabs: ViewerTab[] = [\n // A presentation's slides, edited; then its PDF (the slides as saved), once it has one.\n ...(isPresentation\n ? [\n {\n id: 'slides',\n icon: <Presentation className=\"size-5\" />,\n tooltip: 'Slides',\n label: tabLabel('slides', 'Slides'),\n },\n ]\n : []),\n ...(isArtifact\n ? [\n ...(liveKind\n ? [\n {\n id: 'preview',\n icon: <MonitorPlay className=\"size-5\" />,\n tooltip: 'Preview',\n label: tabLabel('preview', 'Preview'),\n },\n ]\n : []),\n {\n id: 'edit',\n icon: liveKind ? <Code className=\"size-5\" /> : <FileText className=\"size-5\" />,\n tooltip: liveKind ? 'Code' : 'Editor',\n label: tabLabel('edit', liveKind ? 'Code' : 'Document'),\n },\n ...(!liveKind && !isDraft && !isStreaming && isDocx\n ? [\n {\n id: 'pdf',\n icon: <PdfIcon size={20} />,\n tooltip: 'PDF',\n label: tabLabel('pdf', 'PDF'),\n },\n ]\n : []),\n versionsTab,\n ]\n : [\n ...(isDocx\n ? [\n {\n id: 'docx',\n icon: <DocIcon size={20} />,\n tooltip: 'DOCX (with track changes & comments)',\n label: tabLabel('docx', 'DOCX'),\n },\n ]\n : []),\n ...(isXlsx\n ? [\n {\n id: 'xlsx',\n icon: <XlsIcon size={20} />,\n tooltip: 'Spreadsheet',\n label: tabLabel('xlsx', 'Sheet'),\n },\n ]\n : []),\n ...(isPresentation && isDraft\n ? []\n : [{ id: 'pdf', ...mediaTab, label: tabLabel('pdf', mediaTab.tooltip) }]),\n ...(hasVersionsTab ? [versionsTab] : []),\n ]),\n ...((hasParsedContent || compareId) && !liveKind\n ? [\n {\n id: 'html',\n icon: compareId ? <FileText className=\"size-5\" /> : <HtmlIcon size={20} />,\n tooltip: compareId ? 'Word redline' : 'HTML',\n label: tabLabel('html', compareId ? 'Compare' : 'HTML'),\n },\n ]\n : []),\n ]\n\n return { activeTab, handleTabChange, viewerTabs }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -128,7 +128,8 @@ function DocxCommandMenu({
128
128
  "table-column-left",
129
129
  "table-column-right"
130
130
  ]);
131
- if ((!button || !button.disabled) && target.closest('[aria-disabled="true"]') === null && (button && item && direct.has(item) || target.closest('[role="gridcell"]') || target.closest('[role="menuitemradio"]') || target.closest('[data-testid="docx-insert-my-signature"]') || target.closest('[data-testid="docx-insert-my-initials"]') || target.closest('.native-docx-style-gallery [role="option"]') || button && button.closest(".native-docx-style-gallery"))) {
131
+ if ((!button || !button.disabled) && target.closest('[aria-disabled="true"]') === null && (button && item && direct.has(item) || target.closest('[role="gridcell"]') || target.closest('[role="menuitemradio"]') || target.closest('[data-testid="docx-insert-my-signature"]') || target.closest('[data-testid="docx-insert-my-initials"]') || // Picking a Quick Part inserts it at the caret: back to the document.
132
+ target.closest('[data-testid="docx-quick-parts-panel"] li button') || target.closest('.native-docx-style-gallery [role="option"]') || button && button.closest(".native-docx-style-gallery"))) {
132
133
  close();
133
134
  }
134
135
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/docx/DocxCommandMenu.tsx"],
4
- "sourcesContent": ["import React, { useState } from 'react'\nimport { DocxEditor, useChromeTranslate } from '@docx-editor.dev/react'\nimport {\n BookA,\n ChevronDown,\n FilePenLine,\n Home,\n Image,\n LayoutGrid,\n ListChecks,\n Menu,\n Plus,\n Table,\n UsersRound,\n} from 'lucide-react'\nimport { useDefinedTerms } from './definitions/DefinedTerms'\nimport { RibbonMenu } from './RibbonMenu'\nimport { NamedCommandList, RibbonItem } from './RibbonOverflow'\nimport { StyleGallery } from './StyleGallery'\nimport { NoteButtons } from './WordReferences'\nimport { CrossReferenceButton, UpdateCrossReferencesButton } from './references/EditorMenus'\nimport { LayoutTabContent, LAYOUT_TAB, useContextualTabs } from './layout/LayoutTabs'\nimport {\n GenerateImageButton,\n useGenerateImageTarget,\n type DocxImageGeneration,\n} from './layout/GenerateImage'\nimport { QuickParts } from './template/QuickParts'\nimport { HouseTemplatePanel } from './template/HouseTemplatePanel'\nimport { MySignatureMenu, SignatureFieldMenu } from './signatures/SignatureFields'\n\nfunction DefinedTermButton() {\n const terms = useDefinedTerms()\n if (!terms) return null\n return (\n <button\n type=\"button\"\n className=\"native-docx-ribbon-trigger\"\n aria-label={terms.labels.insert}\n title={`${terms.labels.insert} (type @@)`}\n data-testid=\"docx-insert-defined-term\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={(event) => terms.openPicker(event.currentTarget)}\n >\n <BookA size={16} />\n </button>\n )\n}\n\nconst categories = [\n { name: 'Home', icon: Home },\n { name: 'Insert', icon: Plus },\n { name: 'Design', icon: FilePenLine },\n { name: LAYOUT_TAB, icon: LayoutGrid },\n { name: 'References', icon: BookA },\n { name: 'Review', icon: ListChecks },\n] as const\n\n/** One editing menu, with named categories and the existing editor commands. */\nexport function DocxCommandMenu({\n onSave,\n badge,\n imageGeneration,\n}: {\n onSave: () => void\n badge?: React.ReactNode\n imageGeneration?: DocxImageGeneration\n}) {\n const [selected, setSelected] = useState('Home')\n const contextual = useContextualTabs(selected)\n const tab = contextual.shown\n const t = useChromeTranslate()\n useGenerateImageTarget()\n const allCategories = [\n ...categories,\n ...contextual.tabs.map((name) => ({ name, icon: name === 'Table' ? Table : Image })),\n ]\n return (\n <div className=\"native-docx-ribbon native-docx-command-menu\">\n <DocxEditor.Toolbar t={t} preset={false} onSave={onSave}>\n <RibbonMenu\n label=\"Editing tools\"\n icon={\n <>\n <Menu size={16} />\n <span>Editing tools</span>\n <ChevronDown size={14} />\n </>\n }\n className=\"native-docx-command-trigger\"\n popoverClassName=\"native-docx-command-panel\"\n keepMounted\n restoreFocus\n >\n {(close) => (\n <div className=\"native-docx-command-layout\">\n <nav className=\"native-docx-command-categories\" aria-label=\"Editing tool categories\">\n {allCategories.map(({ name, icon: Icon }) => (\n <button\n type=\"button\"\n key={name}\n aria-pressed={tab === name}\n onClick={() => setSelected(name)}\n >\n <Icon size={16} aria-hidden=\"true\" />\n <span>{name}</span>\n </button>\n ))}\n </nav>\n <div\n className=\"native-docx-command-list\"\n role=\"group\"\n aria-label={`${tab} commands`}\n onClick={(event) => {\n const target = event.target as HTMLElement\n const button = target.closest<HTMLButtonElement>('button')\n const item = target.closest<HTMLElement>('[data-ribbon-item]')?.dataset.ribbonItem\n const direct = new Set([\n 'home-undo',\n 'home-redo',\n 'home-save',\n 'home-bold',\n 'home-italic',\n 'home-underline',\n 'home-bullets',\n 'home-numbers',\n 'home-indent',\n 'home-outdent',\n 'home-strike',\n 'home-clear',\n 'references-footnote',\n 'references-endnote',\n 'references-update-cross-references',\n 'table-row-above',\n 'table-row-below',\n 'table-column-left',\n 'table-column-right',\n ])\n if (\n (!button || !button.disabled) &&\n target.closest('[aria-disabled=\"true\"]') === null &&\n ((button && item && direct.has(item)) ||\n target.closest('[role=\"gridcell\"]') ||\n target.closest('[role=\"menuitemradio\"]') ||\n target.closest('[data-testid=\"docx-insert-my-signature\"]') ||\n target.closest('[data-testid=\"docx-insert-my-initials\"]') ||\n target.closest('.native-docx-style-gallery [role=\"option\"]') ||\n (button && button.closest('.native-docx-style-gallery')))\n ) {\n close()\n }\n }}\n >\n <NamedCommandList>\n {tab === 'Home' && (\n <>\n <RibbonItem id=\"home-undo\" label=\"Undo\">\n <DocxEditor.Toolbar.Undo />\n </RibbonItem>\n <RibbonItem id=\"home-redo\" label=\"Redo\">\n <DocxEditor.Toolbar.Redo />\n </RibbonItem>\n <RibbonItem id=\"home-save\" label=\"Save\">\n <DocxEditor.Toolbar.Save />\n </RibbonItem>\n <RibbonItem id=\"home-style\" label=\"Styles\">\n <StyleGallery />\n </RibbonItem>\n <RibbonItem id=\"home-bold\" label=\"Bold\">\n <DocxEditor.Toolbar.Bold />\n </RibbonItem>\n <RibbonItem id=\"home-italic\" label=\"Italic\">\n <DocxEditor.Toolbar.Italic />\n </RibbonItem>\n <RibbonItem id=\"home-underline\" label=\"Underline\">\n <DocxEditor.Toolbar.Underline />\n </RibbonItem>\n <RibbonItem id=\"home-font-family\" label=\"Font family\">\n <DocxEditor.Toolbar.FontFamily />\n </RibbonItem>\n <RibbonItem id=\"home-font-size\" label=\"Font size\">\n <DocxEditor.Toolbar.FontSize />\n </RibbonItem>\n <RibbonItem id=\"home-font-color\" label=\"Font color\">\n <DocxEditor.Toolbar.FontColor />\n </RibbonItem>\n <RibbonItem id=\"home-highlight\" label=\"Highlight\">\n <DocxEditor.Toolbar.Highlight />\n </RibbonItem>\n <RibbonItem id=\"home-alignment\" label=\"Alignment\">\n <DocxEditor.Toolbar.Alignment />\n </RibbonItem>\n <RibbonItem id=\"home-bullets\" label=\"Bulleted list\">\n <DocxEditor.Toolbar.BulletList />\n </RibbonItem>\n <RibbonItem id=\"home-numbers\" label=\"Numbered list\">\n <DocxEditor.Toolbar.NumberedList />\n </RibbonItem>\n <RibbonItem id=\"home-line-spacing\" label=\"Line spacing\">\n <DocxEditor.Toolbar.LineSpacing />\n </RibbonItem>\n <RibbonItem id=\"home-indent\" label=\"Increase indent\">\n <DocxEditor.Toolbar.Indent />\n </RibbonItem>\n <RibbonItem id=\"home-outdent\" label=\"Decrease indent\">\n <DocxEditor.Toolbar.Outdent />\n </RibbonItem>\n <RibbonItem id=\"home-strike\" label=\"Strikethrough\">\n <DocxEditor.Toolbar.Strike />\n </RibbonItem>\n <RibbonItem id=\"home-clear\" label=\"Clear formatting\">\n <DocxEditor.Toolbar.ClearFormatting />\n </RibbonItem>\n </>\n )}\n {tab === 'Insert' && (\n <>\n <RibbonItem id=\"insert-table\" label=\"Table\">\n <DocxEditor.Toolbar.TableInsert />\n </RibbonItem>\n <RibbonItem id=\"insert-picture\" label=\"Picture\">\n <DocxEditor.Toolbar.ImageInsert />\n </RibbonItem>\n {imageGeneration && (\n <RibbonItem id=\"insert-generate-image\" label=\"Generate image\">\n <GenerateImageButton generation={imageGeneration} />\n </RibbonItem>\n )}\n <RibbonItem id=\"insert-page-break\" label=\"Page break\">\n <DocxEditor.Toolbar.Button slotId=\"insert.pageBreak\" />\n </RibbonItem>\n <RibbonItem id=\"insert-link\" label=\"Link\">\n <DocxEditor.Toolbar.Link />\n </RibbonItem>\n <RibbonItem id=\"insert-defined-term\" label=\"Defined term\">\n <DefinedTermButton />\n </RibbonItem>\n <RibbonItem id=\"insert-quick-parts\" label=\"Quick Parts\">\n <QuickParts />\n </RibbonItem>\n <RibbonItem id=\"insert-signature-field\" label=\"Signature field\">\n <SignatureFieldMenu onInserted={close} />\n </RibbonItem>\n <RibbonItem id=\"insert-my-signature\" label=\"My signature\">\n <MySignatureMenu />\n </RibbonItem>\n <RibbonItem id=\"insert-cross-reference\" label=\"Cross-reference\">\n <CrossReferenceButton />\n </RibbonItem>\n </>\n )}\n <LayoutTabContent tab={tab} />\n {tab === 'Design' && (\n <RibbonItem id=\"design-house-template\" label=\"House template\">\n <HouseTemplatePanel />\n </RibbonItem>\n )}\n {tab === 'References' && (\n <>\n <NoteButtons />\n <RibbonItem id=\"references-cross-reference\" label=\"Cross-reference\">\n <CrossReferenceButton />\n </RibbonItem>\n <RibbonItem\n id=\"references-update-cross-references\"\n label=\"Update cross-references\"\n >\n <UpdateCrossReferencesButton />\n </RibbonItem>\n </>\n )}\n {tab === 'Review' && (\n <>\n <RibbonItem id=\"review-editing-mode\" label=\"Editing mode\">\n <DocxEditor.Toolbar.EditingMode />\n </RibbonItem>\n <RibbonItem id=\"review-comments\" label=\"Comments\">\n <DocxEditor.Toolbar.Comments />\n </RibbonItem>\n <RibbonItem id=\"review-options\" label=\"Review options\">\n <RibbonMenu label=\"Review options\" icon={<UsersRound size={16} />}>\n <DocxEditor.Toolbar.Reviewers />\n </RibbonMenu>\n </RibbonItem>\n </>\n )}\n </NamedCommandList>\n </div>\n </div>\n )}\n </RibbonMenu>\n <DocxEditor.Toolbar.TableCellFill hidden />\n </DocxEditor.Toolbar>\n {badge && (\n <span className=\"native-docx-ribbon-badge\" data-testid=\"docx-ribbon-badge\">\n {badge}\n </span>\n )}\n </div>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import React, { useState } from 'react'\nimport { DocxEditor, useChromeTranslate } from '@docx-editor.dev/react'\nimport {\n BookA,\n ChevronDown,\n FilePenLine,\n Home,\n Image,\n LayoutGrid,\n ListChecks,\n Menu,\n Plus,\n Table,\n UsersRound,\n} from 'lucide-react'\nimport { useDefinedTerms } from './definitions/DefinedTerms'\nimport { RibbonMenu } from './RibbonMenu'\nimport { NamedCommandList, RibbonItem } from './RibbonOverflow'\nimport { StyleGallery } from './StyleGallery'\nimport { NoteButtons } from './WordReferences'\nimport { CrossReferenceButton, UpdateCrossReferencesButton } from './references/EditorMenus'\nimport { LayoutTabContent, LAYOUT_TAB, useContextualTabs } from './layout/LayoutTabs'\nimport {\n GenerateImageButton,\n useGenerateImageTarget,\n type DocxImageGeneration,\n} from './layout/GenerateImage'\nimport { QuickParts } from './template/QuickParts'\nimport { HouseTemplatePanel } from './template/HouseTemplatePanel'\nimport { MySignatureMenu, SignatureFieldMenu } from './signatures/SignatureFields'\n\nfunction DefinedTermButton() {\n const terms = useDefinedTerms()\n if (!terms) return null\n return (\n <button\n type=\"button\"\n className=\"native-docx-ribbon-trigger\"\n aria-label={terms.labels.insert}\n title={`${terms.labels.insert} (type @@)`}\n data-testid=\"docx-insert-defined-term\"\n onMouseDown={(event) => event.preventDefault()}\n onClick={(event) => terms.openPicker(event.currentTarget)}\n >\n <BookA size={16} />\n </button>\n )\n}\n\nconst categories = [\n { name: 'Home', icon: Home },\n { name: 'Insert', icon: Plus },\n { name: 'Design', icon: FilePenLine },\n { name: LAYOUT_TAB, icon: LayoutGrid },\n { name: 'References', icon: BookA },\n { name: 'Review', icon: ListChecks },\n] as const\n\n/** One editing menu, with named categories and the existing editor commands. */\nexport function DocxCommandMenu({\n onSave,\n badge,\n imageGeneration,\n}: {\n onSave: () => void\n badge?: React.ReactNode\n imageGeneration?: DocxImageGeneration\n}) {\n const [selected, setSelected] = useState('Home')\n const contextual = useContextualTabs(selected)\n const tab = contextual.shown\n const t = useChromeTranslate()\n useGenerateImageTarget()\n const allCategories = [\n ...categories,\n ...contextual.tabs.map((name) => ({ name, icon: name === 'Table' ? Table : Image })),\n ]\n return (\n <div className=\"native-docx-ribbon native-docx-command-menu\">\n <DocxEditor.Toolbar t={t} preset={false} onSave={onSave}>\n <RibbonMenu\n label=\"Editing tools\"\n icon={\n <>\n <Menu size={16} />\n <span>Editing tools</span>\n <ChevronDown size={14} />\n </>\n }\n className=\"native-docx-command-trigger\"\n popoverClassName=\"native-docx-command-panel\"\n keepMounted\n restoreFocus\n >\n {(close) => (\n <div className=\"native-docx-command-layout\">\n <nav className=\"native-docx-command-categories\" aria-label=\"Editing tool categories\">\n {allCategories.map(({ name, icon: Icon }) => (\n <button\n type=\"button\"\n key={name}\n aria-pressed={tab === name}\n onClick={() => setSelected(name)}\n >\n <Icon size={16} aria-hidden=\"true\" />\n <span>{name}</span>\n </button>\n ))}\n </nav>\n <div\n className=\"native-docx-command-list\"\n role=\"group\"\n aria-label={`${tab} commands`}\n onClick={(event) => {\n const target = event.target as HTMLElement\n const button = target.closest<HTMLButtonElement>('button')\n const item = target.closest<HTMLElement>('[data-ribbon-item]')?.dataset.ribbonItem\n const direct = new Set([\n 'home-undo',\n 'home-redo',\n 'home-save',\n 'home-bold',\n 'home-italic',\n 'home-underline',\n 'home-bullets',\n 'home-numbers',\n 'home-indent',\n 'home-outdent',\n 'home-strike',\n 'home-clear',\n 'references-footnote',\n 'references-endnote',\n 'references-update-cross-references',\n 'table-row-above',\n 'table-row-below',\n 'table-column-left',\n 'table-column-right',\n ])\n if (\n (!button || !button.disabled) &&\n target.closest('[aria-disabled=\"true\"]') === null &&\n ((button && item && direct.has(item)) ||\n target.closest('[role=\"gridcell\"]') ||\n target.closest('[role=\"menuitemradio\"]') ||\n target.closest('[data-testid=\"docx-insert-my-signature\"]') ||\n target.closest('[data-testid=\"docx-insert-my-initials\"]') ||\n // Picking a Quick Part inserts it at the caret: back to the document.\n target.closest('[data-testid=\"docx-quick-parts-panel\"] li button') ||\n target.closest('.native-docx-style-gallery [role=\"option\"]') ||\n (button && button.closest('.native-docx-style-gallery')))\n ) {\n close()\n }\n }}\n >\n <NamedCommandList>\n {tab === 'Home' && (\n <>\n <RibbonItem id=\"home-undo\" label=\"Undo\">\n <DocxEditor.Toolbar.Undo />\n </RibbonItem>\n <RibbonItem id=\"home-redo\" label=\"Redo\">\n <DocxEditor.Toolbar.Redo />\n </RibbonItem>\n <RibbonItem id=\"home-save\" label=\"Save\">\n <DocxEditor.Toolbar.Save />\n </RibbonItem>\n <RibbonItem id=\"home-style\" label=\"Styles\">\n <StyleGallery />\n </RibbonItem>\n <RibbonItem id=\"home-bold\" label=\"Bold\">\n <DocxEditor.Toolbar.Bold />\n </RibbonItem>\n <RibbonItem id=\"home-italic\" label=\"Italic\">\n <DocxEditor.Toolbar.Italic />\n </RibbonItem>\n <RibbonItem id=\"home-underline\" label=\"Underline\">\n <DocxEditor.Toolbar.Underline />\n </RibbonItem>\n <RibbonItem id=\"home-font-family\" label=\"Font family\">\n <DocxEditor.Toolbar.FontFamily />\n </RibbonItem>\n <RibbonItem id=\"home-font-size\" label=\"Font size\">\n <DocxEditor.Toolbar.FontSize />\n </RibbonItem>\n <RibbonItem id=\"home-font-color\" label=\"Font color\">\n <DocxEditor.Toolbar.FontColor />\n </RibbonItem>\n <RibbonItem id=\"home-highlight\" label=\"Highlight\">\n <DocxEditor.Toolbar.Highlight />\n </RibbonItem>\n <RibbonItem id=\"home-alignment\" label=\"Alignment\">\n <DocxEditor.Toolbar.Alignment />\n </RibbonItem>\n <RibbonItem id=\"home-bullets\" label=\"Bulleted list\">\n <DocxEditor.Toolbar.BulletList />\n </RibbonItem>\n <RibbonItem id=\"home-numbers\" label=\"Numbered list\">\n <DocxEditor.Toolbar.NumberedList />\n </RibbonItem>\n <RibbonItem id=\"home-line-spacing\" label=\"Line spacing\">\n <DocxEditor.Toolbar.LineSpacing />\n </RibbonItem>\n <RibbonItem id=\"home-indent\" label=\"Increase indent\">\n <DocxEditor.Toolbar.Indent />\n </RibbonItem>\n <RibbonItem id=\"home-outdent\" label=\"Decrease indent\">\n <DocxEditor.Toolbar.Outdent />\n </RibbonItem>\n <RibbonItem id=\"home-strike\" label=\"Strikethrough\">\n <DocxEditor.Toolbar.Strike />\n </RibbonItem>\n <RibbonItem id=\"home-clear\" label=\"Clear formatting\">\n <DocxEditor.Toolbar.ClearFormatting />\n </RibbonItem>\n </>\n )}\n {tab === 'Insert' && (\n <>\n <RibbonItem id=\"insert-table\" label=\"Table\">\n <DocxEditor.Toolbar.TableInsert />\n </RibbonItem>\n <RibbonItem id=\"insert-picture\" label=\"Picture\">\n <DocxEditor.Toolbar.ImageInsert />\n </RibbonItem>\n {imageGeneration && (\n <RibbonItem id=\"insert-generate-image\" label=\"Generate image\">\n <GenerateImageButton generation={imageGeneration} />\n </RibbonItem>\n )}\n <RibbonItem id=\"insert-page-break\" label=\"Page break\">\n <DocxEditor.Toolbar.Button slotId=\"insert.pageBreak\" />\n </RibbonItem>\n <RibbonItem id=\"insert-link\" label=\"Link\">\n <DocxEditor.Toolbar.Link />\n </RibbonItem>\n <RibbonItem id=\"insert-defined-term\" label=\"Defined term\">\n <DefinedTermButton />\n </RibbonItem>\n <RibbonItem id=\"insert-quick-parts\" label=\"Quick Parts\">\n <QuickParts />\n </RibbonItem>\n <RibbonItem id=\"insert-signature-field\" label=\"Signature field\">\n <SignatureFieldMenu onInserted={close} />\n </RibbonItem>\n <RibbonItem id=\"insert-my-signature\" label=\"My signature\">\n <MySignatureMenu />\n </RibbonItem>\n <RibbonItem id=\"insert-cross-reference\" label=\"Cross-reference\">\n <CrossReferenceButton />\n </RibbonItem>\n </>\n )}\n <LayoutTabContent tab={tab} />\n {tab === 'Design' && (\n <RibbonItem id=\"design-house-template\" label=\"House template\">\n <HouseTemplatePanel />\n </RibbonItem>\n )}\n {tab === 'References' && (\n <>\n <NoteButtons />\n <RibbonItem id=\"references-cross-reference\" label=\"Cross-reference\">\n <CrossReferenceButton />\n </RibbonItem>\n <RibbonItem\n id=\"references-update-cross-references\"\n label=\"Update cross-references\"\n >\n <UpdateCrossReferencesButton />\n </RibbonItem>\n </>\n )}\n {tab === 'Review' && (\n <>\n <RibbonItem id=\"review-editing-mode\" label=\"Editing mode\">\n <DocxEditor.Toolbar.EditingMode />\n </RibbonItem>\n <RibbonItem id=\"review-comments\" label=\"Comments\">\n <DocxEditor.Toolbar.Comments />\n </RibbonItem>\n <RibbonItem id=\"review-options\" label=\"Review options\">\n <RibbonMenu label=\"Review options\" icon={<UsersRound size={16} />}>\n <DocxEditor.Toolbar.Reviewers />\n </RibbonMenu>\n </RibbonItem>\n </>\n )}\n </NamedCommandList>\n </div>\n </div>\n )}\n </RibbonMenu>\n <DocxEditor.Toolbar.TableCellFill hidden />\n </DocxEditor.Toolbar>\n {badge && (\n <span className=\"native-docx-ribbon-badge\" data-testid=\"docx-ribbon-badge\">\n {badge}\n </span>\n )}\n </div>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -25,7 +25,7 @@ export interface NativeDocxAdapter {
25
25
  filename: string;
26
26
  }>;
27
27
  /** Save the live room as the document's next version (same document id). */
28
- save: (documentId: string, state?: string) => Promise<{
28
+ save: (documentId: string, state?: string, autosave?: boolean) => Promise<{
29
29
  document_ext_id: string;
30
30
  version?: number;
31
31
  unchanged?: boolean;
@@ -34,6 +34,7 @@ export interface NativeDocxAdapter {
34
34
  baseUrl?: string;
35
35
  author?: string;
36
36
  subscribeTokenChanges?: (listener: () => void) => () => void;
37
+ registerTurnFlush?: (documentId: string, flush: () => Promise<void>) => () => void;
37
38
  onDirtyChange?: (dirty: boolean) => void;
38
39
  onVersionSaved?: (documentId: string, version?: number) => void | Promise<void>;
39
40
  notify?: (message: string, kind: 'success' | 'error') => void;
@@ -492,7 +492,13 @@ function NativeDocxEditor({
492
492
  });
493
493
  };
494
494
  }, [documentId, isDraft, ready]);
495
- async function saveVersion() {
495
+ const [editRevision, setEditRevision] = useState(0);
496
+ const [checkpoint, setCheckpoint] = useState(null);
497
+ useEffect(() => {
498
+ setEditRevision(0);
499
+ setCheckpoint(null);
500
+ }, [documentId]);
501
+ async function saveVersion(autosave = false) {
496
502
  if (!ready || savingRef.current || stream) return false;
497
503
  if (snapshot || !ready.canEdit) return true;
498
504
  if (offline) return false;
@@ -513,7 +519,7 @@ function NativeDocxEditor({
513
519
  },
514
520
  body: bytes
515
521
  })).json();
516
- })() : await adapter.save(documentId, ready.room ? encodeState(ready.room) : void 0);
522
+ })() : await adapter.save(documentId, ready.room ? encodeState(ready.room) : void 0, autosave);
517
523
  if (revision.current === atRevision) {
518
524
  dirtyRef.current = false;
519
525
  setDirty(false);
@@ -527,7 +533,8 @@ function NativeDocxEditor({
527
533
  adapter.notify?.("The document changed while saving. Please try again.", "error");
528
534
  return false;
529
535
  }
530
- adapter.notify?.(isDraft ? "Word note saved" : "DOCX version saved", "success");
536
+ setCheckpoint({ version: savedVersion, autosave: autosave && !isDraft, revision: atRevision });
537
+ if (!autosave) adapter.notify?.(isDraft ? "Word note saved" : "DOCX version saved", "success");
531
538
  return savedVersion ?? true;
532
539
  } catch (e) {
533
540
  adapter.notify?.(e instanceof Error ? e.message : "Could not save this document.", "error");
@@ -540,11 +547,28 @@ function NativeDocxEditor({
540
547
  }
541
548
  useEffect(() => {
542
549
  if (!saveRef) return;
543
- saveRef.current = saveVersion;
550
+ saveRef.current = () => saveVersion();
544
551
  return () => {
545
552
  saveRef.current = null;
546
553
  };
547
554
  });
555
+ const latestSaveVersion = useRef(saveVersion);
556
+ latestSaveVersion.current = saveVersion;
557
+ useEffect(() => {
558
+ if (!editRevision || compact || snapshot || offline || stream) return;
559
+ const timer = setTimeout(() => {
560
+ void latestSaveVersion.current(true);
561
+ }, 2500);
562
+ return () => clearTimeout(timer);
563
+ }, [editRevision, documentId, compact, snapshot, offline, stream]);
564
+ useEffect(() => {
565
+ if (compact || snapshot) return;
566
+ return adapter.registerTurnFlush?.(documentId, async () => {
567
+ if (!ready?.canEdit) return;
568
+ if (!await saveVersion())
569
+ throw new Error("The Word document could not be saved before this turn.");
570
+ });
571
+ });
548
572
  function editorReady(editor) {
549
573
  ref.current = editor;
550
574
  if (streamRef.current) {
@@ -609,6 +633,7 @@ function NativeDocxEditor({
609
633
  function changed() {
610
634
  if (snapshot) return;
611
635
  revision.current += 1;
636
+ setEditRevision(revision.current);
612
637
  dirtyRef.current = true;
613
638
  setDirty(true);
614
639
  setStatus(
@@ -788,7 +813,7 @@ function NativeDocxEditor({
788
813
  /* @__PURE__ */ jsxs("div", { className: "native-docx-actions", children: [
789
814
  /* @__PURE__ */ jsxs("span", { className: "native-docx-status", role: "status", children: [
790
815
  offline ? /* @__PURE__ */ jsx(WifiOff, { size: 14 }) : !dirty && ready ? /* @__PURE__ */ jsx(Check, { size: 14 }) : null,
791
- status
816
+ checkpoint?.autosave && checkpoint.revision === editRevision ? `v${checkpoint.version} \xB7 Autosaved` : status
792
817
  ] }),
793
818
  /* @__PURE__ */ jsx(DocxParticipants, { session: ready?.room?.session }),
794
819
  !compact && /* @__PURE__ */ jsxs(