@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.
- package/README.md +105 -0
- package/lib/esm/core/components/MenuList.js +2 -5
- package/lib/esm/core/components/MenuList.js.map +1 -1
- package/lib/esm/core/components/MessageBox.js +1 -1
- package/lib/esm/core/components/MessageBox.js.map +1 -1
- package/lib/esm/core/components/shadcn/dialog.js +16 -2
- package/lib/esm/core/components/shadcn/dialog.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filter/SelectFilter.js +6 -9
- package/lib/esm/core/components/shadcn/filters/filter/SelectFilter.js.map +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js +1 -1
- package/lib/esm/core/components/shadcn/filters/filterBar.js.map +1 -1
- package/lib/esm/core/components/shadcn/selectBox.js +23 -5
- package/lib/esm/core/components/shadcn/selectBox.js.map +1 -1
- package/lib/esm/core/components/shadcn/tabs.js +3 -3
- package/lib/esm/core/components/shadcn/tabs.js.map +1 -1
- package/lib/esm/env/index.js +3 -0
- package/lib/esm/env/index.js.map +1 -1
- package/lib/esm/features/agent/chat/AgentChart.js +184 -0
- package/lib/esm/features/agent/chat/AgentChart.js.map +1 -0
- package/lib/esm/features/agent/chat/ModernAgentConversation.js +87 -10
- package/lib/esm/features/agent/chat/ModernAgentConversation.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js +6 -2
- package/lib/esm/features/agent/chat/ModernAgentOutput/AllMessagesMixed.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js +4 -4
- package/lib/esm/features/agent/chat/ModernAgentOutput/Header.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js +4 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js +12 -4
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageInput.js.map +1 -1
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js +60 -56
- package/lib/esm/features/agent/chat/ModernAgentOutput/MessageItem.js.map +1 -1
- package/lib/esm/features/agent/chat/index.js +1 -0
- package/lib/esm/features/agent/chat/index.js.map +1 -1
- package/lib/esm/features/agent/createChartTool.js +354 -0
- package/lib/esm/features/agent/createChartTool.js.map +1 -0
- package/lib/esm/features/agent/examples.js +295 -0
- package/lib/esm/features/agent/examples.js.map +1 -0
- package/lib/esm/features/agent/index.js +2 -0
- package/lib/esm/features/agent/index.js.map +1 -1
- package/lib/esm/features/agent/visualization.js +165 -0
- package/lib/esm/features/agent/visualization.js.map +1 -0
- package/lib/esm/features/facets/CollectionsFacetsNav.js +5 -1
- package/lib/esm/features/facets/CollectionsFacetsNav.js.map +1 -1
- package/lib/esm/features/index.js +1 -0
- package/lib/esm/features/index.js.map +1 -1
- package/lib/esm/features/layout/GenericPageNavHeader.js +14 -4
- package/lib/esm/features/layout/GenericPageNavHeader.js.map +1 -1
- package/lib/esm/features/magic-pdf/AnnotatedImageSlider.js +268 -0
- package/lib/esm/features/magic-pdf/AnnotatedImageSlider.js.map +1 -0
- package/lib/esm/features/magic-pdf/DownloadPopover.js +11 -11
- package/lib/esm/features/magic-pdf/DownloadPopover.js.map +1 -1
- package/lib/esm/features/magic-pdf/ExtractedContentView.js +77 -0
- package/lib/esm/features/magic-pdf/ExtractedContentView.js.map +1 -0
- package/lib/esm/features/magic-pdf/MagicPdfProvider.js +242 -0
- package/lib/esm/features/magic-pdf/MagicPdfProvider.js.map +1 -0
- package/lib/esm/features/magic-pdf/MagicPdfView.js +41 -47
- package/lib/esm/features/magic-pdf/MagicPdfView.js.map +1 -1
- package/lib/esm/features/pdf-viewer/PdfPageRenderer.js +261 -0
- package/lib/esm/features/pdf-viewer/PdfPageRenderer.js.map +1 -0
- package/lib/esm/features/pdf-viewer/PdfPageSlider.js +276 -0
- package/lib/esm/features/pdf-viewer/PdfPageSlider.js.map +1 -0
- package/lib/esm/features/pdf-viewer/SimplePdfViewer.js +71 -0
- package/lib/esm/features/pdf-viewer/SimplePdfViewer.js.map +1 -0
- package/lib/esm/features/pdf-viewer/index.js +4 -0
- package/lib/esm/features/pdf-viewer/index.js.map +1 -0
- package/lib/esm/features/store/collections/EditCollectionView.js +3 -5
- package/lib/esm/features/store/collections/EditCollectionView.js.map +1 -1
- package/lib/esm/features/store/collections/SharedPropsEditor.js +1 -2
- package/lib/esm/features/store/collections/SharedPropsEditor.js.map +1 -1
- package/lib/esm/features/store/objects/DocumentSearchResults.js +0 -7
- package/lib/esm/features/store/objects/DocumentSearchResults.js.map +1 -1
- package/lib/esm/features/store/objects/components/ContentOverview.js +273 -83
- package/lib/esm/features/store/objects/components/ContentOverview.js.map +1 -1
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js +153 -0
- package/lib/esm/features/store/objects/components/useContentPanelHooks.js.map +1 -0
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js +3 -3
- package/lib/esm/features/store/objects/layout/DocumentTableColumn.js.map +1 -1
- package/lib/esm/features/store/objects/layout/renderers.js +13 -0
- package/lib/esm/features/store/objects/layout/renderers.js.map +1 -1
- package/lib/esm/features/utils/index.js +2 -0
- package/lib/esm/features/utils/index.js.map +1 -1
- package/lib/esm/features/utils/mimeType.js +8 -0
- package/lib/esm/features/utils/mimeType.js.map +1 -1
- package/lib/esm/features/utils/print.js +181 -0
- package/lib/esm/features/utils/print.js.map +1 -0
- package/lib/esm/features/utils/workflowStatus.js +43 -0
- package/lib/esm/features/utils/workflowStatus.js.map +1 -0
- package/lib/esm/router/HistoryNavigator.js +22 -2
- package/lib/esm/router/HistoryNavigator.js.map +1 -1
- package/lib/esm/shell/login/UserInfo.js +2 -1
- package/lib/esm/shell/login/UserInfo.js.map +1 -1
- package/lib/esm/shell/login/UserSessionMenu.js +7 -1
- package/lib/esm/shell/login/UserSessionMenu.js.map +1 -1
- package/lib/esm/widgets/form/Form.js +6 -2
- package/lib/esm/widgets/form/Form.js.map +1 -1
- package/lib/esm/widgets/markdown/MarkdownRenderer.js +226 -4
- package/lib/esm/widgets/markdown/MarkdownRenderer.js.map +1 -1
- package/lib/esm/widgets/schema-editor/ManagedSchema.js +0 -3
- package/lib/esm/widgets/schema-editor/ManagedSchema.js.map +1 -1
- package/lib/esm/widgets/schema-editor/json-schema4-utils.js +1 -1
- package/lib/esm/widgets/schema-editor/json-schema4-utils.js.map +1 -1
- package/lib/esm/widgets/xml-viewer/components/XMLViewer.js +18 -9
- package/lib/esm/widgets/xml-viewer/components/XMLViewer.js.map +1 -1
- package/lib/esm/widgets/xml-viewer/constants/index.js +10 -0
- package/lib/esm/widgets/xml-viewer/constants/index.js.map +1 -1
- package/lib/tsconfig.tsbuildinfo +1 -1
- package/lib/types/core/components/MessageBox.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/dialog.d.ts +2 -1
- package/lib/types/core/components/shadcn/dialog.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/filters/filterBar.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/selectBox.d.ts +5 -1
- package/lib/types/core/components/shadcn/selectBox.d.ts.map +1 -1
- package/lib/types/core/components/shadcn/tabs.d.ts +3 -1
- package/lib/types/core/components/shadcn/tabs.d.ts.map +1 -1
- package/lib/types/env/index.d.ts +2 -0
- package/lib/types/env/index.d.ts.map +1 -1
- package/lib/types/features/agent/chat/AgentChart.d.ts +48 -0
- package/lib/types/features/agent/chat/AgentChart.d.ts.map +1 -0
- package/lib/types/features/agent/chat/ModernAgentConversation.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts +3 -2
- package/lib/types/features/agent/chat/ModernAgentOutput/AllMessagesMixed.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts +2 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/Header.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts +4 -2
- package/lib/types/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageInput.d.ts +2 -4
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageInput.d.ts.map +1 -1
- package/lib/types/features/agent/chat/ModernAgentOutput/MessageItem.d.ts.map +1 -1
- package/lib/types/features/agent/chat/index.d.ts +1 -0
- package/lib/types/features/agent/chat/index.d.ts.map +1 -1
- package/lib/types/features/agent/createChartTool.d.ts +178 -0
- package/lib/types/features/agent/createChartTool.d.ts.map +1 -0
- package/lib/types/features/agent/examples.d.ts +59 -0
- package/lib/types/features/agent/examples.d.ts.map +1 -0
- package/lib/types/features/agent/index.d.ts +2 -0
- package/lib/types/features/agent/index.d.ts.map +1 -1
- package/lib/types/features/agent/visualization.d.ts +95 -0
- package/lib/types/features/agent/visualization.d.ts.map +1 -0
- package/lib/types/features/facets/CollectionsFacetsNav.d.ts.map +1 -1
- package/lib/types/features/index.d.ts +1 -0
- package/lib/types/features/index.d.ts.map +1 -1
- package/lib/types/features/layout/GenericPageNavHeader.d.ts.map +1 -1
- package/lib/types/features/magic-pdf/AnnotatedImageSlider.d.ts +13 -0
- package/lib/types/features/magic-pdf/AnnotatedImageSlider.d.ts.map +1 -0
- package/lib/types/features/magic-pdf/DownloadPopover.d.ts.map +1 -1
- package/lib/types/features/magic-pdf/ExtractedContentView.d.ts +8 -0
- package/lib/types/features/magic-pdf/ExtractedContentView.d.ts.map +1 -0
- package/lib/types/features/magic-pdf/MagicPdfProvider.d.ts +58 -0
- package/lib/types/features/magic-pdf/MagicPdfProvider.d.ts.map +1 -0
- package/lib/types/features/magic-pdf/MagicPdfView.d.ts +1 -1
- package/lib/types/features/magic-pdf/MagicPdfView.d.ts.map +1 -1
- package/lib/types/features/pdf-viewer/PdfPageRenderer.d.ts +83 -0
- package/lib/types/features/pdf-viewer/PdfPageRenderer.d.ts.map +1 -0
- package/lib/types/features/pdf-viewer/PdfPageSlider.d.ts +29 -0
- package/lib/types/features/pdf-viewer/PdfPageSlider.d.ts.map +1 -0
- package/lib/types/features/pdf-viewer/SimplePdfViewer.d.ts +19 -0
- package/lib/types/features/pdf-viewer/SimplePdfViewer.d.ts.map +1 -0
- package/lib/types/features/pdf-viewer/index.d.ts +4 -0
- package/lib/types/features/pdf-viewer/index.d.ts.map +1 -0
- package/lib/types/features/store/collections/EditCollectionView.d.ts.map +1 -1
- package/lib/types/features/store/collections/SharedPropsEditor.d.ts.map +1 -1
- package/lib/types/features/store/objects/DocumentSearchResults.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/ContentOverview.d.ts.map +1 -1
- package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts +30 -0
- package/lib/types/features/store/objects/components/useContentPanelHooks.d.ts.map +1 -0
- package/lib/types/features/store/objects/layout/renderers.d.ts.map +1 -1
- package/lib/types/features/utils/index.d.ts +2 -0
- package/lib/types/features/utils/index.d.ts.map +1 -1
- package/lib/types/features/utils/mimeType.d.ts +1 -0
- package/lib/types/features/utils/mimeType.d.ts.map +1 -1
- package/lib/types/features/utils/print.d.ts +10 -0
- package/lib/types/features/utils/print.d.ts.map +1 -0
- package/lib/types/features/utils/workflowStatus.d.ts +10 -0
- package/lib/types/features/utils/workflowStatus.d.ts.map +1 -0
- package/lib/types/router/HistoryNavigator.d.ts +3 -0
- package/lib/types/router/HistoryNavigator.d.ts.map +1 -1
- package/lib/types/shell/login/UserInfo.d.ts.map +1 -1
- package/lib/types/shell/login/UserSessionMenu.d.ts.map +1 -1
- package/lib/types/widgets/form/Form.d.ts.map +1 -1
- package/lib/types/widgets/markdown/MarkdownRenderer.d.ts +5 -1
- package/lib/types/widgets/markdown/MarkdownRenderer.d.ts.map +1 -1
- package/lib/types/widgets/schema-editor/ManagedSchema.d.ts.map +1 -1
- package/lib/types/widgets/xml-viewer/components/XMLViewer.d.ts.map +1 -1
- package/lib/types/widgets/xml-viewer/constants/index.d.ts +10 -0
- package/lib/types/widgets/xml-viewer/constants/index.d.ts.map +1 -1
- package/lib/vertesia-ui-core.js +1 -1
- package/lib/vertesia-ui-core.js.map +1 -1
- package/lib/vertesia-ui-env.js +1 -1
- package/lib/vertesia-ui-env.js.map +1 -1
- package/lib/vertesia-ui-features.js +1 -1
- package/lib/vertesia-ui-features.js.map +1 -1
- package/lib/vertesia-ui-layout.js +1 -1
- package/lib/vertesia-ui-layout.js.map +1 -1
- package/lib/vertesia-ui-router.js +1 -1
- package/lib/vertesia-ui-router.js.map +1 -1
- package/lib/vertesia-ui-session.js +1 -1
- package/lib/vertesia-ui-session.js.map +1 -1
- package/lib/vertesia-ui-shell.js +1 -1
- package/lib/vertesia-ui-shell.js.map +1 -1
- package/lib/vertesia-ui-widgets.js +1 -1
- package/lib/vertesia-ui-widgets.js.map +1 -1
- package/package.json +11 -8
- package/src/core/components/MenuList.tsx +3 -6
- package/src/core/components/MessageBox.tsx +7 -2
- package/src/core/components/SelectBox.tsx +1 -1
- package/src/core/components/shadcn/dialog.tsx +19 -1
- package/src/core/components/shadcn/filters/filter/SelectFilter.tsx +31 -31
- package/src/core/components/shadcn/filters/filterBar.tsx +1 -0
- package/src/core/components/shadcn/selectBox.tsx +32 -6
- package/src/core/components/shadcn/tabs.tsx +3 -2
- package/src/env/index.ts +5 -0
- package/src/features/agent/CHART_INSTRUCTIONS.md +228 -0
- package/src/features/agent/chat/AgentChart.tsx +601 -0
- package/src/features/agent/chat/ModernAgentConversation.tsx +123 -11
- package/src/features/agent/chat/ModernAgentOutput/AllMessagesMixed.tsx +8 -2
- package/src/features/agent/chat/ModernAgentOutput/Header.tsx +12 -2
- package/src/features/agent/chat/ModernAgentOutput/InlineSlidingPlanPanel.tsx +6 -1
- package/src/features/agent/chat/ModernAgentOutput/MessageInput.tsx +15 -10
- package/src/features/agent/chat/ModernAgentOutput/MessageItem.tsx +122 -87
- package/src/features/agent/chat/index.ts +1 -0
- package/src/features/agent/createChartTool.ts +364 -0
- package/src/features/agent/examples.ts +321 -0
- package/src/features/agent/index.ts +2 -0
- package/src/features/agent/visualization.ts +227 -0
- package/src/features/facets/CollectionsFacetsNav.tsx +5 -1
- package/src/features/index.ts +1 -0
- package/src/features/layout/GenericPageNavHeader.tsx +15 -4
- package/src/features/magic-pdf/AnnotatedImageSlider.tsx +482 -0
- package/src/features/magic-pdf/DownloadPopover.tsx +45 -40
- package/src/features/magic-pdf/ExtractedContentView.tsx +132 -0
- package/src/features/magic-pdf/MagicPdfProvider.tsx +297 -0
- package/src/features/magic-pdf/MagicPdfView.tsx +184 -91
- package/src/features/pdf-viewer/PdfPageRenderer.tsx +612 -0
- package/src/features/pdf-viewer/PdfPageSlider.tsx +473 -0
- package/src/features/pdf-viewer/SimplePdfViewer.tsx +142 -0
- package/src/features/pdf-viewer/index.ts +3 -0
- package/src/features/store/collections/EditCollectionView.tsx +3 -5
- package/src/features/store/collections/SharedPropsEditor.tsx +1 -2
- package/src/features/store/objects/DocumentSearchResults.tsx +0 -7
- package/src/features/store/objects/components/ContentOverview.tsx +677 -210
- package/src/features/store/objects/components/useContentPanelHooks.ts +169 -0
- package/src/features/store/objects/layout/DocumentTableColumn.tsx +3 -3
- package/src/features/store/objects/layout/knowledge.md +1 -0
- package/src/features/store/objects/layout/renderers.tsx +25 -0
- package/src/features/utils/index.ts +3 -1
- package/src/features/utils/mimeType.ts +10 -1
- package/src/features/utils/print.ts +189 -0
- package/src/features/utils/workflowStatus.ts +44 -0
- package/src/router/HistoryNavigator.ts +30 -2
- package/src/shell/login/UserInfo.tsx +2 -0
- package/src/shell/login/UserSessionMenu.tsx +12 -1
- package/src/widgets/form/Form.tsx +8 -3
- package/src/widgets/markdown/MarkdownRenderer.tsx +350 -6
- package/src/widgets/schema-editor/ManagedSchema.ts +0 -3
- package/src/widgets/schema-editor/json-schema4-utils.ts +1 -1
- package/src/widgets/xml-viewer/components/XMLViewer.tsx +22 -10
- package/src/widgets/xml-viewer/constants/index.ts +11 -0
- package/lib/esm/features/magic-pdf/PageSlider.js +0 -70
- package/lib/esm/features/magic-pdf/PageSlider.js.map +0 -1
- package/lib/esm/features/magic-pdf/PdfPageProvider.js +0 -188
- package/lib/esm/features/magic-pdf/PdfPageProvider.js.map +0 -1
- package/lib/esm/features/magic-pdf/TextPageView.js +0 -62
- package/lib/esm/features/magic-pdf/TextPageView.js.map +0 -1
- package/lib/esm/features/magic-pdf/useResizeOnDrag.js +0 -34
- package/lib/esm/features/magic-pdf/useResizeOnDrag.js.map +0 -1
- package/lib/types/features/magic-pdf/PageSlider.d.ts +0 -9
- package/lib/types/features/magic-pdf/PageSlider.d.ts.map +0 -1
- package/lib/types/features/magic-pdf/PdfPageProvider.d.ts +0 -39
- package/lib/types/features/magic-pdf/PdfPageProvider.d.ts.map +0 -1
- package/lib/types/features/magic-pdf/TextPageView.d.ts +0 -8
- package/lib/types/features/magic-pdf/TextPageView.d.ts.map +0 -1
- package/lib/types/features/magic-pdf/useResizeOnDrag.d.ts +0 -9
- package/lib/types/features/magic-pdf/useResizeOnDrag.d.ts.map +0 -1
- package/src/features/magic-pdf/PageSlider.tsx +0 -142
- package/src/features/magic-pdf/PdfPageProvider.tsx +0 -310
- package/src/features/magic-pdf/TextPageView.tsx +0 -91
- 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
|
+
}
|