@pezkuwi/react-qr 3.16.8 → 3.17.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/build/Display.js +91 -0
- package/build/DisplayAddress.js +12 -0
- package/build/DisplayPayload.js +12 -0
- package/build/NetworkSpecs.js +12 -0
- package/build/README.md +3 -0
- package/build/Scan.js +53 -0
- package/build/ScanAddress.js +41 -0
- package/build/ScanSignature.js +8 -0
- package/{bundle-pezkuwi-react-qr.js → build/bundle-pezkuwi-react-qr.js} +97 -80
- package/build/bundle.js +6 -0
- package/build/cjs/Display.d.ts +12 -0
- package/build/cjs/Display.js +95 -0
- package/build/cjs/DisplayAddress.d.ts +12 -0
- package/build/cjs/DisplayAddress.js +16 -0
- package/build/cjs/DisplayPayload.d.ts +15 -0
- package/build/cjs/DisplayPayload.js +16 -0
- package/build/cjs/NetworkSpecs.d.ts +11 -0
- package/build/cjs/NetworkSpecs.js +16 -0
- package/build/cjs/Scan.d.ts +12 -0
- package/build/cjs/Scan.js +57 -0
- package/build/cjs/ScanAddress.d.ts +19 -0
- package/build/cjs/ScanAddress.js +45 -0
- package/build/cjs/ScanSignature.d.ts +15 -0
- package/build/cjs/ScanSignature.js +12 -0
- package/build/cjs/bundle.d.ts +6 -0
- package/build/cjs/bundle.js +15 -0
- package/build/cjs/constants.js +12 -0
- package/build/cjs/index.js +5 -0
- package/build/cjs/packageDetect.js +5 -0
- package/build/cjs/packageInfo.js +4 -0
- package/build/cjs/qrcode.js +8 -0
- package/build/cjs/styled.js +5 -0
- package/build/cjs/util.js +59 -0
- package/build/constants.d.ts +9 -0
- package/build/constants.js +9 -0
- package/build/index.d.ts +2 -0
- package/build/index.js +2 -0
- package/build/package.json +274 -0
- package/build/packageDetect.d.ts +1 -0
- package/build/packageDetect.js +3 -0
- package/build/packageInfo.d.ts +6 -0
- package/build/packageInfo.js +1 -0
- package/build/qrcode.d.ts +3 -0
- package/build/qrcode.js +4 -0
- package/build/styled.d.ts +1 -0
- package/build/styled.js +1 -0
- package/build/util.d.ts +7 -0
- package/build/util.js +50 -0
- package/{cjs → build-tsc-cjs}/packageInfo.js +1 -1
- package/{packageInfo.js → build-tsc-esm/packageInfo.js} +1 -1
- package/package.json +3 -237
- package/src/Display.tsx +153 -0
- package/src/DisplayAddress.tsx +40 -0
- package/src/DisplayPayload.tsx +42 -0
- package/src/NetworkSpecs.tsx +39 -0
- package/src/Scan.tsx +100 -0
- package/src/ScanAddress.tsx +82 -0
- package/src/ScanSignature.tsx +39 -0
- package/src/bundle.ts +9 -0
- package/src/constants.ts +12 -0
- package/src/index.ts +6 -0
- package/src/packageDetect.ts +11 -0
- package/src/packageInfo.ts +6 -0
- package/src/qrcode.ts +15 -0
- package/src/styled.ts +4 -0
- package/src/util.spec.ts +100 -0
- package/src/util.ts +83 -0
- package/tsconfig.build.json +14 -0
- package/tsconfig.build.tsbuildinfo +1 -0
- package/tsconfig.spec.json +16 -0
- package/tsconfig.spec.tsbuildinfo +1 -0
- /package/{cjs → build}/Display.d.ts +0 -0
- /package/{cjs → build}/DisplayAddress.d.ts +0 -0
- /package/{cjs → build}/DisplayPayload.d.ts +0 -0
- /package/{LICENSE → build/LICENSE} +0 -0
- /package/{cjs → build}/NetworkSpecs.d.ts +0 -0
- /package/{cjs → build}/Scan.d.ts +0 -0
- /package/{cjs → build}/ScanAddress.d.ts +0 -0
- /package/{cjs → build}/ScanSignature.d.ts +0 -0
- /package/{cjs → build}/bundle.d.ts +0 -0
- /package/{constants.d.ts → build/cjs/constants.d.ts} +0 -0
- /package/{index.d.ts → build/cjs/index.d.ts} +0 -0
- /package/{cjs → build/cjs}/package.json +0 -0
- /package/{packageDetect.d.ts → build/cjs/packageDetect.d.ts} +0 -0
- /package/{packageInfo.d.ts → build/cjs/packageInfo.d.ts} +0 -0
- /package/{qrcode.d.ts → build/cjs/qrcode.d.ts} +0 -0
- /package/{styled.d.ts → build/cjs/styled.d.ts} +0 -0
- /package/{util.d.ts → build/cjs/util.d.ts} +0 -0
- /package/{Display.d.ts → build-tsc/Display.d.ts} +0 -0
- /package/{DisplayAddress.d.ts → build-tsc/DisplayAddress.d.ts} +0 -0
- /package/{DisplayPayload.d.ts → build-tsc/DisplayPayload.d.ts} +0 -0
- /package/{NetworkSpecs.d.ts → build-tsc/NetworkSpecs.d.ts} +0 -0
- /package/{Scan.d.ts → build-tsc/Scan.d.ts} +0 -0
- /package/{ScanAddress.d.ts → build-tsc/ScanAddress.d.ts} +0 -0
- /package/{ScanSignature.d.ts → build-tsc/ScanSignature.d.ts} +0 -0
- /package/{bundle.d.ts → build-tsc/bundle.d.ts} +0 -0
- /package/{cjs → build-tsc}/constants.d.ts +0 -0
- /package/{cjs → build-tsc}/index.d.ts +0 -0
- /package/{cjs → build-tsc}/packageDetect.d.ts +0 -0
- /package/{cjs → build-tsc}/packageInfo.d.ts +0 -0
- /package/{cjs → build-tsc}/qrcode.d.ts +0 -0
- /package/{cjs → build-tsc}/styled.d.ts +0 -0
- /package/{cjs → build-tsc}/util.d.ts +0 -0
- /package/{cjs → build-tsc-cjs}/Display.js +0 -0
- /package/{cjs → build-tsc-cjs}/DisplayAddress.js +0 -0
- /package/{cjs → build-tsc-cjs}/DisplayPayload.js +0 -0
- /package/{cjs → build-tsc-cjs}/NetworkSpecs.js +0 -0
- /package/{cjs → build-tsc-cjs}/Scan.js +0 -0
- /package/{cjs → build-tsc-cjs}/ScanAddress.js +0 -0
- /package/{cjs → build-tsc-cjs}/ScanSignature.js +0 -0
- /package/{cjs → build-tsc-cjs}/bundle.js +0 -0
- /package/{cjs → build-tsc-cjs}/constants.js +0 -0
- /package/{cjs → build-tsc-cjs}/index.js +0 -0
- /package/{cjs → build-tsc-cjs}/packageDetect.js +0 -0
- /package/{cjs → build-tsc-cjs}/qrcode.js +0 -0
- /package/{cjs → build-tsc-cjs}/styled.js +0 -0
- /package/{cjs → build-tsc-cjs}/util.js +0 -0
- /package/{Display.js → build-tsc-esm/Display.js} +0 -0
- /package/{DisplayAddress.js → build-tsc-esm/DisplayAddress.js} +0 -0
- /package/{DisplayPayload.js → build-tsc-esm/DisplayPayload.js} +0 -0
- /package/{NetworkSpecs.js → build-tsc-esm/NetworkSpecs.js} +0 -0
- /package/{Scan.js → build-tsc-esm/Scan.js} +0 -0
- /package/{ScanAddress.js → build-tsc-esm/ScanAddress.js} +0 -0
- /package/{ScanSignature.js → build-tsc-esm/ScanSignature.js} +0 -0
- /package/{bundle.js → build-tsc-esm/bundle.js} +0 -0
- /package/{constants.js → build-tsc-esm/constants.js} +0 -0
- /package/{index.js → build-tsc-esm/index.js} +0 -0
- /package/{packageDetect.js → build-tsc-esm/packageDetect.js} +0 -0
- /package/{qrcode.js → build-tsc-esm/qrcode.js} +0 -0
- /package/{styled.js → build-tsc-esm/styled.js} +0 -0
- /package/{util.js → build-tsc-esm/util.js} +0 -0
package/build/Display.js
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { objectSpread } from '@pezkuwi/util';
|
|
4
|
+
import { xxhashAsHex } from '@pezkuwi/util-crypto';
|
|
5
|
+
import { qrcode } from './qrcode.js';
|
|
6
|
+
import { styled } from './styled.js';
|
|
7
|
+
import { createFrames, createImgSize } from './util.js';
|
|
8
|
+
const DEFAULT_FRAME_DELAY = 2750;
|
|
9
|
+
const TIMER_INC = 500;
|
|
10
|
+
function getDataUrl(value) {
|
|
11
|
+
const qr = qrcode(0, 'M');
|
|
12
|
+
// HACK See our qrcode stringToBytes override as used internally. This
|
|
13
|
+
// will only work for the case where we actually pass `Bytes` in here
|
|
14
|
+
qr.addData(value, 'Byte');
|
|
15
|
+
qr.make();
|
|
16
|
+
return qr.createDataURL(16, 0);
|
|
17
|
+
}
|
|
18
|
+
function Display({ className = '', size, skipEncoding, style = {}, timerDelay = DEFAULT_FRAME_DELAY, value }) {
|
|
19
|
+
const [{ image }, setFrameState] = useState({ frameIdx: 0, frames: [], image: null, valueHash: null });
|
|
20
|
+
const timerRef = useRef({ timerDelay, timerId: null });
|
|
21
|
+
const containerStyle = useMemo(() => createImgSize(size), [size]);
|
|
22
|
+
// run on initial load to setup the global timer and provide and unsubscribe
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
const nextFrame = () => setFrameState((state) => {
|
|
25
|
+
// when we have a single frame, we only ever fire once
|
|
26
|
+
if (state.frames.length <= 1) {
|
|
27
|
+
return state;
|
|
28
|
+
}
|
|
29
|
+
let frameIdx = state.frameIdx + 1;
|
|
30
|
+
// when we overflow, skip to the first and slightly increase the delay between frames
|
|
31
|
+
if (frameIdx === state.frames.length) {
|
|
32
|
+
frameIdx = 0;
|
|
33
|
+
timerRef.current.timerDelay = timerRef.current.timerDelay + TIMER_INC;
|
|
34
|
+
}
|
|
35
|
+
// only encode the frames on demand, not above as part of the
|
|
36
|
+
// state derivation - in the case of large payloads, this should
|
|
37
|
+
// be slightly more responsive on initial load
|
|
38
|
+
const newState = objectSpread({}, state, {
|
|
39
|
+
frameIdx,
|
|
40
|
+
image: getDataUrl(state.frames[frameIdx])
|
|
41
|
+
});
|
|
42
|
+
// set the new timer last
|
|
43
|
+
timerRef.current.timerId = setTimeout(nextFrame, timerRef.current.timerDelay);
|
|
44
|
+
return newState;
|
|
45
|
+
});
|
|
46
|
+
timerRef.current.timerId = setTimeout(nextFrame, timerRef.current.timerDelay);
|
|
47
|
+
return () => {
|
|
48
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
49
|
+
timerRef.current.timerId && clearTimeout(timerRef.current.timerId);
|
|
50
|
+
};
|
|
51
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
52
|
+
}, []);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
setFrameState((state) => {
|
|
55
|
+
const valueHash = xxhashAsHex(value);
|
|
56
|
+
if (valueHash === state.valueHash) {
|
|
57
|
+
return state;
|
|
58
|
+
}
|
|
59
|
+
const frames = skipEncoding
|
|
60
|
+
? [value]
|
|
61
|
+
: createFrames(value);
|
|
62
|
+
// encode on demand
|
|
63
|
+
return {
|
|
64
|
+
frameIdx: 0,
|
|
65
|
+
frames,
|
|
66
|
+
image: getDataUrl(frames[0]),
|
|
67
|
+
valueHash
|
|
68
|
+
};
|
|
69
|
+
});
|
|
70
|
+
}, [skipEncoding, value]);
|
|
71
|
+
if (!image) {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
return (_jsx(StyledDiv, { className: className, style: containerStyle, children: _jsx("div", { className: 'ui--qr-Display', style: style, children: _jsx("img", { src: image }) }) }));
|
|
75
|
+
}
|
|
76
|
+
const StyledDiv = styled.div `
|
|
77
|
+
.ui--qr-Display {
|
|
78
|
+
height: 100%;
|
|
79
|
+
width: 100%;
|
|
80
|
+
|
|
81
|
+
img,
|
|
82
|
+
svg {
|
|
83
|
+
background: white;
|
|
84
|
+
height: auto !important;
|
|
85
|
+
max-height: 100%;
|
|
86
|
+
max-width: 100%;
|
|
87
|
+
width: auto !important;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
`;
|
|
91
|
+
export const QrDisplay = React.memo(Display);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useMemo } from 'react';
|
|
3
|
+
import { QrDisplay } from './Display.js';
|
|
4
|
+
import { createAddressPayload } from './util.js';
|
|
5
|
+
function DisplayAddress({ address, className, genesisHash, size, style, timerDelay }) {
|
|
6
|
+
const data = useMemo(() => createAddressPayload(address, genesisHash), [address, genesisHash]);
|
|
7
|
+
if (!data) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return (_jsx(QrDisplay, { className: className, size: size, skipEncoding: true, style: style, timerDelay: timerDelay, value: data }));
|
|
11
|
+
}
|
|
12
|
+
export const QrDisplayAddress = React.memo(DisplayAddress);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useMemo } from 'react';
|
|
3
|
+
import { QrDisplay } from './Display.js';
|
|
4
|
+
import { createSignPayload } from './util.js';
|
|
5
|
+
function DisplayPayload({ address, className, cmd, genesisHash, payload, size, style, timerDelay }) {
|
|
6
|
+
const data = useMemo(() => createSignPayload(address, cmd, payload, genesisHash), [address, cmd, payload, genesisHash]);
|
|
7
|
+
if (!data) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return (_jsx(QrDisplay, { className: className, size: size, style: style, timerDelay: timerDelay, value: data }));
|
|
11
|
+
}
|
|
12
|
+
export const QrDisplayPayload = React.memo(DisplayPayload);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useMemo } from 'react';
|
|
3
|
+
import { QrDisplay } from './Display.js';
|
|
4
|
+
import { encodeString } from './util.js';
|
|
5
|
+
function DisplayNetworkSpecs({ className, networkSpecs, size, style }) {
|
|
6
|
+
const data = useMemo(() => encodeString(JSON.stringify(networkSpecs)), [networkSpecs]);
|
|
7
|
+
if (!data) {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return (_jsx(QrDisplay, { className: className, size: size, skipEncoding: true, style: style, value: data }));
|
|
11
|
+
}
|
|
12
|
+
export const QrNetworkSpecs = React.memo(DisplayNetworkSpecs);
|
package/build/README.md
ADDED
package/build/Scan.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { BrowserQRCodeReader } from '@zxing/browser';
|
|
3
|
+
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
|
|
4
|
+
import { styled } from './styled.js';
|
|
5
|
+
import { createImgSize } from './util.js';
|
|
6
|
+
const DEFAULT_DELAY = 150;
|
|
7
|
+
const DEFAULT_ERROR = (error) => {
|
|
8
|
+
console.error('@pezkuwi/react-qr:Scan', error.message);
|
|
9
|
+
};
|
|
10
|
+
function Scan({ className = '', delay = DEFAULT_DELAY, onError = DEFAULT_ERROR, onScan, size, style = {} }) {
|
|
11
|
+
const videoRef = useRef(null);
|
|
12
|
+
const controlsRef = useRef(null);
|
|
13
|
+
const containerStyle = useMemo(() => createImgSize(size), [size]);
|
|
14
|
+
const _onError = useCallback((error) => onError(error), [onError]);
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
const codeReader = new BrowserQRCodeReader();
|
|
17
|
+
const startScanning = async () => {
|
|
18
|
+
try {
|
|
19
|
+
const videoInputDevices = await BrowserQRCodeReader.listVideoInputDevices();
|
|
20
|
+
const selectedDeviceId = videoInputDevices[0].deviceId;
|
|
21
|
+
controlsRef.current = await codeReader.decodeFromVideoDevice(selectedDeviceId, videoRef.current ?? undefined, (result, error) => {
|
|
22
|
+
if (result) {
|
|
23
|
+
onScan(result.getText());
|
|
24
|
+
}
|
|
25
|
+
if (error && !(error instanceof Error)) {
|
|
26
|
+
_onError(new Error(error));
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
_onError(error instanceof Error ? error : new Error('Unknown error occurred'));
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
35
|
+
const timeoutId = setTimeout(startScanning, delay);
|
|
36
|
+
return () => {
|
|
37
|
+
clearTimeout(timeoutId);
|
|
38
|
+
if (controlsRef.current) {
|
|
39
|
+
controlsRef.current.stop();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}, [onScan, _onError, delay]);
|
|
43
|
+
return (_jsx(StyledDiv, { className: className, style: containerStyle, children: _jsx("video", { className: 'ui--qr-Scan', ref: videoRef, style: style }) }));
|
|
44
|
+
}
|
|
45
|
+
const StyledDiv = styled.div `
|
|
46
|
+
.ui--qr-Scan {
|
|
47
|
+
display: inline-block;
|
|
48
|
+
height: 100%;
|
|
49
|
+
transform: matrix(-1, 0, 0, 1, 0, 0);
|
|
50
|
+
width: 100%;
|
|
51
|
+
}
|
|
52
|
+
`;
|
|
53
|
+
export const QrScan = React.memo(Scan);
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useCallback } from 'react';
|
|
3
|
+
import { decodeAddress } from '@pezkuwi/util-crypto';
|
|
4
|
+
import { ADDRESS_PREFIX, SEED_PREFIX } from './constants.js';
|
|
5
|
+
import { QrScan } from './Scan.js';
|
|
6
|
+
function ScanAddress({ className, isEthereum, onError, onScan, size, style }) {
|
|
7
|
+
const _onScan = useCallback((data) => {
|
|
8
|
+
if (data) {
|
|
9
|
+
try {
|
|
10
|
+
let prefix;
|
|
11
|
+
let content;
|
|
12
|
+
let genesisHash;
|
|
13
|
+
let name;
|
|
14
|
+
if (!isEthereum) {
|
|
15
|
+
[prefix, content, genesisHash, ...name] = data.split(':');
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
[prefix, content, ...name] = data.split(':');
|
|
19
|
+
genesisHash = null;
|
|
20
|
+
content = content.substring(0, 42);
|
|
21
|
+
}
|
|
22
|
+
const expectedPrefix = (isEthereum ? 'ethereum' : ADDRESS_PREFIX);
|
|
23
|
+
const isValidPrefix = (prefix === expectedPrefix) || (prefix === SEED_PREFIX);
|
|
24
|
+
if (!isValidPrefix) {
|
|
25
|
+
throw new Error(`Invalid prefix received, expected '${expectedPrefix} or ${SEED_PREFIX}' , found '${prefix}'`);
|
|
26
|
+
}
|
|
27
|
+
const isAddress = prefix === expectedPrefix;
|
|
28
|
+
if (isAddress && !isEthereum) {
|
|
29
|
+
decodeAddress(content);
|
|
30
|
+
}
|
|
31
|
+
onScan({ content, genesisHash: genesisHash, isAddress, name: name?.length ? name.join(':') : undefined });
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
onError && onError(error);
|
|
35
|
+
console.error('@pezkuwi/react-qr:QrScanAddress', error.message, data);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}, [onScan, onError, isEthereum]);
|
|
39
|
+
return (_jsx(QrScan, { className: className, onError: onError, onScan: _onScan, size: size, style: style }));
|
|
40
|
+
}
|
|
41
|
+
export const QrScanAddress = React.memo(ScanAddress);
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import React, { useCallback } from 'react';
|
|
3
|
+
import { QrScan } from './Scan.js';
|
|
4
|
+
function ScanSignature({ className, onError, onScan, size, style }) {
|
|
5
|
+
const _onScan = useCallback((signature) => signature && onScan({ signature: `0x${signature}` }), [onScan]);
|
|
6
|
+
return (_jsx(QrScan, { className: className, onError: onError, onScan: _onScan, size: size, style: style }));
|
|
7
|
+
}
|
|
8
|
+
export const QrScanSignature = React.memo(ScanSignature);
|