@tfw.in/structura-lib 0.2.0 → 0.2.2

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 (49) hide show
  1. package/README.md +72 -323
  2. package/dist/cjs/EditableContent.js +46 -18
  3. package/dist/cjs/HtmlViewer.js +238 -85
  4. package/dist/cjs/MathRenderer.js +88 -0
  5. package/dist/cjs/PdfDocumentViewer.js +1 -1
  6. package/dist/cjs/SemanticTagParser.js +189 -0
  7. package/dist/cjs/SemanticTagRenderer.js +135 -0
  8. package/dist/cjs/Structura.js +49 -76
  9. package/dist/cjs/Table.js +75 -8
  10. package/dist/cjs/TableCell.js +34 -10
  11. package/dist/cjs/index.js +12 -0
  12. package/dist/cjs/node_modules/react-icons/fa/index.esm.js +6 -0
  13. package/dist/cjs/styles.css +2 -4
  14. package/dist/cjs/styles.css.map +1 -1
  15. package/dist/esm/EditableContent.js +51 -19
  16. package/dist/esm/HtmlViewer.js +287 -103
  17. package/dist/esm/MathRenderer.js +85 -0
  18. package/dist/esm/PdfDocumentViewer.js +1 -1
  19. package/dist/esm/SemanticTagParser.js +187 -0
  20. package/dist/esm/SemanticTagRenderer.js +140 -0
  21. package/dist/esm/Structura.js +57 -80
  22. package/dist/esm/Table.js +85 -8
  23. package/dist/esm/TableCell.js +34 -6
  24. package/dist/esm/index.js +3 -0
  25. package/dist/esm/node_modules/react-icons/fa/index.esm.js +5 -1
  26. package/dist/esm/styles.css +2 -4
  27. package/dist/esm/styles.css.map +1 -1
  28. package/dist/esm/types/DocumentOutline.d.ts +7 -0
  29. package/dist/esm/types/EditableContent.d.ts +8 -1
  30. package/dist/esm/types/HtmlViewer.d.ts +9 -2
  31. package/dist/esm/types/MathRenderer.d.ts +25 -0
  32. package/dist/esm/types/SemanticTagParser.d.ts +33 -0
  33. package/dist/esm/types/SemanticTagRenderer.d.ts +17 -0
  34. package/dist/esm/types/Structura.d.ts +13 -8
  35. package/dist/esm/types/Table.d.ts +4 -1
  36. package/dist/esm/types/TableCell.d.ts +7 -1
  37. package/dist/esm/types/helpers/index.d.ts +0 -1
  38. package/dist/esm/types/index.d.ts +3 -0
  39. package/dist/esm/types/test-app/src/App.d.ts +1 -2
  40. package/dist/index.d.ts +90 -10
  41. package/package.json +9 -16
  42. package/PRODUCTION_ARCHITECTURE.md +0 -511
  43. package/SAVE_FUNCTIONALITY_COMPLETE.md +0 -448
  44. package/dist/cjs/ui/badge.js +0 -34
  45. package/dist/esm/types/helpers/jsonToHtml.d.ts +0 -40
  46. package/dist/esm/ui/badge.js +0 -31
  47. package/server/README.md +0 -203
  48. package/server/db.js +0 -142
  49. package/server/server.js +0 -165
@@ -0,0 +1,85 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { useMemo } from 'react';
3
+ import katex from 'katex';
4
+
5
+ /**
6
+ * Renders LaTeX math expressions in HTML content using KaTeX.
7
+ * Supports both inline ($...$) and display ($$...$$) math.
8
+ */
9
+ // Regex patterns for math delimiters
10
+ var DISPLAY_MATH_REGEX = /\$\$([\s\S]*?)\$\$/g;
11
+ var INLINE_MATH_REGEX = /\$([^\$\n]+?)\$/g;
12
+ /**
13
+ * Render a single LaTeX expression to HTML using KaTeX
14
+ */
15
+ function renderLatex(latex, displayMode) {
16
+ try {
17
+ return katex.renderToString(latex, {
18
+ displayMode: displayMode,
19
+ throwOnError: false,
20
+ errorColor: "#cc0000",
21
+ strict: false,
22
+ trust: true,
23
+ macros: {
24
+ "\\leq": "\\le",
25
+ "\\geq": "\\ge"
26
+ }
27
+ });
28
+ } catch (error) {
29
+ console.warn("KaTeX render error:", error);
30
+ // Return the original with error styling
31
+ return "<span class=\"katex-error\" style=\"color: #cc0000;\">".concat(latex, "</span>");
32
+ }
33
+ }
34
+ /**
35
+ * Process HTML content and render all math expressions
36
+ */
37
+ function renderMathInHtml(html) {
38
+ if (!html) return "";
39
+ // First, handle display math ($$...$$)
40
+ var result = html.replace(DISPLAY_MATH_REGEX, function (match, latex) {
41
+ return renderLatex(latex.trim(), true);
42
+ });
43
+ // Then, handle inline math ($...$)
44
+ // The $...$ pattern with closing $ is always math, not currency
45
+ result = result.replace(INLINE_MATH_REGEX, function (match, latex) {
46
+ return renderLatex(latex.trim(), false);
47
+ });
48
+ return result;
49
+ }
50
+ /**
51
+ * Check if content contains any math expressions
52
+ */
53
+ function containsMath(html) {
54
+ if (!html) return false;
55
+ return DISPLAY_MATH_REGEX.test(html) || INLINE_MATH_REGEX.test(html);
56
+ }
57
+ /**
58
+ * React component that renders HTML with math expressions
59
+ */
60
+ function MathContent(_ref) {
61
+ var html = _ref.html,
62
+ _ref$className = _ref.className,
63
+ className = _ref$className === void 0 ? "" : _ref$className,
64
+ _ref$as = _ref.as,
65
+ Component = _ref$as === void 0 ? "span" : _ref$as;
66
+ var renderedHtml = useMemo(function () {
67
+ return renderMathInHtml(html);
68
+ }, [html]);
69
+ return jsx(Component, {
70
+ className: className,
71
+ dangerouslySetInnerHTML: {
72
+ __html: renderedHtml
73
+ }
74
+ });
75
+ }
76
+ /**
77
+ * Hook to get rendered math HTML
78
+ */
79
+ function useMathHtml(html) {
80
+ return useMemo(function () {
81
+ return renderMathInHtml(html);
82
+ }, [html]);
83
+ }
84
+
85
+ export { MathContent, containsMath, MathContent as default, renderMathInHtml, useMathHtml };
@@ -177,7 +177,7 @@ function PdfDocumentViewer(_ref2) {
177
177
  var currentPath = "".concat(path, "/").concat(block.block_type, "[").concat(index, "](").concat(block.id, ")");
178
178
  // Assuming block.polygon is number[][] (array of points)
179
179
  var points = block.polygon;
180
- if (points && Array.isArray(points) && points.length >= 2 && block.block_type !== "Page") {
180
+ if (points && Array.isArray(points) && points.length >= 2 && block.block_type !== "Page" && block.block_type !== "TableCell") {
181
181
  // Calculate bbox from points
182
182
  var x_coords = points.map(function (p) {
183
183
  return p[0];
@@ -0,0 +1,187 @@
1
+ // Semantic Tag Parser for SOP/Batch Record domain tags
2
+ // Supports: MeasurementTag, HiddenMeasurementTag, ValueTag, DateTimeTag, FileTag, ImageTag
3
+ // Regular expression patterns for tag detection
4
+ // Standard tag: [[value][type:TYPE][attr:value]...]
5
+ // Hidden tag: {[value][type:TYPE][attr:value]...]}
6
+ var STANDARD_TAG_PATTERN = /\[\[([^\]]+)\](\[([^\]]+)\])*\]/g;
7
+ var HIDDEN_TAG_PATTERN = /\{\[([^\]]+)\](\[([^\]]+)\])*\]\}/g;
8
+ // Parse a single tag's attribute string like "[type:MEASUREMENT][uom:mL/min][id:abc-123]"
9
+ function parseTagAttributes(attributeStr) {
10
+ var attributes = {};
11
+ var type = 'VALUE'; // Default type
12
+ // Match all [key:value] pairs
13
+ var attrPattern = /\[([^:\]]+):([^\]]+)\]/g;
14
+ var match;
15
+ while ((match = attrPattern.exec(attributeStr)) !== null) {
16
+ var key = match[1].toLowerCase();
17
+ var value = match[2];
18
+ switch (key) {
19
+ case 'type':
20
+ type = value.toUpperCase();
21
+ break;
22
+ case 'uom':
23
+ attributes.uom = value;
24
+ break;
25
+ case 'id':
26
+ attributes.id = value;
27
+ break;
28
+ case 'format':
29
+ attributes.format = value;
30
+ break;
31
+ case 'filter':
32
+ attributes.filter = value;
33
+ break;
34
+ }
35
+ }
36
+ return {
37
+ type: type,
38
+ attributes: attributes
39
+ };
40
+ }
41
+ // Parse a single tag match
42
+ function parseTag(match, isHidden) {
43
+ var rawMatch = match[0];
44
+ var startIndex = match.index;
45
+ var endIndex = startIndex + rawMatch.length;
46
+ // Extract the value (first bracket content) and attributes (remaining brackets)
47
+ var innerContent;
48
+ if (isHidden) {
49
+ // Remove {[ and ]} wrapper
50
+ innerContent = rawMatch.slice(2, -2);
51
+ } else {
52
+ // Remove [[ and ]] wrapper (but there might be more brackets for attributes)
53
+ innerContent = rawMatch.slice(2, -1);
54
+ }
55
+ // Split by ][ to get value and attributes
56
+ var parts = innerContent.split('][');
57
+ var value = parts[0];
58
+ var attributeStr = parts.length > 1 ? '[' + parts.slice(1).join('][') + ']' : '';
59
+ var _parseTagAttributes = parseTagAttributes(attributeStr),
60
+ type = _parseTagAttributes.type,
61
+ attributes = _parseTagAttributes.attributes;
62
+ // Adjust type for hidden tags
63
+ var finalType = isHidden ? 'HIDDEN_MEASUREMENT' : type;
64
+ return {
65
+ type: finalType,
66
+ value: value,
67
+ rawMatch: rawMatch,
68
+ startIndex: startIndex,
69
+ endIndex: endIndex,
70
+ attributes: attributes,
71
+ isHidden: isHidden
72
+ };
73
+ }
74
+ // Main parsing function
75
+ function parseSemanticTags(text) {
76
+ var tags = [];
77
+ // Find all standard tags
78
+ var match;
79
+ var standardPattern = new RegExp(STANDARD_TAG_PATTERN.source, 'g');
80
+ while ((match = standardPattern.exec(text)) !== null) {
81
+ tags.push(parseTag(match, false));
82
+ }
83
+ // Find all hidden tags
84
+ var hiddenPattern = new RegExp(HIDDEN_TAG_PATTERN.source, 'g');
85
+ while ((match = hiddenPattern.exec(text)) !== null) {
86
+ tags.push(parseTag(match, true));
87
+ }
88
+ // Sort tags by start index
89
+ tags.sort(function (a, b) {
90
+ return a.startIndex - b.startIndex;
91
+ });
92
+ // Build segments
93
+ var segments = [];
94
+ var currentIndex = 0;
95
+ for (var _i = 0, _tags = tags; _i < _tags.length; _i++) {
96
+ var tag = _tags[_i];
97
+ // Add text before this tag
98
+ if (tag.startIndex > currentIndex) {
99
+ segments.push({
100
+ type: 'text',
101
+ content: text.slice(currentIndex, tag.startIndex)
102
+ });
103
+ }
104
+ // Add the tag segment (skip hidden tags in output)
105
+ if (!tag.isHidden) {
106
+ segments.push({
107
+ type: 'tag',
108
+ content: tag.value,
109
+ tag: tag
110
+ });
111
+ }
112
+ currentIndex = tag.endIndex;
113
+ }
114
+ // Add remaining text after last tag
115
+ if (currentIndex < text.length) {
116
+ segments.push({
117
+ type: 'text',
118
+ content: text.slice(currentIndex)
119
+ });
120
+ }
121
+ return {
122
+ originalText: text,
123
+ tags: tags,
124
+ segments: segments
125
+ };
126
+ }
127
+ // Check if text contains any semantic tags
128
+ function hasSemanticTags(text) {
129
+ if (!text) return false;
130
+ return STANDARD_TAG_PATTERN.test(text) || HIDDEN_TAG_PATTERN.test(text);
131
+ }
132
+ // Get tag type display info (for styling)
133
+ function getTagTypeInfo(type) {
134
+ switch (type) {
135
+ case 'MEASUREMENT':
136
+ return {
137
+ color: 'text-blue-700',
138
+ bgColor: 'bg-blue-100 border-blue-300',
139
+ icon: '📏',
140
+ label: 'Measurement'
141
+ };
142
+ case 'VALUE':
143
+ return {
144
+ color: 'text-emerald-700',
145
+ bgColor: 'bg-emerald-100 border-emerald-300',
146
+ icon: '📝',
147
+ label: 'Value'
148
+ };
149
+ case 'FILE':
150
+ return {
151
+ color: 'text-purple-700',
152
+ bgColor: 'bg-purple-100 border-purple-300',
153
+ icon: '📄',
154
+ label: 'File'
155
+ };
156
+ case 'IMAGE':
157
+ return {
158
+ color: 'text-pink-700',
159
+ bgColor: 'bg-pink-100 border-pink-300',
160
+ icon: '🖼️',
161
+ label: 'Image'
162
+ };
163
+ case 'DATETIME':
164
+ return {
165
+ color: 'text-orange-700',
166
+ bgColor: 'bg-orange-100 border-orange-300',
167
+ icon: '📅',
168
+ label: 'DateTime'
169
+ };
170
+ case 'HIDDEN_MEASUREMENT':
171
+ return {
172
+ color: 'text-gray-500',
173
+ bgColor: 'bg-gray-100 border-gray-300',
174
+ icon: '👁️‍🗨️',
175
+ label: 'Hidden'
176
+ };
177
+ default:
178
+ return {
179
+ color: 'text-gray-700',
180
+ bgColor: 'bg-gray-100 border-gray-300',
181
+ icon: '🏷️',
182
+ label: 'Tag'
183
+ };
184
+ }
185
+ }
186
+
187
+ export { getTagTypeInfo, hasSemanticTags, parseSemanticTags };
@@ -0,0 +1,140 @@
1
+ import { slicedToArray as _slicedToArray } from './_virtual/_rollupPluginBabelHelpers.js';
2
+ import { jsx, jsxs } from 'react/jsx-runtime';
3
+ import { useState } from 'react';
4
+ import { hasSemanticTags, parseSemanticTags, getTagTypeInfo } from './SemanticTagParser.js';
5
+
6
+ // Individual tag badge component
7
+ function TagBadge(_ref) {
8
+ var tag = _ref.tag,
9
+ _ref$showTooltip = _ref.showTooltip,
10
+ showTooltip = _ref$showTooltip === void 0 ? true : _ref$showTooltip,
11
+ onClick = _ref.onClick;
12
+ var _useState = useState(false),
13
+ _useState2 = _slicedToArray(_useState, 2),
14
+ isHovered = _useState2[0],
15
+ setIsHovered = _useState2[1];
16
+ var typeInfo = getTagTypeInfo(tag.type);
17
+ return jsxs("span", {
18
+ className: "relative inline-flex items-center gap-1 px-1.5 py-0.5 mx-0.5 rounded border text-xs font-medium cursor-default transition-all\n ".concat(typeInfo.bgColor, " ").concat(typeInfo.color, "\n ").concat(onClick ? 'cursor-pointer hover:shadow-md' : '', "\n ").concat(isHovered ? 'ring-2 ring-offset-1 ring-blue-400' : ''),
19
+ onMouseEnter: function onMouseEnter() {
20
+ return setIsHovered(true);
21
+ },
22
+ onMouseLeave: function onMouseLeave() {
23
+ return setIsHovered(false);
24
+ },
25
+ onClick: onClick,
26
+ children: [jsx("span", {
27
+ className: "text-[10px]",
28
+ children: typeInfo.icon
29
+ }), jsx("span", {
30
+ children: tag.value
31
+ }), tag.attributes.uom && jsx("span", {
32
+ className: "text-[10px] opacity-75 ml-0.5",
33
+ children: tag.attributes.uom
34
+ }), showTooltip && isHovered && jsx("div", {
35
+ className: "absolute bottom-full left-1/2 -translate-x-1/2 mb-2 z-50 pointer-events-none",
36
+ children: jsxs("div", {
37
+ className: "bg-gray-900 text-white text-xs rounded-lg px-3 py-2 shadow-lg whitespace-nowrap",
38
+ children: [jsxs("div", {
39
+ className: "font-semibold mb-1",
40
+ children: [typeInfo.label, " Tag"]
41
+ }), jsxs("div", {
42
+ className: "space-y-0.5 text-gray-300",
43
+ children: [jsxs("div", {
44
+ children: ["Value: ", jsx("span", {
45
+ className: "text-white",
46
+ children: tag.value
47
+ })]
48
+ }), tag.attributes.uom && jsxs("div", {
49
+ children: ["Unit: ", jsx("span", {
50
+ className: "text-white",
51
+ children: tag.attributes.uom
52
+ })]
53
+ }), tag.attributes.id && jsxs("div", {
54
+ className: "text-[10px] text-gray-400 truncate max-w-[200px]",
55
+ children: ["ID: ", tag.attributes.id]
56
+ }), tag.attributes.format && jsxs("div", {
57
+ children: ["Format: ", jsx("span", {
58
+ className: "text-white",
59
+ children: tag.attributes.format
60
+ })]
61
+ })]
62
+ }), jsx("div", {
63
+ className: "absolute top-full left-1/2 -translate-x-1/2 -mt-px",
64
+ children: jsx("div", {
65
+ className: "border-4 border-transparent border-t-gray-900"
66
+ })
67
+ })]
68
+ })
69
+ })]
70
+ });
71
+ }
72
+ // Main renderer component
73
+ function SemanticTagRenderer(_ref2) {
74
+ var content = _ref2.content,
75
+ _ref2$className = _ref2.className,
76
+ className = _ref2$className === void 0 ? '' : _ref2$className,
77
+ _ref2$showTooltips = _ref2.showTooltips,
78
+ showTooltips = _ref2$showTooltips === void 0 ? true : _ref2$showTooltips,
79
+ onTagClick = _ref2.onTagClick;
80
+ // If no semantic tags, just return the content as-is
81
+ if (!hasSemanticTags(content)) {
82
+ return jsx("span", {
83
+ className: className,
84
+ dangerouslySetInnerHTML: {
85
+ __html: content
86
+ }
87
+ });
88
+ }
89
+ var parsed = parseSemanticTags(content);
90
+ return jsx("span", {
91
+ className: className,
92
+ children: parsed.segments.map(function (segment, index) {
93
+ if (segment.type === 'text') {
94
+ // Render plain text (may contain HTML)
95
+ return jsx("span", {
96
+ dangerouslySetInnerHTML: {
97
+ __html: segment.content
98
+ }
99
+ }, index);
100
+ } else if (segment.type === 'tag' && segment.tag) {
101
+ // Render semantic tag badge
102
+ return jsx(TagBadge, {
103
+ tag: segment.tag,
104
+ showTooltip: showTooltips,
105
+ onClick: onTagClick ? function () {
106
+ return onTagClick(segment.tag);
107
+ } : undefined
108
+ }, index);
109
+ }
110
+ return null;
111
+ })
112
+ });
113
+ }
114
+ function SmartContent(_ref3) {
115
+ var content = _ref3.content,
116
+ _ref3$className = _ref3.className,
117
+ className = _ref3$className === void 0 ? '' : _ref3$className,
118
+ _ref3$enableSemanticT = _ref3.enableSemanticTags,
119
+ enableSemanticTags = _ref3$enableSemanticT === void 0 ? true : _ref3$enableSemanticT,
120
+ _ref3$showTooltips = _ref3.showTooltips,
121
+ showTooltips = _ref3$showTooltips === void 0 ? true : _ref3$showTooltips,
122
+ onTagClick = _ref3.onTagClick;
123
+ if (enableSemanticTags && hasSemanticTags(content)) {
124
+ return jsx(SemanticTagRenderer, {
125
+ content: content,
126
+ className: className,
127
+ showTooltips: showTooltips,
128
+ onTagClick: onTagClick
129
+ });
130
+ }
131
+ // Regular content without semantic tags
132
+ return jsx("span", {
133
+ className: className,
134
+ dangerouslySetInnerHTML: {
135
+ __html: content
136
+ }
137
+ });
138
+ }
139
+
140
+ export { SmartContent, SemanticTagRenderer as default };
@@ -2,14 +2,13 @@ import { slicedToArray as _slicedToArray, asyncToGenerator as _asyncToGenerator,
2
2
  import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { useState, useRef, useEffect } from 'react';
4
4
  import { Button } from './ui/button.js';
5
- import { Card, CardHeader, CardTitle, CardContent } from './ui/card.js';
5
+ import { Card, CardContent } from './ui/card.js';
6
6
  import { Tabs, TabsList, TabsTrigger, TabsContent } from './ui/tabs.js';
7
7
  import * as LucideIcons from 'lucide-react';
8
8
  import PdfDocumentViewer from './PdfDocumentViewer.js';
9
9
  import HtmlViewer from './HtmlViewer.js';
10
10
  import { preprocessData } from './helpers/preprocessData.js';
11
11
  import { PanelGroup, Panel, PanelResizeHandle } from 'react-resizable-panels';
12
- import { Badge } from './ui/badge.js';
13
12
  import { Progress } from './ui/progress.js';
14
13
  import { ScrollArea } from './ui/scroll-area.js';
15
14
  import { GET, POST } from './route.js';
@@ -17,15 +16,24 @@ import { GET, POST } from './route.js';
17
16
  // Remove component aliases and use direct imports
18
17
  // This will preserve the propser types
19
18
  function Structura(_ref) {
20
- var initialPdfPath = _ref.initialPdfPath,
19
+ var apiKey = _ref.apiKey,
20
+ baseUrl = _ref.baseUrl,
21
+ initialPdfPath = _ref.initialPdfPath,
21
22
  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]);
23
+ _ref$editMode = _ref.editMode,
24
+ editMode = _ref$editMode === void 0 ? true : _ref$editMode,
25
+ _ref$jsonMode = _ref.jsonMode,
26
+ jsonMode = _ref$jsonMode === void 0 ? true : _ref$jsonMode,
27
+ _ref$mathRendering = _ref.mathRendering,
28
+ mathRendering = _ref$mathRendering === void 0 ? true : _ref$mathRendering,
29
+ _ref$semanticTags = _ref.semanticTags,
30
+ semanticTags = _ref$semanticTags === void 0 ? true : _ref$semanticTags,
31
+ _ref$headerFooterBadg = _ref.headerFooterBadges,
32
+ headerFooterBadges = _ref$headerFooterBadg === void 0 ? true : _ref$headerFooterBadg,
33
+ _ref$defaultViewMode = _ref.defaultViewMode,
34
+ defaultViewMode = _ref$defaultViewMode === void 0 ? 'read' : _ref$defaultViewMode,
35
+ onContentChange = _ref.onContentChange,
36
+ onExport = _ref.onExport;
29
37
  // Log the imported SDK items to demonstrate usage
30
38
  // console.log("Imported BlockSchema from SDK:", BlockSchema);
31
39
  var _useState = useState(null),
@@ -48,7 +56,7 @@ function Structura(_ref) {
48
56
  _useState0 = _slicedToArray(_useState9, 2),
49
57
  fileUrl = _useState0[0],
50
58
  setFileUrl = _useState0[1];
51
- var _useState1 = useState(null),
59
+ var _useState1 = useState(initialJsonData || null),
52
60
  _useState10 = _slicedToArray(_useState1, 2),
53
61
  jsonData = _useState10[0],
54
62
  setJsonData = _useState10[1];
@@ -93,20 +101,18 @@ function Structura(_ref) {
93
101
  _useState30 = _slicedToArray(_useState29, 2),
94
102
  isDraggingOver = _useState30[0],
95
103
  setIsDraggingOver = _useState30[1]; //NOSONAR
96
- // Load initial JSON data if provided (for faster iteration without API calls)
104
+ // Sync initialJsonData prop with state when it changes
97
105
  useEffect(function () {
98
- var _a;
99
106
  if (initialJsonData) {
100
- console.log('[Structura] Loading initial JSON data from props');
101
107
  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
108
  }
109
109
  }, [initialJsonData]);
110
+ // Sync initialPdfPath prop with state when it changes
111
+ useEffect(function () {
112
+ if (initialPdfPath) {
113
+ setFileUrl(initialPdfPath);
114
+ }
115
+ }, [initialPdfPath]);
110
116
  useEffect(function () {
111
117
  var handleDragOver = function handleDragOver(e) {
112
118
  e.preventDefault();
@@ -350,12 +356,10 @@ function Structura(_ref) {
350
356
  // Add logging to the useEffect that watches isFileLoaded
351
357
  useEffect(function () {
352
358
  // console.log("!!! [Structura] isFileLoaded changed:", isFileLoaded);
353
- // Skip API call if we already have initialJsonData (cached mode)
359
+ // Skip auto-generation if we already have JSON data from props
354
360
  if (isFileLoaded && !initialJsonData) {
355
361
  // console.log("!!! [Structura] Calling handleGenerateJSON due to isFileLoaded");
356
362
  handleGenerateJSON();
357
- } else if (isFileLoaded && initialJsonData) {
358
- console.log('[Structura] Skipping API call - using cached JSON data');
359
363
  }
360
364
  }, [isFileLoaded, initialJsonData]);
361
365
  // Handle removing the PDF and resetting state
@@ -391,7 +395,7 @@ function Structura(_ref) {
391
395
  formData = new FormData();
392
396
  formData.append("file", file);
393
397
  // console.log("!!! [Structura] FormData:", formData);
394
- if (props === null || props === void 0 ? void 0 : props.APIKey) {
398
+ if (apiKey) {
395
399
  _context2.n = 3;
396
400
  break;
397
401
  }
@@ -399,8 +403,8 @@ function Structura(_ref) {
399
403
  case 3:
400
404
  _context2.n = 4;
401
405
  return POST(formData, {
402
- apiKey: props.APIKey,
403
- baseUrl: props.baseUrl
406
+ apiKey: apiKey,
407
+ baseUrl: baseUrl
404
408
  });
405
409
  case 4:
406
410
  submitResponse = _context2.v;
@@ -431,8 +435,8 @@ function Structura(_ref) {
431
435
  case 8:
432
436
  _context2.n = 9;
433
437
  return GET(requestId, {
434
- apiKey: props.APIKey,
435
- baseUrl: props.baseUrl
438
+ apiKey: apiKey,
439
+ baseUrl: baseUrl
436
440
  });
437
441
  case 9:
438
442
  resultResponse = _context2.v;
@@ -600,28 +604,7 @@ function Structura(_ref) {
600
604
  }
601
605
  return jsxs("div", {
602
606
  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", {
607
+ children: [jsx("div", {
625
608
  className: "md:hidden",
626
609
  children: jsxs(Tabs, {
627
610
  value: activeTab,
@@ -753,7 +736,14 @@ function Structura(_ref) {
753
736
  selectedBboxId: selectedBboxId,
754
737
  isLoading: isLoading,
755
738
  onNodeClick: handleHtmlNodeClick,
756
- onSave: props.onSave
739
+ editMode: editMode,
740
+ jsonMode: jsonMode,
741
+ mathRendering: mathRendering,
742
+ semanticTags: semanticTags,
743
+ headerFooterBadges: headerFooterBadges,
744
+ defaultViewMode: defaultViewMode,
745
+ onContentChange: onContentChange,
746
+ onExport: onExport
757
747
  })
758
748
  })
759
749
  })]
@@ -766,22 +756,10 @@ function Structura(_ref) {
766
756
  children: [jsx(Panel, {
767
757
  minSize: 20,
768
758
  defaultSize: 50,
769
- children: jsxs(Card, {
759
+ children: jsx(Card, {
770
760
  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",
761
+ children: jsx(CardContent, {
762
+ className: "p-0 flex-1 flex flex-col overflow-hidden h-full",
785
763
  children: jsx(ScrollArea, {
786
764
  className: "w-full h-[calc(100vh-220px)]",
787
765
  children: fileUrl ? jsx(PdfDocumentViewer, {
@@ -876,25 +854,17 @@ function Structura(_ref) {
876
854
  })
877
855
  })
878
856
  })
879
- })]
857
+ })
880
858
  })
881
859
  }), jsx(PanelResizeHandle, {
882
860
  className: "w-1.5 bg-black hover:bg-primary/20 transition-colors cursor-col-resize"
883
861
  }), jsx(Panel, {
884
862
  minSize: 20,
885
863
  defaultSize: 50,
886
- children: jsxs(Card, {
864
+ children: jsx(Card, {
887
865
  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",
866
+ children: jsx(CardContent, {
867
+ className: "p-0 h-full relative overflow-hidden",
898
868
  children: jsx("div", {
899
869
  className: "absolute inset-0",
900
870
  children: jsonData ? jsx(HtmlViewer, {
@@ -902,7 +872,14 @@ function Structura(_ref) {
902
872
  selectedBboxId: selectedBboxId,
903
873
  isLoading: isLoading,
904
874
  onNodeClick: handleHtmlNodeClick,
905
- onSave: props.onSave
875
+ editMode: editMode,
876
+ jsonMode: jsonMode,
877
+ mathRendering: mathRendering,
878
+ semanticTags: semanticTags,
879
+ headerFooterBadges: headerFooterBadges,
880
+ defaultViewMode: defaultViewMode,
881
+ onContentChange: onContentChange,
882
+ onExport: onExport
906
883
  }) : jsx("div", {
907
884
  className: "flex flex-col items-center justify-center h-full p-8 text-center",
908
885
  children: jsxs("div", {
@@ -919,7 +896,7 @@ function Structura(_ref) {
919
896
  })
920
897
  })
921
898
  })
922
- })]
899
+ })
923
900
  })
924
901
  })]
925
902
  })