@scanly/react 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +50 -6
- package/dist/index.js.map +1 -1
- package/package.json +43 -33
package/README.md
CHANGED
|
@@ -1,3 +1,30 @@
|
|
|
1
1
|
# @scanly/react
|
|
2
2
|
|
|
3
|
-
Thin
|
|
3
|
+
Thin React adapter over `@scanly/browser` for Scanly SDK v2.1.0. Decoding, Worker ownership, camera runtime, tracking, and memory management remain outside React.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @scanly/react
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
```tsx
|
|
10
|
+
"use client";
|
|
11
|
+
import { useScanly } from "@scanly/react";
|
|
12
|
+
|
|
13
|
+
export function UploadScanner() {
|
|
14
|
+
const { outcome, scanning, scanFile, cancel } = useScanly();
|
|
15
|
+
return <>
|
|
16
|
+
<input type="file" accept="image/*" onChange={(event) => {
|
|
17
|
+
const file = event.currentTarget.files?.[0];
|
|
18
|
+
if (file) void scanFile(file);
|
|
19
|
+
}} />
|
|
20
|
+
<button onClick={cancel} disabled={!scanning}>Cancel</button>
|
|
21
|
+
<output>{outcome?.ok ? outcome.primary.rawText : ""}</output>
|
|
22
|
+
</>;
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
`useScanly` owns one `BrowserCaptureSession`, starts it after mount, and disposes its session and Worker on unmount. For camera UI, compose `BrowserCameraSource` from `@scanly/browser` in an effect and stop/dispose it in the effect cleanup.
|
|
27
|
+
|
|
28
|
+
This is the standard public React package for React 18 and 19-compatible peer ranges (`>=18 <20`).
|
|
29
|
+
|
|
30
|
+
Version: 2.1.0 · [React usage](https://github.com/Yangjunjie-Lin/Scanly/blob/main/docs/sdk/usage.md)
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,KAAK,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACxH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7E,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,4BAAiC,GAAG,eAAe,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,KAAK,4BAA4B,EAAE,KAAK,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACxH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,qBAAqB,CAAC;IAC/B,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,sBAAsB,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAC7E,MAAM,IAAI,IAAI,CAAC;IACf,KAAK,IAAI,IAAI,CAAC;CACf;AAED,wBAAgB,SAAS,CAAC,OAAO,GAAE,4BAAiC,GAAG,eAAe,CA6DrF"}
|
package/dist/index.js
CHANGED
|
@@ -1,28 +1,72 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import { useCallback, useEffect, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
3
|
import { BrowserCaptureSession } from "@scanly/browser";
|
|
4
4
|
export function useScanly(options = {}) {
|
|
5
5
|
const [session] = useState(() => new BrowserCaptureSession(options));
|
|
6
6
|
const [outcome, setOutcome] = useState(null);
|
|
7
7
|
const [scanning, setScanning] = useState(false);
|
|
8
|
+
const mounted = useRef(true);
|
|
9
|
+
const stateEpoch = useRef(0);
|
|
10
|
+
const nextCallId = useRef(0);
|
|
11
|
+
const latestCallId = useRef(0);
|
|
12
|
+
const activeCalls = useRef(new Map());
|
|
13
|
+
const lifecycleGeneration = useRef(0);
|
|
8
14
|
useEffect(() => {
|
|
15
|
+
const calls = activeCalls.current;
|
|
16
|
+
lifecycleGeneration.current += 1;
|
|
17
|
+
mounted.current = true;
|
|
18
|
+
setScanning(calls.size > 0);
|
|
9
19
|
session.initialize();
|
|
10
20
|
session.start();
|
|
11
|
-
return () => {
|
|
21
|
+
return () => {
|
|
22
|
+
mounted.current = false;
|
|
23
|
+
stateEpoch.current += 1;
|
|
24
|
+
calls.clear();
|
|
25
|
+
session.cancel();
|
|
26
|
+
const cleanupGeneration = ++lifecycleGeneration.current;
|
|
27
|
+
queueMicrotask(() => {
|
|
28
|
+
if (lifecycleGeneration.current === cleanupGeneration)
|
|
29
|
+
void session.dispose();
|
|
30
|
+
});
|
|
31
|
+
};
|
|
12
32
|
}, [session]);
|
|
13
33
|
const scanFile = useCallback(async (file, scanOptions = {}) => {
|
|
14
|
-
|
|
34
|
+
const callId = ++nextCallId.current;
|
|
35
|
+
const epoch = stateEpoch.current;
|
|
36
|
+
latestCallId.current = callId;
|
|
37
|
+
activeCalls.current.set(callId, epoch);
|
|
38
|
+
if (mounted.current)
|
|
39
|
+
setScanning(true);
|
|
15
40
|
try {
|
|
16
41
|
const next = await session.scanFile(file, scanOptions);
|
|
17
|
-
|
|
42
|
+
if (mounted.current && stateEpoch.current === epoch && latestCallId.current === callId)
|
|
43
|
+
setOutcome(next);
|
|
18
44
|
return next;
|
|
19
45
|
}
|
|
20
46
|
finally {
|
|
47
|
+
if (stateEpoch.current === epoch) {
|
|
48
|
+
activeCalls.current.delete(callId);
|
|
49
|
+
if (mounted.current)
|
|
50
|
+
setScanning(activeCalls.current.size > 0);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, [session]);
|
|
54
|
+
const cancel = useCallback(() => {
|
|
55
|
+
stateEpoch.current += 1;
|
|
56
|
+
activeCalls.current.clear();
|
|
57
|
+
session.cancel();
|
|
58
|
+
if (mounted.current)
|
|
59
|
+
setScanning(false);
|
|
60
|
+
}, [session]);
|
|
61
|
+
const reset = useCallback(() => {
|
|
62
|
+
stateEpoch.current += 1;
|
|
63
|
+
activeCalls.current.clear();
|
|
64
|
+
session.cancel();
|
|
65
|
+
if (mounted.current) {
|
|
21
66
|
setScanning(false);
|
|
67
|
+
setOutcome(null);
|
|
22
68
|
}
|
|
23
69
|
}, [session]);
|
|
24
|
-
const cancel = useCallback(() => { session.cancel(); setScanning(false); }, [session]);
|
|
25
|
-
const reset = useCallback(() => { session.cancel(); setScanning(false); setOutcome(null); }, [session]);
|
|
26
70
|
return { session, outcome, scanning, scanFile, cancel, reset };
|
|
27
71
|
}
|
|
28
72
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAC;AAEb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,33 +1,43 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@scanly/react",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "React
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
},
|
|
26
|
-
"
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
"
|
|
32
|
-
}
|
|
33
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@scanly/react",
|
|
3
|
+
"version": "2.1.0",
|
|
4
|
+
"description": "React adapter for the Scanly browser barcode scanning runtime",
|
|
5
|
+
"keywords": ["barcode", "qr-code", "scanner", "react", "hook", "scanly"],
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/Yangjunjie-Lin/Scanly.git",
|
|
9
|
+
"directory": "packages/react"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/Yangjunjie-Lin/Scanly#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Yangjunjie-Lin/Scanly/issues"
|
|
14
|
+
},
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"type": "module",
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "./dist/index.js",
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"import": "./dist/index.js"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsc -p tsconfig.build.json"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@scanly/browser": "2.1.0"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": ">=18 <20"
|
|
38
|
+
},
|
|
39
|
+
"devDependencies": {
|
|
40
|
+
"@types/react": "^18.3.3",
|
|
41
|
+
"react": "^18.3.1"
|
|
42
|
+
}
|
|
43
|
+
}
|