@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/dist/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.resultsToJson = exports.resultsToCsv = exports.resultsToText = exports.calculateScale = exports.scaleQuad = exports.scaleFrame = exports.DropzonePreview = exports.DropzonePrompt = exports.OcrDropzone = exports.BoundingBox = exports.OcrOverlay = exports.defaultOcrService = exports.OcrService = exports.useOcr = exports.useRusto = exports.RustoContext = exports.RustoProvider = void 0;
|
|
18
|
+
// Provider & Context
|
|
19
|
+
var RustoProvider_js_1 = require("./context/RustoProvider.js");
|
|
20
|
+
Object.defineProperty(exports, "RustoProvider", { enumerable: true, get: function () { return RustoProvider_js_1.RustoProvider; } });
|
|
21
|
+
var RustoContext_js_1 = require("./context/RustoContext.js");
|
|
22
|
+
Object.defineProperty(exports, "RustoContext", { enumerable: true, get: function () { return RustoContext_js_1.RustoContext; } });
|
|
23
|
+
// Hooks
|
|
24
|
+
var useRusto_js_1 = require("./hooks/useRusto.js");
|
|
25
|
+
Object.defineProperty(exports, "useRusto", { enumerable: true, get: function () { return useRusto_js_1.useRusto; } });
|
|
26
|
+
var useOcr_js_1 = require("./hooks/useOcr.js");
|
|
27
|
+
Object.defineProperty(exports, "useOcr", { enumerable: true, get: function () { return useOcr_js_1.useOcr; } });
|
|
28
|
+
// Services
|
|
29
|
+
var ocrService_js_1 = require("./services/ocrService.js");
|
|
30
|
+
Object.defineProperty(exports, "OcrService", { enumerable: true, get: function () { return ocrService_js_1.OcrService; } });
|
|
31
|
+
Object.defineProperty(exports, "defaultOcrService", { enumerable: true, get: function () { return ocrService_js_1.defaultOcrService; } });
|
|
32
|
+
// UI Components
|
|
33
|
+
var OcrOverlay_js_1 = require("./components/OcrOverlay.js");
|
|
34
|
+
Object.defineProperty(exports, "OcrOverlay", { enumerable: true, get: function () { return OcrOverlay_js_1.OcrOverlay; } });
|
|
35
|
+
var BoundingBox_js_1 = require("./components/BoundingBox.js");
|
|
36
|
+
Object.defineProperty(exports, "BoundingBox", { enumerable: true, get: function () { return BoundingBox_js_1.BoundingBox; } });
|
|
37
|
+
var OcrDropzone_js_1 = require("./components/OcrDropzone.js");
|
|
38
|
+
Object.defineProperty(exports, "OcrDropzone", { enumerable: true, get: function () { return OcrDropzone_js_1.OcrDropzone; } });
|
|
39
|
+
var DropzonePrompt_js_1 = require("./components/DropzonePrompt.js");
|
|
40
|
+
Object.defineProperty(exports, "DropzonePrompt", { enumerable: true, get: function () { return DropzonePrompt_js_1.DropzonePrompt; } });
|
|
41
|
+
var DropzonePreview_js_1 = require("./components/DropzonePreview.js");
|
|
42
|
+
Object.defineProperty(exports, "DropzonePreview", { enumerable: true, get: function () { return DropzonePreview_js_1.DropzonePreview; } });
|
|
43
|
+
// Geometry & Formatters
|
|
44
|
+
var geometry_js_1 = require("./utils/geometry.js");
|
|
45
|
+
Object.defineProperty(exports, "scaleFrame", { enumerable: true, get: function () { return geometry_js_1.scaleFrame; } });
|
|
46
|
+
Object.defineProperty(exports, "scaleQuad", { enumerable: true, get: function () { return geometry_js_1.scaleQuad; } });
|
|
47
|
+
Object.defineProperty(exports, "calculateScale", { enumerable: true, get: function () { return geometry_js_1.calculateScale; } });
|
|
48
|
+
var formatters_js_1 = require("./utils/formatters.js");
|
|
49
|
+
Object.defineProperty(exports, "resultsToText", { enumerable: true, get: function () { return formatters_js_1.resultsToText; } });
|
|
50
|
+
Object.defineProperty(exports, "resultsToCsv", { enumerable: true, get: function () { return formatters_js_1.resultsToCsv; } });
|
|
51
|
+
Object.defineProperty(exports, "resultsToJson", { enumerable: true, get: function () { return formatters_js_1.resultsToJson; } });
|
|
52
|
+
// Types
|
|
53
|
+
__exportStar(require("./types/index.js"), exports);
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,qBAAqB;AACrB,+DAA2D;AAAlD,iHAAA,aAAa,OAAA;AACtB,6DAAyD;AAAhD,+GAAA,YAAY,OAAA;AAErB,QAAQ;AACR,mDAA+C;AAAtC,uGAAA,QAAQ,OAAA;AACjB,+CAA2C;AAAlC,mGAAA,MAAM,OAAA;AAEf,WAAW;AACX,0DAAyE;AAAhE,2GAAA,UAAU,OAAA;AAAE,kHAAA,iBAAiB,OAAA;AAEtC,gBAAgB;AAChB,4DAAwD;AAA/C,2GAAA,UAAU,OAAA;AACnB,8DAA0D;AAAjD,6GAAA,WAAW,OAAA;AACpB,8DAA0D;AAAjD,6GAAA,WAAW,OAAA;AACpB,oEAAgE;AAAvD,mHAAA,cAAc,OAAA;AACvB,sEAAkE;AAAzD,qHAAA,eAAe,OAAA;AAExB,wBAAwB;AACxB,mDAA4E;AAAnE,yGAAA,UAAU,OAAA;AAAE,wGAAA,SAAS,OAAA;AAAE,6GAAA,cAAc,OAAA;AAC9C,uDAAmF;AAA1E,8GAAA,aAAa,OAAA;AAAE,6GAAA,YAAY,OAAA;AAAE,8GAAA,aAAa,OAAA;AAEnD,QAAQ;AACR,mDAAiC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { WebOcrEngine, type DetectTextOptions, type ImageSource, type InitializeConfig, type TextResult } from '@rustors/web';
|
|
2
|
+
export declare class OcrService {
|
|
3
|
+
private engine;
|
|
4
|
+
constructor(engineInstance?: WebOcrEngine);
|
|
5
|
+
init(config?: InitializeConfig): Promise<void>;
|
|
6
|
+
isReady(): boolean;
|
|
7
|
+
detect(source: ImageSource, options?: DetectTextOptions): Promise<TextResult[] | string>;
|
|
8
|
+
terminate(): void;
|
|
9
|
+
getEngine(): WebOcrEngine;
|
|
10
|
+
}
|
|
11
|
+
export declare const defaultOcrService: OcrService;
|
|
12
|
+
//# sourceMappingURL=ocrService.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocrService.d.ts","sourceRoot":"","sources":["../../src/services/ocrService.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EAChB,MAAM,cAAc,CAAC;AAEtB,qBAAa,UAAU;IACrB,OAAO,CAAC,MAAM,CAAe;gBAEjB,cAAc,CAAC,EAAE,YAAY;IAI5B,IAAI,CAAC,MAAM,CAAC,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIpD,OAAO,IAAI,OAAO;IAIZ,MAAM,CACjB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE,iBAAiB,GAC1B,OAAO,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC;IAO1B,SAAS,IAAI,IAAI;IAIjB,SAAS,IAAI,YAAY;CAGjC;AAED,eAAO,MAAM,iBAAiB,YAAmB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.defaultOcrService = exports.OcrService = void 0;
|
|
4
|
+
const web_1 = require("@rustors/web");
|
|
5
|
+
class OcrService {
|
|
6
|
+
constructor(engineInstance) {
|
|
7
|
+
this.engine = engineInstance || new web_1.WebOcrEngine();
|
|
8
|
+
}
|
|
9
|
+
async init(config) {
|
|
10
|
+
await this.engine.initialize(config);
|
|
11
|
+
}
|
|
12
|
+
isReady() {
|
|
13
|
+
return this.engine.isInitialized();
|
|
14
|
+
}
|
|
15
|
+
async detect(source, options) {
|
|
16
|
+
if (!this.engine.isInitialized()) {
|
|
17
|
+
throw new Error('OCR Service engine is not ready. Call init() first.');
|
|
18
|
+
}
|
|
19
|
+
return this.engine.detectText(source, options);
|
|
20
|
+
}
|
|
21
|
+
terminate() {
|
|
22
|
+
this.engine.terminate();
|
|
23
|
+
}
|
|
24
|
+
getEngine() {
|
|
25
|
+
return this.engine;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.OcrService = OcrService;
|
|
29
|
+
exports.defaultOcrService = new OcrService();
|
|
30
|
+
//# sourceMappingURL=ocrService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ocrService.js","sourceRoot":"","sources":["../../src/services/ocrService.ts"],"names":[],"mappings":";;;AAAA,sCAMsB;AAEtB,MAAa,UAAU;IAGrB,YAAY,cAA6B;QACvC,IAAI,CAAC,MAAM,GAAG,cAAc,IAAI,IAAI,kBAAY,EAAE,CAAC;IACrD,CAAC;IAEM,KAAK,CAAC,IAAI,CAAC,MAAyB;QACzC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IACvC,CAAC;IAEM,OAAO;QACZ,OAAO,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC;IACrC,CAAC;IAEM,KAAK,CAAC,MAAM,CACjB,MAAmB,EACnB,OAA2B;QAE3B,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;QACzE,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAEM,SAAS;QACd,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;IAC1B,CAAC;IAEM,SAAS;QACd,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;CACF;AAhCD,gCAgCC;AAEY,QAAA,iBAAiB,GAAG,IAAI,UAAU,EAAE,CAAC"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
import type { TextResult, DetectTextOptions } from '@rustors/web';
|
|
3
|
+
export interface BoundingBoxProps {
|
|
4
|
+
item: TextResult;
|
|
5
|
+
scaleX: number;
|
|
6
|
+
scaleY: number;
|
|
7
|
+
highlightColor?: string;
|
|
8
|
+
showTooltip?: boolean;
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
onClick?: (item: TextResult) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface OcrOverlayProps {
|
|
14
|
+
imageSrc: string;
|
|
15
|
+
results: TextResult[];
|
|
16
|
+
naturalWidth?: number;
|
|
17
|
+
naturalHeight?: number;
|
|
18
|
+
highlightColor?: string;
|
|
19
|
+
showTooltips?: boolean;
|
|
20
|
+
className?: string;
|
|
21
|
+
style?: CSSProperties;
|
|
22
|
+
onItemClick?: (item: TextResult) => void;
|
|
23
|
+
}
|
|
24
|
+
export interface DropzonePromptProps {
|
|
25
|
+
title?: string;
|
|
26
|
+
subtitle?: string;
|
|
27
|
+
icon?: ReactNode;
|
|
28
|
+
className?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface DropzonePreviewProps {
|
|
31
|
+
previewUrl: string;
|
|
32
|
+
onClear: () => void;
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface OcrDropzoneProps {
|
|
36
|
+
onFileSelect?: (file: File) => void;
|
|
37
|
+
onDetect?: (results: TextResult[] | string) => void;
|
|
38
|
+
autoDetect?: boolean;
|
|
39
|
+
detectOptions?: DetectTextOptions;
|
|
40
|
+
accept?: string;
|
|
41
|
+
className?: string;
|
|
42
|
+
style?: CSSProperties;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=components.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.d.ts","sourceRoot":"","sources":["../../src/types/components.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAElE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,UAAU,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC;CAC1C;AAED,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAC/B,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IACpC,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,KAAK,IAAI,CAAC;IACpD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,aAAa,CAAC,EAAE,iBAAiB,CAAC;IAClC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,aAAa,CAAC;CACvB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"components.js","sourceRoot":"","sources":["../../src/types/components.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { InitializeConfig } from '@rustors/web';
|
|
2
|
+
import type { OcrService } from '../services/ocrService.js';
|
|
3
|
+
export type RustoStatus = 'idle' | 'initializing' | 'ready' | 'error';
|
|
4
|
+
export interface RustoContextValue {
|
|
5
|
+
status: RustoStatus;
|
|
6
|
+
isReady: boolean;
|
|
7
|
+
error: Error | null;
|
|
8
|
+
initialize: (config?: InitializeConfig) => Promise<void>;
|
|
9
|
+
service: OcrService;
|
|
10
|
+
}
|
|
11
|
+
export interface RustoProviderProps {
|
|
12
|
+
children: React.ReactNode;
|
|
13
|
+
config?: InitializeConfig;
|
|
14
|
+
autoInitialize?: boolean;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/types/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,cAAc,GAAG,OAAO,GAAG,OAAO,CAAC;AAEtE,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,UAAU,EAAE,CAAC,MAAM,CAAC,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,OAAO,EAAE,UAAU,CAAC;CACrB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/types/context.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DetectTextOptions, ImageSource, TextResult } from '@rustors/web';
|
|
2
|
+
export interface UseOcrOptions extends DetectTextOptions {
|
|
3
|
+
onSuccess?: (results: TextResult[] | string) => void;
|
|
4
|
+
onError?: (error: Error) => void;
|
|
5
|
+
}
|
|
6
|
+
export interface UseOcrReturn {
|
|
7
|
+
detect: (source: ImageSource, overrideOptions?: DetectTextOptions) => Promise<TextResult[] | string>;
|
|
8
|
+
results: TextResult[];
|
|
9
|
+
spatialText: string;
|
|
10
|
+
isProcessing: boolean;
|
|
11
|
+
error: Error | null;
|
|
12
|
+
reset: () => void;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,UAAU,EACX,MAAM,cAAc,CAAC;AAEtB,MAAM,WAAW,aAAc,SAAQ,iBAAiB;IACtD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,KAAK,IAAI,CAAC;IACrD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,CACN,MAAM,EAAE,WAAW,EACnB,eAAe,CAAC,EAAE,iBAAiB,KAChC,OAAO,CAAC,UAAU,EAAE,GAAG,MAAM,CAAC,CAAC;IACpC,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,OAAO,CAAC;IACtB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,KAAK,EAAE,MAAM,IAAI,CAAC;CACnB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/types/hooks.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,YAAY,CAAC;AAC3B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./context.js"), exports);
|
|
18
|
+
__exportStar(require("./hooks.js"), exports);
|
|
19
|
+
__exportStar(require("./components.js"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,6CAA2B;AAC3B,kDAAgC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TextResult } from '@rustors/web';
|
|
2
|
+
/**
|
|
3
|
+
* Combines all recognized text tokens into a single text block.
|
|
4
|
+
*/
|
|
5
|
+
export declare function resultsToText(results: TextResult[]): string;
|
|
6
|
+
/**
|
|
7
|
+
* Formats OCR results into standard CSV with bounding box coordinates and scores.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resultsToCsv(results: TextResult[]): string;
|
|
10
|
+
/**
|
|
11
|
+
* Pretty formats OCR results as a JSON string.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resultsToJson(results: TextResult[], indent?: number): string;
|
|
14
|
+
//# sourceMappingURL=formatters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.d.ts","sourceRoot":"","sources":["../../src/utils/formatters.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAE3D;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,CAO1D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,MAAM,GAAE,MAAU,GAAG,MAAM,CAE/E"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.resultsToText = resultsToText;
|
|
4
|
+
exports.resultsToCsv = resultsToCsv;
|
|
5
|
+
exports.resultsToJson = resultsToJson;
|
|
6
|
+
/**
|
|
7
|
+
* Combines all recognized text tokens into a single text block.
|
|
8
|
+
*/
|
|
9
|
+
function resultsToText(results) {
|
|
10
|
+
return results.map((r) => r.text).join('\n');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Formats OCR results into standard CSV with bounding box coordinates and scores.
|
|
14
|
+
*/
|
|
15
|
+
function resultsToCsv(results) {
|
|
16
|
+
const header = 'text,score,left,top,width,height';
|
|
17
|
+
const rows = results.map((r) => {
|
|
18
|
+
const escapedText = `"${r.text.replace(/"/g, '""')}"`;
|
|
19
|
+
return `${escapedText},${r.score.toFixed(4)},${r.frame.left},${r.frame.top},${r.frame.width},${r.frame.height}`;
|
|
20
|
+
});
|
|
21
|
+
return [header, ...rows].join('\n');
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Pretty formats OCR results as a JSON string.
|
|
25
|
+
*/
|
|
26
|
+
function resultsToJson(results, indent = 2) {
|
|
27
|
+
return JSON.stringify(results, null, indent);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=formatters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatters.js","sourceRoot":"","sources":["../../src/utils/formatters.ts"],"names":[],"mappings":";;AAKA,sCAEC;AAKD,oCAOC;AAKD,sCAEC;AAxBD;;GAEG;AACH,SAAgB,aAAa,CAAC,OAAqB;IACjD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,SAAgB,YAAY,CAAC,OAAqB;IAChD,MAAM,MAAM,GAAG,kCAAkC,CAAC;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QAC7B,MAAM,WAAW,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC;QACtD,OAAO,GAAG,WAAW,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;IAClH,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAgB,aAAa,CAAC,OAAqB,EAAE,SAAiB,CAAC;IACrE,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Frame } from '@rustors/web';
|
|
2
|
+
export type QuadPoints = [[number, number], [number, number], [number, number], [number, number]];
|
|
3
|
+
export declare function scaleFrame(frame: Frame, scaleX: number, scaleY: number): Frame;
|
|
4
|
+
export declare function scaleQuad(quad: QuadPoints, scaleX: number, scaleY: number): QuadPoints;
|
|
5
|
+
export declare function calculateScale(naturalWidth: number, naturalHeight: number, renderWidth: number, renderHeight: number): {
|
|
6
|
+
scaleX: number;
|
|
7
|
+
scaleY: number;
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=geometry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.d.ts","sourceRoot":"","sources":["../../src/utils/geometry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAElG,wBAAgB,UAAU,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,KAAK,CAO9E;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,UAAU,CAOtF;AAED,wBAAgB,cAAc,CAC5B,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAQpC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.scaleFrame = scaleFrame;
|
|
4
|
+
exports.scaleQuad = scaleQuad;
|
|
5
|
+
exports.calculateScale = calculateScale;
|
|
6
|
+
function scaleFrame(frame, scaleX, scaleY) {
|
|
7
|
+
return {
|
|
8
|
+
left: Math.round(frame.left * scaleX * 100) / 100,
|
|
9
|
+
top: Math.round(frame.top * scaleY * 100) / 100,
|
|
10
|
+
width: Math.round(frame.width * scaleX * 100) / 100,
|
|
11
|
+
height: Math.round(frame.height * scaleY * 100) / 100,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
function scaleQuad(quad, scaleX, scaleY) {
|
|
15
|
+
return [
|
|
16
|
+
[Math.round(quad[0][0] * scaleX * 100) / 100, Math.round(quad[0][1] * scaleY * 100) / 100],
|
|
17
|
+
[Math.round(quad[1][0] * scaleX * 100) / 100, Math.round(quad[1][1] * scaleY * 100) / 100],
|
|
18
|
+
[Math.round(quad[2][0] * scaleX * 100) / 100, Math.round(quad[2][1] * scaleY * 100) / 100],
|
|
19
|
+
[Math.round(quad[3][0] * scaleX * 100) / 100, Math.round(quad[3][1] * scaleY * 100) / 100],
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
function calculateScale(naturalWidth, naturalHeight, renderWidth, renderHeight) {
|
|
23
|
+
if (naturalWidth <= 0 || naturalHeight <= 0 || renderWidth <= 0 || renderHeight <= 0) {
|
|
24
|
+
return { scaleX: 1, scaleY: 1 };
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
scaleX: renderWidth / naturalWidth,
|
|
28
|
+
scaleY: renderHeight / naturalHeight,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=geometry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"geometry.js","sourceRoot":"","sources":["../../src/utils/geometry.ts"],"names":[],"mappings":";;AAIA,gCAOC;AAED,8BAOC;AAED,wCAaC;AA/BD,SAAgB,UAAU,CAAC,KAAY,EAAE,MAAc,EAAE,MAAc;IACrE,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG;QACjD,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG;QAC/C,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG;QACnD,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG;KACtD,CAAC;AACJ,CAAC;AAED,SAAgB,SAAS,CAAC,IAAgB,EAAE,MAAc,EAAE,MAAc;IACxE,OAAO;QACL,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC1F,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC1F,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;QAC1F,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;KAC3F,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc,CAC5B,YAAoB,EACpB,aAAqB,EACrB,WAAmB,EACnB,YAAoB;IAEpB,IAAI,YAAY,IAAI,CAAC,IAAI,aAAa,IAAI,CAAC,IAAI,WAAW,IAAI,CAAC,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACrF,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IAClC,CAAC;IACD,OAAO;QACL,MAAM,EAAE,WAAW,GAAG,YAAY;QAClC,MAAM,EAAE,YAAY,GAAG,aAAa;KACrC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rustors/react",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "React hooks, provider, and UI components for RustO! OCR engine",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ocr",
|
|
7
|
+
"rusto",
|
|
8
|
+
"react",
|
|
9
|
+
"hooks",
|
|
10
|
+
"components",
|
|
11
|
+
"text-recognition",
|
|
12
|
+
"typescript"
|
|
13
|
+
],
|
|
14
|
+
"homepage": "https://github.com/byrizki/rusto-rs#readme",
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/byrizki/rusto-rs/issues"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"author": "byrizki <contact@byrizki.com> (https://github.com/byrizki)",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/byrizki/rusto-rs.git",
|
|
23
|
+
"directory": "packages/react"
|
|
24
|
+
},
|
|
25
|
+
"main": "dist/index.js",
|
|
26
|
+
"module": "dist/index.mjs",
|
|
27
|
+
"types": "dist/index.d.ts",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
31
|
+
"import": "./dist/index.mjs",
|
|
32
|
+
"require": "./dist/index.js"
|
|
33
|
+
},
|
|
34
|
+
"./package.json": "./package.json"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"src",
|
|
39
|
+
"README.md",
|
|
40
|
+
"LICENSE"
|
|
41
|
+
],
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public",
|
|
44
|
+
"registry": "https://registry.npmjs.org/"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsc -p tsconfig.build.json",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"clean": "rm -rf dist"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"react": ">=18.0.0",
|
|
53
|
+
"@rustors/web": ">=0.2.5"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/react": "^18.2.0",
|
|
57
|
+
"react": "^18.2.0",
|
|
58
|
+
"@rustors/web": "file:../web",
|
|
59
|
+
"typescript": "^5.0.2"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { BoundingBoxProps } from '../types/index.js';
|
|
3
|
+
import { scaleFrame } from '../utils/geometry.js';
|
|
4
|
+
|
|
5
|
+
export function BoundingBox({
|
|
6
|
+
item,
|
|
7
|
+
scaleX,
|
|
8
|
+
scaleY,
|
|
9
|
+
highlightColor = 'rgba(59, 130, 246, 0.4)',
|
|
10
|
+
showTooltip = true,
|
|
11
|
+
className,
|
|
12
|
+
style,
|
|
13
|
+
onClick,
|
|
14
|
+
}: BoundingBoxProps): ReactElement {
|
|
15
|
+
const scaled = scaleFrame(item.frame, scaleX, scaleY);
|
|
16
|
+
|
|
17
|
+
const boxStyle: React.CSSProperties = {
|
|
18
|
+
position: 'absolute',
|
|
19
|
+
left: `${scaled.left}px`,
|
|
20
|
+
top: `${scaled.top}px`,
|
|
21
|
+
width: `${scaled.width}px`,
|
|
22
|
+
height: `${scaled.height}px`,
|
|
23
|
+
border: `1.5px solid ${highlightColor}`,
|
|
24
|
+
backgroundColor: highlightColor.replace(/[\d.]+\)$/, '0.15)'),
|
|
25
|
+
cursor: onClick ? 'pointer' : 'default',
|
|
26
|
+
pointerEvents: 'auto',
|
|
27
|
+
boxSizing: 'border-box',
|
|
28
|
+
borderRadius: '2px',
|
|
29
|
+
...style,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const tooltipStyle: React.CSSProperties = {
|
|
33
|
+
position: 'absolute',
|
|
34
|
+
bottom: '100%',
|
|
35
|
+
left: '0',
|
|
36
|
+
backgroundColor: '#1f2937',
|
|
37
|
+
color: '#ffffff',
|
|
38
|
+
fontSize: '11px',
|
|
39
|
+
lineHeight: '1.2',
|
|
40
|
+
padding: '2px 6px',
|
|
41
|
+
borderRadius: '4px',
|
|
42
|
+
whiteSpace: 'nowrap',
|
|
43
|
+
pointerEvents: 'none',
|
|
44
|
+
zIndex: 10,
|
|
45
|
+
transform: 'translateY(-2px)',
|
|
46
|
+
boxShadow: '0 2px 4px rgba(0,0,0,0.2)',
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<div
|
|
51
|
+
className={className}
|
|
52
|
+
style={boxStyle}
|
|
53
|
+
onClick={() => onClick?.(item)}
|
|
54
|
+
title={`${item.text} (${Math.round(item.score * 100)}%)`}
|
|
55
|
+
>
|
|
56
|
+
{showTooltip && (
|
|
57
|
+
<span style={tooltipStyle}>
|
|
58
|
+
{item.text} <small style={{ opacity: 0.75 }}>({Math.round(item.score * 100)}%)</small>
|
|
59
|
+
</span>
|
|
60
|
+
)}
|
|
61
|
+
</div>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { DropzonePreviewProps } from '../types/index.js';
|
|
3
|
+
|
|
4
|
+
export function DropzonePreview({
|
|
5
|
+
previewUrl,
|
|
6
|
+
onClear,
|
|
7
|
+
className,
|
|
8
|
+
}: DropzonePreviewProps): ReactElement {
|
|
9
|
+
return (
|
|
10
|
+
<div
|
|
11
|
+
className={className}
|
|
12
|
+
style={{
|
|
13
|
+
position: 'relative',
|
|
14
|
+
display: 'flex',
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
justifyContent: 'center',
|
|
17
|
+
padding: '12px',
|
|
18
|
+
width: '100%',
|
|
19
|
+
boxSizing: 'border-box',
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
<img
|
|
23
|
+
src={previewUrl}
|
|
24
|
+
alt="Uploaded Preview"
|
|
25
|
+
style={{
|
|
26
|
+
maxHeight: '260px',
|
|
27
|
+
maxWidth: '100%',
|
|
28
|
+
objectFit: 'contain',
|
|
29
|
+
borderRadius: '4px',
|
|
30
|
+
}}
|
|
31
|
+
/>
|
|
32
|
+
<button
|
|
33
|
+
type="button"
|
|
34
|
+
onClick={(e) => {
|
|
35
|
+
e.stopPropagation();
|
|
36
|
+
onClear();
|
|
37
|
+
}}
|
|
38
|
+
style={{
|
|
39
|
+
position: 'absolute',
|
|
40
|
+
top: '16px',
|
|
41
|
+
right: '16px',
|
|
42
|
+
backgroundColor: 'rgba(0, 0, 0, 0.65)',
|
|
43
|
+
color: '#ffffff',
|
|
44
|
+
border: 'none',
|
|
45
|
+
borderRadius: '50%',
|
|
46
|
+
width: '28px',
|
|
47
|
+
height: '28px',
|
|
48
|
+
display: 'flex',
|
|
49
|
+
alignItems: 'center',
|
|
50
|
+
justifyContent: 'center',
|
|
51
|
+
cursor: 'pointer',
|
|
52
|
+
fontSize: '14px',
|
|
53
|
+
lineHeight: 1,
|
|
54
|
+
}}
|
|
55
|
+
aria-label="Remove image"
|
|
56
|
+
>
|
|
57
|
+
×
|
|
58
|
+
</button>
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { type ReactElement } from 'react';
|
|
2
|
+
import type { DropzonePromptProps } from '../types/index.js';
|
|
3
|
+
|
|
4
|
+
export function DropzonePrompt({
|
|
5
|
+
title = 'Click or drag image here to scan',
|
|
6
|
+
subtitle = 'Supports PNG, JPEG, WebP, and document scans',
|
|
7
|
+
icon,
|
|
8
|
+
className,
|
|
9
|
+
}: DropzonePromptProps): ReactElement {
|
|
10
|
+
return (
|
|
11
|
+
<div
|
|
12
|
+
className={className}
|
|
13
|
+
style={{
|
|
14
|
+
display: 'flex',
|
|
15
|
+
flexDirection: 'column',
|
|
16
|
+
alignItems: 'center',
|
|
17
|
+
justifyContent: 'center',
|
|
18
|
+
padding: '32px 16px',
|
|
19
|
+
textAlign: 'center',
|
|
20
|
+
pointerEvents: 'none',
|
|
21
|
+
}}
|
|
22
|
+
>
|
|
23
|
+
{icon || (
|
|
24
|
+
<svg
|
|
25
|
+
style={{ width: '40px', height: '40px', color: '#6b7280', marginBottom: '12px' }}
|
|
26
|
+
fill="none"
|
|
27
|
+
stroke="currentColor"
|
|
28
|
+
viewBox="0 0 24 24"
|
|
29
|
+
>
|
|
30
|
+
<path
|
|
31
|
+
strokeLinecap="round"
|
|
32
|
+
strokeLinejoin="round"
|
|
33
|
+
strokeWidth={1.5}
|
|
34
|
+
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"
|
|
35
|
+
/>
|
|
36
|
+
</svg>
|
|
37
|
+
)}
|
|
38
|
+
<p style={{ margin: '0 0 4px', fontSize: '14px', fontWeight: 600, color: '#374151' }}>
|
|
39
|
+
{title}
|
|
40
|
+
</p>
|
|
41
|
+
<p style={{ margin: 0, fontSize: '12px', color: '#6b7280' }}>
|
|
42
|
+
{subtitle}
|
|
43
|
+
</p>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|