@brightchain/brightpass-react-components 0.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 -0
- package/package.json +42 -0
- package/src/index.js +35 -0
- package/src/index.js.map +1 -0
- package/src/lib/BrightPassRoutes.js +33 -0
- package/src/lib/BrightPassRoutes.js.map +1 -0
- package/src/lib/components/BreadcrumbNav.js +70 -0
- package/src/lib/components/BreadcrumbNav.js.map +1 -0
- package/src/lib/components/CreateVaultDialog.js +57 -0
- package/src/lib/components/CreateVaultDialog.js.map +1 -0
- package/src/lib/components/EntryDetailView.js +167 -0
- package/src/lib/components/EntryDetailView.js.map +1 -0
- package/src/lib/components/EntryForm.js +196 -0
- package/src/lib/components/EntryForm.js.map +1 -0
- package/src/lib/components/MasterPasswordPrompt.js +56 -0
- package/src/lib/components/MasterPasswordPrompt.js.map +1 -0
- package/src/lib/components/SearchBar.js +137 -0
- package/src/lib/components/SearchBar.js.map +1 -0
- package/src/lib/context/BrightPassProvider.js +158 -0
- package/src/lib/context/BrightPassProvider.js.map +1 -0
- package/src/lib/dialogs/EmergencyAccessDialog.js +139 -0
- package/src/lib/dialogs/EmergencyAccessDialog.js.map +1 -0
- package/src/lib/dialogs/ImportDialog.js +146 -0
- package/src/lib/dialogs/ImportDialog.js.map +1 -0
- package/src/lib/dialogs/ShareDialog.js +82 -0
- package/src/lib/dialogs/ShareDialog.js.map +1 -0
- package/src/lib/hooks/useBrightPassApi.js +13 -0
- package/src/lib/hooks/useBrightPassApi.js.map +1 -0
- package/src/lib/hooks/useBrightPassAutofill.js +80 -0
- package/src/lib/hooks/useBrightPassAutofill.js.map +1 -0
- package/src/lib/hooks/useBrightPassExtensionBridge.js +108 -0
- package/src/lib/hooks/useBrightPassExtensionBridge.js.map +1 -0
- package/src/lib/hooks/useBrightPassTranslation.js +12 -0
- package/src/lib/hooks/useBrightPassTranslation.js.map +1 -0
- package/src/lib/services/BrightPassApiService.js +219 -0
- package/src/lib/services/BrightPassApiService.js.map +1 -0
- package/src/lib/views/AuditLogView.js +120 -0
- package/src/lib/views/AuditLogView.js.map +1 -0
- package/src/lib/views/PasswordGeneratorPage.js +20 -0
- package/src/lib/views/PasswordGeneratorPage.js.map +1 -0
- package/src/lib/views/VaultDetailView.js +93 -0
- package/src/lib/views/VaultDetailView.js.map +1 -0
- package/src/lib/views/VaultListView.js +99 -0
- package/src/lib/views/VaultListView.js.map +1 -0
- package/src/lib/widgets/BreachCheckWidget.js +57 -0
- package/src/lib/widgets/BreachCheckWidget.js.map +1 -0
- package/src/lib/widgets/PasswordGeneratorWidget.js +137 -0
- package/src/lib/widgets/PasswordGeneratorWidget.js.map +1 -0
- package/src/lib/widgets/TOTPWidget.js +165 -0
- package/src/lib/widgets/TOTPWidget.js.map +1 -0
- package/src/test-setup.js +13 -0
- package/src/test-setup.js.map +1 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { BrightPassStrings } from '@brightchain/brightchain-lib';
|
|
3
|
+
import { Alert, Box, Button, CircularProgress, TextField, Typography, } from '@mui/material';
|
|
4
|
+
import { useCallback, useState } from 'react';
|
|
5
|
+
import { useBrightPassTranslation } from '../hooks/useBrightPassTranslation';
|
|
6
|
+
import { useBrightPassApi } from '../hooks/useBrightPassApi';
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/* Pure helper functions — exported for property-based testing */
|
|
9
|
+
/* ------------------------------------------------------------------ */
|
|
10
|
+
/**
|
|
11
|
+
* Determine the alert severity and i18n message key based on a breach result.
|
|
12
|
+
* Exported for property-based testing (Property 12).
|
|
13
|
+
*/
|
|
14
|
+
export function formatBreachMessage(breached, count) {
|
|
15
|
+
if (breached) {
|
|
16
|
+
return { severity: 'warning', messageKey: 'Breach_Found' };
|
|
17
|
+
}
|
|
18
|
+
return { severity: 'success', messageKey: 'Breach_NotFound' };
|
|
19
|
+
}
|
|
20
|
+
export const BreachCheckWidget = ({ initialPassword = '', }) => {
|
|
21
|
+
const { t } = useBrightPassTranslation();
|
|
22
|
+
const brightPassApi = useBrightPassApi();
|
|
23
|
+
const [password, setPassword] = useState(initialPassword);
|
|
24
|
+
const [checking, setChecking] = useState(false);
|
|
25
|
+
const [result, setResult] = useState(null);
|
|
26
|
+
const [error, setError] = useState(null);
|
|
27
|
+
const handleCheck = useCallback(async () => {
|
|
28
|
+
if (!password.trim())
|
|
29
|
+
return;
|
|
30
|
+
setChecking(true);
|
|
31
|
+
setError(null);
|
|
32
|
+
setResult(null);
|
|
33
|
+
try {
|
|
34
|
+
const breachResult = await brightPassApi.checkBreach(password);
|
|
35
|
+
setResult(breachResult);
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
const message = err?.message ?? 'Breach check failed';
|
|
39
|
+
setError(message);
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
setChecking(false);
|
|
43
|
+
}
|
|
44
|
+
}, [password]);
|
|
45
|
+
const breachMessage = result ? formatBreachMessage(result.breached, result.count) : null;
|
|
46
|
+
return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t(BrightPassStrings.Breach_Title) }), _jsxs(Box, { sx: { display: 'flex', gap: 1, mb: 2, alignItems: 'flex-start' }, children: [_jsx(TextField, { value: password, onChange: (e) => {
|
|
47
|
+
setPassword(e.target.value);
|
|
48
|
+
setResult(null);
|
|
49
|
+
setError(null);
|
|
50
|
+
}, type: "password", label: t(BrightPassStrings.Breach_Password), size: "small", fullWidth: true, disabled: checking, "aria-label": t(BrightPassStrings.Breach_Password) }), _jsx(Button, { variant: "contained", onClick: handleCheck, disabled: checking || !password.trim(), sx: { whiteSpace: 'nowrap', minWidth: 'auto' }, children: checking ? (_jsx(CircularProgress, { size: 20, color: "inherit" })) : (t(BrightPassStrings.Breach_Check)) })] }), error && (_jsx(Alert, { severity: "error", sx: { mb: 1 }, children: error })), breachMessage && result && (_jsx(Alert, { severity: breachMessage.severity, sx: { mb: 1 }, children: breachMessage.severity === 'warning'
|
|
51
|
+
? t(BrightPassStrings.Breach_Found, {
|
|
52
|
+
COUNT: String(result.count),
|
|
53
|
+
})
|
|
54
|
+
: t(BrightPassStrings.Breach_NotFound) }))] }));
|
|
55
|
+
};
|
|
56
|
+
export default BreachCheckWidget;
|
|
57
|
+
//# sourceMappingURL=BreachCheckWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BreachCheckWidget.js","sourceRoot":"","sources":["../../../../../brightpass-react-components/src/lib/widgets/BreachCheckWidget.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { BrightPassStrings, } from '@brightchain/brightchain-lib';
|
|
3
|
+
import { Box, Button, Chip, LinearProgress, Slider, Switch, TextField, Typography, } from '@mui/material';
|
|
4
|
+
import { useCallback, useRef, useState } from 'react';
|
|
5
|
+
import { useBrightPassTranslation } from '../hooks/useBrightPassTranslation';
|
|
6
|
+
import { useBrightPassApi } from '../hooks/useBrightPassApi';
|
|
7
|
+
/**
|
|
8
|
+
* Pure function to classify password strength based on entropy bits.
|
|
9
|
+
* Exported for property-based testing (Property 8).
|
|
10
|
+
*/
|
|
11
|
+
export function classifyStrength(entropy) {
|
|
12
|
+
if (entropy < 40)
|
|
13
|
+
return 'weak';
|
|
14
|
+
if (entropy < 60)
|
|
15
|
+
return 'fair';
|
|
16
|
+
if (entropy < 80)
|
|
17
|
+
return 'strong';
|
|
18
|
+
return 'very_strong';
|
|
19
|
+
}
|
|
20
|
+
const STRENGTH_COLORS = {
|
|
21
|
+
weak: '#d32f2f',
|
|
22
|
+
fair: '#ed6c02',
|
|
23
|
+
strong: '#2e7d32',
|
|
24
|
+
very_strong: '#1565c0',
|
|
25
|
+
};
|
|
26
|
+
const STRENGTH_PROGRESS = {
|
|
27
|
+
weak: 25,
|
|
28
|
+
fair: 50,
|
|
29
|
+
strong: 75,
|
|
30
|
+
very_strong: 100,
|
|
31
|
+
};
|
|
32
|
+
const CLIPBOARD_CLEAR_MS = 30000;
|
|
33
|
+
const STRENGTH_LABEL_KEYS = {
|
|
34
|
+
weak: BrightPassStrings.PasswordGen_Strength_Weak,
|
|
35
|
+
fair: BrightPassStrings.PasswordGen_Strength_Fair,
|
|
36
|
+
strong: BrightPassStrings.PasswordGen_Strength_Strong,
|
|
37
|
+
very_strong: BrightPassStrings.PasswordGen_Strength_VeryStrong,
|
|
38
|
+
};
|
|
39
|
+
const TOGGLE_FIELDS = [
|
|
40
|
+
{ field: 'uppercase', labelKey: BrightPassStrings.PasswordGen_Uppercase },
|
|
41
|
+
{ field: 'lowercase', labelKey: BrightPassStrings.PasswordGen_Lowercase },
|
|
42
|
+
{ field: 'digits', labelKey: BrightPassStrings.PasswordGen_Digits },
|
|
43
|
+
{ field: 'symbols', labelKey: BrightPassStrings.PasswordGen_Symbols },
|
|
44
|
+
];
|
|
45
|
+
export const PasswordGeneratorWidget = ({ onUsePassword }) => {
|
|
46
|
+
const { t } = useBrightPassTranslation();
|
|
47
|
+
const brightPassApi = useBrightPassApi();
|
|
48
|
+
const [options, setOptions] = useState({
|
|
49
|
+
length: 16,
|
|
50
|
+
uppercase: true,
|
|
51
|
+
lowercase: true,
|
|
52
|
+
digits: true,
|
|
53
|
+
symbols: true,
|
|
54
|
+
});
|
|
55
|
+
const [result, setResult] = useState(null);
|
|
56
|
+
const [generating, setGenerating] = useState(false);
|
|
57
|
+
const [copied, setCopied] = useState(false);
|
|
58
|
+
const [error, setError] = useState(null);
|
|
59
|
+
const clipboardTimerRef = useRef(null);
|
|
60
|
+
const copiedTimerRef = useRef(null);
|
|
61
|
+
const handleGenerate = useCallback(async () => {
|
|
62
|
+
setGenerating(true);
|
|
63
|
+
setError(null);
|
|
64
|
+
setCopied(false);
|
|
65
|
+
try {
|
|
66
|
+
const generated = await brightPassApi.generatePassword(options);
|
|
67
|
+
setResult(generated);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
const message = err?.message ?? 'Generation failed';
|
|
71
|
+
setError(message);
|
|
72
|
+
}
|
|
73
|
+
finally {
|
|
74
|
+
setGenerating(false);
|
|
75
|
+
}
|
|
76
|
+
}, [options]);
|
|
77
|
+
const handleCopy = useCallback(async () => {
|
|
78
|
+
if (!result?.password)
|
|
79
|
+
return;
|
|
80
|
+
try {
|
|
81
|
+
await navigator.clipboard.writeText(result.password);
|
|
82
|
+
setCopied(true);
|
|
83
|
+
if (copiedTimerRef.current)
|
|
84
|
+
clearTimeout(copiedTimerRef.current);
|
|
85
|
+
copiedTimerRef.current = setTimeout(() => setCopied(false), 2000);
|
|
86
|
+
if (clipboardTimerRef.current) {
|
|
87
|
+
clearTimeout(clipboardTimerRef.current);
|
|
88
|
+
}
|
|
89
|
+
clipboardTimerRef.current = setTimeout(async () => {
|
|
90
|
+
try {
|
|
91
|
+
await navigator.clipboard.writeText('');
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
// Clipboard API may not be available in background
|
|
95
|
+
}
|
|
96
|
+
}, CLIPBOARD_CLEAR_MS);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
// Clipboard write failed
|
|
100
|
+
}
|
|
101
|
+
}, [result]);
|
|
102
|
+
const handleUsePassword = useCallback(() => {
|
|
103
|
+
if (result?.password && onUsePassword) {
|
|
104
|
+
onUsePassword(result.password);
|
|
105
|
+
}
|
|
106
|
+
}, [result, onUsePassword]);
|
|
107
|
+
const updateToggle = useCallback((field) => {
|
|
108
|
+
setOptions((prev) => ({ ...prev, [field]: !prev[field] }));
|
|
109
|
+
}, []);
|
|
110
|
+
const strength = result?.strength ?? null;
|
|
111
|
+
return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t(BrightPassStrings.PasswordGen_Title) }), _jsxs(Box, { sx: { mb: 2 }, children: [_jsxs(Typography, { gutterBottom: true, children: [t(BrightPassStrings.PasswordGen_Length), ": ", options.length] }), _jsx(Slider, { value: options.length, min: 8, max: 128, onChange: (_, value) => setOptions((prev) => ({
|
|
112
|
+
...prev,
|
|
113
|
+
length: value,
|
|
114
|
+
})), "aria-label": t(BrightPassStrings.PasswordGen_Length) })] }), _jsx(Box, { sx: { display: 'flex', flexWrap: 'wrap', gap: 2, mb: 2 }, children: TOGGLE_FIELDS.map(({ field, labelKey }) => (_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 0.5 }, children: [_jsx(Switch, { checked: options[field], onChange: () => updateToggle(field), inputProps: {
|
|
115
|
+
'aria-label': t(labelKey),
|
|
116
|
+
} }), _jsx(Typography, { variant: "body2", children: t(labelKey) })] }, field))) }), _jsx(Button, { variant: "contained", onClick: handleGenerate, disabled: generating, sx: { mb: 2 }, children: t(BrightPassStrings.PasswordGen_Generate) }), error && (_jsx(Typography, { color: "error", sx: { mb: 1 }, children: error })), result && (_jsxs(Box, { sx: { mb: 2 }, children: [_jsx(TextField, { value: result.password, fullWidth: true, slotProps: { input: { readOnly: true } }, sx: { mb: 1, fontFamily: 'monospace' } }), strength && (_jsxs(Box, { sx: { mb: 1 }, children: [_jsxs(Box, { sx: {
|
|
117
|
+
display: 'flex',
|
|
118
|
+
alignItems: 'center',
|
|
119
|
+
gap: 1,
|
|
120
|
+
mb: 0.5,
|
|
121
|
+
}, children: [_jsx(Chip, { label: t(STRENGTH_LABEL_KEYS[strength]), size: "small", sx: {
|
|
122
|
+
backgroundColor: STRENGTH_COLORS[strength],
|
|
123
|
+
color: '#fff',
|
|
124
|
+
} }), _jsx(Typography, { variant: "caption", color: "text.secondary", children: t(BrightPassStrings.PasswordGen_Entropy, {
|
|
125
|
+
BITS: String(Math.round(result.entropy)),
|
|
126
|
+
}) })] }), _jsx(LinearProgress, { variant: "determinate", value: STRENGTH_PROGRESS[strength], sx: {
|
|
127
|
+
height: 6,
|
|
128
|
+
borderRadius: 3,
|
|
129
|
+
'& .MuiLinearProgress-bar': {
|
|
130
|
+
backgroundColor: STRENGTH_COLORS[strength],
|
|
131
|
+
},
|
|
132
|
+
} })] })), _jsxs(Box, { sx: { display: 'flex', gap: 1 }, children: [_jsx(Button, { variant: "outlined", onClick: handleCopy, children: copied
|
|
133
|
+
? t(BrightPassStrings.PasswordGen_Copied)
|
|
134
|
+
: t(BrightPassStrings.PasswordGen_Copy) }), onUsePassword && (_jsx(Button, { variant: "contained", onClick: handleUsePassword, children: t(BrightPassStrings.PasswordGen_UsePassword) }))] })] }))] }));
|
|
135
|
+
};
|
|
136
|
+
export default PasswordGeneratorWidget;
|
|
137
|
+
//# sourceMappingURL=PasswordGeneratorWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PasswordGeneratorWidget.js","sourceRoot":"","sources":["../../../../../brightpass-react-components/src/lib/widgets/PasswordGeneratorWidget.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { BrightPassStrings } from '@brightchain/brightchain-lib';
|
|
3
|
+
import { Box, Button, CircularProgress, Typography, } from '@mui/material';
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
5
|
+
import { useBrightPassTranslation } from '../hooks/useBrightPassTranslation';
|
|
6
|
+
import { useBrightPassApi } from '../hooks/useBrightPassApi';
|
|
7
|
+
/* ------------------------------------------------------------------ */
|
|
8
|
+
/* Pure helper functions — exported for property-based testing */
|
|
9
|
+
/* ------------------------------------------------------------------ */
|
|
10
|
+
/**
|
|
11
|
+
* Format a 6-digit TOTP code as "XXX XXX" for readability.
|
|
12
|
+
*/
|
|
13
|
+
export function formatTotpCode(code) {
|
|
14
|
+
if (code.length === 6)
|
|
15
|
+
return `${code.slice(0, 3)} ${code.slice(3)}`;
|
|
16
|
+
return code;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calculate seconds remaining in the current TOTP window.
|
|
20
|
+
* Returns a value in [0, period - 1].
|
|
21
|
+
*/
|
|
22
|
+
export function calculateRemainingSeconds(timestampMs, period) {
|
|
23
|
+
return period - 1 - (Math.floor(timestampMs / 1000) % period);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Validate a base32-encoded string.
|
|
27
|
+
*/
|
|
28
|
+
export function isValidBase32(input) {
|
|
29
|
+
return /^[A-Z2-7]+=*$/i.test(input) && input.length > 0;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Validate an otpauth:// URI containing a valid base32 secret.
|
|
33
|
+
*/
|
|
34
|
+
export function isValidOtpauthUri(input) {
|
|
35
|
+
try {
|
|
36
|
+
const url = new URL(input);
|
|
37
|
+
return (url.protocol === 'otpauth:' &&
|
|
38
|
+
url.searchParams.has('secret') &&
|
|
39
|
+
isValidBase32(url.searchParams.get('secret')));
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Validate a TOTP secret — either raw base32 or an otpauth:// URI.
|
|
47
|
+
*/
|
|
48
|
+
export function isValidTotpSecret(input) {
|
|
49
|
+
return isValidBase32(input) || isValidOtpauthUri(input);
|
|
50
|
+
}
|
|
51
|
+
/* ------------------------------------------------------------------ */
|
|
52
|
+
/* Component */
|
|
53
|
+
/* ------------------------------------------------------------------ */
|
|
54
|
+
const CLIPBOARD_CLEAR_MS = 30000;
|
|
55
|
+
const COUNTDOWN_INTERVAL_MS = 1000;
|
|
56
|
+
export const TOTPWidget = ({ secret, showQrCode = false, }) => {
|
|
57
|
+
const { t } = useBrightPassTranslation();
|
|
58
|
+
const brightPassApi = useBrightPassApi();
|
|
59
|
+
const [totpCode, setTotpCode] = useState(null);
|
|
60
|
+
const [remaining, setRemaining] = useState(30);
|
|
61
|
+
const [copied, setCopied] = useState(false);
|
|
62
|
+
const [error, setError] = useState(null);
|
|
63
|
+
const clipboardTimerRef = useRef(null);
|
|
64
|
+
const copiedTimerRef = useRef(null);
|
|
65
|
+
const countdownRef = useRef(null);
|
|
66
|
+
const fetchCode = useCallback(async () => {
|
|
67
|
+
try {
|
|
68
|
+
setError(null);
|
|
69
|
+
const code = await brightPassApi.generateTotp(secret);
|
|
70
|
+
setTotpCode(code);
|
|
71
|
+
setRemaining(code.remainingSeconds);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
const message = err?.message ?? 'Failed to generate TOTP';
|
|
75
|
+
setError(message);
|
|
76
|
+
}
|
|
77
|
+
}, [secret]);
|
|
78
|
+
// Fetch on mount and whenever the secret changes
|
|
79
|
+
useEffect(() => {
|
|
80
|
+
fetchCode();
|
|
81
|
+
}, [fetchCode]);
|
|
82
|
+
// Countdown timer — ticks every second, re-fetches when reaching zero
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
countdownRef.current = setInterval(() => {
|
|
85
|
+
setRemaining((prev) => {
|
|
86
|
+
if (prev <= 1) {
|
|
87
|
+
fetchCode();
|
|
88
|
+
return 30;
|
|
89
|
+
}
|
|
90
|
+
return prev - 1;
|
|
91
|
+
});
|
|
92
|
+
}, COUNTDOWN_INTERVAL_MS);
|
|
93
|
+
return () => {
|
|
94
|
+
if (countdownRef.current)
|
|
95
|
+
clearInterval(countdownRef.current);
|
|
96
|
+
};
|
|
97
|
+
}, [fetchCode]);
|
|
98
|
+
// Cleanup clipboard timers on unmount
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
return () => {
|
|
101
|
+
if (clipboardTimerRef.current)
|
|
102
|
+
clearTimeout(clipboardTimerRef.current);
|
|
103
|
+
if (copiedTimerRef.current)
|
|
104
|
+
clearTimeout(copiedTimerRef.current);
|
|
105
|
+
};
|
|
106
|
+
}, []);
|
|
107
|
+
const handleCopy = useCallback(async () => {
|
|
108
|
+
if (!totpCode?.code)
|
|
109
|
+
return;
|
|
110
|
+
try {
|
|
111
|
+
await navigator.clipboard.writeText(totpCode.code);
|
|
112
|
+
setCopied(true);
|
|
113
|
+
if (copiedTimerRef.current)
|
|
114
|
+
clearTimeout(copiedTimerRef.current);
|
|
115
|
+
copiedTimerRef.current = setTimeout(() => setCopied(false), 2000);
|
|
116
|
+
if (clipboardTimerRef.current)
|
|
117
|
+
clearTimeout(clipboardTimerRef.current);
|
|
118
|
+
clipboardTimerRef.current = setTimeout(async () => {
|
|
119
|
+
try {
|
|
120
|
+
await navigator.clipboard.writeText('');
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
// Clipboard API may not be available in background
|
|
124
|
+
}
|
|
125
|
+
}, CLIPBOARD_CLEAR_MS);
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
// Clipboard write failed
|
|
129
|
+
}
|
|
130
|
+
}, [totpCode]);
|
|
131
|
+
const period = totpCode?.period ?? 30;
|
|
132
|
+
const progressValue = (remaining / period) * 100;
|
|
133
|
+
const otpauthUri = `otpauth://totp/?secret=${encodeURIComponent(secret)}&period=${period}&digits=6&algorithm=SHA1`;
|
|
134
|
+
return (_jsxs(Box, { children: [_jsx(Typography, { variant: "h6", gutterBottom: true, children: t(BrightPassStrings.TOTP_Title) }), error && (_jsx(Typography, { color: "error", sx: { mb: 1 }, children: error })), totpCode && (_jsxs(Box, { sx: { mb: 2 }, children: [_jsx(Typography, { variant: "caption", color: "text.secondary", sx: { mb: 0.5, display: 'block' }, children: t(BrightPassStrings.TOTP_Code) }), _jsxs(Box, { sx: {
|
|
135
|
+
display: 'flex',
|
|
136
|
+
alignItems: 'center',
|
|
137
|
+
gap: 2,
|
|
138
|
+
mb: 2,
|
|
139
|
+
}, children: [_jsx(Typography, { variant: "h3", sx: {
|
|
140
|
+
fontFamily: 'monospace',
|
|
141
|
+
fontWeight: 'bold',
|
|
142
|
+
letterSpacing: '0.15em',
|
|
143
|
+
}, children: formatTotpCode(totpCode.code) }), _jsxs(Box, { sx: { position: 'relative', display: 'inline-flex' }, children: [_jsx(CircularProgress, { variant: "determinate", value: progressValue, size: 48, thickness: 4 }), _jsx(Box, { sx: {
|
|
144
|
+
top: 0,
|
|
145
|
+
left: 0,
|
|
146
|
+
bottom: 0,
|
|
147
|
+
right: 0,
|
|
148
|
+
position: 'absolute',
|
|
149
|
+
display: 'flex',
|
|
150
|
+
alignItems: 'center',
|
|
151
|
+
justifyContent: 'center',
|
|
152
|
+
}, children: _jsx(Typography, { variant: "caption", color: "text.secondary", children: remaining }) })] })] }), _jsx(Typography, { variant: "body2", color: "text.secondary", sx: { mb: 1 }, children: t(BrightPassStrings.TOTP_SecondsRemaining, {
|
|
153
|
+
SECONDS: String(remaining),
|
|
154
|
+
}) }), _jsx(Button, { variant: "outlined", onClick: handleCopy, children: copied
|
|
155
|
+
? t(BrightPassStrings.TOTP_Copied)
|
|
156
|
+
: t(BrightPassStrings.TOTP_CopyCode) })] })), showQrCode && (_jsxs(Box, { sx: { mt: 2 }, children: [_jsx(Typography, { variant: "subtitle2", gutterBottom: true, children: t(BrightPassStrings.TOTP_QrCode) }), _jsx(Typography, { variant: "caption", color: "text.secondary", sx: { display: 'block', mb: 0.5 }, children: t(BrightPassStrings.TOTP_SecretUri) }), _jsx(Typography, { variant: "body2", sx: {
|
|
157
|
+
fontFamily: 'monospace',
|
|
158
|
+
wordBreak: 'break-all',
|
|
159
|
+
p: 1,
|
|
160
|
+
bgcolor: 'action.hover',
|
|
161
|
+
borderRadius: 1,
|
|
162
|
+
}, children: otpauthUri })] }))] }));
|
|
163
|
+
};
|
|
164
|
+
export default TOTPWidget;
|
|
165
|
+
//# sourceMappingURL=TOTPWidget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TOTPWidget.js","sourceRoot":"","sources":["../../../../../brightpass-react-components/src/lib/widgets/TOTPWidget.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test setup for brightpass-react-components.
|
|
3
|
+
* Polyfills Node.js globals that jsdom doesn't provide but are needed
|
|
4
|
+
* by dependencies like ecies-lib.
|
|
5
|
+
*/
|
|
6
|
+
import { TextDecoder, TextEncoder } from 'util';
|
|
7
|
+
if (typeof globalThis.TextEncoder === 'undefined') {
|
|
8
|
+
Object.assign(globalThis, {
|
|
9
|
+
TextEncoder,
|
|
10
|
+
TextDecoder,
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=test-setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-setup.js","sourceRoot":"","sources":["../../../brightpass-react-components/src/test-setup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,MAAM,CAAC;AAEhD,IAAI,OAAO,UAAU,CAAC,WAAW,KAAK,WAAW,EAAE,CAAC;IAClD,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE;QACxB,WAAW;QACX,WAAW;KACZ,CAAC,CAAC;AACL,CAAC"}
|