@tfw.in/structura-lib 0.2.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/PRODUCTION_ARCHITECTURE.md +511 -0
- package/README.md +379 -0
- package/SAVE_FUNCTIONALITY_COMPLETE.md +448 -0
- package/dist/cjs/EditableContent.js +150 -0
- package/dist/cjs/HtmlViewer.js +587 -0
- package/dist/cjs/PdfComponents.js +16 -0
- package/dist/cjs/PdfDocumentViewer.js +281 -0
- package/dist/cjs/Structura.js +806 -0
- package/dist/cjs/Table.js +164 -0
- package/dist/cjs/TableCell.js +115 -0
- package/dist/cjs/accuracyMetrics.js +39 -0
- package/dist/cjs/helpers/preprocessData.js +143 -0
- package/dist/cjs/index.js +7 -0
- package/dist/cjs/lib/polyfills.js +15 -0
- package/dist/cjs/lib/utils.js +10 -0
- package/dist/cjs/node_modules/react-icons/fa/index.esm.js +14 -0
- package/dist/cjs/node_modules/react-icons/lib/esm/iconBase.js +69 -0
- package/dist/cjs/node_modules/react-icons/lib/esm/iconContext.js +15 -0
- package/dist/cjs/polyfills.js +19 -0
- package/dist/cjs/route.js +102 -0
- package/dist/cjs/styles.css +7 -0
- package/dist/cjs/styles.css.map +1 -0
- package/dist/cjs/ui/badge.js +34 -0
- package/dist/cjs/ui/button.js +71 -0
- package/dist/cjs/ui/card.js +86 -0
- package/dist/cjs/ui/progress.js +45 -0
- package/dist/cjs/ui/scroll-area.js +62 -0
- package/dist/cjs/ui/tabs.js +60 -0
- package/dist/cjs/worker.js +36 -0
- package/dist/esm/EditableContent.js +161 -0
- package/dist/esm/HtmlViewer.js +640 -0
- package/dist/esm/PdfComponents.js +21 -0
- package/dist/esm/PdfDocumentViewer.js +294 -0
- package/dist/esm/Structura.js +951 -0
- package/dist/esm/Table.js +182 -0
- package/dist/esm/TableCell.js +122 -0
- package/dist/esm/_virtual/_rollupPluginBabelHelpers.js +305 -0
- package/dist/esm/accuracyMetrics.js +41 -0
- package/dist/esm/helpers/preprocessData.js +152 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/lib/polyfills.js +13 -0
- package/dist/esm/lib/utils.js +8 -0
- package/dist/esm/node_modules/react-icons/fa/index.esm.js +11 -0
- package/dist/esm/node_modules/react-icons/lib/esm/iconBase.js +66 -0
- package/dist/esm/node_modules/react-icons/lib/esm/iconContext.js +12 -0
- package/dist/esm/polyfills.js +17 -0
- package/dist/esm/route.js +154 -0
- package/dist/esm/styles.css +7 -0
- package/dist/esm/styles.css.map +1 -0
- package/dist/esm/types/EditableContent.d.ts +9 -0
- package/dist/esm/types/HtmlViewer.d.ts +10 -0
- package/dist/esm/types/PdfComponents.d.ts +35 -0
- package/dist/esm/types/PdfDocumentViewer.d.ts +22 -0
- package/dist/esm/types/Structura.d.ts +11 -0
- package/dist/esm/types/Table.d.ts +12 -0
- package/dist/esm/types/TableCell.d.ts +13 -0
- package/dist/esm/types/accuracy.d.ts +23 -0
- package/dist/esm/types/accuracyMetrics.d.ts +5 -0
- package/dist/esm/types/helpers/flattenJSON.d.ts +1 -0
- package/dist/esm/types/helpers/hardMerging.d.ts +2 -0
- package/dist/esm/types/helpers/index.d.ts +6 -0
- package/dist/esm/types/helpers/jsonToHtml.d.ts +40 -0
- package/dist/esm/types/helpers/preprocessData.d.ts +3 -0
- package/dist/esm/types/helpers/removeMetadata.d.ts +1 -0
- package/dist/esm/types/helpers/tableProcessor.d.ts +1 -0
- package/dist/esm/types/index.d.ts +3 -0
- package/dist/esm/types/lib/polyfills.d.ts +1 -0
- package/dist/esm/types/lib/utils.d.ts +2 -0
- package/dist/esm/types/polyfills.d.ts +1 -0
- package/dist/esm/types/route.d.ts +45 -0
- package/dist/esm/types/test-app/src/App.d.ts +4 -0
- package/dist/esm/types/test-app/src/main.d.ts +1 -0
- package/dist/esm/types/test-app/vite.config.d.ts +2 -0
- package/dist/esm/types/types.d.ts +23 -0
- package/dist/esm/types/ui/alert.d.ts +8 -0
- package/dist/esm/types/ui/badge.d.ts +9 -0
- package/dist/esm/types/ui/button.d.ts +11 -0
- package/dist/esm/types/ui/card.d.ts +8 -0
- package/dist/esm/types/ui/progress.d.ts +6 -0
- package/dist/esm/types/ui/scroll-area.d.ts +5 -0
- package/dist/esm/types/ui/skeleton.d.ts +2 -0
- package/dist/esm/types/ui/tabs.d.ts +7 -0
- package/dist/esm/types/worker.d.ts +1 -0
- package/dist/esm/ui/badge.js +31 -0
- package/dist/esm/ui/button.js +50 -0
- package/dist/esm/ui/card.js +67 -0
- package/dist/esm/ui/progress.js +26 -0
- package/dist/esm/ui/scroll-area.js +45 -0
- package/dist/esm/ui/tabs.js +39 -0
- package/dist/esm/worker.js +50 -0
- package/dist/index.d.ts +38 -0
- package/package.json +85 -0
- package/server/README.md +203 -0
- package/server/db.js +142 -0
- package/server/server.js +165 -0
|
@@ -0,0 +1,951 @@
|
|
|
1
|
+
import { slicedToArray as _slicedToArray, asyncToGenerator as _asyncToGenerator, regenerator as _regenerator, createForOfIteratorHelper as _createForOfIteratorHelper } from './_virtual/_rollupPluginBabelHelpers.js';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useState, useRef, useEffect } from 'react';
|
|
4
|
+
import { Button } from './ui/button.js';
|
|
5
|
+
import { Card, CardHeader, CardTitle, CardContent } from './ui/card.js';
|
|
6
|
+
import { Tabs, TabsList, TabsTrigger, TabsContent } from './ui/tabs.js';
|
|
7
|
+
import * as LucideIcons from 'lucide-react';
|
|
8
|
+
import PdfDocumentViewer from './PdfDocumentViewer.js';
|
|
9
|
+
import HtmlViewer from './HtmlViewer.js';
|
|
10
|
+
import { preprocessData } from './helpers/preprocessData.js';
|
|
11
|
+
import { PanelGroup, Panel, PanelResizeHandle } from 'react-resizable-panels';
|
|
12
|
+
import { Badge } from './ui/badge.js';
|
|
13
|
+
import { Progress } from './ui/progress.js';
|
|
14
|
+
import { ScrollArea } from './ui/scroll-area.js';
|
|
15
|
+
import { GET, POST } from './route.js';
|
|
16
|
+
|
|
17
|
+
// Remove component aliases and use direct imports
|
|
18
|
+
// This will preserve the propser types
|
|
19
|
+
function Structura(_ref) {
|
|
20
|
+
var initialPdfPath = _ref.initialPdfPath,
|
|
21
|
+
initialJsonData = _ref.initialJsonData,
|
|
22
|
+
props = _ref.props;
|
|
23
|
+
// Log the API key (for development only - remove in production)
|
|
24
|
+
// useEffect(() => {
|
|
25
|
+
// if (props?.APIKey) {
|
|
26
|
+
// console.log("API Key provided:", props.APIKey);
|
|
27
|
+
// }
|
|
28
|
+
// }, [props]);
|
|
29
|
+
// Log the imported SDK items to demonstrate usage
|
|
30
|
+
// console.log("Imported BlockSchema from SDK:", BlockSchema);
|
|
31
|
+
var _useState = useState(null),
|
|
32
|
+
_useState2 = _slicedToArray(_useState, 2),
|
|
33
|
+
numPages = _useState2[0],
|
|
34
|
+
setNumPages = _useState2[1];
|
|
35
|
+
var _useState3 = useState(1),
|
|
36
|
+
_useState4 = _slicedToArray(_useState3, 2);
|
|
37
|
+
_useState4[0];
|
|
38
|
+
var setPageNumber = _useState4[1];
|
|
39
|
+
var _useState5 = useState(null),
|
|
40
|
+
_useState6 = _slicedToArray(_useState5, 2);
|
|
41
|
+
_useState6[0];
|
|
42
|
+
var setSelectedField = _useState6[1];
|
|
43
|
+
var _useState7 = useState(null),
|
|
44
|
+
_useState8 = _slicedToArray(_useState7, 2),
|
|
45
|
+
file = _useState8[0],
|
|
46
|
+
setFile = _useState8[1];
|
|
47
|
+
var _useState9 = useState(initialPdfPath || null),
|
|
48
|
+
_useState0 = _slicedToArray(_useState9, 2),
|
|
49
|
+
fileUrl = _useState0[0],
|
|
50
|
+
setFileUrl = _useState0[1];
|
|
51
|
+
var _useState1 = useState(null),
|
|
52
|
+
_useState10 = _slicedToArray(_useState1, 2),
|
|
53
|
+
jsonData = _useState10[0],
|
|
54
|
+
setJsonData = _useState10[1];
|
|
55
|
+
var _useState11 = useState(null),
|
|
56
|
+
_useState12 = _slicedToArray(_useState11, 2),
|
|
57
|
+
allowedPages = _useState12[0],
|
|
58
|
+
setAllowedPages = _useState12[1];
|
|
59
|
+
var pdfWrapperRef = useRef(null);
|
|
60
|
+
var _useState13 = useState([]),
|
|
61
|
+
_useState14 = _slicedToArray(_useState13, 2);
|
|
62
|
+
_useState14[0];
|
|
63
|
+
var setFlattenedFields = _useState14[1];
|
|
64
|
+
var _useState15 = useState(false),
|
|
65
|
+
_useState16 = _slicedToArray(_useState15, 2),
|
|
66
|
+
isLoading = _useState16[0],
|
|
67
|
+
setIsLoading = _useState16[1];
|
|
68
|
+
var _useState17 = useState(0),
|
|
69
|
+
_useState18 = _slicedToArray(_useState17, 2),
|
|
70
|
+
loadingProgress = _useState18[0],
|
|
71
|
+
setLoadingProgress = _useState18[1];
|
|
72
|
+
var _useState19 = useState(null),
|
|
73
|
+
_useState20 = _slicedToArray(_useState19, 2),
|
|
74
|
+
selectedBboxId = _useState20[0],
|
|
75
|
+
setSelectedBboxId = _useState20[1];
|
|
76
|
+
var _useState21 = useState(null),
|
|
77
|
+
_useState22 = _slicedToArray(_useState21, 2);
|
|
78
|
+
_useState22[0];
|
|
79
|
+
var setError = _useState22[1];
|
|
80
|
+
var _useState23 = useState(false),
|
|
81
|
+
_useState24 = _slicedToArray(_useState23, 2),
|
|
82
|
+
isFileLoaded = _useState24[0],
|
|
83
|
+
setIsFileLoaded = _useState24[1];
|
|
84
|
+
var _useState25 = useState("pdf"),
|
|
85
|
+
_useState26 = _slicedToArray(_useState25, 2),
|
|
86
|
+
activeTab = _useState26[0],
|
|
87
|
+
setActiveTab = _useState26[1];
|
|
88
|
+
var _useState27 = useState('checking'),
|
|
89
|
+
_useState28 = _slicedToArray(_useState27, 2);
|
|
90
|
+
_useState28[0];
|
|
91
|
+
var setBackendStatus = _useState28[1];
|
|
92
|
+
var _useState29 = useState(false),
|
|
93
|
+
_useState30 = _slicedToArray(_useState29, 2),
|
|
94
|
+
isDraggingOver = _useState30[0],
|
|
95
|
+
setIsDraggingOver = _useState30[1]; //NOSONAR
|
|
96
|
+
// Load initial JSON data if provided (for faster iteration without API calls)
|
|
97
|
+
useEffect(function () {
|
|
98
|
+
var _a;
|
|
99
|
+
if (initialJsonData) {
|
|
100
|
+
console.log('[Structura] Loading initial JSON data from props');
|
|
101
|
+
setJsonData(initialJsonData);
|
|
102
|
+
var pageCount = ((_a = initialJsonData.children) === null || _a === void 0 ? void 0 : _a.length) || 0;
|
|
103
|
+
setAllowedPages(Array.from({
|
|
104
|
+
length: pageCount
|
|
105
|
+
}, function (_, i) {
|
|
106
|
+
return i + 1;
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
}, [initialJsonData]);
|
|
110
|
+
useEffect(function () {
|
|
111
|
+
var handleDragOver = function handleDragOver(e) {
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
e.stopPropagation();
|
|
114
|
+
// If PDF viewer is visible and no file is loaded, activate drag indicator
|
|
115
|
+
if (!fileUrl && !isDraggingOver && activeTab === "pdf") {
|
|
116
|
+
setIsDraggingOver(true);
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
var handleDragEnter = function handleDragEnter(e) {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
e.stopPropagation();
|
|
122
|
+
// If PDF viewer is visible and no file is loaded, activate drag indicator
|
|
123
|
+
if (!fileUrl && !isDraggingOver && activeTab === "pdf") {
|
|
124
|
+
setIsDraggingOver(true);
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
var handleDragLeave = function handleDragLeave(e) {
|
|
128
|
+
e.preventDefault();
|
|
129
|
+
e.stopPropagation();
|
|
130
|
+
// Only deactivate if we're leaving the document
|
|
131
|
+
if (e.relatedTarget === null) {
|
|
132
|
+
setIsDraggingOver(false);
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
var handleDrop = function handleDrop(e) {
|
|
136
|
+
e.preventDefault();
|
|
137
|
+
e.stopPropagation();
|
|
138
|
+
setIsDraggingOver(false);
|
|
139
|
+
};
|
|
140
|
+
// Prevent the browser from automatically opening dropped files
|
|
141
|
+
document.addEventListener('dragover', handleDragOver);
|
|
142
|
+
document.addEventListener('dragenter', handleDragEnter);
|
|
143
|
+
document.addEventListener('dragleave', handleDragLeave);
|
|
144
|
+
document.addEventListener('drop', handleDrop);
|
|
145
|
+
return function () {
|
|
146
|
+
document.removeEventListener('dragover', handleDragOver);
|
|
147
|
+
document.removeEventListener('dragenter', handleDragEnter);
|
|
148
|
+
document.removeEventListener('dragleave', handleDragLeave);
|
|
149
|
+
document.removeEventListener('drop', handleDrop);
|
|
150
|
+
};
|
|
151
|
+
}, [fileUrl, isDraggingOver, activeTab]);
|
|
152
|
+
// Add useEffect to handle selected PDF from localStorage
|
|
153
|
+
useEffect(function () {
|
|
154
|
+
var handleSelectedPdf = /*#__PURE__*/function () {
|
|
155
|
+
var _ref2 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee() {
|
|
156
|
+
var selectedPdfStr, selectedPdf, fileDataStr, fileData, byteCharacters, byteNumbers, i, byteArray, blob, pdfFile, newFileUrl, response, _blob, _pdfFile, _fileDataStr, _fileData, _byteCharacters, _byteNumbers, _i, _byteArray, _blob2, _pdfFile2, _newFileUrl, _response, _blob3, _pdfFile3, _t, _t2, _t3;
|
|
157
|
+
return _regenerator().w(function (_context) {
|
|
158
|
+
while (1) switch (_context.n) {
|
|
159
|
+
case 0:
|
|
160
|
+
selectedPdfStr = localStorage.getItem('selectedPdf');
|
|
161
|
+
if (!selectedPdfStr) {
|
|
162
|
+
_context.n = 9;
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
_context.p = 1;
|
|
166
|
+
selectedPdf = JSON.parse(selectedPdfStr);
|
|
167
|
+
if (!(selectedPdf.path === 'user-uploaded')) {
|
|
168
|
+
_context.n = 2;
|
|
169
|
+
break;
|
|
170
|
+
}
|
|
171
|
+
// For user-uploaded files, retrieve from sessionStorage
|
|
172
|
+
fileDataStr = sessionStorage.getItem('pdfFileData');
|
|
173
|
+
if (fileDataStr) {
|
|
174
|
+
try {
|
|
175
|
+
// Restore the file from sessionStorage
|
|
176
|
+
fileData = JSON.parse(fileDataStr);
|
|
177
|
+
byteCharacters = atob(fileData.data);
|
|
178
|
+
byteNumbers = new Array(byteCharacters.length);
|
|
179
|
+
for (i = 0; i < byteCharacters.length; i++) {
|
|
180
|
+
byteNumbers[i] = byteCharacters.charCodeAt(i);
|
|
181
|
+
}
|
|
182
|
+
byteArray = new Uint8Array(byteNumbers);
|
|
183
|
+
blob = new Blob([byteArray], {
|
|
184
|
+
type: 'application/pdf'
|
|
185
|
+
});
|
|
186
|
+
pdfFile = new File([blob], fileData.name, {
|
|
187
|
+
type: 'application/pdf'
|
|
188
|
+
});
|
|
189
|
+
newFileUrl = URL.createObjectURL(blob);
|
|
190
|
+
setFile(pdfFile);
|
|
191
|
+
setFileUrl(newFileUrl);
|
|
192
|
+
setIsFileLoaded(true);
|
|
193
|
+
} catch (error) {
|
|
194
|
+
console.error('Error parsing PDF data from sessionStorage:', error);
|
|
195
|
+
setError('Failed to load the PDF file. Please try uploading again.');
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
setError('PDF data not found. Please upload the file again.');
|
|
199
|
+
}
|
|
200
|
+
_context.n = 6;
|
|
201
|
+
break;
|
|
202
|
+
case 2:
|
|
203
|
+
_context.p = 2;
|
|
204
|
+
_context.n = 3;
|
|
205
|
+
return fetch(selectedPdf.path);
|
|
206
|
+
case 3:
|
|
207
|
+
response = _context.v;
|
|
208
|
+
_context.n = 4;
|
|
209
|
+
return response.blob();
|
|
210
|
+
case 4:
|
|
211
|
+
_blob = _context.v;
|
|
212
|
+
_pdfFile = new File([_blob], selectedPdf.name, {
|
|
213
|
+
type: 'application/pdf'
|
|
214
|
+
}); // Set the file and URL
|
|
215
|
+
setFile(_pdfFile);
|
|
216
|
+
setFileUrl(URL.createObjectURL(_blob));
|
|
217
|
+
setIsFileLoaded(true);
|
|
218
|
+
_context.n = 6;
|
|
219
|
+
break;
|
|
220
|
+
case 5:
|
|
221
|
+
_context.p = 5;
|
|
222
|
+
_t = _context.v;
|
|
223
|
+
console.error('Error fetching PDF:', _t);
|
|
224
|
+
setError('Failed to load the PDF file. Please try again.');
|
|
225
|
+
case 6:
|
|
226
|
+
// Clear the localStorage
|
|
227
|
+
localStorage.removeItem('selectedPdf');
|
|
228
|
+
_context.n = 8;
|
|
229
|
+
break;
|
|
230
|
+
case 7:
|
|
231
|
+
_context.p = 7;
|
|
232
|
+
_t2 = _context.v;
|
|
233
|
+
console.error('Error loading selected PDF:', _t2);
|
|
234
|
+
setError('Failed to load selected PDF');
|
|
235
|
+
localStorage.removeItem('selectedPdf');
|
|
236
|
+
case 8:
|
|
237
|
+
_context.n = 14;
|
|
238
|
+
break;
|
|
239
|
+
case 9:
|
|
240
|
+
if (!initialPdfPath) {
|
|
241
|
+
_context.n = 14;
|
|
242
|
+
break;
|
|
243
|
+
}
|
|
244
|
+
if (!(initialPdfPath === 'user-uploaded')) {
|
|
245
|
+
_context.n = 10;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
// Same logic as above for retrieving from sessionStorage
|
|
249
|
+
_fileDataStr = sessionStorage.getItem('pdfFileData');
|
|
250
|
+
if (_fileDataStr) {
|
|
251
|
+
try {
|
|
252
|
+
_fileData = JSON.parse(_fileDataStr);
|
|
253
|
+
_byteCharacters = atob(_fileData.data);
|
|
254
|
+
_byteNumbers = new Array(_byteCharacters.length);
|
|
255
|
+
for (_i = 0; _i < _byteCharacters.length; _i++) {
|
|
256
|
+
_byteNumbers[_i] = _byteCharacters.charCodeAt(_i);
|
|
257
|
+
}
|
|
258
|
+
_byteArray = new Uint8Array(_byteNumbers);
|
|
259
|
+
_blob2 = new Blob([_byteArray], {
|
|
260
|
+
type: 'application/pdf'
|
|
261
|
+
});
|
|
262
|
+
_pdfFile2 = new File([_blob2], _fileData.name, {
|
|
263
|
+
type: 'application/pdf'
|
|
264
|
+
});
|
|
265
|
+
_newFileUrl = URL.createObjectURL(_blob2);
|
|
266
|
+
setFile(_pdfFile2);
|
|
267
|
+
setFileUrl(_newFileUrl);
|
|
268
|
+
setIsFileLoaded(true);
|
|
269
|
+
} catch (error) {
|
|
270
|
+
console.error('Error parsing PDF data from sessionStorage:', error);
|
|
271
|
+
setError('Failed to load the PDF file. Please try uploading again.');
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
setError('PDF data not found. Please upload the file again.');
|
|
275
|
+
}
|
|
276
|
+
_context.n = 14;
|
|
277
|
+
break;
|
|
278
|
+
case 10:
|
|
279
|
+
_context.p = 10;
|
|
280
|
+
_context.n = 11;
|
|
281
|
+
return fetch(initialPdfPath);
|
|
282
|
+
case 11:
|
|
283
|
+
_response = _context.v;
|
|
284
|
+
_context.n = 12;
|
|
285
|
+
return _response.blob();
|
|
286
|
+
case 12:
|
|
287
|
+
_blob3 = _context.v;
|
|
288
|
+
_pdfFile3 = new File([_blob3], 'document.pdf', {
|
|
289
|
+
type: 'application/pdf'
|
|
290
|
+
});
|
|
291
|
+
setFile(_pdfFile3);
|
|
292
|
+
setFileUrl(URL.createObjectURL(_blob3));
|
|
293
|
+
setIsFileLoaded(true);
|
|
294
|
+
_context.n = 14;
|
|
295
|
+
break;
|
|
296
|
+
case 13:
|
|
297
|
+
_context.p = 13;
|
|
298
|
+
_t3 = _context.v;
|
|
299
|
+
console.error('Error fetching PDF:', _t3);
|
|
300
|
+
setError("Failed to load the PDF file from ".concat(initialPdfPath, ". Please try again."));
|
|
301
|
+
case 14:
|
|
302
|
+
return _context.a(2);
|
|
303
|
+
}
|
|
304
|
+
}, _callee, null, [[10, 13], [2, 5], [1, 7]]);
|
|
305
|
+
}));
|
|
306
|
+
return function handleSelectedPdf() {
|
|
307
|
+
return _ref2.apply(this, arguments);
|
|
308
|
+
};
|
|
309
|
+
}();
|
|
310
|
+
handleSelectedPdf();
|
|
311
|
+
}, [initialPdfPath]);
|
|
312
|
+
// Simulate loading progress
|
|
313
|
+
useEffect(function () {
|
|
314
|
+
if (isLoading) {
|
|
315
|
+
var interval = setInterval(function () {
|
|
316
|
+
setLoadingProgress(function (prev) {
|
|
317
|
+
var newProgress = prev + 10;
|
|
318
|
+
if (newProgress >= 100) {
|
|
319
|
+
clearInterval(interval);
|
|
320
|
+
return 100;
|
|
321
|
+
}
|
|
322
|
+
return newProgress;
|
|
323
|
+
});
|
|
324
|
+
}, 300);
|
|
325
|
+
return function () {
|
|
326
|
+
return clearInterval(interval);
|
|
327
|
+
};
|
|
328
|
+
} else {
|
|
329
|
+
setLoadingProgress(0);
|
|
330
|
+
}
|
|
331
|
+
}, [isLoading]);
|
|
332
|
+
// Add logging to handleFileUpload
|
|
333
|
+
var handleFileUpload = function handleFileUpload(uploadedFile) {
|
|
334
|
+
// console.log("!!! [Structura] handleFileUpload called with file:", uploadedFile.name);
|
|
335
|
+
// console.log("!!! [Structura] File details:", {
|
|
336
|
+
// name: uploadedFile.name,
|
|
337
|
+
// type: uploadedFile.type,
|
|
338
|
+
// size: uploadedFile.size
|
|
339
|
+
// });
|
|
340
|
+
setFile(uploadedFile);
|
|
341
|
+
setFileUrl(URL.createObjectURL(uploadedFile));
|
|
342
|
+
setJsonData(null);
|
|
343
|
+
setAllowedPages(null);
|
|
344
|
+
setSelectedBboxId(null);
|
|
345
|
+
setIsFileLoaded(false);
|
|
346
|
+
setError(null);
|
|
347
|
+
setActiveTab("pdf");
|
|
348
|
+
// console.log("!!! [Structura] File upload state updated");
|
|
349
|
+
};
|
|
350
|
+
// Add logging to the useEffect that watches isFileLoaded
|
|
351
|
+
useEffect(function () {
|
|
352
|
+
// console.log("!!! [Structura] isFileLoaded changed:", isFileLoaded);
|
|
353
|
+
// Skip API call if we already have initialJsonData (cached mode)
|
|
354
|
+
if (isFileLoaded && !initialJsonData) {
|
|
355
|
+
// console.log("!!! [Structura] Calling handleGenerateJSON due to isFileLoaded");
|
|
356
|
+
handleGenerateJSON();
|
|
357
|
+
} else if (isFileLoaded && initialJsonData) {
|
|
358
|
+
console.log('[Structura] Skipping API call - using cached JSON data');
|
|
359
|
+
}
|
|
360
|
+
}, [isFileLoaded, initialJsonData]);
|
|
361
|
+
// Handle removing the PDF and resetting state
|
|
362
|
+
var handleRemovePDF = function handleRemovePDF() {
|
|
363
|
+
setFile(null);
|
|
364
|
+
setFileUrl(null);
|
|
365
|
+
setJsonData(null);
|
|
366
|
+
setAllowedPages(null);
|
|
367
|
+
setSelectedBboxId(null);
|
|
368
|
+
setIsFileLoaded(false);
|
|
369
|
+
setNumPages(null);
|
|
370
|
+
setPageNumber(1);
|
|
371
|
+
setSelectedField(null);
|
|
372
|
+
setFlattenedFields([]);
|
|
373
|
+
setError(null);
|
|
374
|
+
};
|
|
375
|
+
var handleGenerateJSON = /*#__PURE__*/function () {
|
|
376
|
+
var _ref3 = _asyncToGenerator(/*#__PURE__*/_regenerator().m(function _callee2() {
|
|
377
|
+
var formData, submitResponse, errorData, requestId, resultData, resultResponse, processedData, errorMessage, _t4;
|
|
378
|
+
return _regenerator().w(function (_context2) {
|
|
379
|
+
while (1) switch (_context2.n) {
|
|
380
|
+
case 0:
|
|
381
|
+
if (!(!isFileLoaded || !file)) {
|
|
382
|
+
_context2.n = 1;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
return _context2.a(2);
|
|
386
|
+
case 1:
|
|
387
|
+
setIsLoading(true);
|
|
388
|
+
setLoadingProgress(0);
|
|
389
|
+
_context2.p = 2;
|
|
390
|
+
// Send the PDF file as FormData to the API route
|
|
391
|
+
formData = new FormData();
|
|
392
|
+
formData.append("file", file);
|
|
393
|
+
// console.log("!!! [Structura] FormData:", formData);
|
|
394
|
+
if (props === null || props === void 0 ? void 0 : props.APIKey) {
|
|
395
|
+
_context2.n = 3;
|
|
396
|
+
break;
|
|
397
|
+
}
|
|
398
|
+
throw new Error("API key is required but not provided");
|
|
399
|
+
case 3:
|
|
400
|
+
_context2.n = 4;
|
|
401
|
+
return POST(formData, {
|
|
402
|
+
apiKey: props.APIKey,
|
|
403
|
+
baseUrl: props.baseUrl
|
|
404
|
+
});
|
|
405
|
+
case 4:
|
|
406
|
+
submitResponse = _context2.v;
|
|
407
|
+
console.log("API response status:", submitResponse.status);
|
|
408
|
+
if (!(submitResponse.status !== 200)) {
|
|
409
|
+
_context2.n = 7;
|
|
410
|
+
break;
|
|
411
|
+
}
|
|
412
|
+
errorData = submitResponse;
|
|
413
|
+
console.error("Submission error details:", errorData);
|
|
414
|
+
if (!(submitResponse.status === 503)) {
|
|
415
|
+
_context2.n = 5;
|
|
416
|
+
break;
|
|
417
|
+
}
|
|
418
|
+
throw new Error("Backend connection error: ".concat(errorData.details || "Could not connect to backend service"));
|
|
419
|
+
case 5:
|
|
420
|
+
if (!(submitResponse.status === 401)) {
|
|
421
|
+
_context2.n = 6;
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
throw new Error("Authentication error: Invalid API key. Please check your API key.");
|
|
425
|
+
case 6:
|
|
426
|
+
throw new Error("Failed to submit PDF: ".concat(errorData.error || "Unknown error"));
|
|
427
|
+
case 7:
|
|
428
|
+
setLoadingProgress(50);
|
|
429
|
+
requestId = submitResponse.data.request_id; // Poll for result every 2 seconds
|
|
430
|
+
resultData = null;
|
|
431
|
+
case 8:
|
|
432
|
+
_context2.n = 9;
|
|
433
|
+
return GET(requestId, {
|
|
434
|
+
apiKey: props.APIKey,
|
|
435
|
+
baseUrl: props.baseUrl
|
|
436
|
+
});
|
|
437
|
+
case 9:
|
|
438
|
+
resultResponse = _context2.v;
|
|
439
|
+
if (!(resultResponse.data.status === "completed")) {
|
|
440
|
+
_context2.n = 10;
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
// Store the response data
|
|
444
|
+
resultData = resultResponse.data;
|
|
445
|
+
// console.log("!!! [Structura] ResultData:", resultData.result);
|
|
446
|
+
return _context2.a(3, 12);
|
|
447
|
+
case 10:
|
|
448
|
+
// if (pollCount > 60) { // Timeout after 2 minutes
|
|
449
|
+
// throw new Error("Polling timed out. Please try again later.");
|
|
450
|
+
// }
|
|
451
|
+
_context2.n = 11;
|
|
452
|
+
return new Promise(function (res) {
|
|
453
|
+
return setTimeout(res, 2000);
|
|
454
|
+
});
|
|
455
|
+
case 11:
|
|
456
|
+
_context2.n = 8;
|
|
457
|
+
break;
|
|
458
|
+
case 12:
|
|
459
|
+
// Now validate the data format after polling is complete
|
|
460
|
+
// if (resultData) {
|
|
461
|
+
// // Zod validation
|
|
462
|
+
// const parseResult = DocumentOutputSchema.safeParse(resultData);
|
|
463
|
+
// if (!parseResult.success) {
|
|
464
|
+
// // Handle validation errors
|
|
465
|
+
// console.error("Invalid data format from server:", parseResult.error);
|
|
466
|
+
// setError("Invalid data format from server. Please check console for details.");
|
|
467
|
+
// setIsLoading(false);
|
|
468
|
+
// return;
|
|
469
|
+
// }
|
|
470
|
+
// resultData = parseResult.data;
|
|
471
|
+
// }
|
|
472
|
+
setLoadingProgress(90);
|
|
473
|
+
processedData = preprocessData(resultData); // console.log("!!! [Structura] ProcessedData:", processedData);
|
|
474
|
+
setJsonData(processedData.result);
|
|
475
|
+
setActiveTab("html");
|
|
476
|
+
_context2.n = 14;
|
|
477
|
+
break;
|
|
478
|
+
case 13:
|
|
479
|
+
_context2.p = 13;
|
|
480
|
+
_t4 = _context2.v;
|
|
481
|
+
console.error("Error processing PDF:", _t4);
|
|
482
|
+
errorMessage = _t4 instanceof Error ? _t4.message : "Failed to process PDF";
|
|
483
|
+
setError("".concat(errorMessage, ". ").concat(_t4.toString().includes("Backend connection") ? "Backend is unavailable." : "Please try again."));
|
|
484
|
+
setBackendStatus('offline');
|
|
485
|
+
setJsonData(null);
|
|
486
|
+
case 14:
|
|
487
|
+
_context2.p = 14;
|
|
488
|
+
setLoadingProgress(100);
|
|
489
|
+
setTimeout(function () {
|
|
490
|
+
setIsLoading(false);
|
|
491
|
+
}, 300);
|
|
492
|
+
return _context2.f(14);
|
|
493
|
+
case 15:
|
|
494
|
+
return _context2.a(2);
|
|
495
|
+
}
|
|
496
|
+
}, _callee2, null, [[2, 13, 14, 15]]);
|
|
497
|
+
}));
|
|
498
|
+
return function handleGenerateJSON() {
|
|
499
|
+
return _ref3.apply(this, arguments);
|
|
500
|
+
};
|
|
501
|
+
}();
|
|
502
|
+
// Handle click on HTML element in the right panel
|
|
503
|
+
var handleHtmlNodeClick = function handleHtmlNodeClick(nodeId) {
|
|
504
|
+
// console.log(`[PdfHighlighter] HTML Node clicked: ${nodeId}`);
|
|
505
|
+
setSelectedBboxId(nodeId);
|
|
506
|
+
// PDF scrolling will be handled by the useEffect below
|
|
507
|
+
};
|
|
508
|
+
// Handler for when a bbox is clicked in the PDF viewer
|
|
509
|
+
var handlePdfBboxClicked = function handlePdfBboxClicked(blockId) {
|
|
510
|
+
// console.log(`[PdfHighlighter] PDF Bbox clicked: ${blockId}`);
|
|
511
|
+
setSelectedBboxId(blockId);
|
|
512
|
+
// HTML scrolling is handled by HtmlViewer's own useEffect
|
|
513
|
+
};
|
|
514
|
+
// Effect to scroll PDF page into view when selectedBboxId changes
|
|
515
|
+
useEffect(function () {
|
|
516
|
+
if (!selectedBboxId || !jsonData || !jsonData.children || !pdfWrapperRef.current) {
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
var findPageOfBlock = function findPageOfBlock(blockIdToFind, documentData) {
|
|
520
|
+
if (!documentData || !documentData.children) return null;
|
|
521
|
+
var _loop = function _loop() {
|
|
522
|
+
var pageBlock = documentData.children[i];
|
|
523
|
+
if (pageBlock.block_type === "Page") {
|
|
524
|
+
// Check if the pageBlock itself is the target
|
|
525
|
+
if (pageBlock.id === blockIdToFind) {
|
|
526
|
+
return {
|
|
527
|
+
v: i + 1
|
|
528
|
+
}; // Page numbers are 1-indexed
|
|
529
|
+
}
|
|
530
|
+
// Recursively search within this page's children
|
|
531
|
+
var _blockExistsInPage = function blockExistsInPage(currentBlock) {
|
|
532
|
+
if (currentBlock.id === blockIdToFind) return true;
|
|
533
|
+
if (currentBlock.children) {
|
|
534
|
+
var _iterator = _createForOfIteratorHelper(currentBlock.children),
|
|
535
|
+
_step;
|
|
536
|
+
try {
|
|
537
|
+
for (_iterator.s(); !(_step = _iterator.n()).done;) {
|
|
538
|
+
var child = _step.value;
|
|
539
|
+
if (_blockExistsInPage(child)) return true;
|
|
540
|
+
}
|
|
541
|
+
} catch (err) {
|
|
542
|
+
_iterator.e(err);
|
|
543
|
+
} finally {
|
|
544
|
+
_iterator.f();
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return false;
|
|
548
|
+
};
|
|
549
|
+
if (_blockExistsInPage(pageBlock)) {
|
|
550
|
+
return {
|
|
551
|
+
v: i + 1
|
|
552
|
+
}; // Page numbers are 1-indexed
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
},
|
|
556
|
+
_ret;
|
|
557
|
+
for (var i = 0; i < documentData.children.length; i++) {
|
|
558
|
+
_ret = _loop();
|
|
559
|
+
if (_ret) return _ret.v;
|
|
560
|
+
}
|
|
561
|
+
return null;
|
|
562
|
+
};
|
|
563
|
+
var pageNumWithSelectedBlock = findPageOfBlock(selectedBboxId, jsonData);
|
|
564
|
+
if (pageNumWithSelectedBlock !== null) {
|
|
565
|
+
// console.log(`[PdfHighlighter] Selected bbox ${selectedBboxId} found on page ${pageNumWithSelectedBlock}. Scrolling PDF page.`);
|
|
566
|
+
var pageElementId = "pdf-page-container-".concat(pageNumWithSelectedBlock);
|
|
567
|
+
var pageElement = document.getElementById(pageElementId); // Check if element exists before timeout
|
|
568
|
+
if (pageElement) {
|
|
569
|
+
// console.log(`[PdfHighlighter] Scheduling scroll for PDF Page element ${pageElementId}`);
|
|
570
|
+
setTimeout(function () {
|
|
571
|
+
var el = document.getElementById(pageElementId); // Re-fetch element in timeout
|
|
572
|
+
if (el) {
|
|
573
|
+
// console.log(`[PdfHighlighter] Timeout: Scrolling to PDF Page element ${el.id} (align to top)`);
|
|
574
|
+
el.scrollIntoView(true); // Align to top, auto behavior
|
|
575
|
+
} else {
|
|
576
|
+
console.warn("[PdfHighlighter] Timeout: PDF Page element ".concat(pageElementId, " not found at time of scroll."));
|
|
577
|
+
}
|
|
578
|
+
}, 0); // Small delay
|
|
579
|
+
} else {
|
|
580
|
+
console.warn("[PdfHighlighter] PDF Page element ".concat(pageElementId, " not found for scheduling scroll."));
|
|
581
|
+
}
|
|
582
|
+
} else {
|
|
583
|
+
console.log("[PdfHighlighter] Selected bbox ".concat(selectedBboxId, " not found in any page or jsonData not structured as expected."));
|
|
584
|
+
}
|
|
585
|
+
}, [selectedBboxId, jsonData, pdfWrapperRef]);
|
|
586
|
+
// Determine which pages to render
|
|
587
|
+
var pagesToRender = [];
|
|
588
|
+
if (numPages) {
|
|
589
|
+
if (allowedPages && allowedPages.length > 0) {
|
|
590
|
+
pagesToRender = allowedPages.filter(function (p) {
|
|
591
|
+
return p >= 1 && p <= numPages;
|
|
592
|
+
});
|
|
593
|
+
} else {
|
|
594
|
+
pagesToRender = Array.from({
|
|
595
|
+
length: numPages
|
|
596
|
+
}, function (_, i) {
|
|
597
|
+
return i + 1;
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
return jsxs("div", {
|
|
602
|
+
className: "h-screen max-h-screen flex flex-col bg-background text-foreground",
|
|
603
|
+
children: [jsx("header", {
|
|
604
|
+
className: "border-b border-border bg-card p-4",
|
|
605
|
+
children: jsxs("div", {
|
|
606
|
+
className: "container mx-auto flex justify-between items-center",
|
|
607
|
+
children: [jsxs("div", {
|
|
608
|
+
className: "flex items-center space-x-2",
|
|
609
|
+
children: [jsx(LucideIcons.FileText, {
|
|
610
|
+
className: "h-6 w-6 text-primary"
|
|
611
|
+
}), jsx("h1", {
|
|
612
|
+
className: "text-2xl mt-2.5 font-bold",
|
|
613
|
+
children: "PLAYGROUND"
|
|
614
|
+
})]
|
|
615
|
+
}), jsx("div", {
|
|
616
|
+
className: "flex items-center gap-2",
|
|
617
|
+
children: jsx(Badge, {
|
|
618
|
+
variant: "outline",
|
|
619
|
+
className: "px-3 py-1 text-xs",
|
|
620
|
+
children: isFileLoaded ? "Document Loaded" : "No Document"
|
|
621
|
+
})
|
|
622
|
+
})]
|
|
623
|
+
})
|
|
624
|
+
}), jsx("div", {
|
|
625
|
+
className: "md:hidden",
|
|
626
|
+
children: jsxs(Tabs, {
|
|
627
|
+
value: activeTab,
|
|
628
|
+
onValueChange: setActiveTab,
|
|
629
|
+
className: "w-full",
|
|
630
|
+
children: [jsxs(TabsList, {
|
|
631
|
+
className: "grid w-full grid-cols-2",
|
|
632
|
+
children: [jsxs(TabsTrigger, {
|
|
633
|
+
value: "pdf",
|
|
634
|
+
className: "flex items-center gap-2",
|
|
635
|
+
children: [jsx(LucideIcons.FileText, {
|
|
636
|
+
className: "h-4 w-4"
|
|
637
|
+
}), "PDF View"]
|
|
638
|
+
}), jsxs(TabsTrigger, {
|
|
639
|
+
value: "html",
|
|
640
|
+
className: "flex items-center gap-2",
|
|
641
|
+
children: [jsx(LucideIcons.FileText, {
|
|
642
|
+
className: "h-4 w-4"
|
|
643
|
+
}), "HTML View"]
|
|
644
|
+
})]
|
|
645
|
+
}), jsx(TabsContent, {
|
|
646
|
+
value: "pdf",
|
|
647
|
+
className: "p-0 border-0",
|
|
648
|
+
children: jsx("div", {
|
|
649
|
+
ref: pdfWrapperRef,
|
|
650
|
+
className: "h-[calc(100vh-220px)] overflow-auto",
|
|
651
|
+
children: jsx(ScrollArea, {
|
|
652
|
+
className: "w-full h-[calc(100vh-220px)]",
|
|
653
|
+
children: fileUrl ? jsx(PdfDocumentViewer, {
|
|
654
|
+
fileUrl: fileUrl,
|
|
655
|
+
allowedPages: pagesToRender,
|
|
656
|
+
onLoadSuccess: function onLoadSuccess(num) {
|
|
657
|
+
// console.log("!!! PDF loaded successfully, numPages:", num);
|
|
658
|
+
setNumPages(num);
|
|
659
|
+
// console.log("!!! Setting isFileLoaded to true");
|
|
660
|
+
setIsFileLoaded(true);
|
|
661
|
+
},
|
|
662
|
+
onFileUpload: handleFileUpload,
|
|
663
|
+
onRemovePDF: handleRemovePDF,
|
|
664
|
+
jsonData: jsonData,
|
|
665
|
+
selectedBboxId: selectedBboxId,
|
|
666
|
+
onPdfBboxClick: handlePdfBboxClicked
|
|
667
|
+
}) : jsx("div", {
|
|
668
|
+
className: "min-h-full w-full flex flex-col items-center justify-center p-8 text-center transition-all duration-200 ".concat(isDraggingOver ? 'bg-primary/10 border-2 border-dashed border-primary' : 'bg-muted/50'),
|
|
669
|
+
onDragOver: function onDragOver(e) {
|
|
670
|
+
e.preventDefault();
|
|
671
|
+
e.stopPropagation();
|
|
672
|
+
setIsDraggingOver(true);
|
|
673
|
+
},
|
|
674
|
+
onDragLeave: function onDragLeave(e) {
|
|
675
|
+
e.preventDefault();
|
|
676
|
+
e.stopPropagation();
|
|
677
|
+
setIsDraggingOver(false);
|
|
678
|
+
},
|
|
679
|
+
onDrop: function onDrop(e) {
|
|
680
|
+
e.preventDefault();
|
|
681
|
+
e.stopPropagation();
|
|
682
|
+
setIsDraggingOver(false);
|
|
683
|
+
// console.log("!!! File drop event triggered");
|
|
684
|
+
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
685
|
+
// If multiple files were dropped, show an error
|
|
686
|
+
if (e.dataTransfer.files.length > 1) {
|
|
687
|
+
// console.log("!!! Multiple files dropped - showing error");
|
|
688
|
+
setError('Please upload only one PDF file at a time');
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
var _file = e.dataTransfer.files[0];
|
|
692
|
+
// console.log("!!! Dropped file type:", file.type);
|
|
693
|
+
if (_file.type === 'application/pdf') {
|
|
694
|
+
// console.log("!!! Valid PDF file dropped:", file.name);
|
|
695
|
+
handleFileUpload(_file);
|
|
696
|
+
} else {
|
|
697
|
+
// console.log("!!! Invalid file type dropped");
|
|
698
|
+
setError("Invalid file type: ".concat(_file.name, ". Please upload a PDF file only."));
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
},
|
|
702
|
+
children: jsxs("div", {
|
|
703
|
+
className: "max-w-md mx-auto flex flex-col items-center",
|
|
704
|
+
children: [jsx("div", {
|
|
705
|
+
className: "w-24 h-24 border-2 border-dashed rounded-full flex items-center justify-center mb-6 transition-all duration-200 ".concat(isDraggingOver ? 'border-primary bg-primary/5 scale-110' : 'border-muted-foreground/50'),
|
|
706
|
+
children: jsx(LucideIcons.Upload, {
|
|
707
|
+
className: "h-12 w-12 transition-colors duration-200 ".concat(isDraggingOver ? 'text-primary' : 'text-muted-foreground')
|
|
708
|
+
})
|
|
709
|
+
}), jsx("h3", {
|
|
710
|
+
className: "text-xl font-medium mb-4",
|
|
711
|
+
children: isDraggingOver ? 'Release to Upload PDF' : 'Drop PDF Here or Click to Upload'
|
|
712
|
+
}), jsx("p", {
|
|
713
|
+
className: "text-muted-foreground mb-6",
|
|
714
|
+
children: isDraggingOver ? 'Let go to start processing your document' : 'Drag and drop your PDF document here, or click the button below to browse files'
|
|
715
|
+
}), jsxs(Button, {
|
|
716
|
+
onClick: function onClick() {
|
|
717
|
+
var _a;
|
|
718
|
+
return (_a = document.getElementById('pdf-upload')) === null || _a === void 0 ? void 0 : _a.click();
|
|
719
|
+
},
|
|
720
|
+
className: "flex items-center gap-2",
|
|
721
|
+
size: "lg",
|
|
722
|
+
children: ["Upload Document ", jsx(LucideIcons.Upload, {
|
|
723
|
+
className: "h-4 w-4 ml-1"
|
|
724
|
+
})]
|
|
725
|
+
}), jsx("input", {
|
|
726
|
+
type: "file",
|
|
727
|
+
id: "pdf-upload",
|
|
728
|
+
accept: ".pdf",
|
|
729
|
+
className: "hidden",
|
|
730
|
+
onChange: function onChange(e) {
|
|
731
|
+
var _a;
|
|
732
|
+
// console.log("!!! File input onChange triggered");
|
|
733
|
+
if ((_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0]) {
|
|
734
|
+
// console.log("!!! File selected from input:", e.target.files[0].name);
|
|
735
|
+
handleFileUpload(e.target.files[0]);
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}), jsx("p", {
|
|
739
|
+
className: "text-xs text-muted-foreground mt-4",
|
|
740
|
+
children: "Supported format: PDF only"
|
|
741
|
+
})]
|
|
742
|
+
})
|
|
743
|
+
})
|
|
744
|
+
})
|
|
745
|
+
})
|
|
746
|
+
}), jsx(TabsContent, {
|
|
747
|
+
value: "html",
|
|
748
|
+
className: "p-0 border-0",
|
|
749
|
+
children: jsx("div", {
|
|
750
|
+
className: "h-[calc(100vh-220px)]",
|
|
751
|
+
children: jsx(HtmlViewer, {
|
|
752
|
+
jsonData: jsonData,
|
|
753
|
+
selectedBboxId: selectedBboxId,
|
|
754
|
+
isLoading: isLoading,
|
|
755
|
+
onNodeClick: handleHtmlNodeClick,
|
|
756
|
+
onSave: props.onSave
|
|
757
|
+
})
|
|
758
|
+
})
|
|
759
|
+
})]
|
|
760
|
+
})
|
|
761
|
+
}), jsx("div", {
|
|
762
|
+
className: "hidden md:block flex-1 overflow-hidden",
|
|
763
|
+
children: jsxs(PanelGroup, {
|
|
764
|
+
direction: "horizontal",
|
|
765
|
+
className: "h-full",
|
|
766
|
+
children: [jsx(Panel, {
|
|
767
|
+
minSize: 20,
|
|
768
|
+
defaultSize: 50,
|
|
769
|
+
children: jsxs(Card, {
|
|
770
|
+
className: "h-full border-0 rounded-none",
|
|
771
|
+
children: [jsx(CardHeader, {
|
|
772
|
+
className: "py-3 px-4 border-b bg-muted/30",
|
|
773
|
+
children: jsxs(CardTitle, {
|
|
774
|
+
className: "text-base flex items-center gap-2",
|
|
775
|
+
children: [jsx(LucideIcons.FileText, {
|
|
776
|
+
className: "h-4 w-4"
|
|
777
|
+
}), "PDF Document", file && jsx(Badge, {
|
|
778
|
+
variant: "secondary",
|
|
779
|
+
className: "ml-2",
|
|
780
|
+
children: file.name
|
|
781
|
+
})]
|
|
782
|
+
})
|
|
783
|
+
}), jsx(CardContent, {
|
|
784
|
+
className: "p-0 flex-1 flex flex-col overflow-hidden",
|
|
785
|
+
children: jsx(ScrollArea, {
|
|
786
|
+
className: "w-full h-[calc(100vh-220px)]",
|
|
787
|
+
children: fileUrl ? jsx(PdfDocumentViewer, {
|
|
788
|
+
fileUrl: fileUrl,
|
|
789
|
+
allowedPages: pagesToRender,
|
|
790
|
+
onLoadSuccess: function onLoadSuccess(num) {
|
|
791
|
+
// console.log("!!! PDF loaded successfully, numPages:", num);
|
|
792
|
+
setNumPages(num);
|
|
793
|
+
// console.log("!!! Setting isFileLoaded to true");
|
|
794
|
+
setIsFileLoaded(true);
|
|
795
|
+
},
|
|
796
|
+
onFileUpload: handleFileUpload,
|
|
797
|
+
onRemovePDF: handleRemovePDF,
|
|
798
|
+
jsonData: jsonData,
|
|
799
|
+
selectedBboxId: selectedBboxId,
|
|
800
|
+
onPdfBboxClick: handlePdfBboxClicked
|
|
801
|
+
}) : jsx("div", {
|
|
802
|
+
className: "min-h-full w-full flex flex-col items-center justify-center p-8 text-center transition-all duration-200 ".concat(isDraggingOver ? 'bg-primary/10 border-2 border-dashed border-primary' : 'bg-muted/50'),
|
|
803
|
+
onDragOver: function onDragOver(e) {
|
|
804
|
+
e.preventDefault();
|
|
805
|
+
e.stopPropagation();
|
|
806
|
+
setIsDraggingOver(true);
|
|
807
|
+
},
|
|
808
|
+
onDragLeave: function onDragLeave(e) {
|
|
809
|
+
e.preventDefault();
|
|
810
|
+
e.stopPropagation();
|
|
811
|
+
setIsDraggingOver(false);
|
|
812
|
+
},
|
|
813
|
+
onDrop: function onDrop(e) {
|
|
814
|
+
e.preventDefault();
|
|
815
|
+
e.stopPropagation();
|
|
816
|
+
setIsDraggingOver(false);
|
|
817
|
+
// console.log("!!! File drop event triggered");
|
|
818
|
+
if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
|
|
819
|
+
// If multiple files were dropped, show an error
|
|
820
|
+
if (e.dataTransfer.files.length > 1) {
|
|
821
|
+
// console.log("!!! Multiple files dropped - showing error");
|
|
822
|
+
setError('Please upload only one PDF file at a time');
|
|
823
|
+
return;
|
|
824
|
+
}
|
|
825
|
+
var _file2 = e.dataTransfer.files[0];
|
|
826
|
+
// console.log("!!! Dropped file type:", file.type);
|
|
827
|
+
if (_file2.type === 'application/pdf') {
|
|
828
|
+
// console.log("!!! Valid PDF file dropped:", file.name);
|
|
829
|
+
handleFileUpload(_file2);
|
|
830
|
+
} else {
|
|
831
|
+
// console.log("!!! Invalid file type dropped");
|
|
832
|
+
setError("Invalid file type: ".concat(_file2.name, ". Please upload a PDF file only."));
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
},
|
|
836
|
+
children: jsxs("div", {
|
|
837
|
+
className: "max-w-md mx-auto flex flex-col items-center",
|
|
838
|
+
children: [jsx("div", {
|
|
839
|
+
className: "w-24 h-24 border-2 border-dashed rounded-full flex items-center justify-center mb-6 transition-all duration-200 ".concat(isDraggingOver ? 'border-primary bg-primary/5 scale-110' : 'border-muted-foreground/50'),
|
|
840
|
+
children: jsx(LucideIcons.Upload, {
|
|
841
|
+
className: "h-12 w-12 transition-colors duration-200 ".concat(isDraggingOver ? 'text-primary' : 'text-muted-foreground')
|
|
842
|
+
})
|
|
843
|
+
}), jsx("h3", {
|
|
844
|
+
className: "text-xl font-medium mb-4",
|
|
845
|
+
children: isDraggingOver ? 'Release to Upload PDF' : 'Drop PDF Here or Click to Upload'
|
|
846
|
+
}), jsx("p", {
|
|
847
|
+
className: "text-muted-foreground mb-6",
|
|
848
|
+
children: isDraggingOver ? 'Let go to start processing your document' : 'Drag and drop your PDF document here, or click the button below to browse files'
|
|
849
|
+
}), jsxs(Button, {
|
|
850
|
+
onClick: function onClick() {
|
|
851
|
+
var _a;
|
|
852
|
+
return (_a = document.getElementById('pdf-upload')) === null || _a === void 0 ? void 0 : _a.click();
|
|
853
|
+
},
|
|
854
|
+
className: "flex items-center gap-2",
|
|
855
|
+
size: "lg",
|
|
856
|
+
children: ["Upload Document ", jsx(LucideIcons.Upload, {
|
|
857
|
+
className: "h-4 w-4 ml-1"
|
|
858
|
+
})]
|
|
859
|
+
}), jsx("input", {
|
|
860
|
+
type: "file",
|
|
861
|
+
id: "pdf-upload",
|
|
862
|
+
accept: ".pdf",
|
|
863
|
+
className: "hidden",
|
|
864
|
+
onChange: function onChange(e) {
|
|
865
|
+
var _a;
|
|
866
|
+
// console.log("!!! File input onChange triggered");
|
|
867
|
+
if ((_a = e.target.files) === null || _a === void 0 ? void 0 : _a[0]) {
|
|
868
|
+
// console.log("!!! File selected from input:", e.target.files[0].name);
|
|
869
|
+
handleFileUpload(e.target.files[0]);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}), jsx("p", {
|
|
873
|
+
className: "text-xs text-muted-foreground mt-4",
|
|
874
|
+
children: "Supported format: PDF only"
|
|
875
|
+
})]
|
|
876
|
+
})
|
|
877
|
+
})
|
|
878
|
+
})
|
|
879
|
+
})]
|
|
880
|
+
})
|
|
881
|
+
}), jsx(PanelResizeHandle, {
|
|
882
|
+
className: "w-1.5 bg-black hover:bg-primary/20 transition-colors cursor-col-resize"
|
|
883
|
+
}), jsx(Panel, {
|
|
884
|
+
minSize: 20,
|
|
885
|
+
defaultSize: 50,
|
|
886
|
+
children: jsxs(Card, {
|
|
887
|
+
className: "h-full border-0 rounded-none",
|
|
888
|
+
children: [jsx(CardHeader, {
|
|
889
|
+
className: "py-3 px-4 border-b bg-muted/30",
|
|
890
|
+
children: jsxs(CardTitle, {
|
|
891
|
+
className: "text-base flex items-center gap-2",
|
|
892
|
+
children: [jsx(LucideIcons.FileText, {
|
|
893
|
+
className: "h-4 w-4"
|
|
894
|
+
}), "HTML Structure"]
|
|
895
|
+
})
|
|
896
|
+
}), jsx(CardContent, {
|
|
897
|
+
className: "p-0 h-[calc(100%-56px)] relative overflow-hidden",
|
|
898
|
+
children: jsx("div", {
|
|
899
|
+
className: "absolute inset-0",
|
|
900
|
+
children: jsonData ? jsx(HtmlViewer, {
|
|
901
|
+
jsonData: jsonData,
|
|
902
|
+
selectedBboxId: selectedBboxId,
|
|
903
|
+
isLoading: isLoading,
|
|
904
|
+
onNodeClick: handleHtmlNodeClick,
|
|
905
|
+
onSave: props.onSave
|
|
906
|
+
}) : jsx("div", {
|
|
907
|
+
className: "flex flex-col items-center justify-center h-full p-8 text-center",
|
|
908
|
+
children: jsxs("div", {
|
|
909
|
+
className: "bg-muted/50 p-8 rounded-lg flex flex-col items-center",
|
|
910
|
+
children: [jsx(LucideIcons.Upload, {
|
|
911
|
+
className: "h-12 w-12 text-muted-foreground mb-4"
|
|
912
|
+
}), jsx("h3", {
|
|
913
|
+
className: "text-lg font-medium mb-2",
|
|
914
|
+
children: "No Data Available"
|
|
915
|
+
}), jsx("p", {
|
|
916
|
+
className: "text-muted-foreground mb-4",
|
|
917
|
+
children: "First upload a PDF document, then generate the HTML structure"
|
|
918
|
+
})]
|
|
919
|
+
})
|
|
920
|
+
})
|
|
921
|
+
})
|
|
922
|
+
})]
|
|
923
|
+
})
|
|
924
|
+
})]
|
|
925
|
+
})
|
|
926
|
+
}), isLoading && jsx("div", {
|
|
927
|
+
className: "fixed bottom-0 left-0 right-0 bg-background border-t border-border p-4 z-50",
|
|
928
|
+
children: jsx("div", {
|
|
929
|
+
className: "container mx-auto",
|
|
930
|
+
children: jsxs("div", {
|
|
931
|
+
className: "flex flex-col gap-2",
|
|
932
|
+
children: [jsxs("div", {
|
|
933
|
+
className: "flex items-center justify-between",
|
|
934
|
+
children: [jsx("span", {
|
|
935
|
+
className: "text-sm font-medium",
|
|
936
|
+
children: "Processing document..."
|
|
937
|
+
}), jsxs("span", {
|
|
938
|
+
className: "text-sm text-muted-foreground",
|
|
939
|
+
children: [loadingProgress, "%"]
|
|
940
|
+
})]
|
|
941
|
+
}), jsx(Progress, {
|
|
942
|
+
value: loadingProgress,
|
|
943
|
+
className: "h-2"
|
|
944
|
+
})]
|
|
945
|
+
})
|
|
946
|
+
})
|
|
947
|
+
})]
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
export { Structura as default };
|