@vertesia/ui 0.80.0-dev.20251121 → 0.80.0

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 (277) hide show
  1. package/README.md +105 -0
  2. package/lib/esm/core/components/MenuList.js +2 -5
  3. package/lib/esm/core/components/MenuList.js.map +1 -1
  4. package/lib/esm/core/components/MessageBox.js +1 -1
  5. package/lib/esm/core/components/MessageBox.js.map +1 -1
  6. package/lib/esm/core/components/shadcn/dialog.js +16 -2
  7. package/lib/esm/core/components/shadcn/dialog.js.map +1 -1
  8. package/lib/esm/core/components/shadcn/filters/filter/SelectFilter.js +6 -9
  9. package/lib/esm/core/components/shadcn/filters/filter/SelectFilter.js.map +1 -1
  10. package/lib/esm/core/components/shadcn/filters/filterBar.js +1 -1
  11. package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
  12. package/lib/esm/core/components/shadcn/selectBox.js +23 -5
  13. package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
  14. package/lib/esm/core/components/shadcn/tabs.js +3 -3
  15. package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
  16. package/lib/esm/env/index.js +3 -0
  17. package/lib/esm/env/index.js.map +1 -1
  18. package/lib/esm/features/agent/chat/AgentChart.js +184 -0
  19. package/lib/esm/features/agent/chat/AgentChart.js.map +1 -0
  20. package/lib/esm/features/agent/chat/ModernAgentConversation.js +87 -10
  21. package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
  22. package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +6 -2
  23. package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
  24. package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +4 -4
  25. package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
  26. package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +4 -1
  27. package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
  28. package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js +12 -4
  29. package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
  30. package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +60 -56
  31. package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
  32. package/lib/esm/features/agent/chat/index.js +1 -0
  33. package/lib/esm/features/agent/chat/index.js.map +1 -1
  34. package/lib/esm/features/agent/createChartTool.js +354 -0
  35. package/lib/esm/features/agent/createChartTool.js.map +1 -0
  36. package/lib/esm/features/agent/examples.js +295 -0
  37. package/lib/esm/features/agent/examples.js.map +1 -0
  38. package/lib/esm/features/agent/index.js +2 -0
  39. package/lib/esm/features/agent/index.js.map +1 -1
  40. package/lib/esm/features/agent/visualization.js +165 -0
  41. package/lib/esm/features/agent/visualization.js.map +1 -0
  42. package/lib/esm/features/facets/CollectionsFacetsNav.js +5 -1
  43. package/lib/esm/features/facets/CollectionsFacetsNav.js.map +1 -1
  44. package/lib/esm/features/index.js +1 -0
  45. package/lib/esm/features/index.js.map +1 -1
  46. package/lib/esm/features/layout/GenericPageNavHeader.js +14 -4
  47. package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -1
  48. package/lib/esm/features/magic-pdf/AnnotatedImageSlider.js +268 -0
  49. package/lib/esm/features/magic-pdf/AnnotatedImageSlider.js.map +1 -0
  50. package/lib/esm/features/magic-pdf/DownloadPopover.js +11 -11
  51. package/lib/esm/features/magic-pdf/DownloadPopover.js.map +1 -1
  52. package/lib/esm/features/magic-pdf/ExtractedContentView.js +77 -0
  53. package/lib/esm/features/magic-pdf/ExtractedContentView.js.map +1 -0
  54. package/lib/esm/features/magic-pdf/MagicPdfProvider.js +242 -0
  55. package/lib/esm/features/magic-pdf/MagicPdfProvider.js.map +1 -0
  56. package/lib/esm/features/magic-pdf/MagicPdfView.js +41 -47
  57. package/lib/esm/features/magic-pdf/MagicPdfView.js.map +1 -1
  58. package/lib/esm/features/pdf-viewer/PdfPageRenderer.js +261 -0
  59. package/lib/esm/features/pdf-viewer/PdfPageRenderer.js.map +1 -0
  60. package/lib/esm/features/pdf-viewer/PdfPageSlider.js +276 -0
  61. package/lib/esm/features/pdf-viewer/PdfPageSlider.js.map +1 -0
  62. package/lib/esm/features/pdf-viewer/SimplePdfViewer.js +71 -0
  63. package/lib/esm/features/pdf-viewer/SimplePdfViewer.js.map +1 -0
  64. package/lib/esm/features/pdf-viewer/index.js +4 -0
  65. package/lib/esm/features/pdf-viewer/index.js.map +1 -0
  66. package/lib/esm/features/store/collections/EditCollectionView.js +3 -5
  67. package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
  68. package/lib/esm/features/store/collections/SharedPropsEditor.js +1 -2
  69. package/lib/esm/features/store/collections/SharedPropsEditor.js.map +1 -1
  70. package/lib/esm/features/store/objects/DocumentSearchResults.js +0 -7
  71. package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
  72. package/lib/esm/features/store/objects/components/ContentOverview.js +273 -83
  73. package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
  74. package/lib/esm/features/store/objects/components/useContentPanelHooks.js +153 -0
  75. package/lib/esm/features/store/objects/components/useContentPanelHooks.js.map +1 -0
  76. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +3 -3
  77. package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
  78. package/lib/esm/features/store/objects/layout/renderers.js +13 -0
  79. package/lib/esm/features/store/objects/layout/renderers.js.map +1 -1
  80. package/lib/esm/features/utils/index.js +2 -0
  81. package/lib/esm/features/utils/index.js.map +1 -1
  82. package/lib/esm/features/utils/mimeType.js +8 -0
  83. package/lib/esm/features/utils/mimeType.js.map +1 -1
  84. package/lib/esm/features/utils/print.js +181 -0
  85. package/lib/esm/features/utils/print.js.map +1 -0
  86. package/lib/esm/features/utils/workflowStatus.js +43 -0
  87. package/lib/esm/features/utils/workflowStatus.js.map +1 -0
  88. package/lib/esm/router/HistoryNavigator.js +22 -2
  89. package/lib/esm/router/HistoryNavigator.js.map +1 -1
  90. package/lib/esm/shell/login/UserInfo.js +2 -1
  91. package/lib/esm/shell/login/UserInfo.js.map +1 -1
  92. package/lib/esm/shell/login/UserSessionMenu.js +7 -1
  93. package/lib/esm/shell/login/UserSessionMenu.js.map +1 -1
  94. package/lib/esm/widgets/form/Form.js +6 -2
  95. package/lib/esm/widgets/form/Form.js.map +1 -1
  96. package/lib/esm/widgets/markdown/MarkdownRenderer.js +226 -4
  97. package/lib/esm/widgets/markdown/MarkdownRenderer.js.map +1 -1
  98. package/lib/esm/widgets/schema-editor/ManagedSchema.js +0 -3
  99. package/lib/esm/widgets/schema-editor/ManagedSchema.js.map +1 -1
  100. package/lib/esm/widgets/schema-editor/json-schema4-utils.js +1 -1
  101. package/lib/esm/widgets/schema-editor/json-schema4-utils.js.map +1 -1
  102. package/lib/esm/widgets/xml-viewer/components/XMLViewer.js +18 -9
  103. package/lib/esm/widgets/xml-viewer/components/XMLViewer.js.map +1 -1
  104. package/lib/esm/widgets/xml-viewer/constants/index.js +10 -0
  105. package/lib/esm/widgets/xml-viewer/constants/index.js.map +1 -1
  106. package/lib/tsconfig.tsbuildinfo +1 -1
  107. package/lib/types/core/components/MessageBox.d.ts.map +1 -1
  108. package/lib/types/core/components/shadcn/dialog.d.ts +2 -1
  109. package/lib/types/core/components/shadcn/dialog.d.ts.map +1 -1
  110. package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
  111. package/lib/types/core/components/shadcn/selectBox.d.ts +5 -1
  112. package/lib/types/core/components/shadcn/selectBox.d.ts.map +1 -1
  113. package/lib/types/core/components/shadcn/tabs.d.ts +3 -1
  114. package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
  115. package/lib/types/env/index.d.ts +2 -0
  116. package/lib/types/env/index.d.ts.map +1 -1
  117. package/lib/types/features/agent/chat/AgentChart.d.ts +48 -0
  118. package/lib/types/features/agent/chat/AgentChart.d.ts.map +1 -0
  119. package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
  120. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +3 -2
  121. package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
  122. package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts +2 -1
  123. package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
  124. package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts +4 -2
  125. package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
  126. package/lib/types/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +2 -4
  127. package/lib/types/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
  128. package/lib/types/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
  129. package/lib/types/features/agent/chat/index.d.ts +1 -0
  130. package/lib/types/features/agent/chat/index.d.ts.map +1 -1
  131. package/lib/types/features/agent/createChartTool.d.ts +178 -0
  132. package/lib/types/features/agent/createChartTool.d.ts.map +1 -0
  133. package/lib/types/features/agent/examples.d.ts +59 -0
  134. package/lib/types/features/agent/examples.d.ts.map +1 -0
  135. package/lib/types/features/agent/index.d.ts +2 -0
  136. package/lib/types/features/agent/index.d.ts.map +1 -1
  137. package/lib/types/features/agent/visualization.d.ts +95 -0
  138. package/lib/types/features/agent/visualization.d.ts.map +1 -0
  139. package/lib/types/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
  140. package/lib/types/features/index.d.ts +1 -0
  141. package/lib/types/features/index.d.ts.map +1 -1
  142. package/lib/types/features/layout/GenericPageNavHeader.d.ts.map +1 -1
  143. package/lib/types/features/magic-pdf/AnnotatedImageSlider.d.ts +13 -0
  144. package/lib/types/features/magic-pdf/AnnotatedImageSlider.d.ts.map +1 -0
  145. package/lib/types/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
  146. package/lib/types/features/magic-pdf/ExtractedContentView.d.ts +8 -0
  147. package/lib/types/features/magic-pdf/ExtractedContentView.d.ts.map +1 -0
  148. package/lib/types/features/magic-pdf/MagicPdfProvider.d.ts +58 -0
  149. package/lib/types/features/magic-pdf/MagicPdfProvider.d.ts.map +1 -0
  150. package/lib/types/features/magic-pdf/MagicPdfView.d.ts +1 -1
  151. package/lib/types/features/magic-pdf/MagicPdfView.d.ts.map +1 -1
  152. package/lib/types/features/pdf-viewer/PdfPageRenderer.d.ts +83 -0
  153. package/lib/types/features/pdf-viewer/PdfPageRenderer.d.ts.map +1 -0
  154. package/lib/types/features/pdf-viewer/PdfPageSlider.d.ts +29 -0
  155. package/lib/types/features/pdf-viewer/PdfPageSlider.d.ts.map +1 -0
  156. package/lib/types/features/pdf-viewer/SimplePdfViewer.d.ts +19 -0
  157. package/lib/types/features/pdf-viewer/SimplePdfViewer.d.ts.map +1 -0
  158. package/lib/types/features/pdf-viewer/index.d.ts +4 -0
  159. package/lib/types/features/pdf-viewer/index.d.ts.map +1 -0
  160. package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
  161. package/lib/types/features/store/collections/SharedPropsEditor.d.ts.map +1 -1
  162. package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
  163. package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
  164. package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts +30 -0
  165. package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -0
  166. package/lib/types/features/store/objects/layout/renderers.d.ts.map +1 -1
  167. package/lib/types/features/utils/index.d.ts +2 -0
  168. package/lib/types/features/utils/index.d.ts.map +1 -1
  169. package/lib/types/features/utils/mimeType.d.ts +1 -0
  170. package/lib/types/features/utils/mimeType.d.ts.map +1 -1
  171. package/lib/types/features/utils/print.d.ts +10 -0
  172. package/lib/types/features/utils/print.d.ts.map +1 -0
  173. package/lib/types/features/utils/workflowStatus.d.ts +10 -0
  174. package/lib/types/features/utils/workflowStatus.d.ts.map +1 -0
  175. package/lib/types/router/HistoryNavigator.d.ts +3 -0
  176. package/lib/types/router/HistoryNavigator.d.ts.map +1 -1
  177. package/lib/types/shell/login/UserInfo.d.ts.map +1 -1
  178. package/lib/types/shell/login/UserSessionMenu.d.ts.map +1 -1
  179. package/lib/types/widgets/form/Form.d.ts.map +1 -1
  180. package/lib/types/widgets/markdown/MarkdownRenderer.d.ts +5 -1
  181. package/lib/types/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
  182. package/lib/types/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
  183. package/lib/types/widgets/xml-viewer/components/XMLViewer.d.ts.map +1 -1
  184. package/lib/types/widgets/xml-viewer/constants/index.d.ts +10 -0
  185. package/lib/types/widgets/xml-viewer/constants/index.d.ts.map +1 -1
  186. package/lib/vertesia-ui-core.js +1 -1
  187. package/lib/vertesia-ui-core.js.map +1 -1
  188. package/lib/vertesia-ui-env.js +1 -1
  189. package/lib/vertesia-ui-env.js.map +1 -1
  190. package/lib/vertesia-ui-features.js +1 -1
  191. package/lib/vertesia-ui-features.js.map +1 -1
  192. package/lib/vertesia-ui-layout.js +1 -1
  193. package/lib/vertesia-ui-layout.js.map +1 -1
  194. package/lib/vertesia-ui-router.js +1 -1
  195. package/lib/vertesia-ui-router.js.map +1 -1
  196. package/lib/vertesia-ui-session.js +1 -1
  197. package/lib/vertesia-ui-session.js.map +1 -1
  198. package/lib/vertesia-ui-shell.js +1 -1
  199. package/lib/vertesia-ui-shell.js.map +1 -1
  200. package/lib/vertesia-ui-widgets.js +1 -1
  201. package/lib/vertesia-ui-widgets.js.map +1 -1
  202. package/package.json +11 -8
  203. package/src/core/components/MenuList.tsx +3 -6
  204. package/src/core/components/MessageBox.tsx +7 -2
  205. package/src/core/components/SelectBox.tsx +1 -1
  206. package/src/core/components/shadcn/dialog.tsx +19 -1
  207. package/src/core/components/shadcn/filters/filter/SelectFilter.tsx +31 -31
  208. package/src/core/components/shadcn/filters/filterBar.tsx +1 -0
  209. package/src/core/components/shadcn/selectBox.tsx +32 -6
  210. package/src/core/components/shadcn/tabs.tsx +3 -2
  211. package/src/env/index.ts +5 -0
  212. package/src/features/agent/CHART_INSTRUCTIONS.md +228 -0
  213. package/src/features/agent/chat/AgentChart.tsx +601 -0
  214. package/src/features/agent/chat/ModernAgentConversation.tsx +123 -11
  215. package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +8 -2
  216. package/src/features/agent/chat/ModernAgentOutput/Header.tsx +12 -2
  217. package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +6 -1
  218. package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +15 -10
  219. package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +122 -87
  220. package/src/features/agent/chat/index.ts +1 -0
  221. package/src/features/agent/createChartTool.ts +364 -0
  222. package/src/features/agent/examples.ts +321 -0
  223. package/src/features/agent/index.ts +2 -0
  224. package/src/features/agent/visualization.ts +227 -0
  225. package/src/features/facets/CollectionsFacetsNav.tsx +5 -1
  226. package/src/features/index.ts +1 -0
  227. package/src/features/layout/GenericPageNavHeader.tsx +15 -4
  228. package/src/features/magic-pdf/AnnotatedImageSlider.tsx +482 -0
  229. package/src/features/magic-pdf/DownloadPopover.tsx +45 -40
  230. package/src/features/magic-pdf/ExtractedContentView.tsx +132 -0
  231. package/src/features/magic-pdf/MagicPdfProvider.tsx +297 -0
  232. package/src/features/magic-pdf/MagicPdfView.tsx +184 -91
  233. package/src/features/pdf-viewer/PdfPageRenderer.tsx +612 -0
  234. package/src/features/pdf-viewer/PdfPageSlider.tsx +473 -0
  235. package/src/features/pdf-viewer/SimplePdfViewer.tsx +142 -0
  236. package/src/features/pdf-viewer/index.ts +3 -0
  237. package/src/features/store/collections/EditCollectionView.tsx +3 -5
  238. package/src/features/store/collections/SharedPropsEditor.tsx +1 -2
  239. package/src/features/store/objects/DocumentSearchResults.tsx +0 -7
  240. package/src/features/store/objects/components/ContentOverview.tsx +677 -210
  241. package/src/features/store/objects/components/useContentPanelHooks.ts +169 -0
  242. package/src/features/store/objects/layout/DocumentTableColumn.tsx +3 -3
  243. package/src/features/store/objects/layout/knowledge.md +1 -0
  244. package/src/features/store/objects/layout/renderers.tsx +25 -0
  245. package/src/features/utils/index.ts +3 -1
  246. package/src/features/utils/mimeType.ts +10 -1
  247. package/src/features/utils/print.ts +189 -0
  248. package/src/features/utils/workflowStatus.ts +44 -0
  249. package/src/router/HistoryNavigator.ts +30 -2
  250. package/src/shell/login/UserInfo.tsx +2 -0
  251. package/src/shell/login/UserSessionMenu.tsx +12 -1
  252. package/src/widgets/form/Form.tsx +8 -3
  253. package/src/widgets/markdown/MarkdownRenderer.tsx +350 -6
  254. package/src/widgets/schema-editor/ManagedSchema.ts +0 -3
  255. package/src/widgets/schema-editor/json-schema4-utils.ts +1 -1
  256. package/src/widgets/xml-viewer/components/XMLViewer.tsx +22 -10
  257. package/src/widgets/xml-viewer/constants/index.ts +11 -0
  258. package/lib/esm/features/magic-pdf/PageSlider.js +0 -70
  259. package/lib/esm/features/magic-pdf/PageSlider.js.map +0 -1
  260. package/lib/esm/features/magic-pdf/PdfPageProvider.js +0 -188
  261. package/lib/esm/features/magic-pdf/PdfPageProvider.js.map +0 -1
  262. package/lib/esm/features/magic-pdf/TextPageView.js +0 -62
  263. package/lib/esm/features/magic-pdf/TextPageView.js.map +0 -1
  264. package/lib/esm/features/magic-pdf/useResizeOnDrag.js +0 -34
  265. package/lib/esm/features/magic-pdf/useResizeOnDrag.js.map +0 -1
  266. package/lib/types/features/magic-pdf/PageSlider.d.ts +0 -9
  267. package/lib/types/features/magic-pdf/PageSlider.d.ts.map +0 -1
  268. package/lib/types/features/magic-pdf/PdfPageProvider.d.ts +0 -39
  269. package/lib/types/features/magic-pdf/PdfPageProvider.d.ts.map +0 -1
  270. package/lib/types/features/magic-pdf/TextPageView.d.ts +0 -8
  271. package/lib/types/features/magic-pdf/TextPageView.d.ts.map +0 -1
  272. package/lib/types/features/magic-pdf/useResizeOnDrag.d.ts +0 -9
  273. package/lib/types/features/magic-pdf/useResizeOnDrag.d.ts.map +0 -1
  274. package/src/features/magic-pdf/PageSlider.tsx +0 -142
  275. package/src/features/magic-pdf/PdfPageProvider.tsx +0 -310
  276. package/src/features/magic-pdf/TextPageView.tsx +0 -91
  277. package/src/features/magic-pdf/useResizeOnDrag.ts +0 -42
@@ -0,0 +1,132 @@
1
+ import { JSONCode, XMLViewer, MarkdownRenderer } from '@vertesia/ui/widgets';
2
+ import { Loader2 } from 'lucide-react';
3
+ import { useEffect, useState } from "react";
4
+ import { useMagicPdfContext } from "./MagicPdfProvider";
5
+ import { ViewType } from "./types";
6
+
7
+ function LoadingSpinner({ className }: { className?: string }) {
8
+ return (
9
+ <div className={`flex items-center justify-center ${className || ''}`}>
10
+ <Loader2 className="w-6 h-6 animate-spin text-gray-400" />
11
+ </div>
12
+ );
13
+ }
14
+
15
+
16
+ interface ExtractedContentViewProps {
17
+ pageNumber: number;
18
+ viewType: ViewType;
19
+ }
20
+ export function ExtractedContentView({ viewType, pageNumber }: ExtractedContentViewProps) {
21
+ switch (viewType) {
22
+ case "json":
23
+ return <JsonPageLayoutView pageNumber={pageNumber} />;
24
+ case "markdown":
25
+ return <MarkdownPageView pageNumber={pageNumber} />;
26
+ default:
27
+ return <XmlPageView pageNumber={pageNumber} />;
28
+ }
29
+ }
30
+
31
+ interface XmlPageViewProps {
32
+ pageNumber: number;
33
+ }
34
+ function XmlPageView({ pageNumber }: XmlPageViewProps) {
35
+ const { xmlPages: pages } = useMagicPdfContext();
36
+ return (
37
+ <div className="px-4 py-2">
38
+ <XMLViewer xml={pages[pageNumber - 1]} collapsible />
39
+ </div>
40
+ )
41
+ }
42
+
43
+ interface JsonPageLayoutViewProps {
44
+ pageNumber: number;
45
+ }
46
+ function JsonPageLayoutView({ pageNumber }: JsonPageLayoutViewProps) {
47
+ const [content, setContent] = useState<unknown>(null);
48
+ const [loading, setLoading] = useState(true);
49
+ const [error, setError] = useState<string | null>(null);
50
+ const { layoutProvider } = useMagicPdfContext();
51
+
52
+ useEffect(() => {
53
+ setLoading(true);
54
+ setError(null);
55
+ layoutProvider.getPageLayout(pageNumber)
56
+ .then((layoutContent) => {
57
+ setContent(layoutContent ? JSON.parse(layoutContent) : null);
58
+ setLoading(false);
59
+ })
60
+ .catch((err: Error) => {
61
+ console.error(err);
62
+ setError(err.message || 'Failed to load layout');
63
+ setLoading(false);
64
+ });
65
+ }, [pageNumber, layoutProvider]);
66
+
67
+ if (loading) {
68
+ return (
69
+ <div className="px-4 py-8">
70
+ <LoadingSpinner />
71
+ </div>
72
+ );
73
+ }
74
+
75
+ if (error) {
76
+ return (
77
+ <div className="px-4 py-2 text-red-500 text-sm">
78
+ {error}
79
+ </div>
80
+ );
81
+ }
82
+
83
+ return content ? <JSONCode className="w-full" data={content} /> : null;
84
+ }
85
+
86
+ interface MarkdownPageViewProps {
87
+ pageNumber: number;
88
+ }
89
+ function MarkdownPageView({ pageNumber }: MarkdownPageViewProps) {
90
+ const [content, setContent] = useState<string | null>(null);
91
+ const [loading, setLoading] = useState(true);
92
+ const [error, setError] = useState<string | null>(null);
93
+ const { markdownProvider } = useMagicPdfContext();
94
+
95
+ useEffect(() => {
96
+ setLoading(true);
97
+ setError(null);
98
+ markdownProvider.getPageMarkdown(pageNumber)
99
+ .then((md) => {
100
+ setContent(md);
101
+ setLoading(false);
102
+ })
103
+ .catch((err: Error) => {
104
+ console.error(err);
105
+ setError(err.message || 'Failed to load markdown');
106
+ setLoading(false);
107
+ });
108
+ }, [pageNumber, markdownProvider]);
109
+
110
+ if (loading) {
111
+ return (
112
+ <div className="h-full flex flex-col items-center justify-center gap-2">
113
+ <LoadingSpinner />
114
+ <span className="text-sm text-muted-foreground">Loading...</span>
115
+ </div>
116
+ );
117
+ }
118
+
119
+ if (error) {
120
+ return (
121
+ <div className="px-4 py-2 text-red-500 text-sm">
122
+ {error}
123
+ </div>
124
+ );
125
+ }
126
+
127
+ return (
128
+ <div className="px-4 py-2 prose prose-sm max-w-none dark:prose-invert">
129
+ {content ? <MarkdownRenderer>{content}</MarkdownRenderer> : <div>No markdown content available</div>}
130
+ </div>
131
+ )
132
+ }
@@ -0,0 +1,297 @@
1
+ import { useUserSession } from "@vertesia/ui/session";
2
+ import { VertesiaClient } from "@vertesia/client";
3
+ import {
4
+ ContentObject,
5
+ DocumentMetadata,
6
+ PDF_RENDITION_NAME,
7
+ } from "@vertesia/common";
8
+ import React, { createContext, useEffect, useState } from "react";
9
+
10
+ const DEFAULT_PAGE_COUNT = 10;
11
+ const ADVANCED_PROCESSING_PREFIX = "magic-pdf";
12
+
13
+ export enum ImageType {
14
+ original = 'original',
15
+ instrumented = 'instrumented',
16
+ }
17
+
18
+ interface MagicPdfContextValue {
19
+ count: number;
20
+ layoutProvider: PageLayoutProvider;
21
+ markdownProvider: PageMarkdownProvider;
22
+ imageProvider: PageImageProvider;
23
+ xml: string;
24
+ xmlPages: string[];
25
+ pdfUrl: string;
26
+ pdfUrlLoading: boolean;
27
+ }
28
+
29
+ /** Provider for lazy-loading page images on demand */
30
+ export class PageImageProvider {
31
+ private cache: Map<string, string> = new Map();
32
+ private pending: Map<string, Promise<string>> = new Map();
33
+
34
+ constructor(
35
+ private client: VertesiaClient,
36
+ private objectId: string,
37
+ public totalPages: number
38
+ ) {}
39
+
40
+ private getCacheKey(page: number, type: ImageType): string {
41
+ return `${type}-${page}`;
42
+ }
43
+
44
+ /** Get the URL for a specific page and image type, fetching lazily if needed */
45
+ async getPageImageUrl(page: number, type: ImageType): Promise<string> {
46
+ const key = this.getCacheKey(page, type);
47
+
48
+ // Return cached URL if available
49
+ const cached = this.cache.get(key);
50
+ if (cached) return cached;
51
+
52
+ // Return pending promise if already fetching
53
+ const pending = this.pending.get(key);
54
+ if (pending) return pending;
55
+
56
+ // Fetch the URL
57
+ const promise = this.fetchImageUrl(page, type);
58
+ this.pending.set(key, promise);
59
+
60
+ try {
61
+ const url = await promise;
62
+ this.cache.set(key, url);
63
+ return url;
64
+ } finally {
65
+ this.pending.delete(key);
66
+ }
67
+ }
68
+
69
+ private async fetchImageUrl(page: number, type: ImageType): Promise<string> {
70
+ const path = this.getImagePath(page, type);
71
+ const response = await this.client.files.getDownloadUrl(path);
72
+ return response.url;
73
+ }
74
+
75
+ private getImagePath(page: number, type: ImageType): string {
76
+ const basePath = `${ADVANCED_PROCESSING_PREFIX}/${this.objectId}/pages`;
77
+ switch (type) {
78
+ case ImageType.original:
79
+ return `${basePath}/page-${page}.original.jpg`;
80
+ case ImageType.instrumented:
81
+ return `${basePath}/page-${page}.instrumented.jpg`;
82
+ }
83
+ }
84
+ }
85
+
86
+ class PageLayoutProvider {
87
+ private cache: Map<number, string> = new Map();
88
+ private pending: Map<number, Promise<string>> = new Map();
89
+
90
+ constructor(
91
+ private client: VertesiaClient,
92
+ private objectId: string,
93
+ public totalPages: number
94
+ ) {}
95
+
96
+ async getPageLayout(page: number): Promise<string> {
97
+ // Return cached content if available
98
+ const cached = this.cache.get(page);
99
+ if (cached !== undefined) return cached;
100
+
101
+ // Return pending promise if already fetching
102
+ const pending = this.pending.get(page);
103
+ if (pending) return pending;
104
+
105
+ // Fetch the layout
106
+ const promise = this.fetchPageLayout(page);
107
+ this.pending.set(page, promise);
108
+
109
+ try {
110
+ const content = await promise;
111
+ this.cache.set(page, content);
112
+ return content;
113
+ } finally {
114
+ this.pending.delete(page);
115
+ }
116
+ }
117
+
118
+ private async fetchPageLayout(page: number): Promise<string> {
119
+ const path = `${ADVANCED_PROCESSING_PREFIX}/${this.objectId}/pages/page-${page}.layout.json`;
120
+ const response = await this.client.files.getDownloadUrl(path);
121
+ const result = await fetch(response.url, { method: "GET" });
122
+ if (!result.ok) {
123
+ throw new Error("Failed to fetch json layout: " + result.statusText);
124
+ }
125
+ return result.text();
126
+ }
127
+ }
128
+
129
+ class PageMarkdownProvider {
130
+ private pages: string[] = [];
131
+
132
+ constructor(public totalPages: number) {}
133
+
134
+ // Initialize by parsing pages from the full markdown content
135
+ // Pages are delimited by <!-- {"page":N} --> markers
136
+ initFromContent(markdownContent: string) {
137
+ this.pages = extractMarkdownPages(markdownContent, this.totalPages);
138
+ }
139
+
140
+ // Keep for backwards compatibility with non-markdown processors
141
+ async loadUrls(_vertesia: VertesiaClient, _objectId: string) {
142
+ // No-op for markdown processor - content is already parsed
143
+ }
144
+
145
+ async getPageMarkdown(page: number): Promise<string> {
146
+ const index = page - 1;
147
+ if (index < 0 || index >= this.pages.length) {
148
+ return '';
149
+ }
150
+ return this.pages[index];
151
+ }
152
+ }
153
+
154
+ // Extract markdown pages from content delimited by <!-- {"page":N} --> markers
155
+ function extractMarkdownPages(content: string, totalPages: number): string[] {
156
+ const pages: string[] = new Array(totalPages).fill('');
157
+
158
+ // Match page delimiters: <!-- {"page":N} -->
159
+ const pageDelimiterRegex = /<!--\s*\{\s*"page"\s*:\s*(\d+)\s*\}\s*-->/g;
160
+
161
+ // Find all page markers and their positions
162
+ const markers: { page: number; index: number }[] = [];
163
+ let match;
164
+ while ((match = pageDelimiterRegex.exec(content)) !== null) {
165
+ markers.push({
166
+ page: parseInt(match[1], 10),
167
+ index: match.index + match[0].length,
168
+ });
169
+ }
170
+
171
+ // Extract content between markers
172
+ for (let i = 0; i < markers.length; i++) {
173
+ const marker = markers[i];
174
+ const pageIndex = marker.page - 1;
175
+
176
+ if (pageIndex < 0 || pageIndex >= totalPages) {
177
+ continue;
178
+ }
179
+
180
+ const startIndex = marker.index;
181
+
182
+ // Find the actual end by looking for the next delimiter or end of content
183
+ const nextDelimiterMatch = content.slice(startIndex).match(/<!--\s*\{\s*"page"\s*:\s*\d+\s*\}\s*-->/);
184
+ const actualEndIndex = nextDelimiterMatch
185
+ ? startIndex + nextDelimiterMatch.index!
186
+ : content.length;
187
+
188
+ let pageContent = content.slice(startIndex, actualEndIndex).trim();
189
+
190
+ // Remove trailing --- separators if present
191
+ pageContent = pageContent.replace(/\n---\s*$/, '').trim();
192
+
193
+ pages[pageIndex] = pageContent;
194
+ }
195
+
196
+ return pages;
197
+ }
198
+
199
+ const MagicPdfContext = createContext<MagicPdfContextValue | undefined>(undefined);
200
+
201
+ interface MagicPdfProviderProps {
202
+ object: ContentObject;
203
+ children: React.ReactNode;
204
+ }
205
+ export function MagicPdfProvider({ children, object }: MagicPdfProviderProps) {
206
+ const { client } = useUserSession();
207
+ const page_count = (object.metadata as DocumentMetadata).page_count || DEFAULT_PAGE_COUNT;
208
+ const isMarkdownProcessor = (object.metadata as DocumentMetadata)?.content_processor?.type === 'markdown';
209
+
210
+ // Create initial context immediately (synchronously) for both processor types
211
+ const [info, setInfo] = useState<MagicPdfContextValue>(() => {
212
+ const markdownProvider = new PageMarkdownProvider(page_count);
213
+ if (isMarkdownProcessor && object.text) {
214
+ markdownProvider.initFromContent(object.text);
215
+ }
216
+ const xml = object.text ? cleanXml(object.text) : "";
217
+ return {
218
+ count: page_count,
219
+ layoutProvider: new PageLayoutProvider(client, object.id, page_count),
220
+ markdownProvider,
221
+ imageProvider: new PageImageProvider(client, object.id, page_count),
222
+ xml,
223
+ xmlPages: object.text ? extractXmlPages(xml) : [],
224
+ pdfUrl: '',
225
+ pdfUrlLoading: true,
226
+ };
227
+ });
228
+
229
+ useEffect(() => {
230
+ if (isMarkdownProcessor) {
231
+ // For markdown processor, fetch the PDF URL lazily
232
+ // Priority: PDF rendition > source (only if source is PDF)
233
+ const metadata = object.metadata as DocumentMetadata;
234
+ const pdfRendition = metadata?.renditions?.find(r => r.name === PDF_RENDITION_NAME);
235
+ const isPdfSource = object.content?.type === 'application/pdf';
236
+ const sourceToResolve = pdfRendition?.content?.source || (isPdfSource ? object.content?.source : undefined);
237
+
238
+ if (sourceToResolve) {
239
+ client.store.objects.getDownloadUrl(sourceToResolve, undefined, 'inline')
240
+ .then((response) => {
241
+ setInfo(prev => ({ ...prev, pdfUrl: response.url, pdfUrlLoading: false }));
242
+ })
243
+ .catch((e) => {
244
+ console.warn('Failed to get PDF URL:', e);
245
+ setInfo(prev => ({ ...prev, pdfUrlLoading: false }));
246
+ });
247
+ } else {
248
+ setInfo(prev => ({ ...prev, pdfUrlLoading: false }));
249
+ }
250
+ } else {
251
+ // For XML processor, no pre-loading needed - images load on demand
252
+ setInfo(prev => ({ ...prev, pdfUrlLoading: false }));
253
+ }
254
+ }, [object.id, client, isMarkdownProcessor, page_count]);
255
+
256
+ return (
257
+ <MagicPdfContext.Provider value={info}>
258
+ {children}
259
+ </MagicPdfContext.Provider>
260
+ );
261
+ }
262
+
263
+ export function getResourceUrl(
264
+ vertesia: VertesiaClient,
265
+ objectId: string,
266
+ name: string,
267
+ ): Promise<string> {
268
+ return vertesia.files
269
+ .getDownloadUrl(`${ADVANCED_PROCESSING_PREFIX}/${objectId}/${name}`)
270
+ .then((r) => r.url);
271
+ }
272
+
273
+ export function useMagicPdfContext() {
274
+ const context = React.useContext(MagicPdfContext);
275
+ if (!context) {
276
+ throw new Error(
277
+ "useMagicPdfContext must be used within a MagicPdfProvider",
278
+ );
279
+ }
280
+ return context;
281
+ }
282
+
283
+ function extractXmlPages(xml: string): string[] {
284
+ // Parse the XML string
285
+ const doc = new DOMParser().parseFromString(cleanXml(xml), "text/xml");
286
+ const pages = doc.getElementsByTagName("page");
287
+ const serializer = new XMLSerializer();
288
+ return Array.from(pages).map((p) => serializer.serializeToString(p));
289
+ }
290
+
291
+ function cleanXml(xml: string) {
292
+ const cleanedXML = xml
293
+ // eslint-disable-next-line no-control-regex
294
+ .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "")
295
+ .replace(/<\?xml.*?\?>/g, "");
296
+ return cleanedXML;
297
+ }