global: private xpub support part 2

This commit is contained in:
nym21
2026-06-17 11:25:42 +02:00
parent 0c7861071d
commit 43df9e098c
68 changed files with 1836 additions and 1653 deletions
+102
View File
@@ -0,0 +1,102 @@
/**
* @typedef {Object} StoredWallet
* @property {string} id
* @property {string} name
*/
/**
* @typedef {Object} WalletSelectorOptions
* @property {() => string} getSelectedId
* @property {(walletId: string) => void} onSelect
*/
/**
* @param {HTMLElement} walletList
* @param {StoredWallet[]} wallets
* @param {WalletSelectorOptions} options
*/
function renderButtons(walletList, wallets, options) {
walletList.replaceChildren();
for (const wallet of wallets) {
const button = document.createElement("button");
const selected = wallet.id === options.getSelectedId();
button.type = "button";
button.className = "wallets__wallet-button";
button.setAttribute("aria-pressed", selected ? "true" : "false");
button.setAttribute("data-wallet-id", wallet.id);
button.append(wallet.name);
button.addEventListener("click", () => {
options.onSelect(wallet.id);
});
walletList.append(button);
}
}
/**
* @param {HTMLElement} walletList
* @param {WalletSelectorOptions} options
*/
export function createSelector(walletList, options) {
function selectSnappedWallet() {
const buttons = [...walletList.querySelectorAll(".wallets__wallet-button")];
if (buttons.length === 0) return;
const listRect = walletList.getBoundingClientRect();
const listCenter = listRect.left + listRect.width / 2;
const closest = buttons.reduce((best, button) => {
const rect = button.getBoundingClientRect();
const center = rect.left + rect.width / 2;
const distance = Math.abs(center - listCenter);
return distance < best.distance
? { button, distance }
: best;
}, {
button: buttons[0],
distance: Number.POSITIVE_INFINITY,
});
const id = closest.button.getAttribute("data-wallet-id");
if (id && id !== options.getSelectedId()) {
options.onSelect(id);
}
}
walletList.addEventListener("scrollend", () => {
selectSnappedWallet();
});
walletList.addEventListener("wheel", (event) => {
const delta = Math.abs(event.deltaX) > Math.abs(event.deltaY)
? event.deltaX
: event.deltaY;
if (delta === 0) return;
const maxScrollLeft = walletList.scrollWidth - walletList.clientWidth;
const nextScrollLeft = Math.max(
0,
Math.min(maxScrollLeft, walletList.scrollLeft + delta),
);
if (nextScrollLeft === walletList.scrollLeft) return;
event.preventDefault();
walletList.scrollLeft = nextScrollLeft;
}, { passive: false });
return {
clear() {
walletList.replaceChildren();
},
/**
* @param {StoredWallet[]} wallets
*/
render(wallets) {
renderButtons(walletList, wallets, options);
},
};
}
+56
View File
@@ -0,0 +1,56 @@
main.wallets {
.wallets__selector {
min-width: 0;
}
.wallets__wallet-list {
display: flex;
gap: 1rem;
min-width: 0;
overflow-x: auto;
padding-bottom: 0.25rem;
overscroll-behavior-inline: contain;
scroll-padding-inline: var(--page-x);
scroll-snap-type: x proximity;
}
.wallets__wallet-button {
flex: 0 0 auto;
scroll-snap-align: center;
border: 0;
padding: 0;
color: var(--white);
background: transparent;
font-family: var(--font-serif);
font-size: 4rem;
font-weight: 400;
line-height: 1;
opacity: 0.48;
cursor: pointer;
}
.wallets__wallet-button[aria-pressed="true"] {
opacity: 1;
}
.wallets__wallet-button:focus-visible {
outline: 2px solid var(--orange);
outline-offset: 2px;
}
}
@media (max-width: 56rem) {
main.wallets {
.wallets__wallet-button {
font-size: 3rem;
}
}
}
@media (max-width: 34rem) {
main.wallets {
.wallets__wallet-button {
font-size: 2.5rem;
}
}
}