@rustors/react 0.0.0-stage → 0.3.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/LICENSE +21 -0
- package/README.md +85 -2
- package/dist/components/BoundingBox.d.ts +4 -0
- package/dist/components/BoundingBox.d.ts.map +1 -0
- package/dist/components/BoundingBox.js +40 -0
- package/dist/components/BoundingBox.js.map +1 -0
- package/dist/components/DropzonePreview.d.ts +4 -0
- package/dist/components/DropzonePreview.d.ts.map +1 -0
- package/dist/components/DropzonePreview.js +40 -0
- package/dist/components/DropzonePreview.js.map +1 -0
- package/dist/components/DropzonePrompt.d.ts +4 -0
- package/dist/components/DropzonePrompt.d.ts.map +1 -0
- package/dist/components/DropzonePrompt.js +16 -0
- package/dist/components/DropzonePrompt.js.map +1 -0
- package/dist/components/OcrDropzone.d.ts +4 -0
- package/dist/components/OcrDropzone.d.ts.map +1 -0
- package/dist/components/OcrDropzone.js +65 -0
- package/dist/components/OcrDropzone.js.map +1 -0
- package/dist/components/OcrOverlay.d.ts +4 -0
- package/dist/components/OcrOverlay.d.ts.map +1 -0
- package/dist/components/OcrOverlay.js +50 -0
- package/dist/components/OcrOverlay.js.map +1 -0
- package/dist/context/RustoContext.d.ts +3 -0
- package/dist/context/RustoContext.d.ts.map +1 -0
- package/dist/context/RustoContext.js +6 -0
- package/dist/context/RustoContext.js.map +1 -0
- package/dist/context/RustoProvider.d.ts +4 -0
- package/dist/context/RustoProvider.d.ts.map +1 -0
- package/dist/context/RustoProvider.js +41 -0
- package/dist/context/RustoProvider.js.map +1 -0
- package/dist/hooks/useOcr.d.ts +3 -0
- package/dist/hooks/useOcr.d.ts.map +1 -0
- package/dist/hooks/useOcr.js +59 -0
- package/dist/hooks/useOcr.js.map +1 -0
- package/dist/hooks/useRusto.d.ts +3 -0
- package/dist/hooks/useRusto.d.ts.map +1 -0
- package/dist/hooks/useRusto.js +13 -0
- package/dist/hooks/useRusto.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +54 -0
- package/dist/index.js.map +1 -0
- package/dist/services/ocrService.d.ts +12 -0
- package/dist/services/ocrService.d.ts.map +1 -0
- package/dist/services/ocrService.js +30 -0
- package/dist/services/ocrService.js.map +1 -0
- package/dist/types/components.d.ts +44 -0
- package/dist/types/components.d.ts.map +1 -0
- package/dist/types/components.js +3 -0
- package/dist/types/components.js.map +1 -0
- package/dist/types/context.d.ts +16 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +3 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/hooks.d.ts +14 -0
- package/dist/types/hooks.d.ts.map +1 -0
- package/dist/types/hooks.js +3 -0
- package/dist/types/hooks.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +20 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/formatters.d.ts +14 -0
- package/dist/utils/formatters.d.ts.map +1 -0
- package/dist/utils/formatters.js +29 -0
- package/dist/utils/formatters.js.map +1 -0
- package/dist/utils/geometry.d.ts +9 -0
- package/dist/utils/geometry.d.ts.map +1 -0
- package/dist/utils/geometry.js +31 -0
- package/dist/utils/geometry.js.map +1 -0
- package/package.json +59 -4
- package/src/components/BoundingBox.tsx +63 -0
- package/src/components/DropzonePreview.tsx +61 -0
- package/src/components/DropzonePrompt.tsx +46 -0
- package/src/components/OcrDropzone.tsx +117 -0
- package/src/components/OcrOverlay.tsx +100 -0
- package/src/context/RustoContext.ts +4 -0
- package/src/context/RustoProvider.tsx +62 -0
- package/src/hooks/useOcr.ts +73 -0
- package/src/hooks/useRusto.ts +11 -0
- package/src/index.ts +34 -0
- package/src/services/ocrService.ts +43 -0
- package/src/types/components.ts +48 -0
- package/src/types/context.ts +18 -0
- package/src/types/hooks.ts +22 -0
- package/src/types/index.ts +3 -0
- package/src/utils/formatters.ts +27 -0
- package/src/utils/geometry.ts +36 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 RustO Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,86 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @rustors/react
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> Official React hooks, provider, and UI components for [RustO!](https://github.com/byrizki/rusto-rs)
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Provider Lifecycle**: Effortless engine initialization, status tracking (`idle`, `initializing`, `ready`, `error`), and error recovery with `<RustoProvider>`.
|
|
8
|
+
- **Easy Hooks**: `useRusto()` to access engine status, and `useOcr()` for running OCR and managing state (`isProcessing`, `results`, `spatialText`).
|
|
9
|
+
- **Composite Components**: `<OcrOverlay>` for displaying interactive bounding boxes, and `<OcrDropzone>` for drag-and-drop scanning.
|
|
10
|
+
- **Architectural Purity**: Functional logic is strictly separated into testable services and hooks; components remain clean and declarative.
|
|
11
|
+
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @rustors/react @rustors/web
|
|
16
|
+
# or
|
|
17
|
+
yarn add @rustors/react @rustors/web
|
|
18
|
+
# or
|
|
19
|
+
pnpm add @rustors/react @rustors/web
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Quick Start
|
|
23
|
+
|
|
24
|
+
### 1. Wrap your application with `RustoProvider`
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import React from 'react';
|
|
28
|
+
import { RustoProvider } from '@rustors/react';
|
|
29
|
+
import { getModelUrls } from '@rustors/model-ppocrv6-tiny';
|
|
30
|
+
|
|
31
|
+
const modelUrls = getModelUrls('/models/ppocrv6-tiny');
|
|
32
|
+
|
|
33
|
+
export function App() {
|
|
34
|
+
return (
|
|
35
|
+
<RustoProvider
|
|
36
|
+
config={{
|
|
37
|
+
preset: 'ppv6',
|
|
38
|
+
models: {
|
|
39
|
+
detection: modelUrls.detection,
|
|
40
|
+
recognition: modelUrls.recognition,
|
|
41
|
+
dictionary: modelUrls.dictionary,
|
|
42
|
+
},
|
|
43
|
+
}}
|
|
44
|
+
>
|
|
45
|
+
<OcrScanner />
|
|
46
|
+
</RustoProvider>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Scan and Display with Hooks & Overlay
|
|
52
|
+
|
|
53
|
+
```tsx
|
|
54
|
+
import React, { useState } from 'react';
|
|
55
|
+
import { useOcr, OcrOverlay, OcrDropzone } from '@rustors/react';
|
|
56
|
+
|
|
57
|
+
export function OcrScanner() {
|
|
58
|
+
const [imageSrc, setImageSrc] = useState<string | null>(null);
|
|
59
|
+
const { detect, results, isProcessing } = useOcr();
|
|
60
|
+
|
|
61
|
+
const handleFileSelect = async (file: File) => {
|
|
62
|
+
setImageSrc(URL.createObjectURL(file));
|
|
63
|
+
await detect(file);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return (
|
|
67
|
+
<div>
|
|
68
|
+
<OcrDropzone onFileSelect={handleFileSelect} />
|
|
69
|
+
|
|
70
|
+
{isProcessing && <p>Scanning document...</p>}
|
|
71
|
+
|
|
72
|
+
{imageSrc && results.length > 0 && (
|
|
73
|
+
<OcrOverlay
|
|
74
|
+
imageSrc={imageSrc}
|
|
75
|
+
results={results}
|
|
76
|
+
onItemClick={(item) => alert(`Clicked: ${item.text}`)}
|
|
77
|
+
/>
|
|
78
|
+
)}
|
|
79
|
+
</div>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
MIT License
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { BoundingBoxProps } from '../types/index.js';
|
|
3
|
+
export declare function BoundingBox({ item, scaleX, scaleY, highlightColor, showTooltip, className, style, onClick, }: BoundingBoxProps): ReactElement;
|
|
4
|
+
//# sourceMappingURL=BoundingBox.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BoundingBox.d.ts","sourceRoot":"","sources":["../../src/components/BoundingBox.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAG1D,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,MAAM,EACN,MAAM,EACN,cAA0C,EAC1C,WAAkB,EAClB,SAAS,EACT,KAAK,EACL,OAAO,GACR,EAAE,gBAAgB,GAAG,YAAY,CAiDjC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BoundingBox = BoundingBox;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const geometry_js_1 = require("../utils/geometry.js");
|
|
6
|
+
function BoundingBox({ item, scaleX, scaleY, highlightColor = 'rgba(59, 130, 246, 0.4)', showTooltip = true, className, style, onClick, }) {
|
|
7
|
+
const scaled = (0, geometry_js_1.scaleFrame)(item.frame, scaleX, scaleY);
|
|
8
|
+
const boxStyle = {
|
|
9
|
+
position: 'absolute',
|
|
10
|
+
left: `${scaled.left}px`,
|
|
11
|
+
top: `${scaled.top}px`,
|
|
12
|
+
width: `${scaled.width}px`,
|
|
13
|
+
height: `${scaled.height}px`,
|
|
14
|
+
border: `1.5px solid ${highlightColor}`,
|
|
15
|
+
backgroundColor: highlightColor.replace(/[\d.]+\)$/, '0.15)'),
|
|
16
|
+
cursor: onClick ? 'pointer' : 'default',
|
|
17
|
+
pointerEvents: 'auto',
|
|
18
|
+
boxSizing: 'border-box',
|
|
19
|
+
borderRadius: '2px',
|
|
20
|
+
...style,
|
|
21
|
+
};
|
|
22
|
+
const tooltipStyle = {
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
bottom: '100%',
|
|
25
|
+
left: '0',
|
|
26
|
+
backgroundColor: '#1f2937',
|
|
27
|
+
color: '#ffffff',
|
|
28
|
+
fontSize: '11px',
|
|
29
|
+
lineHeight: '1.2',
|
|
30
|
+
padding: '2px 6px',
|
|
31
|
+
borderRadius: '4px',
|
|
32
|
+
whiteSpace: 'nowrap',
|
|
33
|
+
pointerEvents: 'none',
|
|
34
|
+
zIndex: 10,
|
|
35
|
+
transform: 'translateY(-2px)',
|
|
36
|
+
boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
|
|
37
|
+
};
|
|
38
|
+
return ((0, jsx_runtime_1.jsx)("div", { className: className, style: boxStyle, onClick: () => onClick?.(item), title: `${item.text} (${Math.round(item.score * 100)}%)`, children: showTooltip && ((0, jsx_runtime_1.jsxs)("span", { style: tooltipStyle, children: [item.text, " ", (0, jsx_runtime_1.jsxs)("small", { style: { opacity: 0.75 }, children: ["(", Math.round(item.score * 100), "%)"] })] })) }));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=BoundingBox.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BoundingBox.js","sourceRoot":"","sources":["../../src/components/BoundingBox.tsx"],"names":[],"mappings":";;AAIA,kCA0DC;;AA5DD,sDAAkD;AAElD,SAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,MAAM,EACN,MAAM,EACN,cAAc,GAAG,yBAAyB,EAC1C,WAAW,GAAG,IAAI,EAClB,SAAS,EACT,KAAK,EACL,OAAO,GACU;IACjB,MAAM,MAAM,GAAG,IAAA,wBAAU,EAAC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAEtD,MAAM,QAAQ,GAAwB;QACpC,QAAQ,EAAE,UAAU;QACpB,IAAI,EAAE,GAAG,MAAM,CAAC,IAAI,IAAI;QACxB,GAAG,EAAE,GAAG,MAAM,CAAC,GAAG,IAAI;QACtB,KAAK,EAAE,GAAG,MAAM,CAAC,KAAK,IAAI;QAC1B,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,IAAI;QAC5B,MAAM,EAAE,eAAe,cAAc,EAAE;QACvC,eAAe,EAAE,cAAc,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC;QAC7D,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;QACvC,aAAa,EAAE,MAAM;QACrB,SAAS,EAAE,YAAY;QACvB,YAAY,EAAE,KAAK;QACnB,GAAG,KAAK;KACT,CAAC;IAEF,MAAM,YAAY,GAAwB;QACxC,QAAQ,EAAE,UAAU;QACpB,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,GAAG;QACT,eAAe,EAAE,SAAS;QAC1B,KAAK,EAAE,SAAS;QAChB,QAAQ,EAAE,MAAM;QAChB,UAAU,EAAE,KAAK;QACjB,OAAO,EAAE,SAAS;QAClB,YAAY,EAAE,KAAK;QACnB,UAAU,EAAE,QAAQ;QACpB,aAAa,EAAE,MAAM;QACrB,MAAM,EAAE,EAAE;QACV,SAAS,EAAE,kBAAkB;QAC7B,SAAS,EAAE,2BAA2B;KACvC,CAAC;IAEF,OAAO,CACL,gCACE,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE,QAAQ,EACf,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAC9B,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,IAAI,YAEvD,WAAW,IAAI,CACd,kCAAM,KAAK,EAAE,YAAY,aACtB,IAAI,CAAC,IAAI,OAAE,mCAAO,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,kBAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,GAAG,CAAC,UAAW,IACjF,CACR,GACG,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropzonePreview.d.ts","sourceRoot":"","sources":["../../src/components/DropzonePreview.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAE9D,wBAAgB,eAAe,CAAC,EAC9B,UAAU,EACV,OAAO,EACP,SAAS,GACV,EAAE,oBAAoB,GAAG,YAAY,CAqDrC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DropzonePreview = DropzonePreview;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
function DropzonePreview({ previewUrl, onClear, className, }) {
|
|
6
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, style: {
|
|
7
|
+
position: 'relative',
|
|
8
|
+
display: 'flex',
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
padding: '12px',
|
|
12
|
+
width: '100%',
|
|
13
|
+
boxSizing: 'border-box',
|
|
14
|
+
}, children: [(0, jsx_runtime_1.jsx)("img", { src: previewUrl, alt: "Uploaded Preview", style: {
|
|
15
|
+
maxHeight: '260px',
|
|
16
|
+
maxWidth: '100%',
|
|
17
|
+
objectFit: 'contain',
|
|
18
|
+
borderRadius: '4px',
|
|
19
|
+
} }), (0, jsx_runtime_1.jsx)("button", { type: "button", onClick: (e) => {
|
|
20
|
+
e.stopPropagation();
|
|
21
|
+
onClear();
|
|
22
|
+
}, style: {
|
|
23
|
+
position: 'absolute',
|
|
24
|
+
top: '16px',
|
|
25
|
+
right: '16px',
|
|
26
|
+
backgroundColor: 'rgba(0, 0, 0, 0.65)',
|
|
27
|
+
color: '#ffffff',
|
|
28
|
+
border: 'none',
|
|
29
|
+
borderRadius: '50%',
|
|
30
|
+
width: '28px',
|
|
31
|
+
height: '28px',
|
|
32
|
+
display: 'flex',
|
|
33
|
+
alignItems: 'center',
|
|
34
|
+
justifyContent: 'center',
|
|
35
|
+
cursor: 'pointer',
|
|
36
|
+
fontSize: '14px',
|
|
37
|
+
lineHeight: 1,
|
|
38
|
+
}, "aria-label": "Remove image", children: "\u00D7" })] }));
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=DropzonePreview.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropzonePreview.js","sourceRoot":"","sources":["../../src/components/DropzonePreview.tsx"],"names":[],"mappings":";;AAGA,0CAyDC;;AAzDD,SAAgB,eAAe,CAAC,EAC9B,UAAU,EACV,OAAO,EACP,SAAS,GACY;IACrB,OAAO,CACL,iCACE,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE,MAAM;YACf,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,OAAO,EAAE,MAAM;YACf,KAAK,EAAE,MAAM;YACb,SAAS,EAAE,YAAY;SACxB,aAED,gCACE,GAAG,EAAE,UAAU,EACf,GAAG,EAAC,kBAAkB,EACtB,KAAK,EAAE;oBACL,SAAS,EAAE,OAAO;oBAClB,QAAQ,EAAE,MAAM;oBAChB,SAAS,EAAE,SAAS;oBACpB,YAAY,EAAE,KAAK;iBACpB,GACD,EACF,mCACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE;oBACb,CAAC,CAAC,eAAe,EAAE,CAAC;oBACpB,OAAO,EAAE,CAAC;gBACZ,CAAC,EACD,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,GAAG,EAAE,MAAM;oBACX,KAAK,EAAE,MAAM;oBACb,eAAe,EAAE,qBAAqB;oBACtC,KAAK,EAAE,SAAS;oBAChB,MAAM,EAAE,MAAM;oBACd,YAAY,EAAE,KAAK;oBACnB,KAAK,EAAE,MAAM;oBACb,MAAM,EAAE,MAAM;oBACd,OAAO,EAAE,MAAM;oBACf,UAAU,EAAE,QAAQ;oBACpB,cAAc,EAAE,QAAQ;oBACxB,MAAM,EAAE,SAAS;oBACjB,QAAQ,EAAE,MAAM;oBAChB,UAAU,EAAE,CAAC;iBACd,gBACU,cAAc,uBAGlB,IACL,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropzonePrompt.d.ts","sourceRoot":"","sources":["../../src/components/DropzonePrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,wBAAgB,cAAc,CAAC,EAC7B,KAA0C,EAC1C,QAAyD,EACzD,IAAI,EACJ,SAAS,GACV,EAAE,mBAAmB,GAAG,YAAY,CAqCpC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DropzonePrompt = DropzonePrompt;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
function DropzonePrompt({ title = 'Click or drag image here to scan', subtitle = 'Supports PNG, JPEG, WebP, and document scans', icon, className, }) {
|
|
6
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, style: {
|
|
7
|
+
display: 'flex',
|
|
8
|
+
flexDirection: 'column',
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
justifyContent: 'center',
|
|
11
|
+
padding: '32px 16px',
|
|
12
|
+
textAlign: 'center',
|
|
13
|
+
pointerEvents: 'none',
|
|
14
|
+
}, children: [icon || ((0, jsx_runtime_1.jsx)("svg", { style: { width: '40px', height: '40px', color: '#6b7280', marginBottom: '12px' }, fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 1.5, d: "M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" }) })), (0, jsx_runtime_1.jsx)("p", { style: { margin: '0 0 4px', fontSize: '14px', fontWeight: 600, color: '#374151' }, children: title }), (0, jsx_runtime_1.jsx)("p", { style: { margin: 0, fontSize: '12px', color: '#6b7280' }, children: subtitle })] }));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=DropzonePrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DropzonePrompt.js","sourceRoot":"","sources":["../../src/components/DropzonePrompt.tsx"],"names":[],"mappings":";;AAGA,wCA0CC;;AA1CD,SAAgB,cAAc,CAAC,EAC7B,KAAK,GAAG,kCAAkC,EAC1C,QAAQ,GAAG,8CAA8C,EACzD,IAAI,EACJ,SAAS,GACW;IACpB,OAAO,CACL,iCACE,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE;YACL,OAAO,EAAE,MAAM;YACf,aAAa,EAAE,QAAQ;YACvB,UAAU,EAAE,QAAQ;YACpB,cAAc,EAAE,QAAQ;YACxB,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,QAAQ;YACnB,aAAa,EAAE,MAAM;SACtB,aAEA,IAAI,IAAI,CACP,gCACE,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,EAAE,EAChF,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,OAAO,EAAC,WAAW,YAEnB,iCACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,WAAW,EAAE,GAAG,EAChB,CAAC,EAAC,2JAA2J,GAC7J,GACE,CACP,EACD,8BAAG,KAAK,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,YACjF,KAAK,GACJ,EACJ,8BAAG,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,YACxD,QAAQ,GACP,IACA,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { OcrDropzoneProps } from '../types/index.js';
|
|
3
|
+
export declare function OcrDropzone({ onFileSelect, onDetect, autoDetect, detectOptions, accept, className, style, }: OcrDropzoneProps): ReactElement;
|
|
4
|
+
//# sourceMappingURL=OcrDropzone.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OcrDropzone.d.ts","sourceRoot":"","sources":["../../src/components/OcrDropzone.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EAGlB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAK1D,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,QAAQ,EACR,UAAkB,EAClB,aAAa,EACb,MAAoD,EACpD,SAAS,EACT,KAAK,GACN,EAAE,gBAAgB,GAAG,YAAY,CA+FjC"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OcrDropzone = OcrDropzone;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const DropzonePrompt_js_1 = require("./DropzonePrompt.js");
|
|
7
|
+
const DropzonePreview_js_1 = require("./DropzonePreview.js");
|
|
8
|
+
const useOcr_js_1 = require("../hooks/useOcr.js");
|
|
9
|
+
function OcrDropzone({ onFileSelect, onDetect, autoDetect = false, detectOptions, accept = 'image/png,image/jpeg,image/webp,image/bmp', className, style, }) {
|
|
10
|
+
const fileInputRef = (0, react_1.useRef)(null);
|
|
11
|
+
const [isDragOver, setIsDragOver] = (0, react_1.useState)(false);
|
|
12
|
+
const [previewUrl, setPreviewUrl] = (0, react_1.useState)(null);
|
|
13
|
+
const { detect } = (0, useOcr_js_1.useOcr)({
|
|
14
|
+
...detectOptions,
|
|
15
|
+
onSuccess: (res) => onDetect?.(res),
|
|
16
|
+
});
|
|
17
|
+
const handleFile = (0, react_1.useCallback)(async (file) => {
|
|
18
|
+
onFileSelect?.(file);
|
|
19
|
+
const url = URL.createObjectURL(file);
|
|
20
|
+
setPreviewUrl(url);
|
|
21
|
+
if (autoDetect) {
|
|
22
|
+
await detect(file, detectOptions);
|
|
23
|
+
}
|
|
24
|
+
}, [autoDetect, detect, detectOptions, onFileSelect]);
|
|
25
|
+
const onDragOver = (0, react_1.useCallback)((e) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
setIsDragOver(true);
|
|
28
|
+
}, []);
|
|
29
|
+
const onDragLeave = (0, react_1.useCallback)(() => {
|
|
30
|
+
setIsDragOver(false);
|
|
31
|
+
}, []);
|
|
32
|
+
const onDrop = (0, react_1.useCallback)((e) => {
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
setIsDragOver(false);
|
|
35
|
+
const files = e.dataTransfer.files;
|
|
36
|
+
if (files && files.length > 0) {
|
|
37
|
+
handleFile(files[0]);
|
|
38
|
+
}
|
|
39
|
+
}, [handleFile]);
|
|
40
|
+
const onInputChange = (0, react_1.useCallback)((e) => {
|
|
41
|
+
const files = e.target.files;
|
|
42
|
+
if (files && files.length > 0) {
|
|
43
|
+
handleFile(files[0]);
|
|
44
|
+
}
|
|
45
|
+
}, [handleFile]);
|
|
46
|
+
const clearSelection = (0, react_1.useCallback)(() => {
|
|
47
|
+
if (previewUrl) {
|
|
48
|
+
URL.revokeObjectURL(previewUrl);
|
|
49
|
+
}
|
|
50
|
+
setPreviewUrl(null);
|
|
51
|
+
if (fileInputRef.current) {
|
|
52
|
+
fileInputRef.current.value = '';
|
|
53
|
+
}
|
|
54
|
+
}, [previewUrl]);
|
|
55
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, onClick: () => fileInputRef.current?.click(), onDragOver: onDragOver, onDragLeave: onDragLeave, onDrop: onDrop, style: {
|
|
56
|
+
border: `2px dashed ${isDragOver ? '#3b82f6' : '#d1d5db'}`,
|
|
57
|
+
borderRadius: '8px',
|
|
58
|
+
backgroundColor: isDragOver ? '#eff6ff' : '#fafafa',
|
|
59
|
+
cursor: 'pointer',
|
|
60
|
+
transition: 'border-color 0.15s ease, background-color 0.15s ease',
|
|
61
|
+
boxSizing: 'border-box',
|
|
62
|
+
...style,
|
|
63
|
+
}, children: [(0, jsx_runtime_1.jsx)("input", { ref: fileInputRef, type: "file", accept: accept, onChange: onInputChange, style: { display: 'none' } }), previewUrl ? ((0, jsx_runtime_1.jsx)(DropzonePreview_js_1.DropzonePreview, { previewUrl: previewUrl, onClear: clearSelection })) : ((0, jsx_runtime_1.jsx)(DropzonePrompt_js_1.DropzonePrompt, {}))] }));
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=OcrDropzone.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OcrDropzone.js","sourceRoot":"","sources":["../../src/components/OcrDropzone.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { OcrOverlayProps } from '../types/index.js';
|
|
3
|
+
export declare function OcrOverlay({ imageSrc, results, naturalWidth: propNaturalWidth, naturalHeight: propNaturalHeight, highlightColor, showTooltips, className, style, onItemClick, }: OcrOverlayProps): ReactElement;
|
|
4
|
+
//# sourceMappingURL=OcrOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OcrOverlay.d.ts","sourceRoot":"","sources":["../../src/components/OcrOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,YAAY,EAElB,MAAM,OAAO,CAAC;AACf,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAIzD,wBAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,OAAO,EACP,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,iBAAiB,EAChC,cAAc,EACd,YAAmB,EACnB,SAAS,EACT,KAAK,EACL,WAAW,GACZ,EAAE,eAAe,GAAG,YAAY,CA8EhC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.OcrOverlay = OcrOverlay;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const BoundingBox_js_1 = require("./BoundingBox.js");
|
|
7
|
+
const geometry_js_1 = require("../utils/geometry.js");
|
|
8
|
+
function OcrOverlay({ imageSrc, results, naturalWidth: propNaturalWidth, naturalHeight: propNaturalHeight, highlightColor, showTooltips = true, className, style, onItemClick, }) {
|
|
9
|
+
const imgRef = (0, react_1.useRef)(null);
|
|
10
|
+
const [renderDims, setRenderDims] = (0, react_1.useState)({
|
|
11
|
+
width: 0,
|
|
12
|
+
height: 0,
|
|
13
|
+
});
|
|
14
|
+
const [naturalDims, setNaturalDims] = (0, react_1.useState)({
|
|
15
|
+
width: propNaturalWidth || 0,
|
|
16
|
+
height: propNaturalHeight || 0,
|
|
17
|
+
});
|
|
18
|
+
const onImageLoad = (0, react_1.useCallback)((e) => {
|
|
19
|
+
const img = e.currentTarget;
|
|
20
|
+
setNaturalDims({
|
|
21
|
+
width: img.naturalWidth,
|
|
22
|
+
height: img.naturalHeight,
|
|
23
|
+
});
|
|
24
|
+
setRenderDims({
|
|
25
|
+
width: img.clientWidth,
|
|
26
|
+
height: img.clientHeight,
|
|
27
|
+
});
|
|
28
|
+
}, []);
|
|
29
|
+
const effectiveNaturalWidth = propNaturalWidth || naturalDims.width;
|
|
30
|
+
const effectiveNaturalHeight = propNaturalHeight || naturalDims.height;
|
|
31
|
+
const { scaleX, scaleY } = (0, geometry_js_1.calculateScale)(effectiveNaturalWidth, effectiveNaturalHeight, renderDims.width || effectiveNaturalWidth, renderDims.height || effectiveNaturalHeight);
|
|
32
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: className, style: {
|
|
33
|
+
position: 'relative',
|
|
34
|
+
display: 'inline-block',
|
|
35
|
+
overflow: 'hidden',
|
|
36
|
+
...style,
|
|
37
|
+
}, children: [(0, jsx_runtime_1.jsx)("img", { ref: imgRef, src: imageSrc, alt: "OCR Target", onLoad: onImageLoad, style: {
|
|
38
|
+
display: 'block',
|
|
39
|
+
maxWidth: '100%',
|
|
40
|
+
height: 'auto',
|
|
41
|
+
} }), (0, jsx_runtime_1.jsx)("div", { style: {
|
|
42
|
+
position: 'absolute',
|
|
43
|
+
top: 0,
|
|
44
|
+
left: 0,
|
|
45
|
+
right: 0,
|
|
46
|
+
bottom: 0,
|
|
47
|
+
pointerEvents: 'none',
|
|
48
|
+
}, children: results.map((item, idx) => ((0, jsx_runtime_1.jsx)(BoundingBox_js_1.BoundingBox, { item: item, scaleX: scaleX, scaleY: scaleY, highlightColor: highlightColor, showTooltip: showTooltips, onClick: onItemClick }, `${item.text}-${idx}`))) })] }));
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=OcrOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OcrOverlay.js","sourceRoot":"","sources":["../../src/components/OcrOverlay.tsx"],"names":[],"mappings":";;AAWA,gCAwFC;;AAnGD,iCAMe;AAEf,qDAA+C;AAC/C,sDAAsD;AAEtD,SAAgB,UAAU,CAAC,EACzB,QAAQ,EACR,OAAO,EACP,YAAY,EAAE,gBAAgB,EAC9B,aAAa,EAAE,iBAAiB,EAChC,cAAc,EACd,YAAY,GAAG,IAAI,EACnB,SAAS,EACT,KAAK,EACL,WAAW,GACK;IAChB,MAAM,MAAM,GAAG,IAAA,cAAM,EAA0B,IAAI,CAAC,CAAC;IACrD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,IAAA,gBAAQ,EAAoC;QAC9E,KAAK,EAAE,CAAC;QACR,MAAM,EAAE,CAAC;KACV,CAAC,CAAC;IACH,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,IAAA,gBAAQ,EAAoC;QAChF,KAAK,EAAE,gBAAgB,IAAI,CAAC;QAC5B,MAAM,EAAE,iBAAiB,IAAI,CAAC;KAC/B,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,IAAA,mBAAW,EAAC,CAAC,CAAmC,EAAE,EAAE;QACtE,MAAM,GAAG,GAAG,CAAC,CAAC,aAAa,CAAC;QAC5B,cAAc,CAAC;YACb,KAAK,EAAE,GAAG,CAAC,YAAY;YACvB,MAAM,EAAE,GAAG,CAAC,aAAa;SAC1B,CAAC,CAAC;QACH,aAAa,CAAC;YACZ,KAAK,EAAE,GAAG,CAAC,WAAW;YACtB,MAAM,EAAE,GAAG,CAAC,YAAY;SACzB,CAAC,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,qBAAqB,GAAG,gBAAgB,IAAI,WAAW,CAAC,KAAK,CAAC;IACpE,MAAM,sBAAsB,GAAG,iBAAiB,IAAI,WAAW,CAAC,MAAM,CAAC;IAEvE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,4BAAc,EACvC,qBAAqB,EACrB,sBAAsB,EACtB,UAAU,CAAC,KAAK,IAAI,qBAAqB,EACzC,UAAU,CAAC,MAAM,IAAI,sBAAsB,CAC5C,CAAC;IAEF,OAAO,CACL,iCACE,SAAS,EAAE,SAAS,EACpB,KAAK,EAAE;YACL,QAAQ,EAAE,UAAU;YACpB,OAAO,EAAE,cAAc;YACvB,QAAQ,EAAE,QAAQ;YAClB,GAAG,KAAK;SACT,aAED,gCACE,GAAG,EAAE,MAAM,EACX,GAAG,EAAE,QAAQ,EACb,GAAG,EAAC,YAAY,EAChB,MAAM,EAAE,WAAW,EACnB,KAAK,EAAE;oBACL,OAAO,EAAE,OAAO;oBAChB,QAAQ,EAAE,MAAM;oBAChB,MAAM,EAAE,MAAM;iBACf,GACD,EACF,gCACE,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,GAAG,EAAE,CAAC;oBACN,IAAI,EAAE,CAAC;oBACP,KAAK,EAAE,CAAC;oBACR,MAAM,EAAE,CAAC;oBACT,aAAa,EAAE,MAAM;iBACtB,YAEA,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAC1B,uBAAC,4BAAW,IAEV,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,EAC9B,WAAW,EAAE,YAAY,EACzB,OAAO,EAAE,WAAW,IANf,GAAG,IAAI,CAAC,IAAI,IAAI,GAAG,EAAE,CAO1B,CACH,CAAC,GACE,IACF,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustoContext.d.ts","sourceRoot":"","sources":["../../src/context/RustoContext.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,eAAO,MAAM,YAAY,mDAAgD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustoContext.js","sourceRoot":"","sources":["../../src/context/RustoContext.ts"],"names":[],"mappings":";;;AAAA,iCAAsC;AAGzB,QAAA,YAAY,GAAG,IAAA,qBAAa,EAA2B,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustoProvider.d.ts","sourceRoot":"","sources":["../../src/context/RustoProvider.tsx"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,OAAO,CAAC;AAIf,OAAO,KAAK,EAEV,kBAAkB,EAEnB,MAAM,mBAAmB,CAAC;AAE3B,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAM,EACN,cAAqB,GACtB,EAAE,kBAAkB,GAAG,YAAY,CAyCnC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.RustoProvider = RustoProvider;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const RustoContext_js_1 = require("./RustoContext.js");
|
|
7
|
+
const ocrService_js_1 = require("../services/ocrService.js");
|
|
8
|
+
function RustoProvider({ children, config, autoInitialize = true, }) {
|
|
9
|
+
const [status, setStatus] = (0, react_1.useState)('idle');
|
|
10
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
11
|
+
const initialize = (0, react_1.useCallback)(async (overrideConfig) => {
|
|
12
|
+
try {
|
|
13
|
+
setStatus('initializing');
|
|
14
|
+
setError(null);
|
|
15
|
+
await ocrService_js_1.defaultOcrService.init(overrideConfig || config);
|
|
16
|
+
setStatus('ready');
|
|
17
|
+
}
|
|
18
|
+
catch (err) {
|
|
19
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
20
|
+
setError(errorObj);
|
|
21
|
+
setStatus('error');
|
|
22
|
+
throw errorObj;
|
|
23
|
+
}
|
|
24
|
+
}, [config]);
|
|
25
|
+
(0, react_1.useEffect)(() => {
|
|
26
|
+
if (autoInitialize && status === 'idle') {
|
|
27
|
+
initialize().catch(() => {
|
|
28
|
+
// Error state already captured in state
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
}, [autoInitialize, status, initialize]);
|
|
32
|
+
const value = (0, react_1.useMemo)(() => ({
|
|
33
|
+
status,
|
|
34
|
+
isReady: status === 'ready',
|
|
35
|
+
error,
|
|
36
|
+
initialize,
|
|
37
|
+
service: ocrService_js_1.defaultOcrService,
|
|
38
|
+
}), [status, error, initialize]);
|
|
39
|
+
return (0, jsx_runtime_1.jsx)(RustoContext_js_1.RustoContext.Provider, { value: value, children: children });
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=RustoProvider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RustoProvider.js","sourceRoot":"","sources":["../../src/context/RustoProvider.tsx"],"names":[],"mappings":";;AAgBA,sCA6CC;;AA7DD,iCAMe;AAEf,uDAAiD;AACjD,6DAA8D;AAO9D,SAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,MAAM,EACN,cAAc,GAAG,IAAI,GACF;IACnB,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,IAAA,gBAAQ,EAAc,MAAM,CAAC,CAAC;IAC1D,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,UAAU,GAAG,IAAA,mBAAW,EAC5B,KAAK,EAAE,cAAiC,EAAiB,EAAE;QACzD,IAAI,CAAC;YACH,SAAS,CAAC,cAAc,CAAC,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,CAAC;YACf,MAAM,iCAAiB,CAAC,IAAI,CAAC,cAAc,IAAI,MAAM,CAAC,CAAC;YACvD,SAAS,CAAC,OAAO,CAAC,CAAC;QACrB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,SAAS,CAAC,OAAO,CAAC,CAAC;YACnB,MAAM,QAAQ,CAAC;QACjB,CAAC;IACH,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,IAAA,iBAAS,EAAC,GAAG,EAAE;QACb,IAAI,cAAc,IAAI,MAAM,KAAK,MAAM,EAAE,CAAC;YACxC,UAAU,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE;gBACtB,wCAAwC;YAC1C,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IAEzC,MAAM,KAAK,GAAsB,IAAA,eAAO,EACtC,GAAG,EAAE,CAAC,CAAC;QACL,MAAM;QACN,OAAO,EAAE,MAAM,KAAK,OAAO;QAC3B,KAAK;QACL,UAAU;QACV,OAAO,EAAE,iCAAiB;KAC3B,CAAC,EACF,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAC5B,CAAC;IAEF,OAAO,uBAAC,8BAAY,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,YAAG,QAAQ,GAAyB,CAAC;AACjF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOcr.d.ts","sourceRoot":"","sources":["../../src/hooks/useOcr.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAErE,wBAAgB,MAAM,CAAC,OAAO,GAAE,aAAkB,GAAG,YAAY,CA8DhE"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useOcr = useOcr;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const RustoContext_js_1 = require("../context/RustoContext.js");
|
|
6
|
+
const ocrService_js_1 = require("../services/ocrService.js");
|
|
7
|
+
function useOcr(options = {}) {
|
|
8
|
+
const context = (0, react_1.useContext)(RustoContext_js_1.RustoContext);
|
|
9
|
+
const service = context?.service || ocrService_js_1.defaultOcrService;
|
|
10
|
+
const [results, setResults] = (0, react_1.useState)([]);
|
|
11
|
+
const [spatialText, setSpatialText] = (0, react_1.useState)('');
|
|
12
|
+
const [isProcessing, setIsProcessing] = (0, react_1.useState)(false);
|
|
13
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
14
|
+
const reset = (0, react_1.useCallback)(() => {
|
|
15
|
+
setResults([]);
|
|
16
|
+
setSpatialText('');
|
|
17
|
+
setIsProcessing(false);
|
|
18
|
+
setError(null);
|
|
19
|
+
}, []);
|
|
20
|
+
const detect = (0, react_1.useCallback)(async (source, overrideOptions) => {
|
|
21
|
+
setIsProcessing(true);
|
|
22
|
+
setError(null);
|
|
23
|
+
const mergedOptions = {
|
|
24
|
+
...options,
|
|
25
|
+
...overrideOptions,
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
const output = await service.detect(source, mergedOptions);
|
|
29
|
+
if (typeof output === 'string') {
|
|
30
|
+
setSpatialText(output);
|
|
31
|
+
setResults([]);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
setResults(output);
|
|
35
|
+
setSpatialText('');
|
|
36
|
+
}
|
|
37
|
+
options.onSuccess?.(output);
|
|
38
|
+
return output;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
const errorObj = err instanceof Error ? err : new Error(String(err));
|
|
42
|
+
setError(errorObj);
|
|
43
|
+
options.onError?.(errorObj);
|
|
44
|
+
throw errorObj;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
setIsProcessing(false);
|
|
48
|
+
}
|
|
49
|
+
}, [options, service]);
|
|
50
|
+
return {
|
|
51
|
+
detect,
|
|
52
|
+
results,
|
|
53
|
+
spatialText,
|
|
54
|
+
isProcessing,
|
|
55
|
+
error,
|
|
56
|
+
reset,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=useOcr.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOcr.js","sourceRoot":"","sources":["../../src/hooks/useOcr.ts"],"names":[],"mappings":";;AAUA,wBA8DC;AAxED,iCAA0D;AAM1D,gEAA0D;AAC1D,6DAA8D;AAG9D,SAAgB,MAAM,CAAC,UAAyB,EAAE;IAChD,MAAM,OAAO,GAAG,IAAA,kBAAU,EAAC,8BAAY,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,iCAAiB,CAAC;IAEtD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,IAAA,gBAAQ,EAAe,EAAE,CAAC,CAAC;IACzD,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,IAAA,gBAAQ,EAAS,EAAE,CAAC,CAAC;IAC3D,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,IAAA,gBAAQ,EAAU,KAAK,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,IAAA,gBAAQ,EAAe,IAAI,CAAC,CAAC;IAEvD,MAAM,KAAK,GAAG,IAAA,mBAAW,EAAC,GAAG,EAAE;QAC7B,UAAU,CAAC,EAAE,CAAC,CAAC;QACf,cAAc,CAAC,EAAE,CAAC,CAAC;QACnB,eAAe,CAAC,KAAK,CAAC,CAAC;QACvB,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,MAAM,GAAG,IAAA,mBAAW,EACxB,KAAK,EACH,MAAmB,EACnB,eAAmC,EACH,EAAE;QAClC,eAAe,CAAC,IAAI,CAAC,CAAC;QACtB,QAAQ,CAAC,IAAI,CAAC,CAAC;QAEf,MAAM,aAAa,GAAsB;YACvC,GAAG,OAAO;YACV,GAAG,eAAe;SACnB,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;YAE3D,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;gBAC/B,cAAc,CAAC,MAAM,CAAC,CAAC;gBACvB,UAAU,CAAC,EAAE,CAAC,CAAC;YACjB,CAAC;iBAAM,CAAC;gBACN,UAAU,CAAC,MAAM,CAAC,CAAC;gBACnB,cAAc,CAAC,EAAE,CAAC,CAAC;YACrB,CAAC;YAED,OAAO,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,CAAC;YAC5B,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,QAAQ,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YACrE,QAAQ,CAAC,QAAQ,CAAC,CAAC;YACnB,OAAO,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC;YAC5B,MAAM,QAAQ,CAAC;QACjB,CAAC;gBAAS,CAAC;YACT,eAAe,CAAC,KAAK,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,EACD,CAAC,OAAO,EAAE,OAAO,CAAC,CACnB,CAAC;IAEF,OAAO;QACL,MAAM;QACN,OAAO;QACP,WAAW;QACX,YAAY;QACZ,KAAK;QACL,KAAK;KACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRusto.d.ts","sourceRoot":"","sources":["../../src/hooks/useRusto.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useRusto = useRusto;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const RustoContext_js_1 = require("../context/RustoContext.js");
|
|
6
|
+
function useRusto() {
|
|
7
|
+
const context = (0, react_1.useContext)(RustoContext_js_1.RustoContext);
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw new Error('useRusto must be used within a RustoProvider.');
|
|
10
|
+
}
|
|
11
|
+
return context;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=useRusto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useRusto.js","sourceRoot":"","sources":["../../src/hooks/useRusto.ts"],"names":[],"mappings":";;AAIA,4BAMC;AAVD,iCAAmC;AACnC,gEAA0D;AAG1D,SAAgB,QAAQ;IACtB,MAAM,OAAO,GAAG,IAAA,kBAAU,EAAC,8BAAY,CAAC,CAAC;IACzC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export { RustoProvider } from './context/RustoProvider.js';
|
|
2
|
+
export { RustoContext } from './context/RustoContext.js';
|
|
3
|
+
export { useRusto } from './hooks/useRusto.js';
|
|
4
|
+
export { useOcr } from './hooks/useOcr.js';
|
|
5
|
+
export { OcrService, defaultOcrService } from './services/ocrService.js';
|
|
6
|
+
export { OcrOverlay } from './components/OcrOverlay.js';
|
|
7
|
+
export { BoundingBox } from './components/BoundingBox.js';
|
|
8
|
+
export { OcrDropzone } from './components/OcrDropzone.js';
|
|
9
|
+
export { DropzonePrompt } from './components/DropzonePrompt.js';
|
|
10
|
+
export { DropzonePreview } from './components/DropzonePreview.js';
|
|
11
|
+
export { scaleFrame, scaleQuad, calculateScale } from './utils/geometry.js';
|
|
12
|
+
export { resultsToText, resultsToCsv, resultsToJson } from './utils/formatters.js';
|
|
13
|
+
export * from './types/index.js';
|
|
14
|
+
export type { TextResult, Frame, ImageSource, DetectTextOptions, InitializeConfig, ModelPreset, } from '@rustors/web';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAGzD,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAG3C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAGzE,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAGnF,cAAc,kBAAkB,CAAC;AAGjC,YAAY,EACV,UAAU,EACV,KAAK,EACL,WAAW,EACX,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,GACZ,MAAM,cAAc,CAAC"}
|