hd-wallet-ui 2.0.5 → 2.0.7
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 +2 -2
- package/src/app.js +25 -30
- package/src/clipboard.js +44 -0
- package/src/hash.js +9 -0
- package/styles/main.css +12 -4
- package/styles/widget.css +12 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hd-wallet-ui",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "HD Wallet modal UI — login, keys, identity, trust map, and security bond. Attach to any button in your app.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/app.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"buffer": "^6.0.3",
|
|
41
41
|
"flatbuffers": "^25.9.23",
|
|
42
42
|
"flatc-wasm": "^26.1.32",
|
|
43
|
-
"hd-wallet-wasm": "^2.0.
|
|
43
|
+
"hd-wallet-wasm": "^2.0.7",
|
|
44
44
|
"qrcode": "^1.5.3",
|
|
45
45
|
"spacedatastandards.org": "^1.93.3",
|
|
46
46
|
"vcard-cryptoperson": "^1.1.11"
|
package/src/app.js
CHANGED
|
@@ -28,6 +28,8 @@ window.Buffer = Buffer;
|
|
|
28
28
|
|
|
29
29
|
import { getModalHTML } from './template.js';
|
|
30
30
|
import WalletStorage, { StorageMethod } from './wallet-storage.js';
|
|
31
|
+
import { safeCopyText } from './clipboard.js';
|
|
32
|
+
import { normalizeTabHash } from './hash.js';
|
|
31
33
|
|
|
32
34
|
import {
|
|
33
35
|
cryptoConfig,
|
|
@@ -74,14 +76,7 @@ const $ = (id) => {
|
|
|
74
76
|
return null;
|
|
75
77
|
};
|
|
76
78
|
|
|
77
|
-
export
|
|
78
|
-
return String(rawHash || '')
|
|
79
|
-
.replace(/^\/+/g, '')
|
|
80
|
-
.split(/[/?#]/)[0]
|
|
81
|
-
.replace(/[^a-z0-9_-]/gi, '')
|
|
82
|
-
.replace(/-tab$/i, '')
|
|
83
|
-
.toLowerCase();
|
|
84
|
-
}
|
|
79
|
+
export { normalizeTabHash };
|
|
85
80
|
|
|
86
81
|
const $q = (sel) => _root.querySelector(sel) || (_root !== document ? document.querySelector(sel) : null);
|
|
87
82
|
const $qa = (sel) => {
|
|
@@ -1612,9 +1607,7 @@ async function handleAccountAction(action, idx) {
|
|
|
1612
1607
|
showReceiveModal(acct);
|
|
1613
1608
|
break;
|
|
1614
1609
|
case 'copy':
|
|
1615
|
-
|
|
1616
|
-
await navigator.clipboard.writeText(acct.address);
|
|
1617
|
-
} catch {}
|
|
1610
|
+
await safeCopyText(acct.address);
|
|
1618
1611
|
break;
|
|
1619
1612
|
case 'toggle':
|
|
1620
1613
|
toggleAccountActive(idx);
|
|
@@ -1669,7 +1662,7 @@ async function showReceiveModal(acct) {
|
|
|
1669
1662
|
overlay.style.display = 'flex';
|
|
1670
1663
|
|
|
1671
1664
|
overlay.querySelector('#wallet-receive-copy')?.addEventListener('click', () => {
|
|
1672
|
-
|
|
1665
|
+
void safeCopyText(acct.address);
|
|
1673
1666
|
}, { once: true });
|
|
1674
1667
|
|
|
1675
1668
|
overlay.querySelector('#wallet-receive-close')?.addEventListener('click', () => {
|
|
@@ -2835,12 +2828,10 @@ function populateAccountAddressDropdown() {
|
|
|
2835
2828
|
|
|
2836
2829
|
const copyBtn = $('account-address-copy');
|
|
2837
2830
|
if (copyBtn) {
|
|
2838
|
-
copyBtn.onclick = () => {
|
|
2839
|
-
if (xpubStr) {
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
setTimeout(() => { copyBtn.title = 'Copy xpub'; }, 1500);
|
|
2843
|
-
});
|
|
2831
|
+
copyBtn.onclick = async () => {
|
|
2832
|
+
if (xpubStr && await safeCopyText(xpubStr)) {
|
|
2833
|
+
copyBtn.title = 'Copied!';
|
|
2834
|
+
setTimeout(() => { copyBtn.title = 'Copy xpub'; }, 1500);
|
|
2844
2835
|
}
|
|
2845
2836
|
};
|
|
2846
2837
|
}
|
|
@@ -2856,12 +2847,10 @@ function populateAccountAddressDropdown() {
|
|
|
2856
2847
|
}
|
|
2857
2848
|
const peerCopyBtn = $('account-peerid-copy');
|
|
2858
2849
|
if (peerCopyBtn) {
|
|
2859
|
-
peerCopyBtn.onclick = () => {
|
|
2860
|
-
if (peerIdStr) {
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
setTimeout(() => { peerCopyBtn.title = 'Copy PeerID'; }, 1500);
|
|
2864
|
-
});
|
|
2850
|
+
peerCopyBtn.onclick = async () => {
|
|
2851
|
+
if (peerIdStr && await safeCopyText(peerIdStr)) {
|
|
2852
|
+
peerCopyBtn.title = 'Copied!';
|
|
2853
|
+
setTimeout(() => { peerCopyBtn.title = 'Copy PeerID'; }, 1500);
|
|
2865
2854
|
}
|
|
2866
2855
|
};
|
|
2867
2856
|
}
|
|
@@ -4683,9 +4672,12 @@ function setupMainAppHandlers() {
|
|
|
4683
4672
|
if (!value) {
|
|
4684
4673
|
throw new Error('Nothing to copy');
|
|
4685
4674
|
}
|
|
4686
|
-
await
|
|
4687
|
-
|
|
4688
|
-
|
|
4675
|
+
if (await safeCopyText(value)) {
|
|
4676
|
+
btn.classList.add('copied');
|
|
4677
|
+
setTimeout(() => btn.classList.remove('copied'), 1500);
|
|
4678
|
+
} else {
|
|
4679
|
+
throw new Error('Clipboard unavailable');
|
|
4680
|
+
}
|
|
4689
4681
|
} catch (err) {
|
|
4690
4682
|
console.error('Copy failed:', err);
|
|
4691
4683
|
}
|
|
@@ -5050,7 +5042,9 @@ function setupMainAppHandlers() {
|
|
|
5050
5042
|
$('copy-vcard')?.addEventListener('click', async () => {
|
|
5051
5043
|
const vcard = state._exportedVCard || '';
|
|
5052
5044
|
try {
|
|
5053
|
-
await
|
|
5045
|
+
if (!await safeCopyText(vcard)) {
|
|
5046
|
+
throw new Error('Clipboard unavailable');
|
|
5047
|
+
}
|
|
5054
5048
|
const btn = $('copy-vcard');
|
|
5055
5049
|
if (btn) {
|
|
5056
5050
|
btn.textContent = 'Copied!';
|
|
@@ -5697,7 +5691,7 @@ function setupTrustHandlers() {
|
|
|
5697
5691
|
$('encrypt-copy-bundle')?.addEventListener('click', () => {
|
|
5698
5692
|
const bundle = $('encrypt-bundle')?.value;
|
|
5699
5693
|
if (bundle) {
|
|
5700
|
-
|
|
5694
|
+
void safeCopyText(bundle);
|
|
5701
5695
|
}
|
|
5702
5696
|
});
|
|
5703
5697
|
|
|
@@ -5853,7 +5847,8 @@ function setupHomepageHandlers() {
|
|
|
5853
5847
|
btn.addEventListener('click', () => {
|
|
5854
5848
|
const code = btn.closest('.code-block')?.querySelector('code');
|
|
5855
5849
|
if (code) {
|
|
5856
|
-
|
|
5850
|
+
safeCopyText(code.textContent).then((copied) => {
|
|
5851
|
+
if (!copied) return;
|
|
5857
5852
|
btn.title = 'Copied!';
|
|
5858
5853
|
setTimeout(() => { btn.title = 'Copy code'; }, 2000);
|
|
5859
5854
|
});
|
package/src/clipboard.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
export async function safeCopyText(value) {
|
|
2
|
+
const text = String(value ?? '');
|
|
3
|
+
if (!text) return false;
|
|
4
|
+
|
|
5
|
+
try {
|
|
6
|
+
const writeText = globalThis.navigator?.clipboard?.writeText;
|
|
7
|
+
if (typeof writeText === 'function') {
|
|
8
|
+
await writeText.call(globalThis.navigator.clipboard, text);
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
} catch {
|
|
12
|
+
// Fall through to the legacy DOM copy path below.
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return fallbackCopyText(text);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function fallbackCopyText(text) {
|
|
19
|
+
const doc = globalThis.document;
|
|
20
|
+
if (!doc?.body || typeof doc.createElement !== 'function' || typeof doc.execCommand !== 'function') {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const textarea = doc.createElement('textarea');
|
|
25
|
+
textarea.value = text;
|
|
26
|
+
textarea.readOnly = true;
|
|
27
|
+
textarea.setAttribute('aria-hidden', 'true');
|
|
28
|
+
textarea.style.position = 'fixed';
|
|
29
|
+
textarea.style.left = '-9999px';
|
|
30
|
+
textarea.style.top = '0';
|
|
31
|
+
textarea.style.opacity = '0';
|
|
32
|
+
|
|
33
|
+
doc.body.appendChild(textarea);
|
|
34
|
+
try {
|
|
35
|
+
textarea.focus();
|
|
36
|
+
textarea.select();
|
|
37
|
+
textarea.setSelectionRange(0, textarea.value.length);
|
|
38
|
+
return Boolean(doc.execCommand('copy'));
|
|
39
|
+
} catch {
|
|
40
|
+
return false;
|
|
41
|
+
} finally {
|
|
42
|
+
textarea.remove();
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/hash.js
ADDED
package/styles/main.css
CHANGED
|
@@ -1214,6 +1214,11 @@ body:has(.modal.active) .nav-bar {
|
|
|
1214
1214
|
align-items: center;
|
|
1215
1215
|
gap: 10px;
|
|
1216
1216
|
margin-top: 4px;
|
|
1217
|
+
min-width: 0;
|
|
1218
|
+
}
|
|
1219
|
+
|
|
1220
|
+
.account-address-label {
|
|
1221
|
+
flex: 0 0 auto;
|
|
1217
1222
|
}
|
|
1218
1223
|
|
|
1219
1224
|
.account-address-select {
|
|
@@ -1236,9 +1241,9 @@ body:has(.modal.active) .nav-bar {
|
|
|
1236
1241
|
white-space: nowrap;
|
|
1237
1242
|
overflow: hidden;
|
|
1238
1243
|
text-overflow: ellipsis;
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1244
|
+
flex: 1 1 auto;
|
|
1245
|
+
min-width: 12ch;
|
|
1246
|
+
width: 100%;
|
|
1242
1247
|
}
|
|
1243
1248
|
|
|
1244
1249
|
.account-address-copy {
|
|
@@ -1246,10 +1251,13 @@ body:has(.modal.active) .nav-bar {
|
|
|
1246
1251
|
border: none;
|
|
1247
1252
|
color: var(--white-30);
|
|
1248
1253
|
cursor: pointer;
|
|
1254
|
+
height: 24px;
|
|
1249
1255
|
padding: 2px;
|
|
1256
|
+
width: 24px;
|
|
1250
1257
|
flex-shrink: 0;
|
|
1251
1258
|
display: flex;
|
|
1252
1259
|
align-items: center;
|
|
1260
|
+
justify-content: center;
|
|
1253
1261
|
}
|
|
1254
1262
|
.account-address-copy:hover {
|
|
1255
1263
|
color: var(--white-70);
|
|
@@ -1257,7 +1265,7 @@ body:has(.modal.active) .nav-bar {
|
|
|
1257
1265
|
|
|
1258
1266
|
@media (max-width: 600px) {
|
|
1259
1267
|
.account-address-display {
|
|
1260
|
-
|
|
1268
|
+
min-width: 10ch;
|
|
1261
1269
|
}
|
|
1262
1270
|
}
|
|
1263
1271
|
|
package/styles/widget.css
CHANGED
|
@@ -1216,6 +1216,11 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
|
|
|
1216
1216
|
align-items: center;
|
|
1217
1217
|
gap: 10px;
|
|
1218
1218
|
margin-top: 4px;
|
|
1219
|
+
min-width: 0;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
#hd-wallet-ui-container .account-address-label {
|
|
1223
|
+
flex: 0 0 auto;
|
|
1219
1224
|
}
|
|
1220
1225
|
|
|
1221
1226
|
#hd-wallet-ui-container .account-address-select {
|
|
@@ -1238,9 +1243,9 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
|
|
|
1238
1243
|
white-space: nowrap;
|
|
1239
1244
|
overflow: hidden;
|
|
1240
1245
|
text-overflow: ellipsis;
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1246
|
+
flex: 1 1 auto;
|
|
1247
|
+
min-width: 12ch;
|
|
1248
|
+
width: 100%;
|
|
1244
1249
|
}
|
|
1245
1250
|
|
|
1246
1251
|
#hd-wallet-ui-container .account-address-copy {
|
|
@@ -1248,10 +1253,13 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
|
|
|
1248
1253
|
border: none;
|
|
1249
1254
|
color: var(--white-30);
|
|
1250
1255
|
cursor: pointer;
|
|
1256
|
+
height: 24px;
|
|
1251
1257
|
padding: 2px;
|
|
1258
|
+
width: 24px;
|
|
1252
1259
|
flex-shrink: 0;
|
|
1253
1260
|
display: flex;
|
|
1254
1261
|
align-items: center;
|
|
1262
|
+
justify-content: center;
|
|
1255
1263
|
}
|
|
1256
1264
|
#hd-wallet-ui-container .account-address-copy:hover {
|
|
1257
1265
|
color: var(--white-70);
|
|
@@ -1259,7 +1267,7 @@ body:has(#hd-wallet-ui-container .modal.active) #hd-wallet-ui-container .nav-bar
|
|
|
1259
1267
|
|
|
1260
1268
|
@media (max-width: 600px) {
|
|
1261
1269
|
#hd-wallet-ui-container .account-address-display {
|
|
1262
|
-
|
|
1270
|
+
min-width: 10ch;
|
|
1263
1271
|
}
|
|
1264
1272
|
}
|
|
1265
1273
|
|