@nddeps/barcode-scanner 0.4.0 → 0.5.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/package.json CHANGED
@@ -1,65 +1,65 @@
1
- {
2
- "name": "@nddeps/barcode-scanner",
3
- "version": "0.4.0",
4
- "private": false,
5
- "keywords": [
6
- "barcode",
7
- "scanner",
8
- "barcode-scanner"
9
- ],
10
- "homepage": "https://github.com/No-Deprecated-Dependencies/barcode-scanner",
11
- "repository": {
12
- "type": "git",
13
- "url": "https://github.com/No-Deprecated-Dependencies/barcode-scanner.git"
14
- },
15
- "license": "MIT",
16
- "author": "Aleksei Saenko",
17
- "type": "module",
18
- "exports": {
19
- ".": {
20
- "types": "./dist/index.d.ts",
21
- "import": "./dist/index.js"
22
- },
23
- "./worker": {
24
- "import": "./dist/worker.js"
25
- }
26
- },
27
- "main": "./dist/index.js",
28
- "types": "./dist/index.d.ts",
29
- "files": [
30
- "./dist"
31
- ],
32
- "scripts": {
33
- "build": "vite build && tsc -b",
34
- "dev": "vite",
35
- "preview": "vite preview"
36
- },
37
- "dependencies": {
38
- "barcode-detector": "^3.0.8",
39
- "zxing-wasm": "^2.2.4"
40
- },
41
- "devDependencies": {
42
- "@eslint/css": "^0.14.1",
43
- "@eslint/js": "^9.39.2",
44
- "@eslint/json": "^1.0.0",
45
- "@eslint/markdown": "^7.5.1",
46
- "@types/emscripten": "^1.41.5",
47
- "@types/node": "^25.1.0",
48
- "eslint": "^9.39.2",
49
- "eslint-config-prettier": "^10.1.8",
50
- "eslint-plugin-perfectionist": "^5.4.0",
51
- "eslint-plugin-prettier": "^5.5.5",
52
- "globals": "^17.2.0",
53
- "jiti": "^2.6.1",
54
- "prettier": "3.8.1",
55
- "sort-package-json": "^3.6.1",
56
- "stylelint": "^16.26.1",
57
- "stylelint-config-recess-order": "^7.6.0",
58
- "stylelint-config-standard": "^39.0.1",
59
- "stylelint-config-standard-scss": "^16.0.0",
60
- "stylelint-order": "^7.0.1",
61
- "typescript": "~5.9.3",
62
- "typescript-eslint": "^8.54.0",
63
- "vite": "^7.3.1"
64
- }
65
- }
1
+ {
2
+ "name": "@nddeps/barcode-scanner",
3
+ "version": "0.5.0",
4
+ "private": false,
5
+ "keywords": [
6
+ "barcode",
7
+ "scanner",
8
+ "barcode-scanner"
9
+ ],
10
+ "homepage": "https://github.com/No-Deprecated-Dependencies/barcode-scanner",
11
+ "repository": {
12
+ "type": "git",
13
+ "url": "git+https://github.com/No-Deprecated-Dependencies/barcode-scanner.git"
14
+ },
15
+ "license": "MIT",
16
+ "author": "Aleksei Saenko",
17
+ "type": "module",
18
+ "exports": {
19
+ ".": {
20
+ "types": "./dist/index.d.ts",
21
+ "import": "./dist/index.js"
22
+ },
23
+ "./worker": {
24
+ "import": "./dist/worker.js"
25
+ }
26
+ },
27
+ "main": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "files": [
30
+ "./dist"
31
+ ],
32
+ "scripts": {
33
+ "build": "vite build && tsc -b",
34
+ "dev": "vite",
35
+ "preview": "vite preview"
36
+ },
37
+ "dependencies": {
38
+ "barcode-detector": "^3.0.8",
39
+ "zxing-wasm": "^2.2.4"
40
+ },
41
+ "devDependencies": {
42
+ "@eslint/css": "^0.14.1",
43
+ "@eslint/js": "^9.39.2",
44
+ "@eslint/json": "^1.0.0",
45
+ "@eslint/markdown": "^7.5.1",
46
+ "@types/emscripten": "^1.41.5",
47
+ "@types/node": "^25.2.0",
48
+ "eslint": "^9.39.2",
49
+ "eslint-config-prettier": "^10.1.8",
50
+ "eslint-plugin-perfectionist": "^5.4.0",
51
+ "eslint-plugin-prettier": "^5.5.5",
52
+ "globals": "^17.2.0",
53
+ "jiti": "^2.6.1",
54
+ "prettier": "3.8.1",
55
+ "sort-package-json": "^3.6.1",
56
+ "stylelint": "^16.26.1",
57
+ "stylelint-config-recess-order": "^7.6.0",
58
+ "stylelint-config-standard": "^39.0.1",
59
+ "stylelint-config-standard-scss": "^16.0.0",
60
+ "stylelint-order": "^7.0.1",
61
+ "typescript": "~5.9.3",
62
+ "typescript-eslint": "^8.54.0",
63
+ "vite": "^7.3.1"
64
+ }
65
+ }
@@ -1,43 +0,0 @@
1
- import { type ScanArea } from './utils';
2
- type DecodeFailureHandler = (this: State) => Promise<void> | void;
3
- type DecodeSuccessHandler = (this: State, data: string, area: ScanArea) => Promise<void> | void;
4
- type LifecycleHook = (this: State) => void;
5
- type State = {
6
- decodeFrameTs: number;
7
- isDecodeFrameProcessed: boolean;
8
- isDestroyed: boolean;
9
- isVideoActive: boolean;
10
- isVideoPaused: boolean;
11
- scanArea: ScanArea;
12
- scanRate: number;
13
- video: HTMLVideoElement;
14
- };
15
- declare function createBarcodeScanner(video: HTMLVideoElement, { getScanArea, debug, scanRate, handleDecodeFailure, handleDecodeSuccess, lifecycle, }?: {
16
- getScanArea?: (video: HTMLVideoElement) => ScanArea;
17
- scanRate?: number;
18
- debug?: boolean;
19
- handleDecodeFailure?: DecodeFailureHandler;
20
- handleDecodeSuccess?: DecodeSuccessHandler;
21
- lifecycle?: {
22
- onBeforeCreate?: LifecycleHook;
23
- onBeforeDecode?: LifecycleHook;
24
- onBeforeStart?: LifecycleHook;
25
- onBeforeStop?: LifecycleHook;
26
- onCreate?: LifecycleHook;
27
- onDecode?: LifecycleHook;
28
- onStart?: LifecycleHook;
29
- onStop?: LifecycleHook;
30
- };
31
- }): Promise<{
32
- destroy: () => void;
33
- pause: () => Promise<void>;
34
- start: ({ facingMode, ...rest }?: {
35
- facingMode?: "environment" | "user";
36
- handleDecodeFailure?: DecodeFailureHandler;
37
- handleDecodeSuccess?: DecodeSuccessHandler;
38
- }) => Promise<void>;
39
- state: State;
40
- stop: () => Promise<void>;
41
- }>;
42
- export type { DecodeFailureHandler, DecodeSuccessHandler, LifecycleHook, State };
43
- export { createBarcodeScanner };
@@ -1,5 +0,0 @@
1
- declare function createWatchable<T extends object>(init: T): {
2
- state: T;
3
- watch: <T_1>(source: () => T_1, callback: (newValue: T_1) => void) => () => void;
4
- };
5
- export { createWatchable };
@@ -1,6 +0,0 @@
1
- import type { DetectedBarcode } from 'barcode-detector/ponyfill';
2
- declare function createWorker(): {
3
- decode: (imageData: ImageData) => Promise<DetectedBarcode | null>;
4
- worker: Worker;
5
- };
6
- export { createWorker };
@@ -1,289 +0,0 @@
1
- function x(t) {
2
- const o = new EventTarget(), c = new Proxy(t, {
3
- get(n, r, i) {
4
- return Reflect.get(n, r, i);
5
- },
6
- set(n, r, i, s) {
7
- const d = Reflect.set(n, r, i, s);
8
- return o.dispatchEvent(new CustomEvent("change")), d;
9
- }
10
- });
11
- function a(n, r) {
12
- let i = n();
13
- function s() {
14
- const d = n();
15
- JSON.stringify(d) !== JSON.stringify(i) && (i = d, r(d));
16
- }
17
- return o.addEventListener("change", s), () => o.removeEventListener("change", s);
18
- }
19
- return {
20
- state: c,
21
- watch: a
22
- };
23
- }
24
- function F() {
25
- const t = new Worker(new URL(
26
- /* @vite-ignore */
27
- "" + new URL("worker-BTT4rwmP.js", import.meta.url).href,
28
- import.meta.url
29
- ), { type: "module" }), o = new Promise((a, n) => {
30
- const r = setTimeout(() => n(new Error("Worker load timeout")), 16e3);
31
- t.addEventListener(
32
- "message",
33
- ({
34
- data: { payload: i, type: s }
35
- }) => {
36
- s === "message" && (clearTimeout(r), i.status === "success" ? a(!0) : n(new Error("Worker failed to load")));
37
- },
38
- {
39
- once: !0
40
- }
41
- );
42
- });
43
- async function c(a) {
44
- await o;
45
- const n = `${performance.now()}-${Math.random().toString(36).slice(2)}`;
46
- return new Promise((r, i) => {
47
- let s = 0;
48
- const d = ({ data: { payload: w, type: g } }) => {
49
- g !== "decode" || w.uuid !== n || (clearTimeout(s), t.removeEventListener("message", d), r(w.data));
50
- };
51
- s = setTimeout(() => {
52
- t.removeEventListener("message", d), i(new Error("Decode timeout"));
53
- }, 1e3 * 6), t.addEventListener("message", d), t.postMessage({ payload: { data: a, uuid: n }, type: "decode" });
54
- });
55
- }
56
- return {
57
- decode: c,
58
- worker: t
59
- };
60
- }
61
- async function V() {
62
- try {
63
- return (await navigator.permissions.query({ name: "camera" })).state === "granted";
64
- } catch {
65
- return (await navigator.mediaDevices.enumerateDevices()).filter((c) => c.deviceId && c.kind === "videoinput").length > 0;
66
- }
67
- }
68
- async function H() {
69
- if (await V())
70
- return !0;
71
- try {
72
- const o = (await navigator.mediaDevices.getUserMedia({ video: !0 })).getTracks();
73
- for (const c of o)
74
- c.stop();
75
- return !0;
76
- } catch {
77
- return !1;
78
- }
79
- }
80
- function T(t) {
81
- const o = Math.round(0.6666666666666666 * Math.min(t.videoWidth, t.videoHeight));
82
- return {
83
- height: o,
84
- width: o,
85
- x: Math.round((t.videoWidth - o) / 2),
86
- y: Math.round((t.videoHeight - o) / 2)
87
- };
88
- }
89
- function D(t, o) {
90
- const c = window.getComputedStyle(t), [a, n] = c.objectPosition.split(" ").map(
91
- (r, i) => r.endsWith("%") ? (i === 0 ? t.offsetWidth - o.width : t.offsetHeight - o.height) * parseFloat(r) / 100 : parseFloat(r)
92
- );
93
- return {
94
- x: a,
95
- y: n
96
- };
97
- }
98
- function S(t) {
99
- const o = window.getComputedStyle(t), c = { height: t.offsetHeight, width: t.offsetWidth }, a = c.width / c.height, n = { height: t.videoHeight, width: t.videoWidth }, r = n.width / n.height;
100
- switch (o.objectFit) {
101
- case "contain":
102
- return {
103
- height: r < a ? t.offsetHeight : t.offsetWidth / r,
104
- width: r < a ? t.offsetHeight * r : t.offsetWidth
105
- };
106
- case "cover":
107
- return {
108
- height: r > a ? t.offsetHeight : t.offsetWidth / r,
109
- width: r > a ? t.offsetHeight * r : t.offsetWidth
110
- };
111
- case "fill":
112
- return c;
113
- case "none":
114
- return n;
115
- case "scale-down":
116
- return {
117
- height: Math.min(
118
- r < a ? t.offsetHeight : t.offsetWidth / r,
119
- t.videoHeight
120
- ),
121
- width: Math.min(
122
- r < a ? t.offsetHeight * r : t.offsetWidth,
123
- t.videoWidth
124
- )
125
- };
126
- default:
127
- return n;
128
- }
129
- }
130
- function k(t) {
131
- return "BarcodeDetector" in t;
132
- }
133
- function L(t, o) {
134
- const c = /scaleX\(-1\)/.test(t.style.transform), a = S(t), n = D(t, a), r = c ? t.videoWidth - o.x - o.width : o.x, i = o.y;
135
- return {
136
- height: o.height / t.videoHeight * a.height,
137
- width: o.width / t.videoWidth * a.width,
138
- x: r / t.videoWidth * a.width + n.x,
139
- y: i / t.videoHeight * a.height + n.y
140
- };
141
- }
142
- function O(t, o) {
143
- const c = /scaleX\(-1\)/.test(t.style.transform), a = S(t), n = D(t, a), r = c ? a.width - (o.x - n.x) - o.width : o.x - n.x, i = o.y - n.y, s = t.videoHeight / a.height, d = t.videoWidth / a.width;
144
- return {
145
- height: o.height * s,
146
- width: o.width * d,
147
- x: r * d,
148
- y: i * s
149
- };
150
- }
151
- function j(t) {
152
- return new Promise((o) => setTimeout(o, t));
153
- }
154
- async function B(t, {
155
- getScanArea: o = T,
156
- debug: c,
157
- scanRate: a = 24,
158
- handleDecodeFailure: n = () => {
159
- },
160
- handleDecodeSuccess: r = () => {
161
- },
162
- lifecycle: i = {}
163
- } = {}) {
164
- if (!(t instanceof HTMLVideoElement))
165
- throw new Error("video is not a HTMLVideoElement");
166
- if (!(r instanceof Function))
167
- throw new Error("handleDecodeSuccess is not a function");
168
- if (!(n instanceof Function))
169
- throw new Error("handleDecodeFailure is not a function");
170
- const s = document.createElement("canvas"), d = s.getContext("2d", { willReadFrequently: !0 });
171
- if (!d)
172
- throw new Error("canvas context is not supported");
173
- const { decode: w, worker: g } = F(), { state: e } = x({
174
- decodeFrameTs: performance.now(),
175
- isDecodeFrameProcessed: !1,
176
- isDestroyed: !1,
177
- isVideoActive: !1,
178
- isVideoPaused: !1,
179
- scanArea: o(t),
180
- scanRate: a,
181
- video: t
182
- }), v = t.requestVideoFrameCallback?.bind(t) ?? requestAnimationFrame;
183
- e.video.autoplay = !0, e.video.disablePictureInPicture = !0, e.video.hidden = !1, e.video.muted = !0, e.video.playsInline = !0, i.onCreate && i.onCreate.call(e);
184
- function W(h, u) {
185
- v(m);
186
- async function m() {
187
- if (e.isDestroyed || e.isVideoActive === !1)
188
- return;
189
- if (
190
- // Skip if the time since the last request frame is less than the scan rate
191
- performance.now() - e.decodeFrameTs < 1e3 / e.scanRate || // Skip if the frame is already processed
192
- e.isDecodeFrameProcessed || // Skip if the video is not ready
193
- e.video.readyState <= 1
194
- ) {
195
- v(m);
196
- return;
197
- }
198
- e.isDecodeFrameProcessed = !0, e.scanArea = o(e.video), i.onBeforeDecode && i.onBeforeDecode.call(e), s.height = e.scanArea.height, s.width = e.scanArea.width, d.clearRect(0, 0, s.width, s.height), d.drawImage(
199
- e.video,
200
- e.scanArea.x,
201
- e.scanArea.y,
202
- e.scanArea.width,
203
- e.scanArea.height,
204
- 0,
205
- 0,
206
- s.width,
207
- s.height
208
- );
209
- const l = d.getImageData(0, 0, s.width, s.height);
210
- c && window.dispatchEvent(
211
- new CustomEvent("barcode-scanner:decode-frame", {
212
- detail: {
213
- imageData: l
214
- }
215
- })
216
- );
217
- try {
218
- const f = await w(l);
219
- if (f) {
220
- const p = f.cornerPoints.map((b) => b.x), y = f.cornerPoints.map((b) => b.y), R = {
221
- height: Math.max(...y) - Math.min(...y),
222
- width: Math.max(...p) - Math.min(...p),
223
- x: Math.min(...p) + e.scanArea.x,
224
- y: Math.min(...y) + e.scanArea.y
225
- };
226
- await Promise.resolve(h.call(e, f.rawValue, R));
227
- } else
228
- await Promise.resolve(u.call(e));
229
- } catch (f) {
230
- console.warn("Failed to decode barcode"), f && console.error(f);
231
- } finally {
232
- i.onDecode && i.onDecode.call(e), e.decodeFrameTs = performance.now(), e.isDecodeFrameProcessed = !1, v(m);
233
- }
234
- }
235
- }
236
- function E() {
237
- e.isDestroyed || (A(), g.terminate(), e.isDestroyed = !0);
238
- }
239
- async function P() {
240
- if (e.isVideoActive === !1 || e.isVideoPaused || e.isDestroyed)
241
- return;
242
- e.video.pause(), s.height = e.video.videoHeight, s.width = e.video.videoWidth, d.drawImage(e.video, 0, 0, s.width, s.height, 0, 0, s.width, s.height);
243
- const h = await new Promise((u, m) => {
244
- s.toBlob(
245
- (l) => {
246
- l ? u(l) : m(new Error("Failed to convert canvas to blob"));
247
- },
248
- "image/jpeg",
249
- 0.9
250
- );
251
- });
252
- e.video.poster.startsWith("blob:") && URL.revokeObjectURL(e.video.poster), e.video.poster = URL.createObjectURL(h), e.video.srcObject instanceof MediaStream && e.video.srcObject.getTracks().forEach((u) => u.stop()), e.isVideoPaused = !0, e.video.srcObject = null;
253
- }
254
- async function M({
255
- facingMode: h = "environment",
256
- ...u
257
- } = {}) {
258
- if (i.onBeforeStart && i.onBeforeStart.call(e), !await H())
259
- throw new Error("No camera access");
260
- e.video.srcObject instanceof MediaStream || (e.video.srcObject = await navigator.mediaDevices.getUserMedia({
261
- video: {
262
- facingMode: h
263
- }
264
- }), await e.video.play(), e.isVideoActive = !0, e.isVideoPaused = !1, e.scanArea = o(e.video), e.video.style.transform = h === "user" ? "scaleX(-1)" : "none", i.onStart && i.onStart.call(e), W(u.handleDecodeSuccess ?? r, u.handleDecodeFailure ?? n));
265
- }
266
- async function A() {
267
- e.isVideoActive === !1 || e.isDestroyed || (i.onBeforeStop && i.onBeforeStop.call(e), e.video.srcObject instanceof MediaStream && e.video.srcObject.getTracks().forEach((h) => h.stop()), e.video.poster.startsWith("blob:") && URL.revokeObjectURL(e.video.poster), e.isVideoActive = !1, e.isVideoPaused = !1, e.video.poster = "", e.video.srcObject = null, i.onStop && i.onStop.call(e));
268
- }
269
- return {
270
- destroy: E,
271
- pause: P,
272
- start: M,
273
- state: e,
274
- stop: A
275
- };
276
- }
277
- export {
278
- B as createBarcodeScanner,
279
- B as default,
280
- H as getCameraAccess,
281
- T as getScanArea,
282
- D as getVideoRenderOffset,
283
- S as getVideoRenderSize,
284
- V as hasCameraAccess,
285
- k as isBarcodeDetectorAvailable,
286
- L as translateAreaToVideoRender,
287
- O as translateAreaToVideoSource,
288
- j as wait
289
- };
package/dist/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import { createBarcodeScanner } from './create-barcode-scanner';
2
- export * from './utils';
3
- export { createBarcodeScanner };
4
- export default createBarcodeScanner;
@@ -1,2 +0,0 @@
1
- declare function getCameraAccess(): Promise<boolean>;
2
- export { getCameraAccess };
@@ -1,9 +0,0 @@
1
- type ScanArea = {
2
- height: number;
3
- width: number;
4
- x: number;
5
- y: number;
6
- };
7
- declare function getScanArea(video: HTMLVideoElement): ScanArea;
8
- export type { ScanArea };
9
- export { getScanArea };
@@ -1,8 +0,0 @@
1
- import type { RenderSize } from './get-video-render-size';
2
- type RenderOffset = {
3
- x: number;
4
- y: number;
5
- };
6
- declare function getVideoRenderOffset(video: HTMLVideoElement, renderSize: RenderSize): RenderOffset;
7
- export type { RenderOffset };
8
- export { getVideoRenderOffset };
@@ -1,7 +0,0 @@
1
- type RenderSize = {
2
- height: number;
3
- width: number;
4
- };
5
- declare function getVideoRenderSize(video: HTMLVideoElement): RenderSize;
6
- export type { RenderSize };
7
- export { getVideoRenderSize };
@@ -1,2 +0,0 @@
1
- declare function hasCameraAccess(): Promise<boolean>;
2
- export { hasCameraAccess };
@@ -1,9 +0,0 @@
1
- export * from './get-camera-access';
2
- export * from './get-scan-area';
3
- export * from './get-video-render-offset';
4
- export * from './get-video-render-size';
5
- export * from './has-camera-access';
6
- export * from './is-barcode-detector-available';
7
- export * from './translate-area-to-video-render';
8
- export * from './translate-area-to-video-source';
9
- export * from './wait';
@@ -1,7 +0,0 @@
1
- import type { BarcodeDetector, BarcodeDetectorOptions } from 'barcode-detector/ponyfill';
2
- declare function isBarcodeDetectorAvailable<T extends object>(value: T): value is {
3
- BarcodeDetector: {
4
- new (barcodeDetectorOptions?: BarcodeDetectorOptions): BarcodeDetector;
5
- } & BarcodeDetector;
6
- } & T;
7
- export { isBarcodeDetectorAvailable };
@@ -1,3 +0,0 @@
1
- import type { ScanArea } from './get-scan-area';
2
- declare function translateAreaToVideoRender(video: HTMLVideoElement, area: ScanArea): ScanArea;
3
- export { translateAreaToVideoRender };
@@ -1,3 +0,0 @@
1
- import type { ScanArea } from './get-scan-area';
2
- declare function translateAreaToVideoSource(video: HTMLVideoElement, area: ScanArea): ScanArea;
3
- export { translateAreaToVideoSource };
@@ -1,2 +0,0 @@
1
- declare function wait(ms: number): Promise<unknown>;
2
- export { wait };