UNPKG

@aioha/react-ui

Version:

Ready-made React modal for Aioha

68 lines (67 loc) 4.68 kB
import React, { useEffect, useRef, useState } from 'react'; import { useAioha } from '@aioha/providers/react'; import { ErrorAlert } from './ErrorAlert.js'; import { BackButton } from './BackButton.js'; import { SpinningIcon } from '../Icons.js'; import { RightAngledArrow } from '../TableUtils.js'; export const AccountDiscovery = ({ provider, options, onPrevious, onNext }) => { const { aioha } = useAioha(); const discovering = useRef(false); const stopDiscovery = useRef(() => { }); const discovered = useRef({}); const [completed, setCompleted] = useState(false); const [count, setCount] = useState(0); const [error, setError] = useState(); const [isPrompt, showPrompt] = useState(false); useEffect(() => { const discover = async () => { if (discovering.current) return; discovering.current = true; const result = await aioha.discoverAccounts(provider, (disc, stop) => { stopDiscovery.current = stop; const d = { pubkey: disc.pubkey, path: disc.path, role: disc.role }; if (!discovered.current[disc.username]) { discovered.current[disc.username] = [d]; } else if (!discovered.current[disc.username].find((a) => a.role === d.role)) { discovered.current[disc.username].push(d); } setCount((c) => c + 1); }, options); setCompleted(true); if (!result.success) { setError(result.error); } }; discover(); }, []); const userSelected = (user) => { showPrompt(true); onNext(user, discovered.current[user]); }; if (isPrompt) return (React.createElement("div", { className: "flex-col gap-20 my-3" }, React.createElement("svg", { className: "w-20 h-20 ml-auto mr-auto text-gray-900 dark:text-gray-100", "aria-hidden": "true", xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24" }, React.createElement("path", { stroke: "currentColor", strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: "1.5", d: "M6 15h12M6 6h12m-6 12h.01M7 21h10a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1H7a1 1 0 0 0-1 1v16a1 1 0 0 0 1 1Z" })), React.createElement("div", { className: "text-lg my-3 text-gray-900 dark:text-gray-100 text-center" }, "Please approve login request on the device."))); return (React.createElement("div", { className: "flex-col gap-3" }, React.createElement("div", { className: "mb-3 w-full" }, React.createElement(BackButton, { onPrevious: onPrevious })), !!error && React.createElement(ErrorAlert, { error: error }), Object.keys(discovered.current).length > 0 && (React.createElement("div", { className: "w-full overflow-x-auto" }, React.createElement("table", { className: "min-w-full divide-y divide-gray-200 dark:divide-gray-600" }, React.createElement("tbody", { className: "bg-white divide-y divide-gray-200 dark:bg-gray-700 dark:divide-gray-600" }, Object.entries(discovered.current).map(([username, auths]) => (React.createElement("tr", { key: username, className: "hover:bg-gray-50 dark:hover:bg-gray-600 cursor-pointer", onClick: () => userSelected(username) }, React.createElement("td", { className: "px-3 py-4 whitespace-nowrap" }, React.createElement("div", { className: "text-sm font-medium text-gray-900 dark:text-gray-100" }, username)), React.createElement("td", { className: "px-3 py-4 whitespace-nowrap" }, React.createElement("div", { className: "flex flex-wrap gap-2" }, auths.map((auth, index) => (React.createElement("span", { key: index, className: "px-2 inline-flex text-xs leading-5 font-semplify rounded-full bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200" }, auth.role))))), React.createElement(RightAngledArrow, null)))))))), !completed ? (React.createElement("button", { type: "button", className: "flex gap-2 items-center justify-center mt-3 ml-auto mr-auto text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 font-medium rounded-lg text-sm px-5 py-2.5 dark:bg-gray-700 dark:text-white dark:hover:bg-gray-800 enabled:hover:cursor-pointer disabled:hover:cursor-not-allowed", onClick: stopDiscovery.current, disabled: count === 0 }, React.createElement(SpinningIcon, { size: 5 }), "Stop")) : null)); };